Execute ResetOperation in Workspace Runnable
[egit.git] / org.eclipse.egit.core / src / org / eclipse / egit / core / op / ResetOperation.java
blobb0dbda849481565a081942113c65162c5bdc3b0a
1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *******************************************************************************/
11 package org.eclipse.egit.core.op;
13 import java.io.File;
14 import java.io.IOException;
16 import org.eclipse.core.resources.IWorkspaceRunnable;
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.SubProgressMonitor;
21 import org.eclipse.egit.core.CoreText;
22 import org.eclipse.egit.core.internal.util.ProjectUtil;
23 import org.eclipse.jgit.lib.Commit;
24 import org.eclipse.jgit.lib.Constants;
25 import org.eclipse.jgit.lib.GitIndex;
26 import org.eclipse.jgit.lib.ObjectId;
27 import org.eclipse.jgit.lib.RefUpdate;
28 import org.eclipse.jgit.lib.Repository;
29 import org.eclipse.jgit.lib.Tag;
30 import org.eclipse.jgit.lib.Tree;
31 import org.eclipse.jgit.lib.WorkDirCheckout;
32 import org.eclipse.osgi.util.NLS;
33 import org.eclipse.team.core.TeamException;
35 /**
36 * A class for changing a ref and possibly index and workdir too.
38 public class ResetOperation implements IEGitOperation {
39 /**
40 * Kind of reset
42 public enum ResetType {
43 /**
44 * Just change the ref. The index and workdir are not changed.
46 SOFT,
48 /**
49 * Change the ref and the index. The workdir is not changed.
51 MIXED,
53 /**
54 * Change the ref, the index and the workdir
56 HARD
59 private final Repository repository;
60 private final String refName;
61 private final ResetType type;
63 private Commit commit;
64 private Tree newTree;
65 private GitIndex index;
67 /**
68 * Construct a {@link ResetOperation}
70 * @param repository
71 * @param refName
72 * @param type
74 public ResetOperation(Repository repository, String refName, ResetType type) {
75 this.repository = repository;
76 this.refName = refName;
77 this.type = type;
80 /* (non-Javadoc)
81 * @see org.eclipse.egit.core.op.IEGitOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
83 public void execute(IProgressMonitor monitor) throws CoreException {
84 if (type == ResetType.HARD) {
85 IWorkspaceRunnable action = new IWorkspaceRunnable() {
86 public void run(IProgressMonitor monitor) throws CoreException {
87 reset(monitor);
90 // lock workspace to protect working tree changes
91 ResourcesPlugin.getWorkspace().run(action, monitor);
92 } else {
93 reset(monitor);
97 private void reset(IProgressMonitor monitor) throws CoreException {
98 monitor.beginTask(NLS.bind(CoreText.ResetOperation_performingReset,
99 type.toString().toLowerCase(), refName), 7);
101 mapObjects();
102 monitor.worked(1);
104 writeRef();
105 monitor.worked(1);
107 if (type != ResetType.SOFT) {
108 if (type == ResetType.MIXED)
109 resetIndex();
110 else
111 readIndex();
112 writeIndex();
114 monitor.worked(1);
116 if (type == ResetType.HARD) {
117 checkoutIndex();
119 monitor.worked(1);
121 if (type != ResetType.SOFT) {
122 refreshIndex();
124 monitor.worked(1);
126 monitor.worked(1);
128 if (type == ResetType.HARD)
129 // only refresh if working tree changes
130 ProjectUtil.refreshProjects(repository, new SubProgressMonitor(
131 monitor, 1));
133 monitor.done();
136 private void refreshIndex() throws TeamException {
137 // File workdir = repository.getDirectory().getParentFile();
138 // for (Entry e : newIndex.getMembers()) {
139 // try {
140 // e.update(new File(workdir, e.getName()));
141 // } catch (IOException ignore) {}
142 // }
143 try {
144 index.write();
145 } catch (IOException e1) {
146 throw new TeamException(CoreText.ResetOperation_writingIndex, e1);
150 private void mapObjects() throws TeamException {
151 final ObjectId commitId;
152 try {
153 commitId = repository.resolve(refName);
154 } catch (IOException e) {
155 throw new TeamException(NLS.bind(
156 CoreText.ResetOperation_lookingUpRef, refName), e);
158 try {
159 commit = repository.mapCommit(commitId);
160 } catch (IOException e) {
161 try {
162 Tag t = repository.mapTag(refName, commitId);
163 commit = repository.mapCommit(t.getObjId());
164 } catch (IOException e2) {
165 throw new TeamException(NLS.bind(
166 CoreText.ResetOperation_lookingUpCommit, commitId), e2);
172 private void writeRef() throws TeamException {
173 try {
174 final RefUpdate ru = repository.updateRef(Constants.HEAD);
175 ru.setNewObjectId(commit.getCommitId());
176 String name = refName;
177 if (name.startsWith("refs/heads/")) //$NON-NLS-1$
178 name = name.substring(11);
179 if (name.startsWith("refs/remotes/")) //$NON-NLS-1$
180 name = name.substring(13);
181 String message = "reset --" //$NON-NLS-1$
182 + type.toString().toLowerCase() + " " + name; //$NON-NLS-1$
183 ru.setRefLogMessage(message, false);
184 if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE)
185 throw new TeamException(NLS.bind(
186 CoreText.ResetOperation_cantUpdate, ru.getName()));
187 } catch (IOException e) {
188 throw new TeamException(NLS.bind(
189 CoreText.ResetOperation_updatingFailed, Constants.HEAD), e);
193 private void readIndex() throws TeamException {
194 try {
195 newTree = commit.getTree();
196 index = repository.getIndex();
197 } catch (IOException e) {
198 throw new TeamException(CoreText.ResetOperation_readingIndex, e);
202 private void resetIndex() throws TeamException {
203 try {
204 newTree = commit.getTree();
205 index = repository.getIndex();
206 index.readTree(newTree);
207 } catch (IOException e) {
208 throw new TeamException(CoreText.ResetOperation_readingIndex, e);
212 private void writeIndex() throws CoreException {
213 try {
214 index.write();
215 } catch (IOException e) {
216 throw new TeamException(CoreText.ResetOperation_writingIndex, e);
220 private void checkoutIndex() throws TeamException {
221 final File parentFile = repository.getWorkDir();
222 try {
223 WorkDirCheckout workDirCheckout =
224 new WorkDirCheckout(repository, parentFile, index, newTree);
225 workDirCheckout.setFailOnConflict(false);
226 workDirCheckout.checkout();
227 } catch (IOException e) {
228 throw new TeamException(
229 CoreText.ResetOperation_mappingTreeForCommit, e);