Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2891691
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rARC Arcanist
Attached
Detach File
Event Timeline
Log In to Comment