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>tags/v0.11.1
@@ -52,6 +52,7 @@ import org.eclipse.jgit.api.errors.JGitInternalException; | |||
import org.eclipse.jgit.api.errors.RefAlreadyExistsException; | |||
import org.eclipse.jgit.api.errors.RefNotFoundException; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.Ref; | |||
import org.eclipse.jgit.lib.RefUpdate; | |||
import org.eclipse.jgit.lib.RepositoryTestCase; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
@@ -97,9 +98,12 @@ public class CheckoutCommandTest extends RepositoryTestCase { | |||
git.checkout().setName("test").call(); | |||
assertEquals("[Test.txt, mode:100644, content:Some change]", | |||
indexState(CONTENT)); | |||
git.checkout().setName("master").call(); | |||
Ref result = git.checkout().setName("master").call(); | |||
assertEquals("[Test.txt, mode:100644, content:Hello world]", | |||
indexState(CONTENT)); | |||
assertEquals("refs/heads/master", result.getName()); | |||
assertEquals("refs/heads/master", git.getRepository() | |||
.getFullBranch()); | |||
} catch (Exception e) { | |||
fail(e.getMessage()); | |||
} | |||
@@ -171,4 +175,17 @@ public class CheckoutCommandTest extends RepositoryTestCase { | |||
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 class CheckoutCommand extends GitCommand<Ref> { | |||
String refLogMessage = "checkout: moving from " | |||
+ headRef.getTarget().getName(); | |||
ObjectId branch = repo.resolve(name); | |||
Ref ref = repo.getRef(name); | |||
if (branch == null) | |||
throw new RefNotFoundException(MessageFormat.format(JGitText | |||
.get().refNotResolved, name)); | |||
@@ -148,11 +148,20 @@ public class CheckoutCommand extends GitCommand<Ref> { | |||
status = new CheckoutResult(Status.CONFLICTS, fileList); | |||
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.setRefLogMessage(refLogMessage + "to " | |||
+ 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); | |||
@@ -174,8 +183,6 @@ public class CheckoutCommand extends GitCommand<Ref> { | |||
throw new JGitInternalException(MessageFormat.format(JGitText | |||
.get().checkoutUnexpectedResult, updateResult.name())); | |||
Ref result = repo.getRef(name); | |||
if (!repo.isBare() && !dco.getToBeDeleted().isEmpty()) { | |||
List<File> fileList = new ArrayList<File>(); | |||
for (String filePath : dco.getToBeDeleted()) { | |||
@@ -185,7 +192,7 @@ public class CheckoutCommand extends GitCommand<Ref> { | |||
} | |||
else | |||
status = CheckoutResult.OK_RESULT; | |||
return result; | |||
return ref; | |||
} catch (IOException ioe) { | |||
throw new JGitInternalException(ioe.getMessage(), ioe); | |||
} finally { |