mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 00:02:40 +01:00
Allow arc
to identify repositories without "project_id"
Summary: Ref T4343. Continues the process of reducing the prominence of Arcanist Projects. Primarily: - Query Phabricator to identify the working copy based on explicit configuration, or guess based on heuristics. - Enhance `arc which` to explain the process to the user. - The `project_id` key is no longer required in `.arcconfig`. Minor/cleanup changes: - Rename `project_id` to `project.name` (consistency, clarity). - Rename `conduit_uri` to `phabricator.uri` (consistency, clairty). - These both need documentation updates. - Add `repository.callsign` to explicitly bind to a repository. - Updated `.arcconfig` for the new values. - Fix a unit test which broke a while ago when we fixed a rare definition of "unstaged". - Make `getRepositoryUUID()` generic so we can get rid of one `instanceof`. Test Plan: - Ran `arc which`. - Ran `arc diff`. - This doesn't really change anything, so the only real risk is version compatibility breaks. This //does// introduce such a break, but the window is very narrow: if you upgrade `arc` after this commit, and try to diff against a Phabricator which was updated after yesterday (D8068) but before D8072 lands, the lookup will work so we'll add `repositoryPHID` to the `differential.creatediff` call, but it won't exist in Phabricator yet. This window is so narrow that I'm not going to try to fix it, as I'd guess there is a significant chance that no users will be affected. I don't see a clever way to fix it that doesn't involve a lot of work, either. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4343 Differential Revision: https://secure.phabricator.com/D8073
This commit is contained in:
parent
e4b1e8e681
commit
a7376624b4
13 changed files with 310 additions and 27 deletions
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"project_id" : "arcanist",
|
"phabricator.uri" : "https://secure.phabricator.com/",
|
||||||
"conduit_uri" : "https://secure.phabricator.com/",
|
|
||||||
"lint.engine" : "PhutilLintEngine",
|
"lint.engine" : "PhutilLintEngine",
|
||||||
"unit.engine" : "PhutilUnitTestEngine",
|
"unit.engine" : "PhutilUnitTestEngine",
|
||||||
"load" : [
|
"load" : [
|
||||||
|
|
|
@ -204,8 +204,8 @@ try {
|
||||||
if ($force_conduit) {
|
if ($force_conduit) {
|
||||||
$conduit_uri = $force_conduit;
|
$conduit_uri = $force_conduit;
|
||||||
} else {
|
} else {
|
||||||
$project_conduit_uri =
|
$project_conduit_uri = $configuration_manager->getProjectConfig(
|
||||||
$configuration_manager->getProjectConfig('conduit_uri');
|
'phabricator.uri');
|
||||||
if ($project_conduit_uri) {
|
if ($project_conduit_uri) {
|
||||||
$conduit_uri = $project_conduit_uri;
|
$conduit_uri = $project_conduit_uri;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -205,7 +205,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistBundleTestCase' => 'ArcanistTestCase',
|
'ArcanistBundleTestCase' => 'ArcanistTestCase',
|
||||||
'ArcanistCSSLintLinter' => 'ArcanistExternalLinter',
|
'ArcanistCSSLintLinter' => 'ArcanistExternalLinter',
|
||||||
'ArcanistCSSLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
'ArcanistCSSLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
||||||
'ArcanistCSharpLinter' => 'ArcanistFutureLinter',
|
'ArcanistCSharpLinter' => 'ArcanistLinter',
|
||||||
'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
|
'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
'ArcanistCapabilityNotSupportedException' => 'Exception',
|
'ArcanistCapabilityNotSupportedException' => 'Exception',
|
||||||
'ArcanistChooseInvalidRevisionException' => 'Exception',
|
'ArcanistChooseInvalidRevisionException' => 'Exception',
|
||||||
|
|
|
@ -32,6 +32,32 @@ final class ArcanistSettings {
|
||||||
'unit test engines.',
|
'unit test engines.',
|
||||||
'example' => '["/var/arc/customlib/src"]',
|
'example' => '["/var/arc/customlib/src"]',
|
||||||
),
|
),
|
||||||
|
'repository.callsign' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'example' => '"X"',
|
||||||
|
'help' => pht(
|
||||||
|
'Associate the working copy with a specific Phabricator repository. '.
|
||||||
|
'Normally, arc can figure this association out on its own, but if '.
|
||||||
|
'your setup is unusual you can use this option to tell it what the '.
|
||||||
|
'desired value is.'),
|
||||||
|
),
|
||||||
|
'phabricator.uri' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'legacy' => 'conduit_uri',
|
||||||
|
'example' => '"https://phabricator.mycompany.com/"',
|
||||||
|
'help' => pht(
|
||||||
|
'Associates this working copy with a specific installation of '.
|
||||||
|
'Phabricator.'),
|
||||||
|
),
|
||||||
|
'project.name' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'legacy' => 'project_id',
|
||||||
|
'example' => '"arcanist"',
|
||||||
|
'help' => pht(
|
||||||
|
'Associates this working copy with a named Arcanist Project. '.
|
||||||
|
'This is primarily useful if you use SVN and have several different '.
|
||||||
|
'projects in the same repository.'),
|
||||||
|
),
|
||||||
'lint.engine' => array(
|
'lint.engine' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'legacy' => 'lint_engine',
|
'legacy' => 'lint_engine',
|
||||||
|
|
|
@ -369,6 +369,18 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
|
||||||
if (preg_match('/^\* ([^\(].*)$/m', $stdout, $matches)) {
|
if (preg_match('/^\* ([^\(].*)$/m', $stdout, $matches)) {
|
||||||
return $matches[1];
|
return $matches[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemoteURI() {
|
||||||
|
list($stdout) = $this->execxLocal('remote show -n origin');
|
||||||
|
|
||||||
|
$matches = null;
|
||||||
|
if (preg_match('/^\s*Fetch URL: (.*)$/m', $stdout, $matches)) {
|
||||||
|
return trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1038,4 +1038,16 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
||||||
|
|
||||||
return array(trim($name), trim($rev));
|
return array(trim($name), trim($rev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRemoteURI() {
|
||||||
|
list($stdout) = $this->execxLocal('paths default');
|
||||||
|
|
||||||
|
$stdout = trim($stdout);
|
||||||
|
if (strlen($stdout)) {
|
||||||
|
return $stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,6 +330,8 @@ abstract class ArcanistRepositoryAPI {
|
||||||
abstract public function loadWorkingCopyDifferentialRevisions(
|
abstract public function loadWorkingCopyDifferentialRevisions(
|
||||||
ConduitClient $conduit,
|
ConduitClient $conduit,
|
||||||
array $query);
|
array $query);
|
||||||
|
abstract public function getRemoteURI();
|
||||||
|
|
||||||
|
|
||||||
public function getUnderlyingWorkingCopyRevision() {
|
public function getUnderlyingWorkingCopyRevision() {
|
||||||
return $this->getWorkingCopyRevision();
|
return $this->getWorkingCopyRevision();
|
||||||
|
@ -643,4 +645,8 @@ abstract class ArcanistRepositoryAPI {
|
||||||
return $commit;
|
return $commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRepositoryUUID() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,10 @@ final class ArcanistSubversionAPI extends ArcanistRepositoryAPI {
|
||||||
return 'svn';
|
return 'svn';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRemoteURI() {
|
||||||
|
return idx($this->getSVNInfo('/'), 'Repository Root');
|
||||||
|
}
|
||||||
|
|
||||||
public function buildInfoFuture($path) {
|
public function buildInfoFuture($path) {
|
||||||
if ($path == '/') {
|
if ($path == '/') {
|
||||||
// When the root of a working copy is referenced by a symlink and you
|
// When the root of a working copy is referenced by a symlink and you
|
||||||
|
@ -587,7 +591,7 @@ EODIFF;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRepositorySVNUUID() {
|
public function getRepositoryUUID() {
|
||||||
$info = $this->getSVNInfo('/');
|
$info = $this->getSVNInfo('/');
|
||||||
return $info['Repository UUID'];
|
return $info['Repository UUID'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ final class ArcanistRepositoryAPIStateTestCase extends ArcanistTestCase {
|
||||||
'UNSTAGED' => $f_mod | $f_uns | $f_unc,
|
'UNSTAGED' => $f_mod | $f_uns | $f_unc,
|
||||||
'UNTRACKED' => $f_unt,
|
'UNTRACKED' => $f_unt,
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEqual($expect_uncommitted, $api->getUncommittedStatus());
|
$this->assertEqual($expect_uncommitted, $api->getUncommittedStatus());
|
||||||
|
|
||||||
$expect_range = array(
|
$expect_range = array(
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
*
|
*
|
||||||
* @task conduit Conduit
|
* @task conduit Conduit
|
||||||
* @task scratch Scratch Files
|
* @task scratch Scratch Files
|
||||||
* @group workflow
|
* @task phabrep Phabricator Repositories
|
||||||
|
*
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
abstract class ArcanistBaseWorkflow extends Phobject {
|
abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
|
@ -64,6 +65,8 @@ abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
private $stashed;
|
private $stashed;
|
||||||
|
|
||||||
private $projectInfo;
|
private $projectInfo;
|
||||||
|
private $repositoryInfo;
|
||||||
|
private $repositoryReasons;
|
||||||
|
|
||||||
private $arcanistConfiguration;
|
private $arcanistConfiguration;
|
||||||
private $parentWorkflow;
|
private $parentWorkflow;
|
||||||
|
@ -1518,4 +1521,187 @@ abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
return $this->repositoryVersion;
|
return $this->repositoryVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Phabricator Repositories )------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the PHID of the Phabricator repository this working copy corresponds
|
||||||
|
* to. Returns `null` no repository can be identified.
|
||||||
|
*
|
||||||
|
* @return phid|null Repository PHID, or null if no repository can be
|
||||||
|
* identified.
|
||||||
|
*
|
||||||
|
* @task phabrep
|
||||||
|
*/
|
||||||
|
protected function getRepositoryPHID() {
|
||||||
|
return idx($this->getRepositoryInformation(), 'phid');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the callsign of the Phabricator repository this working copy
|
||||||
|
* corresponds to. Returns `null` no repository can be identified.
|
||||||
|
*
|
||||||
|
* @return string|null Repository callsign, or null if no repository can be
|
||||||
|
* identified.
|
||||||
|
*
|
||||||
|
* @task phabrep
|
||||||
|
*/
|
||||||
|
protected function getRepositoryCallsign() {
|
||||||
|
return idx($this->getRepositoryInformation(), 'callsign');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get human-readable reasoning explaining how `arc` evaluated which
|
||||||
|
* Phabricator repository corresponds to this working copy. Used by
|
||||||
|
* `arc which` to explain the process to users.
|
||||||
|
*
|
||||||
|
* @return list<string> Human-readable explanation of the repository
|
||||||
|
* association process.
|
||||||
|
*
|
||||||
|
* @task phabrep
|
||||||
|
*/
|
||||||
|
protected function getRepositoryReasons() {
|
||||||
|
$this->getRepositoryInformation();
|
||||||
|
return $this->repositoryReasons;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task phabrep
|
||||||
|
*/
|
||||||
|
private function getRepositoryInformation() {
|
||||||
|
if ($this->repositoryInfo === null) {
|
||||||
|
list($info, $reasons) = $this->loadRepositoryInformation();
|
||||||
|
$this->repositoryInfo = $info;
|
||||||
|
$this->repositoryReasons = $reasons;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->repositoryInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task phabrep
|
||||||
|
*/
|
||||||
|
private function loadRepositoryInformation() {
|
||||||
|
list($query, $reasons) = $this->getRepositoryQuery();
|
||||||
|
if (!$query) {
|
||||||
|
return array(null, $reasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$results = $this->getConduit()->callMethodSynchronous(
|
||||||
|
'repository.query',
|
||||||
|
$query);
|
||||||
|
} catch (ConduitClientException $ex) {
|
||||||
|
if ($ex->getErrorCode() == 'ERR-CONDUIT-CALL') {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'This version of Arcanist is more recent than the version of '.
|
||||||
|
'Phabricator you are connecting to: the Phabricator install is '.
|
||||||
|
'out of date and does not have support for identifying '.
|
||||||
|
'repositories by callsign or URI. Update Phabricator to enable '.
|
||||||
|
'these features.');
|
||||||
|
return array(null, $reasons);
|
||||||
|
}
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = null;
|
||||||
|
if (!$results) {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'No repositories matched the query. Check that your configuration '.
|
||||||
|
'is correct, or use "repository.callsign" to select a repository '.
|
||||||
|
'explicitly.');
|
||||||
|
} else if (count($results) > 1) {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Multiple repostories (%s) matched the query. You can use the '.
|
||||||
|
'"repository.callsign" configuration to select the one you want.',
|
||||||
|
implode(', ', ipull($results, 'callsign')));
|
||||||
|
} else {
|
||||||
|
$result = head($results);
|
||||||
|
$reasons[] = pht('Found a unique matching repository.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($result, $reasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task phabrep
|
||||||
|
*/
|
||||||
|
private function getRepositoryQuery() {
|
||||||
|
$reasons = array();
|
||||||
|
|
||||||
|
$callsign = $this->getConfigFromAnySource('repository.callsign');
|
||||||
|
if ($callsign) {
|
||||||
|
$query = array(
|
||||||
|
'callsigns' => array($callsign),
|
||||||
|
);
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Configuration value "repository.callsign" is set to "%s".',
|
||||||
|
$callsign);
|
||||||
|
return array($query, $reasons);
|
||||||
|
} else {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Configuration value "repository.callsign" is empty.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$project_info = $this->getProjectInfo();
|
||||||
|
if ($this->getProjectInfo()) {
|
||||||
|
if (!empty($project_info['repository']['callsign'])) {
|
||||||
|
$callsign = $project_info['repository']['callsign'];
|
||||||
|
$query = array(
|
||||||
|
'callsigns' => array($callsign),
|
||||||
|
);
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Configuration value "project.id" is set to "%s"; this project '.
|
||||||
|
'is associated with the "%s" repository.',
|
||||||
|
$this->getWorkingCopy()->getProjectID(),
|
||||||
|
$callsign);
|
||||||
|
return array($query, $reasons);
|
||||||
|
} else {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Configuration value "project.id" is set to "%s", but this '.
|
||||||
|
'project is not associated with a repository.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Configuration value "project.id" is empty.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$uuid = $this->getRepositoryAPI()->getRepositoryUUID();
|
||||||
|
if ($uuid !== null) {
|
||||||
|
$query = array(
|
||||||
|
'uuids' => array($uuid),
|
||||||
|
);
|
||||||
|
$reasons[] = pht(
|
||||||
|
'The UUID for this working copy is "%s".',
|
||||||
|
$uuid);
|
||||||
|
return array($query, $reasons);
|
||||||
|
} else {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'This repository has no VCS UUID (this is normal for git/hg).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote_uri = $this->getRepositoryAPI()->getRemoteURI();
|
||||||
|
if ($remote_uri !== null) {
|
||||||
|
$query = array(
|
||||||
|
'remoteURIs' => array($remote_uri),
|
||||||
|
);
|
||||||
|
$reasons[] = pht(
|
||||||
|
'The remote URI for this working copy is "%s".',
|
||||||
|
$remote_uri);
|
||||||
|
return array($query, $reasons);
|
||||||
|
} else {
|
||||||
|
$reasons[] = pht(
|
||||||
|
'Unable to determine the remote URI for this repository.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(null, $reasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -508,9 +508,9 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
$diff_spec = array(
|
$diff_spec = array(
|
||||||
'changes' => mpull($changes, 'toDictionary'),
|
'changes' => mpull($changes, 'toDictionary'),
|
||||||
'lintStatus' => $this->getLintStatus($lint_result),
|
'lintStatus' => $this->getLintStatus($lint_result),
|
||||||
'unitStatus' => $this->getUnitStatus($unit_result),
|
'unitStatus' => $this->getUnitStatus($unit_result),
|
||||||
) + $this->buildDiffSpecification();
|
) + $this->buildDiffSpecification();
|
||||||
|
|
||||||
$conduit = $this->getConduit();
|
$conduit = $this->getConduit();
|
||||||
|
@ -2243,6 +2243,7 @@ EOTEXT
|
||||||
$vcs = $repository_api->getSourceControlSystemName();
|
$vcs = $repository_api->getSourceControlSystemName();
|
||||||
$source_path = $repository_api->getPath();
|
$source_path = $repository_api->getPath();
|
||||||
$branch = $repository_api->getBranchName();
|
$branch = $repository_api->getBranchName();
|
||||||
|
$repo_uuid = $repository_api->getRepositoryUUID();
|
||||||
|
|
||||||
if ($repository_api instanceof ArcanistGitAPI) {
|
if ($repository_api instanceof ArcanistGitAPI) {
|
||||||
$info = $this->getGitParentLogInfo();
|
$info = $this->getGitParentLogInfo();
|
||||||
|
@ -2258,8 +2259,6 @@ EOTEXT
|
||||||
if ($info['uuid']) {
|
if ($info['uuid']) {
|
||||||
$repo_uuid = $info['uuid'];
|
$repo_uuid = $info['uuid'];
|
||||||
}
|
}
|
||||||
} else if ($repository_api instanceof ArcanistSubversionAPI) {
|
|
||||||
$repo_uuid = $repository_api->getRepositorySVNUUID();
|
|
||||||
} else if ($repository_api instanceof ArcanistMercurialAPI) {
|
} else if ($repository_api instanceof ArcanistMercurialAPI) {
|
||||||
|
|
||||||
$bookmark = $repository_api->getActiveBookmark();
|
$bookmark = $repository_api->getActiveBookmark();
|
||||||
|
@ -2280,7 +2279,7 @@ EOTEXT
|
||||||
$project_id = $this->getWorkingCopy()->getProjectID();
|
$project_id = $this->getWorkingCopy()->getProjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
$data = array(
|
||||||
'sourceMachine' => php_uname('n'),
|
'sourceMachine' => php_uname('n'),
|
||||||
'sourcePath' => $source_path,
|
'sourcePath' => $source_path,
|
||||||
'branch' => $branch,
|
'branch' => $branch,
|
||||||
|
@ -2288,12 +2287,16 @@ EOTEXT
|
||||||
'sourceControlSystem' => $vcs,
|
'sourceControlSystem' => $vcs,
|
||||||
'sourceControlPath' => $base_path,
|
'sourceControlPath' => $base_path,
|
||||||
'sourceControlBaseRevision' => $base_revision,
|
'sourceControlBaseRevision' => $base_revision,
|
||||||
'parentRevisionID' => $parent,
|
|
||||||
'repositoryUUID' => $repo_uuid,
|
|
||||||
'creationMethod' => 'arc',
|
'creationMethod' => 'arc',
|
||||||
'arcanistProject' => $project_id,
|
'arcanistProject' => $project_id,
|
||||||
'authorPHID' => $this->getUserPHID(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$repository_phid = $this->getRepositoryPHID();
|
||||||
|
if ($repository_phid) {
|
||||||
|
$data['repositoryPHID'] = $repository_phid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ EOTEXT
|
||||||
public function getCommandHelp() {
|
public function getCommandHelp() {
|
||||||
return phutil_console_format(<<<EOTEXT
|
return phutil_console_format(<<<EOTEXT
|
||||||
Supports: svn, git, hg
|
Supports: svn, git, hg
|
||||||
Shows which commits 'arc diff' will select, and which revision is in
|
Shows which repository the current working copy corresponds to,
|
||||||
|
which commits 'arc diff' will select, and which revision is in
|
||||||
the working copy (or which revisions, if more than one matches).
|
the working copy (or which revisions, if more than one matches).
|
||||||
EOTEXT
|
EOTEXT
|
||||||
);
|
);
|
||||||
|
@ -69,6 +70,11 @@ EOTEXT
|
||||||
|
|
||||||
public function run() {
|
public function run() {
|
||||||
|
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
|
$this->printRepositorySection();
|
||||||
|
$console->writeOut("\n");
|
||||||
|
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
|
||||||
$arg_commit = $this->getArgument('commit');
|
$arg_commit = $this->getArgument('commit');
|
||||||
|
@ -184,4 +190,34 @@ EOTEXT
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function printRepositorySection() {
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
$console->writeOut("**%s**\n", pht('REPOSITORY'));
|
||||||
|
|
||||||
|
$callsign = $this->getRepositoryCallsign();
|
||||||
|
|
||||||
|
$console->writeOut(
|
||||||
|
"%s\n\n",
|
||||||
|
pht(
|
||||||
|
'To identify the repository associated with this working copy, '.
|
||||||
|
'arc followed this process:'));
|
||||||
|
|
||||||
|
foreach ($this->getRepositoryReasons() as $reason) {
|
||||||
|
$reason = phutil_console_wrap($reason, 4);
|
||||||
|
$console->writeOut("%s\n\n", $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($callsign) {
|
||||||
|
$console->writeOut(
|
||||||
|
"%s\n",
|
||||||
|
pht('This working copy is associated with the %s repository.',
|
||||||
|
phutil_console_format('**%s**', $callsign)));
|
||||||
|
} else {
|
||||||
|
$console->writeOut(
|
||||||
|
"%s\n",
|
||||||
|
pht('This working copy is not associated with any repository.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,6 +187,7 @@ final class ArcanistWorkingCopyIdentity {
|
||||||
|
|
||||||
private static function parseRawConfigFile($raw_config, $from_where) {
|
private static function parseRawConfigFile($raw_config, $from_where) {
|
||||||
$proj = json_decode($raw_config, true);
|
$proj = json_decode($raw_config, true);
|
||||||
|
|
||||||
if (!is_array($proj)) {
|
if (!is_array($proj)) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Unable to parse '.arcconfig' file '{$from_where}'. The file contents ".
|
"Unable to parse '.arcconfig' file '{$from_where}'. The file contents ".
|
||||||
|
@ -194,16 +195,7 @@ final class ArcanistWorkingCopyIdentity {
|
||||||
"FILE CONTENTS\n".
|
"FILE CONTENTS\n".
|
||||||
substr($raw_config, 0, 2048));
|
substr($raw_config, 0, 2048));
|
||||||
}
|
}
|
||||||
$required_keys = array(
|
|
||||||
'project_id',
|
|
||||||
);
|
|
||||||
foreach ($required_keys as $key) {
|
|
||||||
if (!array_key_exists($key, $proj)) {
|
|
||||||
throw new Exception(
|
|
||||||
"Required key '{$key}' is missing from '.arcconfig' file ".
|
|
||||||
"'{$from_where}'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $proj;
|
return $proj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +205,12 @@ final class ArcanistWorkingCopyIdentity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProjectID() {
|
public function getProjectID() {
|
||||||
|
$project_id = $this->getProjectConfig('project.name');
|
||||||
|
if ($project_id) {
|
||||||
|
return $project_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is an older name for the setting.
|
||||||
return $this->getProjectConfig('project_id');
|
return $this->getProjectConfig('project_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue