@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Track closed branches in Mercurial

Summary: Ref T6160. Ref T7100. Mercurial branch heads can be closed; track this state so we can be smarter about it.

Test Plan: Closed a branch, run `repository update`, saw it close in the cursor table.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T6160, T7100

Differential Revision: https://secure.phabricator.com/D12550

+109 -16
+2
resources/sql/autopatches/20150425.isclosed.sql
··· 1 + ALTER TABLE {$NAMESPACE}_repository.repository_refcursor 2 + ADD isClosed BOOL NOT NULL;
+1 -1
src/applications/diffusion/controller/DiffusionRefTableController.php
··· 75 75 76 76 $cached_hash = idx($cache, 'identifier'); 77 77 if ($cached_hash !== null) { 78 - $cache_hash = DiffusionView::linkCommit( 78 + $cached_hash = DiffusionView::linkCommit( 79 79 $repository, 80 80 $cached_hash); 81 81 }
+42 -14
src/applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialBranchesQuery.php
··· 16 16 protected function executeQuery() { 17 17 $repository = $this->getRepository(); 18 18 19 + $specs = array(); 19 20 if ($this->contains !== null) { 20 - $spec = hgsprintf('(descendants(%s) and head())', $this->contains); 21 + $specs['all'] = hgsprintf( 22 + '(descendants(%s) and head())', 23 + $this->contains); 24 + $specs['open'] = hgsprintf( 25 + '(descendants(%s) and head() and not closed())', 26 + $this->contains); 21 27 } else { 22 - $spec = hgsprintf('head()'); 28 + $specs['all'] = hgsprintf('head()'); 29 + $specs['open'] = hgsprintf('head() and not closed()'); 23 30 } 24 31 25 - list($stdout) = $repository->execxLocalCommand( 26 - 'log --template %s --rev %s', 27 - '{node}\1{branch}\2', 28 - $spec); 32 + $futures = array(); 33 + foreach ($specs as $key => $spec) { 34 + $futures[$key] = $repository->getLocalCommandFuture( 35 + 'log --template %s --rev %s', 36 + '{node}\1{branch}\2', 37 + $spec); 38 + } 29 39 30 40 $branches = array(); 41 + $open = array(); 42 + foreach (new FutureIterator($futures) as $key => $future) { 43 + list($stdout) = $future->resolvex(); 31 44 32 - $lines = explode("\2", $stdout); 33 - $lines = array_filter($lines); 34 - foreach ($lines as $line) { 35 - list($node, $branch) = explode("\1", $line); 36 - $branches[] = id(new DiffusionRepositoryRef()) 37 - ->setShortName($branch) 38 - ->setCommitIdentifier($node); 45 + $lines = explode("\2", $stdout); 46 + $lines = array_filter($lines); 47 + foreach ($lines as $line) { 48 + list($node, $branch) = explode("\1", $line); 49 + $id = $node.'/'.$branch; 50 + if (empty($branches[$id])) { 51 + $branches[$id] = id(new DiffusionRepositoryRef()) 52 + ->setShortName($branch) 53 + ->setCommitIdentifier($node); 54 + } 55 + 56 + if ($key == 'open') { 57 + $open[$id] = true; 58 + } 59 + } 39 60 } 40 61 41 - return $branches; 62 + foreach ($branches as $id => $branch) { 63 + $branch->setRawFields( 64 + array( 65 + 'closed' => (empty($open[$id])), 66 + )); 67 + } 68 + 69 + return array_values($branches); 42 70 } 43 71 44 72 }
+48
src/applications/repository/engine/PhabricatorRepositoryRefEngine.php
··· 19 19 20 20 $repository = $this->getRepository(); 21 21 22 + $branches_may_close = false; 23 + 22 24 $vcs = $repository->getVersionControlSystem(); 23 25 switch ($vcs) { 24 26 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: ··· 31 33 $branches = $this->loadMercurialBranchPositions($repository); 32 34 $bookmarks = $this->loadMercurialBookmarkPositions($repository); 33 35 $tags = array(); 36 + $branches_may_close = true; 34 37 break; 35 38 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 36 39 $branches = $this->loadGitBranchPositions($repository); ··· 86 89 87 90 $this->newRefs = array(); 88 91 $this->deadRefs = array(); 92 + } 93 + 94 + if ($branches && $branches_may_close) { 95 + $this->updateBranchStates($repository, $branches); 96 + } 97 + } 98 + 99 + private function updateBranchStates( 100 + PhabricatorRepository $repository, 101 + array $branches) { 102 + 103 + assert_instances_of($branches, 'DiffusionRepositoryRef'); 104 + 105 + $all_cursors = id(new PhabricatorRepositoryRefCursorQuery()) 106 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 107 + ->withRepositoryPHIDs(array($repository->getPHID())) 108 + ->execute(); 109 + 110 + $state_map = array(); 111 + $type_branch = PhabricatorRepositoryRefCursor::TYPE_BRANCH; 112 + foreach ($all_cursors as $cursor) { 113 + if ($cursor->getRefType() !== $type_branch) { 114 + continue; 115 + } 116 + $raw_name = $cursor->getRefNameRaw(); 117 + $hash = $cursor->getCommitIdentifier(); 118 + 119 + $state_map[$raw_name][$hash] = $cursor; 120 + } 121 + 122 + foreach ($branches as $branch) { 123 + $cursor = idx($state_map, $branch->getShortName(), array()); 124 + $cursor = idx($cursor, $branch->getCommitIdentifier()); 125 + if (!$cursor) { 126 + continue; 127 + } 128 + 129 + $fields = $branch->getRawFields(); 130 + 131 + $cursor_state = (bool)$cursor->getIsClosed(); 132 + $branch_state = (bool)idx($fields, 'closed'); 133 + 134 + if ($cursor_state != $branch_state) { 135 + $cursor->setIsClosed((int)$branch_state)->save(); 136 + } 89 137 } 90 138 } 91 139
+14 -1
src/applications/repository/storage/PhabricatorRepository.php
··· 544 544 // trusted, Mercurial prints out a warning to stdout, twice, after Feb 2011. 545 545 // 546 546 // http://selenic.com/pipermail/mercurial-devel/2011-February/028541.html 547 + // 548 + // After Jan 2015, it may also fail to write to a revision branch cache. 549 + 550 + $ignore = array( 551 + 'ignoring untrusted configuration option', 552 + "couldn't write revision branch cache:", 553 + ); 554 + 555 + foreach ($ignore as $key => $pattern) { 556 + $ignore[$key] = preg_quote($pattern, '/'); 557 + } 558 + 559 + $ignore = '('.implode('|', $ignore).')'; 547 560 548 561 $lines = preg_split('/(?<=\n)/', $stdout); 549 - $regex = '/ignoring untrusted configuration option .*\n$/'; 562 + $regex = '/'.$ignore.'.*\n$/'; 550 563 551 564 foreach ($lines as $key => $line) { 552 565 $lines[$key] = preg_replace($regex, '', $line);
+2
src/applications/repository/storage/PhabricatorRepositoryRefCursor.php
··· 18 18 protected $refNameRaw; 19 19 protected $refNameEncoding; 20 20 protected $commitIdentifier; 21 + protected $isClosed = 0; 21 22 22 23 private $repository = self::ATTACHABLE; 23 24 ··· 35 36 // T6203/NULLABILITY 36 37 // This probably should not be nullable; refNameRaw is not nullable. 37 38 'refNameEncoding' => 'text16?', 39 + 'isClosed' => 'bool', 38 40 ), 39 41 self::CONFIG_KEY_SCHEMA => array( 40 42 'key_cursor' => array(