log: Add whitespace ignore options

Similar to what we did with diff, implement whitespace ignore options
for log too.  This requires us to define some means of creating any
RawText object type at will inside of DiffFormatter, so we define a
new factory interface to construct RawText instances on demand.

Unfortunately we have to copy the entire block of common options.
args4j only processes the options/arguments on the one command class
and Java doesn't support multiple inheritance.

Change-Id: Ia16cd3a11b850fffae9fbe7b721d7e43f1d0e8a5
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
Shawn O. Pearce 2010-07-03 17:32:47 -07:00
parent bd8740dc14
commit 8a0c58394d
11 changed files with 181 additions and 58 deletions

View File

@ -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

View File

@ -53,12 +53,12 @@
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 @@
@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 @@ void tree_0(final AbstractTreeIterator c) {
@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 @@ protected void run() throws Exception {
out.flush();
} else {
fmt.setRepository(db);
fmt.format(files);
fmt.flush();
diffFmt.setRepository(db);
diffFmt.format(files);
diffFmt.flush();
}
}
@ -173,6 +186,8 @@ private List<DiffEntry> scan() throws IOException {
List<DiffEntry> 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());
}

View File

@ -60,8 +60,13 @@
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<AnyObjectId, Set<Ref>> 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 @@ protected void show(final RevCommit c) throws Exception {
}
out.println();
if (c.getParentCount() > 0 && (showNameAndStatusOnly || showPatch))
if (c.getParentCount() == 1 && (showNameAndStatusOnly || showPatch))
showDiff(c);
out.flush();
}
@ -163,6 +204,8 @@ private void showDiff(RevCommit c) throws IOException {
List<DiffEntry> 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 @@ private void showDiff(RevCommit c) throws IOException {
diffFmt.format(files);
diffFmt.flush();
}
out.println();
}
}

View File

@ -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}

View File

@ -66,6 +66,7 @@ public static JGitText get() {
/***/ public String URINotSupported;
/***/ public String URLNotFound;
/***/ public String aNewObjectIdIsRequired;
/***/ public String abbreviationLengthMustBeNonNegative;
/***/ public String advertisementCameBefore;
/***/ public String advertisementOfCameBefore;
/***/ public String amazonS3ActionFailed;

View File

@ -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 void setContext(final int lineCount) {
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 void format(List<? extends DiffEntry> entries) throws IOException {
/**
* 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 @@ private void formatAndDiff(DiffEntry ent) throws IOException {
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();
}

View File

@ -65,6 +65,25 @@
* 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;

View File

@ -51,6 +51,13 @@
* 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.

View File

@ -50,6 +50,13 @@
* 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.

View File

@ -50,6 +50,13 @@
* 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.

View File

@ -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.