1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-21 22:32: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:
epriestley 2020-04-08 07:18:46 -07:00
parent a1ee2ab931
commit 0b3cd39230
9 changed files with 170 additions and 23 deletions

View file

@ -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',

View 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();
}
}

View file

@ -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(

View file

@ -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(

View 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;
}
}

View file

@ -18,7 +18,7 @@ final class ArcanistGitWorkingCopy
return new self();
}
public function newRepositoryAPI() {
protected function newRepositoryAPI() {
return new ArcanistGitAPI($this->getPath());
}

View file

@ -18,7 +18,7 @@ final class ArcanistMercurialWorkingCopy
return new self();
}
public function newRepositoryAPI() {
protected function newRepositoryAPI() {
return new ArcanistMercurialAPI($this->getPath());
}

View file

@ -70,7 +70,7 @@ final class ArcanistSubversionWorkingCopy
return head($candidates);
}
public function newRepositoryAPI() {
protected function newRepositoryAPI() {
return new ArcanistSubversionAPI($this->getPath());
}

View file

@ -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;
}
}