diff options
author | Robin Stocker <robin@nibor.org> | 2013-08-12 15:13:03 +0200 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2013-09-13 15:13:12 +0200 |
commit | 02bd26e5a636fe2d9f128860530eda27ac35b334 (patch) | |
tree | 69dd6957af6cd91ef50e6aa38ec41501c5e8308a /org.eclipse.jgit | |
parent | 4b8a848a477cc77caf8e74de6d28b3bcbcaed413 (diff) | |
download | jgit-02bd26e5a636fe2d9f128860530eda27ac35b334.tar.gz jgit-02bd26e5a636fe2d9f128860530eda27ac35b334.zip |
ResetCommand: Allow reset on unborn branch when ref not specified
In C Git 1.8.2, "git reset" now also works on an unborn branch (no HEAD
yet) if no explicit ref was specified. In that case, it is treated as a
reset to an empty tree.
This can be useful for callers because "unborn branch" no longer has to
be special-cased to "git rm --cached".
Bug: 414870
Change-Id: Ied750116f767518ae4d48823cf00752b049a8477
Signed-off-by: Robin Stocker <robin@nibor.org>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java | 141 | ||||
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java | 2 |
2 files changed, 86 insertions, 57 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java index 6827026bac..3a1c209a2d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012, Chris Aniszczyk <caniszczyk@gmail.com> + * Copyright (C) 2011-2013, Chris Aniszczyk <caniszczyk@gmail.com> * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -67,6 +67,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.CanonicalTreeParser; +import org.eclipse.jgit.treewalk.EmptyTreeIterator; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilterGroup; @@ -114,7 +115,9 @@ public class ResetCommand extends GitCommand<Ref> { KEEP // TODO not implemented yet } - private String ref = Constants.HEAD; + // We need to be able to distinguish whether the caller set the ref + // explicitly or not, so we apply the default (HEAD) only later. + private String ref = null; private ResetType mode; @@ -139,9 +142,6 @@ public class ResetCommand extends GitCommand<Ref> { public Ref call() throws GitAPIException, CheckoutConflictException { checkCallable(); - Ref r; - RevCommit commit; - try { RepositoryState state = repo.getRepositoryState(); final boolean merging = state.equals(RepositoryState.MERGING) @@ -152,61 +152,55 @@ public class ResetCommand extends GitCommand<Ref> { final boolean reverting = state.equals(RepositoryState.REVERTING) || state.equals(RepositoryState.REVERTING_RESOLVED); - // resolve the ref to a commit - final ObjectId commitId; - try { - commitId = repo.resolve(ref + "^{commit}"); //$NON-NLS-1$ - if (commitId == null) { - // @TODO throw an InvalidRefNameException. We can't do that - // now because this would break the API - throw new JGitInternalException("Invalid ref " + ref - + " specified"); - } - } catch (IOException e) { - throw new JGitInternalException( - MessageFormat.format(JGitText.get().cannotRead, ref), - e); - } - RevWalk rw = new RevWalk(repo); - try { - commit = rw.parseCommit(commitId); - } catch (IOException e) { - throw new JGitInternalException( - MessageFormat.format( - JGitText.get().cannotReadCommit, commitId.toString()), - e); - } finally { - rw.release(); + final ObjectId commitId = resolveRefToCommitId(); + // When ref is explicitly specified, it has to resolve + if (ref != null && commitId == null) { + // @TODO throw an InvalidRefNameException. We can't do that + // now because this would break the API + throw new JGitInternalException("Invalid ref " + ref + + " specified"); } + final ObjectId commitTree; + if (commitId != null) + commitTree = parseCommit(commitId).getTree(); + else + commitTree = null; + if (!filepaths.isEmpty()) { // reset [commit] -- paths - resetIndexForPaths(commit); + resetIndexForPaths(commitTree); setCallable(false); return repo.getRef(Constants.HEAD); } - // write the ref - final RefUpdate ru = repo.updateRef(Constants.HEAD); - ru.setNewObjectId(commitId); - - String refName = Repository.shortenRefName(ref); - String message = refName + ": updating " + Constants.HEAD; //$NON-NLS-1$ - ru.setRefLogMessage(message, false); - if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE) - throw new JGitInternalException(MessageFormat.format( - JGitText.get().cannotLock, ru.getName())); - - ObjectId origHead = ru.getOldObjectId(); - if (origHead != null) - repo.writeOrigHead(origHead); + final Ref result; + if (commitId != null) { + // write the ref + final RefUpdate ru = repo.updateRef(Constants.HEAD); + ru.setNewObjectId(commitId); + + String refName = Repository.shortenRefName(getRefOrHEAD()); + String message = refName + ": updating " + Constants.HEAD; //$NON-NLS-1$ + ru.setRefLogMessage(message, false); + if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE) + throw new JGitInternalException(MessageFormat.format( + JGitText.get().cannotLock, ru.getName())); + + ObjectId origHead = ru.getOldObjectId(); + if (origHead != null) + repo.writeOrigHead(origHead); + result = ru.getRef(); + } else { + result = repo.getRef(Constants.HEAD); + } switch (mode) { case HARD: - checkoutIndex(commit); + checkoutIndex(commitTree); break; case MIXED: - resetIndex(commit); + resetIndex(commitTree); break; case SOFT: // do nothing, only the ref was changed break; @@ -228,19 +222,41 @@ public class ResetCommand extends GitCommand<Ref> { } setCallable(false); - r = ru.getRef(); + return result; } catch (IOException e) { throw new JGitInternalException( JGitText.get().exceptionCaughtDuringExecutionOfResetCommand, e); } + } + + private RevCommit parseCommit(final ObjectId commitId) { + RevCommit commit; + RevWalk rw = new RevWalk(repo); + try { + commit = rw.parseCommit(commitId); + } catch (IOException e) { + throw new JGitInternalException(MessageFormat.format( + JGitText.get().cannotReadCommit, commitId.toString()), e); + } finally { + rw.release(); + } + return commit; + } - return r; + private ObjectId resolveRefToCommitId() { + try { + return repo.resolve(getRefOrHEAD() + "^{commit}"); //$NON-NLS-1$ + } catch (IOException e) { + throw new JGitInternalException( + MessageFormat.format(JGitText.get().cannotRead, getRefOrHEAD()), + e); + } } /** * @param ref - * the ref to reset to + * the ref to reset to, defaults to HEAD if not specified * @return this instance */ public ResetCommand setRef(String ref) { @@ -276,7 +292,14 @@ public class ResetCommand extends GitCommand<Ref> { return this; } - private void resetIndexForPaths(RevCommit commit) { + private String getRefOrHEAD() { + if (ref != null) + return ref; + else + return Constants.HEAD; + } + + private void resetIndexForPaths(ObjectId commitTree) { DirCache dc = null; try { dc = repo.lockDirCache(); @@ -284,7 +307,10 @@ public class ResetCommand extends GitCommand<Ref> { final TreeWalk tw = new TreeWalk(repo); tw.addTree(new DirCacheBuildIterator(builder)); - tw.addTree(commit.getTree()); + if (commitTree != null) + tw.addTree(commitTree); + else + tw.addTree(new EmptyTreeIterator()); tw.setFilter(PathFilterGroup.createFromStrings(filepaths)); tw.setRecursive(true); @@ -310,14 +336,17 @@ public class ResetCommand extends GitCommand<Ref> { } } - private void resetIndex(RevCommit commit) throws IOException { + private void resetIndex(ObjectId commitTree) throws IOException { DirCache dc = repo.lockDirCache(); TreeWalk walk = null; try { DirCacheBuilder builder = dc.builder(); walk = new TreeWalk(repo); - walk.addTree(commit.getTree()); + if (commitTree != null) + walk.addTree(commitTree); + else + walk.addTree(new EmptyTreeIterator()); walk.addTree(new DirCacheIterator(dc)); walk.setRecursive(true); @@ -352,12 +381,12 @@ public class ResetCommand extends GitCommand<Ref> { } } - private void checkoutIndex(RevCommit commit) throws IOException, + private void checkoutIndex(ObjectId commitTree) throws IOException, GitAPIException { DirCache dc = repo.lockDirCache(); try { DirCacheCheckout checkout = new DirCacheCheckout(repo, dc, - commit.getTree()); + commitTree); checkout.setFailOnConflict(false); try { checkout.checkout(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java index 5458426b1a..dd9ee10bf3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -280,7 +280,7 @@ public class DirCacheCheckout { builder = dc.builder(); walk = new NameConflictTreeWalk(repo); - walk.addTree(mergeCommitTree); + addTree(walk, mergeCommitTree); walk.addTree(new DirCacheBuildIterator(builder)); walk.addTree(workingTree); |