2 /*=====================================================================*\
3 || ###################################################################
4 || # ViewSVN [#]version[#]
5 || # Copyright ©2002-[#]year[#] Iris Studios, Inc.
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
23 * Common functions that aren't Xquery-related and advanced query systems
29 * Interacts with the command line subsystem to
30 * access SVN information
38 * Prepares data for output
42 * @param string Standard data
44 * @return string Output-ready data
46 function format($string)
49 $string = htmlspecialchars($string);
52 $string = str_replace("\t", ' ', $string);
57 $string = preg_replace('#( +)#e', '$this->format_spaces("\1")', $string);
62 $string = str_replace(' ', ' ', $string);
65 // convert advanced diff
66 $string = str_replace(array('{@+' . '+}', '{@-' . '-}'), array('<span class="diff_add_bit">', '<span class="diff_del_bit">'), $string);
67 $string = str_replace(array('{/@+' . '+}', '{/@-' . '-}'), '</span>', $string);
70 $string = nl2br($string);
76 * Formats a SVN log message
80 * @param string Unformatted log message
82 * @return string Output-ready log message
84 function format_log_message($message)
88 $message = $viewsvn->entity_encode($message);
90 $message = preg_replace('#r([0-9]+)#e', '"<a href=\"" . $viewsvn->path . "/" . $viewsvn->paths->out("diff.php" . $viewsvn->paths->fetch_rev_str(true, "\1", 0), $viewsvn->paths->fetch_repos($viewsvn->paths->parse()) . "/") . "\">r\1</a>"', $message);
93 $lines = explode("\n", $message);
95 foreach ($lines AS $line)
97 if (preg_match('#^\s*?(\*|\-)\s?(.*)#', $line, $matches))
101 $message .= '<li>' . $matches[2] . '</li>';
105 $message .= '<ul class="list">';
106 $message .= '<li>' . $matches[2] . '</li>';
120 $message .= '<br />';
133 $message = preg_replace('#(<br />)*$#', '', $message);
138 // ###################################################################
140 * Parses a date from Xquery XML outut
144 * @param string Date string
146 * @return string Formatted and readable date string
148 function format_date_string($string)
150 // 2005-01-23T20:42:53.703057Z
151 return preg_replace('#(....)\-(..)\-(..)T(..):(..):(..).(.*)Z#e', 'gmdate("r", mktime(\4, \5, \6, \2, \3, \1))', $string);
155 * Counts the spaces and replaces two or more ones
159 * @param string Spaced string
161 * @return string 'd string
163 function format_spaces($thestring)
165 if (strlen($thestring) >= 2)
167 $thestring = str_replace(' ', ' ', $thestring);
174 * Prints the file changed list
178 * @public array List of file changes
179 * @public string The repository
180 * @public integer Current revision
182 * @return string Processed HTML
184 function construct_file_changes($changes, $repos, $revision)
190 foreach ($changes AS $file)
192 switch ($file['action'])
196 $tooltip = $viewsvn->lang
->string('Added');
199 $class = 'file_delete';
200 $tooltip = $viewsvn->lang
->string('Deleted');
203 $class = 'file_modify';
204 $tooltip = $viewsvn->lang
->string('Modified');
207 $class = 'file_replace';
208 $tooltip = $viewsvn->lang
->string('Replaced');
212 $show['from'] = (bool
)$file['from'];
216 $class = 'file_move';
217 $tooltip = 'Moved/Copied';
218 preg_match('#(.*):([0-9]+)#', $file['from'], $matches);
219 $link['from'] = $viewsvn->paths
->out('view.php' . $viewsvn->paths
->fetch_rev_str(false
, $matches[2]), $repos . $matches[1]);
222 $link['file'] = $viewsvn->paths
->out('view.php' . $viewsvn->paths
->fetch_rev_str(false
, $revision), $repos . $file['file']);
224 eval('$files .= "' . $viewsvn->template
->fetch('file_change') . '";');
231 * Generates a clean revision number
235 * @param integer Revision number
237 * @return mixed Cleaned revision or HEAD
239 function rev($revision)
241 if (($revision = intval($revision)) < 1)
250 * Annotation/blame system; constructs an array
251 * that is ready for output
259 * Array of blame information
262 var $blame = array();
265 * Raw "svn blame" output
271 * Constructor: create blame and store data
273 * @param string Repository
275 * @param integer Revision
277 function SVNBlame($repos, $path, $revision)
281 $this->rawoutput
= $viewsvn->svn
->blame($repos, $path, $revision);
286 * Returns blame for display
290 * @return array Blame data
298 * Parses the blame data
306 foreach ($this->rawoutput
AS $line)
308 if (preg_match('#^\s+([0-9]+)\s+([\w\.\-_]+)\s(.*)$#', $line, $matches))
310 $this->blame
[] = array(
311 'rev' => $matches[1],
312 'author' => $matches[2],
313 'line' => $matches[3],
314 'lineno' => $lineno++
318 else if (preg_match('#^\s+([0-9]+)\s+([\w\.\-_]+)$#', $line, $matches))
320 $this->blame
[] = array(
321 'rev' => $matches[1],
322 'author' => $matches[2],
324 'lineno' => $lineno++
332 * Log management system; creates a complex list
333 * of SVN log information
347 * Raw "svn log" output
353 * Constructor: create log store for the given file
355 * @param string Repository
357 * @param integer Lower revision
358 * @param integer Higher revision
360 function SVNLog($repos, $path, $lorev, $hirev)
364 $this->rawoutput
= $viewsvn->svn
->log($repos, $path, $lorev, $hirev);
369 * Returns logs for display
373 * @return array Log data
381 * Splits up the raw output into a usable log
389 for ($i = 1; $i <= count($this->rawoutput
) - 1; $i++
)
391 $line = $this->rawoutput
["$i"];
393 if (preg_match('#^r([0-9]*) \| (.*?) \| (....-..-.. ..:..:..) ([0-9\-]*) \((.*?)\) \| ([0-9]*) lines?$#', $line, $matches))
395 if (isset($this->logs
["$lastrev"]))
397 $this->logs
["$lastrev"]['message'] = $this->strip_last_line($this->logs
["$lastrev"]['message']);
400 $this->logs
["$matches[1]"] = array(
401 'rev' => $matches[1],
402 'author' => $matches[2],
403 'date' => $matches[3],
404 'timezone' => $matches[4],
405 'lines' => $matches[6],
409 $lastrev = $matches[1];
411 else if (preg_match('#^\s+([ADMR])\s(.*)#', $line, $matches))
413 if (preg_match('#(.*) \(from (.*?)\)$#', $matches[2], $amatches))
415 $matches[2] = $amatches[1];
418 $this->logs
["$lastrev"]['files'][] = array(
419 'action' => $matches[1],
420 'file' => trim($matches[2]),
421 'from' => (isset($amatches[2]) ?
$amatches[2] : '')
426 if (trim($line) != 'Changed paths:')
428 $this->logs
["$lastrev"]['message'] .= $line . "\n";
433 if (isset($this->logs
["$lastrev"]))
435 $this->logs
["$lastrev"]['message'] = $this->strip_last_line($this->logs
["$lastrev"]['message']);
440 * Trims the last dash line off a message
444 * @param string Message with annoying-ass line
446 * @return string Clean string
448 function strip_last_line($string)
450 return trim(preg_replace("#\n(.*?)\n$#", '', $string));
455 * Diff system; constructs a diff array that
456 * is ready for output
463 * Array of diff information
469 * Raw "svn diff" output
475 * Constructor: create and store diff data
477 * @param string Repository
479 * @param integer Lower revision
480 * @param integer Higher revision
482 function SVNDiff($repos, $path, $lorev, $hirev)
486 $this->rawoutput
= $viewsvn->svn
->diff($repos, $path, $lorev, $hirev);
491 * Returns diffs for display
495 * @return array Diff data
503 * Processes and prepares diff data
512 $indexcounter = null
;
517 foreach ($this->rawoutput
AS $line)
519 if (preg_match('#^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@$#', $line, $bits))
523 $this->diff
["$index"][ ++
$chunk ]['hunk'] = array('old' => array('line' => $bits[1], 'count' => $bits[2]), 'new' => array('line' => $bits[3], 'count' => $bits[4]));
524 $lines['old'] = $this->diff
["$index"]["$chunk"]['hunk']['old']['line'] - 1;
525 $lines['new'] = $this->diff
["$index"]["$chunk"]['hunk']['new']['line'] - 1;
528 else if (preg_match('#^Property changes on: (.*?)$#', $line, $bits))
532 $this->diff
["$index"]['props'] = array();
536 if ($indexcounter <= 3 AND $indexcounter !== null
)
541 else if ($indexcounter == 3)
543 $indexcounter = null
;
547 if (preg_match('#^([\+\- ])(.*)#', $line, $matches) AND !$property)
550 $content = $matches[2];
554 $this->diff
["$index"]["$chunk"][] = array(
557 'oldlineno' => ++
$lines['old'],
558 'newlineno' => ++
$lines['new']
563 else if ($act == '+')
565 // potential line delta
566 if (count($delstack) > 0)
568 $lastline = array_shift($delstack);
570 if ($delta = @$this->fetch_diff_extent($lastline['line'], $content))
572 if (strlen($lastline['line']) > ($delta['start'] - $delta['end']))
574 $end = strlen($lastline['line']) +
$delta['end'];
575 $viewsvn->debug("RM delta- = " . $end);
576 $change = '{@-' . '-}' . substr($lastline['line'], $delta['start'], $end - $delta['start']) . '{/@-' . '-}';
577 $this->diff
["$index"]["$chunk"]["$lastline[INDEX]"]['line'] = substr($lastline['line'], 0, $delta['start']) . $change . substr($lastline['line'], $end);
580 if (strlen($content) > $delta['start'] - $delta['end'])
582 $end = strlen($content) +
$delta['end'];
583 $viewsvn->debug("MK delta+ = " . $end);
584 $change = '{@+' . '+}' . substr($content, $delta['start'], $end - $delta['start']) . '{/@+' . '+}';
585 $content = substr($content, 0, $delta['start']) . $change . substr($content, $end);
590 $this->diff
["$index"]["$chunk"][] = array(
594 'newlineno' => ++
$lines['new']
597 else if ($act == '-')
599 $this->diff
["$index"]["$chunk"][] = $thearray = array(
602 'oldlineno' => ++
$lines['old'],
606 $key = count($this->diff
["$index"]["$chunk"]) - 2;
607 $thearray['INDEX'] = $key;
609 array_push($delstack, $thearray);
615 if (preg_match('#^Index: (.*?)$#', $line, $matches))
617 $index = $matches[1];
625 if (preg_match('#^__*_$#', trim($line)))
627 $viewsvn->debug("skipping: $line");
631 if (preg_match('#Name: (.*?)$#', $line, $matches))
633 $curprop = $matches[1];
634 $viewsvn->debug("prop: $curprop");
639 if (preg_match('#^\s+?\+(.*)#', $line, $matches))
642 $this->diff
["$index"]['props']["$curprop"]['add'] .= $matches[1];
644 else if (preg_match('#^\s+?\-(.*)#', $line, $matches))
647 $this->diff
["$index"]['props']["$curprop"]['del'] .= $matches[1];
649 else if (!preg_match('#^\s+[\+\- ](.*)#', $line) AND trim($line) != '')
651 $this->diff
["$index"]['props']["$curprop"]["$mode"] .= "\n" . $line;
657 $this->diff
["$index"]["$chunk"][] = array(
660 'oldlineno' => ++
$lines['old'],
661 'newlineno' => ++
$lines['new']
670 * Returns the amount of change that occured
675 * @param string Old line
676 * @param string New line
678 * @return array Difference of positions
680 function fetch_diff_extent($old, $new)
685 $min = min(strlen($old), strlen($new));
687 $viewsvn->debug("min1 = $min");
689 while ($start < $min AND $old["$start"] == $new["$start"])
695 $min = $min - $start;
697 $viewsvn->debug("min2 = $min");
699 $viewsvn->debug("checking: " . $old[ strlen($old) +
$end ] . ' == ' . $new[ strlen($new) +
$end ]);
701 while (-$end <= $min AND $old[ strlen($old) +
$end ] == $new[ strlen($new) +
$end ])
706 return array('start' => $start, 'end' => $end +
1);
710 /*=====================================================================*\
711 || ###################################################################
714 || ###################################################################
715 \*=====================================================================*/