1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-20 05:42:40 +01:00

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
This commit is contained in:
epriestley 2013-10-29 21:04:38 -07:00
parent cdcfbb69a0
commit 19124554d8
6 changed files with 98 additions and 22 deletions

View file

@ -30,14 +30,22 @@ final class ConduitAPI_diffusion_branchquery_Method
// We need to add 1 in case we pick up HEAD.
$count = $offset + $limit + 1;
list($stdout) = $repository->execxLocalCommand(
'for-each-ref %C --sort=-creatordate --format=%s refs/remotes',
$count ? '--count='.(int)$count : null,
'%(refname:short) %(objectname)');
$branch_list = DiffusionGitBranch::parseRemoteBranchOutput(
$stdout,
$only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
if ($repository->isWorkingCopyBare()) {
list($stdout) = $repository->execxLocalCommand(
'for-each-ref %C --sort=-creatordate --format=%s refs/heads',
$count ? '--count='.(int)$count : null,
'%(refname:short) %(objectname)');
$branch_list = DiffusionGitBranch::parseLocalBranchOutput(
$stdout);
} else {
list($stdout) = $repository->execxLocalCommand(
'for-each-ref %C --sort=-creatordate --format=%s refs/remotes',
$count ? '--count='.(int)$count : null,
'%(refname:short) %(objectname)');
$branch_list = DiffusionGitBranch::parseRemoteBranchOutput(
$stdout,
$only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
}
$branches = array();
foreach ($branch_list as $name => $head) {

View file

@ -25,13 +25,20 @@ final class ConduitAPI_diffusion_commitbranchesquery_Method
$repository = $drequest->getRepository();
$commit = $request->getValue('commit');
list($contains) = $repository->execxLocalCommand(
'branch -r --verbose --no-abbrev --contains %s',
$commit);
return DiffusionGitBranch::parseRemoteBranchOutput(
$contains,
DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
if ($repository->isWorkingCopyBare()) {
list($contains) = $repository->execxLocalCommand(
'branch --verbose --no-abbrev --contains %s',
$commit);
return DiffusionGitBranch::parseLocalBranchOutput(
$contains);
} else {
list($contains) = $repository->execxLocalCommand(
'branch -r --verbose --no-abbrev --contains %s',
$commit);
return DiffusionGitBranch::parseRemoteBranchOutput(
$contains,
DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
}
}
protected function getMercurialResult(ConduitAPIRequest $request) {

View file

@ -70,4 +70,31 @@ final class DiffusionGitBranch {
return $map;
}
/**
* As above, but with no `-r`. Used for bare repositories.
*/
public static function parseLocalBranchOutput($stdout) {
$map = array();
$lines = array_filter(explode("\n", $stdout));
$regex = '/^[* ]*(\(no branch\)|\S+)\s+([a-z0-9]{40})/';
foreach ($lines as $line) {
$matches = null;
if (!preg_match($regex, $line, $matches)) {
throw new Exception("Failed to parse {$line}!");
}
$branch = $matches[1];
$branch_head = $matches[2];
if ($branch == '(no branch)') {
continue;
}
$map[$branch] = $branch_head;
}
return $map;
}
}

View file

@ -526,12 +526,18 @@ final class PhabricatorRepositoryPullLocalDaemon
$repository->getRemoteURI(),
$repository->getLocalPath());
list($stdout) = $repository->execxLocalCommand(
'branch -r --verbose --no-abbrev');
$branches = DiffusionGitBranch::parseRemoteBranchOutput(
$stdout,
$only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
if ($repository->isWorkingCopyBare()) {
list($stdout) = $repository->execxLocalCommand(
'branch --verbose --no-abbrev');
$branches = DiffusionGitBranch::parseLocalBranchOutput(
$stdout);
} else {
list($stdout) = $repository->execxLocalCommand(
'branch -r --verbose --no-abbrev');
$branches = DiffusionGitBranch::parseRemoteBranchOutput(
$stdout,
$only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
}
if (!$branches) {
// This repository has no branches at all, so we don't need to do

View file

@ -177,7 +177,16 @@ final class PhabricatorRepositoryPullEngine
$retry = false;
do {
// This is a local command, but needs credentials.
$future = $repository->getRemoteCommandFuture('fetch --all --prune');
if ($repository->isWorkingCopyBare()) {
// For bare working copies, we need this magic incantation.
$future = $repository->getRemoteCommandFuture(
'fetch origin %s --prune',
'+refs/heads/*:refs/heads/*');
} else {
$future = $repository->getRemoteCommandFuture(
'fetch --all --prune');
}
$future->setCWD($path);
list($err, $stdout, $stderr) = $future->resolve();

View file

@ -786,6 +786,25 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
Filesystem::assertReadable($local);
}
/**
* Determine if the working copy is bare or not. In Git, this corresponds
* to `--bare`. In Mercurial, `--noupdate`.
*/
public function isWorkingCopyBare() {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
return false;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$local = $this->getLocalPath();
if (Filesystem::pathExists($local.'/.git')) {
return false;
} else {
return true;
}
}
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */