diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java | 79 |
1 files changed, 78 insertions, 1 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 1ddfd6d77a..206d4062b7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java @@ -44,12 +44,17 @@ package org.eclipse.jgit.api; import java.io.IOException; import java.text.MessageFormat; +import java.util.Collection; +import java.util.LinkedList; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.dircache.DirCacheCheckout; +import org.eclipse.jgit.dircache.DirCacheEditor; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; @@ -58,6 +63,9 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; /** * A class used to execute a {@code Reset} command. It has setters for all @@ -103,10 +111,12 @@ public class ResetCommand extends GitCommand<Ref> { KEEP // TODO not implemented yet } - private String ref; + private String ref = Constants.HEAD; private ResetType mode; + private Collection<String> filepaths = new LinkedList<String>(); + /** * * @param repo @@ -157,6 +167,13 @@ public class ResetCommand extends GitCommand<Ref> { rw.release(); } + if (!filepaths.isEmpty()) { + // reset [commit] -- paths + resetIndexForPaths(commit); + setCallable(false); + return repo.getRef(Constants.HEAD); + } + // write the ref final RefUpdate ru = repo.updateRef(Constants.HEAD); ru.setNewObjectId(commitId); @@ -217,10 +234,70 @@ public class ResetCommand extends GitCommand<Ref> { * @return this instance */ public ResetCommand setMode(ResetType mode) { + if (!filepaths.isEmpty()) + throw new JGitInternalException(MessageFormat.format( + JGitText.get().illegalCombinationOfArguments, + "[--mixed | --soft | --hard]", "<paths>...")); this.mode = mode; return this; } + /** + * @param file + * the file to add + * @return this instance + */ + public ResetCommand addPath(String file) { + if (mode != null) + throw new JGitInternalException(MessageFormat.format( + JGitText.get().illegalCombinationOfArguments, "<paths>...", + "[--mixed | --soft | --hard]")); + filepaths.add(file); + return this; + } + + private void resetIndexForPaths(RevCommit commit) { + DirCache dc = null; + final DirCacheEditor edit; + try { + dc = repo.lockDirCache(); + edit = dc.editor(); + + final TreeWalk tw = new TreeWalk(repo); + tw.addTree(new DirCacheIterator(dc)); + tw.addTree(commit.getTree()); + tw.setFilter(PathFilterGroup.createFromStrings(filepaths)); + + while (tw.next()) { + final String path = tw.getPathString(); + // DirCacheIterator dci = tw.getTree(0, DirCacheIterator.class); + final CanonicalTreeParser tree = tw.getTree(1, + CanonicalTreeParser.class); + if (tree == null) + // file is not in the commit, remove from index + edit.add(new DirCacheEditor.DeletePath(path)); + else { + // revert index to commit + edit.add(new DirCacheEditor.PathEdit(path) { + @Override + public void apply(DirCacheEntry ent) { + ent.setFileMode(tree.getEntryFileMode()); + ent.setObjectId(tree.getEntryObjectId()); + ent.setLastModified(0); + } + }); + } + } + + edit.commit(); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (dc != null) + dc.unlock(); + } + } + private void resetIndex(RevCommit commit) throws IOException { DirCache dc = null; try { |