From a612e6af36c9c2bd2ef81d9c1697ce1543a1a9df Mon Sep 17 00:00:00 2001
From: John Crygier <john.crygier@aon.com>
Date: Sat, 31 Mar 2012 08:32:16 -0400
Subject: [PATCH] Add ClientLogger so scripts can log info / warning messages to the pushing client.

---
 groovy/blockpush.groovy                       |   14 ++++---
 src/com/gitblit/GitServlet.java               |    8 ++-
 tests/com/gitblit/tests/GroovyScriptTest.java |   66 ++++++++++++++++++++++++++++-----
 src/com/gitblit/utils/ClientLogger.java       |   32 ++++++++++++++++
 4 files changed, 101 insertions(+), 19 deletions(-)

diff --git a/groovy/blockpush.groovy b/groovy/blockpush.groovy
index a4cede3..79d696c 100644
--- a/groovy/blockpush.groovy
+++ b/groovy/blockpush.groovy
@@ -21,6 +21,7 @@
 import org.eclipse.jgit.transport.ReceiveCommand
 import org.eclipse.jgit.transport.ReceiveCommand.Result
 import org.slf4j.Logger
+import com.gitblit.utils.ClientLogger
 
 /**
  * Sample Gitblit Pre-Receive Hook: blockpush
@@ -50,12 +51,13 @@
  * chain, "return false" at the appropriate failure points.
  *
  * Bound Variables:
- *  gitblit		Gitblit Server	 		com.gitblit.GitBlit
- *  repository	Gitblit Repository		com.gitblit.models.RepositoryModel
- *  user		Gitblit User			com.gitblit.models.UserModel
- *  commands	JGit commands 			Collection<org.eclipse.jgit.transport.ReceiveCommand>
- *	url			Base url for Gitblit	String
- *  log			Logger instance			org.slf4j.Logger
+ *  gitblit			Gitblit Server	 		com.gitblit.GitBlit
+ *  repository		Gitblit Repository		com.gitblit.models.RepositoryModel
+ *  user			Gitblit User			com.gitblit.models.UserModel
+ *  clientLogger	Logs messages to client	com.gitblit.utils.ClientLogger
+ *  commands		JGit commands			Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ *	url				Base url for Gitblit	String
+ *  logger			Logger instance			org.slf4j.Logger
  *  
  */
 
diff --git a/src/com/gitblit/GitServlet.java b/src/com/gitblit/GitServlet.java
index 73c6eaa..94042c7 100644
--- a/src/com/gitblit/GitServlet.java
+++ b/src/com/gitblit/GitServlet.java
@@ -50,6 +50,7 @@
 
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.utils.ClientLogger;
 import com.gitblit.utils.FileUtils;
 import com.gitblit.utils.HttpUtils;
 import com.gitblit.utils.StringUtils;
@@ -166,7 +167,7 @@
 			scripts.addAll(GitBlit.self().getPreReceiveScriptsInherited(repository));
 			scripts.addAll(repository.preReceiveScripts);
 			UserModel user = getUserModel(rp);
