Checkout: fix handling if name does not refer to a local branch
The CheckoutCommand does not handle names other than local branch names properly; it must detach HEAD if such a name is encountered (for example a commit ID or a remote tracking branch). Change-Id: I5d55177f4029bcc34fc2649fd564b125a2929cc4 Signed-off-by: Mathias Kinzler <mathias.kinzler@sap.com> Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
This commit is contained in:
parent
0c22243c4a
commit
89a4dcf71f
|
@ -52,6 +52,7 @@
|
||||||
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
|
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
|
||||||
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.RefUpdate;
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
import org.eclipse.jgit.lib.RepositoryTestCase;
|
import org.eclipse.jgit.lib.RepositoryTestCase;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
@ -97,9 +98,12 @@ public void testCheckout() {
|
||||||
git.checkout().setName("test").call();
|
git.checkout().setName("test").call();
|
||||||
assertEquals("[Test.txt, mode:100644, content:Some change]",
|
assertEquals("[Test.txt, mode:100644, content:Some change]",
|
||||||
indexState(CONTENT));
|
indexState(CONTENT));
|
||||||
git.checkout().setName("master").call();
|
Ref result = git.checkout().setName("master").call();
|
||||||
assertEquals("[Test.txt, mode:100644, content:Hello world]",
|
assertEquals("[Test.txt, mode:100644, content:Hello world]",
|
||||||
indexState(CONTENT));
|
indexState(CONTENT));
|
||||||
|
assertEquals("refs/heads/master", result.getName());
|
||||||
|
assertEquals("refs/heads/master", git.getRepository()
|
||||||
|
.getFullBranch());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -171,4 +175,17 @@ public void testCheckoutWithNonDeletedFiles() throws Exception {
|
||||||
fis.close();
|
fis.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCheckoutCommit() {
|
||||||
|
try {
|
||||||
|
Ref result = git.checkout().setName(initialCommit.name()).call();
|
||||||
|
assertEquals("[Test.txt, mode:100644, content:Hello world]",
|
||||||
|
indexState(CONTENT));
|
||||||
|
assertNull(result);
|
||||||
|
assertEquals(initialCommit.name(), git.getRepository()
|
||||||
|
.getFullBranch());
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ public Ref call() throws JGitInternalException, RefAlreadyExistsException,
|
||||||
String refLogMessage = "checkout: moving from "
|
String refLogMessage = "checkout: moving from "
|
||||||
+ headRef.getTarget().getName();
|
+ headRef.getTarget().getName();
|
||||||
ObjectId branch = repo.resolve(name);
|
ObjectId branch = repo.resolve(name);
|
||||||
Ref ref = repo.getRef(name);
|
|
||||||
if (branch == null)
|
if (branch == null)
|
||||||
throw new RefNotFoundException(MessageFormat.format(JGitText
|
throw new RefNotFoundException(MessageFormat.format(JGitText
|
||||||
.get().refNotResolved, name));
|
.get().refNotResolved, name));
|
||||||
|
@ -148,11 +148,20 @@ public Ref call() throws JGitInternalException, RefAlreadyExistsException,
|
||||||
status = new CheckoutResult(Status.CONFLICTS, fileList);
|
status = new CheckoutResult(Status.CONFLICTS, fileList);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
RefUpdate refUpdate = repo.updateRef(Constants.HEAD);
|
Ref ref = repo.getRef(name);
|
||||||
|
if (ref != null && !ref.getName().startsWith(Constants.R_HEADS))
|
||||||
|
ref = null;
|
||||||
|
RefUpdate refUpdate = repo.updateRef(Constants.HEAD, ref == null);
|
||||||
refUpdate.setForceUpdate(force);
|
refUpdate.setForceUpdate(force);
|
||||||
refUpdate.setRefLogMessage(refLogMessage + "to "
|
refUpdate.setRefLogMessage(refLogMessage + "to "
|
||||||
+ newCommit.getName(), false);
|
+ newCommit.getName(), false);
|
||||||
Result updateResult = refUpdate.link(ref.getName());
|
Result updateResult;
|
||||||
|
if (ref != null)
|
||||||
|
updateResult = refUpdate.link(ref.getName());
|
||||||
|
else {
|
||||||
|
refUpdate.setNewObjectId(newCommit);
|
||||||
|
updateResult = refUpdate.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
setCallable(false);
|
setCallable(false);
|
||||||
|
|
||||||
|
@ -174,8 +183,6 @@ public Ref call() throws JGitInternalException, RefAlreadyExistsException,
|
||||||
throw new JGitInternalException(MessageFormat.format(JGitText
|
throw new JGitInternalException(MessageFormat.format(JGitText
|
||||||
.get().checkoutUnexpectedResult, updateResult.name()));
|
.get().checkoutUnexpectedResult, updateResult.name()));
|
||||||
|
|
||||||
Ref result = repo.getRef(name);
|
|
||||||
|
|
||||||
if (!repo.isBare() && !dco.getToBeDeleted().isEmpty()) {
|
if (!repo.isBare() && !dco.getToBeDeleted().isEmpty()) {
|
||||||
List<File> fileList = new ArrayList<File>();
|
List<File> fileList = new ArrayList<File>();
|
||||||
for (String filePath : dco.getToBeDeleted()) {
|
for (String filePath : dco.getToBeDeleted()) {
|
||||||
|
@ -185,7 +192,7 @@ public Ref call() throws JGitInternalException, RefAlreadyExistsException,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
status = CheckoutResult.OK_RESULT;
|
status = CheckoutResult.OK_RESULT;
|
||||||
return result;
|
return ref;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new JGitInternalException(ioe.getMessage(), ioe);
|
throw new JGitInternalException(ioe.getMessage(), ioe);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
Loading…
Reference in New Issue