Bug: 346350 Change-Id: I119766a00bc52a810c51cffaa19207cb8555ca22 Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>tags/v3.0.2.201309041250-rc2
@@ -415,6 +415,7 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase { | |||
walk.release(); | |||
// update the HEAD | |||
RefUpdate refUpdate = db.updateRef(Constants.HEAD); | |||
refUpdate.setRefLogMessage("checkout: moving to " + branchName, false); | |||
refUpdate.link(branchName); | |||
} | |||
@@ -74,6 +74,7 @@ import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.PersonIdent; | |||
import org.eclipse.jgit.lib.RefUpdate; | |||
import org.eclipse.jgit.lib.ReflogEntry; | |||
import org.eclipse.jgit.lib.RepositoryState; | |||
import org.eclipse.jgit.merge.MergeStrategy; | |||
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason; | |||
@@ -107,6 +108,8 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
// update the HEAD | |||
RefUpdate refUpdate = db.updateRef(Constants.HEAD, true); | |||
refUpdate.setNewObjectId(commit); | |||
refUpdate.setRefLogMessage("checkout: moving to " + head.getName(), | |||
false); | |||
refUpdate.forceUpdate(); | |||
} | |||
@@ -123,7 +126,7 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
// create file2 on master | |||
File file2 = writeTrashFile("file2", "file2"); | |||
git.add().addFilepattern("file2").call(); | |||
git.commit().setMessage("Add file2").call(); | |||
RevCommit second = git.commit().setMessage("Add file2").call(); | |||
assertTrue(new File(db.getWorkTree(), "file2").exists()); | |||
checkoutBranch("refs/heads/topic"); | |||
@@ -133,6 +136,22 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
assertTrue(new File(db.getWorkTree(), "file2").exists()); | |||
checkFile(file2, "file2"); | |||
assertEquals(Status.FAST_FORWARD, res.getStatus()); | |||
List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) | |||
.getReverseEntries(); | |||
List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") | |||
.getReverseEntries(); | |||
List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") | |||
.getReverseEntries(); | |||
assertEquals("rebase finished: returning to refs/heads/topic", headLog | |||
.get(0).getComment()); | |||
assertEquals("checkout: moving from topic to " + second.getName(), | |||
headLog.get(1).getComment()); | |||
assertEquals(2, masterLog.size()); | |||
assertEquals(2, topicLog.size()); | |||
assertEquals( | |||
"rebase finished: refs/heads/topic onto " + second.getName(), | |||
topicLog.get(0).getComment()); | |||
} | |||
@Test | |||
@@ -153,7 +172,8 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
// write a second commit | |||
writeTrashFile("file2", "file2 new content"); | |||
git.add().addFilepattern("file2").call(); | |||
git.commit().setMessage("Change content of file2").call(); | |||
RevCommit second = git.commit().setMessage("Change content of file2") | |||
.call(); | |||
checkoutBranch("refs/heads/topic"); | |||
assertFalse(new File(db.getWorkTree(), "file2").exists()); | |||
@@ -162,6 +182,22 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
assertTrue(new File(db.getWorkTree(), "file2").exists()); | |||
checkFile(file2, "file2 new content"); | |||
assertEquals(Status.FAST_FORWARD, res.getStatus()); | |||
List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) | |||
.getReverseEntries(); | |||
List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") | |||
.getReverseEntries(); | |||
List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") | |||
.getReverseEntries(); | |||
assertEquals("rebase finished: returning to refs/heads/topic", headLog | |||
.get(0).getComment()); | |||
assertEquals("checkout: moving from topic to " + second.getName(), | |||
headLog.get(1).getComment()); | |||
assertEquals(3, masterLog.size()); | |||
assertEquals(2, topicLog.size()); | |||
assertEquals( | |||
"rebase finished: refs/heads/topic onto " + second.getName(), | |||
topicLog.get(0).getComment()); | |||
} | |||
/** | |||
@@ -242,6 +278,29 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
assertDerivedFrom(rw.next(), c); | |||
assertEquals(b, rw.next()); | |||
assertEquals(a, rw.next()); | |||
List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) | |||
.getReverseEntries(); | |||
List<ReflogEntry> sideLog = db.getReflogReader("refs/heads/side") | |||
.getReverseEntries(); | |||
List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") | |||
.getReverseEntries(); | |||
List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") | |||
.getReverseEntries(); | |||
assertEquals("rebase finished: returning to refs/heads/topic", headLog | |||
.get(0).getComment()); | |||
assertEquals("rebase: update file2 on side", headLog.get(1) | |||
.getComment()); | |||
assertEquals("rebase: Add file2", headLog.get(2).getComment()); | |||
assertEquals("rebase: update file3 on topic", headLog.get(3) | |||
.getComment()); | |||
assertEquals("checkout: moving from topic to " + b.getName(), headLog | |||
.get(4).getComment()); | |||
assertEquals(2, masterLog.size()); | |||
assertEquals(2, sideLog.size()); | |||
assertEquals(5, topicLog.size()); | |||
assertEquals("rebase finished: refs/heads/topic onto " + b.getName(), | |||
topicLog.get(0).getComment()); | |||
} | |||
static void assertDerivedFrom(RevCommit derived, RevCommit original) { | |||
@@ -261,6 +320,11 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
RebaseResult result = git.rebase().setUpstream(parent).call(); | |||
assertEquals(Status.UP_TO_DATE, result.getStatus()); | |||
assertEquals(2, db.getReflogReader(Constants.HEAD).getReverseEntries() | |||
.size()); | |||
assertEquals(2, db.getReflogReader("refs/heads/master") | |||
.getReverseEntries().size()); | |||
} | |||
@Test | |||
@@ -274,6 +338,11 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
RebaseResult res = git.rebase().setUpstream(first).call(); | |||
assertEquals(Status.UP_TO_DATE, res.getStatus()); | |||
assertEquals(1, db.getReflogReader(Constants.HEAD).getReverseEntries() | |||
.size()); | |||
assertEquals(1, db.getReflogReader("refs/heads/master") | |||
.getReverseEntries().size()); | |||
} | |||
@Test | |||
@@ -328,6 +397,18 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
assertEquals(lastMasterChange, new RevWalk(db).parseCommit( | |||
db.resolve(Constants.HEAD)).getParent(0)); | |||
assertEquals(origHead, db.readOrigHead()); | |||
List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) | |||
.getReverseEntries(); | |||
List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") | |||
.getReverseEntries(); | |||
List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") | |||
.getReverseEntries(); | |||
assertEquals(2, masterLog.size()); | |||
assertEquals(3, topicLog.size()); | |||
assertEquals("rebase finished: refs/heads/topic onto " | |||
+ lastMasterChange.getName(), topicLog.get(0).getComment()); | |||
assertEquals("rebase finished: returning to refs/heads/topic", headLog | |||
.get(0).getComment()); | |||
} | |||
@Test | |||
@@ -366,6 +447,13 @@ public class RebaseCommandTest extends RepositoryTestCase { | |||
assertEquals(lastMasterChange, new RevWalk(db).parseCommit( | |||
db.resolve(Constants.HEAD)).getParent(0)); | |||
List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) | |||
.getReverseEntries(); | |||
assertEquals(8, headLog.size()); | |||
assertEquals("rebase: change file1 in topic", headLog.get(0) | |||
.getComment()); | |||
assertEquals("checkout: moving from " + topicCommit.getName() + " to " | |||
+ lastMasterChange.getName(), headLog.get(1).getComment()); | |||
} | |||
@Test |
@@ -82,6 +82,8 @@ import org.eclipse.jgit.treewalk.FileTreeIterator; | |||
* >Git documentation about cherry-pick</a> | |||
*/ | |||
public class CherryPickCommand extends GitCommand<CherryPickResult> { | |||
private String reflogPrefix = "cherry-pick:"; //$NON-NLS-1$ | |||
private List<Ref> commits = new LinkedList<Ref>(); | |||
private String ourCommitName = null; | |||
@@ -166,9 +168,8 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> { | |||
dco.checkout(); | |||
newHead = new Git(getRepository()).commit() | |||
.setMessage(srcCommit.getFullMessage()) | |||
.setReflogComment( | |||
"cherry-pick: " //$NON-NLS-1$ | |||
+ srcCommit.getShortMessage()) | |||
.setReflogComment(reflogPrefix + " " //$NON-NLS-1$ | |||
+ srcCommit.getShortMessage()) | |||
.setAuthor(srcCommit.getAuthorIdent()).call(); | |||
cherryPickedRefs.add(src); | |||
} else { | |||
@@ -242,6 +243,21 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> { | |||
return this; | |||
} | |||
/** | |||
* Set the prefix to use in the reflog. | |||
* <p> | |||
* This is primarily needed for implementing rebase in terms of | |||
* cherry-picking | |||
* | |||
* @param prefix | |||
* including ":" | |||
* @return {@code this} | |||
*/ | |||
public CherryPickCommand setReflogPrefix(final String prefix) { | |||
this.reflogPrefix = prefix; | |||
return this; | |||
} | |||
private String calculateOurName(Ref headRef) { | |||
if (ourCommitName != null) | |||
return ourCommitName; |
@@ -319,7 +319,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
String ourCommitName = getOurCommitName(); | |||
CherryPickResult cherryPickResult = new Git(repo) | |||
.cherryPick().include(commitToPick) | |||
.setOurCommitName(ourCommitName).call(); | |||
.setOurCommitName(ourCommitName) | |||
.setReflogPrefix("rebase:").call(); //$NON-NLS-1$ | |||
switch (cherryPickResult.getStatus()) { | |||
case FAILED: | |||
if (operation == Operation.BEGIN) | |||
@@ -353,7 +354,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
} | |||
if (newHead != null) { | |||
String headName = rebaseState.readFile(HEAD_NAME); | |||
updateHead(headName, newHead); | |||
updateHead(headName, newHead, upstreamCommit); | |||
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE); | |||
if (lastStepWasForward) | |||
return RebaseResult.FAST_FORWARD_RESULT; | |||
@@ -370,18 +371,20 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
private String getOurCommitName() { | |||
// If onto is different from upstream, this should say "onto", but | |||
// RebaseCommand doesn't support a different "onto" at the moment. | |||
String ourCommitName = "Upstream, based on " | |||
String ourCommitName = "Upstream, based on " //$NON-NLS-1$ | |||
+ Repository.shortenRefName(upstreamCommitName); | |||
return ourCommitName; | |||
} | |||
private void updateHead(String headName, RevCommit newHead) | |||
private void updateHead(String headName, RevCommit newHead, RevCommit onto) | |||
throws IOException { | |||
// point the previous head (if any) to the new commit | |||
if (headName.startsWith(Constants.R_REFS)) { | |||
RefUpdate rup = repo.updateRef(headName); | |||
rup.setNewObjectId(newHead); | |||
rup.setRefLogMessage("rebase finished: " + headName + " onto " //$NON-NLS-1$ | |||
+ onto.getName(), false); | |||
Result res = rup.forceUpdate(); | |||
switch (res) { | |||
case FAST_FORWARD: | |||
@@ -392,6 +395,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
throw new JGitInternalException("Updating HEAD failed"); | |||
} | |||
rup = repo.updateRef(Constants.HEAD); | |||
rup.setRefLogMessage("rebase finished: returning to " + headName, //$NON-NLS-1$ | |||
false); | |||
res = rup.link(headName); | |||
switch (res) { | |||
case FAST_FORWARD: | |||
@@ -614,7 +619,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
if (head.isSymbolic()) | |||
headName = head.getTarget().getName(); | |||
else | |||
headName = "detached HEAD"; | |||
headName = head.getObjectId().getName(); | |||
ObjectId headId = head.getObjectId(); | |||
if (headId == null) | |||
throw new RefNotFoundException(MessageFormat.format( | |||
@@ -629,10 +634,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
monitor.beginTask(MessageFormat.format( | |||
JGitText.get().resettingHead, | |||
upstreamCommit.getShortMessage()), ProgressMonitor.UNKNOWN); | |||
checkoutCommit(upstreamCommit); | |||
checkoutCommit(headName, upstreamCommit); | |||
monitor.endTask(); | |||
updateHead(headName, upstreamCommit); | |||
updateHead(headName, upstreamCommit, upstream); | |||
return RebaseResult.FAST_FORWARD_RESULT; | |||
} | |||
@@ -691,7 +696,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
upstreamCommit.getShortMessage()), ProgressMonitor.UNKNOWN); | |||
boolean checkoutOk = false; | |||
try { | |||
checkoutOk = checkoutCommit(upstreamCommit); | |||
checkoutOk = checkoutCommit(headName, upstreamCommit); | |||
} finally { | |||
if (!checkoutOk) | |||
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE); | |||
@@ -732,7 +737,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
if (head.isSymbolic()) | |||
headName = head.getTarget().getName(); | |||
else | |||
headName = "detached HEAD"; | |||
headName = head.getObjectId().getName(); | |||
return tryFastForward(headName, headCommit, newCommit); | |||
} | |||
@@ -843,6 +848,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
// update the HEAD | |||
RefUpdate refUpdate = repo.updateRef(Constants.HEAD, false); | |||
refUpdate.setRefLogMessage("rebase: aborting", false); //$NON-NLS-1$ | |||
Result res = refUpdate.link(headName); | |||
switch (res) { | |||
case FAST_FORWARD: | |||
@@ -864,7 +870,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
} | |||
} | |||
private boolean checkoutCommit(RevCommit commit) throws IOException, | |||
private boolean checkoutCommit(String headName, RevCommit commit) | |||
throws IOException, | |||
CheckoutConflictException { | |||
try { | |||
RevCommit head = walk.parseCommit(repo.resolve(Constants.HEAD)); | |||
@@ -880,6 +887,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> { | |||
RefUpdate refUpdate = repo.updateRef(Constants.HEAD, true); | |||
refUpdate.setExpectedOldObjectId(head); | |||
refUpdate.setNewObjectId(commit); | |||
refUpdate.setRefLogMessage( | |||
"checkout: moving from " //$NON-NLS-1$ | |||
+ Repository.shortenRefName(headName) | |||
+ " to " + commit.getName(), false); //$NON-NLS-1$ | |||
Result res = refUpdate.forceUpdate(); | |||
switch (res) { | |||
case FAST_FORWARD: |