diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties index 67357be1d..e879d6b60 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties @@ -68,6 +68,7 @@ metaVar_gitDir=GIT_DIR metaVar_hostName=HOSTNAME metaVar_linesOfContext=lines metaVar_message=message +metaVar_n=n metaVar_name=name metaVar_object=object metaVar_op=OP @@ -171,6 +172,7 @@ usage_produceAnEclipseIPLog=Produce an Eclipse IP log usage_pruneStaleTrackingRefs=prune stale tracking refs usage_recurseIntoSubtrees=recurse into subtrees usage_recordChangesToRepository=Record changes to the repository +usage_renameLimit=limit size of rename matrix usage_setTheGitRepositoryToOperateOn=set the git repository to operate on usage_showRefNamesMatchingCommits=Show ref names matching commits usage_showPatch=display patch diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java index 32499618d..77ed73048 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java @@ -53,12 +53,12 @@ import java.util.List; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffFormatter; -import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.diff.RawTextIgnoreAllWhitespace; import org.eclipse.jgit.diff.RawTextIgnoreLeadingWhitespace; import org.eclipse.jgit.diff.RawTextIgnoreTrailingWhitespace; import org.eclipse.jgit.diff.RawTextIgnoreWhitespaceChange; import org.eclipse.jgit.diff.RenameDetector; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.TextProgressMonitor; import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler; import org.eclipse.jgit.treewalk.AbstractTreeIterator; @@ -70,6 +70,9 @@ import org.kohsuke.args4j.Option; @Command(common = true, usage = "usage_ShowDiffs") class Diff extends TextBuiltin { + private final DiffFormatter diffFmt = new DiffFormatter( // + new BufferedOutputStream(System.out)); + @Argument(index = 0, metaVar = "metaVar_treeish", required = true) void tree_0(final AbstractTreeIterator c) { trees.add(c); @@ -81,45 +84,55 @@ class Diff extends TextBuiltin { @Option(name = "--", metaVar = "metaVar_paths", multiValued = true, handler = PathTreeFilterHandler.class) private TreeFilter pathFilter = TreeFilter.ALL; + // BEGIN -- Options shared with Log + @Option(name = "-p", usage = "usage_showPatch") + boolean showPatch; + @Option(name = "-M", usage = "usage_detectRenames") private boolean detectRenames; + @Option(name = "-l", usage = "usage_renameLimit") + private Integer renameLimit; + @Option(name = "--name-status", usage = "usage_nameStatus") private boolean showNameAndStatusOnly; @Option(name = "--ignore-space-at-eol") - private boolean ignoreWsTrailing; + void ignoreSpaceAtEol(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreTrailingWhitespace.FACTORY); + } @Option(name = "--ignore-leading-space") - private boolean ignoreWsLeading; + void ignoreLeadingSpace(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreLeadingWhitespace.FACTORY); + } @Option(name = "-b", aliases = { "--ignore-space-change" }) - private boolean ignoreWsChange; + void ignoreSpaceChange(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreWhitespaceChange.FACTORY); + } @Option(name = "-w", aliases = { "--ignore-all-space" }) - private boolean ignoreWsAll; + void ignoreAllSpace(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreAllWhitespace.FACTORY); + } @Option(name = "-U", aliases = { "--unified" }, metaVar = "metaVar_linesOfContext") void unified(int lines) { - fmt.setContext(lines); + diffFmt.setContext(lines); } - private DiffFormatter fmt = new DiffFormatter( // - new BufferedOutputStream(System.out)) { - @Override - protected RawText newRawText(byte[] raw) { - if (ignoreWsAll) - return new RawTextIgnoreAllWhitespace(raw); - else if (ignoreWsTrailing) - return new RawTextIgnoreTrailingWhitespace(raw); - else if (ignoreWsChange) - return new RawTextIgnoreWhitespaceChange(raw); - else if (ignoreWsLeading) - return new RawTextIgnoreLeadingWhitespace(raw); - else - return new RawText(raw); - } - }; + @Option(name = "--abbrev", metaVar = "n") + void abbrev(int lines) { + diffFmt.setAbbreviationLength(lines); + } + + @Option(name = "--full-index") + void abbrev(@SuppressWarnings("unused") boolean on) { + diffFmt.setAbbreviationLength(Constants.OBJECT_ID_STRING_LENGTH); + } + + // END -- Options shared with Log @Override protected void run() throws Exception { @@ -130,9 +143,9 @@ class Diff extends TextBuiltin { out.flush(); } else { - fmt.setRepository(db); - fmt.format(files); - fmt.flush(); + diffFmt.setRepository(db); + diffFmt.format(files); + diffFmt.flush(); } } @@ -173,6 +186,8 @@ class Diff extends TextBuiltin { List files = DiffEntry.scan(walk); if (detectRenames) { RenameDetector rd = new RenameDetector(db); + if (renameLimit != null) + rd.setRenameLimit(renameLimit.intValue()); rd.addAll(files); files = rd.compute(new TextProgressMonitor()); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java index aa4e8ae3c..83ef6eb87 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java @@ -60,8 +60,13 @@ import java.util.TimeZone; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffFormatter; +import org.eclipse.jgit.diff.RawTextIgnoreAllWhitespace; +import org.eclipse.jgit.diff.RawTextIgnoreLeadingWhitespace; +import org.eclipse.jgit.diff.RawTextIgnoreTrailingWhitespace; +import org.eclipse.jgit.diff.RawTextIgnoreWhitespaceChange; import org.eclipse.jgit.diff.RenameDetector; import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.TextProgressMonitor; @@ -78,27 +83,63 @@ class Log extends RevWalkTextBuiltin { private final DateFormat fmt; + private final DiffFormatter diffFmt = new DiffFormatter( // + new BufferedOutputStream(System.out)); + private Map> allRefsByPeeledObjectId; @Option(name="--decorate", usage="usage_showRefNamesMatchingCommits") private boolean decorate; + // BEGIN -- Options shared with Diff + @Option(name = "-p", usage = "usage_showPatch") + boolean showPatch; + @Option(name = "-M", usage = "usage_detectRenames") private boolean detectRenames; + @Option(name = "-l", usage = "usage_renameLimit") + private Integer renameLimit; + @Option(name = "--name-status", usage = "usage_nameStatus") private boolean showNameAndStatusOnly; - @Option(name = "-p", usage = "usage_showPatch") - private boolean showPatch; + @Option(name = "--ignore-space-at-eol") + void ignoreSpaceAtEol(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreTrailingWhitespace.FACTORY); + } + + @Option(name = "--ignore-leading-space") + void ignoreLeadingSpace(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreLeadingWhitespace.FACTORY); + } + + @Option(name = "-b", aliases = { "--ignore-space-change" }) + void ignoreSpaceChange(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreWhitespaceChange.FACTORY); + } + + @Option(name = "-w", aliases = { "--ignore-all-space" }) + void ignoreAllSpace(@SuppressWarnings("unused") boolean on) { + diffFmt.setRawTextFactory(RawTextIgnoreAllWhitespace.FACTORY); + } @Option(name = "-U", aliases = { "--unified" }, metaVar = "metaVar_linesOfContext") void unified(int lines) { diffFmt.setContext(lines); } - private DiffFormatter diffFmt = new DiffFormatter( // - new BufferedOutputStream(System.out)); + @Option(name = "--abbrev", metaVar = "metaVar_n") + void abbrev(int lines) { + diffFmt.setAbbreviationLength(lines); + } + + @Option(name = "--full-index") + void abbrev(@SuppressWarnings("unused") boolean on) { + diffFmt.setAbbreviationLength(Constants.OBJECT_ID_STRING_LENGTH); + } + + // END -- Options shared with Diff Log() { fmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy ZZZZZ", Locale.US); @@ -147,7 +188,7 @@ class Log extends RevWalkTextBuiltin { } out.println(); - if (c.getParentCount() > 0 && (showNameAndStatusOnly || showPatch)) + if (c.getParentCount() == 1 && (showNameAndStatusOnly || showPatch)) showDiff(c); out.flush(); } @@ -163,6 +204,8 @@ class Log extends RevWalkTextBuiltin { List files = DiffEntry.scan(tw); if (detectRenames) { RenameDetector rd = new RenameDetector(db); + if (renameLimit != null) + rd.setRenameLimit(renameLimit.intValue()); rd.addAll(files); files = rd.compute(new TextProgressMonitor()); } @@ -175,5 +218,6 @@ class Log extends RevWalkTextBuiltin { diffFmt.format(files); diffFmt.flush(); } + out.println(); } } diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties index afe7a8c05..50fadfa81 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties @@ -6,6 +6,7 @@ JRELacksMD5Implementation=JRE lacks MD5 implementation URINotSupported=URI not supported: {0} URLNotFound={0} not found aNewObjectIdIsRequired=A NewObjectId is required. +abbreviationLengthMustBeNonNegative=Abbreviation length must not be negative. advertisementCameBefore=advertisement of {0}^{} came before {1} advertisementOfCameBefore=advertisement of {0}^{} came before {1} amazonS3ActionFailed={0} of '{1}' failed: {2} {3} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java index 1f21b4a02..f46461be6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java @@ -66,6 +66,7 @@ public class JGitText extends TranslationBundle { /***/ public String URINotSupported; /***/ public String URLNotFound; /***/ public String aNewObjectIdIsRequired; + /***/ public String abbreviationLengthMustBeNonNegative; /***/ public String advertisementCameBefore; /***/ public String advertisementOfCameBefore; /***/ public String amazonS3ActionFailed; 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 e114b9220..c12c54b05 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -73,6 +73,10 @@ public class DiffFormatter { private int context; + private int abbreviationLength; + + private RawText.Factory rawTextFactory = RawText.FACTORY; + /** * Create a new formatter with a default level of context. * @@ -84,6 +88,7 @@ public class DiffFormatter { public DiffFormatter(OutputStream out) { this.out = out; setContext(3); + setAbbreviationLength(8); } /** @return the stream we are outputting data to. */ @@ -116,6 +121,36 @@ public class DiffFormatter { context = lineCount; } + /** + * Change the number of digits to show in an ObjectId. + * + * @param count + * number of digits to show in an ObjectId. + */ + public void setAbbreviationLength(final int count) { + if (count < 0) + throw new IllegalArgumentException( + JGitText.get().abbreviationLengthMustBeNonNegative); + abbreviationLength = count; + } + + /** + * Set the helper that constructs difference output. + * + * @param type + * the factory to create different output. Different types of + * factories can produce different whitespace behavior, for + * example. + * @see RawText#FACTORY + * @see RawTextIgnoreAllWhitespace#FACTORY + * @see RawTextIgnoreLeadingWhitespace#FACTORY + * @see RawTextIgnoreTrailingWhitespace#FACTORY + * @see RawTextIgnoreWhitespaceChange#FACTORY + */ + public void setRawTextFactory(RawText.Factory type) { + rawTextFactory = type; + } + /** * Flush the underlying output stream of this formatter. * @@ -143,24 +178,13 @@ public class DiffFormatter { /** * Format a patch script for one file entry. * - * @param entry + * @param ent * the entry to be formatted. * @throws IOException * a file's content cannot be read, or the output stream cannot * be written to. */ - public void format(DiffEntry entry) throws IOException { - if (entry instanceof FileHeader) { - format( - (FileHeader) entry, // - newRawText(open(entry.getOldMode(), entry.getOldId())), - newRawText(open(entry.getNewMode(), entry.getNewId()))); - } else { - formatAndDiff(entry); - } - } - - private void formatAndDiff(DiffEntry ent) throws IOException { + public void format(DiffEntry ent) throws IOException { String oldName = quotePath("a/" + ent.getOldName()); String newName = quotePath("b/" + ent.getNewName()); out.write(encode("diff --git " + oldName + " " + newName + "\n")); @@ -250,27 +274,16 @@ public class DiffFormatter { out.write(encodeASCII("Binary files differ\n")); } else { - RawText a = newRawText(aRaw); - RawText b = newRawText(bRaw); + RawText a = rawTextFactory.create(aRaw); + RawText b = rawTextFactory.create(bRaw); formatEdits(a, b, new MyersDiff(a, b).getEdits()); } } } - /** - * Construct a RawText sequence for use with {@link MyersDiff}. - * - * @param content - * text to be compared. - * @return the raw text instance to handle the content. - */ - protected RawText newRawText(byte[] content) { - return new RawText(content); - } - private String format(AbbreviatedObjectId oldId) { if (oldId.isComplete() && db != null) - oldId = oldId.toObjectId().abbreviate(db, 8); + oldId = oldId.toObjectId().abbreviate(db, abbreviationLength); return oldId.name(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java index c01cb7ad8..574d2edf9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java @@ -65,6 +65,25 @@ import org.eclipse.jgit.util.RawParseUtils; * they are converting from "line number" to "element index". */ public class RawText implements Sequence { + /** Creates a RawText instance. */ + public static interface Factory { + /** + * Construct a RawText instance for the content. + * + * @param input + * the content array. + * @return a RawText instance wrapping this content. + */ + RawText create(byte[] input); + } + + /** Creates RawText that does not treat whitespace specially. */ + public static final Factory FACTORY = new Factory() { + public RawText create(byte[] input) { + return new RawText(input); + } + }; + /** Number of bytes to check for heuristics in {@link #isBinary(byte[])} */ private static final int FIRST_FEW_BYTES = 8000; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java index f72259605..211618a3f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreAllWhitespace.java @@ -51,6 +51,13 @@ import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace; * A version of {@link RawText} that ignores all whitespace. */ public class RawTextIgnoreAllWhitespace extends RawText { + /** Creates RawText that ignores all whitespace. */ + @SuppressWarnings("hiding") + public static final Factory FACTORY = new Factory() { + public RawText create(byte[] input) { + return new RawTextIgnoreAllWhitespace(input); + } + }; /** * Create a new sequence from an existing content byte array. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java index 1d928766a..23778973b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreLeadingWhitespace.java @@ -50,6 +50,13 @@ import static org.eclipse.jgit.util.RawCharUtil.trimLeadingWhitespace; * A version of {@link RawText} that ignores leading whitespace. */ public class RawTextIgnoreLeadingWhitespace extends RawText { + /** Creates RawText that ignores only leading whitespace. */ + @SuppressWarnings("hiding") + public static final Factory FACTORY = new Factory() { + public RawText create(byte[] input) { + return new RawTextIgnoreLeadingWhitespace(input); + } + }; /** * Create a new sequence from an existing content byte array. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java index b9095940c..3feb2e783 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreTrailingWhitespace.java @@ -50,6 +50,13 @@ import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace; * A version of {@link RawText} that ignores trailing whitespace. */ public class RawTextIgnoreTrailingWhitespace extends RawText { + /** Creates RawText that ignores only trailing whitespace. */ + @SuppressWarnings("hiding") + public static final Factory FACTORY = new Factory() { + public RawText create(byte[] input) { + return new RawTextIgnoreTrailingWhitespace(input); + } + }; /** * Create a new sequence from an existing content byte array. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java index 399f038bc..e6bd8e98b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawTextIgnoreWhitespaceChange.java @@ -45,14 +45,21 @@ package org.eclipse.jgit.diff; import static org.eclipse.jgit.util.RawCharUtil.isWhitespace; -import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace; import static org.eclipse.jgit.util.RawCharUtil.trimLeadingWhitespace; +import static org.eclipse.jgit.util.RawCharUtil.trimTrailingWhitespace; /** * A version of {@link RawText} that ignores changes in the amount of * whitespace, as well as trailing whitespace. */ public class RawTextIgnoreWhitespaceChange extends RawText { + /** Creates RawText that ignores only whitespace changes. */ + @SuppressWarnings("hiding") + public static final Factory FACTORY = new Factory() { + public RawText create(byte[] input) { + return new RawTextIgnoreWhitespaceChange(input); + } + }; /** * Create a new sequence from an existing content byte array.