Update reflog like C Git during rebase (non-interactive)
Bug: 346350 Change-Id: I119766a00bc52a810c51cffaa19207cb8555ca22 Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
This commit is contained in:
parent
bd57789735
commit
99d981ce35
|
@ -415,6 +415,7 @@ protected void checkoutBranch(String branchName)
|
|||
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.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 @@ private void checkoutCommit(RevCommit commit) throws IllegalStateException,
|
|||
// 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 void testFastForwardWithNewFile() throws Exception {
|
|||
// 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 void testFastForwardWithNewFile() throws Exception {
|
|||
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 void testFastForwardWithMultipleCommits() throws Exception {
|
|||
// 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 void testFastForwardWithMultipleCommits() throws Exception {
|
|||
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 void testRebaseShouldIgnoreMergeCommits()
|
|||
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 void testRebaseParentOntoHeadShouldBeUptoDate() throws Exception {
|
|||
|
||||
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 void testUpToDate() throws Exception {
|
|||
|
||||
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 void testConflictFreeWithSingleFile() throws Exception {
|
|||
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 void testDetachedHead() throws Exception {
|
|||
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 @@
|
|||
* >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 CherryPickResult call() throws GitAPIException, NoMessageException,
|
|||
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 CherryPickCommand setOurCommitName(String ourCommitName) {
|
|||
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 RebaseResult call() throws GitAPIException, NoHeadException,
|
|||
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 RebaseResult call() throws GitAPIException, NoHeadException,
|
|||
}
|
||||
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 RebaseResult call() throws GitAPIException, NoHeadException,
|
|||
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 @@ private void updateHead(String headName, RevCommit newHead)
|
|||
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 @@ private RebaseResult initFilesAndRewind() throws IOException,
|
|||
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 @@ else if (!isInteractive() && walk.isMergedInto(headCommit, upstream)) {
|
|||
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 @@ else if (!isInteractive() && walk.isMergedInto(headCommit, upstream)) {
|
|||
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 RevCommit tryFastForward(RevCommit newCommit) throws IOException,
|
|||
if (head.isSymbolic())
|
||||
headName = head.getTarget().getName();
|
||||
else
|
||||
headName = "detached HEAD";
|
||||
headName = head.getObjectId().getName();
|
||||
return tryFastForward(headName, headCommit, newCommit);
|
||||
}
|
||||
|
||||
|
@ -843,6 +848,7 @@ private RebaseResult abort(RebaseResult result) throws IOException {
|
|||
|
||||
// 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 @@ private RebaseResult abort(RebaseResult result) throws IOException {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ private boolean checkoutCommit(RevCommit commit) throws IOException,
|
|||
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:
|
||||
|
|
Loading…
Reference in New Issue