aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
diff options
context:
space:
mode:
authorChris Aniszczyk <caniszczyk@gmail.com>2011-02-01 08:47:04 -0600
committerChris Aniszczyk <caniszczyk@gmail.com>2011-02-17 10:28:26 -0600
commit5f258d91c02f0876b6dd3fd798717d2fe7c2db18 (patch)
treef98e2fe396cc2d9ef827c8cce34bc644d47e5e55 /org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
parentc13bf057540f11e2503e1205d46c800f9d00fd7b (diff)
downloadjgit-5f258d91c02f0876b6dd3fd798717d2fe7c2db18.tar.gz
jgit-5f258d91c02f0876b6dd3fd798717d2fe7c2db18.zip
Add git-reset to the Git API
Bug: 334764 Change-Id: Ice404629687d7f2a595d8d4eccf471b12f7e32ec Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
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.java258
1 files changed, 258 insertions, 0 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
new file mode 100644
index 0000000000..d55767d3a6
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2011, Chris Aniszczyk <caniszczyk@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+
+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.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.RepositoryState;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * A class used to execute a {@code Reset} command. It has setters for all
+ * supported options and arguments of this command and a {@link #call()} method
+ * to finally execute the command. Each instance of this class should only be
+ * used for one invocation of the command (means: one call to {@link #call()})
+ *
+ * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-reset.html"
+ * >Git documentation about Reset</a>
+ */
+public class ResetCommand extends GitCommand<Ref> {
+
+ /**
+ * Kind of reset
+ */
+ public enum ResetType {
+ /**
+ * Just change the ref, the index and workdir are not changed.
+ */
+ SOFT,
+
+ /**
+ * Change the ref and the index, the workdir is not changed.
+ */
+ MIXED,
+
+ /**
+ * Change the ref, the index and the workdir
+ */
+ HARD,
+
+ /**
+ * Resets the index and updates the files in the working tree that are
+ * different between respective commit and HEAD, but keeps those which
+ * are different between the index and working tree
+ */
+ MERGE, // TODO not implemented yet
+
+ /**
+ * Change the ref, the index and the workdir that are different between
+ * respective commit and HEAD
+ */
+ KEEP // TODO not implemented yet
+ }
+
+ private String ref;
+
+ private ResetType mode;
+
+ /**
+ *
+ * @param repo
+ */
+ public ResetCommand(Repository repo) {
+ super(repo);
+ }
+
+ /**
+ * Executes the {@code Reset} command. Each instance of this class should
+ * only be used for one invocation of the command. Don't call this method
+ * twice on an instance.
+ *
+ * @return the Ref after reset
+ */
+ public Ref call() throws IOException {
+ checkCallable();
+
+ Ref r;
+ RevCommit commit;
+
+ try {
+ boolean merging = false;
+ if (repo.getRepositoryState().equals(RepositoryState.MERGING)
+ || repo.getRepositoryState().equals(
+ RepositoryState.MERGING_RESOLVED))
+ merging = true;
+
+ // resolve the ref to a commit
+ final ObjectId commitId;
+ try {
+ commitId = repo.resolve(ref);
+ } catch (IOException e) {
+ throw new JGitInternalException(
+ MessageFormat.format(JGitText.get().cannotRead, ref),
+ e);
+ }
+ RevWalk rw = new RevWalk(repo);
+ try {
+ commit = rw.parseCommit(commitId);
+ } catch (IOException e) {
+ throw new JGitInternalException(
+ MessageFormat.format(
+ JGitText.get().cannotReadCommit, commitId.toString()),
+ e);
+ } finally {
+ rw.release();
+ }
+
+ // write the ref
+ final RefUpdate ru = repo.updateRef(Constants.HEAD);
+ ru.setNewObjectId(commitId);
+
+ String refName = Repository.shortenRefName(ref);
+ String message = "reset --" //$NON-NLS-1$
+ + mode.toString().toLowerCase() + " " + refName; //$NON-NLS-1$
+ ru.setRefLogMessage(message, false);
+ if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE)
+ throw new JGitInternalException(MessageFormat.format(
+ JGitText.get().cannotLock, ru.getName()));
+
+ switch (mode) {
+ case HARD:
+ checkoutIndex(commit);
+ break;
+ case MIXED:
+ resetIndex(commit);
+ break;
+ case SOFT: // do nothing, only the ref was changed
+ break;
+ case KEEP: // TODO
+ case MERGE: // TODO
+ throw new UnsupportedOperationException();
+
+ }
+
+ if (mode != ResetType.SOFT && merging)
+ resetMerge();
+
+ setCallable(false);
+ r = ru.getRef();
+ } catch (IOException e) {
+ throw new JGitInternalException(
+ JGitText.get().exceptionCaughtDuringExecutionOfResetCommand,
+ e);
+ }
+
+ return r;
+ }
+
+ /**
+ * @param ref
+ * the ref to reset to
+ * @return this instance
+ */
+ public ResetCommand setRef(String ref) {
+ this.ref = ref;
+ return this;
+ }
+
+ /**
+ * @param mode
+ * the mode of the reset command
+ * @return this instance
+ */
+ public ResetCommand setMode(ResetType mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ private void resetIndex(RevCommit commit) throws IOException {
+ DirCache dc = null;
+ try {
+ dc = repo.lockDirCache();
+ dc.clear();
+ DirCacheBuilder dcb = dc.builder();
+ dcb.addTree(new byte[0], 0, repo.newObjectReader(),
+ commit.getTree());
+ dcb.commit();
+ } catch (IOException e) {
+ throw e;
+ } finally {
+ if (dc != null)
+ dc.unlock();
+ }
+ }
+
+ private void checkoutIndex(RevCommit commit) throws IOException {
+ DirCache dc = null;
+ try {
+ dc = repo.lockDirCache();
+ DirCacheCheckout checkout = new DirCacheCheckout(repo, dc,
+ commit.getTree());
+ checkout.setFailOnConflict(false);
+ checkout.checkout();
+ } catch (IOException e) {
+ throw e;
+ } finally {
+ if (dc != null)
+ dc.unlock();
+ }
+ }
+
+ private void resetMerge() throws IOException {
+ repo.writeMergeHeads(null);
+ repo.writeMergeCommitMsg(null);
+ }
+
+}