From 97d3afed7f416bc3c0740b05974949ea38520c7e Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 28 Dec 2011 20:09:46 -0500
Subject: [PATCH] Manager support for hook script inheritance

---
 src/com/gitblit/client/GitblitClient.java     |  113 ++++++++++++++++++++++++++++++++++++-
 src/com/gitblit/client/EditTeamDialog.java    |   41 +++++++++++++
 src/com/gitblit/client/RepositoriesPanel.java |   10 ++-
 src/com/gitblit/client/TeamsPanel.java        |    6 ++
 src/com/gitblit/RpcServlet.java               |    6 +-
 5 files changed, 165 insertions(+), 11 deletions(-)

diff --git a/src/com/gitblit/RpcServlet.java b/src/com/gitblit/RpcServlet.java
index c33bd8a..2d51388 100644
--- a/src/com/gitblit/RpcServlet.java
+++ b/src/com/gitblit/RpcServlet.java
@@ -276,7 +276,7 @@
 			}
 		} else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {
 			// return the server's settings
-			ServerSettings settings = GitBlit.self().getSettingsModel();			
+			ServerSettings settings = GitBlit.self().getSettingsModel();
 			if (allowAdmin) {
 				// return all settings
 				result = settings;
@@ -294,12 +294,12 @@
 					keys.add(Keys.federation.sets);
 				}
 				// build the settings
-				ServerSettings managementSettings = new ServerSettings();				
+				ServerSettings managementSettings = new ServerSettings();
 				for (String key : keys) {
 					managementSettings.add(settings.get(key));
 				}
 				if (allowManagement) {
-					settings.pushScripts = settings.pushScripts;
+					managementSettings.pushScripts = settings.pushScripts;
 				}
 				result = managementSettings;
 			}
diff --git a/src/com/gitblit/client/EditTeamDialog.java b/src/com/gitblit/client/EditTeamDialog.java
index a04ed2c..49669e2 100644
--- a/src/com/gitblit/client/EditTeamDialog.java
+++ b/src/com/gitblit/client/EditTeamDialog.java
@@ -71,6 +71,10 @@
 
 	private JPalette<String> userPalette;
 
+	private JPalette<String> preReceivePalette;
+
+	private JPalette<String> postReceivePalette;
+
 	private Set<String> teamnames;
 
 	public EditTeamDialog(int protocolVersion, ServerSettings settings) {
@@ -141,10 +145,24 @@
 		};
 		usersPanel.add(userPalette, BorderLayout.CENTER);
 
+		preReceivePalette = new JPalette<String>(true);
+		JPanel preReceivePanel = new JPanel(new BorderLayout(5, 5));
+		preReceivePanel.add(
+				newFieldPanel(Translation.get("gb.preReceiveScripts"), preReceivePalette),
+				BorderLayout.CENTER);
+
+		postReceivePalette = new JPalette<String>(true);
+		JPanel postReceivePanel = new JPanel(new BorderLayout(5, 5));
+		postReceivePanel.add(
+				newFieldPanel(Translation.get("gb.postReceiveScripts"), postReceivePalette),
+				BorderLayout.CENTER);
+
 		JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);
 		panel.addTab(Translation.get("gb.general"), fieldsPanelTop);
 		panel.addTab(Translation.get("gb.teamMembers"), usersPanel);
 		panel.addTab(Translation.get("gb.restrictedRepositories"), repositoriesPanel);
+		panel.addTab(Translation.get("gb.preReceiveScripts"), preReceivePanel);
+		panel.addTab(Translation.get("gb.postReceiveScripts"), postReceivePanel);
 
 		JButton createButton = new JButton(Translation.get("gb.save"));
 		createButton.addActionListener(new ActionListener() {
@@ -241,6 +259,13 @@
 
 		team.users.clear();
 		team.users.addAll(userPalette.getSelections());
+
+		team.preReceiveScripts.clear();
+		team.preReceiveScripts.addAll(preReceivePalette.getSelections());
+
+		team.postReceiveScripts.clear();
+		team.postReceiveScripts.addAll(postReceivePalette.getSelections());
+
 		return true;
 	}
 
@@ -278,6 +303,22 @@
 		userPalette.setObjects(users, selected);
 	}
 
