diff options
Diffstat (limited to 'org.eclipse.jgit')
9 files changed, 230 insertions, 121 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java index 7dbcdaa6d9..55ecc4e22a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java @@ -112,15 +112,15 @@ public class DiffEntry { entry.oldMode = walk.getFileMode(0); entry.newMode = walk.getFileMode(1); - entry.newName = entry.oldName = walk.getPathString(); + entry.newPath = entry.oldPath = walk.getPathString(); if (entry.oldMode == FileMode.MISSING) { - entry.oldName = DiffEntry.DEV_NULL; + entry.oldPath = DiffEntry.DEV_NULL; entry.changeType = ChangeType.ADD; r.add(entry); } else if (entry.newMode == FileMode.MISSING) { - entry.newName = DiffEntry.DEV_NULL; + entry.newPath = DiffEntry.DEV_NULL; entry.changeType = ChangeType.DELETE; r.add(entry); @@ -139,11 +139,11 @@ public class DiffEntry { DiffEntry e = new DiffEntry(); e.oldId = A_ZERO; e.oldMode = FileMode.MISSING; - e.oldName = DEV_NULL; + e.oldPath = DEV_NULL; e.newId = AbbreviatedObjectId.fromObjectId(id); e.newMode = FileMode.REGULAR_FILE; - e.newName = path; + e.newPath = path; e.changeType = ChangeType.ADD; return e; } @@ -152,11 +152,11 @@ public class DiffEntry { DiffEntry e = new DiffEntry(); e.oldId = AbbreviatedObjectId.fromObjectId(id); e.oldMode = FileMode.REGULAR_FILE; - e.oldName = path; + e.oldPath = path; e.newId = A_ZERO; e.newMode = FileMode.MISSING; - e.newName = DEV_NULL; + e.newPath = DEV_NULL; e.changeType = ChangeType.DELETE; return e; } @@ -164,10 +164,10 @@ public class DiffEntry { static DiffEntry modify(String path) { DiffEntry e = new DiffEntry(); e.oldMode = FileMode.REGULAR_FILE; - e.oldName = path; + e.oldPath = path; e.newMode = FileMode.REGULAR_FILE; - e.newName = path; + e.newPath = path; e.changeType = ChangeType.MODIFY; return e; } @@ -185,21 +185,21 @@ public class DiffEntry { DiffEntry del = new DiffEntry(); del.oldId = entry.getOldId(); del.oldMode = entry.getOldMode(); - del.oldName = entry.getOldName(); + del.oldPath = entry.getOldPath(); del.newId = A_ZERO; del.newMode = FileMode.MISSING; - del.newName = DiffEntry.DEV_NULL; + del.newPath = DiffEntry.DEV_NULL; del.changeType = ChangeType.DELETE; DiffEntry add = new DiffEntry(); add.oldId = A_ZERO; add.oldMode = FileMode.MISSING; - add.oldName = DiffEntry.DEV_NULL; + add.oldPath = DiffEntry.DEV_NULL; add.newId = entry.getNewId(); add.newMode = entry.getNewMode(); - add.newName = entry.getNewName(); + add.newPath = entry.getNewPath(); add.changeType = ChangeType.ADD; return Arrays.asList(del, add); } @@ -210,11 +210,11 @@ public class DiffEntry { r.oldId = src.oldId; r.oldMode = src.oldMode; - r.oldName = src.oldName; + r.oldPath = src.oldPath; r.newId = dst.newId; r.newMode = dst.newMode; - r.newName = dst.newName; + r.newPath = dst.newPath; r.changeType = changeType; r.score = score; @@ -223,10 +223,10 @@ public class DiffEntry { } /** File name of the old (pre-image). */ - protected String oldName; + protected String oldPath; /** File name of the new (post-image). */ - protected String newName; + protected String newPath; /** Old mode of the file, if described by the patch, else null. */ protected FileMode oldMode; @@ -253,7 +253,7 @@ public class DiffEntry { * of this patch: * <ul> * <li><i>file add</i>: always <code>/dev/null</code></li> - * <li><i>file modify</i>: always {@link #getNewName()}</li> + * <li><i>file modify</i>: always {@link #getNewPath()}</li> * <li><i>file delete</i>: always the file being deleted</li> * <li><i>file copy</i>: source file the copy originates from</li> * <li><i>file rename</i>: source file the rename originates from</li> @@ -261,8 +261,8 @@ public class DiffEntry { * * @return old name for this file. */ - public String getOldName() { - return oldName; + public String getOldPath() { + return oldPath; } /** @@ -272,7 +272,7 @@ public class DiffEntry { * of this patch: * <ul> * <li><i>file add</i>: always the file being created</li> - * <li><i>file modify</i>: always {@link #getOldName()}</li> + * <li><i>file modify</i>: always {@link #getOldPath()}</li> * <li><i>file delete</i>: always <code>/dev/null</code></li> * <li><i>file copy</i>: destination file the copy ends up at</li> * <li><i>file rename</i>: destination file the rename ends up at/li> @@ -280,8 +280,8 @@ public class DiffEntry { * * @return new name for this file. */ - public String getNewName() { - return newName; + public String getNewPath() { + return newPath; } /** @return the old file mode, if described in the patch */ @@ -294,14 +294,14 @@ public class DiffEntry { return newMode; } - /** @return the type of change this patch makes on {@link #getNewName()} */ + /** @return the type of change this patch makes on {@link #getNewPath()} */ public ChangeType getChangeType() { return changeType; } /** - * @return similarity score between {@link #getOldName()} and - * {@link #getNewName()} if {@link #getChangeType()} is + * @return similarity score between {@link #getOldPath()} and + * {@link #getNewPath()} if {@link #getChangeType()} is * {@link ChangeType#COPY} or {@link ChangeType#RENAME}. */ public int getScore() { @@ -334,19 +334,19 @@ public class DiffEntry { buf.append(" "); switch (changeType) { case ADD: - buf.append(newName); + buf.append(newPath); break; case COPY: - buf.append(oldName + "->" + newName); + buf.append(oldPath + "->" + newPath); break; case DELETE: - buf.append(oldName); + buf.append(oldPath); break; case MODIFY: - buf.append(oldName); + buf.append(oldPath); break; case RENAME: - buf.append(oldName + "->" + newName); + buf.append(oldPath + "->" + newPath); break; } buf.append("]"); 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 4ee742ae16..bb4a77c427 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -246,8 +246,8 @@ public class DiffFormatter { private void writeDiffHeader(OutputStream o, DiffEntry ent) throws IOException { - String oldName = quotePath("a/" + ent.getOldName()); - String newName = quotePath("b/" + ent.getNewName()); + String oldName = quotePath("a/" + ent.getOldPath()); + String newName = quotePath("b/" + ent.getNewPath()); o.write(encode("diff --git " + oldName + " " + newName + "\n")); switch (ent.getChangeType()) { @@ -267,10 +267,10 @@ public class DiffFormatter { o.write(encodeASCII("similarity index " + ent.getScore() + "%")); o.write('\n'); - o.write(encode("rename from " + quotePath(ent.getOldName()))); + o.write(encode("rename from " + quotePath(ent.getOldPath()))); o.write('\n'); - o.write(encode("rename to " + quotePath(ent.getNewName()))); + o.write(encode("rename to " + quotePath(ent.getNewPath()))); o.write('\n'); break; @@ -278,10 +278,10 @@ public class DiffFormatter { o.write(encodeASCII("similarity index " + ent.getScore() + "%")); o.write('\n'); - o.write(encode("copy from " + quotePath(ent.getOldName()))); + o.write(encode("copy from " + quotePath(ent.getOldPath()))); o.write('\n'); - o.write(encode("copy to " + quotePath(ent.getNewName()))); + o.write(encode("copy to " + quotePath(ent.getNewPath()))); o.write('\n'); if (!ent.getOldMode().equals(ent.getNewMode())) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java index fedd7cda15..3ae3dc422c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java @@ -80,8 +80,8 @@ public class RenameDetector { // the old name. // if (ent.changeType == ChangeType.DELETE) - return ent.oldName; - return ent.newName; + return ent.oldPath; + return ent.newPath; } private int sortOf(ChangeType changeType) { @@ -369,18 +369,18 @@ public class RenameDetector { + deleted.size()); for (DiffEntry src : deleted) { - nameMap.put(src.oldName, src); + nameMap.put(src.oldPath, src); pm.update(1); } for (DiffEntry dst : added) { - DiffEntry src = nameMap.remove(dst.newName); + DiffEntry src = nameMap.remove(dst.newPath); if (src != null) { if (sameType(src.oldMode, dst.newMode)) { entries.add(DiffEntry.pair(ChangeType.MODIFY, src, dst, src.score)); } else { - nameMap.put(src.oldName, src); + nameMap.put(src.oldPath, src); newAdded.add(dst); } } else { @@ -509,10 +509,10 @@ public class RenameDetector { long[] matrix = new long[dels.size() * adds.size()]; int mNext = 0; for (int addIdx = 0; addIdx < adds.size(); addIdx++) { - String addedName = adds.get(addIdx).newName; + String addedName = adds.get(addIdx).newPath; for (int delIdx = 0; delIdx < dels.size(); delIdx++) { - String deletedName = dels.get(delIdx).oldName; + String deletedName = dels.get(delIdx).oldPath; int score = SimilarityRenameDetector.nameScore(addedName, deletedName); matrix[mNext] = SimilarityRenameDetector.encode(score, addIdx, delIdx); @@ -625,7 +625,7 @@ public class RenameDetector { } private static String path(DiffEntry de) { - return de.changeType == ChangeType.DELETE ? de.oldName : de.newName; + return de.changeType == ChangeType.DELETE ? de.oldPath : de.newPath; } private static FileMode mode(DiffEntry de) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java index 22b74f461c..39bcebb4c3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java @@ -216,7 +216,8 @@ class SimilarityIndex { for (;;) { if (srcKey == dstKey) { - common += countOf(dstHash[dstIdx]); + common += Math.min(countOf(srcHash[srcIdx]), + countOf(dstHash[dstIdx])); if (++srcIdx == srcHash.length) break; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java index d05fc2a313..643ac01525 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java @@ -266,7 +266,7 @@ class SimilarityRenameDetector { // nameScore returns a value between 0 and 100, but we want it // to be in the same range as the content score. This allows it // to be dropped into the pretty formula for the final score. - int nameScore = nameScore(srcEnt.oldName, dstEnt.newName) * 100; + int nameScore = nameScore(srcEnt.oldPath, dstEnt.newPath) * 100; int score = (contentScore * 99 + nameScore * 1) / 10000; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java index db0f942b07..d4e6ac9824 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -44,97 +45,163 @@ package org.eclipse.jgit.lib; -import java.io.File; import java.io.IOException; import java.util.HashSet; -import org.eclipse.jgit.lib.GitIndex.Entry; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.AbstractTreeIterator; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.WorkingTreeIterator; +import org.eclipse.jgit.treewalk.filter.TreeFilter; /** - * Compares the Index, a Tree, and the working directory - * - * @deprecated Use {@link org.eclipse.jgit.treewalk.TreeWalk} instead, with at - * least the {@link org.eclipse.jgit.dircache.DirCacheIterator} and - * {@link org.eclipse.jgit.treewalk.FileTreeIterator} iterators, and setting - * the filter {@link org.eclipse.jgit.treewalk.filter.TreeFilter#ANY_DIFF}. + * Compares the index, a tree, and the working directory + * Ignored files are not taken into account. + * The following information is retrieved: + * <li> added files + * <li> changed files + * <li> removed files + * <li> missing files + * <li> modified files + * <li> untracked files */ -@Deprecated public class IndexDiff { - private GitIndex index; - private Tree tree; + + private final static int TREE = 0; + + private final static int INDEX = 1; + + private final static int WORKDIR = 2; + + private final Repository repository; + + private final RevTree tree; + + private final WorkingTreeIterator initialWorkingTreeIterator; + + private HashSet<String> added = new HashSet<String>(); + + private HashSet<String> changed = new HashSet<String>(); + + private HashSet<String> removed = new HashSet<String>(); + + private HashSet<String> missing = new HashSet<String>(); + + private HashSet<String> modified = new HashSet<String>(); + + private HashSet<String> untracked = new HashSet<String>(); /** - * Construct an indexdiff for diffing the workdir against - * the index. + * Construct an IndexDiff * * @param repository + * @param revstr + * symbolic name e.g. HEAD + * @param workingTreeIterator + * iterator for working directory * @throws IOException */ - public IndexDiff(Repository repository) throws IOException { - this.tree = repository.mapTree(Constants.HEAD); - this.index = repository.getIndex(); + public IndexDiff(Repository repository, String revstr, + WorkingTreeIterator workingTreeIterator) throws IOException { + this.repository = repository; + ObjectId objectId = repository.resolve(revstr); + tree = new RevWalk(repository).parseTree(objectId); + this.initialWorkingTreeIterator = workingTreeIterator; } /** - * Construct an indexdiff for diffing the workdir against both - * the index and a tree. + * Construct an Indexdiff * - * @param tree - * @param index + * @param repository + * @param objectId + * tree id + * @param workingTreeIterator + * iterator for working directory + * @throws IOException */ - public IndexDiff(Tree tree, GitIndex index) { - this.tree = tree; - this.index = index; + public IndexDiff(Repository repository, ObjectId objectId, + WorkingTreeIterator workingTreeIterator) throws IOException { + this.repository = repository; + tree = new RevWalk(repository).parseTree(objectId); + this.initialWorkingTreeIterator = workingTreeIterator; } - boolean anyChanges = false; - /** * Run the diff operation. Until this is called, all lists will be empty + * * @return if anything is different between index, tree, and workdir * @throws IOException */ public boolean diff() throws IOException { - final File root = index.getRepository().getWorkTree(); - new IndexTreeWalker(index, tree, root, new AbstractIndexTreeVisitor() { - public void visitEntry(TreeEntry treeEntry, Entry indexEntry, File file) { - if (treeEntry == null) { - added.add(indexEntry.getName()); - anyChanges = true; - } else if (indexEntry == null) { - if (!(treeEntry instanceof Tree)) - removed.add(treeEntry.getFullName()); - anyChanges = true; + boolean changesExist = false; + DirCache dirCache = repository.readDirCache(); + TreeWalk treeWalk = new TreeWalk(repository); + treeWalk.reset(); + treeWalk.setRecursive(true); + // add the trees (tree, dirchache, workdir) + treeWalk.addTree(tree); + treeWalk.addTree(new DirCacheIterator(dirCache)); + treeWalk.addTree(initialWorkingTreeIterator); + treeWalk.setFilter(TreeFilter.ANY_DIFF); + while (treeWalk.next()) { + AbstractTreeIterator treeIterator = treeWalk.getTree(TREE, + AbstractTreeIterator.class); + DirCacheIterator dirCacheIterator = treeWalk.getTree(INDEX, + DirCacheIterator.class); + WorkingTreeIterator workingTreeIterator = treeWalk.getTree(WORKDIR, + WorkingTreeIterator.class); + FileMode fileModeTree = treeWalk.getFileMode(TREE); + + if (treeIterator != null) { + if (dirCacheIterator != null) { + if (!treeIterator.getEntryObjectId().equals( + dirCacheIterator.getEntryObjectId())) { + // in repo, in index, content diff => changed + changed.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } } else { - if (!treeEntry.getId().equals(indexEntry.getObjectId())) { - changed.add(indexEntry.getName()); - anyChanges = true; + // in repo, not in index => removed + if (!fileModeTree.equals(FileMode.TYPE_TREE)) { + removed.add(treeIterator.getEntryPathString()); + changesExist = true; } } - - if (indexEntry != null) { - if (!file.exists()) { - missing.add(indexEntry.getName()); - anyChanges = true; - } else { - if (indexEntry.isModified(root, true)) { - modified.add(indexEntry.getName()); - anyChanges = true; - } + } else { + if (dirCacheIterator != null) { + // not in repo, in index => added + added.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } else { + // not in repo, not in index => untracked + if (workingTreeIterator != null + && !workingTreeIterator.isEntryIgnored()) { + untracked.add(workingTreeIterator.getEntryPathString()); + changesExist = true; } } } - }).walk(); - return anyChanges; + if (dirCacheIterator != null) { + if (workingTreeIterator == null) { + // in index, not in workdir => missing + missing.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } else { + if (!dirCacheIterator.idEqual(workingTreeIterator)) { + // in index, in workdir, content differs => modified + modified.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } + } + } + } + return changesExist; } - HashSet<String> added = new HashSet<String>(); - HashSet<String> changed = new HashSet<String>(); - HashSet<String> removed = new HashSet<String>(); - HashSet<String> missing = new HashSet<String>(); - HashSet<String> modified = new HashSet<String>(); - /** * @return list of files added to the index, not in the tree */ @@ -169,4 +236,11 @@ public class IndexDiff { public HashSet<String> getModified() { return modified; } + + /** + * @return list of files on modified on disk relative to the index + */ + public HashSet<String> getUntracked() { + return untracked; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java index 0c24fc6be2..eae1040f09 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java @@ -385,12 +385,12 @@ public class FileHeader extends DiffEntry { if (buf[sp - 2] != '"') { return eol; } - oldName = QuotedString.GIT_PATH.dequote(buf, bol, sp - 1); - oldName = p1(oldName); + oldPath = QuotedString.GIT_PATH.dequote(buf, bol, sp - 1); + oldPath = p1(oldPath); } else { - oldName = decode(Constants.CHARSET, buf, aStart, sp - 1); + oldPath = decode(Constants.CHARSET, buf, aStart, sp - 1); } - newName = oldName; + newPath = oldPath; return eol; } @@ -431,27 +431,27 @@ public class FileHeader extends DiffEntry { parseNewFileMode(ptr, eol); } else if (match(buf, ptr, COPY_FROM) >= 0) { - oldName = parseName(oldName, ptr + COPY_FROM.length, eol); + oldPath = parseName(oldPath, ptr + COPY_FROM.length, eol); changeType = ChangeType.COPY; } else if (match(buf, ptr, COPY_TO) >= 0) { - newName = parseName(newName, ptr + COPY_TO.length, eol); + newPath = parseName(newPath, ptr + COPY_TO.length, eol); changeType = ChangeType.COPY; } else if (match(buf, ptr, RENAME_OLD) >= 0) { - oldName = parseName(oldName, ptr + RENAME_OLD.length, eol); + oldPath = parseName(oldPath, ptr + RENAME_OLD.length, eol); changeType = ChangeType.RENAME; } else if (match(buf, ptr, RENAME_NEW) >= 0) { - newName = parseName(newName, ptr + RENAME_NEW.length, eol); + newPath = parseName(newPath, ptr + RENAME_NEW.length, eol); changeType = ChangeType.RENAME; } else if (match(buf, ptr, RENAME_FROM) >= 0) { - oldName = parseName(oldName, ptr + RENAME_FROM.length, eol); + oldPath = parseName(oldPath, ptr + RENAME_FROM.length, eol); changeType = ChangeType.RENAME; } else if (match(buf, ptr, RENAME_TO) >= 0) { - newName = parseName(newName, ptr + RENAME_TO.length, eol); + newPath = parseName(newPath, ptr + RENAME_TO.length, eol); changeType = ChangeType.RENAME; } else if (match(buf, ptr, SIMILARITY_INDEX) >= 0) { @@ -474,14 +474,14 @@ public class FileHeader extends DiffEntry { } void parseOldName(int ptr, final int eol) { - oldName = p1(parseName(oldName, ptr + OLD_NAME.length, eol)); - if (oldName == DEV_NULL) + oldPath = p1(parseName(oldPath, ptr + OLD_NAME.length, eol)); + if (oldPath == DEV_NULL) changeType = ChangeType.ADD; } void parseNewName(int ptr, final int eol) { - newName = p1(parseName(newName, ptr + NEW_NAME.length, eol)); - if (newName == DEV_NULL) + newPath = p1(parseName(newPath, ptr + NEW_NAME.length, eol)); + if (newPath == DEV_NULL) changeType = ChangeType.DELETE; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java index 8ec2d2b091..41cfcf8691 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java @@ -245,8 +245,8 @@ class RewriteTreeFilter extends RevFilter { TreeFilter newFilter = oldFilter; for (DiffEntry ent : files) { - if (isRename(ent) && ent.getNewName().equals(oldFilter.getPath())) { - newFilter = FollowFilter.create(ent.getOldName()); + if (isRename(ent) && ent.getNewPath().equals(oldFilter.getPath())) { + newFilter = FollowFilter.create(ent.getOldPath()); break; } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java index 2ffcbed9f1..a8e505d6e5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java @@ -61,6 +61,8 @@ import org.eclipse.jgit.lib.PersonIdent; */ public class ChangeIdUtil { + static final String CHANGE_ID = "Change-Id:"; + // package-private so the unit test can test this part only static String clean(String msg) { return msg.// @@ -136,8 +138,39 @@ public class ChangeIdUtil { * @return a commit message with an inserted Change-Id line */ public static String insertId(String message, ObjectId changeId) { - if (message.indexOf("\nChange-Id:") > 0) + return insertId(message, changeId, false); + } + + /** + * Find the right place to insert a Change-Id and return it. + * <p> + * If no Change-Id is found the Change-Id is inserted before + * the first footer line but after a Bug line. + * + * If Change-Id is found and replaceExisting is set to false, + * the message is unchanged. + * + * If Change-Id is found and replaceExisting is set to true, + * the Change-Id is replaced with {@code changeId}. + * + * @param message + * @param changeId + * @param replaceExisting + * @return a commit message with an inserted Change-Id line + */ + public static String insertId(String message, ObjectId changeId, + boolean replaceExisting) { + if (message.indexOf(CHANGE_ID) > 0) { + if (replaceExisting) { + int i = message.indexOf(CHANGE_ID) + 10; + while (message.charAt(i) == ' ') + i++; + String oldId = message.length() == (i + 40) ? + message.substring(i) : message.substring(i, i + 41); + message = message.replace(oldId, "I" + changeId.getName()); + } return message; + } String[] lines = message.split("\n"); int footerFirstLine = lines.length; @@ -173,7 +206,8 @@ public class ChangeIdUtil { } if (insertAfter == lines.length && insertAfter == footerFirstLine) ret.append("\n"); - ret.append("Change-Id: I"); + ret.append(CHANGE_ID); + ret.append(" I"); ret.append(ObjectId.toString(changeId)); ret.append("\n"); for (; i < lines.length; ++i) { |