diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java index 743733586..21fbe0a13 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2010, Chris Aniszczyk + * Copyright (C) 2011, Matthias Sohn * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -61,8 +62,13 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.transport.RefSpec; +import org.eclipse.jgit.transport.RemoteConfig; +import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.util.FileUtils; import org.junit.Before; import org.junit.Test; @@ -205,4 +211,32 @@ public void testCheckoutCommit() { fail(e.getMessage()); } } + + @Test + public void testCheckoutRemoteTrackingWithoutLocalBranch() { + try { + // create second repository + Repository db2 = createWorkRepository(); + Git git2 = new Git(db2); + + // setup the second repository to fetch from the first repository + final StoredConfig config = db2.getConfig(); + RemoteConfig remoteConfig = new RemoteConfig(config, "origin"); + URIish uri = new URIish(db.getDirectory().toURI().toURL()); + remoteConfig.addURI(uri); + remoteConfig.update(config); + config.save(); + + // fetch from first repository + RefSpec spec = new RefSpec("+refs/heads/*:refs/remotes/origin/*"); + git2.fetch().setRemote("origin").setRefSpecs(spec).call(); + // checkout remote tracking branch in second repository + // (no local branches exist yet in second repository) + git2.checkout().setName("remotes/origin/test").call(); + assertEquals("[Test.txt, mode:100644, content:Some change]", + indexState(db2, CONTENT)); + } catch (Exception e) { + fail(e.getMessage()); + } + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java index 3a50bca5f..ee4165dfb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java @@ -167,20 +167,24 @@ public void setUp() throws Exception { * 'stage' is only presented when the stage is different from 0. All * reported time stamps are mapped to strings like "t0", "t1", ... "tn". The * smallest reported time-stamp will be called "t0". This allows to write - * assertions against the string although the concrete value of the - * time stamps is unknown. + * assertions against the string although the concrete value of the time + * stamps is unknown. + * + * @param repo + * the repository the index state should be determined for * * @param includedOptions * a bitmask constructed out of the constants {@link #MOD_TIME}, - * {@link #SMUDGE}, {@link #LENGTH}, {@link #CONTENT_ID} and {@link #CONTENT} - * controlling which info is present in the resulting string. + * {@link #SMUDGE}, {@link #LENGTH}, {@link #CONTENT_ID} and + * {@link #CONTENT} controlling which info is present in the + * resulting string. * @return a string encoding the index state * @throws IllegalStateException * @throws IOException */ - public String indexState(int includedOptions) + public String indexState(Repository repo, int includedOptions) throws IllegalStateException, IOException { - DirCache dc = db.readDirCache(); + DirCache dc = repo.readDirCache(); StringBuilder sb = new StringBuilder(); TreeSet timeStamps = null; @@ -223,6 +227,46 @@ public String indexState(int includedOptions) return sb.toString(); } + /** + * Represent the state of the index in one String. This representation is + * useful when writing tests which do assertions on the state of the index. + * By default information about path, mode, stage (if different from 0) is + * included. A bitmask controls which additional info about + * modificationTimes, smudge state and length is included. + *

+ * The format of the returned string is described with this BNF: + * + *

+	 * result = ( "[" path mode stage? time? smudge? length? sha1? content? "]" )* .
+	 * mode = ", mode:" number .
+	 * stage = ", stage:" number .
+	 * time = ", time:t" timestamp-index .
+	 * smudge = "" | ", smudged" .
+	 * length = ", length:" number .
+	 * sha1 = ", sha1:" hex-sha1 .
+	 * content = ", content:" blob-data .
+	 * 
+ * + * 'stage' is only presented when the stage is different from 0. All + * reported time stamps are mapped to strings like "t0", "t1", ... "tn". The + * smallest reported time-stamp will be called "t0". This allows to write + * assertions against the string although the concrete value of the time + * stamps is unknown. + * + * @param includedOptions + * a bitmask constructed out of the constants {@link #MOD_TIME}, + * {@link #SMUDGE}, {@link #LENGTH}, {@link #CONTENT_ID} and + * {@link #CONTENT} controlling which info is present in the + * resulting string. + * @return a string encoding the index state + * @throws IllegalStateException + * @throws IOException + */ + public String indexState(int includedOptions) + throws IllegalStateException, IOException { + return indexState(db, includedOptions); + } + /** * Resets the index to represent exactly some filesystem content. E.g. the * following call will replace the index with the working tree content: diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java index 73ca26167..16c1fcfa3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2010, Chris Aniszczyk + * Copyright (C) 2011, Matthias Sohn * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -54,13 +55,15 @@ import org.eclipse.jgit.dircache.DirCacheCheckout; import org.eclipse.jgit.errors.AmbiguousObjectException; import org.eclipse.jgit.errors.CheckoutConflictException; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefUpdate; -import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; /** @@ -119,21 +122,22 @@ public Ref call() throws JGitInternalException, RefAlreadyExistsException, command.call(); } - RevWalk revWalk = new RevWalk(repo); Ref headRef = repo.getRef(Constants.HEAD); - RevCommit headCommit = revWalk.parseCommit(headRef.getObjectId()); String refLogMessage = "checkout: moving from " + headRef.getTarget().getName(); ObjectId branch = repo.resolve(name); - if (branch == null) throw new RefNotFoundException(MessageFormat.format(JGitText .get().refNotResolved, name)); + RevWalk revWalk = new RevWalk(repo); + AnyObjectId headId = headRef.getObjectId(); + RevCommit headCommit = headId == null ? null : revWalk + .parseCommit(headId); RevCommit newCommit = revWalk.parseCommit(branch); - - DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit - .getTree(), repo.lockDirCache(), newCommit.getTree()); + RevTree headTree = headCommit == null ? null : headCommit.getTree(); + DirCacheCheckout dco = new DirCacheCheckout(repo, headTree, + repo.lockDirCache(), newCommit.getTree()); dco.setFailOnConflict(true); try { dco.checkout();