ResetOperation was not doing mixed reset properly
[egit/zawir.git] / org.spearce.egit.core / src / org / spearce / egit / core / op / ResetOperation.java
blob13421ec0c01078f0e64cddaecdd24204122d33f5
1 /*
2 * Copyright (C) 2007 Dave Watson <dwatson@mimvista.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License, version 2.1, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org.spearce.egit.core.op;
19 import java.io.File;
20 import java.io.IOException;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.resources.IWorkspaceRunnable;
25 import org.eclipse.core.resources.ResourcesPlugin;
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IProgressMonitor;
28 import org.eclipse.team.core.TeamException;
29 import org.spearce.jgit.lib.Commit;
30 import org.spearce.jgit.lib.GitIndex;
31 import org.spearce.jgit.lib.ObjectId;
32 import org.spearce.jgit.lib.LockFile;
33 import org.spearce.jgit.lib.RefLogWriter;
34 import org.spearce.jgit.lib.Repository;
35 import org.spearce.jgit.lib.Tag;
36 import org.spearce.jgit.lib.Tree;
37 import org.spearce.jgit.lib.WorkDirCheckout;
39 /**
40 * A class for changing a ref and possibly index and workdir too.
42 public class ResetOperation implements IWorkspaceRunnable {
43 /**
44 * Kind of reset
46 public enum ResetType {
47 /**
48 * Just change the ref. The index and workdir are not changed.
50 SOFT,
52 /**
53 * Change the ref and the index. The workdir is not changed.
55 MIXED,
57 /**
58 * Change the ref, the index and the workdir
60 HARD
63 private final Repository repository;
64 private final String refName;
65 private final ResetType type;
67 private Commit commit;
68 private Commit previousCommit;
69 private Tree newTree;
70 private GitIndex index;
72 /**
73 * Construct a {@link ResetOperation}
75 * @param repository
76 * @param refName
77 * @param type
79 public ResetOperation(Repository repository, String refName, ResetType type) {
80 this.repository = repository;
81 this.refName = refName;
82 this.type = type;
85 public void run(IProgressMonitor monitor) throws CoreException {
86 monitor.beginTask("Performing " + type.toString().toLowerCase() + " reset to " + refName, 7);
88 mapObjects();
89 monitor.worked(1);
91 writeRef();
92 monitor.worked(1);
94 if (type != ResetType.SOFT) {
95 if (type == ResetType.MIXED)
96 resetIndex();
97 else
98 readIndex();
99 writeIndex();
101 monitor.worked(1);
103 if (type == ResetType.HARD) {
104 checkoutIndex();
106 monitor.worked(1);
108 if (type != ResetType.SOFT) {
109 refreshIndex();
111 monitor.worked(1);
113 writeReflogs();
114 monitor.worked(1);
116 refreshProjects();
118 monitor.done();
121 private void refreshIndex() throws TeamException {
122 // File workdir = repository.getDirectory().getParentFile();
123 // for (Entry e : newIndex.getMembers()) {
124 // try {
125 // e.update(new File(workdir, e.getName()));
126 // } catch (IOException ignore) {}
127 // }
128 try {
129 index.write();
130 } catch (IOException e1) {
131 throw new TeamException("Writing index", e1);
135 private void refreshProjects() {
136 final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
137 final File parentFile = repository.getWorkDir();
138 for (IProject p : projects) {
139 final File file = p.getLocation().toFile();
140 if (file.getAbsolutePath().startsWith(parentFile.getAbsolutePath())) {
141 try {
142 System.out.println("Refreshing " + p);
143 p.refreshLocal(IResource.DEPTH_INFINITE, null);
144 } catch (CoreException e) {
145 e.printStackTrace();
151 private void mapObjects() throws TeamException {
152 final ObjectId commitId;
153 try {
154 commitId = repository.resolve(refName);
155 } catch (IOException e) {
156 throw new TeamException("looking up ref " + 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("looking up commit " + commitId, e2);
169 try {
170 previousCommit = repository.mapCommit(repository.resolve("HEAD"));
171 } catch (IOException e) {
172 throw new TeamException("looking up HEAD commit", e);
176 private void writeRef() throws TeamException {
177 LockFile lockRef;
178 try {
179 lockRef = repository.lockRef("HEAD");
180 } catch (IOException e) {
181 throw new TeamException("Could not lock ref for HEAD", e);
183 try {
184 lockRef.write(commit.getCommitId());
185 } catch (IOException e) {
186 throw new TeamException("Could not write ref for HEAD", e);
189 if (!lockRef.commit())
190 throw new TeamException("writing ref failed");
193 private void readIndex() throws TeamException {
194 try {
195 newTree = commit.getTree();
196 index = repository.getIndex();
197 } catch (IOException e) {
198 throw new TeamException("Reading index", 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("Reading index", e);
212 private void writeIndex() throws CoreException {
213 try {
214 index.write();
215 } catch (IOException e) {
216 throw new TeamException("Writing index", 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("mapping tree for commit", e);
233 private void writeReflog(String reflogRelPath) throws IOException {
234 String name = refName;
235 if (name.startsWith("refs/heads/"))
236 name = name.substring(11);
237 if (name.startsWith("refs/remotes/"))
238 name = name.substring(13);
240 String message = "reset --" + type.toString().toLowerCase() + " " + name;
242 RefLogWriter.writeReflog(repository, previousCommit.getCommitId(), commit.getCommitId(), message, reflogRelPath);
245 private void writeReflogs() throws TeamException {
246 try {
247 writeReflog("HEAD");
248 writeReflog(repository.getFullBranch());
249 } catch (IOException e) {
250 throw new TeamException("Writing reflogs", e);