Merge branch 'stable-0.8'
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / RepositoryUtil.java
blob8d3326dba5eb64b7f6893eec4a1ca6d6fae25ae9
1 /*******************************************************************************
2 * Copyright (c) 2010 SAP AG.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
8 * Contributors:
9 * Mathias Kinzler (SAP AG) - initial implementation
10 *******************************************************************************/
11 package org.eclipse.egit.ui;
13 import java.io.File;
14 import java.io.IOException;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.TreeSet;
21 import org.eclipse.jgit.lib.Constants;
22 import org.eclipse.jgit.lib.ObjectId;
23 import org.eclipse.jgit.lib.Ref;
24 import org.eclipse.jgit.lib.Repository;
25 import org.eclipse.jgit.lib.Tag;
27 /**
28 * Utility class for handling Repositories in the UI.
30 public class RepositoryUtil {
32 private final Map<String, Map<String, String>> commitMappingCache = new HashMap<String, Map<String, String>>();
34 private final Map<String, String> repositoryNameCache = new HashMap<String, String>();
36 /**
37 * Clients should obtain an instance from {@link Activator}
39 RepositoryUtil() {
40 // nothing
43 /**
44 * Used by {@link Activator}
46 void dispose() {
47 commitMappingCache.clear();
48 repositoryNameCache.clear();
51 /**
52 * Tries to map a commit to a symbolic reference.
53 * <p>
54 * This value will be cached for the given commit ID unless refresh is
55 * specified. The return value will be the full name, e.g.
56 * "refs/remotes/someBranch", "refs/tags/v.1.0"
57 * <p>
58 * Since this mapping is not unique, the following precedence rules are
59 * used:
60 * <ul>
61 * <li>Tags take precedence over branches</li>
62 * <li>Local branches take preference over remote branches</li>
63 * <li>Newer references take precedence over older ones where time stamps
64 * are available</li>
65 * <li>If there are still ambiguities, the reference name with the highest
66 * lexicographic value will be returned</li>
67 * </ul>
69 * @param repository
70 * the {@link Repository}
71 * @param commitId
72 * a commit
73 * @param refresh
74 * if true, the cache will be invalidated
75 * @return the symbolic reference, or <code>null</code> if no such reference
76 * can be found
78 public String mapCommitToRef(Repository repository, String commitId,
79 boolean refresh) {
81 synchronized (commitMappingCache) {
83 if (!ObjectId.isId(commitId)) {
84 return null;
87 Map<String, String> cacheEntry = commitMappingCache.get(repository
88 .getDirectory().toString());
89 if (!refresh && cacheEntry != null
90 && cacheEntry.containsKey(commitId)) {
91 // this may be null in fact
92 return cacheEntry.get(commitId);
94 if (cacheEntry == null) {
95 cacheEntry = new HashMap<String, String>();
96 commitMappingCache.put(repository.getDirectory().getPath(),
97 cacheEntry);
98 } else {
99 cacheEntry.clear();
102 Map<String, Date> tagMap = new HashMap<String, Date>();
103 try {
104 Map<String, Ref> tags = repository.getRefDatabase().getRefs(
105 Constants.R_TAGS);
106 for (Ref tagRef : tags.values()) {
107 Tag tag = repository.mapTag(tagRef.getName());
108 if (tag.getObjId().name().equals(commitId)) {
109 Date timestamp;
110 if (tag.getTagger() != null) {
111 timestamp = tag.getTagger().getWhen();
112 } else {
113 timestamp = null;
115 tagMap.put(tagRef.getName(), timestamp);
118 } catch (IOException e) {
119 // ignore here
122 String cacheValue = null;
124 if (!tagMap.isEmpty()) {
125 // we try to obtain the "latest" tag
126 Date compareDate = new Date(0);
127 for (Map.Entry<String, Date> tagEntry : tagMap.entrySet()) {
128 if (tagEntry.getValue() != null
129 && tagEntry.getValue().after(compareDate)) {
130 compareDate = tagEntry.getValue();
131 cacheValue = tagEntry.getKey();
134 // if we don't have time stamps, we sort
135 if (cacheValue == null) {
136 String compareString = ""; //$NON-NLS-1$
137 for (String tagName : tagMap.keySet()) {
138 if (tagName.compareTo(compareString) >= 0) {
139 cacheValue = tagName;
140 compareString = tagName;
146 if (cacheValue == null) {
147 // we didnt't find a tag, so let's look for local branches
148 Set<String> branchNames = new TreeSet<String>();
149 // put this into a sorted set
150 try {
151 Map<String, Ref> remoteBranches = repository
152 .getRefDatabase().getRefs(Constants.R_HEADS);
153 for (Ref branch : remoteBranches.values()) {
154 if (branch.getObjectId().name().equals(commitId)) {
155 branchNames.add(branch.getName());
158 } catch (IOException e) {
159 // ignore here
161 if (!branchNames.isEmpty()) {
162 // get the last (sorted) entry
163 cacheValue = branchNames.toArray(new String[branchNames
164 .size()])[branchNames.size() - 1];
168 if (cacheValue == null) {
169 // last try: remote branches
170 Set<String> branchNames = new TreeSet<String>();
171 // put this into a sorted set
172 try {
173 Map<String, Ref> remoteBranches = repository
174 .getRefDatabase().getRefs(Constants.R_REMOTES);
175 for (Ref branch : remoteBranches.values()) {
176 if (branch.getObjectId().name().equals(commitId)) {
177 branchNames.add(branch.getName());
180 if (!branchNames.isEmpty()) {
181 // get the last (sorted) entry
182 cacheValue = branchNames.toArray(new String[branchNames
183 .size()])[branchNames.size() - 1];
185 } catch (IOException e) {
186 // ignore here
189 cacheEntry.put(commitId, cacheValue);
190 return cacheValue;
195 * Return a cached UI "name" for a Repository
196 * <p>
197 * This uses the name of the parent of the repository's directory.
199 * @param repository
200 * @return the name
202 public String getRepositoryName(Repository repository) {
203 synchronized (repositoryNameCache) {
204 File gitDir = repository.getDirectory();
205 if (gitDir != null) {
206 String name = repositoryNameCache.get(gitDir.getPath()
207 .toString());
208 if (name != null) {
209 return name;
211 name = gitDir.getParentFile().getName();
212 repositoryNameCache.put(gitDir.getPath().toString(), name);
213 return name;
216 return ""; //$NON-NLS-1$