[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 /** 3 * VC_svn implementation. 4 * 5 * Copyright 2000-2006 Anil Madhavapeddy, <anil@recoil.org> 6 * 7 * $Horde: framework/VC/VC/svn.php,v 1.28.4.18 2006/05/12 04:47:08 chuck Exp $ 8 * 9 * @author Anil Madhavapeddy <anil@recoil.org> 10 * @since Horde 3.0 11 * @package VC 12 */ 13 class VC_svn extends VC { 14 15 /** 16 * Constructor. 17 * 18 * @param array $params Any parameter the class expects. 19 * Current parameters: 20 * 'sourceroot': The source root for this 21 * repository 22 * 'paths': Hash with the locations of all 23 * necessary binaries: 'svn', 'diff' 24 */ 25 function VC_svn($params) 26 { 27 $this->_sourceroot = $params['sourceroot']; 28 $this->_paths = $params['paths']; 29 } 30 31 function isFile($where) 32 { 33 return true; 34 } 35 36 function &queryDir($where) 37 { 38 $dir = new VC_Directory_svn($this, $where); 39 return $dir; 40 } 41 42 function getCheckout($file, $rev) 43 { 44 return VC_Checkout_svn::get($this, $file->queryFullPath(), $rev); 45 } 46 47 function getDiff($file, $rev1, $rev2, $type = 'context', $num = 3, $ws = true) 48 { 49 return VC_Diff_svn::get($this, $file, $rev1, $rev2, $type, $num, $ws); 50 } 51 52 function &getFileObject($filename, $cache = null, $quicklog = false) 53 { 54 $fo = &VC_File_svn::getFileObject($this, $filename, $cache, $quicklog); 55 return $fo; 56 } 57 58 function &getAnnotateObject($filename) 59 { 60 $blame = new VC_Annotate_svn($this, $filename); 61 return $blame; 62 } 63 64 function &getPatchsetObject($filename, $cache = null) 65 { 66 $po = &VC_Patchset_svn::getPatchsetObject($this, $filename, $cache); 67 return $po; 68 } 69 70 } 71 72 /** 73 * VC_svn annotate class. 74 * 75 * Anil Madhavapeddy, <anil@recoil.org> 76 * 77 * @author Anil Madhavapeddy <anil@recoil.org> 78 * @package VC 79 */ 80 class VC_Annotate_svn { 81 82 var $file; 83 var $SVN; 84 var $tmpfile; 85 86 function VC_Annotate_svn($rep, $file) 87 { 88 $this->SVN = $rep; 89 $this->file = $file; 90 } 91 92 function doAnnotate($rev) 93 { 94 /* Make sure that the file values for this object is valid. */ 95 if (is_a($this->file, 'PEAR_Error')) { 96 return false; 97 } 98 99 if (!VC_Revision::valid($rev)) { 100 return false; 101 } 102 103 $Q = VC_WINDOWS ? '"' : "'"; 104 $command = $this->SVN->getPath('svn') . ' annotate -r 1:' . $rev . ' ' . $Q . str_replace($Q, '\\' . $Q, $this->file->queryFullPath()) . $Q . ' 2>&1'; 105 $pipe = popen($command, 'r'); 106 if (!$pipe) { 107 return PEAR::raiseError('Failed to execute svn annotate: ' . $command); 108 } 109 110 $lines = array(); 111 $lineno = 1; 112 while (!feof($pipe)) { 113 $line = fgets($pipe, 4096); 114 if (preg_match('/^\s+(\d+)\s+([\w\.]+)\s(.*)$/', $line, $regs)) { 115 $entry = array(); 116 $entry['rev'] = $regs[1]; 117 $entry['author'] = trim($regs[2]); 118 $entry['date'] = ''; 119 $entry['line'] = $regs[3]; 120 $entry['lineno'] = $lineno++; 121 $lines[] = $entry; 122 } 123 } 124 125 pclose($pipe); 126 return $lines; 127 } 128 129 } 130 131 /** 132 * VC_svn checkout class. 133 * 134 * Anil Madhavapeddy, <anil@recoil.org> 135 * 136 * @author Anil Madhavapeddy <anil@recoil.org> 137 * @package VC 138 */ 139 class VC_Checkout_svn { 140 141 /** 142 * Static function which returns a file pointing to the head of the requested 143 * revision of an RCS file. 144 * @param fullname Fully qualified pathname of the desired RCS file to checkout 145 * @param rev RCS revision number to check out 146 * @return Either a PEAR_Error object, or a stream pointer to the head of the checkout 147 */ 148 function get($rep, $fullname, $rev) 149 { 150 if (!VC_Revision::valid($rev)) { 151 return PEAR::raiseError('Invalid revision number'); 152 } 153 154 if (VC_WINDOWS) { 155 $Q = '"'; 156 $mode = 'rb'; 157 } else { 158 $Q = "'"; 159 $mode = 'r'; 160 } 161 162 if (!($RCS = popen($rep->getPath('svn') . ' cat -r ' . $rev . ' ' . $Q . str_replace($Q, '\\' . $Q, $fullname) . $Q . ' 2>&1', $mode))) { 163 return PEAR::raiseError('Couldn\'t perform checkout of the requested file'); 164 } 165 166 return $RCS; 167 } 168 169 } 170 171 /** 172 * VC_svn diff class. 173 * 174 * Copyright Anil Madhavapeddy, <anil@recoil.org> 175 * 176 * @author Anil Madhavapeddy <anil@recoil.org> 177 * @package VC 178 */ 179 class VC_Diff_svn { 180 181 /** 182 * Obtain the differences between two revisions of a file. 183 * 184 * @param VC_svn $rep A repository object. 185 * @param VC_File_svn $file The desired file. 186 * @param string $rev1 Original revision number to compare from. 187 * @param string $rev2 New revision number to compare against. 188 * @param string $type The type of diff (e.g. 'unified'). 189 * @param integer $num Number of lines to be used in context and 190 * unified diffs. 191 * @param boolean $ws Show whitespace in the diff? 192 * 193 * @return string|boolean False on failure, or a string containing the 194 * diff on success. 195 */ 196 function get($rep, $file, $rev1, $rev2, $type = 'context', $num = 3, 197 $ws = true) 198 { 199 /* Make sure that the file parameter is valid */ 200 if (is_a($file, 'PEAR_Error')) { 201 return false; 202 } 203 204 /* Check that the revision numbers are valid */ 205 $rev1 = VC_Revision::valid($rev1) ? $rev1 : 0; 206 $rev2 = VC_Revision::valid($rev1) ? $rev2 : 0; 207 208 $fullName = $file->queryFullPath(); 209 $diff = array(); 210 $options = ''; 211 if (!$ws) { 212 $options .= ' -bB '; 213 } 214 215 switch ($type) { 216 case 'context': 217 $options .= '--context=' . (int)$num; 218 break; 219 220 case 'unified': 221 $options .= '--unified=' . (int)$num; 222 break; 223 224 case 'column': 225 $options .= '--side-by-side --width=120'; 226 break; 227 228 case 'ed': 229 $options .= '-e'; 230 break; 231 } 232 233 // TODO: add options for $hr options - however these may not 234 // be compatible with some diffs. 235 $Q = VC_WINDOWS ? '"' : "'"; 236 $command = $rep->getPath('svn') . " diff --diff-cmd " . $rep->getPath('diff') . " -r $rev1:$rev2 -x " . $Q . $options . $Q . ' ' . $file->queryFullPath() . ' 2>&1'; 237 238 exec($command, $diff, $retval); 239 return $diff; 240 } 241 242 } 243 244 /** 245 * VC_svn directory class. 246 * 247 * Copyright Anil Madhavapeddy, <anil@recoil.org> 248 * 249 * @author Anil Madhavapeddy <anil@recoil.org> 250 * @package VC 251 */ 252 class VC_Directory_svn { 253 254 var $rep; 255 var $dirName; 256 var $files; 257 var $atticFiles; 258 var $mergedFiles; 259 var $dirs; 260 var $parent; 261 var $moduleName; 262 263 /** 264 * Create a SVN Directory object to store information about the 265 * files in a single directory in the repository 266 * 267 * @param VC_Repository_svn $rp The VC_Repository object this directory 268 * is part of. 269 * @param string $dn Path to the directory. 270 * @param VC_Directory_svn $pn The parent VC_Directory to this one. 271 */ 272 function VC_Directory_svn($rep, $dn, $pn = '') 273 { 274 $this->rep = $rep; 275 $this->parent = $pn; 276 $this->moduleName = $dn; 277 $this->dirName = "/$dn"; 278 $this->files = array(); 279 $this->dirs = array(); 280 } 281 282 /** 283 * Return fully qualified pathname to this directory with no 284 * trailing /. 285 * 286 * @return Pathname of this directory 287 */ 288 function queryDir() 289 { 290 return $this->dirName; 291 } 292 293 function &queryDirList() 294 { 295 return $this->dirs; 296 } 297 298 function &queryFileList($showattic = false) 299 { 300 if ($showattic && isset($this->mergedFiles)) { 301 return $this->mergedFiles; 302 } else { 303 return $this->files; 304 } 305 } 306 307 /** 308 * Tell the object to open and browse its current directory, and 309 * retrieve a list of all the objects in there. It then populates 310 * the file/directory stack and makes it available for retrieval. 311 * 312 * @return PEAR_Error object on an error, 1 on success. 313 */ 314 function browseDir($cache = null, $quicklog = true, $showattic = false) 315 { 316 $Q = VC_WINDOWS ? '"' : "'" ; 317 $cmd = $this->rep->getPath('svn') . ' ls ' . $Q . str_replace($Q, '\\' . $Q, $this->rep->sourceroot() . $this->queryDir()) . $Q . ' 2>&1'; 318 $dir = popen($cmd, 'r'); 319 if (!$dir) { 320 return PEAR::raiseError('Failed to execute svn ls: ' . $cmd); 321 } 322 323 /* Create two arrays - one of all the files, and the other of 324 * all the dirs. */ 325 $errors = array(); 326 while (!feof($dir)) { 327 $line = chop(fgets($dir, 1024)); 328 if (!strlen($line)) { 329 continue; 330 } 331 332 if (substr($line, 0, 4) == 'svn:') { 333 $errors[] = $line; 334 } elseif (substr($line, -1) == '/') { 335 $this->dirs[] = substr($line, 0, -1); 336 } else { 337 $fl = $this->rep->getFileObject($this->queryDir() . "/$line", $cache, $quicklog); 338 if (is_a($fl, 'PEAR_Error')) { 339 return $fl; 340 } else { 341 $this->files[] = $fl; 342 } 343 } 344 } 345 346 pclose($dir); 347 348 if ($errors) { 349 return PEAR::raiseError(implode("\n", $errors)); 350 } 351 352 return true; 353 } 354 355 /** 356 * Sort the contents of the directory in a given fashion and 357 * order. 358 * 359 * @param $how Of the form VC_SORT_* where * can be: 360 * NONE, NAME, AGE, REV for sorting by name, age or revision. 361 * @param $dir Of the form VC_SORT_* where * can be: 362 * ASCENDING, DESCENDING for the order of the sort. 363 */ 364 function applySort($how = VC_SORT_NONE, $dir = VC_SORT_ASCENDING) 365 { 366 /* TODO: this code looks very inefficient! optimise... - 367 * avsm. */ 368 369 // Assume by name for the moment. 370 natcasesort($this->dirs); 371 $this->doFileSort($this->files, $how, $dir); 372 if (isset($this->atticFiles)) { 373 $this->doFileSort($this->atticFiles, $how, $dir); 374 } 375 if (isset($this->mergedFiles)) { 376 $this->doFileSort($this->mergedFiles, $how, $dir); 377 } 378 if ($dir == VC_SORT_DESCENDING) { 379 $this->dirs = array_reverse($this->dirs); 380 $this->files = array_reverse($this->files); 381 if (isset($this->mergedFiles)) { 382 $this->mergedFiles = array_reverse($this->mergedFiles); 383 } 384 } 385 } 386 387 function doFileSort(&$fileList, $how = VC_SORT_NONE, $dir = VC_SORT_ASCENDING) 388 { 389 switch ($how) { 390 case VC_SORT_AGE: 391 usort($fileList, array($this, 'fileAgeSort')); 392 break; 393 394 case VC_SORT_NAME: 395 usort($fileList, array($this, 'fileNameSort')); 396 break; 397 398 case VC_SORT_AUTHOR: 399 usort($fileList, array($this, 'fileAuthorSort')); 400 break; 401 402 case VC_SORT_REV: 403 usort($fileList, array($this, 'fileRevSort')); 404 break; 405 406 case VC_SORT_NONE: 407 default: 408 break; 409 } 410 } 411 412 /** 413 * Sort function for ascending age. 414 */ 415 function fileAgeSort($a, $b) 416 { 417 $aa = $a->queryLastLog(); 418 $bb = $b->queryLastLog(); 419 if ($aa->queryDate() == $bb->queryDate()) { 420 return 0; 421 } else { 422 return ($aa->queryDate() < $bb->queryDate()) ? 1 : -1; 423 } 424 } 425 426 /** 427 * Sort function by author name. 428 */ 429 function fileAuthorSort($a, $b) 430 { 431 $aa = $a->queryLastLog(); 432 $bb = $b->queryLastLog(); 433 if ($aa->queryAuthor() == $bb->queryAuthor()) { 434 return 0; 435 } else { 436 return ($aa->queryAuthor() > $bb->queryAuthor()) ? 1 : -1; 437 } 438 } 439 440 /** 441 * Sort function for ascending filename. 442 */ 443 function fileNameSort($a, $b) 444 { 445 return strcasecmp($a->name, $b->name); 446 } 447 448 /** 449 * Sort function for ascending revision. 450 */ 451 function fileRevSort($a, $b) 452 { 453 return VC_Revision::cmp($a->queryHead(), $b->queryHead()); 454 } 455 456 } 457 458 /** 459 * VC_svn file class. 460 * 461 * Copyright Anil Madhavapeddy, <anil@recoil.org> 462 * 463 * @author Anil Madhavapeddy <anil@recoil.org> 464 * @package VC 465 */ 466 class VC_File_svn extends VC_File { 467 468 /** 469 * Create a repository file object, and give it information about 470 * what its parent directory and repository objects are. 471 * 472 * @param string $fl Full path to this file. 473 */ 474 function VC_File_svn($rep, $fl, $quicklog = false) 475 { 476 $this->rep = $rep; 477 $this->name = basename($fl); 478 $this->dir = dirname($fl); 479 $this->logs = array(); 480 $this->quicklog = $quicklog; 481 $this->revs = array(); 482 $this->revsym = array(); 483 $this->symrev = array(); 484 $this->branches = array(); 485 } 486 487 function &getFileObject($rep, $filename, $cache = null, $quicklog = false) 488 { 489 /* The version of the cached data. Increment this whenever the 490 * internal storage format changes, such that we must 491 * invalidate prior cached data. */ 492 $cacheVersion = 2; 493 $cacheId = $rep->sourceroot() . '_n' . $filename . '_f' . (int)$quicklog . '_v' . $cacheVersion; 494 495 if ($cache && 496 // The file is cached for one hour no matter what, because 497 // there is no way to determine with Subversion the time 498 // the file last changed. 499 $cache->exists($cacheId, 3600)) { 500 $fileOb = unserialize($cache->get($cacheId, 3600)); 501 $fileOb->setRepository($rep); 502 } else { 503 $fileOb = new VC_File_svn($rep, $filename, $quicklog); 504 $fileOb->setRepository($rep); 505 if (is_a(($result = $fileOb->getBrowseInfo()), 'PEAR_Error')) { 506 return $result; 507 } 508 $fileOb->applySort(VC_SORT_AGE); 509 510 if ($cache) { 511 $cache->set($cacheId, serialize($fileOb)); 512 } 513 } 514 515 return $fileOb; 516 } 517 518 /** 519 * If this file is present in an Attic directory, this indicates 520 * it. 521 * 522 * @return true if file is in the Attic, and false otherwise 523 */ 524 function isAtticFile() 525 { 526 // Not implemented yet 527 return false; 528 } 529 530 /** 531 * Returns the name of the current file as in the repository 532 * 533 * @return Filename (without the path) 534 */ 535 function queryRepositoryName() 536 { 537 return $this->name; 538 } 539 540 /** 541 * Returns name of the current file without the repository 542 * extensions (usually ,v) 543 * 544 * @return Filename without repository extension 545 */ 546 function queryName() 547 { 548 return preg_replace('/,v$/', '', $this->name); 549 } 550 551 /** 552 * Return the last revision of the current file on the HEAD branch 553 * 554 * @return Last revision of the current file 555 */ 556 function queryRevision() 557 { 558 if (!isset($this->revs[0])) { 559 return PEAR::raiseError('No revisions'); 560 } 561 return $this->revs[0]; 562 } 563 564 function queryPreviousRevision($rev) 565 { 566 $last = false; 567 foreach ($this->revs as $entry) { 568 if ($last) 569 return $entry; 570 if ($entry == $rev) 571 $last = true; 572 } 573 574 return false; 575 } 576 577 /** 578 * Return the HEAD (most recent) revision number for this file. 579 * 580 * @return HEAD revision number 581 */ 582 function queryHead() 583 { 584 return $this->queryRevision(); 585 } 586 587 /** 588 * Return the last VC_Log object in the file. 589 * 590 * @return VC_Log of the last entry in the file 591 */ 592 function queryLastLog() 593 { 594 if (!isset($this->revs[0]) || !isset($this->logs[$this->revs[0]])) { 595 return PEAR::raiseError('No revisions'); 596 } 597 return $this->logs[$this->revs[0]]; 598 } 599 600 /** 601 * Sort the list of VC_Log objects that this file contains. 602 * 603 * @param how VC_SORT_REV (sort by revision), 604 * VC_SORT_NAME (sort by author name), 605 * VC_SORT_AGE (sort by commit date) 606 */ 607 function applySort($how = VC_SORT_REV) 608 { 609 switch ($how) { 610 case VC_SORT_REV: 611 $func = 'Revision'; 612 break; 613 case VC_SORT_NAME: 614 $func = 'Name'; 615 break; 616 case VC_SORT_AGE: 617 $func = 'Age'; 618 break; 619 default: 620 $func = 'Revision'; 621 } 622 uasort($this->logs, array($this, "sortBy$func")); 623 return true; 624 } 625 626 /** 627 * The sortBy*() functions are internally used by applySort. 628 */ 629 function sortByRevision($a, $b) 630 { 631 return VC_Revision::cmp($b->rev, $a->rev); 632 } 633 634 function sortByAge($a, $b) 635 { 636 return $b->date - $a->date; 637 } 638 639 function sortByName($a, $b) 640 { 641 return strcmp($a->author, $b->author); 642 } 643 644 /** 645 * Populate the object with information about the revisions logs 646 * and dates of the file. 647 * 648 * @return mixed boolean True on success, 649 * PEAR_Error On error. 650 */ 651 function getBrowseInfo() 652 { 653 /* This doesn't work; need to find another way to simply 654 * request the most recent revision: 655 * 656 * $flag = $this->quicklog ? '-r HEAD ' : ''; */ 657 $flag = ''; 658 $Q = VC_WINDOWS ? '"' : "'"; 659 $cmd = $this->rep->getPath('svn') . ' log -v ' . $flag . $Q . str_replace($Q, '\\' . $Q, $this->queryFullPath()) . $Q . ' 2>&1'; 660 $pipe = popen($cmd, 'r'); 661 if (!$pipe) { 662 return PEAR::raiseError('Failed to execute svn log: ' . $cmd); 663 } 664 665 fgets($pipe); 666 while (!feof($pipe)) { 667 $log = new VC_Log_svn($this->rep, $this); 668 $err = $log->processLog($pipe); 669 if ($err) { 670 $rev = $log->queryRevision(); 671 $this->logs[$rev] = $log; 672 $this->revs[] = $rev; 673 } 674 675 if ($this->quicklog) { 676 break; 677 } 678 } 679 680 pclose($pipe); 681 return true; 682 } 683 684 /** 685 * Return the fully qualified filename of this object. 686 * 687 * @return Fully qualified filename of this object 688 */ 689 function queryFullPath() 690 { 691 return $this->rep->sourceroot() . '/' . $this->queryModulePath(); 692 } 693 694 /** 695 * Return the name of this file relative to its sourceroot. 696 * 697 * @return string Pathname relative to the sourceroot. 698 */ 699 function queryModulePath() 700 { 701 return $this->dir . '/' . $this->name; 702 } 703 704 } 705 706 /** 707 * VC_svn log class. 708 * 709 * Anil Madhavapeddy, <anil@recoil.org> 710 * 711 * @author Anil Madhavapeddy <anil@recoil.org> 712 * @package VC 713 */ 714 class VC_Log_svn { 715 716 var $rep; 717 var $err; 718 var $file; 719 var $files; 720 var $tags; 721 var $rev; 722 var $date; 723 var $log; 724 var $author; 725 var $state; 726 var $lines; 727 var $branches; 728 729 /** 730 * Constructor. 731 */ 732 function VC_Log_svn($rep, $fl) 733 { 734 $this->rep = $rep; 735 $this->file = $fl; 736 $this->branches = array(); 737 } 738 739 function processLog($pipe) 740 { 741 $line = fgets($pipe); 742 743 if (feof($pipe)) { 744 return false; 745 } 746 747 if (preg_match('/^r([0-9]*) \| (.*?) \| (.*) \(.*\) \| ([0-9]*) lines?$/', $line, $matches)) { 748 $this->rev = $matches[1]; 749 $this->author = $matches[2]; 750 $this->date = strtotime($matches[3]); 751 $size = $matches[4]; 752 } else { 753 $this->err = $line; 754 return false; 755 } 756 757 fgets($pipe); 758 759 $this->files = array(); 760 while (($line = trim(fgets($pipe))) != '') { 761 $this->files[] = $line; 762 } 763 764 for ($i = 0; $i != $size; ++$i) { 765 $this->log = $this->log . chop(fgets($pipe)) . "\n"; 766 } 767 768 $this->log = chop($this->log); 769 fgets($pipe); 770 771 return true; 772 } 773 774 function queryDate() 775 { 776 return $this->date; 777 } 778 779 function queryRevision() 780 { 781 return $this->rev; 782 } 783 784 function queryAuthor() 785 { 786 return $this->author; 787 } 788 789 function queryLog() 790 { 791 return $this->log; 792 } 793 794 function queryChangedLines() 795 { 796 return isset($this->lines) ? ($this->lines) : ''; 797 } 798 799 /** 800 * Given a branch revision number, this function remaps it 801 * accordingly, and performs a lookup on the file object to 802 * return the symbolic name(s) of that branch in the tree. 803 * 804 * @return hash of symbolic names => branch numbers 805 */ 806 function querySymbolicBranches() 807 { 808 $symBranches = array(); 809 foreach ($this->branches as $branch) { 810 $parts = explode('.', $branch); 811 $last = array_pop($parts); 812 $parts[] = '0'; 813 $parts[] = $last; 814 $rev = implode('.', $parts); 815 if (isset($this->file->branches[$branch])) { 816 $symBranches[$this->file->branches[$branch]] = $branch; 817 } 818 } 819 return $symBranches; 820 } 821 822 } 823 824 /** 825 * VC_svn Patchset class. 826 * 827 * Copyright Anil Madhavapeddy, <anil@recoil.org> 828 * 829 * @author Anil Madhavapeddy <anil@recoil.org> 830 * @package VC 831 */ 832 class VC_Patchset_svn extends VC_Patchset { 833 834 var $_file; 835 836 /** 837 * Create a patchset object. 838 * 839 * @param string $file The filename to get patchsets for. 840 */ 841 function VC_Patchset_svn($file) 842 { 843 $this->_file = $file; 844 } 845 846 function &getPatchsetObject($rep, $filename, $cache = null) 847 { 848 /* The version of the cached data. Increment this whenever the 849 * internal storage format changes, such that we must 850 * invalidate prior cached data. */ 851 $cacheVersion = 1; 852 $cacheId = $rep->sourceroot() . '_n' . $filename . '_f_v' . $cacheVersion; 853 854 if ($cache && 855 // The file is cached for one hour no matter what, because 856 // there is no way to determine with svn the time the file 857 // last changed. 858 $cache->exists($cacheId, 3600)) { 859 $psOb = unserialize($cache->get($cacheId, 3600)); 860 $psOb->setRepository($rep); 861 } else { 862 $psOb = new VC_Patchset_svn($filename); 863 $psOb->setRepository($rep); 864 if (is_a(($result = $psOb->getPatchsets()), 'PEAR_Error')) { 865 return $result; 866 } 867 868 if ($cache) { 869 $cache->set($cacheId, serialize($psOb)); 870 } 871 } 872 873 return $psOb; 874 } 875 876 /** 877 * Populate the object with information about the patchsets that 878 * this file is involved in. 879 * 880 * @return mixed PEAR_Error object on error, or true on success. 881 */ 882 function getPatchsets() 883 { 884 $fileOb = new VC_File_svn($this->_rep, $this->_file); 885 if (is_a(($result = $fileOb->getBrowseInfo()), 'PEAR_Error')) { 886 return $result; 887 } 888 889 $this->_patchsets = array(); 890 foreach ($fileOb->logs as $rev => $log) { 891 $this->_patchsets[$rev] = array(); 892 $this->_patchsets[$rev]['date'] = $log->queryDate(); 893 $this->_patchsets[$rev]['author'] = $log->queryAuthor(); 894 $this->_patchsets[$rev]['branch'] = ''; 895 $this->_patchsets[$rev]['tag'] = ''; 896 $this->_patchsets[$rev]['log'] = $log->queryLog(); 897 $this->_patchsets[$rev]['members'] = array(); 898 foreach ($log->files as $file) { 899 $action = substr($file, 0, 1); 900 $file = preg_replace('/.*?\s(.*?)(\s|$).*/', '\\1', $file); 901 $to = $rev; 902 if ($action == 'A') { 903 $from = 'INITIAL'; 904 } elseif ($action == 'D') { 905 $from = $to; 906 $to = '(DEAD)'; 907 } else { 908 // This technically isn't the previous revision, 909 // but it works for diffing purposes. 910 $from = $to - 1; 911 } 912 913 $this->_patchsets[$rev]['members'][] = array('file' => $file, 914 'from' => $from, 915 'to' => $to); 916 } 917 } 918 919 return true; 920 } 921 922 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |