/*******************************************************************************
* Copyright (c) 2011, 2014 Benjamin Muskalla and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Benjamin Muskalla <bmuskalla@tasktop.com> - initial API and implementation
*******************************************************************************/
package org.eclipse.egit.ui.internal;
import java.io.IOException;
import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.clone.ProjectRecord;
import org.eclipse.egit.ui.internal.repository.tree.RefNode;
import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject;
import org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.osgi.util.NLS;
/**
* Various methods to compute label for different Git repository elements.
*/
public class GitLabels {
private GitLabels() {
}
/**
* @param ref
* @return a description of the ref, or null if the ref does not have a
* description
*/
public static String getRefDescription(Ref ref) {
String name = ref.getName();
if (name.equals(Constants.HEAD)) {
if (ref.isSymbolic())
return UIText.GitLabelProvider_RefDescriptionHeadSymbolic;
else
return UIText.GitLabelProvider_RefDescriptionHead;
} else if (name.equals(Constants.ORIG_HEAD))
return UIText.GitLabelProvider_RefDescriptionOrigHead;
else if (name.equals(Constants.FETCH_HEAD))
return UIText.GitLabelProvider_RefDescriptionFetchHead;
else if (name.equals(Constants.R_STASH))
return UIText.GitLabelProvider_RefDescriptionStash;
else
return null;
}
/**
* 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) {
// UPWARDS ARROW
sb.append('\u2191');
sb.append(ahead);
}
if (behind != 0) {
if (sb.length() != 0)
sb.append(' ');
// DOWNWARDS ARROW
sb.append('\u2193');
sb.append(status.getBehindCount());
}
return sb.toString();
}
/**
* Returns a {@link StyledString} that is initialized with "> " if the
* repository has any changes, empty otherwise.
*
* @param repository
* to get the string for
* @return the {@link StyledString}
*/
public static @NonNull StyledString getChangedPrefix(
@NonNull Repository repository) {
StyledString string = new StyledString();
if (RepositoryUtil.hasChanges(repository)) {
string.append('>', StyledString.DECORATIONS_STYLER);
string.append(' ');
}
return string;
}
/**
* Computes detailed repository label that consists of repository name,
* state, checked-out branch and it's status (returned by
* {@linkplain #formatBranchTrackingStatus(BranchTrackingStatus)})
*
* @param repository
* @return a styled string for the repository
* @throws IOException
*/
public static @NonNull StyledString getStyledLabel(
@NonNull Repository repository)
throws IOException {
RepositoryUtil repositoryUtil = Activator.getDefault()
.getRepositoryUtil();
StyledString string = getChangedPrefix(repository);
string.append(repositoryUtil.getRepositoryName(repository));
String branch = repositoryUtil.getShortBranch(repository);
if (branch != null) {
string.append(' ');
string.append('[', StyledString.DECORATIONS_STYLER);
string.append(branch, StyledString.DECORATIONS_STYLER);
BranchTrackingStatus trackingStatus = BranchTrackingStatus.of(
repository, branch);
if (trackingStatus != null
&& (trackingStatus.getAheadCount() != 0 || trackingStatus
.getBehindCount() != 0)) {
String formattedTrackingStatus = GitLabels
.formatBranchTrackingStatus(trackingStatus);
string.append(' ');
string.append(formattedTrackingStatus,
StyledString.DECORATIONS_STYLER);
}
RepositoryState repositoryState = repository.getRepositoryState();
if (repositoryState != RepositoryState.SAFE) {
string.append(" - ", StyledString.DECORATIONS_STYLER); //$NON-NLS-1$
string.append(repositoryState.getDescription(),
StyledString.DECORATIONS_STYLER);
}
string.append(']', StyledString.DECORATIONS_STYLER);
}
return string;
}
/**
* Tries to return label produced by
* {@linkplain #getStyledLabel(Repository)}. If
* {@linkplain #getStyledLabel(Repository)} throws <code>Exception</code>
* then logs it and falls back to {@linkplain #getPlainShortLabel(Object)}
* result.
*
* @param repository
* @return repository label
*/
public static @NonNull StyledString getStyledLabelSafe(
@NonNull Repository repository) {
try {
return getStyledLabel(repository);
} catch (IOException e) {
logLabelRetrievalFailure(repository, e);
}
return new StyledString(getPlainShortLabel(repository));
}
/**
* <p>
* If the <code>element</code> represents a repository then tries to return
* it's styled label (created by {@link #getStyledLabel(Repository)}). If
* the <code>element</code> is not a repository or if
* {@link #getStyledLabel(Repository)} threw <code>IOException</code> then
* this method returns element's simple label (
* {@link #getPlainShortLabel(Object)}). If the element is a repository then
* the returned label is appended with absolute path to this repository.
* </p>
* <p>
* IOException thrown by {@link #getStyledLabel(Repository)} is logged.
* </p>
*
* @param element
* @return element's label
*/
public static @NonNull StyledString getStyledLabelExtendedSafe(
Object element) {
Repository repo = asRepository(element);
if (repo != null) {
try {
StyledString text = getStyledLabel(repo);
text.append(getLabelExtension(repo),
StyledString.QUALIFIER_STYLER);
return text;
} catch (IOException e) {
logLabelRetrievalFailure(element, e);
}
}
return new StyledString(getPlainShortLabelExtended(element));
}
/**
* @param element
* @return label computed by {@linkplain #getPlainShortLabel(Object)} with
* appended path to the repository if element represents a
* repository
*/
public static String getPlainShortLabelExtended(Object element) {
return getPlainShortLabel(element) + getLabelExtension(element);
}
private static void logLabelRetrievalFailure(Object element, IOException e) {
Activator.logError(
NLS.bind(UIText.GitLabelProvider_UnableToRetrieveLabel,
element.toString()), e);
}
private static String getLabelExtension(Object element) {
Repository repo = asRepository(element);
if (repo != null)
return " - " + getRepositoryAbsolutePath(repo); //$NON-NLS-1$
else
return ""; //$NON-NLS-1$
}
/**
* @param element
* @return simple short label of the Git element (repository, reference,
* changeset, etc.).
*/
public static String getPlainShortLabel(Object element) {
if (element instanceof Repository)
return getRepositorySimpleLabel((Repository) element);
if (element instanceof RefNode)
return getRefNodeSimpleLabel((RefNode) element);
if (element instanceof Ref)
return ((Ref) element).getName();
if (element instanceof ProjectRecord)
return ((ProjectRecord) element).getProjectLabel();
if (element instanceof GitModelObject)
return ((GitModelObject) element).getName();
return (element != null ? element.toString() : ""); //$NON-NLS-1$
}
private static String getRefNodeSimpleLabel(RefNode refNode) {
return refNode.getObject().getName();
}
private static String getRepositorySimpleLabel(Repository repository) {
return Activator.getDefault().getRepositoryUtil()
.getRepositoryName(repository);
}
private static String getRepositoryAbsolutePath(Repository repository) {
return repository.getDirectory().getAbsolutePath();
}
private static Repository asRepository(Object element) {
if (element instanceof Repository)
return (Repository) element;
else if (element instanceof GitModelRepository)
return ((GitModelRepository) element).getRepository();
else
return null;
}
}