[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/Horde/VC/ -> svn.php (source)

   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  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7