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
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
;
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
;
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
{
51 ISchedulingRule schedulingRule
;
54 * Construct a {@link DiscardChangesOperation} object.
58 public DiscardChangesOperation(IResource
[] files
) {
60 schedulingRule
= calcRefreshRule(files
);
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()
74 for (IResource resource
: resources
) {
75 ISchedulingRule rule
= ruleFactory
.refreshRule(resource
);
79 if (rules
.size() == 0)
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
>();
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
);
107 IStatus status
= Activator
.error(
108 CoreText
.DiscardChangesOperation_repoNotFound
, null);
109 throw new CoreException(status
);
112 discardChange(res
, repo
, modifiedIndexes
);
113 } catch (IOException e
) {
115 String message
= NLS
.bind(
116 CoreText
.DiscardChangesOperation_discardFailed
, res
118 Activator
.logError(message
, e
);
122 for (GitIndex index
: modifiedIndexes
) {
125 } catch (IOException e
) {
128 CoreText
.DiscardChangesOperation_writeIndexFailed
, e
);
133 ProjectUtil
.refreshResources(files
, new SubProgressMonitor(monitor
,
135 } catch (CoreException e
) {
137 Activator
.logError(CoreText
.DiscardChangesOperation_refreshFailed
,
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();
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
);
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()) {
185 getAllMembersHelper(res
, 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
;
195 for (IResource r
: cont
.members()) {
196 if (r
.getLocation().toFile().isFile()) {
199 getAllMembersHelper(r
, tmp
);
202 } catch (CoreException e
) {
203 // thrown by members()
204 // ignore children in case parent resource no longer accessible