From 9129381d7a55c0dfae625b2b07fe1e04409df6a3 Mon Sep 17 00:00:00 2001
From: Philip L. McMahon <philip.l.mcmahon@gmail.com>
Date: Fri, 27 Jan 2012 00:20:21 -0500
Subject: [PATCH] Allow administrative modification of the default branch/tag referenced by HEAD.

---
 src/com/gitblit/GitBlit.java                         |    8 ++++
 src/com/gitblit/wicket/GitBlitWebApp.properties      |    2 +
 src/com/gitblit/wicket/pages/EditRepositoryPage.java |   19 +++++++++
 src/com/gitblit/models/RepositoryModel.java          |    2 +
 src/com/gitblit/wicket/pages/EditRepositoryPage.html |    1 
 src/com/gitblit/utils/JGitUtils.java                 |   44 ++++++++++++++++++++++
 6 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index bf3660d..b6bf7bf 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -69,6 +69,7 @@
 import com.gitblit.models.FederationProposal;
 import com.gitblit.models.FederationSet;
 import com.gitblit.models.Metric;
+import com.gitblit.models.RefModel;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.ServerSettings;
 import com.gitblit.models.ServerStatus;
@@ -786,6 +787,10 @@
 			model.mailingLists = new ArrayList<String>(Arrays.asList(config.getStringList(
 					"gitblit", null, "mailingList")));
 		}
+		model.defaultHead = JGitUtils.getDefaultHead(r);
+		model.availableHeads = new ArrayList<RefModel>();
+		model.availableHeads.addAll(JGitUtils.getLocalBranches(r, true, -1));
+		model.availableHeads.addAll(JGitUtils.getTags(r, true, -1));
 		r.close();
 		return model;
 	}
@@ -981,6 +986,9 @@
 		// update settings
 		if (r != null) {
 			updateConfiguration(r, repository);
+			if (repository.defaultHead != null) {
+				JGitUtils.setDefaultHead(r, repository.defaultHead.reference);
+			}
 			r.close();
 		}
 	}
diff --git a/src/com/gitblit/models/RepositoryModel.java b/src/com/gitblit/models/RepositoryModel.java
index ad0adaa..d3e9158 100644
--- a/src/com/gitblit/models/RepositoryModel.java
+++ b/src/com/gitblit/models/RepositoryModel.java
@@ -58,6 +58,8 @@
 	public List<String> preReceiveScripts;
 	public List<String> postReceiveScripts;
 	public List<String> mailingLists;
+	public RefModel defaultHead;
+	public List<RefModel> availableHeads;
 
 	private String displayName;
 	
diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java
index a540c2a..0750b07 100644
--- a/src/com/gitblit/utils/JGitUtils.java
+++ b/src/com/gitblit/utils/JGitUtils.java
@@ -1156,6 +1156,50 @@
 	}
 
 	/**
+	 * Returns the default HEAD for a repository. Normally returns the ref HEAD points to, but if HEAD points to nothing
+	 * it returns null.
+	 *
+	 * @param repository
+	 * @return the refmodel for HEAD or null
+	 */
+	public static RefModel getDefaultHead(Repository repository) {
+		RefModel ref = 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);
+				}
+				rw.dispose();
+			}
+		} catch (Throwable t) {
+			LOGGER.error("Failed to get default head!", t);
+		}
+		return ref;
+	}
+
+	/**
+	 * Sets the default HEAD symbolic ref for a repository.
+	 *
+	 * @param repository
+	 * @param ref
+	 */
+	public static void setDefaultHead(Repository repository, Ref ref) {
+		try {
+			RefUpdate head = repository.updateRef(Constants.HEAD);
+			RefUpdate.Result result = head.link(ref.getName());
+			LOGGER.debug(MessageFormat.format("Set repository {0} default head to {1} ({2})",
+					repository.getDirectory().getAbsolutePath(), ref.getName(), result));
+		} catch (IOException e) {
+			LOGGER.error("Failed to set default head!", e);
+		}
+	}
+
+	/**
 	 * Returns all refs grouped by their associated object id.
 	 * 
 	 * @param repository
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index 713fee7..b6e4523 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -131,6 +131,8 @@
 gb.sendProposal propose
 gb.status = status
 gb.origin = origin
+gb.defaultHead = default head
+gb.defaultHeadDescription = current branch after clone. e.g. refs/heads/master
 gb.federationStrategy = federation strategy
 gb.federationRegistration = federation registration
 gb.federationResults = federation pull results
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/com/gitblit/wicket/pages/EditRepositoryPage.html
index d282d10..9878930 100644
--- a/src/com/gitblit/wicket/pages/EditRepositoryPage.html
+++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.html
@@ -14,6 +14,7 @@
 				<tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input class="span6" type="text" wicket:id="name" id="name" size="40" tabindex="1" /> &nbsp;<span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td></tr>
 				<tr><th><wicket:message key="gb.description"></wicket:message></th><td class="edit"><input class="span6" type="text" wicket:id="description" size="40" tabindex="2" /></td></tr>
 				<tr><th><wicket:message key="gb.origin"></wicket:message></th><td class="edit"><input class="span7" type="text" wicket:id="origin" size="80" tabindex="3" /></td></tr>
+				<tr><th><wicket:message key="gb.defaultHead"></wicket:message></th><td class="edit"><select wicket:id="defaultHead" /> &nbsp;<span class="help-inline"><wicket:message key="gb.defaultHeadDescription"></wicket:message></span></td></tr>
 				<tr><th><wicket:message key="gb.owner"></wicket:message></th><td class="edit"><select wicket:id="owner" tabindex="4" /> &nbsp;<span class="help-inline"><wicket:message key="gb.ownerDescription"></wicket:message></span></td></tr>
 				<tr><th><wicket:message key="gb.enableTickets"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useTickets" tabindex="5" /> &nbsp;<span class="help-inline"><wicket:message key="gb.useTicketsDescription"></wicket:message></span></td></tr>
 				<tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useDocs" tabindex="6" /> &nbsp;<span class="help-inline"><wicket:message key="gb.useDocsDescription"></wicket:message></span></td></tr>
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/com/gitblit/wicket/pages/EditRepositoryPage.java
index 7d2d64c..6c04249 100644
--- a/src/com/gitblit/wicket/pages/EditRepositoryPage.java
+++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.java
@@ -45,6 +45,7 @@
 import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
 import com.gitblit.Keys;
+import com.gitblit.models.RefModel;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.ArrayUtils;
@@ -271,6 +272,9 @@
 		form.add(new CheckBox("isFrozen"));
 		// TODO enable origin definition
 		form.add(new TextField<String>("origin").setEnabled(false/* isCreate */));
+		// enable alteration of the default branch after clone
+		form.add(new DropDownChoice<RefModel>("defaultHead", repositoryModel.availableHeads,
+				new RefModelRenderer()).setEnabled(GitBlitWebSession.get().canAdmin()));
 
 		// federation strategies - remove ORIGIN choice if this repository has
 		// no origin.
@@ -361,6 +365,21 @@
 		}
 	}
 
+	private class RefModelRenderer implements IChoiceRenderer<RefModel> {
+
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public String getDisplayValue(RefModel type) {
+			return type.displayName;
+		}
+
+		@Override
+		public String getIdValue(RefModel type, int index) {
+			return type.getName();
+		}
+	}
+
 	private class AccessRestrictionRenderer implements IChoiceRenderer<AccessRestrictionType> {
 
 		private static final long serialVersionUID = 1L;

--
Gitblit v1.9.1