From 334689082a611fa667ae8cb2094db9ce97a58836 Mon Sep 17 00:00:00 2001 From: danij Date: Sun, 18 Mar 2012 14:32:37 +0000 Subject: [PATCH] Homepage|Build Repository|Cleanup: Moved commit log formatting utilities to commitutils.php --- .../buildrepository/buildrepository.php | 455 +++++------------- web/plugins/buildrepository/commitutils.php | 262 ++++++++++ 2 files changed, 371 insertions(+), 346 deletions(-) create mode 100644 web/plugins/buildrepository/commitutils.php diff --git a/web/plugins/buildrepository/buildrepository.php b/web/plugins/buildrepository/buildrepository.php index 3ce01ad878..71131304ae 100644 --- a/web/plugins/buildrepository/buildrepository.php +++ b/web/plugins/buildrepository/buildrepository.php @@ -50,351 +50,9 @@ ///@} require_once('buildevent.class.php'); -require_once('packagefactory.class.php'); require_once('buildlogparser.class.php'); - -function retrieveBuildLogXml(&$buildLogUri) -{ - // Open a new cURL session. - $cs = curl_init(); - if($cs === FALSE) - throw new Exception('Failed initializing cURL'); - - curl_setopt($cs, CURLOPT_URL, $buildLogUri); - curl_setopt($cs, CURLOPT_HEADER, false); - curl_setopt($cs, CURLOPT_RETURNTRANSFER, true); - - $xml = curl_exec($cs); - if($xml === FALSE) - $error = curl_error($cs); - curl_close($cs); - if($xml === FALSE) - throw new Exception('Failed retrieving file' + $error); - - return $xml; -} - -/** - * Determine if the local cached copy of the remote build log requires an - * update (i.e., the remote server indicates the file has changed, or our - * cached copy has been manually purged). - * - * @param buildLogUri (String) Uri locator to the remote build log. - * @param cacheName (String) Name of the cache copy of the log. - * @return (Boolean) @c true if the cache copy of the log needs an update. - */ -function mustUpdateCachedBuildLog(&$buildLogUri, &$cacheName) -{ - global $FrontController; - - if(!$FrontController->contentCache()->isPresent($cacheName)) - return TRUE; - - // Only query the remote server at most once every five minutes for an - // updated build log. The modified time of our local cached copy is used - // to determine when it is time to query (we touch the cached copy after - // each query attempt). - $cacheInfo = new ContentInfo(); - $FrontController->contentCache()->getInfo($cacheName, $cacheInfo); - if(time() < strtotime('+5 minutes', $cacheInfo->modifiedTime)) - return FALSE; - - // Check the remote time of the log and compare with our local cached copy. - try - { - // Open a new cURL session. - $cs = curl_init(); - if($cs === FALSE) - throw new Exception('Failed initializing cURL'); - - // We only want the headers. - curl_setopt($cs, CURLOPT_URL, $buildLogUri); - curl_setopt($cs, CURLOPT_NOBODY, true); - curl_setopt($cs, CURLOPT_RETURNTRANSFER, true); - curl_setopt($cs, CURLOPT_FILETIME, true); - - $xml = curl_exec($cs); - if($xml !== FALSE) - { - $timestamp = curl_getinfo($cs, CURLINFO_FILETIME); - // Close the cURL session. - curl_close($cs); - - if($timestamp != -1) - { - if($timestamp > $cacheInfo->modifiedTime) - { - // Update necessary. - return TRUE; - } - else - { - // Touch our cached copy so we can delay checking again. - $FrontController->contentCache()->touch($cacheName); - return FALSE; - } - } - else - { - // Server could/would not supply the headers we are interested in. - // We'll err on the side of caution and update (our five minute - // repeat delay mitigates the sting). - return TRUE; - } - } - else - { - $error = curl_error($cs); - // We are now done with the cURL session. - curl_close($cs); - throw new Exception('Failed retrieving file info' + $error); - } - } - catch(Exception $e) - { - /// @todo Store error so users can query. - //setError($e->getMessage()); - return FALSE; - } -} - -function addCommitToGroup(&$groups, $groupName, &$commit) -{ - if(!is_array($groups)) - throw new Exception('Invalid groups argument, array expected'); - - $key = array_casekey_exists($groupName, $groups); - if($key === false) - { - $groups[$groupName] = array(); - $group = &$groups[$groupName]; - } - else - { - $group = &$groups[$key]; - } - - $group[] = $commit; -} - -function groupBuildCommits(&$build, &$groups) -{ - if(!$build instanceof BuildEvent) - throw new Exception('Received invalid BuildEvent'); - if(!is_array($groups)) - throw new Exception('Invalid groups argument, array expected'); - - foreach($build->commits as &$commit) - { - if(!is_array($commit['tags']) || 0 === count($commit['tags'])) - { - addCommitToGroup($groups, 'Miscellaneous', $commit); - continue; - } - - $tags = $commit['tags']; - reset($tags); - $firstTag = key($tags); - addCommitToGroup($groups, $firstTag, $commit); - } -} - -function make_pretty_hyperlink($matches) -{ - $uri = implode('', array_slice($matches, 1)); - return genHyperlinkHTML($uri, 40, 'link-external'); -} - -function formatCommitMessageHTML($msg) -{ - if(strcasecmp(gettype($msg), 'string')) return $msg; - - // Process the commit message, replacing web URIs with clickable links. - htmlspecialchars($msg); - $msg = preg_replace_callback("/([^A-z0-9])(http|ftp|https)([\:\/\/])([^\\s]+)/", - "make_pretty_hyperlink", $msg); - $msg = nl2br($msg); - return $msg; -} - -function outputCommitHTML(&$commit) -{ - if(!is_array($commit)) - throw new Exception('Invalid commit argument, array expected'); - - // Format the commit message for HTML output. - $message = $commit['message']; - $haveMessage = (bool)(strlen($message) > 0); - - // Compose the supplementary tag list. - $tagList = '
'; - if(is_array($commit['tags'])) - { - $n = (integer)0; - foreach($commit['tags'] as $tag => $value) - { - // Skip the first tag (its used for grouping). - if($n++ === 0) continue; - - // Do not output guessed tags (mainly used for grouping). - if(is_array($value) && isset($value['guessed']) && $value['guessed'] !== 0) continue; - - $cleanTag = htmlspecialchars($tag); - $tagList .= '
'; - } - } - $tagList .= '
'; - - $repoLinkTitle = 'Show changes in the repository for this commit submitted on '. date(DATE_RFC2822, $commit['submitDate']) .'.'; - - // Ouput HTML for the commit. -?>