-			runGroovy(repository, user, commands, scripts);
+			runGroovy(repository, user, commands, rp, scripts);
 			for (ReceiveCommand cmd : commands) {
 				if (!Result.NOT_ATTEMPTED.equals(cmd.getResult())) {
 					logger.warn(MessageFormat.format("{0} {1} because \"{2}\"", cmd.getNewId()
@@ -194,7 +195,7 @@
 			scripts.addAll(GitBlit.self().getPostReceiveScriptsInherited(repository));
 			scripts.addAll(repository.postReceiveScripts);
 			UserModel user = getUserModel(rp);
-			runGroovy(repository, user, commands, scripts);
+			runGroovy(repository, user, commands, rp, scripts);
 
 			// Experimental
 			// runNativeScript(rp, "hooks/post-receive", commands);
@@ -238,7 +239,7 @@
 		 * @param scripts
 		 */
 		protected void runGroovy(RepositoryModel repository, UserModel user,
-				Collection<ReceiveCommand> commands, Set<String> scripts) {
+				Collection<ReceiveCommand> commands, ReceivePack rp, Set<String> scripts) {
 			if (scripts == null || scripts.size() == 0) {
 				// no Groovy scripts to execute
 				return;
@@ -251,6 +252,7 @@
 			binding.setVariable("commands", commands);
 			binding.setVariable("url", gitblitUrl);
 			binding.setVariable("logger", logger);
+			binding.setVariable("clientLogger", new ClientLogger(rp));
 			for (String script : scripts) {
 				if (StringUtils.isEmpty(script)) {
 					continue;
diff --git a/src/com/gitblit/utils/ClientLogger.java b/src/com/gitblit/utils/ClientLogger.java
new file mode 100644
index 0000000..2e16fd1
--- /dev/null
+++ b/src/com/gitblit/utils/ClientLogger.java
@@ -0,0 +1,32 @@
+package com.gitblit.utils;
+
+import org.eclipse.jgit.transport.ReceivePack;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to log messages to the pushing client.  Intended to be used by
+ * the Groovy Hooks.
+ * 
+ * @author jcrygier
+ *
+ */
+public class ClientLogger {
+	
+	static final Logger logger = LoggerFactory.getLogger(ClientLogger.class);	
+	private ReceivePack rp;
+	
+	public ClientLogger(ReceivePack rp) {
+		this.rp = rp;
+	}
+	
+	/**
+	 * Sends a message to the git client.  Useful for sending INFO / WARNING messages.
+	 * 
+	 * @param message
+	 */
+	public void sendMessage(String message) {
+		rp.sendMessage(message);
+	}
+	
+}
diff --git a/tests/com/gitblit/tests/GroovyScriptTest.java b/tests/com/gitblit/tests/GroovyScriptTest.java
index 5051100..8538d64 100644
--- a/tests/com/gitblit/tests/GroovyScriptTest.java
+++ b/tests/com/gitblit/tests/GroovyScriptTest.java
@@ -20,7 +20,9 @@
 import groovy.lang.Binding;
 import groovy.util.GroovyScriptEngine;
 
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileWriter;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -69,6 +71,7 @@
 	public void testSendMail() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		commands.add(new ReceiveCommand(ObjectId
 				.fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
@@ -80,7 +83,7 @@
 		RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git");
 		repository.mailingLists.add("list@helloworld.git");
 
-		test("sendmail.groovy", gitblit, logger, commands, repository);
+		test("sendmail.groovy", gitblit, logger, clientLogger, commands, repository);
 		assertEquals(1, logger.messages.size());
 		assertEquals(1, gitblit.messages.size());
 		MockMail m = gitblit.messages.get(0);
@@ -92,26 +95,28 @@
 	public void testProtectRefsCreateBranch() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		commands.add(new ReceiveCommand(ObjectId.zeroId(), ObjectId
 				.fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master"));
 		
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
-		test("protect-refs.groovy", gitblit, logger, commands, repository);
+		test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository);
 	}
 	
 	@Test
 	public void testProtectRefsCreateTag() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		commands.add(new ReceiveCommand(ObjectId.zeroId(), ObjectId
 				.fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/tags/v1.0"));
 		
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
-		test("protect-refs.groovy", gitblit, logger, commands, repository);
+		test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository);
 		assertEquals(0, logger.messages.size());
 	}
 	
@@ -119,6 +124,7 @@
 	public void testProtectRefsFastForward() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		commands.add(new ReceiveCommand(ObjectId
 				.fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
@@ -126,7 +132,7 @@
 		
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
-		test("protect-refs.groovy", gitblit, logger, commands, repository);
+		test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository);
 		assertEquals(0, logger.messages.size());
 	}
 	
@@ -134,6 +140,7 @@
 	public void testProtectRefsDeleteMasterBranch() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		ReceiveCommand command = new ReceiveCommand(ObjectId
 				.fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), ObjectId.zeroId(),
@@ -142,7 +149,7 @@
 		
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
-		test("protect-refs.groovy", gitblit, logger, commands, repository);
+		test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository);
 		assertEquals(ReceiveCommand.Result.REJECTED_NODELETE, command.getResult());
 		assertEquals(0, logger.messages.size());
 	}
@@ -151,6 +158,7 @@
 	public void testProtectRefsDeleteOtherBranch() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		commands.add(new ReceiveCommand(ObjectId
 				.fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), ObjectId.zeroId(),
@@ -158,7 +166,7 @@
 		
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
-		test("protect-refs.groovy", gitblit, logger, commands, repository);
+		test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository);
 		assertEquals(0, logger.messages.size());
 	}
 	
@@ -166,6 +174,7 @@
 	public void testProtectRefsDeleteTag() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		ReceiveCommand command = new ReceiveCommand(ObjectId
 				.fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), ObjectId.zeroId(),
@@ -174,7 +183,7 @@
 		
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
-		test("protect-refs.groovy", gitblit, logger, commands, repository);
+		test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository);
 		assertEquals(ReceiveCommand.Result.REJECTED_NODELETE, command.getResult());
 		assertEquals(0, logger.messages.size());
 	}
@@ -183,6 +192,7 @@
 	public void testBlockPush() throws Exception {
 		MockGitblit gitblit = new MockGitblit();
 		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
 		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
 		commands.add(new ReceiveCommand(ObjectId
 				.fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
@@ -191,14 +201,41 @@
 		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());		
 
 		try {
-			test("blockpush.groovy", gitblit, logger, commands, repository);
+			test("blockpush.groovy", gitblit, logger, clientLogger, commands, repository);
 			assertTrue("blockpush should have failed!", false);
 		} catch (GitBlitException e) {
 			assertTrue(e.getMessage().contains("failed"));
 		}
 	}
+	
+	@Test
+	public void testClientLogging() throws Exception {
+		MockGitblit gitblit = new MockGitblit();
+		MockLogger logger = new MockLogger();
+		MockClientLogger clientLogger = new MockClientLogger();
+		List<ReceiveCommand> commands = new ArrayList<ReceiveCommand>();
+		commands.add(new ReceiveCommand(ObjectId
+				.fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId
+				.fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master"));
+		
+		RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date());
+		
+		File groovyDir = GitBlit.getGroovyScriptsFolder();
+		File tempScript = File.createTempFile("testClientLogging", "groovy", groovyDir);
+		tempScript.deleteOnExit();
+		
+		BufferedWriter writer = new BufferedWriter(new FileWriter(tempScript));
+		
+		writer.write("import com.gitblit.utils.ClientLogger\n");
+		writer.write("clientLogger.sendMessage('this is a test message')\n");
+		writer.flush();
+		writer.close();
 
-	private void test(String script, MockGitblit gitblit, MockLogger logger,
+		test(tempScript.getName(), gitblit, logger, clientLogger, commands, repository);
+		assertTrue("Message Missing", clientLogger.messages.contains("this is a test message"));
+	}
+
+	private void test(String script, MockGitblit gitblit, MockLogger logger, MockClientLogger clientLogger,
 			List<ReceiveCommand> commands, RepositoryModel repository) throws Exception {
 
 		UserModel user = new UserModel("mock");
@@ -215,6 +252,7 @@
 		binding.setVariable("commands", commands);
 		binding.setVariable("url", gitblitUrl);
 		binding.setVariable("logger", logger);
+		binding.setVariable("clientLogger", clientLogger);
 
 		Object result = gse.run(script, binding);
 		if (result instanceof Boolean) {
@@ -266,6 +304,14 @@
 			messages.add(message);
 		}
 	}
+	
+	class MockClientLogger {
+		List<String> messages = new ArrayList<String>();
+
+		public void sendMessage(String message) {
+			messages.add(message);
+		}
+	}
 
 	class MockMail {
 		final Collection<String> toAddresses;
@@ -284,4 +330,4 @@
 					+ message;
 		}
 	}
-}
\ No newline at end of file
+}

--
Gitblit v1.9.1