diff options
author | Kevin Sawicki <kevin@github.com> | 2011-05-03 08:07:15 -0700 |
---|---|---|
committer | Kevin Sawicki <kevin@github.com> | 2011-05-03 08:07:15 -0700 |
commit | ec92f8f59e1365048866d875458ff999f9c41bae (patch) | |
tree | a8adef8bc07afe82768f0cea900c26cc50b43ee1 /org.eclipse.jgit | |
parent | d05d351f3be5207a168c43b7cc52404195c2d567 (diff) | |
download | jgit-ec92f8f59e1365048866d875458ff999f9c41bae.tar.gz jgit-ec92f8f59e1365048866d875458ff999f9c41bae.zip |
Add path support to checkout command.
Change-Id: I89e8edfc6dd87d5bf8fd08704df2432720084330
Signed-off-by: Kevin Sawicki <kevin@github.com>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java | 87 |
1 files changed, 84 insertions, 3 deletions
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 16c1fcfa33..f3a2e53602 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -43,8 +43,11 @@ */ package org.eclipse.jgit.api; +import java.io.File; import java.io.IOException; import java.text.MessageFormat; +import java.util.LinkedList; +import java.util.List; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.api.CheckoutResult.Status; @@ -52,7 +55,12 @@ import org.eclipse.jgit.api.errors.InvalidRefNameException; 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.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheCheckout; +import org.eclipse.jgit.dircache.DirCacheEditor; +import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.AmbiguousObjectException; import org.eclipse.jgit.errors.CheckoutConflictException; import org.eclipse.jgit.lib.AnyObjectId; @@ -65,6 +73,8 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; /** * Checkout a branch to the working tree @@ -82,17 +92,20 @@ public class CheckoutCommand extends GitCommand<Ref> { private CreateBranchCommand.SetupUpstreamMode upstreamMode; - private String startPoint = Constants.HEAD; + private String startPoint = null; private RevCommit startCommit; private CheckoutResult status; + private List<String> paths; + /** * @param repo */ protected CheckoutCommand(Repository repo) { super(repo); + this.paths = new LinkedList<String>(); } /** @@ -111,6 +124,12 @@ public class CheckoutCommand extends GitCommand<Ref> { checkCallable(); processOptions(); try { + if (!paths.isEmpty()) { + checkoutPaths(); + status = CheckoutResult.OK_RESULT; + setCallable(false); + return null; + } if (createBranch) { Git git = new Git(repo); @@ -196,6 +215,67 @@ public class CheckoutCommand extends GitCommand<Ref> { } } + /** + * @param path + * Path to update in the working tree and index. + * @return {@code this} + */ + public CheckoutCommand addPath(String path) { + checkCallable(); + this.paths.add(path); + return this; + } + + /** + * Checkout paths into index and working directory + * + * @return this instance + * @throws IOException + * @throws RefNotFoundException + */ + protected CheckoutCommand checkoutPaths() throws IOException, + RefNotFoundException { + RevWalk revWalk = new RevWalk(repo); + DirCache dc = repo.lockDirCache(); + try { + TreeWalk treeWalk = new TreeWalk(revWalk.getObjectReader()); + treeWalk.setRecursive(true); + treeWalk.addTree(new DirCacheIterator(dc)); + treeWalk.setFilter(PathFilterGroup.createFromStrings(paths)); + List<String> files = new LinkedList<String>(); + while (treeWalk.next()) + files.add(treeWalk.getPathString()); + + if (startCommit != null || startPoint != null) { + DirCacheEditor editor = dc.editor(); + TreeWalk startWalk = new TreeWalk(revWalk.getObjectReader()); + startWalk.setRecursive(true); + startWalk.setFilter(treeWalk.getFilter()); + startWalk.addTree(revWalk.parseCommit(getStartPoint()) + .getTree()); + while (startWalk.next()) { + final ObjectId blobId = startWalk.getObjectId(0); + editor.add(new PathEdit(startWalk.getPathString()) { + + public void apply(DirCacheEntry ent) { + ent.setObjectId(blobId); + } + }); + } + editor.commit(); + } + + File workTree = repo.getWorkTree(); + for (String file : files) + DirCacheCheckout.checkoutEntry(repo, new File(workTree, file), + dc.getEntry(file)); + } finally { + dc.unlock(); + revWalk.release(); + } + return this; + } + private ObjectId getStartPoint() throws AmbiguousObjectException, RefNotFoundException, IOException { if (startCommit != null) @@ -215,8 +295,9 @@ public class CheckoutCommand extends GitCommand<Ref> { } private void processOptions() throws InvalidRefNameException { - if (name == null - || !Repository.isValidRefName(Constants.R_HEADS + name)) + if (paths.isEmpty() + && (name == null || !Repository + .isValidRefName(Constants.R_HEADS + name))) throw new InvalidRefNameException(MessageFormat.format(JGitText .get().branchNameInvalid, name == null ? "<null>" : name)); } |