Changeset View
Changeset View
Standalone View
Standalone View
src/workingcopy/ArcanistWorkingCopy.php
| <?php | <?php | ||||
| abstract class ArcanistWorkingCopy | abstract class ArcanistWorkingCopy | ||||
| extends Phobject { | extends Phobject { | ||||
| private $path; | private $path; | ||||
| private $workingDirectory; | private $workingDirectory; | ||||
| private $repositoryAPI; | |||||
| public static function newFromWorkingDirectory($path) { | public static function newFromWorkingDirectory($path) { | ||||
| $working_types = id(new PhutilClassMapQuery()) | $working_types = id(new PhutilClassMapQuery()) | ||||
| ->setAncestorClass(__CLASS__) | ->setAncestorClass(__CLASS__) | ||||
| ->execute(); | ->execute(); | ||||
| $paths = Filesystem::walkToRoot($path); | $paths = Filesystem::walkToRoot($path); | ||||
| $paths = array_reverse($paths); | $paths = array_reverse($paths); | ||||
| $candidates = array(); | $candidates = array(); | ||||
| foreach ($paths as $path_key => $ancestor_path) { | foreach ($paths as $path_key => $ancestor_path) { | ||||
| foreach ($working_types as $working_type) { | foreach ($working_types as $working_type) { | ||||
| $working_copy = $working_type->newWorkingCopyFromDirectories( | $working_copy = $working_type->newWorkingCopyFromDirectories( | ||||
| $path, | $path, | ||||
| $ancestor_path); | $ancestor_path); | ||||
| if (!$working_copy) { | if (!$working_copy) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| $working_copy->path = $ancestor_path; | self::configureWorkingCopy($working_copy, $ancestor_path, $path); | ||||
| $working_copy->workingDirectory = $path; | |||||
| $candidates[] = $working_copy; | $candidates[] = $working_copy; | ||||
| } | } | ||||
| } | } | ||||
| // If we've found multiple candidate working copies, we need to pick one. | // 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 | // We let the innermost working copy pick the best candidate from among | ||||
| // candidates of the same type. The rules for Git and Mercurial differ | // candidates of the same type. The rules for Git and Mercurial differ | ||||
| // slightly from the rules for Subversion. | // slightly from the rules for Subversion. | ||||
| if ($candidates) { | if ($candidates) { | ||||
| $deepest = last($candidates); | $deepest = last($candidates); | ||||
| foreach ($candidates as $key => $candidate) { | foreach ($candidates as $key => $candidate) { | ||||
| if (get_class($candidate) != get_class($deepest)) { | if (get_class($candidate) != get_class($deepest)) { | ||||
| unset($candidates[$key]); | unset($candidates[$key]); | ||||
| } | } | ||||
| } | } | ||||
| $candidates = array_values($candidates); | $candidates = array_values($candidates); | ||||
| return $deepest->selectFromNestedWorkingCopies($candidates); | 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( | abstract protected function newWorkingCopyFromDirectories( | ||||
| $working_directory, | $working_directory, | ||||
| $ancestor_directory); | $ancestor_directory); | ||||
| final public function getPath($to_file = null) { | final public function getPath($to_file = null) { | ||||
| return Filesystem::concatenatePaths( | return Filesystem::concatenatePaths( | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | abstract class ArcanistWorkingCopy | ||||
| } | } | ||||
| protected function selectFromNestedWorkingCopies(array $candidates) { | protected function selectFromNestedWorkingCopies(array $candidates) { | ||||
| // Normally, the best working copy in a stack is the deepest working copy. | // Normally, the best working copy in a stack is the deepest working copy. | ||||
| // Subversion uses slightly different rules. | // Subversion uses slightly different rules. | ||||
| return last($candidates); | 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; | |||||
| } | |||||
| } | } | ||||