Add example git and svn hook scripts
authorChuck Hagenbuch <chuck@horde.org>
Mon, 30 Aug 2010 01:11:16 +0000 (21:11 -0400)
committerChuck Hagenbuch <chuck@horde.org>
Mon, 30 Aug 2010 01:11:16 +0000 (21:11 -0400)
whups/scripts/whups-git-hook-conf.php.dist [new file with mode: 0644]
whups/scripts/whups-git-hook.php [new file with mode: 0755]
whups/scripts/whups-svn-hook-conf.php.dist [new file with mode: 0644]
whups/scripts/whups-svn-hook.php [new file with mode: 0755]

diff --git a/whups/scripts/whups-git-hook-conf.php.dist b/whups/scripts/whups-git-hook-conf.php.dist
new file mode 100644 (file)
index 0000000..e78035b
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/**
+ * commit-update-tickets.php configuration
+ */
+// Path to git
+$git = '/usr/bin/git';
+
+// XML-RPC endpoint
+$rpc_endpoint = 'https://dev.horde.org/horde/rpc.php';
+
+// XML-RPC method to call
+$rpc_method = 'tickets.addComment';
+
+// XML-RPC options, usually username and password
+$rpc_options = array('user' => '',
+                     'pass' => '');
diff --git a/whups/scripts/whups-git-hook.php b/whups/scripts/whups-git-hook.php
new file mode 100755 (executable)
index 0000000..618dfa8
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/env php
+<?php
+/**
+ * commit-update-tickets.php: scan commit logs for ticket numbers
+ * denoted by a flexible regular expression and post the log message
+ * and a link to the changeset diff in a comment to those tickets.
+ *
+ * Usage: commit-update-tickets.php PATH_TO_REPO REVISION
+ *
+ * @category Horde
+ * @package  maintainer_tools
+ */
+
+require_once 'Horde/Autoloader/Default.php';
+
+
+/**
+ ** Initialize expected values to rule out pre-existing input by any
+ ** means, then include our configuration file.
+ **/
+
+$git = $rpc_endpoint = $rpc_method = null;
+$rpc_options = array();
+
+require dirname(__FILE__) . '/commit-update-tickets-conf.php';
+
+
+/**
+ ** Sanity checks
+ **/
+
+if (!is_executable($git)) {
+    abort("Required program $git is not executable.");
+}
+
+if (is_null($rpc_endpoint) || is_null($rpc_method)) {
+    abort("Required XML-RPC configuration is missing or incomplete.");
+}
+
+if (count($_SERVER['argv']) < 4) {
+    usage();
+}
+
+
+/**
+ ** Command-line parsing
+ **/
+
+array_shift($_SERVER['argv']);
+$repo = array_shift($_SERVER['argv']);
+$rev = array_shift($_SERVER['argv']);
+$links = implode("\n", $_SERVER['argv']);
+
+if (!file_exists($repo)) {
+    abort("Repository $repo does not exist.");
+}
+
+if (!is_dir($repo)) {
+    abort("Repository $repo is not a directory.");
+}
+
+
+/**
+ ** Read the log message for this revision
+ **/
+
+// Run git show to get the log message for this revision
+$log_message = shell_exec(implode(' ', array(
+    escapeshellcmd($git),
+    '--git-dir=' . escapeshellarg($repo),
+    'show',
+    '--summary',
+    '--pretty=format:%s%n%b',
+    escapeshellarg($rev)
+)));
+
+if (!empty($log_message)) {
+    $tickets = find_tickets($log_message);
+    $kolab_tickets = find_kolab_tickets($log_message);
+
+    foreach ($kolab_tickets as $ticket) {
+        $log_message .= "\nThis ticket also references kolab issue: http://issues.kolab.org/issue$ticket\n\n";
+    }
+
+    if (count($tickets)) {
+        $log_message = "Changes have been made in Git for this ticket:\n\n$log_message$links";
+        foreach ($tickets as $ticket) {
+            post_comment($ticket, $log_message);
+        }
+    }
+}
+
+exit(0);
+
+
+/**
+ ** Functions
+ **/
+
+function abort($msg) {
+    fputs(STDERR, $msg . "\n");
+    exit(1);
+}
+
+function usage() {
+    abort("usage: commit-update-tickets.php PATH_TO_REPO REVISION LINKS");
+}
+
+function find_tickets($log_message) {
+    preg_match_all('/(?:(?<!kolab\/)(?:bug|ticket|request|enhancement|issue):?\s*#?|#)(\d+)/i', $log_message, $matches);
+    return array_unique($matches[1]);
+}
+
+/**
+ * Locate kolab tickets with kolab/issue1234
+ */
+function find_kolab_tickets($log_message) {
+    preg_match_all('/(?:(?:kolab\/issue))(\d+)/i', $log_message, $matches);
+    return array_unique($matches[1]);
+}
+
+function post_comment($ticket, $log_message) {
+    $result = Horde_Rpc::request(
+        'xmlrpc',
+        $GLOBALS['rpc_endpoint'],
+        $GLOBALS['rpc_method'],
+        array((int)$ticket, $log_message),
+        $GLOBALS['rpc_options']);
+
+    if (is_a($result, 'PEAR_Error')) {
+        abort($result->getMessage());
+    }
+
+    return true;
+}
diff --git a/whups/scripts/whups-svn-hook-conf.php.dist b/whups/scripts/whups-svn-hook-conf.php.dist
new file mode 100644 (file)
index 0000000..72fba8b
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/**
+ ** commit-update-tickets.php configuration
+ **/
+
+// Path to svnlook
+$svnlook = '/usr/bin/svnlook';
+
+// XML-RPC endpoint
+$rpc_endpoint = 'https://dev.horde.org/horde/rpc.php';
+
+// XML-RPC method to call
+$rpc_method = 'tickets.addComment';
+
+// XML-RPC options, usually username and password
+$rpc_options = array('user' => '',
+                     'pass' => '');
diff --git a/whups/scripts/whups-svn-hook.php b/whups/scripts/whups-svn-hook.php
new file mode 100755 (executable)
index 0000000..48b433b
--- /dev/null
@@ -0,0 +1,122 @@
+#!/usr/bin/env php
+<?php
+/**
+ * commit-update-tickets.php: scan commit logs for ticket numbers
+ * (denoted by a flexible regular expression and post the log message
+ * and a link to the changeset diff in a comment to those tickets.
+ *
+ * Usage: commit-update-tickets.php REPOS REVISION
+ *
+ * @category Horde
+ * @package  maintainer_tools
+ */
+
+
+/**
+ ** Includes
+ **/
+
+require_once 'Horde/RPC.php';
+
+
+/**
+ ** Initialize expected values to rule out pre-existing input by any
+ ** means, then include our configuration file.
+ **/
+
+$svnlook = null;
+$rpc_endpoint = null;
+$rpc_method = null;
+$rpc_options = array();
+
+include dirname(__FILE__) . '/commit-update-tickets-conf.php';
+
+
+/**
+ ** Sanity checks
+ **/
+
+if (!is_executable($svnlook)) {
+    abort("Required program $svnlook is not executable.");
+}
+
+if (is_null($rpc_endpoint) || is_null($rpc_method)) {
+    abort("Required XML-RPC configuration is missing or incomplete.");
+}
+
+if (count($_SERVER['argv']) != 3) {
+    usage();
+}
+
+
+/**
+ ** Command-line parsing
+ **/
+
+$repos = $_SERVER['argv'][1];
+$rev = $_SERVER['argv'][2];
+
+if (!file_exists($repos)) {
+    abort("Repository $repos does not exist.");
+}
+
+if (!is_dir($repos)) {
+    abort("Repository $repos is not a directory.");
+}
+
+
+/**
+ ** Read the log message for this revision
+ **/
+
+// Run svnlook log to get the log message for this revision
+exec(implode(' ', array($svnlook,
+                        'log',
+                        '--revision',
+                        escapeshellarg($rev),
+                        escapeshellarg($repos))),
+     $log_message);
+
+$tickets = find_tickets($log_message);
+if (count($tickets)) {
+    foreach ($tickets as $ticket) {
+        post_comment($ticket, $log_message);
+    }
+}
+
+exit(0);
+
+
+/**
+ ** Functions
+ **/
+
+function abort($msg) {
+    fputs(STDERR, $msg . "\n");
+    exit(1);
+}
+
+function usage() {
+    abort("usage: commit-update-tickets.php REPOS REVISION");
+}
+
+function find_tickets($log_message) {
+    preg_match_all('/#(\d+)/', $log_message, $matches_1);
+    preg_match_all('/(bug|ticket|request|enhancement|issue):\s*#?(\d+)/i', $log_message, $matches_2);
+    return array_unique(array_merge($matches_1[1], $matches_2[2]));
+}
+
+function post_comment($ticket, $log_message) {
+    $result = Horde_RPC::request(
+        'xmlrpc',
+        $GLOBALS['rpc_endpoint'],
+        $GLOBALS['rpc_method'],
+        array((int)$ticket, $log_message),
+        $GLOBALS['rpc_options']);
+
+    if (is_a($result, 'PEAR_Error')) {
+        abort($result->getMessage());
+    }
+
+    return true;
+}