gwynne Mon, 20 Jul 2009 04:40:31 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=284413
Changed paths: A SVNROOT/commit-bugs.php U SVNROOT/commit-email.php A SVNROOT/commit-svnroot.php U SVNROOT/post-commit Log: - reorganized the post-commit hook quite a bit to load common information and call sub-hooks for various tasks - added a catch-all email for php/php-src/ to ensure some emails get where they're going - moved Rasmus' bug stuff to its own file - moved the SVNROOT check to its own file as well - make a passing attempt to marshal back to the client the results of SVNROOT updates - actually show the client an error when SMTP connection fails - use ===/!== instead of ==/!= in a couple places as a matter of style
Added: SVNROOT/commit-bugs.php =================================================================== --- SVNROOT/commit-bugs.php (rev 0) +++ SVNROOT/commit-bugs.php 2009-07-20 04:40:31 UTC (rev 284413) @@ -0,0 +1,107 @@ +<?php + +// This script is intended to be called from post-commit. It assumes that all +// the appropriate variables and functions are defined. + +// ----------------------------------------------------------------------------------------------------------------------------- +// Constants +$version = substr('$Revision$', strlen('$Revision: '), -2); +$bug_pattern = '/(?:(pecl|pear)\s*)?(?:bug|#)[\s#:]*([0-9]+)/iuX'; +$bug_url_prefixes = array( + 'pear' => 'http://pear.php.net/bugs', + 'pecl' => 'http://pecl.php.net/bugs', + '' => 'http://bugs.php.net', +); +$bug_rpc_url = 'http://bugs.php.net/rpc.php'; +$viewvc_url_prefix = 'http://svn.php.net/viewvc/?view=revision&revision='; + +// ----------------------------------------------------------------------------------------------------------------------------- +// Get the list of mentioned bugs from the commit log +if (preg_match_all($bug_pattern, $commit_info['log_message'], $matched_bugs, PREG_SET_ORDER) < 1) { + // If no bugs matched, we don't have to do anything. + return; +} + +// ----------------------------------------------------------------------------------------------------------------------------- +// Process the matches +$bug_list = array(); +foreach ($matched_bugs as $matched_bug) { + $bug = array(); + $bug['project'] = isset($matched_bug[1]) ? $matched_bug[1] : ''; + $bug['number'] = intval($matched_bug[2]); + $bugid = $bug['project'] . $bug['number']; + $bug['url_prefix'] = isset($bug_url_prefixes[$bug['project']]) ? $bug_url_prefixes[$bug['project']] : $bug_url_prefixes['']; + $bug['url'] = $bug['url_prefix'] . '/' . $bug['number']; + $bug['status'] = 'unknown'; + $bug['short_desc'] = ''; + $bug_list[$bugid] = $bug; +} + +// ----------------------------------------------------------------------------------------------------------------------------- +// Make an RPC call for each bug +if (!$is_DEBUG) { + include __DIR__ . '/secret.inc'; +} +foreach ($bug_list as &$bug) { + // Only do this for core PHP bugs + if ($bug['project'] !== '') { + continue; + } + + $comment = "Automatic comment from SVN on behalf of {$commit_info['author']}\n" . + "Revision: {$viewvc_url_prefix}{$REV}\n" . + "Log: {$commit_info['log_message']}\n"; + + $postdata = array( + 'user' => $commit_info['author'], + 'id' => $bug['number'], + 'ncomment' => $comment, + 'MAGIC_COOKIE' => $is_DEBUG ? 'nonsense' : $SVN_MAGIC_COOKIE, + ); + array_walk($postdata, create_function('&$v, $k', '$v = rawurlencode($k) . "=" . rawurlencode($v);')); + $postdata = implode('&', $postdata); + + if ($is_DEBUG) { + print "DEBUG: Bug #{$bug['number']}: Would have posted this rawurlencoded string to {$bug_rpc_url}:\n{$postdata}\n"; + if (mt_rand(0, 1) === 1) { + $bug['error'] = 'DEBUG-some kind of error'; + } else { + $bug['status'] = 'DEBUG-unknown'; + $bug['short_desc'] = "DEBUG-Bug #{$bug['number']}"; + } + continue; + } + // Hook an env var so emails can be resent without messing with bugs + if (getenv('NOBUG')) { + continue; + } + + $ch = curl_init(); + curl_setopt_array(array( + CURLOPT_URL => $bug_rpc_url, + CURLOPT_RETURNTRANSFER => TRUE, + CURLOPT_POST => TRUE, + CURLOPT_CONNECTTIMEOUT => 5, + CURLOPT_TIMEOUT => 5, + CURLOPT_POSTFIELDS => $postdata, + )); + + $result = curl_exec($ch); + + if ($result === FALSE) { + $bug['error'] = curl_error($ch); + } else { + $bug_server_data = json_decode($result, TRUE); + if (isset($bug_server_data['result']['status'])) { + $bug['status'] = $bug_server_data['result']['status']['status']; + $bug['short_desc'] = $bug_server_data['result']['status']['sdesc']; + } else { + $bug['error'] = $bug_server_data['result']['error']; + } + } + curl_close($ch); +} +unset($SVN_MAGIC_COOKIE); + +// $bug_list is now available to later-running hooks +?> Property changes on: SVNROOT/commit-bugs.php ___________________________________________________________________ Added: svn:keywords + Id Rev Revision Added: svn:eol-style + native Modified: SVNROOT/commit-email.php =================================================================== --- SVNROOT/commit-email.php 2009-07-20 04:31:07 UTC (rev 284412) +++ SVNROOT/commit-email.php 2009-07-20 04:40:31 UTC (rev 284413) @@ -1,9 +1,7 @@ <?php -// Note that this script is intended to be called from inside the post-commit -// hook. It makes some assumptions: $REPOS and $REV are defined, the -// run_svnlook() function is declared, $changed_paths and $dirs_changed are -// determined. +// This script is intended to be called from post-commit. It assumes that all +// the appropriate variables and functions are defined. // ----------------------------------------------------------------------------------------------------------------------------- // Constants @@ -30,6 +28,7 @@ '|^php/ZendAPI|' => array('zend-engine-...@lists.php.net', 'doc-...@lists.php.net'), '|^php/php-src/Zend|' => array('zend-engine-...@lists.php.net'), '|^php/php-src/TSRM|' => array('zend-engine-...@lists.php.net'), + '|^php/php-src|' => array('php-cvs@lists.php.net'), // phpdoc '|^phpdoc/doc-base|' => array('doc-...@lists.php.net'), @@ -117,43 +116,11 @@ } // ----------------------------------------------------------------------------------------------------------------------------- -// Get info from commit -$commit_info = run_svnlook('info'); -$commit_user = trim($commit_info[0]); -$commit_date = strtotime(substr($commit_info[1], 0, strlen("0000-00-00 00:00:00 +0000"))); -$commit_log = implode("\n", array_slice($commit_info, 3)); -// Support bug#1234 bug url extraction -$bugs = preg_match_all("/(?:pecl|pear|)\\s*(?:bug|#)[\\s#:]*([0-9]+)/i", $commit_log, $bugs_array); - -// ----------------------------------------------------------------------------------------------------------------------------- -// Determine "from" address -// Various repositories can play with this to read from their equivelant of the old cvsusers folder, or whatever else they like -$usersDB = file(dirname(__FILE__) . '/users.db'); -$from = NULL; -$saw_last_ISO = FALSE; -foreach ($usersDB as $userline) { - list ($username, $fullname, $email) = explode(":", trim($userline)); - if ($username === 'ladderalice') { - $saw_last_ISO = TRUE; - } - if ($username === $commit_user) { - if ($saw_last_ISO !== TRUE) { - $fullname = iconv("ISO-8859-1", "UTF-8//TRANSLIT", $fullname); - } - $from = array($username, $fullname); - break; - } -} -if (is_null($from)) { - die("Couldn't find user\n"); -} - -// ----------------------------------------------------------------------------------------------------------------------------- // Build list of e-mail addresses and parent changed path $emails_to = array(); -$parent_path = $dirs_changed[0]; +$parent_path = $commit_info['dirs_changed'][0]; -foreach ($dirs_changed as $changed_path) { +foreach ($commit_info['dirs_changed'] as $changed_path) { foreach ($commit_email_list as $regex => $email_list) { if (preg_match($regex, $changed_path, $matches) === 1) { $emails_to = array_merge($emails_to, $email_list); @@ -173,32 +140,18 @@ $emails_to = array_unique($emails_to); // ----------------------------------------------------------------------------------------------------------------------------- -// Get diffs -$diffs = run_svnlook('diff'); -$diffs = implode("\n", $diffs); -$diffs_length = strlen($diffs); +// Process diffs +$diffs_length = strlen($commit_info['diffs']); $diffs_string = ($diffs_length > 262144 ? "<diffs exceeded maximum size>" : - ($diffs_length > 8192 ? NULL : $diffs)); + ($diffs_length > 8192 ? NULL : $commit_info['diffs'])); // ----------------------------------------------------------------------------------------------------------------------------- // Build e-mail -$boundary = sha1("{$commit_user}{$commit_date}"); -$messageid = "{$commit_user}-{$commit_date}-{$REV}-" . mt_rand(); +$boundary = sha1("{$commit_info['author']}{$commit_info['date']}"); +$messageid = "{$commit_info['author']}-{$commit_info['date']}-{$REV}-" . mt_rand(); $subject = "svn: " . ($parent_path === '' ? '/' : $parent_path); -switch (substr(trim($changed_paths[0]),4)) { - case 'pear': $bug_url = 'http://pear.php.net/bugs'; break; - case 'pecl': $bug_url = 'http://pecl.php.net/bugs'; break; - default: $bug_url = 'http://bugs.php.net'; break; -} -foreach($bugs_array[0] as $k=>$bug_match) { - if(stristr($bug_match,'pecl')) $bug_urls[$k] = 'http://pecl.php.net/bugs'; - else if(stristr($bug_match,'pear')) $bug_urls[$k] = 'http://pear.php.net/bugs'; - else $bug_urls[$k] = $bug_url; - -} - -foreach ($changed_paths as $changed_path) { +foreach ($commit_info['changed_paths'] as $changed_path) { $changed_path = trim(strstr($changed_path, ' ')); if (substr($changed_path, -1) !== '/') { $subject .= ' ' . substr($changed_path, strlen($parent_path)); @@ -206,46 +159,26 @@ } $subject = substr($subject, 0, 950); // Max SMTP line length = 998. Some slop in this value. -$fullname = "=?utf-8?q?" . imap_8bit(str_replace(array('?', ' '), array('=3F', '_'), $from[1])) . "?="; +$fullname = "=?utf-8?q?" . imap_8bit(str_replace(array('?', ' '), array('=3F', '_'), $commit_info['author_name'])) . "?="; -$msg_headers = "From: {$fullname} <{$from[...@php.net>\r\n" . +$msg_headers = "From: {$fullname} <{$commit_info['author']...@php.net>\r\n" . "To: " . implode(', ', $emails_to) . "\r\n" . "Message-ID: <svn{$message...@svn.php.net>\r\n" . - "Date: " . date(DATE_RFC822, $commit_date) . "\r\n" . + "Date: " . date(DATE_RFC822, $commit_info['date']) . "\r\n" . "Subject: {$subject}\r\n" . "MIME-Version: 1.0\r\n" . "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n"; $bugs_body = ''; -if ($bugs) { - include '/home/svn/SVNROOT/secret.inc'; - $bugs_body = (count($bugs_array[1])>1) ? "Bugs: " : "Bug: "; - foreach ($bugs_array[1] as $k=>$bug_id) { - $bug_sdesc = ''; - $bug_status = ''; - if($bug_urls[$k]=='http://bugs.php.net') { - $ch = curl_init('http://bugs.php.net/rpc.php'); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POST, 1); - $ncomment = "Automatic comment from SVN on behalf of {$from[0]}\n" . - "Log: $commit_log\n" . - "Revision: http://svn.php.net/viewvc?view=revision&revision={$REV}\n"; - curl_setopt($ch, CURLOPT_POSTFIELDS, "user=" . rawurlencode($from[0]) . - "&id={$bug_id}" . - "&ncomment=" . rawurlencode($ncomment) . - "&MAGIC_COOKIE=$SVN_MAGIC_COOKIE"); - $ret = curl_exec($ch); - if($ret !== false ) { - $json = json_decode($ret,true); - if(isset($json['result']['status'])) { - $bug_status = ' ('.$json['result']['status']['status'].')'; - $bug_sdesc = ' '.$json['result']['status']['sdesc']; - } - } - curl_close($ch); +if (isset($bug_list) && count($bug_list) > 0) { + $bugs_body = count($bug_list) > 1 ? "Bugs: " : "Bug: "; + foreach ($bug_list as $n => $bug) { + if (isset($bug['error'])) { + $status = '(error getting bug information)'; + } else { + $status = "({$bug['status']}) {$bug['short_desc']}"; } - if($k) $bugs_body .= ' '; - $bugs_body .= $bug_urls[$k]."/$bug_id{$bug_status}{$bug_sdesc}\r\n"; + $bugs_body .= "{$bug['url']} {$status}\r\n "; } } @@ -253,17 +186,17 @@ "Content-Type: text/plain; charset=\"utf-8\"\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . - "{$commit_user}\t\t" . date(DATE_RFC2822, $commit_date) . "\r\n" . + "{$commit_info['author']}\t\t" . date(DATE_RFC2822, $commit_info['date']) . "\r\n" . "\r\n" . "Revision: http://svn.php.net/viewvc?view=revision&revision={$REV}\r\n" . "\r\n" . "Changed paths:\r\n" . - "\t" . implode("\r\n\t", $changed_paths) . "\r\n" . + "\t" . implode("\r\n\t", $commit_info['changed_paths']) . "\r\n" . "\r\n" . "Log:\r\n" . - $commit_log . "\r\n" . - "$bugs_body\r\n" . - $diffs_string; + "{$commit_info['log_message']}\r\n" . + "{$bugs_body}\r\n" . + str_replace("\n", "\r\n", $diffs_string); if ($diffs_string === NULL) { $msg_body .= @@ -287,7 +220,7 @@ $socket = fsockopen($smtp_server, getservbyname('smtp', 'tcp'), $errno); } if ($socket === FALSE) { - die("Couldn't connect to SMTP server {$smtp_server}. Errno: {$errno}.\n"); + fail("Couldn't connect to SMTP server {$smtp_server}. Errno: {$errno}.\n"); } fwrite($socket, Added: SVNROOT/commit-svnroot.php =================================================================== --- SVNROOT/commit-svnroot.php (rev 0) +++ SVNROOT/commit-svnroot.php 2009-07-20 04:40:31 UTC (rev 284413) @@ -0,0 +1,34 @@ +<?php + +// This script is intended to be called from post-commit. It assumes that all +// the appropriate variables and functions are defined. + +// ----------------------------------------------------------------------------------------------------------------------------- +// Constants +$version = substr('$Revision$', strlen('$Revision: '), -2); + +// ----------------------------------------------------------------------------------------------------------------------------- +// Check for a SVNROOT commit +$SVNROOT_changed = FALSE; +foreach ($commit_info['dirs_changed'] as $changed_path) { + if (substr($changed_path, 0, 7) == 'SVNROOT') { + $SVNROOT_changed = TRUE; + break; + } +} + +// ----------------------------------------------------------------------------------------------------------------------------- +// If SVNROOT had a commit, we need to update the admin copy +if ($SVNROOT_changed) { + if ($is_DEBUG) { + print "Updating SVNROOT...\n"; + } + chdir(__DIR__); + exec('exec svn update', $output, $status); + fwrite(stderr, implode("\n", $output) . "\n"); + if ($status != 0) { + fail("svn update on SVNROOT failed with exit code {$status}!\n"); + } +} + +?> Property changes on: SVNROOT/commit-svnroot.php ___________________________________________________________________ Added: svn:keywords + Id Rev Revision Added: svn:eol-style + native Modified: SVNROOT/post-commit =================================================================== --- SVNROOT/post-commit 2009-07-20 04:31:07 UTC (rev 284412) +++ SVNROOT/post-commit 2009-07-20 04:40:31 UTC (rev 284413) @@ -23,10 +23,13 @@ if (version_compare('5.2.0', PHP_VERSION, '>')) { fail("Requires at least PHP 5.2.\n"); } +if (!defined('__DIR__')) { + define('__DIR__', dirname(__FILE__)); +} // ----------------------------------------------------------------------------------------------------------------------------- // Arguments -if ($argc != 3) { +if ($argc !== 3) { fail("Pass exactly two arguments: REPOS and REV.\n"); } $REPOS = $argv[1]; @@ -37,7 +40,7 @@ function run_svnlook($command) { exec('exec svnlook ' . escapeshellarg($command) . ' -r ' . escapeshellarg($GLOBALS['REV']) . ' ' . escapeshellarg($GLOBALS['REPOS']), $output, $status); - if ($status != 0) { + if ($status !== 0) { fail("svnlook failed with exit code {$status}\nOutput:\n" . implode("\n", $output) . "\n"); } return $output; @@ -45,35 +48,42 @@ // ----------------------------------------------------------------------------------------------------------------------------- // Build list of changes -$changed_paths = run_svnlook('changed'); -$dirs_changed = run_svnlook('dirs-changed'); +$commit_info = array( + 'changed_paths' => run_svnlook('changed'), + 'dirs_changed' => run_svnlook('dirs-changed'), + 'author' => ($is_DEBUG && getenv("DEBUGUSER")) ? getenv("DEBUGUSER") : trim(implode('', run_svnlook('author'))), + 'log_message' => trim(implode('', run_svnlook('log'))), + 'date' => strtotime(substr(trim(implode('', run_svnlook('date'))), 0, strlen("0000-00-00 00:00:00 +0000"))), + 'diffs' => implode("\n", run_svnlook('diff')), +); // ----------------------------------------------------------------------------------------------------------------------------- -// Call e-mailer script -require dirname(__FILE__) . '/commit-email.php'; - -// ----------------------------------------------------------------------------------------------------------------------------- -// Check for a SVNROOT commit -$SVNROOT_changed = FALSE; -foreach ($dirs_changed as $changed_path) { - if (substr($changed_path, 0, 7) == 'SVNROOT') { - $SVNROOT_changed = TRUE; +// Read the user database +$usersDB = file(dirname(__FILE__) . '/users.db'); +$saw_last_ISO = FALSE; +foreach ($usersDB as $userline) { + list ($username, $fullname, $email) = explode(":", trim($userline)); + if ($username === 'ladderalice') { + $saw_last_ISO = TRUE; } + if ($username === $commit_info['author']) { + if ($saw_last_ISO !== TRUE) { + $fullname = iconv("ISO-8859-1", "UTF-8//TRANSLIT", $fullname); + } + $commit_info['author_name'] = $fullname; + $commit_info['author_email'] = $email; + break; + } } +if (!isset($commit_info['author_name'])) { + fail("Couldn't find user\n"); +} // ----------------------------------------------------------------------------------------------------------------------------- -// If SVNROOT had a commit, we need to update the admin copy -if ($SVNROOT_changed) { - if ($is_DEBUG) { - print "Updating SVNROOT...\n"; - } - chdir(dirname(__FILE__)); - exec('exec svn update', $output, $status); - print implode("\n", $output) . "\n"; - if ($status != 0) { - fail("svn update on SVNROOT failed with exit code {$status}!\n"); - } -} +// Call various sub-scripts +require __DIR__ . '/commit-bugs.php'; +require __DIR__ . '/commit-email.php'; +require __DIR__ . '/commit-svnroot.php'; // ----------------------------------------------------------------------------------------------------------------------------- // Done!
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php