mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Update the "WorkingCopy" API and create a fallback "Filesystem" working copy
Summary: Ref T11968. - Allow "WorkingCopy" objects to maintain an API object and update callers ("get...()" instead of "new...()"). - Always generate a WorkingCopy object and a RepositoryAPI object. Currently, code has to look like this: ``` $working_copy = ... if ($working_copy) { $repository_api = ... if ($repository_api [instanceof ... ]) { ``` This is clunky. There's also no reason some "arc" commands can't run outside a VCS working directory without special-casing how they interact with the filesystem. Conceptually, model the filesystem as a trivial VCS (which stores exactly one commit, always amends onto it, and discards history). Provide a trivial WorkingCopy and API for it. (This change isn't terribly interesting on its own, but chips away at landing the new Hardpoint infrastructure.) Test Plan: Ran `arc version`, `arc upgrade`. Maniphest Tasks: T11968 Differential Revision: https://secure.phabricator.com/D21070
This commit is contained in:
parent
a1ee2ab931
commit
0b3cd39230
9 changed files with 170 additions and 23 deletions
|
@ -187,7 +187,9 @@ phutil_register_library_map(array(
|
|||
'ArcanistFileUploader' => 'upload/ArcanistFileUploader.php',
|
||||
'ArcanistFilenameLinter' => 'lint/linter/ArcanistFilenameLinter.php',
|
||||
'ArcanistFilenameLinterTestCase' => 'lint/linter/__tests__/ArcanistFilenameLinterTestCase.php',
|
||||
'ArcanistFilesystemAPI' => 'repository/api/ArcanistFilesystemAPI.php',
|
||||
'ArcanistFilesystemConfigurationSource' => 'config/source/ArcanistFilesystemConfigurationSource.php',
|
||||
'ArcanistFilesystemWorkingCopy' => 'workingcopy/ArcanistFilesystemWorkingCopy.php',
|
||||
'ArcanistFlagWorkflow' => 'workflow/ArcanistFlagWorkflow.php',
|
||||
'ArcanistFlake8Linter' => 'lint/linter/ArcanistFlake8Linter.php',
|
||||
'ArcanistFlake8LinterTestCase' => 'lint/linter/__tests__/ArcanistFlake8LinterTestCase.php',
|
||||
|
@ -1130,7 +1132,9 @@ phutil_register_library_map(array(
|
|||
'ArcanistFileUploader' => 'Phobject',
|
||||
'ArcanistFilenameLinter' => 'ArcanistLinter',
|
||||
'ArcanistFilenameLinterTestCase' => 'ArcanistLinterTestCase',
|
||||
'ArcanistFilesystemAPI' => 'ArcanistRepositoryAPI',
|
||||
'ArcanistFilesystemConfigurationSource' => 'ArcanistDictionaryConfigurationSource',
|
||||
'ArcanistFilesystemWorkingCopy' => 'ArcanistWorkingCopy',
|
||||
'ArcanistFlagWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistFlake8Linter' => 'ArcanistExternalLinter',
|
||||
'ArcanistFlake8LinterTestCase' => 'ArcanistExternalLinterTestCase',
|
||||
|
|
100
src/repository/api/ArcanistFilesystemAPI.php
Normal file
100
src/repository/api/ArcanistFilesystemAPI.php
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistFilesystemAPI
|
||||
extends ArcanistRepositoryAPI {
|
||||
|
||||
public function getSourceControlSystemName() {
|
||||
return 'filesystem';
|
||||
}
|
||||
|
||||
protected function buildUncommittedStatus() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
protected function buildCommitRangeStatus() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getAllFiles() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getBlame($path) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getRawDiffText($path) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getOriginalFileData($path) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getCurrentFileData($path) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getLocalCommitInformation() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getSourceControlBaseRevision() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getCanonicalRevisionName($string) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getBranchName() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getSourceControlPath() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function isHistoryDefaultImmutable() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function supportsAmend() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getWorkingCopyRevision() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function updateWorkingCopy() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getMetadataPath() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function loadWorkingCopyDifferentialRevisions(
|
||||
ConduitClient $conduit,
|
||||
array $query) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function getRemoteURI() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function supportsLocalCommits() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
protected function buildLocalFuture(array $argv) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
public function supportsCommitRanges() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
}
|
|
@ -48,15 +48,10 @@ EOTEXT
|
|||
);
|
||||
|
||||
foreach ($roots as $lib => $root) {
|
||||
$is_git = false;
|
||||
|
||||
$working_copy = ArcanistWorkingCopy::newFromWorkingDirectory($root);
|
||||
if ($working_copy) {
|
||||
$repository_api = $working_copy->newRepositoryAPI();
|
||||
if ($repository_api instanceof ArcanistGitAPI) {
|
||||
$is_git = true;
|
||||
}
|
||||
}
|
||||
|
||||
$repository_api = $working_copy->getRepositoryAPI();
|
||||
$is_git = ($repository_api instanceof ArcanistGitAPI);
|
||||
|
||||
if (!$is_git) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
|
|
|
@ -43,15 +43,10 @@ EOTEXT
|
|||
'Preparing to upgrade "%s"...',
|
||||
$library));
|
||||
|
||||
$is_git = false;
|
||||
|
||||
$working_copy = ArcanistWorkingCopy::newFromWorkingDirectory($root);
|
||||
if ($working_copy) {
|
||||
$repository_api = $working_copy->newRepositoryAPI();
|
||||
if ($repository_api instanceof ArcanistGitAPI) {
|
||||
$is_git = true;
|
||||
}
|
||||
}
|
||||
|
||||
$repository_api = $working_copy->getRepositoryAPI();
|
||||
$is_git = ($repository_api instanceof ArcanistGitAPI);
|
||||
|
||||
if (!$is_git) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
|
|
27
src/workingcopy/ArcanistFilesystemWorkingCopy.php
Normal file
27
src/workingcopy/ArcanistFilesystemWorkingCopy.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistFilesystemWorkingCopy
|
||||
extends ArcanistWorkingCopy {
|
||||
|
||||
public function getMetadataDirectory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function newWorkingCopyFromDirectories(
|
||||
$working_directory,
|
||||
$ancestor_directory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function newRepositoryAPI() {
|
||||
return new ArcanistFilesystemAPI();
|
||||
}
|
||||
|
||||
public function getProjectConfigurationFilePath() {
|
||||
// We don't support project-level configuration for "filesytem" working
|
||||
// copies because scattering random ".arcconfig" files around the
|
||||
// filesystem and having them affect program behavior is silly.
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@ final class ArcanistGitWorkingCopy
|
|||
return new self();
|
||||
}
|
||||
|
||||
public function newRepositoryAPI() {
|
||||
protected function newRepositoryAPI() {
|
||||
return new ArcanistGitAPI($this->getPath());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ final class ArcanistMercurialWorkingCopy
|
|||
return new self();
|
||||
}
|
||||
|
||||
public function newRepositoryAPI() {
|
||||
protected function newRepositoryAPI() {
|
||||
return new ArcanistMercurialAPI($this->getPath());
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ final class ArcanistSubversionWorkingCopy
|
|||
return head($candidates);
|
||||
}
|
||||
|
||||
public function newRepositoryAPI() {
|
||||
protected function newRepositoryAPI() {
|
||||
return new ArcanistSubversionAPI($this->getPath());
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ abstract class ArcanistWorkingCopy
|
|||
|
||||
private $path;
|
||||
private $workingDirectory;
|
||||
private $repositoryAPI;
|
||||
|
||||
public static function newFromWorkingDirectory($path) {
|
||||
$working_types = id(new PhutilClassMapQuery())
|
||||
|
@ -25,8 +26,7 @@ abstract class ArcanistWorkingCopy
|
|||
continue;
|
||||
}
|
||||
|
||||
$working_copy->path = $ancestor_path;
|
||||
$working_copy->workingDirectory = $path;
|
||||
self::configureWorkingCopy($working_copy, $ancestor_path, $path);
|
||||
|
||||
$candidates[] = $working_copy;
|
||||
}
|
||||
|
@ -50,7 +50,16 @@ abstract class ArcanistWorkingCopy
|
|||
return $deepest->selectFromNestedWorkingCopies($candidates);
|
||||
}
|
||||
|
||||
return null;
|
||||
// If we haven't found a legitimate working copy that belongs to a
|
||||
// supported version control system, return a "filesystem" working copy.
|
||||
// This allows some commands to work as expected even if run outside
|
||||
// of a real working copy.
|
||||
|
||||
$working_copy = new ArcanistFilesystemWorkingCopy();
|
||||
|
||||
self::configureWorkingCopy($working_copy, $ancestor_path, $path);
|
||||
|
||||
return $working_copy;
|
||||
}
|
||||
|
||||
abstract protected function newWorkingCopyFromDirectories(
|
||||
|
@ -110,6 +119,23 @@ abstract class ArcanistWorkingCopy
|
|||
return last($candidates);
|
||||
}
|
||||
|
||||
abstract public function newRepositoryAPI();
|
||||
final public function getRepositoryAPI() {
|
||||
if (!$this->repositoryAPI) {
|
||||
$this->repositoryAPI = $this->newRepositoryAPI();
|
||||
}
|
||||
|
||||
return $this->repositoryAPI;
|
||||
}
|
||||
|
||||
abstract protected function newRepositoryAPI();
|
||||
|
||||
private static function configureWorkingCopy(
|
||||
ArcanistWorkingCopy $working_copy,
|
||||
$ancestor_path,
|
||||
$path) {
|
||||
|
||||
$working_copy->path = $ancestor_path;
|
||||
$working_copy->workingDirectory = $path;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue