diffLinesOfContext; } public function setDiffLinesOfContext($lines) { $this->diffLinesOfContext = $lines; return $this; } public static function newAPIFromWorkingCopyIdentity( ArcanistWorkingCopyIdentity $working_copy) { $root = $working_copy->getProjectRoot(); if (!$root) { throw new ArcanistUsageException( "There is no readable '.arcconfig' file in the working directory or ". "any parent directory. Create an '.arcconfig' file to configure arc."); } // check if we're in an svn working copy list($err) = exec_manual('svn info'); if (!$err) { return newv('ArcanistSubversionAPI', array($root)); } if (Filesystem::pathExists($root.'/.hg')) { return newv('ArcanistMercurialAPI', array($root)); } $git_root = self::discoverGitBaseDirectory($root); if ($git_root) { if (!Filesystem::pathsAreEquivalent($root, $git_root)) { throw new ArcanistUsageException( "'.arcconfig' file is located at '{$root}', but working copy root ". "is '{$git_root}'. Move '.arcconfig' file to the working copy root."); } return newv('ArcanistGitAPI', array($root)); } throw new ArcanistUsageException( "The current working directory is not part of a working copy for a ". "supported version control system (svn, git or mercurial)."); } public function __construct($path) { $this->path = $path; } public function getPath($to_file = null) { if ($to_file !== null) { return $this->path.DIRECTORY_SEPARATOR. ltrim($to_file, DIRECTORY_SEPARATOR); } else { return $this->path.DIRECTORY_SEPARATOR; } } public function getUntrackedChanges() { return $this->getWorkingCopyFilesWithMask(self::FLAG_UNTRACKED); } public function getUnstagedChanges() { return $this->getWorkingCopyFilesWithMask(self::FLAG_UNSTAGED); } public function getUncommittedChanges() { return $this->getWorkingCopyFilesWithMask(self::FLAG_UNCOMMITTED); } public function getMergeConflicts() { return $this->getWorkingCopyFilesWithMask(self::FLAG_CONFLICT); } public function getIncompleteChanges() { return $this->getWorkingCopyFilesWithMask(self::FLAG_INCOMPLETE); } private function getWorkingCopyFilesWithMask($mask) { $match = array(); foreach ($this->getWorkingCopyStatus() as $file => $flags) { if ($flags & $mask) { $match[] = $file; } } return $match; } private static function discoverGitBaseDirectory($root) { try { // NOTE: This awkward construction is to make sure things work on Windows. $future = new ExecFuture('git rev-parse --show-cdup'); $future->setCWD($root); list($stdout) = $future->resolvex(); return Filesystem::resolvePath(rtrim($stdout, "\n"), $root); } catch (CommandException $ex) { if (preg_match('/^fatal: Not a git repository/', $ex->getStdErr())) { return null; } throw $ex; } } abstract public function getBlame($path); abstract public function getWorkingCopyStatus(); abstract public function getRawDiffText($path); abstract public function getOriginalFileData($path); abstract public function getCurrentFileData($path); abstract public function getLocalCommitInformation(); abstract public function getSourceControlBaseRevision(); abstract public function getCanonicalRevisionName($string); abstract public function supportsRelativeLocalCommits(); abstract public function getWorkingCopyRevision(); abstract public function updateWorkingCopy(); abstract public function loadWorkingCopyDifferentialRevisions( ConduitClient $conduit, array $query); public function hasLocalCommit($commit) { throw new ArcanistCapabilityNotSupportedException($this); } public function getCommitMessageForRevision($revision) { throw new ArcanistCapabilityNotSupportedException($this); } public function parseRelativeLocalCommit(array $argv) { throw new ArcanistCapabilityNotSupportedException($this); } public function getAllLocalChanges() { throw new ArcanistCapabilityNotSupportedException($this); } abstract public function supportsLocalBranchMerge(); public function performLocalBranchMerge($branch, $message) { throw new ArcanistCapabilityNotSupportedException($this); } public function getFinalizedRevisionMessage() { throw new ArcanistCapabilityNotSupportedException($this); } public function execxLocal($pattern /*, ... */) { $args = func_get_args(); return $this->buildLocalFuture($args)->resolvex(); } public function execManualLocal($pattern /*, ... */) { $args = func_get_args(); return $this->buildLocalFuture($args)->resolve(); } public function execFutureLocal($pattern /*, ... */) { $args = func_get_args(); return $this->buildLocalFuture($args); } abstract protected function buildLocalFuture(array $argv); }