diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java index 4ad01cf6f0b..ead713cd2ce 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java @@ -51,6 +51,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.List; +import java.util.regex.Pattern; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffEntry.ChangeType; @@ -129,7 +130,7 @@ public void testDiffCached() throws Exception { + "@@ -0,0 +1 @@\n" + "+folder\n" + "\\ No newline at end of file\n"; - assertEquals(expected.toString(), actual); + assertEquals(expected, actual); } @Test @@ -177,7 +178,7 @@ public void testDiffTwoCommits() throws Exception { + "\\ No newline at end of file\n" + "+folder change\n" + "\\ No newline at end of file\n"; - assertEquals(expected.toString(), actual); + assertEquals(expected, actual); } @Test @@ -199,7 +200,7 @@ public void testDiffWithPrefixes() throws Exception { + "+++ new/test.txt\n" + "@@ -1 +1 @@\n" + "-test\n" + "\\ No newline at end of file\n" + "+test change\n" + "\\ No newline at end of file\n"; - assertEquals(expected.toString(), actual); + assertEquals(expected, actual); } @Test @@ -221,7 +222,7 @@ public void testDiffWithNegativeLineCount() throws Exception { + "index f55b5c9..c5ec8fd 100644\n" + "--- a/test.txt\n" + "+++ b/test.txt\n" + "@@ -4,3 +4,3 @@\n" + " 3\n" + "-4\n" + "+4a\n" + " 5\n"; - assertEquals(expected.toString(), actual); + assertEquals(expected, actual); } @Test @@ -241,6 +242,29 @@ public void testNoOutputStreamSet() throws Exception { assertEquals("test.txt", diff.getNewPath()); } + @Test + /** + * Setting a delta filter Pattern (applies to any file) with regex that matches the + * change: diff skipped. + */ + public void testDiffModified_anyDeltaFilter() throws Exception { + write(new File(db.getWorkTree(), "test.txt"), "test"); + File folder = new File(db.getWorkTree(), "folder"); + folder.mkdir(); + write(new File(folder, "folder.txt"), "folder"); + Git git = new Git(db); + git.add().addFilepattern(".").call(); + git.commit().setMessage("Initial commit").call(); + write(new File(folder, "folder.txt"), "folderchange"); + + OutputStream out = new ByteArrayOutputStream(); + Pattern deltaFilterPattern = Pattern.compile("change"); + List entries = git.diff().setDeltaFilterPattern(deltaFilterPattern).setOutputStream(out).call(); + assertEquals(0, entries.size()); + + assertEquals("", out.toString()); + } + private AbstractTreeIterator getTreeIterator(String name) throws IOException { final ObjectId id = db.resolve(name); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java index 24b0f8141e9..26f17a11e1a 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java @@ -47,6 +47,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.util.regex.Pattern; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.diff.DiffEntry.ChangeType; @@ -343,6 +344,187 @@ public void testDiff() throws Exception { assertEquals(expected, actual); } + @Test + public void testDiffDeltaFilter_emptyFilter() throws Exception { + write(new File(db.getDirectory().getParent(), "test.txt"), "test"); + File folder = new File(db.getDirectory().getParent(), "folder"); + FileUtils.mkdir(folder); + write(new File(folder, "folder.txt"), "folder"); + Git git = new Git(db); + git.add().addFilepattern(".").call(); + git.commit().setMessage("Initial commit").call(); + write(new File(folder, "folder.txt"), "folder change"); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os)); + dfmt.setRepository(db); + dfmt.setPathFilter(PathFilter.create("folder")); + DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache()); + FileTreeIterator newTree = new FileTreeIterator(db); + + //testing an empty delta filter + Pattern deltaFilterPattern = Pattern.compile(""); + dfmt.format(dfmt.scan(oldTree, newTree), deltaFilterPattern); + dfmt.flush(); + + String actual = os.toString("UTF-8"); + String expected = + "diff --git a/folder/folder.txt b/folder/folder.txt\n" + + "index 0119635..95c4c65 100644\n" + + "--- a/folder/folder.txt\n" + "+++ b/folder/folder.txt\n" + + "@@ -1 +1 @@\n" + "-folder\n" + + "\\ No newline at end of file\n" + "+folder change\n" + + "\\ No newline at end of file\n"; + + assertEquals(expected, actual); + } + + @Test + /** + * This is an ADD file, the file content matches the filter: diff unchanged. + */ + public void testDiffDeltaFilter_addFile() throws Exception { + write(new File(db.getDirectory().getParent(), "test.txt"), "test"); + File folder = new File(db.getDirectory().getParent(), "folder"); + FileUtils.mkdir(folder); + Git git = new Git(db); + git.add().addFilepattern(".").call(); + git.commit().setMessage("Initial commit").call(); + write(new File(folder, "folder.txt"), "change"); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os)); + dfmt.setRepository(db); + dfmt.setPathFilter(PathFilter.create("folder")); + DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache()); + FileTreeIterator newTree = new FileTreeIterator(db); + + //testing a delta filter with one regex + Pattern deltaFilterPattern = Pattern.compile("change"); + dfmt.format(dfmt.scan(oldTree, newTree), deltaFilterPattern); + dfmt.flush(); + + String actual = os.toString("UTF-8"); + String expected = + "diff --git a/folder/folder.txt b/folder/folder.txt\n" + + "new file mode 100644\n" + + "index 0000000..8013df8\n" + + "--- /dev/null\n" + + "+++ b/folder/folder.txt\n" + + "@@ -0,0 +1 @@\n" + + "+change\n" + + "\\ No newline at end of file\n"; + + assertEquals(expected, actual); + } + + @Test + /** + * This is an DELETE file, the file content matches the filter: diff unchanged. + */ + public void testDiffDeltaFilter_deleteFile() throws Exception { + write(new File(db.getDirectory().getParent(), "test.txt"), "test"); + File folder = new File(db.getDirectory().getParent(), "folder"); + FileUtils.mkdir(folder); + write(new File(folder, "folder.txt"), "change"); + Git git = new Git(db); + git.add().addFilepattern(".").call(); + git.commit().setMessage("Initial commit").call(); + new File(folder, "folder.txt").delete(); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os)); + dfmt.setRepository(db); + dfmt.setPathFilter(PathFilter.create("folder")); + DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache()); + FileTreeIterator newTree = new FileTreeIterator(db); + + //testing a delta filter with one regex + Pattern deltaFilterPattern = Pattern.compile("change"); + dfmt.format(dfmt.scan(oldTree, newTree), deltaFilterPattern); + dfmt.flush(); + + String actual = os.toString("UTF-8"); + String expected = + "diff --git a/folder/folder.txt b/folder/folder.txt\n" + + "deleted file mode 100644\n" + + "index 8013df8..0000000\n" + + "--- a/folder/folder.txt\n" + + "+++ /dev/null\n" + + "@@ -1 +0,0 @@\n" + + "-change\n" + + "\\ No newline at end of file\n"; + + assertEquals(expected, actual); + } + + @Test + /** + * Filter for any file matches the content of the changed file: diff skipped. + */ + public void testDiffDeltaFilter_filteredModifiedFile() throws Exception { + write(new File(db.getDirectory().getParent(), "test.txt"), "test"); + File folder = new File(db.getDirectory().getParent(), "folder"); + FileUtils.mkdir(folder); + write(new File(folder, "folder.txt"), "folder"); + Git git = new Git(db); + git.add().addFilepattern(".").call(); + git.commit().setMessage("Initial commit").call(); + write(new File(folder, "folder.txt"), "folderchange"); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os)); + dfmt.setRepository(db); + dfmt.setPathFilter(PathFilter.create("folder")); + DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache()); + FileTreeIterator newTree = new FileTreeIterator(db); + + //testing a delta filter with one regex (ANY) + Pattern deltaFilterPattern = Pattern.compile("change"); + dfmt.format(dfmt.scan(oldTree, newTree), deltaFilterPattern); + dfmt.flush(); + + assertEquals("", os.toString("UTF-8")); + } + + @Test + /** + * The filter doesn't match any change: diff unchanged. + */ + public void testDiffDeltaFilter_filterNoMatch() throws Exception { + write(new File(db.getDirectory().getParent(), "test.txt"), "test"); + File folder = new File(db.getDirectory().getParent(), "folder"); + FileUtils.mkdir(folder); + write(new File(folder, "folder.txt"), "folder"); + Git git = new Git(db); + git.add().addFilepattern(".").call(); + git.commit().setMessage("Initial commit").call(); + write(new File(folder, "folder.txt"), "folderchange"); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os)); + dfmt.setRepository(db); + dfmt.setPathFilter(PathFilter.create("folder")); + DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache()); + FileTreeIterator newTree = new FileTreeIterator(db); + + //testing a delta filter with one regex (ANY) + Pattern deltaFilterPattern = Pattern.compile("xxxx"); + dfmt.format(dfmt.scan(oldTree, newTree), deltaFilterPattern); + dfmt.flush(); + + String actual = os.toString("UTF-8"); + String expected = + "diff --git a/folder/folder.txt b/folder/folder.txt\n" + + "index 0119635..0b099ef 100644\n" + + "--- a/folder/folder.txt\n" + "+++ b/folder/folder.txt\n" + + "@@ -1 +1 @@\n" + "-folder\n" + + "\\ No newline at end of file\n" + "+folderchange\n" + + "\\ No newline at end of file\n"; + + assertEquals(expected, actual); + } + @Test public void testDiffRootNullToTree() throws Exception { write(new File(db.getDirectory().getParent(), "test.txt"), "test"); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DiffCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DiffCommand.java index 3e3a7a89c8e..61f04b8a9c4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DiffCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DiffCommand.java @@ -48,6 +48,8 @@ import java.io.IOException; import java.io.OutputStream; import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; @@ -94,6 +96,8 @@ public class DiffCommand extends GitCommand> { private ProgressMonitor monitor = NullProgressMonitor.INSTANCE; + private Pattern deltaFilterPattern = null; + /** * @param repo */ @@ -101,12 +105,16 @@ protected DiffCommand(Repository repo) { super(repo); } + + /** * Executes the {@code Diff} command with all the options and parameters * collected by the setter methods (e.g. {@link #setCached(boolean)} of this * class. Each instance of this class should only be used for one invocation * of the command. Don't call this method twice on an instance. * + * Team-Devatscale SC customization to filter some files based on a regex pattern. + * This filter will not be applied if showNameAndStatusOnly is set to true * @return a DiffEntry for each path which is different */ public List call() throws GitAPIException { @@ -149,7 +157,9 @@ public List call() throws GitAPIException { diffFmt.setNewPrefix(destinationPrefix); if (sourcePrefix != null) diffFmt.setOldPrefix(sourcePrefix); - diffFmt.format(result); + + diffFmt.format(result, this.getDeltaFilterPattern()); + diffFmt.flush(); return result; } @@ -274,4 +284,20 @@ public DiffCommand setProgressMonitor(ProgressMonitor monitor) { this.monitor = monitor; return this; } + + public Pattern getDeltaFilterPattern() { + return deltaFilterPattern; + } + + /** + * Set the given delta filter regex pattern. Used only for Source Control. + * + * @param deltaFilterPattern + * the filter pattern + * @return this instance + */ + public DiffCommand setDeltaFilterPattern(Pattern deltaFilterPattern) { + this.deltaFilterPattern = deltaFilterPattern; + return this; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java index 4c0ed386e88..6be212b7762 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -60,7 +60,9 @@ import java.io.OutputStream; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; +import java.util.regex.Pattern; import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm; import org.eclipse.jgit.diff.DiffEntry.ChangeType; @@ -145,6 +147,10 @@ public class DiffFormatter implements AutoCloseable { private ContentSource.Pair source; + private static final String EMPTY_STRING = ""; + + + /** * Create a new formatter with a default level of context. * @@ -651,6 +657,38 @@ public void format(List entries) throws IOException { format(ent); } + /** + * Format the diff entries by filtering out the noise from the given delta filter pattern + * The filter acts only for files that have MODIFY change Type. + * If there are no changes detected, we will remove the diff entry. + * @param entries + * @param deltaFilterPattern + * @throws IOException + */ + + public void format(List entries, Pattern deltaFilterPattern) throws IOException { + if (deltaFilterPattern == null) { + format(entries); + return; + } + Iterator diIterator = entries.iterator(); + while (diIterator.hasNext()) { + DiffEntry diffEntry = diIterator.next(); + if (MODIFY.equals(diffEntry.changeType)) { + FormatResult res = createFormatResult(diffEntry); + String aContent = new String(res.a.content); + String bContent = new String(res.b.content); + aContent = deltaFilterPattern.matcher(aContent).replaceAll(EMPTY_STRING); + bContent = deltaFilterPattern.matcher(bContent).replaceAll(EMPTY_STRING); + if (!aContent.equals(bContent)) + format(res.header, res.a, res.b); + else + diIterator.remove(); + } else format(diffEntry); + } + } + + /** * Format a patch script for one file entry. *