> by

    $group) - { - $commitCount = count($group); - $tagLinkTitle = "Jump to commits tagged '$groupName'"; - -?>
5) - { - $numLists = ceil($groupCount / 5); - for($i = (integer)0; $i < $numLists; $i++) - { - $subList = array_slice($groups, $i*5, 5); - outputCommitJumpList2(&$subList); - } - } - else - { - // Just the one list then. - outputCommitJumpList2($groups); - } - -?>
commits); - if($commitCount) - { - $groups = array(); - groupBuildCommits($build, &$groups); - - $groupCount = count($groups); - if($groupCount > 1) - { - ksort($groups); - - // Generate a jump list? - if($commitCount > 15) - { - outputCommitJumpList($groups); - } - } - - // Generate the commit list itself. -?>
-
-
commits) <= 0) return FALSE; - - $commitsCacheName = 'buildrepository/'.$build->uniqueId().'/commits.html'; - try - { - $FrontController->contentCache()->import($commitsCacheName); - } - catch(Exception $e) - { - $OutputCache = new OutputCache(); - - $OutputCache->start(); - outputCommitLogHTML($build); - $content = $OutputCache->stop(); - - $FrontController->contentCache()->store($commitsCacheName, $content); - - print($content); - } - - return TRUE; -} +require_once('commitutils.php'); +require_once('packagefactory.class.php'); class BuildRepositoryPlugin extends Plugin implements Actioner, RequestInterpreter { @@ -547,6 +205,111 @@ public static function packageSorter($packA, $packB) return $a < $b? -1 : 1; } + /** + * Determine if the local cached copy of the remote build log requires an + * update (i.e., the remote server indicates the file has changed, or our + * cached copy has been manually purged). + * + * @param buildLogUri (String) Uri locator to the remote build log. + * @param cacheName (String) Name of the cache copy of the log. + * @return (Boolean) @c true if the cache copy of the log needs an update. + */ + private static function mustUpdateCachedBuildLog(&$buildLogUri, &$cacheName) + { + global $FrontController; + + if(!$FrontController->contentCache()->isPresent($cacheName)) + return TRUE; + + // Only query the remote server at most once every five minutes for an + // updated build log. The modified time of our local cached copy is used + // to determine when it is time to query (we touch the cached copy after + // each query attempt). + $cacheInfo = new ContentInfo(); + $FrontController->contentCache()->getInfo($cacheName, $cacheInfo); + if(time() < strtotime('+5 minutes', $cacheInfo->modifiedTime)) + return FALSE; + + // Check the remote time of the log and compare with our local cached copy. + try + { + // Open a new cURL session. + $cs = curl_init(); + if($cs === FALSE) + throw new Exception('Failed initializing cURL'); + + // We only want the headers. + curl_setopt($cs, CURLOPT_URL, $buildLogUri); + curl_setopt($cs, CURLOPT_NOBODY, true); + curl_setopt($cs, CURLOPT_RETURNTRANSFER, true); + curl_setopt($cs, CURLOPT_FILETIME, true); + + $xml = curl_exec($cs); + if($xml !== FALSE) + { + $timestamp = curl_getinfo($cs, CURLINFO_FILETIME); + // Close the cURL session. + curl_close($cs); + + if($timestamp != -1) + { + if($timestamp > $cacheInfo->modifiedTime) + { + // Update necessary. + return TRUE; + } + else + { + // Touch our cached copy so we can delay checking again. + $FrontController->contentCache()->touch($cacheName); + return FALSE; + } + } + else + { + // Server could/would not supply the headers we are interested in. + // We'll err on the side of caution and update (our five minute + // repeat delay mitigates the sting). + return TRUE; + } + } + else + { + $error = curl_error($cs); + // We are now done with the cURL session. + curl_close($cs); + throw new Exception('Failed retrieving file info' + $error); + } + } + catch(Exception $e) + { + /// @todo Store error so users can query. + //setError($e->getMessage()); + return FALSE; + } + } + + private static function retrieveBuildLogXml(&$buildLogUri) + { + // Open a new cURL session. + $cs = curl_init(); + if($cs === FALSE) + throw new Exception('Failed initializing cURL'); + + curl_setopt($cs, CURLOPT_URL, $buildLogUri); + curl_setopt($cs, CURLOPT_HEADER, false); + curl_setopt($cs, CURLOPT_RETURNTRANSFER, true); + + $xml = curl_exec($cs); + if($xml === FALSE) + $error = curl_error($cs); + curl_close($cs); + if($xml === FALSE) + throw new Exception('Failed retrieving file' + $error); + + return $xml; + } + /** * Attempt to parse the build log, constructing from it a collection * of the abstract objects we use to model the events an packages it @@ -563,12 +326,12 @@ private function constructBuilds(&$builds) // Is it time to update our cached copy of the build log? $logCacheName = 'buildrepository/events.xml'; - if(mustUpdateCachedBuildLog($buildLogUri, $logCacheName)) + if(self::mustUpdateCachedBuildLog($buildLogUri, $logCacheName)) { try { // Grab a copy and store it in the local file cache. - $logXml = retrieveBuildLogXml($buildLogUri); + $logXml = self::retrieveBuildLogXml($buildLogUri); if($logXml == FALSE) throw new Exception('Failed retrieving build log'); diff --git a/web/plugins/buildrepository/commitutils.php b/web/plugins/buildrepository/commitutils.php new file mode 100644 index 0000000000..591dacbdbc --- /dev/null +++ b/web/plugins/buildrepository/commitutils.php @@ -0,0 +1,262 @@ + + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +includeGuard('commitutils.php'); + +require_once('buildevent.class.php'); + +function addCommitToGroup(&$groups, $groupName, &$commit) +{ + if(!is_array($groups)) + throw new Exception('Invalid groups argument, array expected'); + + $key = array_casekey_exists($groupName, $groups); + if($key === false) + { + $groups[$groupName] = array(); + $group = &$groups[$groupName]; + } + else + { + $group = &$groups[$key]; + } + + $group[] = $commit; +} + +function groupBuildCommits(&$build, &$groups) +{ + if(!$build instanceof BuildEvent) + throw new Exception('Received invalid BuildEvent'); + if(!is_array($groups)) + throw new Exception('Invalid groups argument, array expected'); + + foreach($build->commits as &$commit) + { + if(!is_array($commit['tags']) || 0 === count($commit['tags'])) + { + addCommitToGroup($groups, 'Miscellaneous', $commit); + continue; + } + + $tags = $commit['tags']; + reset($tags); + $firstTag = key($tags); + addCommitToGroup($groups, $firstTag, $commit); + } +} + +function make_pretty_hyperlink($matches) +{ + $uri = implode('', array_slice($matches, 1)); + return genHyperlinkHTML($uri, 40, 'link-external'); +} + +function formatCommitMessageHTML($msg) +{ + if(strcasecmp(gettype($msg), 'string')) return $msg; + + // Process the commit message, replacing web URIs with clickable links. + htmlspecialchars($msg); + $msg = preg_replace_callback("/([^A-z0-9])(http|ftp|https)([\:\/\/])([^\\s]+)/", + "make_pretty_hyperlink", $msg); + $msg = nl2br($msg); + return $msg; +} + +function outputCommitHTML(&$commit) +{ + if(!is_array($commit)) + throw new Exception('Invalid commit argument, array expected'); + + // Format the commit message for HTML output. + $message = $commit['message']; + $haveMessage = (bool)(strlen($message) > 0); + + // Compose the supplementary tag list. + $tagList = '
'; + if(is_array($commit['tags'])) + { + $n = (integer)0; + foreach($commit['tags'] as $tag => $value) + { + // Skip the first tag (its used for grouping). + if($n++ === 0) continue; + + // Do not output guessed tags (mainly used for grouping). + if(is_array($value) && isset($value['guessed']) && $value['guessed'] !== 0) continue; + + $cleanTag = htmlspecialchars($tag); + $tagList .= '
'; + } + } + $tagList .= '
'; + + $repoLinkTitle = 'Show changes in the repository for this commit submitted on '. date(DATE_RFC2822, $commit['submitDate']) .'.'; + + // Ouput HTML for the commit. +?>

> by

    $group) + { + $commitCount = count($group); + $tagLinkTitle = "Jump to commits tagged '$groupName'"; + +?>
5) + { + $numLists = ceil($groupCount / 5); + for($i = (integer)0; $i < $numLists; $i++) + { + $subList = array_slice($groups, $i*5, 5); + outputCommitJumpList2(&$subList); + } + } + else + { + // Just the one list then. + outputCommitJumpList2($groups); + } + +?>
commits); + if($commitCount) + { + $groups = array(); + groupBuildCommits($build, &$groups); + + $groupCount = count($groups); + if($groupCount > 1) + { + ksort($groups); + + // Generate a jump list? + if($commitCount > 15) + { + outputCommitJumpList($groups); + } + } + + // Generate the commit list itself. +?>
+
+
commits) <= 0) return FALSE; + + $commitsCacheName = 'buildrepository/'.$build->uniqueId().'/commits.html'; + try + { + $FrontController->contentCache()->import($commitsCacheName); + } + catch(Exception $e) + { + $OutputCache = new OutputCache(); + + $OutputCache->start(); + outputCommitLogHTML($build); + $content = $OutputCache->stop(); + + $FrontController->contentCache()->store($commitsCacheName, $content); + + print($content); + } + + return TRUE; +}