Action Reactoring (AbstractOperationAction)
[egit.git] / org.eclipse.egit.core / src / org / eclipse / egit / core / op / DiscardChangesOperation.java
blob0a506843ab210d4cbd0404f2b56bc704f590f33c
1 /*******************************************************************************
2 * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com>
3 * Copyright (C) 2010, Roland Grunberg <rgrunber@redhat.com>
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * which accompanies this distribution, and is available at
8 * http://www.eclipse.org/legal/epl-v10.html
10 * Code extracted from org.eclipse.egit.ui.internal.actions.DiscardChangesAction
11 * and reworked.
12 *******************************************************************************/
13 package org.eclipse.egit.core.op;
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
21 import org.eclipse.core.resources.IContainer;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.resources.IResourceRuleFactory;
25 import org.eclipse.core.resources.IWorkspace;
26 import org.eclipse.core.resources.IWorkspaceRunnable;
27 import org.eclipse.core.resources.ResourcesPlugin;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.SubProgressMonitor;
32 import org.eclipse.core.runtime.jobs.ISchedulingRule;
33 import org.eclipse.core.runtime.jobs.MultiRule;
34 import org.eclipse.egit.core.Activator;
35 import org.eclipse.egit.core.CoreText;
36 import org.eclipse.egit.core.internal.util.ProjectUtil;
37 import org.eclipse.egit.core.project.RepositoryMapping;
38 import org.eclipse.jgit.lib.GitIndex;
39 import org.eclipse.jgit.lib.Repository;
40 import org.eclipse.jgit.lib.GitIndex.Entry;
41 import org.eclipse.osgi.util.NLS;
43 /**
44 * The operation discards changes on a set of resources. In case of a folder
45 * resource all file resources in the sub tree are processed.
47 public class DiscardChangesOperation implements IEGitOperation {
49 IResource[] files;
51 ISchedulingRule schedulingRule;
53 /**
54 * Construct a {@link DiscardChangesOperation} object.
56 * @param files
58 public DiscardChangesOperation(IResource[] files) {
59 this.files = files;
60 schedulingRule = calcRefreshRule(files);
63 /* (non-Javadoc)
64 * @see org.eclipse.egit.core.op.IEGitOperation#getSchedulingRule()
66 public ISchedulingRule getSchedulingRule() {
67 return schedulingRule;
70 private static ISchedulingRule calcRefreshRule(IResource[] resources) {
71 List<ISchedulingRule> rules = new ArrayList<ISchedulingRule>();
72 IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace()
73 .getRuleFactory();
74 for (IResource resource : resources) {
75 ISchedulingRule rule = ruleFactory.refreshRule(resource);
76 if (rule != null)
77 rules.add(rule);
79 if (rules.size() == 0)
80 return null;
81 else
82 return new MultiRule(rules.toArray(new IResource[rules.size()]));
85 public void execute(IProgressMonitor monitor) throws CoreException {
86 IWorkspaceRunnable action = new IWorkspaceRunnable() {
87 public void run(IProgressMonitor monitor) throws CoreException {
88 discardChanges(monitor);
91 ResourcesPlugin.getWorkspace().run(action, getSchedulingRule(),
92 IWorkspace.AVOID_UPDATE, monitor);
95 private void discardChanges(IProgressMonitor monitor) throws CoreException {
96 monitor.beginTask(CoreText.DiscardChangesOperation_discardingChanges, 3);
97 boolean errorOccured = false;
98 List<IResource> allFiles = new ArrayList<IResource>();
99 // find all files
100 for (IResource res : files) {
101 allFiles.addAll(getAllMembers(res));
103 Set<GitIndex> modifiedIndexes = new HashSet<GitIndex>();
104 for (IResource res : allFiles) {
105 Repository repo = getRepository(res);
106 if (repo == null) {
107 IStatus status = Activator.error(
108 CoreText.DiscardChangesOperation_repoNotFound, null);
109 throw new CoreException(status);
111 try {
112 discardChange(res, repo, modifiedIndexes);
113 } catch (IOException e) {
114 errorOccured = true;
115 String message = NLS.bind(
116 CoreText.DiscardChangesOperation_discardFailed, res
117 .getFullPath());
118 Activator.logError(message, e);
121 monitor.worked(1);
122 for (GitIndex index : modifiedIndexes) {
123 try {
124 index.write();
125 } catch (IOException e) {
126 errorOccured = true;
127 Activator.logError(
128 CoreText.DiscardChangesOperation_writeIndexFailed, e);
131 monitor.worked(1);
132 try {
133 ProjectUtil.refreshResources(files, new SubProgressMonitor(monitor,
134 1));
135 } catch (CoreException e) {
136 errorOccured = true;
137 Activator.logError(CoreText.DiscardChangesOperation_refreshFailed,
140 monitor.worked(1);
141 monitor.done();
142 if (errorOccured) {
143 IStatus status = Activator.error(
144 CoreText.DiscardChangesOperation_discardFailedSeeLog, null);
145 throw new CoreException(status);
149 private static Repository getRepository(IResource resource) {
150 IProject project = resource.getProject();
151 RepositoryMapping repositoryMapping = RepositoryMapping
152 .getMapping(project);
153 if (repositoryMapping != null)
154 return repositoryMapping.getRepository();
155 else
156 return null;
159 private void discardChange(IResource res, Repository repository,
160 Set<GitIndex> modifiedIndexes) throws IOException {
161 String resRelPath = RepositoryMapping.getMapping(res)
162 .getRepoRelativePath(res);
164 Entry e = repository.getIndex().getEntry(resRelPath);
165 // resource must exist in the index and be dirty
166 if (e != null && e.getStage() == 0
167 && e.isModified(repository.getWorkDir())) {
168 GitIndex index = repository.getIndex();
169 index.checkoutEntry(repository.getWorkDir(), e);
170 modifiedIndexes.add(index);
175 * @param res
176 * an IResource
177 * @return An ArrayList with all members of this IResource of arbitrary
178 * depth. This will return just the argument res if it is a file.
180 private ArrayList<IResource> getAllMembers(IResource res) {
181 ArrayList<IResource> ret = new ArrayList<IResource>();
182 if (res.getLocation().toFile().isFile()) {
183 ret.add(res);
184 } else {
185 getAllMembersHelper(res, ret);
187 return ret;
190 private void getAllMembersHelper(IResource res, ArrayList<IResource> ret) {
191 if (res instanceof IContainer) {
192 ArrayList<IResource> tmp = new ArrayList<IResource>();
193 IContainer cont = (IContainer) res;
194 try {
195 for (IResource r : cont.members()) {
196 if (r.getLocation().toFile().isFile()) {
197 tmp.add(r);
198 } else {
199 getAllMembersHelper(r, tmp);
202 } catch (CoreException e) {
203 // thrown by members()
204 // ignore children in case parent resource no longer accessible
205 return;
208 ret.addAll(tmp);