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

Fix various branch/ref issues with bare repositories in Git

Summary:
Ref T2230. Although all the non-bare commands //run// fine in bare repos, not all of them do exactly the same thing.

This could use further cleanup, but at least get it working again for now.

Test Plan: Ran `bin/repository pull`, `bin/repository discover`, viewed Diffusion (looked at branch table), viewed a commit (looked at "Branches"), for bare and non-bare git repos.

Reviewers: avive, btrahan, avivey

Reviewed By: avivey

CC: aran

Maniphest Tasks: T2230

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

+98 -22
+16 -8
src/applications/diffusion/conduit/ConduitAPI_diffusion_branchquery_Method.php
··· 30 30 // We need to add 1 in case we pick up HEAD. 31 31 $count = $offset + $limit + 1; 32 32 33 - list($stdout) = $repository->execxLocalCommand( 34 - 'for-each-ref %C --sort=-creatordate --format=%s refs/remotes', 35 - $count ? '--count='.(int)$count : null, 36 - '%(refname:short) %(objectname)'); 37 - 38 - $branch_list = DiffusionGitBranch::parseRemoteBranchOutput( 39 - $stdout, 40 - $only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE); 33 + if ($repository->isWorkingCopyBare()) { 34 + list($stdout) = $repository->execxLocalCommand( 35 + 'for-each-ref %C --sort=-creatordate --format=%s refs/heads', 36 + $count ? '--count='.(int)$count : null, 37 + '%(refname:short) %(objectname)'); 38 + $branch_list = DiffusionGitBranch::parseLocalBranchOutput( 39 + $stdout); 40 + } else { 41 + list($stdout) = $repository->execxLocalCommand( 42 + 'for-each-ref %C --sort=-creatordate --format=%s refs/remotes', 43 + $count ? '--count='.(int)$count : null, 44 + '%(refname:short) %(objectname)'); 45 + $branch_list = DiffusionGitBranch::parseRemoteBranchOutput( 46 + $stdout, 47 + $only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE); 48 + } 41 49 42 50 $branches = array(); 43 51 foreach ($branch_list as $name => $head) {
+14 -7
src/applications/diffusion/conduit/ConduitAPI_diffusion_commitbranchesquery_Method.php
··· 25 25 $repository = $drequest->getRepository(); 26 26 $commit = $request->getValue('commit'); 27 27 28 - list($contains) = $repository->execxLocalCommand( 29 - 'branch -r --verbose --no-abbrev --contains %s', 30 - $commit); 31 - 32 - return DiffusionGitBranch::parseRemoteBranchOutput( 33 - $contains, 34 - DiffusionBranchInformation::DEFAULT_GIT_REMOTE); 28 + if ($repository->isWorkingCopyBare()) { 29 + list($contains) = $repository->execxLocalCommand( 30 + 'branch --verbose --no-abbrev --contains %s', 31 + $commit); 32 + return DiffusionGitBranch::parseLocalBranchOutput( 33 + $contains); 34 + } else { 35 + list($contains) = $repository->execxLocalCommand( 36 + 'branch -r --verbose --no-abbrev --contains %s', 37 + $commit); 38 + return DiffusionGitBranch::parseRemoteBranchOutput( 39 + $contains, 40 + DiffusionBranchInformation::DEFAULT_GIT_REMOTE); 41 + } 35 42 } 36 43 37 44 protected function getMercurialResult(ConduitAPIRequest $request) {
+27
src/applications/diffusion/data/DiffusionGitBranch.php
··· 70 70 71 71 return $map; 72 72 } 73 + 74 + /** 75 + * As above, but with no `-r`. Used for bare repositories. 76 + */ 77 + public static function parseLocalBranchOutput($stdout) { 78 + $map = array(); 79 + 80 + $lines = array_filter(explode("\n", $stdout)); 81 + $regex = '/^[* ]*(\(no branch\)|\S+)\s+([a-z0-9]{40})/'; 82 + foreach ($lines as $line) { 83 + $matches = null; 84 + if (!preg_match($regex, $line, $matches)) { 85 + throw new Exception("Failed to parse {$line}!"); 86 + } 87 + 88 + $branch = $matches[1]; 89 + $branch_head = $matches[2]; 90 + if ($branch == '(no branch)') { 91 + continue; 92 + } 93 + 94 + $map[$branch] = $branch_head; 95 + } 96 + 97 + return $map; 98 + } 99 + 73 100 }
+12 -6
src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
··· 526 526 $repository->getRemoteURI(), 527 527 $repository->getLocalPath()); 528 528 529 - list($stdout) = $repository->execxLocalCommand( 530 - 'branch -r --verbose --no-abbrev'); 531 - 532 - $branches = DiffusionGitBranch::parseRemoteBranchOutput( 533 - $stdout, 534 - $only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE); 529 + if ($repository->isWorkingCopyBare()) { 530 + list($stdout) = $repository->execxLocalCommand( 531 + 'branch --verbose --no-abbrev'); 532 + $branches = DiffusionGitBranch::parseLocalBranchOutput( 533 + $stdout); 534 + } else { 535 + list($stdout) = $repository->execxLocalCommand( 536 + 'branch -r --verbose --no-abbrev'); 537 + $branches = DiffusionGitBranch::parseRemoteBranchOutput( 538 + $stdout, 539 + $only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE); 540 + } 535 541 536 542 if (!$branches) { 537 543 // This repository has no branches at all, so we don't need to do
+10 -1
src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
··· 177 177 $retry = false; 178 178 do { 179 179 // This is a local command, but needs credentials. 180 - $future = $repository->getRemoteCommandFuture('fetch --all --prune'); 180 + if ($repository->isWorkingCopyBare()) { 181 + // For bare working copies, we need this magic incantation. 182 + $future = $repository->getRemoteCommandFuture( 183 + 'fetch origin %s --prune', 184 + '+refs/heads/*:refs/heads/*'); 185 + } else { 186 + $future = $repository->getRemoteCommandFuture( 187 + 'fetch --all --prune'); 188 + } 189 + 181 190 $future->setCWD($path); 182 191 list($err, $stdout, $stderr) = $future->resolve(); 183 192
+19
src/applications/repository/storage/PhabricatorRepository.php
··· 786 786 Filesystem::assertReadable($local); 787 787 } 788 788 789 + /** 790 + * Determine if the working copy is bare or not. In Git, this corresponds 791 + * to `--bare`. In Mercurial, `--noupdate`. 792 + */ 793 + public function isWorkingCopyBare() { 794 + switch ($this->getVersionControlSystem()) { 795 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 796 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 797 + return false; 798 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 799 + $local = $this->getLocalPath(); 800 + if (Filesystem::pathExists($local.'/.git')) { 801 + return false; 802 + } else { 803 + return true; 804 + } 805 + } 806 + } 807 + 789 808 790 809 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 791 810