]>
src.bluestatic.org Git - viewsvn.git/blob - includes/svnlib.php
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 * Command line interface with the SVN commands
29 * Interacts with the command line subsystem to
30 * access SVN information
38 * Path to the SVN binary
51 * Constructor: validate SVN path
53 * @param object Controller
55 function SVNLib (& $controller )
57 $this- > controller
=& $controller ;
59 $this- > svnpath
=& $this- > controller
-> xquery
-> cmd ( $this- > controller
-> registry
-> svnpath
);
61 $access = $this- > controller
-> xquery
-> exec ( $this- > svnpath
. ' --version' );
65 $this- > controller
-> registry
-> trigger
-> error ( $this- > controller
-> registry
-> lang
-> string ( 'The SVN binary could not be located' ));
68 if (! preg_match ( '#^svn, version (.*?)\)$#i' , trim ( $access [ 0 ])))
70 $this- > controller
-> registry
-> trigger
-> error ( $this- > controller
-> registry
-> lang
-> string ( 'The SVN binary does not appear to be valid (it failed our tests)' ));
75 * Executes the SVN binary
79 * @param string Command
81 * @return array Output
83 function svn ( $command )
85 $output = $this- > controller
-> xquery
-> exec ( $this- > svnpath
. ' ' . $command . ' 2>&1' );
87 // make sure that we keep escaped chars
88 //$output = str_replace(array('\t', '\n', '\r'), array('\\\t', '\\\n', '\\\r'), $output);
89 //$output = preg_replace('#\\\(.)#', '\\\\\\\\' . '\1', $output);
90 //$output = str_replace('\\', '\\\\', $output);
92 $temp = implode ( " \n " , $output );
93 if ( strpos ( $temp , '(apr' . '_err=' ) !== false )
95 $this- > controller
-> registry
-> trigger
-> error ( nl2br ( $temp ));
101 * SVN Wrapper: standard command system
105 * @param string SVN command
106 * @param string Repository
108 * @param integer Revision
110 * @return array Lines of output
112 function std ( $command , $repos , $path , $revision )
116 $revision = SVNCommon
:: rev ( $revision );
117 $repospath = $viewsvn- > repos
-> fetch_path ( $repos , false );
119 return $this- > svn ( $command . ' ' . $repospath . $path . '@' . $revision );
127 * @param string Repository
129 * @param integer Revision
131 * @return array Lines of blame output
133 function blame ( $repos , $path , $revision )
135 return $this- > std ( 'blame' , $repos , $path , $revision );
143 * @param string Repository
145 * @param integer Revision
147 * @return array Lines of cat output
149 function cat ( $repos , $path , $revision )
151 return $this- > std ( 'cat' , $repos , $path , $revision );
159 * @param string Repository
161 * @param integer Lower revision
162 * @param integer Higher revision
164 * @return array Lines of diff output
166 function diff ( $repos , $path , $lorev , $hirev )
170 $hirev = $this- > rev ( $hirev );
171 $lorev = $this- > rev ( $lorev );
172 if ( $lorev == 'HEAD' )
177 if ( is_integer ( $hirev ) AND is_integer ( $lorev ))
183 if ( $lorev == $hirev )
189 $repospath = $viewsvn- > repos
-> fetch_path ( $repos , false );
191 return $this- > svn ( 'diff -r' . $lorev . ':' . $hirev . ' ' . $repospath . $path );
199 * @param string Repository
201 * @param integer Lower revision
202 * @param integer Higher revision
204 * @return array Lines of log output
206 function log ( $repos , $path , $lorev , $hirev )
210 $hirev = $this- > rev ( $hirev );
211 $lorev = $this- > rev ( $hirev );
212 if ( $lorev == 'HEAD' )
217 if ( is_integer ( $hirev ) AND is_integer ( $lorev ))
223 if ( $lorev == $hirev )
229 $repospath = $viewsvn- > repos
-> fetch_path ( $repos , false );
231 return $this- > svn ( 'log -v -r' . $hirev . ':' . $lorev . ' ' . $repospath . $path );
235 * SVN Wrapper: ls (list)
239 * @param string Repository
241 * @param integer Revision
243 * @return array Lines of list output
245 function ls ( $repos , $path , $revision )
247 return $this- > std ( 'list' , $repos , $path , $revision );
252 * Annotation/blame system; constructs an array
253 * that is ready for output
261 * Array of blame information
264 var $blame = array ();
267 * Raw "svn blame" output
273 * Constructor: create blame and store data
275 * @param string Repository
277 * @param integer Revision
279 function SVNBlame ( $repos , $path , $revision )
283 $this- > rawoutput
= $viewsvn- > svn
-> blame ( $repos , $path , $revision );
288 * Returns blame for display
292 * @return array Blame data
300 * Parses the blame data
308 foreach ( $this- > rawoutput
AS $line )
310 if ( preg_match ( '#^\s+([0-9]+)\s+([\w\.\-_]+)\s(.*)$#' , $line , $matches ))
312 $this- > blame
[] = array (
313 'rev' => $matches [ 1 ],
314 'author' => $matches [ 2 ],
315 'line' => $matches [ 3 ],
316 'lineno' => $lineno ++
320 else if ( preg_match ( '#^\s+([0-9]+)\s+([\w\.\-_]+)$#' , $line , $matches ))
322 $this- > blame
[] = array (
323 'rev' => $matches [ 1 ],
324 'author' => $matches [ 2 ],
326 'lineno' => $lineno ++
334 * Log management system; creates a complex list
335 * of SVN log information
349 * Raw "svn log" output
355 * Constructor: create log store for the given file
357 * @param string Repository
359 * @param integer Lower revision
360 * @param integer Higher revision
362 function SVNLog ( $repos , $path , $lorev , $hirev )
366 $this- > rawoutput
= $viewsvn- > svn
-> log ( $repos , $path , $lorev , $hirev );
371 * Returns logs for display
375 * @return array Log data
383 * Splits up the raw output into a usable log
391 for ( $i = 1 ; $i <= count ( $this- > rawoutput
) - 1 ; $i ++
)
393 $line = $this- > rawoutput
[ " $i" ];
395 if (preg_match('#^r([0-9]*) \| (.*?) \| (....-..-.. ..:..:..) ([0-9\-]*) \((.*?)\) \| ([0-9]*) lines?$#', $line , $matches ))
397 if (isset( $this- >logs[" $lastrev" ]))
399 $this- > logs
[ " $lastrev" ]['message'] = $this- >strip_last_line( $this- >logs[" $lastrev" ][ 'message' ]);
402 $this- > logs
[ " $matches [1]" ] = array (
403 'rev' => $matches [ 1 ],
404 'author' => $matches [ 2 ],
405 'date' => $matches [ 3 ],
406 'timezone' => $matches [ 4 ],
407 'lines' => $matches [ 6 ],
411 $lastrev = $matches [ 1 ];
413 else if ( preg_match ( '#^\s+([ADMR])\s(.*)#' , $line , $matches ))
415 if ( preg_match ( '#(.*) \(from (.*?)\)$#' , $matches [ 2 ], $amatches ))
417 $matches [ 2 ] = $amatches [ 1 ];
420 $this- > logs
[ " $lastrev" ]['files'][] = array(
421 'action' => $matches [1],
422 'file' => trim( $matches [2]),
423 'from' => (isset( $amatches [2]) ? $amatches [2] : '')
428 if (trim( $line ) != 'Changed paths:')
430 $this- >logs[" $lastrev" ][ 'message' ] .= $line . " \n " ;
435 if ( isset ( $this- > logs
[ " $lastrev" ]))
437 $this- >logs[" $lastrev" ][ 'message' ] = $this- > strip_last_line ( $this- > logs
[ " $lastrev" ]['message']);
442 * Trims the last dash line off a message
446 * @param string Message with annoying-ass line
448 * @return string Clean string
450 function strip_last_line( $string )
452 return trim(preg_replace(" #\n(.*?)\n$#", '', $string));
457 * Diff system; constructs a diff array that
458 * is ready for output
465 * Array of diff information
471 * Raw "svn diff" output
477 * Constructor: create and store diff data
479 * @param string Repository
481 * @param integer Lower revision
482 * @param integer Higher revision
484 function SVNDiff ( $repos , $path , $lorev , $hirev )
488 $this- > rawoutput
= $viewsvn- > svn
-> diff ( $repos , $path , $lorev , $hirev );
493 * Returns diffs for display
497 * @return array Diff data
505 * Processes and prepares diff data
514 $indexcounter = null ;
519 foreach ( $this- > rawoutput
AS $line )
521 if ( preg_match ( '#^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@$#' , $line , $bits ))
525 $this- > diff
[ " $index" ][ ++ $chunk ]['hunk'] = array('old' => array('line' => $bits [1], 'count' => $bits [2]), 'new' => array('line' => $bits [3], 'count' => $bits [4]));
526 $lines ['old'] = $this- >diff[" $index" ][ " $chunk" ]['hunk']['old']['line'] - 1;
527 $lines ['new'] = $this- >diff[" $index" ][ " $chunk" ]['hunk']['new']['line'] - 1;
530 else if (preg_match('#^Property changes on: (.*?)$#', $line , $bits ))
534 $this- >diff[" $index" ][ 'props' ] = array ();
538 if ( $indexcounter <= 3 AND $indexcounter !== null )
543 else if ( $indexcounter == 3 )
545 $indexcounter = null ;
549 if ( preg_match ( '#^([\+\- ])(.*)#' , $line , $matches ) AND ! $property )
552 $content = $matches [ 2 ];
556 $this- > diff
[ " $index" ][" $chunk" ][] = array (
559 'oldlineno' => ++
$lines [ 'old' ],
560 'newlineno' => ++
$lines [ 'new' ]
565 else if ( $act == '+' )
567 // potential line delta
568 if ( count ( $delstack ) > 0 )
570 $lastline = array_shift ( $delstack );
572 if ( $delta = @ $this- > fetch_diff_extent ( $lastline [ 'line' ], $content ))
574 if ( strlen ( $lastline [ 'line' ]) > ( $delta [ 'start' ] - $delta [ 'end' ]))
576 $end = strlen ( $lastline [ 'line' ]) +
$delta [ 'end' ];
577 $viewsvn- > debug ( "RM delta- = " . $end );
578 $change = ' {@-' . '-} ' . substr ( $lastline [ 'line' ], $delta [ 'start' ], $end - $delta [ 'start' ]) . ' {/@-' . '-} ' ;
579 $this- > diff
[ " $index" ][" $chunk" ][ " $lastline [INDEX]" ][ 'line' ] = substr ( $lastline [ 'line' ], 0 , $delta [ 'start' ]) . $change . substr ( $lastline [ 'line' ], $end );
582 if ( strlen ( $content ) > $delta [ 'start' ] - $delta [ 'end' ])
584 $end = strlen ( $content ) +
$delta [ 'end' ];
585 $viewsvn- > debug ( "MK delta+ = " . $end );
586 $change = ' {@+' . '+} ' . substr ( $content , $delta [ 'start' ], $end - $delta [ 'start' ]) . ' {/@+' . '+} ' ;
587 $content = substr ( $content , 0 , $delta [ 'start' ]) . $change . substr ( $content , $end );
592 $this- > diff
[ " $index" ][" $chunk" ][] = array (
596 'newlineno' => ++
$lines [ 'new' ]
599 else if ( $act == '-' )
601 $this- > diff
[ " $index" ][" $chunk" ][] = $thearray = array (
604 'oldlineno' => ++
$lines [ 'old' ],
608 $key = count ( $this- > diff
[ " $index" ][" $chunk" ]) - 2 ;
609 $thearray [ 'INDEX' ] = $key ;
611 array_push ( $delstack , $thearray );
617 if ( preg_match ( '#^Index: (.*?)$#' , $line , $matches ))
619 $index = $matches [ 1 ];
627 if ( preg_match ( '#^__*_$#' , trim ( $line )))
629 $viewsvn- > debug ( "skipping: $line" );
633 if (preg_match('#Name: (.*?)$#', $line , $matches ))
635 $curprop = $matches [1];
636 $viewsvn- >debug(" prop
: $curprop" );
641 if ( preg_match ( '#^\s+?\+(.*)#' , $line , $matches ))
644 $this- > diff
[ " $index" ]['props'][" $curprop" ][ 'add' ] .= $matches [ 1 ];
646 else if ( preg_match ( '#^\s+?\-(.*)#' , $line , $matches ))
649 $this- > diff
[ " $index" ]['props'][" $curprop" ][ 'del' ] .= $matches [ 1 ];
651 else if (! preg_match ( '#^\s+[\+\- ](.*)#' , $line ) AND trim ( $line ) != '' )
653 $this- > diff
[ " $index" ]['props'][" $curprop" ][ " $mode" ] .= " \n
" . $line ;
659 $this- >diff[" $index" ][ " $chunk" ][] = array(
662 'oldlineno' => ++ $lines ['old'],
663 'newlineno' => ++ $lines ['new']
672 * Returns the amount of change that occured
677 * @param string Old line
678 * @param string New line
680 * @return array Difference of positions
682 function fetch_diff_extent( $old , $new )
687 $min = min(strlen( $old ), strlen( $new ));
689 $viewsvn- >debug(" min1
= $min" );
691 while ( $start < $min AND $old [ " $start" ] == $new [" $start" ])
697 $min = $min - $start ;
699 $viewsvn- > debug ( "min2 = $min" );
701 $viewsvn- >debug(" checking
: " . $old [ strlen( $old ) + $end ] . ' == ' . $new [ strlen( $new ) + $end ]);
703 while (- $end <= $min AND $old [ strlen( $old ) + $end ] == $new [ strlen( $new ) + $end ])
708 return array('start' => $start , 'end' => $end + 1);
712 /*=====================================================================*\
713 || ###################################################################
716 || ###################################################################
717 \*=====================================================================*/