@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.

Allow repo updates to recover after force push + garbage collection

Summary:
Fixes T5839. If a repository has been force pushed and garbage collected, we might have a ref cursor in the database which still points at the old commit (which no longer exists).

We'll then run a command like `git log <new hash> --not <old hash>` to figure out which commits are newly pushed, and this will bomb out because `<old hash>` is invalid.

Instead, validate all the `<old hash>` values before we try to make use of them.

Test Plan:
- Forced a repository into a bad state by mucking with the datbase, generating a reproducible failure similar to the one in T5839.
- Applied patch.
- `bin/repository update <callsign> --trace` filtered the bad commit and put the repository into the right state.
- Saw new commits recognized correctly.
- Ran `bin/repository update <callsign>` for a Mercurial and SVN repo as a sanity check.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5839

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

+36 -6
-6
src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php
··· 135 135 136 136 $futures = array(); 137 137 foreach ($this->refs as $ref) { 138 - // TODO: There was a note about `--rev 'a b'` not working for branches 139 - // with spaces in their names in older code, but I suspect this was 140 - // misidentified and resulted from the branch name being interpeted as 141 - // a revset. Use hgsprintf() to avoid that. If this doesn't break for a 142 - // bit, remove this comment. Otherwise, consider `-b %s --limit 1`. 143 - 144 138 $futures[$ref] = $repository->getLocalCommandFuture( 145 139 'log --template=%s --rev %s', 146 140 '{node}',
+30
src/applications/repository/engine/PhabricatorRepositoryRefEngine.php
··· 63 63 } 64 64 } 65 65 $all_closing_heads = array_unique($all_closing_heads); 66 + $all_closing_heads = $this->removeMissingCommits($all_closing_heads); 66 67 67 68 foreach ($maps as $type => $refs) { 68 69 $cursor_group = idx($cursor_groups, $type, array()); ··· 103 104 $this->closeCommits[$identifier] = $identifier; 104 105 } 105 106 return $this; 107 + } 108 + 109 + /** 110 + * Remove commits which no longer exist in the repository from a list. 111 + * 112 + * After a force push and garbage collection, we may have branch cursors which 113 + * point at commits which no longer exist. This can make commands issued later 114 + * fail. See T5839 for discussion. 115 + * 116 + * @param list<string> List of commit identifiers. 117 + * @return list<string> List with nonexistent identifiers removed. 118 + */ 119 + private function removeMissingCommits(array $identifiers) { 120 + if (!$identifiers) { 121 + return array(); 122 + } 123 + 124 + $resolved = id(new DiffusionLowLevelResolveRefsQuery()) 125 + ->setRepository($this->getRepository()) 126 + ->withRefs($identifiers) 127 + ->execute(); 128 + 129 + foreach ($identifiers as $key => $identifier) { 130 + if (empty($resolved[$identifier])) { 131 + unset($identifiers[$key]); 132 + } 133 + } 134 + 135 + return $identifiers; 106 136 } 107 137 108 138 private function updateCursors(
+6
src/applications/repository/management/PhabricatorRepositoryManagementUpdateWorkflow.php
··· 42 42 43 43 public function execute(PhutilArgumentParser $args) { 44 44 $this->setVerbose($args->getArg('verbose')); 45 + $console = PhutilConsole::getConsole(); 45 46 46 47 $repos = $this->loadRepositories($args, 'repos'); 47 48 if (count($repos) !== 1) { ··· 102 103 } 103 104 104 105 $lock->unlock(); 106 + 107 + $console->writeOut( 108 + pht( 109 + 'Updated repository **%s**.', 110 + $repository->getMonogram())."\n"); 105 111 106 112 return 0; 107 113 }