]>
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 library and SVN-PHP bridge extension
29 * This class acts as the bridge between the command line Xquery class
30 * and the various display files. It handles preparation of Xquery
39 * Path to the SVN binary
52 // ###################################################################
54 * Constructor: validate SVN path
56 * @param object Controller
58 function SVNLib (& $controller )
60 $this- > controller
=& $controller ;
62 $this- > svnpath
=& $this- > controller
-> xquery
-> cmd ( $this- > controller
-> registry
-> svnpath
);
64 $access = $this- > controller
-> xquery
-> exec ( $this- > svnpath
. ' --version' );
68 $this- > controller
-> registry
-> trigger
-> error ( $this- > controller
-> registry
-> lang
-> string ( 'The SVN binary could not be located' ));
71 if (! preg_match ( '#^svn, version (.*?)\)$#i' , trim ( $access [ 0 ])))
73 $this- > controller
-> registry
-> trigger
-> error ( $this- > controller
-> registry
-> lang
-> string ( 'The SVN binary does not appear to be valid (it failed our tests)' ));
77 // ###################################################################
79 * Executes the SVN binary
83 * @param string Command
85 * @return array Output
87 function svn ( $command )
89 $output = $this- > controller
-> xquery
-> exec ( $this- > svnpath
. ' ' . $command . ' 2>&1' );
91 $temp = implode ( " \n " , $output );
92 if ( strpos ( $temp , '(apr' . '_err=' ) !== false )
94 $this- > controller
-> registry
-> trigger
-> error ( nl2br ( $temp ));
99 // ###################################################################
101 * This function is used to prepare a common command. It sends the
102 * specified command along with the repository path and the current
103 * node. The revision is either fectched from the argument list or
104 * from the node, too.
108 * @param string SVN command
109 * @param bool Alternate revision
111 * @return array Lines of output
113 function command ( $command , $rev = false )
117 $revision = ( $rev !== false ? $rev : SVNCommon
:: rev ( $this- > controller
-> revnum
));
119 return $this- > svn ( $command . ' ' . $this- > controller
-> repospath
. $this- > controller
-> path
. ( $revision !== null ? '@' . $revision : '' ));
122 // ###################################################################
124 * A library complicator function that handles the diff command because
125 * the standard command() system does not work with more complex args.
129 * @param integer Lower revision
130 * @param integer Higher revision
132 * @return array Lines of diff output
134 function diff ( $lorev , $hirev )
138 $hirev = SVNCommon
:: rev ( $hirev );
139 $lorev = SVNCommon
:: rev ( $lorev );
140 if ( $lorev == 'HEAD' )
145 if ( is_integer ( $hirev ) AND is_integer ( $lorev ))
151 if ( $lorev == $hirev )
157 return $this- > svn ( 'diff -r' . $lorev . ':' . $hirev . ' ' . $this- > controller
-> repospath
. $this- > controller
-> path
);
160 // ###################################################################
162 * A library complicator function to create log output. This is needed
163 * because command() doesn't handle ranged revisions.
167 * @param string Repository
169 * @param integer Lower revision
170 * @param integer Higher revision
172 * @return array Lines of log output
174 function log ( $lorev , $hirev )
178 $hirev = $this- > rev ( $hirev );
179 $lorev = $this- > rev ( $hirev );
180 if ( $lorev == 'HEAD' )
185 if ( is_integer ( $hirev ) AND is_integer ( $lorev ))
191 if ( $lorev == $hirev )
197 $repospath = $viewsvn- > repos
-> fetch_path ( $repos , false );
199 return $this- > svn ( 'log -v -r' . $hirev . ':' . $lorev . ' ' . $repospath . $path );
204 * Annotation/blame system; constructs an array that is ready for output
212 * Array of blame information
216 var $blame = array ();
219 * Raw "svn blame" output
225 // ###################################################################
227 * Constructor: create blame and store data
229 * @param object Controller
231 function SVNBlame (& $controller )
233 $this- > rawoutput
= $controller- > library
-> command ( 'blame' );
237 // ###################################################################
239 * Returns blame for display
243 * @return array Blame data
250 // ###################################################################
252 * Parses the blame data
260 foreach ( $this- > rawoutput
AS $line )
262 if ( preg_match ( '#^\s+([0-9]+)\s+([\w\.\-_]+)\s(.*)$#' , $line , $matches ))
264 $this- > blame
[] = array (
265 'rev' => $matches [ 1 ],
266 'author' => $matches [ 2 ],
267 'line' => $matches [ 3 ],
268 'lineno' => $lineno ++
272 else if ( preg_match ( '#^\s+([0-9]+)\s+([\w\.\-_]+)$#' , $line , $matches ))
274 $this- > blame
[] = array (
275 'rev' => $matches [ 1 ],
276 'author' => $matches [ 2 ],
278 'lineno' => $lineno ++
286 * Diff system; constructs a diff array that is ready for output
294 * Array of diff information
301 * Raw "svn diff" output
307 // ###################################################################
309 * Constructor: create and store diff data
311 * @param object Controller
312 * @param integer Lower revision
313 * @param integer Higher revision
315 function SVNDiff (& $controller , $lorev , $hirev )
317 $this- > rawoutput
= $controller- > library
-> diff ( $lorev , $hirev );
321 // ###################################################################
323 * Returns diffs for display
327 * @return array Diff data
334 // ###################################################################
336 * Processes and prepares diff data
345 $indexcounter = null ;
350 foreach ( $this- > rawoutput
AS $line )
352 if ( preg_match ( '#^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@$#' , $line , $bits ))
356 $this- > diff
[ " $index" ][ ++ $chunk ]['hunk'] = array('old' => array('line' => $bits [1], 'count' => $bits [2]), 'new' => array('line' => $bits [3], 'count' => $bits [4]));
357 $lines ['old'] = $this- >diff[" $index" ][ " $chunk" ]['hunk']['old']['line'] - 1;
358 $lines ['new'] = $this- >diff[" $index" ][ " $chunk" ]['hunk']['new']['line'] - 1;
361 else if (preg_match('#^Property changes on: (.*?)$#', $line , $bits ))
365 $this- >diff[" $index" ][ 'props' ] = array ();
369 if ( $indexcounter <= 3 AND $indexcounter !== null )
374 else if ( $indexcounter == 3 )
376 $indexcounter = null ;
380 if ( preg_match ( '#^([\+\- ])(.*)#' , $line , $matches ) AND ! $property )
383 $content = $matches [ 2 ];
387 $this- > diff
[ " $index" ][" $chunk" ][] = array (
390 'oldlineno' => ++
$lines [ 'old' ],
391 'newlineno' => ++
$lines [ 'new' ]
396 else if ( $act == '+' )
398 // potential line delta
399 if ( sizeof ( $delstack ) > 0 )
401 $lastline = array_shift ( $delstack );
403 if ( $delta = @ $this- > fetch_diff_extent ( $lastline [ 'line' ], $content ))
405 if ( strlen ( $lastline [ 'line' ]) > ( $delta [ 'start' ] - $delta [ 'end' ]))
407 $end = strlen ( $lastline [ 'line' ]) +
$delta [ 'end' ];
408 $viewsvn- > debug ( "RM delta- = " . $end );
409 $change = ' {@-' . '-} ' . substr ( $lastline [ 'line' ], $delta [ 'start' ], $end - $delta [ 'start' ]) . ' {/@-' . '-} ' ;
410 $this- > diff
[ " $index" ][" $chunk" ][ " $lastline [INDEX]" ][ 'line' ] = substr ( $lastline [ 'line' ], 0 , $delta [ 'start' ]) . $change . substr ( $lastline [ 'line' ], $end );
413 if ( strlen ( $content ) > $delta [ 'start' ] - $delta [ 'end' ])
415 $end = strlen ( $content ) +
$delta [ 'end' ];
416 $viewsvn- > debug ( "MK delta+ = " . $end );
417 $change = ' {@+' . '+} ' . substr ( $content , $delta [ 'start' ], $end - $delta [ 'start' ]) . ' {/@+' . '+} ' ;
418 $content = substr ( $content , 0 , $delta [ 'start' ]) . $change . substr ( $content , $end );
423 $this- > diff
[ " $index" ][" $chunk" ][] = array (
427 'newlineno' => ++
$lines [ 'new' ]
430 else if ( $act == '-' )
432 $this- > diff
[ " $index" ][" $chunk" ][] = $thearray = array (
435 'oldlineno' => ++
$lines [ 'old' ],
439 $key = sizeof ( $this- > diff
[ " $index" ][" $chunk" ]) - 2 ;
440 $thearray [ 'INDEX' ] = $key ;
442 array_push ( $delstack , $thearray );
448 if ( preg_match ( '#^Index: (.*?)$#' , $line , $matches ))
450 $index = $matches [ 1 ];
458 if ( preg_match ( '#^__*_$#' , trim ( $line )))
460 $viewsvn- > debug ( "skipping: $line" );
464 if (preg_match('#Name: (.*?)$#', $line , $matches ))
466 $curprop = $matches [1];
467 $viewsvn- >debug(" prop
: $curprop" );
472 if ( preg_match ( '#^\s+?\+(.*)#' , $line , $matches ))
475 $this- > diff
[ " $index" ]['props'][" $curprop" ][ 'add' ] .= $matches [ 1 ];
477 else if ( preg_match ( '#^\s+?\-(.*)#' , $line , $matches ))
480 $this- > diff
[ " $index" ]['props'][" $curprop" ][ 'del' ] .= $matches [ 1 ];
482 else if (! preg_match ( '#^\s+[\+\- ](.*)#' , $line ) AND trim ( $line ) != '' )
484 $this- > diff
[ " $index" ]['props'][" $curprop" ][ " $mode" ] .= " \n
" . $line ;
490 $this- >diff[" $index" ][ " $chunk" ][] = array(
493 'oldlineno' => ++ $lines ['old'],
494 'newlineno' => ++ $lines ['new']
502 // ###################################################################
504 * Returns the amount of change that occured between two lines
508 * @param string Old line
509 * @param string New line
511 * @return array Difference of positions
513 function fetch_diff_extent( $old , $new )
518 $min = min(strlen( $old ), strlen( $new ));
520 $viewsvn- >debug(" min1
= $min" );
522 while ( $start < $min AND $old [ " $start" ] == $new [" $start" ])
528 $min = $min - $start ;
530 $viewsvn- > debug ( "min2 = $min" );
532 $viewsvn- >debug(" checking
: " . $old [ strlen( $old ) + $end ] . ' == ' . $new [ strlen( $new ) + $end ]);
534 while (- $end <= $min AND $old [ strlen( $old ) + $end ] == $new [ strlen( $new ) + $end ])
539 return array('start' => $start , 'end' => $end + 1);
543 /*=====================================================================*\
544 || ###################################################################
547 || ###################################################################
548 \*=====================================================================*/