aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Stocker2012-01-16 18:04:57 (EST)
committerMatthias Sohn2012-01-16 18:04:57 (EST)
commita15b717a4b9138fb4d11fc07a26e9f9979b0562f (patch)
tree356354a145129bdf428ccef846b6984717ffc47a
parent37cb29166bfa9abcf09db703d0e7ba5c694277c3 (diff)
downloadegit-a15b717a4b9138fb4d11fc07a26e9f9979b0562f.zip
egit-a15b717a4b9138fb4d11fc07a26e9f9979b0562f.tar.gz
egit-a15b717a4b9138fb4d11fc07a26e9f9979b0562f.tar.bz2
Show detailed branch status in label decoration of projectrefs/changes/78/4678/5
The branch status is shown after the branch name in the decoration if the current branch is different from the remote tracking branch. This is useful as a visual indication that the branch needs to be pushed (or merged/rebased). If there are commits on the branch that are not on the tracking branch, an upwards arrow (↑) followed by the number of commits is shown. This can be read as "the branch is N commits ahead" or "N commits need to be pushed". If there are commits on the tracking branch that are not on the local branch, a downwards arrow (↓) is shown, followed by the number of commits. This can be read as "the branch is N commits behind" or "N commits need to be merged". For example, if there are 2 unpushed commits on master, the project is now shown like this: project [repo master ↑2] If there are both unpushed and unmerged commits (the branches have diverged), it's shown like this: project [repo master ↑2 ↓1] In C Git, information about the tracking branch is displayed in "git status" output. EGit currently doesn't have any indication that a branch needs to be pushed, apart from the labels in History View. When there are multiple repositories involved, it can easily happen that a push is forgotten. This change helps to prevent that. This depends on JGit change I8d2b108c89905c3f0496f3d517879596740787c0. Change-Id: I1e1caca561d1b0a0c194bfc42e64b698f42c6e6a Signed-off-by: Robin Stocker <robin@nibor.org> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitLabelProvider.java33
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResource.java9
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java1
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceHelper.java18
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java22
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/IDecoratableResource.java6
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitDecoratorPreferencePage.java36
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties1
9 files changed, 115 insertions, 14 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
index 854b814..2f89cf6 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
@@ -2623,6 +2623,9 @@ public class UIText extends NLS {
public static String DecoratorPreferencesPage_bindingBranchName;
/** */
+ public static String DecoratorPreferencesPage_bindingBranchStatus;
+
+ /** */
public static String DecoratorPreferencesPage_bindingDirtyFlag;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitLabelProvider.java
index 78b732d..3bf8cae 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitLabelProvider.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitLabelProvider.java
@@ -35,6 +35,7 @@ import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jgit.lib.BranchTrackingStatus;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
@@ -55,6 +56,29 @@ public class GitLabelProvider extends LabelProvider implements
private LabelProvider workbenchLabelProvider;
+ /**
+ * Format the branch tracking status suitable for displaying in decorations and labels.
+ *
+ * @param status
+ * @return the branch tracking status as a string
+ */
+ public static String formatBranchTrackingStatus(BranchTrackingStatus status) {
+ StringBuilder sb = new StringBuilder();
+ int ahead = status.getAheadCount();
+ int behind = status.getBehindCount();
+ if (ahead != 0) {
+ sb.append('↑');
+ sb.append(ahead);
+ }
+ if (behind != 0) {
+ if (sb.length() != 0)
+ sb.append(' ');
+ sb.append('↓');
+ sb.append(status.getBehindCount());
+ }
+ return sb.toString();
+ }
+
@Override
public String getText(Object element) {
if (element instanceof Repository)
@@ -147,6 +171,15 @@ public class GitLabelProvider extends LabelProvider implements
string.append(repositoryState.getDescription(),
StyledString.DECORATIONS_STYLER);
}
+
+ BranchTrackingStatus trackingStatus = BranchTrackingStatus.of(repository, branch);
+ if (trackingStatus != null
+ && (trackingStatus.getAheadCount() != 0 || trackingStatus
+ .getBehindCount() != 0)) {
+ String formattedTrackingStatus = formatBranchTrackingStatus(trackingStatus);
+ string.append(' ');
+ string.append(formattedTrackingStatus, StyledString.DECORATIONS_STYLER);
+ }
string.append(']', StyledString.DECORATIONS_STYLER);
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResource.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResource.java
index 08bfabf..085439c 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResource.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResource.java
@@ -33,6 +33,11 @@ public class DecoratableResource implements IDecoratableResource {
protected String branch = null;
/**
+ * Branch status relative to remote tracking branch
+ */
+ protected String branchStatus = null;
+
+ /**
* Flag indicating whether or not the resource is tracked
*/
protected boolean tracked = false;
@@ -92,6 +97,10 @@ public class DecoratableResource implements IDecoratableResource {
return branch;
}
+ public String getBranchStatus() {
+ return branchStatus;
+ }
+
public boolean isTracked() {
return tracked;
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java
index 1d6c6be..382a256 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java
@@ -62,6 +62,7 @@ class DecoratableResourceAdapter extends DecoratableResource {
repositoryName = DecoratableResourceHelper
.getRepositoryName(repository);
branch = DecoratableResourceHelper.getShortBranch(repository);
+ branchStatus = DecoratableResourceHelper.getBranchStatus(repository);
switch (resource.getType()) {
case IResource.FILE:
extractResourceProperties();
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceHelper.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceHelper.java
index b8984a5..855dcf2 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceHelper.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceHelper.java
@@ -14,6 +14,8 @@ import java.io.IOException;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.internal.GitLabelProvider;
+import org.eclipse.jgit.lib.BranchTrackingStatus;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -56,4 +58,20 @@ public class DecoratableResourceHelper {
return repository.getBranch();
}
+
+ static String getBranchStatus(Repository repo) throws IOException {
+ String branchName = repo.getBranch();
+ if (branchName == null)
+ return null;
+
+ BranchTrackingStatus status = BranchTrackingStatus.of(repo, branchName);
+ if (status == null)
+ return null;
+
+ if (status.getAheadCount() == 0 && status.getBehindCount() == 0)
+ return null;
+
+ String formattedStatus = GitLabelProvider.formatBranchTrackingStatus(status);
+ return formattedStatus;
+ }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java
index a94d9c9..26238d5 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java
@@ -224,6 +224,9 @@ public class GitLightweightDecorator extends LabelProvider implements
public static final String BINDING_BRANCH_NAME = "branch"; //$NON-NLS-1$
/** */
+ public static final String BINDING_BRANCH_STATUS = "branch_status"; //$NON-NLS-1$
+
+ /** */
public static final String BINDING_REPOSITORY_NAME = "repository"; //$NON-NLS-1$
/** */
@@ -239,7 +242,7 @@ public class GitLightweightDecorator extends LabelProvider implements
public static final String FOLDER_FORMAT_DEFAULT = "{dirty:>} {name}"; //$NON-NLS-1$
/** */
- public static final String PROJECT_FORMAT_DEFAULT ="{dirty:>} {name} [{repository} {branch}]"; //$NON-NLS-1$
+ public static final String PROJECT_FORMAT_DEFAULT ="{dirty:>} {name} [{repository} {branch}{ branch_status}]"; //$NON-NLS-1$
private IPreferenceStore store;
@@ -365,6 +368,7 @@ public class GitLightweightDecorator extends LabelProvider implements
bindings.put(BINDING_RESOURCE_NAME, resource.getName());
bindings.put(BINDING_REPOSITORY_NAME, resource.getRepositoryName());
bindings.put(BINDING_BRANCH_NAME, resource.getBranch());
+ bindings.put(BINDING_BRANCH_STATUS, resource.getBranchStatus());
bindings.put(BINDING_DIRTY_FLAG, resource.isDirty() ? ">" : null); //$NON-NLS-1$
bindings.put(BINDING_STAGED_FLAG,
resource.staged() != Staged.NOT_STAGED ? "*" : null); //$NON-NLS-1$
@@ -446,6 +450,8 @@ public class GitLightweightDecorator extends LabelProvider implements
if ((start = format.indexOf('}', end)) > -1) {
String key = format.substring(end + 1, start);
String s;
+ boolean spaceBefore = false;
+ boolean spaceAfter = false;
// Allow users to override the binding
if (key.indexOf(':') > -1) {
@@ -454,8 +460,18 @@ public class GitLightweightDecorator extends LabelProvider implements
if (keyAndBinding.length > 1
&& bindings.get(key) != null)
bindings.put(key, keyAndBinding[1]);
+ } else {
+ if (key.charAt(0) == ' ') {
+ spaceBefore = true;
+ key = key.substring(1);
+ }
+ if (key.charAt(key.length() - 1) == ' ') {
+ spaceAfter = true;
+ key = key.substring(0, key.length() - 1);
+ }
}
+
// We use the BINDING_RESOURCE_NAME key to determine if
// we are doing the prefix or suffix. The name isn't
// actually part of either.
@@ -467,7 +483,11 @@ public class GitLightweightDecorator extends LabelProvider implements
}
if (s != null) {
+ if (spaceBefore)
+ output.append(' ');
output.append(s);
+ if (spaceAfter)
+ output.append(' ');
} else {
// Support removing prefix character if binding is
// null
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/IDecoratableResource.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/IDecoratableResource.java
index 6ab99a1..9875882 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/IDecoratableResource.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/IDecoratableResource.java
@@ -63,6 +63,12 @@ public interface IDecoratableResource {
String getBranch();
/**
+ * @return a symbol indicating the branch status relative to the remote
+ * tracking branch, or <code>null</code> if not applicable
+ */
+ String getBranchStatus();
+
+ /**
* Returns whether or not the resource is tracked by Git
*
* @return whether or not the resource is tracked by Git
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitDecoratorPreferencePage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitDecoratorPreferencePage.java
index 9162c62..bda054c 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitDecoratorPreferencePage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitDecoratorPreferencePage.java
@@ -115,42 +115,42 @@ public class GitDecoratorPreferencePage extends PreferencePage implements
static {
final PreviewResource project = new PreviewResource(
- "Project", IResource.PROJECT, "repository" + '|' + RepositoryState.MERGING.getDescription(), "master", true, false, true, Staged.NOT_STAGED, false, false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "Project", IResource.PROJECT, "repository" + '|' + RepositoryState.MERGING.getDescription(), "master", "↑2 ↓1", true, false, true, Staged.NOT_STAGED, false, false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
final ArrayList<PreviewResource> children = new ArrayList<PreviewResource>();
children
.add(new PreviewResource(
- "folder", IResource.FOLDER, "repository", null, true, false, true, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "folder", IResource.FOLDER, "repository", null, null, true, false, true, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "tracked.txt", IResource.FILE, "repository", null, true, false, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "tracked.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "untracked.txt", IResource.FILE, "repository", null, false, false, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "untracked.txt", IResource.FILE, "repository", null, null, false, false, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "ignored.txt", IResource.FILE, "repository", null, false, true, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "ignored.txt", IResource.FILE, "repository", null, null, false, true, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "dirty.txt", IResource.FILE, "repository", null, true, false, true, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "dirty.txt", IResource.FILE, "repository", null, null, true, false, true, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "staged.txt", IResource.FILE, "repository", null, true, false, false, Staged.MODIFIED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "staged.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.MODIFIED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "partially-staged.txt", IResource.FILE, "repository", null, true, false, true, Staged.MODIFIED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "partially-staged.txt", IResource.FILE, "repository", null, null, true, false, true, Staged.MODIFIED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "added.txt", IResource.FILE, "repository", null, true, false, false, Staged.ADDED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "added.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.ADDED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "removed.txt", IResource.FILE, "repository", null, true, false, false, Staged.REMOVED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "removed.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.REMOVED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "conflict.txt", IResource.FILE, "repository", null, true, false, true, Staged.NOT_STAGED, true, false)); //$NON-NLS-1$ //$NON-NLS-2$
+ "conflict.txt", IResource.FILE, "repository", null, null, true, false, true, Staged.NOT_STAGED, true, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
- "assume-valid.txt", IResource.FILE, "repository", null, true, false, false, Staged.NOT_STAGED, false, true)); //$NON-NLS-1$ //$NON-NLS-2$
+ "assume-valid.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.NOT_STAGED, false, true)); //$NON-NLS-1$ //$NON-NLS-2$
project.children = children;
PREVIEW_FILESYSTEM_ROOT = Collections.singleton(project);
@@ -173,6 +173,9 @@ public class GitDecoratorPreferencePage extends PreferencePage implements
UIText.GitDecoratorPreferencePage_bindingRepositoryNameFlag);
PROJECT_BINDINGS.put(DecorationHelper.BINDING_BRANCH_NAME,
UIText.DecoratorPreferencesPage_bindingBranchName);
+ PROJECT_BINDINGS.put(DecorationHelper.BINDING_BRANCH_STATUS,
+ UIText.DecoratorPreferencesPage_bindingBranchStatus);
+
CHANGESET_LABEL_BINDINGS = new HashMap<String, String>();
CHANGESET_LABEL_BINDINGS.put(removeBraces(GitChangeSetLabelProvider.BINDING_CHANGESET_AUTHOR),
@@ -998,6 +1001,8 @@ public class GitDecoratorPreferencePage extends PreferencePage implements
private final String branch;
+ private final String branchStatus;
+
private final int type;
private Collection children;
@@ -1015,12 +1020,13 @@ public class GitDecoratorPreferencePage extends PreferencePage implements
private boolean assumeValid;
public PreviewResource(String name, int type, String repositoryName, String branch,
- boolean tracked, boolean ignored, boolean dirty, Staged staged,
+ String branchStatus, boolean tracked, boolean ignored, boolean dirty, Staged staged,
boolean conflicts, boolean assumeValid) {
this.name = name;
this.repositoryName = repositoryName;
this.branch = branch;
+ this.branchStatus = branchStatus;
this.type = type;
this.children = Collections.EMPTY_LIST;
this.tracked = tracked;
@@ -1047,6 +1053,10 @@ public class GitDecoratorPreferencePage extends PreferencePage implements
return branch;
}
+ public String getBranchStatus() {
+ return branchStatus;
+ }
+
public boolean isTracked() {
return tracked;
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
index 62d2323..d690a02 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
@@ -907,6 +907,7 @@ DecoratorPreferencesPage_labelDecorationsLink=See <a>''{0}''</a> to enable or di
DecoratorPreferencesPage_generalTabFolder=&General
DecoratorPreferencesPage_bindingResourceName=Name of the resource being decorated
DecoratorPreferencesPage_bindingBranchName=Current branch of the repository
+DecoratorPreferencesPage_bindingBranchStatus=Branch status (compared to remote-tracking)
DecoratorPreferencesPage_bindingDirtyFlag=Flag indicating whether or not the resource is dirty
DecoratorPreferencesPage_bindingStagedFlag=Flag indicating whether or not the resource is staged
DecoratorPreferencesPage_selectVariablesToAdd=Select the &variables to add to the decoration format: