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
9 * Mathias Kinzler (SAP AG) - initial implementation
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
;
14 import java
.io
.IOException
;
15 import java
.util
.Date
;
16 import java
.util
.HashMap
;
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
;
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
>();
37 * Clients should obtain an instance from {@link Activator}
44 * Used by {@link Activator}
47 commitMappingCache
.clear();
48 repositoryNameCache
.clear();
52 * Tries to map a commit to a symbolic reference.
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"
58 * Since this mapping is not unique, the following precedence rules are
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
65 * <li>If there are still ambiguities, the reference name with the highest
66 * lexicographic value will be returned</li>
70 * the {@link Repository}
74 * if true, the cache will be invalidated
75 * @return the symbolic reference, or <code>null</code> if no such reference
78 public String
mapCommitToRef(Repository repository
, String commitId
,
81 synchronized (commitMappingCache
) {
83 if (!ObjectId
.isId(commitId
)) {
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(),
102 Map
<String
, Date
> tagMap
= new HashMap
<String
, Date
>();
104 Map
<String
, Ref
> tags
= repository
.getRefDatabase().getRefs(
106 for (Ref tagRef
: tags
.values()) {
107 Tag tag
= repository
.mapTag(tagRef
.getName());
108 if (tag
.getObjId().name().equals(commitId
)) {
110 if (tag
.getTagger() != null) {
111 timestamp
= tag
.getTagger().getWhen();
115 tagMap
.put(tagRef
.getName(), timestamp
);
118 } catch (IOException e
) {
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
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
) {
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
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
) {
189 cacheEntry
.put(commitId
, cacheValue
);
195 * Return a cached UI "name" for a Repository
197 * This uses the name of the parent of the repository's directory.
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()
211 name
= gitDir
.getParentFile().getName();
212 repositoryNameCache
.put(gitDir
.getPath().toString(), name
);
216 return ""; //$NON-NLS-1$