and. // It's complicated because it's designed not to return those lines themselves. $path = encodepath($this->getSvnpath($path)); $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' | '. $config->enscript." --language=html ". ($l ? "--color --pretty-print=$l" : "")." -o - | ". $config->sed." -n ".$config->quote."1,/^
"; $contentEncoding = $this->repConfig->getContentEncoding(); while (!feof($result)) { $line = fgets($result, 1024); if ($pre) $line = replaceEntities($line, $this->repConfig); else $line = toOutputEncoding($line, $contentEncoding); print hardspace($line); } if ($pre) echo ""; pclose($result); } } } // }}} // {{{ getBlameDetails // // Dump the blame content of a file to the given filename function getBlameDetails($path, $filename, $rev = 0) { global $config; $path = encodepath($this->getSvnpath($path)); $cmd = $config->svn." blame ".$this->repConfig->svnParams().quote($path.'@'.$rev).' > '.quote($filename); $retcode = 0; execCommand($cmd, $retcode); if ($retcode != 0) { print'Unable to call svn command "'.$config->svn.'"'; exit(0); } } // }}} // {{{ getProperty function getProperty($path, $property, $rev = 0) { global $config; $path = encodepath($this->getSvnpath($path)); if ($rev > 0) { $rev = '@'.$rev; } else { $rev = ''; } $ret = runCommand($config->svn." propget $property ".$this->repConfig->svnParams().quote($path.$rev), true); // Remove the surplus newline if (count($ret)) { unset($ret[count($ret) - 1]); } return implode("\n", $ret); } // }}} // {{{ exportDirectory // // Exports the directory to the given location function exportDirectory($path, $filename, $rev = 0) { global $config; $path = encodepath($this->getSvnpath($path)); $cmd = $config->svn." export ".$this->repConfig->svnParams().quote($path.'@'.$rev).' '.quote($filename); $retcode = 0; execCommand($cmd, $retcode); if ($retcode != 0) { print'Unable to call svn command "'.$config->svn.'"'; exit(0); } } // }}} // {{{ getList function getList($path, $rev = 0) { global $config, $curList, $vars, $lang; $xml_parser = xml_parser_create("UTF-8"); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xml_parser, "listStartElement", "listEndElement"); xml_set_character_data_handler($xml_parser, "listCharacterData"); // Since directories returned by svn log don't have trailing slashes (:-(), we need to remove // the trailing slash from the path for comparison purposes if ($path{strlen($path) - 1} == "/" && $path != "/") { $path = substr($path, 0, -1); } $curList = new SVNList; $curList->entries = array(); $curList->path = $path; // Get the list info $path = encodepath($this->getSvnpath($path)); if ($rev == 0) { $headlog = $this->getLog("/", "", "", true, 1); if (is_string($headlog)) { echo $headlog; exit; } if (isset($headlog->entries[0])) $rev = $headlog->entries[0]->rev; } $cmd = quoteCommand($config->svn.' list --xml '.$this->repConfig->svnParams().quote($path.'@'.$rev)); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($cmd, $descriptorspec, $pipes); if (!is_resource($resource)) { echo "
".$lang['BADCMD'].": ".$cmd."
'.$lang['BADCMD'].': '.$cmd.'
'.nl2br($error).'
'; exit; } xml_parser_free($xml_parser); // Sort the entries into alphabetical order usort($curList->entries, "_listSort"); return $curList; } // }}} // {{{ getLog function getLog($path, $brev = "", $erev = 1, $quiet = false, $limit = 2) { global $config, $curLog, $vars, $lang; $xml_parser = xml_parser_create("UTF-8"); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xml_parser, "logStartElement", "logEndElement"); xml_set_character_data_handler($xml_parser, "logCharacterData"); // Since directories returned by svn log don't have trailing slashes (:-(), we need to remove // the trailing slash from the path for comparison purposes if ($path{strlen($path) - 1} == "/" && $path != "/") { $path = substr($path, 0, -1); } $curLog = new SVNLog; $curLog->entries = array(); $curLog->path = $path; $revStr = ""; if ($brev && $erev) { $revStr = "-r$brev:$erev"; } else if ($brev) { $revStr = "-r$brev:1"; } if (($config->subversionMajorVersion > 1 || $config->subversionMinorVersion >=2) && $limit != 0) { $revStr .= " --limit $limit"; } // Get the log info $path = encodepath($this->getSvnpath($path)); $info = "--verbose"; if ($quiet) $info = "--quiet"; $pegRev = ''; if ($brev) { $pegRev = '@'.$brev; } $cmd = quoteCommand($config->svn." log --xml $info $revStr ".$this->repConfig->svnParams().quote($path.$pegRev)); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($cmd, $descriptorspec, $pipes); if (!is_resource($resource)) { echo "".$lang['BADCMD'].": ".$cmd."
'.$lang['BADCMD'].': '.$cmd.'
'.nl2br($error).'
'; } xml_parser_free($xml_parser); foreach ($curLog->entries as $entryKey => $entry) { $fullModAccess = true; $anyModAccess = (count($entry->mods) == 0); foreach ($entry->mods as $modKey => $mod) { $access = $this->repConfig->hasReadAccess($mod->path); if ($access) { $anyModAccess = true; } else { // hide modified entry when access is prohibited unset($curLog->entries[$entryKey]->mods[$modKey]); $fullModAccess = false; } } if (!$fullModAccess) { // hide commit message when access to any of the entries is prohibited $curLog->entries[$entryKey]->msg = ''; } if (!$anyModAccess) { // hide author and date when access to all of the entries is prohibited $curLog->entries[$entryKey]->author = ''; $curLog->entries[$entryKey]->date = ''; $curLog->entries[$entryKey]->committime = ''; $curLog->entries[$entryKey]->age = ''; } } return $curLog; } // }}} function isFile($path, $rev = 0) { global $config; $path = encodepath($this->getSvnpath($path)); if ($rev != 0) { $rev = '@'.$rev; } else { $rev = ''; } $cmd = $config->svn." info --xml ".$this->repConfig->svnParams().quote($path.$rev); $output = runCommand($cmd, true); return strpos(implode(' ', $output), 'kind="file"') !== false; } // {{{ getSvnpath function getSvnpath( $path ) { if ($this->repConfig->subpath === null) { return $this->repConfig->path.$path; } else { $path = preg_replace('|^/?'.$this->repConfig->subpath.'|', '', $path); return $this->repConfig->path.'/'.$this->repConfig->subpath.$path; } } // }}} } // {{{ initSvnVersion function initSvnVersion() { global $config; $ret = runCommand($config->svn_noparams." --version", false); if (preg_match("~([0-9]?)\.([0-9]?)\.([0-9]?)~",$ret[0],$matches)) { $config->setSubversionVersion($matches[0]); $config->setSubversionMajorVersion($matches[1]); $config->setSubversionMinorVersion($matches[2]); } } // }}} path, $b->path); } class SVNLog { var $entries; // Array of entries var $curEntry; // Current entry var $path = ''; // Temporary variable used to trace path history // findEntry // // Return the entry for a given revision function findEntry($rev) { foreach ($this->entries as $index => $entry) { if ($entry->rev == $rev) { return $index; } } } } // }}} // {{{ XML parsing functions--- $curTag = ''; $curList = 0; // {{{ listStartElement function listStartElement($parser, $name, $attrs) { global $curList, $curTag, $debugxml; switch ($name) { case "LIST": if ($debugxml) print "Starting list\n"; if (sizeof($attrs)) { while (list($k, $v) = each($attrs)) { switch ($k) { case "PATH": if ($debugxml) print "Path $v\n"; $curList->path = $v; break; } } } break; case "ENTRY": if ($debugxml) print "Creating new entry\n"; $curList->curEntry = new SVNListEntry; if (sizeof($attrs)) { while (list($k, $v) = each($attrs)) { switch ($k) { case "KIND": if ($debugxml) print "Kind $v\n"; $curList->curEntry->isdir = ($v == 'dir'); break; } } } break; case "COMMIT": if ($debugxml) print "Commit\n"; if (sizeof($attrs)) { while (list($k, $v) = each($attrs)) { switch ($k) { case "REVISION": if ($debugxml) print "Revision $v\n"; $curList->curEntry->rev = $v; break; } } } break; default: $curTag = $name; break; } } // }}} // {{{ listEndElement function listEndElement($parser, $name) { global $curList, $debugxml, $curTag; switch ($name) { case "ENTRY": if ($debugxml) print "Ending new list entry\n"; if ($curList->curEntry->isdir) { $curList->curEntry->file .= '/'; } $curList->entries[] = $curList->curEntry; $curList->curEntry = null; break; } $curTag = ""; } // }}} // {{{ listCharacterData function listCharacterData($parser, $data) { global $curList, $curTag, $lang, $debugxml; switch ($curTag) { case "NAME": if ($debugxml) print "Name: $data\n"; if (empty($data)) return; $curList->curEntry->file .= $data; break; case "AUTHOR": if ($debugxml) print "Author: $data\n"; if (empty($data)) return; $curList->curEntry->author .= htmlentities($data, ENT_COMPAT, "UTF-8"); break; case "DATE": if ($debugxml) print "Date: $data\n"; $data = trim($data); if (empty($data)) return; sscanf($data, "%d-%d-%dT%d:%d:%d.", $y, $mo, $d, $h, $m, $s); $mo = substr("00".$mo, -2); $d = substr("00".$d, -2); $h = substr("00".$h, -2); $m = substr("00".$m, -2); $s = substr("00".$s, -2); $curList->curEntry->date = "$y-$mo-$d $h:$m:$s GMT"; $committime = strtotime($curList->curEntry->date); $curList->curEntry->committime = $committime; $curtime = time(); // Get the number of seconds since the commit $agesecs = $curtime - $committime; if ($agesecs < 0) $agesecs = 0; $curList->curEntry->age = datetimeFormatDuration($agesecs, true, true); break; } } // }}} $curLog = 0; // {{{ logStartElement function logStartElement($parser, $name, $attrs) { global $curLog, $curTag, $debugxml; switch ($name) { case "LOGENTRY": if ($debugxml) print "Creating new log entry\n"; $curLog->curEntry = new SVNLogEntry; $curLog->curEntry->mods = array(); $curLog->curEntry->path = $curLog->path; if (sizeof($attrs)) { while (list($k, $v) = each($attrs)) { switch ($k) { case "REVISION": if ($debugxml) print "Revision $v\n"; $curLog->curEntry->rev = $v; break; } } } break; case "PATH": if ($debugxml) print "Creating new path\n"; $curLog->curEntry->curMod = new SVNMod; if (sizeof($attrs)) { while (list($k, $v) = each($attrs)) { switch ($k) { case "ACTION": if ($debugxml) print "Action $v\n"; $curLog->curEntry->curMod->action = $v; break; case "COPYFROM-PATH": if ($debugxml) print "Copy from: $v\n"; $curLog->curEntry->curMod->copyfrom = $v; break; case "COPYFROM-REV": $curLog->curEntry->curMod->copyrev = $v; break; } } } $curTag = $name; break; default: $curTag = $name; break; } } // }}} // {{{ logEndElement function logEndElement($parser, $name) { global $curLog, $debugxml, $curTag; switch ($name) { case "LOGENTRY": if ($debugxml) print "Ending new log entry\n"; $curLog->entries[] = $curLog->curEntry; break; case "PATH": if ($debugxml) print "Ending path\n"; $curLog->curEntry->mods[] = $curLog->curEntry->curMod; break; case "MSG": $curLog->curEntry->msg = trim($curLog->curEntry->msg); if ($debugxml) print "Completed msg = '".$curLog->curEntry->msg."'\n"; break; } $curTag = ""; } // }}} // {{{ logCharacterData function logCharacterData($parser, $data) { global $curLog, $curTag, $lang, $debugxml; switch ($curTag) { case "AUTHOR": if ($debugxml) print "Author: $data\n"; if (empty($data)) return; $curLog->curEntry->author .= htmlentities($data, ENT_COMPAT, "UTF-8"); break; case "DATE": if ($debugxml) print "Date: $data\n"; $data = trim($data); if (empty($data)) return; sscanf($data, "%d-%d-%dT%d:%d:%d.", $y, $mo, $d, $h, $m, $s); $mo = substr("00".$mo, -2); $d = substr("00".$d, -2); $h = substr("00".$h, -2); $m = substr("00".$m, -2); $s = substr("00".$s, -2); $curLog->curEntry->date = "$y-$mo-$d $h:$m:$s GMT"; $committime = strtotime($curLog->curEntry->date); $curLog->curEntry->committime = $committime; $curtime = time(); // Get the number of seconds since the commit $agesecs = $curtime - $committime; if ($agesecs < 0) $agesecs = 0; $curLog->curEntry->age = datetimeFormatDuration($agesecs, true, true); break; case "MSG": if ($debugxml) print "Msg: '$data'\n"; $curLog->curEntry->msg .= htmlentities($data, ENT_COMPAT, "UTF-8"); break; case "PATH": if ($debugxml) print "Path name: '$data'\n"; $data = trim($data); if (empty($data)) return; $curLog->curEntry->curMod->path .= $data; // The XML returned when a file is renamed/branched in inconsistant. In the case // of a branch, the path information doesn't include the leafname. In the case of // a rename, it does. Ludicrous. if (!empty($curLog->path)) { $pos = strrpos($curLog->path, "/"); $curpath = substr($curLog->path, 0, $pos); $leafname = substr($curLog->path, $pos + 1); } else { $curpath = ""; $leafname = ""; } if ($curLog->curEntry->curMod->action == "A") { if ($debugxml) print "Examining added path '".$curLog->curEntry->curMod->copyfrom."' - Current path = '$curpath', leafname = '$leafname'\n"; if ($data == $curLog->path) { // For directories and renames if ($debugxml) print "New path for comparison: '".$curLog->curEntry->curMod->copyfrom."'\n"; $curLog->path = $curLog->curEntry->curMod->copyfrom; } else if ($data == $curpath || $data == $curpath."/") { // Logs of files that have moved due to branching if ($debugxml) print "New path for comparison: '".$curLog->curEntry->curMod->copyfrom."/$leafname'\n"; $curLog->path = $curLog->curEntry->curMod->copyfrom."/$leafname"; } } break; } } // }}} // }}} // {{{ internal functions (_topLevel and _listSort) // Function returns true if the give entry in a directory tree is at the top level function _topLevel($entry) { // To be at top level, there must be one space before the entry return (strlen($entry) > 1 && $entry{0} == " " && $entry{1} != " "); } // Function to sort two given directory entries. Directories go at the top function _listSort($e1, $e2) { $isDir1 = $e1->file{strlen($e1->file) - 1} == "/"; $isDir2 = $e2->file{strlen($e2->file) - 1} == "/"; if ($isDir1 && !$isDir2) return -1; if ($isDir2 && !$isDir1) return 1; return strnatcasecmp($e1->file, $e2->file); } // }}} // {{{ encodePath // Function to encode a URL without encoding the /'s function encodePath($uri) { global $config; $uri = str_replace(DIRECTORY_SEPARATOR, "/", $uri); $parts = explode('/', $uri); for ($i = 0; $i < count($parts); $i++) { if ( function_exists("mb_detect_encoding") && function_exists("mb_convert_encoding")) { $parts[$i] = mb_convert_encoding($parts[$i], "UTF-8", mb_detect_encoding($parts[$i])); } $parts[$i] = rawurlencode($parts[$i]); } $uri = implode('/', $parts); // Quick hack. Subversion seems to have a bug surrounding the use of %3A instead of : $uri = str_replace("%3A" ,":", $uri); // Correct for Window share names if ( $config->serverIsWindows==true ) { if (substr($uri, 0,2) == "//") { $uri = "\\".substr($uri, 2, strlen($uri)); } if (substr($uri, 0,10)=="file://///" ) { $uri="file:///\\".substr($uri, 10, strlen($uri)); } } return $uri; } // }}} // The SVNRepository class class SVNRepository { var $repConfig; function SVNRepository($repConfig) { $this->repConfig = $repConfig; } // {{{ highlightLine // // Distill line-spanning syntax highlighting so that each line can stand alone // (when invoking on the first line, $attributes should be an empty array) // Invoked to make sure all open syntax highlighting tags (, , , etc.) // are closed at the end of each line and re-opened on the next line function highlightLine($line, &$attributes) { $hline = ""; // Apply any highlighting in effect from the previous line foreach ($attributes as $attr) { $hline.=$attr['text']; } // append the new line $hline.=$line; // update attributes for ($line = strstr($line, "<"); $line; $line = strstr(substr($line,1), "<")) { if (substr($line,1,1) == "/") { // if this closes a tag, remove most recent corresponding opener $tagNamLen = strcspn($line, "> \t", 2); $tagNam = substr($line,2,$tagNamLen); foreach (array_reverse(array_keys($attributes)) as $k) { if ($attributes[$k]['tag'] == $tagNam) { unset($attributes[$k]); break; } } } else { // if this opens a tag, add it to the list $tagNamLen = strcspn($line, "> \t", 1); $tagNam = substr($line,1,$tagNamLen); $tagLen = strcspn($line, ">") + 1; $attributes[] = array('tag' => $tagNam, 'text' => substr($line,0,$tagLen)); } } // close any still-open tags foreach (array_reverse($attributes) as $attr) { $hline.=""; } // XXX: this just simply replaces [ and ] with their entities to prevent // it from being parsed by the template parser; maybe something more // elegant is in order? $hline = str_replace('[', '[', str_replace(']', ']', $hline) ); return $hline; } // }}} // {{{ getFileContents // // Dump the content of a file to the given filename function getFileContents($path, $filename, $rev = 0, $pipe = "", $perLineHighlighting = false) { global $config, $extEnscript; // If there's no filename, we'll just deliver the contents as it is to the user if ($filename == "") { $path = encodepath($this->repConfig->path.$path); passthru(quoteCommand($config->svn." cat ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' '.$pipe)); return; } // Get the file contents info $ext = strrchr($path, "."); $l = @$extEnscript[$ext]; if ($l == "php") { // Output the file to the filename $path = encodepath($this->repConfig->path.$path); $cmd = quoteCommand($config->svn." cat ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' > '.quote($filename)); @exec($cmd); // Get the file as a string (memory hogging, but we have no other options) $content = highlight_file($filename, true); // Destroy the previous version, and replace it with the highlighted version $f = fopen($filename, "w"); if ($f) { // The highlight file function doesn't deal with line endings very nicely at all. We'll have to do it // by hand. // Remove the first line generated by highlight() $pos = strpos($content, "\n"); $content = substr($content, $pos+1); $content = explode("and. // It's complicated because it's designed not to return those lines themselves. $path = encodepath($this->repConfig->path.$path); $cmd = quoteCommand($config->svn." cat ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' | '. $config->enscript." --language=html ". ($l ? "--color --pretty-print=$l" : "")." -o - | ". $config->sed." -n ".$config->quote."1,/^
"; while (!feof($result)) { $line = fgets($result, 1024); if ($pre) $line = replaceEntities($line, $this->repConfig); print hardspace($line); } if ($pre) echo ""; pclose($result); } } } // }}} // {{{ getBlameDetails // // Dump the blame content of a file to the given filename function getBlameDetails($path, $filename, $rev = 0) { global $config; $path = encodepath($this->repConfig->path.$path); $cmd = quoteCommand($config->svn." blame ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' > '.quote($filename)); @exec($cmd); } // }}} // {{{ getProperty function getProperty($path, $property, $rev = 0) { global $config; $path = encodepath($this->repConfig->path.$path); if ($rev > 0) { $rev = ' -r '.$rev; } else { $rev = ''; } $ret = runCommand($config->svn." propget $property ".$this->repConfig->svnParams().quote($path).$rev, true); // Remove the surplus newline if (count($ret)) { unset($ret[count($ret) - 1]); } return implode("\n", $ret); } // }}} // {{{ exportDirectory // // Exports the directory to the given location function exportDirectory($path, $filename, $rev = 0) { global $config; $path = encodepath($this->repConfig->path.$path); $cmd = quoteCommand($config->svn." export ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' '.quote($filename)); @exec($cmd); } // }}} // {{{ getList function getList($path, $rev = 0) { global $config, $curList, $vars, $lang; $xml_parser = xml_parser_create("UTF-8"); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xml_parser, "listStartElement", "listEndElement"); xml_set_character_data_handler($xml_parser, "listCharacterData"); // Since directories returned by svn log don't have trailing slashes (:-(), we need to remove // the trailing slash from the path for comparison purposes if ($path{strlen($path) - 1} == "/" && $path != "/") { $path = substr($path, 0, -1); } $curList = new SVNList; $curList->entries = array(); $curList->path = $path; // Get the list info $path = encodepath($this->repConfig->path.$path); if ($rev == 0) { $headlog = $this->getLog("/", "", "", true, 1); if (isset($headlog->entries[0])) $rev = $headlog->entries[0]->rev; } $revStr = "-r $rev"; $cmd = quoteCommand($config->svn." list --xml $revStr ".$this->repConfig->svnParams().quote($path)); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($cmd, $descriptorspec, $pipes); $error = ""; if (!is_resource($resource)) { echo "
".$lang['BADCMD'].": ".$cmd."
".$lang['BADCMD'].": ".$cmd."
".nl2br($error)."
"; exit; } xml_parser_free($xml_parser); // Sort the entries into alphabetical order with the directories at the top of the list usort($curList->entries, "_listSort"); return $curList; } // }}} // {{{ getLog function getLog($path, $brev = "", $erev = 1, $quiet = false, $limit = 2) { global $config, $curLog, $vars, $lang; $xml_parser = xml_parser_create("UTF-8"); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xml_parser, "logStartElement", "logEndElement"); xml_set_character_data_handler($xml_parser, "logCharacterData"); // Since directories returned by svn log don't have trailing slashes (:-(), we need to remove // the trailing slash from the path for comparison purposes if ($path{strlen($path) - 1} == "/" && $path != "/") { $path = substr($path, 0, -1); } $curLog = new SVNLog; $curLog->entries = array(); $curLog->path = $path; $revStr = ""; if ($brev && $erev) { $revStr = "-r$brev:$erev"; } else if ($brev) { $revStr = "-r$brev:1"; } if (($config->subversionMajorVersion > 1 || $config->subversionMinorVersion >=2) && $limit != 0) { $revStr .= " --limit $limit"; } // Get the log info $path = encodepath($this->repConfig->path.$path); $info = "--verbose"; if ($quiet) $info = "--quiet"; $cmd = quoteCommand($config->svn." log --xml $info $revStr ".$this->repConfig->svnParams().quote($path)); $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $resource = proc_open($cmd, $descriptorspec, $pipes); $error = ""; if (!is_resource($resource)) { echo "".$lang['BADCMD'].": ".$cmd."
".$lang['BADCMD'].": ".$cmd."
".nl2br($error)."
"; exit; } xml_parser_free($xml_parser); foreach ($curLog->entries as $entryKey => $entry) { $fullModAccess = true; $anyModAccess = (count($entry->mods) == 0); foreach ($entry->mods as $modKey => $mod) { $access = $this->repConfig->hasReadAccess($mod->path); if ($access) { $anyModAccess = true; } else { // hide modified entry when access is prohibited unset($curLog->entries[$entryKey]->mods[$modKey]); $fullModAccess = false; } } if (!$fullModAccess) { // hide commit message when access to any of the entries is prohibited $curLog->entries[$entryKey]->msg = ''; } if (!$anyModAccess) { // hide author and date when access to all of the entries is prohibited $curLog->entries[$entryKey]->author = ''; $curLog->entries[$entryKey]->date = ''; $curLog->entries[$entryKey]->committime = ''; $curLog->entries[$entryKey]->age = ''; } } return $curLog; } // }}} } // {{{ initSvnVersion function initSvnVersion(&$major, &$minor) { global $config; $ret = runCommand($config->svn_noparams." --version", false); if (preg_match("~([0-9]?)\.([0-9]?)\.([0-9]?)~",$ret[0],$matches)) { $major = $matches[1]; $minor = $matches[2]; } $config->setSubversionMajorVersion($major); $config->setSubversionMinorVersion($minor); } // }}}websvn |
Subversion Repositories: |
Rev 1 | Rev 3 |
---|