summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java94
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java111
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
4 files changed, 170 insertions, 37 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java
index 5fb894e911..0d31811257 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java
@@ -154,4 +154,98 @@ public class FilterCommandsTest extends RepositoryTestCase {
config.setString("filter", "test", "clean", null);
config.save();
}
+
+ @Test
+ public void testBuiltinSmudgeFilter() throws IOException, GitAPIException {
+ String builtinCommandName = "jgit://builtin/test/smudge";
+ FilterCommandRegistry.register(builtinCommandName,
+ new TestCommandFactory('s'));
+ StoredConfig config = git.getRepository().getConfig();
+ config.setString("filter", "test", "smudge", builtinCommandName);
+ config.save();
+
+ writeTrashFile(".gitattributes", "*.txt filter=test");
+ git.add().addFilepattern(".gitattributes").call();
+ git.commit().setMessage("add filter").call();
+
+ writeTrashFile("Test.txt", "Hello again");
+ git.add().addFilepattern("Test.txt").call();
+ assertEquals(
+ "[.gitattributes, mode:100644, content:*.txt filter=test][Test.txt, mode:100644, content:Hello again]",
+ indexState(CONTENT));
+ assertEquals("Hello again", read("Test.txt"));
+ deleteTrashFile("Test.txt");
+ git.checkout().addPath("Test.txt").call();
+ assertEquals("sHseslslsos sasgsasisn", read("Test.txt"));
+
+ writeTrashFile("Test.bin", "Hello again");
+ git.add().addFilepattern("Test.bin").call();
+ assertEquals(
+ "[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:Hello again]",
+ indexState(CONTENT));
+ deleteTrashFile("Test.bin");
+ git.checkout().addPath("Test.bin").call();
+ assertEquals("Hello again", read("Test.bin"));
+
+ config.setString("filter", "test", "clean", null);
+ config.save();
+
+ git.add().addFilepattern("Test.txt").call();
+ assertEquals(
+ "[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:sHseslslsos sasgsasisn]",
+ indexState(CONTENT));
+
+ config.setString("filter", "test", "clean", null);
+ config.save();
+ }
+
+ @Test
+ public void testBuiltinCleanAndSmudgeFilter() throws IOException, GitAPIException {
+ String builtinCommandPrefix = "jgit://builtin/test/";
+ FilterCommandRegistry.register(builtinCommandPrefix + "smudge",
+ new TestCommandFactory('s'));
+ FilterCommandRegistry.register(builtinCommandPrefix + "clean",
+ new TestCommandFactory('c'));
+ StoredConfig config = git.getRepository().getConfig();
+ config.setString("filter", "test", "smudge", builtinCommandPrefix+"smudge");
+ config.setString("filter", "test", "clean",
+ builtinCommandPrefix + "clean");
+ config.save();
+
+ writeTrashFile(".gitattributes", "*.txt filter=test");
+ git.add().addFilepattern(".gitattributes").call();
+ git.commit().setMessage("add filter").call();
+
+ writeTrashFile("Test.txt", "Hello again");
+ git.add().addFilepattern("Test.txt").call();
+ assertEquals(
+ "[.gitattributes, mode:100644, content:*.txt filter=test][Test.txt, mode:100644, content:cHceclclcoc cacgcacicn]",
+ indexState(CONTENT));
+ assertEquals("Hello again", read("Test.txt"));
+ deleteTrashFile("Test.txt");
+ git.checkout().addPath("Test.txt").call();
+ assertEquals("scsHscsescslscslscsoscs scsascsgscsascsiscsn",
+ read("Test.txt"));
+
+ writeTrashFile("Test.bin", "Hello again");
+ git.add().addFilepattern("Test.bin").call();
+ assertEquals(
+ "[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:cHceclclcoc cacgcacicn]",
+ indexState(CONTENT));
+ deleteTrashFile("Test.bin");
+ git.checkout().addPath("Test.bin").call();
+ assertEquals("Hello again", read("Test.bin"));
+
+ config.setString("filter", "test", "clean", null);
+ config.save();
+
+ git.add().addFilepattern("Test.txt").call();
+ assertEquals(
+ "[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:scsHscsescslscslscsoscs scsascsgscsascsiscsn]",
+ indexState(CONTENT));
+
+ config.setString("filter", "test", "clean", null);
+ config.save();
+ }
+
}
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 327ca0a10b..2c721eabb6 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -279,6 +279,7 @@ expectedLessThanGot=expected less than ''{0}'', got ''{1}''
expectedPktLineWithService=expected pkt-line with ''# service=-'', got ''{0}''
expectedReceivedContentType=expected Content-Type {0}; received Content-Type {1}
expectedReportForRefNotReceived={0}: expected report for ref {1} not received
+failedToDetermineFilterDefinition=An exception occured while determining filter definitions
failedUpdatingRefs=failed updating refs
failureDueToOneOfTheFollowing=Failure due to one of the following:
failureUpdatingFETCH_HEAD=Failure updating FETCH_HEAD: {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 8af7e46a07..c3184437b4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -54,6 +54,8 @@ import java.util.List;
import java.util.Map;
import org.eclipse.jgit.api.errors.FilterFailedException;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
import org.eclipse.jgit.errors.CheckoutConflictException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -86,11 +88,15 @@ import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This class handles checking out one or two trees merging with the index.
*/
public class DirCacheCheckout {
+ private static Logger LOG = LoggerFactory.getLogger(DirCacheCheckout.class);
+
private static final int MAX_EXCEPTION_TEXT_SIZE = 10 * 1024;
/**
@@ -1303,45 +1309,19 @@ public class DirCacheCheckout {
} else {
nonNullEolStreamType = EolStreamType.DIRECT;
}
- OutputStream channel = EolStreamTypeUtil.wrapOutputStream(
- new FileOutputStream(tmpFile), nonNullEolStreamType);
- if (checkoutMetadata.smudgeFilterCommand != null) {
- ProcessBuilder filterProcessBuilder = fs.runInShell(
- checkoutMetadata.smudgeFilterCommand, new String[0]);
- filterProcessBuilder.directory(repo.getWorkTree());
- filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
- repo.getDirectory().getAbsolutePath());
- ExecutionResult result;
- int rc;
- try {
- // TODO: wire correctly with AUTOCRLF
- result = fs.execute(filterProcessBuilder, ol.openStream());
- rc = result.getRc();
- if (rc == 0) {
- result.getStdout().writeTo(channel,
- NullProgressMonitor.INSTANCE);
+ try (OutputStream channel = EolStreamTypeUtil.wrapOutputStream(
+ new FileOutputStream(tmpFile), nonNullEolStreamType)) {
+ if (checkoutMetadata.smudgeFilterCommand != null) {
+ if (FilterCommandRegistry
+ .isRegistered(checkoutMetadata.smudgeFilterCommand)) {
+ runBuiltinFilterCommand(repo, checkoutMetadata, ol,
+ channel);
+ } else {
+ runExternalFilterCommand(repo, entry, checkoutMetadata, ol,
+ fs, channel);
}
- } catch (IOException | InterruptedException e) {
- throw new IOException(new FilterFailedException(e,
- checkoutMetadata.smudgeFilterCommand,
- entry.getPathString()));
-
- } finally {
- channel.close();
- }
- if (rc != 0) {
- throw new IOException(new FilterFailedException(rc,
- checkoutMetadata.smudgeFilterCommand,
- entry.getPathString(),
- result.getStdout().toByteArray(MAX_EXCEPTION_TEXT_SIZE),
- RawParseUtils.decode(result.getStderr()
- .toByteArray(MAX_EXCEPTION_TEXT_SIZE))));
- }
- } else {
- try {
+ } else {
ol.copyTo(channel);
- } finally {
- channel.close();
}
}
// The entry needs to correspond to the on-disk filesize. If the content
@@ -1382,6 +1362,63 @@ public class DirCacheCheckout {
entry.setLastModified(fs.lastModified(f));
}
+ // Run an external filter command
+ private static void runExternalFilterCommand(Repository repo,
+ DirCacheEntry entry,
+ CheckoutMetadata checkoutMetadata, ObjectLoader ol, FS fs,
+ OutputStream channel) throws IOException {
+ ProcessBuilder filterProcessBuilder = fs.runInShell(
+ checkoutMetadata.smudgeFilterCommand, new String[0]);
+ filterProcessBuilder.directory(repo.getWorkTree());
+ filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
+ repo.getDirectory().getAbsolutePath());
+ ExecutionResult result;
+ int rc;
+ try {
+ // TODO: wire correctly with AUTOCRLF
+ result = fs.execute(filterProcessBuilder, ol.openStream());
+ rc = result.getRc();
+ if (rc == 0) {
+ result.getStdout().writeTo(channel,
+ NullProgressMonitor.INSTANCE);
+ }
+ } catch (IOException | InterruptedException e) {
+ throw new IOException(new FilterFailedException(e,
+ checkoutMetadata.smudgeFilterCommand,
+ entry.getPathString()));
+ }
+ if (rc != 0) {
+ throw new IOException(new FilterFailedException(rc,
+ checkoutMetadata.smudgeFilterCommand,
+ entry.getPathString(),
+ result.getStdout().toByteArray(MAX_EXCEPTION_TEXT_SIZE),
+ RawParseUtils.decode(result.getStderr()
+ .toByteArray(MAX_EXCEPTION_TEXT_SIZE))));
+ }
+ }
+
+ // Run a builtin filter command
+ private static void runBuiltinFilterCommand(Repository repo,
+ CheckoutMetadata checkoutMetadata, ObjectLoader ol,
+ OutputStream channel) throws MissingObjectException, IOException {
+ FilterCommand command = null;
+ try {
+ command = FilterCommandRegistry.createFilterCommand(
+ checkoutMetadata.smudgeFilterCommand, repo, ol.openStream(),
+ channel);
+ } catch (IOException e) {
+ LOG.error(JGitText.get().failedToDetermineFilterDefinition, e);
+ // In case an IOException occurred during creating of the command
+ // then proceed as if there would not have been a builtin filter.
+ ol.copyTo(channel);
+ }
+ if (command != null) {
+ while (command.run() != -1) {
+ // loop as long as command.run() tells there is work to do
+ }
+ }
+ }
+
@SuppressWarnings("deprecation")
private static void checkValidPath(CanonicalTreeParser t)
throws InvalidPathException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 758f71d27a..956171b127 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -338,6 +338,7 @@ public class JGitText extends TranslationBundle {
/***/ public String expectedPktLineWithService;
/***/ public String expectedReceivedContentType;
/***/ public String expectedReportForRefNotReceived;
+ /***/ public String failedToDetermineFilterDefinition;
/***/ public String failedUpdatingRefs;
/***/ public String failureDueToOneOfTheFollowing;
/***/ public String failureUpdatingFETCH_HEAD;