StagingView wrongly sorted by state initially
[egit/eclipse.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / ResourcePropertyTester.java
blob879ccabecc7eefd8931cd79b4150836121a56254
1 /*******************************************************************************
2 * Copyright (c) 2011, 2016 SAP AG and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License 2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-2.0/
8 * SPDX-License-Identifier: EPL-2.0
10 * Contributors:
11 * Mathias Kinzler (SAP AG) - initial implementation
12 * Dariusz Luksza <dariusz@luksza.org> - add 'isSafe' implementation
13 * Thomas Wolf <thomas.wolf@paranor.ch> - Bug 493352
14 *******************************************************************************/
15 package org.eclipse.egit.ui.internal;
17 import java.lang.reflect.Method;
18 import java.net.URISyntaxException;
19 import java.util.List;
20 import java.util.Locale;
22 import org.eclipse.core.expressions.PropertyTester;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.egit.core.internal.gerrit.GerritUtil;
25 import org.eclipse.egit.core.project.RepositoryMapping;
26 import org.eclipse.egit.ui.internal.trace.GitTraceLocation;
27 import org.eclipse.jgit.annotations.NonNull;
28 import org.eclipse.jgit.lib.Config;
29 import org.eclipse.jgit.lib.Repository;
30 import org.eclipse.jgit.lib.RepositoryState;
31 import org.eclipse.jgit.transport.RemoteConfig;
33 /**
34 * Resource-based property tester.
35 * <p>
36 * Supported properties:
37 * <ul>
38 * <li>isShared <code>true</code> if the resource is mapped to EGit. EGit may
39 * still affect a resource if it belongs to the workspace of some shared
40 * project.</li>
41 * <li>isContainer <code>true</code> if the resource is a project or a folder</li>
42 * <li>is<em>repository state</em>
43 * <ul>
44 * <li>isSafe - see {@link RepositoryState#SAFE}</li>
45 * <li>isReverting - see {@link RepositoryState#REVERTING}</li>
46 * <li>isRevertingResolved - see {@link RepositoryState#REVERTING_RESOLVED}</li>
47 * <li>isCherryPicking - see {@link RepositoryState#CHERRY_PICKING}</li>
48 * <li>isCherryPickingResolved - see
49 * {@link RepositoryState#CHERRY_PICKING_RESOLVED}</li>
50 * <li>isMerging - see {@link RepositoryState#MERGING}</li>
51 * <li>isMergingResolved - see {@link RepositoryState#MERGING_RESOLVED}</li>
52 * <li>isRebasing - see {@link RepositoryState#REBASING}</li>
53 * <li>isRebasingRebasing - see {@link RepositoryState#REBASING_REBASING}</li>
54 * <li>isRebasingMerge - see {@link RepositoryState#REBASING_MERGE}</li>
55 * <li>isRebasingInteractive - see {@link RepositoryState#REBASING_INTERACTIVE}</li>
56 * <li>isApply - see {@link RepositoryState#APPLY}</li>
57 * <li>isBisecting - see {@link RepositoryState#BISECTING}</li>
58 * </ul>
59 * <li>Capabilities/properties of the current state:<ul>
60 * <li>canCheckout - see {@link RepositoryState#canCheckout()}</li>
61 * <li>canAmend - see {@link RepositoryState#canAmend()}</li>
62 * <li>canCommit - see {@link RepositoryState#canCommit()}</li>
63 * <li>canResetHead - see {@link RepositoryState#canResetHead()}</li>
64 * </ul>
65 * </ul>
67 public class ResourcePropertyTester extends PropertyTester {
69 @Override
70 public boolean test(Object receiver, String property, Object[] args,
71 Object expectedValue) {
72 boolean value = internalTest(receiver, property);
73 boolean trace = GitTraceLocation.PROPERTIESTESTER.isActive();
74 if (trace)
75 GitTraceLocation
76 .getTrace()
77 .trace(GitTraceLocation.PROPERTIESTESTER.getLocation(),
78 "prop " + property + " of " + receiver + " = " + value + ", expected = " + expectedValue); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
79 return value;
82 private boolean internalTest(Object receiver, String property) {
83 if (!(receiver instanceof IResource))
84 return false;
85 IResource res = (IResource) receiver;
86 if ("isContainer".equals(property)) { //$NON-NLS-1$
87 int type = res.getType();
88 return type == IResource.FOLDER || type == IResource.PROJECT;
91 RepositoryMapping mapping = RepositoryMapping.getMapping(res);
92 if (mapping != null) {
93 Repository repository = mapping.getRepository();
94 return testRepositoryState(repository, property);
96 return false;
99 /**
100 * @param repository
101 * @param property
102 * @return true if the repository is in an appropriate state. See
103 * {@link ResourcePropertyTester}
105 public static boolean testRepositoryState(Repository repository, String property) {
106 if ("isShared".equals(property)) //$NON-NLS-1$
107 return repository != null;
108 if (repository != null) {
109 if ("hasGerritConfiguration".equals(property)) { //$NON-NLS-1$
110 return hasGerritConfiguration(repository);
112 if ("canFetchFromGerrit".equals(property)) { //$NON-NLS-1$
113 return canFetchFromGerrit(repository);
115 if ("canPushToGerrit".equals(property)) { //$NON-NLS-1$
116 return canPushToGerrit(repository);
118 RepositoryState state = repository.getRepositoryState();
120 if ("canAbortRebase".equals(property)) //$NON-NLS-1$
121 switch (state) {
122 case REBASING_INTERACTIVE:
123 return true;
124 case REBASING_REBASING:
125 return true;
126 case REBASING_MERGE:
127 return true;
128 default:
129 return false;
132 if ("canContinueRebase".equals(property)) //$NON-NLS-1$
133 switch (state) {
134 case REBASING_INTERACTIVE:
135 return true;
136 case REBASING_MERGE:
137 return true;
138 default:
139 return false;
142 // isSTATE checks repository state where STATE is the CamelCase version
143 // of the RepositoryState enum values.
144 if (property.length() > 3 && property.startsWith("is")) { //$NON-NLS-1$
145 // e.g. isCherryPickingResolved => CHERRY_PICKING_RESOLVED
146 String lookFor = property.substring(2, 3)
147 + property.substring(3).replaceAll("([A-Z])", "_$1") //$NON-NLS-1$//$NON-NLS-2$
148 .toUpperCase(Locale.ROOT);
149 if (state.toString().equals(lookFor))
150 return true;
152 // invokes test methods of RepositoryState, canCommit etc
153 try {
154 Method method = RepositoryState.class.getMethod(property);
155 if (method.getReturnType() == boolean.class) {
156 Boolean ret = (Boolean) method.invoke(state);
157 return ret.booleanValue();
159 } catch (Exception e) {
160 // ignore
163 return false;
167 * @param repository
168 * @return {@code true} if repository has been configured for Gerrit
170 public static boolean hasGerritConfiguration(
171 @NonNull Repository repository) {
172 Config config = repository.getConfig();
173 if (GerritUtil.getCreateChangeId(config)) {
174 return true;
176 try {
177 List<RemoteConfig> remoteConfigs = RemoteConfig.getAllRemoteConfigs(config);
178 for (RemoteConfig remoteConfig : remoteConfigs) {
179 if (GerritUtil.isGerritPush(remoteConfig)
180 || GerritUtil.isGerritFetch(remoteConfig)) {
181 return true;
184 } catch (URISyntaxException e) {
185 // Assume it doesn't contain Gerrit configuration
186 return false;
188 return false;
192 * @param repository
193 * @return {@code true} if repository has been configured to fetch from
194 * Gerrit
196 public static boolean canFetchFromGerrit(@NonNull Repository repository) {
197 Config config = repository.getConfig();
198 try {
199 List<RemoteConfig> remoteConfigs = RemoteConfig
200 .getAllRemoteConfigs(config);
201 for (RemoteConfig remoteConfig : remoteConfigs) {
202 if (GerritUtil.isGerritFetch(remoteConfig)) {
203 return true;
206 } catch (URISyntaxException e) {
207 return false;
209 return false;
213 * @param repository
214 * @return {@code true} if repository has been configured for pushing to
215 * Gerrit
217 public static boolean canPushToGerrit(@NonNull Repository repository) {
218 Config config = repository.getConfig();
219 try {
220 List<RemoteConfig> remoteConfigs = RemoteConfig
221 .getAllRemoteConfigs(config);
222 for (RemoteConfig remoteConfig : remoteConfigs) {
223 if (GerritUtil.isGerritPush(remoteConfig)) {
224 return true;
227 } catch (URISyntaxException e) {
228 return false;
230 return false;