1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-12-23 22:10:54 +01:00

Improve git behavior in the zero- and one- commit case

Summary:
Git works completely differently for commits zero and one than for 2..N so add
more special casing to handle them. See:

  - {T206}
  - {T596}

The getCommitRange() block is also fatal land, although I wasn't able to reach
it. I'll follow up with @s on T596.

Test Plan:
  - Created a new, empty repository ("mkdir x; cd x; git init").
  - Ran "arc lint", "arc unit", "arc diff" against it with no commits (the first
two work, the third fails helpfully).
  - Made an initial commit.
  - Ran "arc lint", "arc unit", "arc diff" against it (all work correctly).

Reviewers: btrahan, jungejason, aran

Reviewed By: aran

CC: s, aran

Differential Revision: 1142
This commit is contained in:
epriestley 2011-11-30 09:15:37 -08:00
parent 3629308f2f
commit c3c4f6ed4c
2 changed files with 54 additions and 20 deletions

View file

@ -25,6 +25,7 @@ class ArcanistGitAPI extends ArcanistRepositoryAPI {
private $status;
private $relativeCommit = null;
private $repositoryHasNoCommits = false;
const SEARCH_LENGTH_FOR_PARENT_REVISIONS = 16;
/**
@ -41,17 +42,33 @@ class ArcanistGitAPI extends ArcanistRepositoryAPI {
return 'git';
}
public function getHasCommits() {
return !$this->repositoryHasNoCommits;
}
public function setRelativeCommit($relative_commit) {
$this->relativeCommit = $relative_commit;
return $this;
}
public function getLocalCommitInformation() {
if ($this->repositoryHasNoCommits) {
// Zero commits.
throw new Exception(
"You can't get local commit information for a repository with no ".
"commits.");
} else if ($this->relativeCommit == self::GIT_MAGIC_ROOT_COMMIT) {
// One commit.
$against = 'HEAD';
} else {
// 2..N commits.
$against = $this->getRelativeCommit().'..HEAD';
}
list($info) = execx(
'(cd %s && git log %s..%s --format=%s --)',
'(cd %s && git log %s --format=%s --)',
$this->getPath(),
$this->getRelativeCommit(),
'HEAD',
$against,
'%H%x00%T%x00%P%x00%at%x00%an%x00%s');
$commits = array();
@ -81,7 +98,14 @@ class ArcanistGitAPI extends ArcanistRepositoryAPI {
'(cd %s; git rev-parse --verify HEAD^)',
$this->getPath());
if ($err) {
list($err) = exec_manual(
'(cd %s; git rev-parse --verify HEAD)',
$this->getPath());
if ($err) {
$this->repositoryHasNoCommits = true;
}
$this->relativeCommit = self::GIT_MAGIC_ROOT_COMMIT;
} else {
$this->relativeCommit = 'HEAD^';
}
@ -159,11 +183,16 @@ class ArcanistGitAPI extends ArcanistRepositoryAPI {
public function getGitCommitLog() {
$relative = $this->getRelativeCommit();
if ($relative == self::GIT_MAGIC_ROOT_COMMIT) {
if ($this->repositoryHasNoCommits) {
// No commits yet.
return '';
} else if ($relative == self::GIT_MAGIC_ROOT_COMMIT) {
// First commit.
list($stdout) = execx(
'(cd %s; git log --format=medium HEAD)',
$this->getPath());
} else {
// 2..N commits.
list($stdout) = execx(
'(cd %s; git log --first-parent --format=medium %s..HEAD)',
$this->getPath(),
@ -221,8 +250,11 @@ class ArcanistGitAPI extends ArcanistRepositoryAPI {
// Find uncommitted changes.
$uncommitted_future = new ExecFuture(
"(cd %s; git diff {$options} --raw HEAD --)",
$this->getPath());
"(cd %s; git diff {$options} --raw %s --)",
$this->getPath(),
$this->repositoryHasNoCommits
? self::GIT_MAGIC_ROOT_COMMIT
: 'HEAD');
// Untracked files
$untracked_future = new ExecFuture(
@ -533,7 +565,7 @@ class ArcanistGitAPI extends ArcanistRepositoryAPI {
$base);
if ($err) {
throw new ArcanistUsageException(
"Unable to parse git commit name '{$base}'.");
"Unable to find any git commit named '{$base}' in this repository.");
}
}
$this->setRelativeCommit(trim($merge_base));

View file

@ -678,23 +678,12 @@ EOTEXT
$repository_api,
$paths);
} else if ($repository_api instanceof ArcanistGitAPI) {
$diff = $repository_api->getFullGitDiff();
if (!strlen($diff)) {
list($base, $tip) = $repository_api->getCommitRange();
if ($tip == 'HEAD') {
if (preg_match('/\^+HEAD/', $base)) {
$more = 'Did you mean HEAD^ instead of ^HEAD?';
} else {
$more = 'Did you specify the wrong relative commit?';
}
} else {
$more = 'Did you specify the wrong commit range?';
}
throw new ArcanistUsageException("No changes found. ({$more})");
throw new ArcanistUsageException(
"No changes found. (Did you specify the wrong commit range?)");
}
$changes = $parser->parseDiff($diff);
} else if ($repository_api instanceof ArcanistMercurialAPI) {
$diff = $repository_api->getFullMercurialDiff();
$changes = $parser->parseDiff($diff);
@ -937,6 +926,19 @@ EOTEXT
$parser = new ArcanistDiffParser();
$commit_messages = $repository_api->getGitCommitLog();
if (!strlen($commit_messages)) {
if (!$repository_api->getHasCommits()) {
throw new ArcanistUsageException(
"This git repository doesn't have any commits yet. You need to ".
"commit something before you can diff against it.");
} else {
throw new ArcanistUsageException(
"The commit range doesn't include any commits. (Did you diff ".
"against the wrong commit?)");
}
}
$commit_messages = $parser->parseDiff($commit_messages);
$problems = array();