+	public void setPreReceiveScripts(List<String> unused, List<String> selected) {
+		Collections.sort(unused);
+		if (selected != null) {
+			Collections.sort(selected);
+		}
+		preReceivePalette.setObjects(unused, selected);
+	}
+
+	public void setPostReceiveScripts(List<String> unused, List<String> selected) {
+		Collections.sort(unused);
+		if (selected != null) {
+			Collections.sort(selected);
+		}
+		postReceivePalette.setObjects(unused, selected);
+	}
+
 	public TeamModel getTeam() {
 		if (canceled) {
 			return null;
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index f9af8df..d37ee91 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -21,9 +21,11 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 import com.gitblit.Constants;
 import com.gitblit.GitBlitException.ForbiddenException;
@@ -183,11 +185,105 @@
 		}
 	}
 
-	public List<String> getAvailableScripts() {
-		if (settings.pushScripts == null) {
-			return new ArrayList<String>();
+	/**
+	 * Returns the list of pre-receive scripts the repository inherited from the
+	 * global settings and team affiliations.
+	 * 
+	 * @param repository
+	 *            if null only the globally specified scripts are returned
+	 * @return a list of scripts
+	 */
+	public List<String> getPreReceiveScriptsInherited(RepositoryModel repository) {
+		Set<String> scripts = new LinkedHashSet<String>();
+		// Globals
+		for (String script : settings.get(Keys.groovy.preReceiveScripts).getStrings()) {
+			if (script.endsWith(".groovy")) {
+				scripts.add(script.substring(0, script.lastIndexOf('.')));
+			} else {
+				scripts.add(script);
+			}
 		}
-		return settings.pushScripts;
+
+		// Team Scripts
+		if (repository != null) {
+			for (String teamname : getPermittedTeamnames(repository)) {
+				TeamModel team = getTeamModel(teamname);
+				scripts.addAll(team.preReceiveScripts);
+			}
+		}
+		return new ArrayList<String>(scripts);
+	}
+
+	/**
+	 * Returns the list of all available Groovy pre-receive push hook scripts
+	 * that are not already inherited by the repository. Script files must have
+	 * .groovy extension
+	 * 
+	 * @param repository
+	 *            optional parameter
+	 * @return list of available hook scripts
+	 */
+	public List<String> getPreReceiveScriptsUnused(RepositoryModel repository) {
+		Set<String> inherited = new TreeSet<String>(getPreReceiveScriptsInherited(repository));
+
+		// create list of available scripts by excluding inherited scripts
+		List<String> scripts = new ArrayList<String>();
+		for (String script : settings.pushScripts) {
+			if (!inherited.contains(script)) {
+				scripts.add(script);
+			}
+		}
+		return scripts;
+	}
+
+	/**
+	 * Returns the list of post-receive scripts the repository inherited from
+	 * the global settings and team affiliations.
+	 * 
+	 * @param repository
+	 *            if null only the globally specified scripts are returned
+	 * @return a list of scripts
+	 */
+	public List<String> getPostReceiveScriptsInherited(RepositoryModel repository) {
+		Set<String> scripts = new LinkedHashSet<String>();
+		// Global Scripts
+		for (String script : settings.get(Keys.groovy.postReceiveScripts).getStrings()) {
+			if (script.endsWith(".groovy")) {
+				scripts.add(script.substring(0, script.lastIndexOf('.')));
+			} else {
+				scripts.add(script);
+			}
+		}
+		// Team Scripts
+		if (repository != null) {
+			for (String teamname : getPermittedTeamnames(repository)) {
+				TeamModel team = getTeamModel(teamname);
+				scripts.addAll(team.postReceiveScripts);
+			}
+		}
+		return new ArrayList<String>(scripts);
+	}
+
+	/**
+	 * Returns the list of unused Groovy post-receive push hook scripts that are
+	 * not already inherited by the repository. Script files must have .groovy
+	 * extension
+	 * 
+	 * @param repository
+	 *            optional parameter
+	 * @return list of available hook scripts
+	 */
+	public List<String> getPostReceiveScriptsUnused(RepositoryModel repository) {
+		Set<String> inherited = new TreeSet<String>(getPostReceiveScriptsInherited(repository));
+
+		// create list of available scripts by excluding inherited scripts
+		List<String> scripts = new ArrayList<String>();
+		for (String script : settings.pushScripts) {
+			if (!inherited.contains(script)) {
+				scripts.add(script);
+			}
+		}
+		return scripts;
 	}
 
 	public ServerSettings getSettings() {
@@ -393,6 +489,15 @@
 		}
 		return teamnames;
 	}
+	
+	public TeamModel getTeamModel(String name) {
+		for (TeamModel team : allTeams) {
+			if (team.name.equalsIgnoreCase(name)) {
+				return team;
+			}
+		}
+		return null;
+	}
 
 	public List<String> getFederationSets() {
 		return settings.get(Keys.federation.sets).getStrings();
diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java
index 2994b76..50284be 100644
--- a/src/com/gitblit/client/RepositoriesPanel.java
+++ b/src/com/gitblit/client/RepositoriesPanel.java
@@ -357,8 +357,8 @@
 		dialog.setTeams(gitblit.getTeamnames(), null);
 		dialog.setRepositories(gitblit.getRepositories());
 		dialog.setFederationSets(gitblit.getFederationSets(), null);
-		dialog.setPreReceiveScripts(gitblit.getAvailableScripts(), null);
-		dialog.setPostReceiveScripts(gitblit.getAvailableScripts(), null);
+		dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(null), null);
+		dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(null), null);
 		dialog.setVisible(true);
 		final RepositoryModel newRepository = dialog.getRepository();
 		final List<String> permittedUsers = dialog.getPermittedUsers();
