From 2cdb73b442169b48da1588ab7cfaac7256677a5e Mon Sep 17 00:00:00 2001
From: Philip L. McMahon <philip.l.mcmahon@gmail.com>
Date: Sat, 28 Jan 2012 13:57:39 -0500
Subject: [PATCH] RepositoryModel will use String rather than RefModel to track the current symbolic head and available heads.
---
src/com/gitblit/utils/JGitUtils.java | 86 ++++++++++++++++++++++++++++++-------------
1 files changed, 60 insertions(+), 26 deletions(-)
diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java
index 05c0852..6470634 100644
--- a/src/com/gitblit/utils/JGitUtils.java
+++ b/src/com/gitblit/utils/JGitUtils.java
@@ -1156,49 +1156,60 @@
}
/**
- * Returns the default HEAD for a repository. Normally returns the ref HEAD points to, but if HEAD points to nothing
- * it returns null.
+ * Returns the target of the symbolic HEAD reference for a repository.
+ * Normally returns a branch reference name, but when HEAD is detached,
+ * the commit is matched against the known tags. The most recent matching
+ * tag ref name will be returned if it references the HEAD commit. If
+ * no match is found, the SHA1 is returned.
*
* @param repository
- * @return the refmodel for HEAD or null
+ * @return the ref name or the SHA1 for detached HEADs
*/
- public static RefModel getDefaultHead(Repository repository) {
- RefModel ref = null;
+ public static String getSymbolicHeadTarget(Repository repository) {
+ String target = null;
try {
- Ref head = repository.getRef(Constants.HEAD);
- if (head != null) {
- Ref target = head.getTarget();
- RevWalk rw = new RevWalk(repository);
- ObjectId targetId = target.getObjectId();
- if (targetId != null) {
- RevObject object = rw.parseAny(targetId);
- ref = new RefModel(target.getName(), target, object);
+ target = repository.getFullBranch();
+ if (!target.startsWith(Constants.R_HEADS)) {
+ // refers to an actual commit, probably a tag
+ // find latest tag that matches the commit, if any
+ List<RefModel> tagModels = getTags(repository, true, -1);
+ if (tagModels.size() > 0) {
+ RefModel tag = null;
+ Date lastDate = new Date(0);
+ for (RefModel tagModel : tagModels) {
+ if (tagModel.getReferencedObjectId().getName().equals(target) &&
+ tagModel.getDate().after(lastDate)) {
+ tag = tagModel;
+ lastDate = tag.getDate();
+ }
+ }
+ target = tag.getName();
}
- rw.dispose();
}
} catch (Throwable t) {
- LOGGER.error("Failed to get default head!", t);
+ error(t, repository, "{0} failed to get symbolic HEAD target");
}
- return ref;
+ return target;
}
-
+
/**
- * Sets the default HEAD symbolic ref for a repository.
+ * Sets the HEAD symbolic ref name for a repository. The HEAD will
+ * be detached if the name does not reference a branch.
*
* @param repository
- * @param ref
+ * @param name
*/
- public static void setDefaultHead(Repository repository, Ref ref) {
+ public static void setSymbolicHeadTarget(Repository repository, String name) {
try {
- boolean detach = !ref.getName().startsWith(Constants.R_HEADS); // detach if not a branch
+ boolean detach = !name.startsWith(Constants.R_HEADS); // detach if not a branch
RefUpdate.Result result;
RefUpdate head = repository.updateRef(Constants.HEAD, detach);
if (detach) { // Tag
- RevCommit commit = getCommit(repository, ref.getObjectId().getName());
+ RevCommit commit = getCommit(repository, name);
head.setNewObjectId(commit.getId());
result = head.forceUpdate();
} else {
- result = head.link(ref.getName());
+ result = head.link(name);
}
switch (result) {
case NEW:
@@ -1207,13 +1218,36 @@
case FAST_FORWARD:
break;
default:
- LOGGER.error(MessageFormat.format("{0} failed to set default head to {1} ({2})",
- repository.getDirectory().getAbsolutePath(), ref.getName(), result));
+ LOGGER.error(MessageFormat.format("{0} symbolic HEAD update to {1} returned result {2}",
+ repository.getDirectory().getAbsolutePath(), name, result));
}
} catch (Throwable t) {
- error(t, repository, "{0} failed to set default head to {1}", ref.getName());
+ error(t, repository, "{0} failed to set symbolic HEAD to {1}", name);
}
}
+
+ /**
+ * Get the full branch and tag ref names for any potential symbolic head targets.
+ *
+ * @param repository
+ * @return a list of ref names
+ */
+ public static List<String> getAvailableHeadTargets(Repository repository) {
+ List<String> targets = new ArrayList<String>();
+ List<RefModel> branchModels = JGitUtils.getLocalBranches(repository, true, -1);
+ if (branchModels.size() > 0) {
+ for (RefModel branchModel : branchModels) {
+ targets.add(branchModel.getName());
+ }
+ }
+ List<RefModel> tagModels = JGitUtils.getTags(repository, true, -1);
+ if (tagModels.size() > 0) {
+ for (RefModel tagModel : tagModels) {
+ targets.add(tagModel.getName());
+ }
+ }
+ return targets;
+ }
/**
* Returns all refs grouped by their associated object id.
--
Gitblit v1.9.1