[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/repository/management/ -> PhabricatorRepositoryManagementUpdateWorkflow.php (source)

   1  <?php
   2  
   3  final class PhabricatorRepositoryManagementUpdateWorkflow
   4    extends PhabricatorRepositoryManagementWorkflow {
   5  
   6    private $verbose;
   7  
   8    public function setVerbose($verbose) {
   9      $this->verbose = $verbose;
  10      return $this;
  11    }
  12  
  13    public function getVerbose() {
  14      return $this->verbose;
  15    }
  16  
  17    public function didConstruct() {
  18      $this
  19        ->setName('update')
  20        ->setExamples('**update** [options] __repository__')
  21        ->setSynopsis(
  22          pht(
  23            'Update __repository__, named by callsign. '.
  24            'This performs the __pull__, __discover__, __ref__ and __mirror__ '.
  25            'operations and is primarily an internal workflow.'))
  26        ->setArguments(
  27          array(
  28            array(
  29              'name'        => 'verbose',
  30              'help'        => 'Show additional debugging information.',
  31            ),
  32            array(
  33              'name'        => 'no-discovery',
  34              'help'        => 'Do not perform discovery.',
  35            ),
  36            array(
  37              'name'        => 'repos',
  38              'wildcard'    => true,
  39            ),
  40          ));
  41    }
  42  
  43    public function execute(PhutilArgumentParser $args) {
  44      $this->setVerbose($args->getArg('verbose'));
  45      $console = PhutilConsole::getConsole();
  46  
  47      $repos = $this->loadRepositories($args, 'repos');
  48      if (count($repos) !== 1) {
  49        throw new PhutilArgumentUsageException(
  50          pht('Specify exactly one repository to update, by callsign.'));
  51      }
  52  
  53      $repository = head($repos);
  54      $callsign = $repository->getCallsign();
  55  
  56      $no_discovery = $args->getArg('no-discovery');
  57  
  58      id(new PhabricatorRepositoryPullEngine())
  59        ->setRepository($repository)
  60        ->setVerbose($this->getVerbose())
  61        ->pullRepository();
  62  
  63      if ($no_discovery) {
  64        return;
  65      }
  66  
  67      // TODO: It would be nice to discover only if we pulled something, but this
  68      // isn't totally trivial. It's slightly more complicated with hosted
  69      // repositories, too.
  70  
  71      $lock_name = get_class($this).':'.$callsign;
  72      $lock = PhabricatorGlobalLock::newLock($lock_name);
  73  
  74      $lock->lock();
  75  
  76      try {
  77        $repository->writeStatusMessage(
  78          PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
  79          null);
  80  
  81        $this->discoverRepository($repository);
  82  
  83        $this->checkIfRepositoryIsFullyImported($repository);
  84  
  85        $this->updateRepositoryRefs($repository);
  86  
  87        $this->mirrorRepository($repository);
  88  
  89        $repository->writeStatusMessage(
  90          PhabricatorRepositoryStatusMessage::TYPE_FETCH,
  91          PhabricatorRepositoryStatusMessage::CODE_OKAY);
  92      } catch (Exception $ex) {
  93        $repository->writeStatusMessage(
  94          PhabricatorRepositoryStatusMessage::TYPE_FETCH,
  95          PhabricatorRepositoryStatusMessage::CODE_ERROR,
  96          array(
  97            'message' => pht(
  98              'Error updating working copy: %s', $ex->getMessage()),
  99          ));
 100  
 101        $lock->unlock();
 102        throw $ex;
 103      }
 104  
 105      $lock->unlock();
 106  
 107      $console->writeOut(
 108        pht(
 109          'Updated repository **%s**.',
 110          $repository->getMonogram())."\n");
 111  
 112      return 0;
 113    }
 114  
 115    private function discoverRepository(PhabricatorRepository $repository) {
 116      $refs = id(new PhabricatorRepositoryDiscoveryEngine())
 117        ->setRepository($repository)
 118        ->setVerbose($this->getVerbose())
 119        ->discoverCommits();
 120  
 121      return (bool)count($refs);
 122    }
 123  
 124    private function mirrorRepository(PhabricatorRepository $repository) {
 125      try {
 126        id(new PhabricatorRepositoryMirrorEngine())
 127          ->setRepository($repository)
 128          ->pushToMirrors();
 129      } catch (Exception $ex) {
 130        // TODO: We should report these into the UI properly, but for now just
 131        // complain. These errors are much less severe than pull errors.
 132        $proxy = new PhutilProxyException(
 133          pht(
 134            'Error while pushing "%s" repository to mirrors.',
 135            $repository->getCallsign()),
 136          $ex);
 137        phlog($proxy);
 138      }
 139    }
 140  
 141    private function updateRepositoryRefs(PhabricatorRepository $repository) {
 142      id(new PhabricatorRepositoryRefEngine())
 143        ->setRepository($repository)
 144        ->updateRefs();
 145    }
 146  
 147    private function checkIfRepositoryIsFullyImported(
 148      PhabricatorRepository $repository) {
 149  
 150      // Check if the repository has the "Importing" flag set. We want to clear
 151      // the flag if we can.
 152      $importing = $repository->getDetail('importing');
 153      if (!$importing) {
 154        // This repository isn't marked as "Importing", so we're done.
 155        return;
 156      }
 157  
 158      // Look for any commit which hasn't imported.
 159      $unparsed_commit = queryfx_one(
 160        $repository->establishConnection('r'),
 161        'SELECT * FROM %T WHERE repositoryID = %d AND (importStatus & %d) != %d
 162          LIMIT 1',
 163        id(new PhabricatorRepositoryCommit())->getTableName(),
 164        $repository->getID(),
 165        PhabricatorRepositoryCommit::IMPORTED_ALL,
 166        PhabricatorRepositoryCommit::IMPORTED_ALL);
 167      if ($unparsed_commit) {
 168        // We found a commit which still needs to import, so we can't clear the
 169        // flag.
 170        return;
 171      }
 172  
 173      // Clear the "importing" flag.
 174      $repository->openTransaction();
 175        $repository->beginReadLocking();
 176          $repository = $repository->reload();
 177          $repository->setDetail('importing', false);
 178          $repository->save();
 179        $repository->endReadLocking();
 180      $repository->saveTransaction();
 181    }
 182  
 183  
 184  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1