aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Stocker2012-01-16 18:04:57 -0500
committerMatthias Sohn2012-01-16 18:04:57 -0500
commita15b717a4b9138fb4d11fc07a26e9f9979b0562f (patch)
tree356354a145129bdf428ccef846b6984717ffc47a
parent37cb29166bfa9abcf09db703d0e7ba5c694277c3 (diff)
downloadegit-a15b717a4b9138fb4d11fc07a26e9f9979b0562f.zip
egit-a15b717a4b9138fb4d11fc07a26e9f9979b0562f.tar.gz
egit-a15b717a4b9138fb4d11fc07a26e9f9979b0562f.tar.xz
Show detailed branch status in label decoration of project
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: