Page MenuHomePhorge

No OneTemporary

diff --git a/src/parser/__tests__/ArcanistBaseCommitParserTestCase.php b/src/parser/__tests__/ArcanistBaseCommitParserTestCase.php
index 5d6b11d2..609595b6 100644
--- a/src/parser/__tests__/ArcanistBaseCommitParserTestCase.php
+++ b/src/parser/__tests__/ArcanistBaseCommitParserTestCase.php
@@ -1,162 +1,160 @@
<?php
final class ArcanistBaseCommitParserTestCase extends PhutilTestCase {
public function testBasics() {
// Verify that the very basics of base commit resolution work.
$this->assertCommit(
pht('Empty Rules'),
null,
array(
));
$this->assertCommit(
'Literal',
'xyz',
array(
'runtime' => 'literal:xyz',
));
}
public function testResolutionOrder() {
// Rules should be resolved in order: args, local, project, global. These
// test cases intentionally scramble argument order to test that resolution
// order is independent of argument order.
$this->assertCommit(
pht('Order: Args'),
'y',
array(
'local' => 'literal:n',
'project' => 'literal:n',
'runtime' => 'literal:y',
'user' => 'literal:n',
));
$this->assertCommit(
pht('Order: Local'),
'y',
array(
'project' => 'literal:n',
'local' => 'literal:y',
'user' => 'literal:n',
));
$this->assertCommit(
pht('Order: Project'),
'y',
array(
'project' => 'literal:y',
'user' => 'literal:n',
));
$this->assertCommit(
pht('Order: Global'),
'y',
array(
'user' => 'literal:y',
));
}
public function testLegacyRule() {
// 'global' should translate to 'user'
$this->assertCommit(
pht('"%s" name', 'global'),
'y',
array(
'runtime' => 'arc:global, arc:halt',
'local' => 'arc:halt',
'project' => 'arc:halt',
'user' => 'literal:y',
));
// 'args' should translate to 'runtime'
$this->assertCommit(
pht('"%s" name', 'args'),
'y',
array(
'runtime' => 'arc:project, literal:y',
'local' => 'arc:halt',
'project' => 'arc:args',
'user' => 'arc:halt',
));
}
public function testHalt() {
// 'arc:halt' should halt all processing.
$this->assertCommit(
pht('Halt'),
null,
array(
'runtime' => 'arc:halt',
'local' => 'literal:xyz',
));
}
public function testYield() {
// 'arc:yield' should yield to other rulesets.
$this->assertCommit(
pht('Yield'),
'xyz',
array(
'runtime' => 'arc:yield, literal:abc',
'local' => 'literal:xyz',
));
// This one should return to 'runtime' after exhausting 'local'.
$this->assertCommit(
pht('Yield + Return'),
'abc',
array(
'runtime' => 'arc:yield, literal:abc',
'local' => 'arc:skip',
));
}
public function testJump() {
// This should resolve to 'abc' without hitting any of the halts.
$this->assertCommit(
pht('Jump'),
'abc',
array(
'runtime' => 'arc:project, arc:halt',
'local' => 'literal:abc',
'project' => 'arc:user, arc:halt',
'user' => 'arc:local, arc:halt',
));
}
public function testJumpReturn() {
// After jumping to project, we should return to 'runtime'.
$this->assertCommit(
pht('Jump Return'),
'xyz',
array(
'runtime' => 'arc:project, literal:xyz',
'local' => 'arc:halt',
'project' => '',
'user' => 'arc:halt',
));
}
private function assertCommit($desc, $commit, $rules) {
$parser = $this->buildParser();
$result = $parser->resolveBaseCommit($rules);
$this->assertEqual($commit, $result, $desc);
}
private function buildParser() {
// TODO: This is a little hacky because we're using the Arcanist repository
// itself to execute tests with, but it should be OK until we get proper
// isolation for repository-oriented test cases.
$root = dirname(phutil_get_library_root('arcanist'));
- $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
- $configuration_manager = new ArcanistConfigurationManager();
- $configuration_manager->setWorkingCopyIdentity($working_copy);
- $repo = ArcanistRepositoryAPI::newAPIFromConfigurationManager(
- $configuration_manager);
+ $working_copy = ArcanistWorkingCopy::newFromWorkingDirectory($root);
- return new ArcanistBaseCommitParser($repo);
+ $api = $working_copy->newRepositoryAPI();
+
+ return new ArcanistBaseCommitParser($api);
}
}
diff --git a/src/workingcopy/ArcanistGitWorkingCopy.php b/src/workingcopy/ArcanistGitWorkingCopy.php
index 9cb157e7..820912ad 100644
--- a/src/workingcopy/ArcanistGitWorkingCopy.php
+++ b/src/workingcopy/ArcanistGitWorkingCopy.php
@@ -1,22 +1,26 @@
<?php
final class ArcanistGitWorkingCopy
extends ArcanistWorkingCopy {
public function getMetadataDirectory() {
return $this->getPath('.git');
}
protected function newWorkingCopyFromDirectories(
$working_directory,
$ancestor_directory) {
if (!Filesystem::pathExists($ancestor_directory.'/.git')) {
return null;
}
return new self();
}
+ public function newRepositoryAPI() {
+ return new ArcanistGitAPI($this->getPath());
+ }
+
}
diff --git a/src/workingcopy/ArcanistMercurialWorkingCopy.php b/src/workingcopy/ArcanistMercurialWorkingCopy.php
index f062270f..b5df4b62 100644
--- a/src/workingcopy/ArcanistMercurialWorkingCopy.php
+++ b/src/workingcopy/ArcanistMercurialWorkingCopy.php
@@ -1,22 +1,26 @@
<?php
final class ArcanistMercurialWorkingCopy
extends ArcanistWorkingCopy {
public function getMetadataDirectory() {
return $this->getPath('.hg');
}
protected function newWorkingCopyFromDirectories(
$working_directory,
$ancestor_directory) {
if (!Filesystem::pathExists($ancestor_directory.'/.hg')) {
return null;
}
return new self();
}
+ public function newRepositoryAPI() {
+ return new ArcanistMercurialAPI($this->getPath());
+ }
+
}
diff --git a/src/workingcopy/ArcanistSubversionWorkingCopy.php b/src/workingcopy/ArcanistSubversionWorkingCopy.php
index e14e7a60..6c4cefed 100644
--- a/src/workingcopy/ArcanistSubversionWorkingCopy.php
+++ b/src/workingcopy/ArcanistSubversionWorkingCopy.php
@@ -1,74 +1,78 @@
<?php
final class ArcanistSubversionWorkingCopy
extends ArcanistWorkingCopy {
public function getProjectConfigurationFilePath() {
// In Subversion, we allow ".arcconfig" to appear at any level of the
// filesystem between the working directory and the working copy root.
// We allow this because Subversion repositories are hierarchical and
// may have a "projects/xyz/" directory which is meaningfully an entirely
// different project from "projects/abc/".
// You can checkout "projects/" and have the ".svn/" directory appear
// there, then change into "abc/" and expect "arc" to operate within the
// context of the "abc/" project.
$paths = Filesystem::walkToRoot($this->getWorkingDirectory());
$root = $this->getPath();
foreach ($paths as $path) {
if (!Filesystem::isDescendant($path, $root)) {
break;
}
$candidate = $path.'/.arcconfig';
if (Filesystem::pathExists($candidate)) {
return $candidate;
}
}
return parent::getProjectConfigurationFilePath();
}
public function getMetadataDirectory() {
return $this->getPath('.svn');
}
protected function newWorkingCopyFromDirectories(
$working_directory,
$ancestor_directory) {
if (!Filesystem::pathExists($ancestor_directory.'/.svn')) {
return null;
}
return new self();
}
protected function selectFromNestedWorkingCopies(array $candidates) {
// To select the best working copy in Subversion, we first walk up the
// tree looking for a working copy with an ".arcconfig" file. If we find
// one, this anchors us.
foreach (array_reverse($candidates) as $candidate) {
$arcconfig = $candidate->getPath('.arcconfig');
if (Filesystem::pathExists($arcconfig)) {
return $candidate;
}
}
// If we didn't find one, we select the outermost working copy. This is
// because older versions of Subversion (prior to 1.7) put a ".svn" file
// in every directory, and all versions of Subversion allow you to check
// out any subdirectory of the project as a working copy.
// We could possibly refine this by testing if the working copy was made
// with a recent version of Subversion and picking the deepest working copy
// if it was, similar to Git and Mercurial.
return head($candidates);
}
+ public function newRepositoryAPI() {
+ return new ArcanistSubversionAPI($this->getPath());
+ }
+
}
diff --git a/src/workingcopy/ArcanistWorkingCopy.php b/src/workingcopy/ArcanistWorkingCopy.php
index c7b9632c..3a6a8ced 100644
--- a/src/workingcopy/ArcanistWorkingCopy.php
+++ b/src/workingcopy/ArcanistWorkingCopy.php
@@ -1,113 +1,115 @@
<?php
abstract class ArcanistWorkingCopy
extends Phobject {
private $path;
private $workingDirectory;
public static function newFromWorkingDirectory($path) {
$working_types = id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->execute();
$paths = Filesystem::walkToRoot($path);
$paths = array_reverse($paths);
$candidates = array();
foreach ($paths as $path_key => $ancestor_path) {
foreach ($working_types as $working_type) {
$working_copy = $working_type->newWorkingCopyFromDirectories(
$path,
$ancestor_path);
if (!$working_copy) {
continue;
}
$working_copy->path = $ancestor_path;
$working_copy->workingDirectory = $path;
$candidates[] = $working_copy;
}
}
// If we've found multiple candidate working copies, we need to pick one.
// We let the innermost working copy pick the best candidate from among
// candidates of the same type. The rules for Git and Mercurial differ
// slightly from the rules for Subversion.
if ($candidates) {
$deepest = last($candidates);
foreach ($candidates as $key => $candidate) {
if (get_class($candidate) != get_class($deepest)) {
unset($candidates[$key]);
}
}
$candidates = array_values($candidates);
return $deepest->selectFromNestedWorkingCopies($candidates);
}
return null;
}
abstract protected function newWorkingCopyFromDirectories(
$working_directory,
$ancestor_directory);
final public function getPath($to_file = null) {
return Filesystem::concatenatePaths(
array(
$this->path,
$to_file,
));
}
final public function getWorkingDirectory() {
return $this->workingDirectory;
}
public function getProjectConfigurationFilePath() {
return $this->getPath('.arcconfig');
}
public function getLocalConfigurationFilePath() {
if ($this->hasMetadataDirectory()) {
return $this->getMetadataPath('arc/config');
}
return null;
}
public function getMetadataDirectory() {
return null;
}
final public function hasMetadataDirectory() {
return ($this->getMetadataDirectory() !== null);
}
final public function getMetadataPath($to_file = null) {
if (!$this->hasMetadataDirectory()) {
throw new Exception(
pht(
'This working copy has no metadata directory, so you can not '.
'resolve metadata paths within it.'));
}
return Filesystem::concatenatePaths(
array(
$this->getMetadataDirectory(),
$to_file,
));
}
protected function selectFromNestedWorkingCopies(array $candidates) {
// Normally, the best working copy in a stack is the deepest working copy.
// Subversion uses slightly different rules.
return last($candidates);
}
+ abstract public function newRepositoryAPI();
+
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 15:36 (3 w, 23 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126060
Default Alt Text
(12 KB)

Event Timeline