1 /*******************************************************************************
2 * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com>
3 * Copyright (C) 2010, Roland Grunberg <rgrunber@redhat.com>
4 * Copyright (C) 2012, 2014 Robin Stocker <robin@nibor.org>
5 * Copyright (C) 2015, Stephan Hackstedt <stephan.hackstedt@googlemail.com>
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License 2.0
9 * which accompanies this distribution, and is available at
10 * https://www.eclipse.org/legal/epl-2.0/
12 * SPDX-License-Identifier: EPL-2.0
14 * Code extracted from org.eclipse.egit.ui.internal.actions.DiscardChangesAction
16 *******************************************************************************/
17 package org
.eclipse
.egit
.core
.op
;
19 import java
.util
.Collection
;
21 import java
.util
.Map
.Entry
;
23 import org
.eclipse
.core
.resources
.IResource
;
24 import org
.eclipse
.core
.resources
.IWorkspace
;
25 import org
.eclipse
.core
.resources
.IWorkspaceRunnable
;
26 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
27 import org
.eclipse
.core
.runtime
.CoreException
;
28 import org
.eclipse
.core
.runtime
.IPath
;
29 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
30 import org
.eclipse
.core
.runtime
.IStatus
;
31 import org
.eclipse
.core
.runtime
.SubMonitor
;
32 import org
.eclipse
.core
.runtime
.jobs
.ISchedulingRule
;
33 import org
.eclipse
.egit
.core
.Activator
;
34 import org
.eclipse
.egit
.core
.EclipseGitProgressTransformer
;
35 import org
.eclipse
.egit
.core
.internal
.CoreText
;
36 import org
.eclipse
.egit
.core
.internal
.job
.RuleUtil
;
37 import org
.eclipse
.egit
.core
.internal
.util
.ProjectUtil
;
38 import org
.eclipse
.egit
.core
.internal
.util
.ResourceUtil
;
39 import org
.eclipse
.jgit
.api
.CheckoutCommand
;
40 import org
.eclipse
.jgit
.api
.Git
;
41 import org
.eclipse
.jgit
.api
.errors
.GitAPIException
;
42 import org
.eclipse
.jgit
.lib
.Repository
;
45 * The operation discards changes on a set of resources (checkout with paths).
46 * In case of a folder resource all file resources in the sub tree are
47 * processed. Untracked files are ignored.
49 public class DiscardChangesOperation
implements IEGitOperation
{
51 private final Map
<Repository
, Collection
<String
>> pathsByRepository
;
52 private final ISchedulingRule schedulingRule
;
54 private String revision
;
59 * The index stage to check out for conflicting files.
65 BASE(CheckoutCommand
.Stage
.BASE
),
69 OURS(CheckoutCommand
.Stage
.OURS
),
73 THEIRS(CheckoutCommand
.Stage
.THEIRS
);
75 private CheckoutCommand
.Stage checkoutStage
;
77 private Stage(CheckoutCommand
.Stage checkoutStage
) {
78 this.checkoutStage
= checkoutStage
;
83 * Construct a {@link DiscardChangesOperation} object.
87 public DiscardChangesOperation(IResource
[] files
) {
92 * Construct a {@link DiscardChangesOperation} object.
97 public DiscardChangesOperation(IResource
[] files
, String revision
) {
98 this(ResourceUtil
.splitResourcesByRepository(files
));
99 this.revision
= revision
;
103 * {@link DiscardChangesOperation} for absolute paths.
107 public DiscardChangesOperation(Collection
<IPath
> paths
) {
108 this(ResourceUtil
.splitPathsByRepository(paths
));
111 private DiscardChangesOperation(
112 Map
<Repository
, Collection
<String
>> pathsByRepository
) {
113 this.pathsByRepository
= pathsByRepository
;
114 this.schedulingRule
= RuleUtil
.getRuleForRepositories(pathsByRepository
119 * Set the index stage to check out for conflicting files. Not compatible
124 public void setStage(Stage stage
) {
125 if (revision
!= null)
126 throw new IllegalStateException(
127 "Either stage or revision can be set, but not both"); //$NON-NLS-1$
134 * @see org.eclipse.egit.core.op.IEGitOperation#getSchedulingRule()
137 public ISchedulingRule
getSchedulingRule() {
138 return schedulingRule
;
142 public void execute(IProgressMonitor m
) throws CoreException
{
143 IWorkspaceRunnable action
= new IWorkspaceRunnable() {
145 public void run(IProgressMonitor actMonitor
) throws CoreException
{
146 discardChanges(actMonitor
);
149 ResourcesPlugin
.getWorkspace().run(action
, getSchedulingRule(),
150 IWorkspace
.AVOID_UPDATE
, m
);
153 private void discardChanges(IProgressMonitor monitor
) throws CoreException
{
154 SubMonitor progress
= SubMonitor
.convert(monitor
,
155 CoreText
.DiscardChangesOperation_discardingChanges
,
156 pathsByRepository
.size() * 2);
157 boolean errorOccurred
= false;
159 for (Entry
<Repository
, Collection
<String
>> entry
: pathsByRepository
161 Repository repository
= entry
.getKey();
162 Collection
<String
> paths
= entry
.getValue();
165 discardChanges(repository
, paths
, progress
.newChild(1));
166 } catch (GitAPIException e
) {
167 errorOccurred
= true;
169 CoreText
.DiscardChangesOperation_discardFailed
, e
);
173 ProjectUtil
.refreshRepositoryResources(repository
, paths
,
174 progress
.newChild(1));
175 } catch (CoreException e
) {
176 errorOccurred
= true;
178 CoreText
.DiscardChangesOperation_refreshFailed
, e
);
183 IStatus status
= Activator
.error(
184 CoreText
.DiscardChangesOperation_discardFailedSeeLog
, null);
185 throw new CoreException(status
);
189 private void discardChanges(Repository repository
, Collection
<String
> paths
,
190 IProgressMonitor progress
)
191 throws GitAPIException
{
192 ResourceUtil
.saveLocalHistory(repository
);
193 try (Git git
= new Git(repository
)) {
194 CheckoutCommand checkoutCommand
= git
.checkout().setProgressMonitor(
195 new EclipseGitProgressTransformer(progress
));
197 if (revision
!= null) {
198 checkoutCommand
.setStartPoint(revision
);
201 checkoutCommand
.setStage(stage
.checkoutStage
);
203 if (paths
.isEmpty() || paths
.contains("")) { //$NON-NLS-1$
204 checkoutCommand
.setAllPaths(true);
206 for (String path
: paths
) {
207 checkoutCommand
.addPath(path
);
210 checkoutCommand
.call();