@@ -417,8 +417,10 @@
 		dialog.setTeams(gitblit.getTeamnames(), gitblit.getPermittedTeamnames(repository));
 		dialog.setRepositories(gitblit.getRepositories());
 		dialog.setFederationSets(gitblit.getFederationSets(), repository.federationSets);
-		dialog.setPreReceiveScripts(gitblit.getAvailableScripts(), repository.preReceiveScripts);
-		dialog.setPostReceiveScripts(gitblit.getAvailableScripts(), repository.postReceiveScripts);
+		dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(repository),
+				repository.preReceiveScripts);
+		dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(repository),
+				repository.postReceiveScripts);
 		dialog.setVisible(true);
 		final RepositoryModel revisedRepository = dialog.getRepository();
 		final List<String> permittedUsers = dialog.getPermittedUsers();
diff --git a/src/com/gitblit/client/TeamsPanel.java b/src/com/gitblit/client/TeamsPanel.java
index 2d1d914..b2a1873 100644
--- a/src/com/gitblit/client/TeamsPanel.java
+++ b/src/com/gitblit/client/TeamsPanel.java
@@ -257,6 +257,8 @@
 		dialog.setTeams(gitblit.getTeams());
 		dialog.setRepositories(gitblit.getRepositories(), null);
 		dialog.setUsers(gitblit.getUsernames(), null);
+		dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(null), null);
+		dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(null), null);
 		dialog.setVisible(true);
 		final TeamModel newTeam = dialog.getTeam();
 		if (newTeam == null) {
@@ -304,6 +306,10 @@
 		dialog.setRepositories(gitblit.getRepositories(), new ArrayList<String>(team.repositories));
 		dialog.setUsers(gitblit.getUsernames(), team.users == null ? null : new ArrayList<String>(
 				team.users));
+		dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(null),
+				team.preReceiveScripts);
+		dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(null),
+				team.postReceiveScripts);
 		dialog.setVisible(true);
 		final TeamModel revisedTeam = dialog.getTeam();
 		if (revisedTeam == null) {

--
Gitblit v1.9.1