mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Allow 'arc' to run without '.arcconfig'
Summary: This is mostly an onboarding thing, but also allows "arc upload", "arc download", and "arc paste" to work anywhere on the system. - Try to read the Phabricator install URI from arc global config if we can't find ".arcconfig". - Build a WorkingCopy anyway if we can't find ".arcconfig", as long as we can find ".svn", ".git", or ".hg". - Make all the workflows handle "no project ID" at least somewhat gracefully. Test Plan: - Ran "arc diff" in .arcconfig-less Mercurial, Git, and Subversion working copies. - Ran "arc upload" and "arc download" from my desktop. - Ran "arc paste" from somewhere random. - Cleared my config and hit the error, got useful instructions. Reviewers: btrahan, csilvers Reviewed By: csilvers CC: aran Differential Revision: https://secure.phabricator.com/D2424
This commit is contained in:
parent
9063cfbdba
commit
5c684594d4
7 changed files with 68 additions and 25 deletions
|
@ -146,6 +146,7 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_config = ArcanistBaseWorkflow::readUserConfigurationFile();
|
$user_config = ArcanistBaseWorkflow::readUserConfigurationFile();
|
||||||
|
$global_config = ArcanistBaseWorkflow::readGlobalArcConfig();
|
||||||
|
|
||||||
$config = $working_copy->getConfig('arcanist_configuration');
|
$config = $working_copy->getConfig('arcanist_configuration');
|
||||||
if ($config) {
|
if ($config) {
|
||||||
|
@ -200,24 +201,25 @@ try {
|
||||||
$need_conduit = $need_conduit ||
|
$need_conduit = $need_conduit ||
|
||||||
$need_auth;
|
$need_auth;
|
||||||
$need_working_copy = $need_working_copy ||
|
$need_working_copy = $need_working_copy ||
|
||||||
$need_conduit ||
|
|
||||||
$need_repository_api;
|
$need_repository_api;
|
||||||
|
|
||||||
if ($need_working_copy) {
|
if ($need_working_copy) {
|
||||||
if (!$working_copy->getProjectRoot()) {
|
if (!$working_copy->getProjectRoot()) {
|
||||||
throw new ArcanistUsageException(
|
throw new ArcanistUsageException(
|
||||||
"There is no '.arcconfig' file in this directory or any parent ".
|
"This command must be run in a Git, Mercurial or Subversion working ".
|
||||||
"directory. Create a '.arcconfig' file to configure this project ".
|
"copy.");
|
||||||
"for use with Arcanist.");
|
|
||||||
}
|
}
|
||||||
$workflow->setWorkingCopy($working_copy);
|
$workflow->setWorkingCopy($working_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($force_conduit) {
|
if ($force_conduit) {
|
||||||
$conduit_uri = $force_conduit;
|
$conduit_uri = $force_conduit;
|
||||||
} else {
|
} else {
|
||||||
$conduit_uri = $working_copy->getConduitURI();
|
if ($working_copy->getConduitURI()) {
|
||||||
|
$conduit_uri = $working_copy->getConduitURI();
|
||||||
|
} else {
|
||||||
|
$conduit_uri = idx($global_config, 'default');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($conduit_uri) {
|
if ($conduit_uri) {
|
||||||
// Set the URI path to '/api/'. TODO: Originally, I contemplated letting
|
// Set the URI path to '/api/'. TODO: Originally, I contemplated letting
|
||||||
|
@ -233,9 +235,17 @@ try {
|
||||||
|
|
||||||
if ($need_conduit) {
|
if ($need_conduit) {
|
||||||
if (!$conduit_uri) {
|
if (!$conduit_uri) {
|
||||||
throw new ArcanistUsageException(
|
|
||||||
"No Conduit URI is specified in the .arcconfig file for this project. ".
|
$message = phutil_console_format(
|
||||||
"Specify the Conduit URI for the host Differential is running on.");
|
"This command requires arc to connect to a Phabricator install, but ".
|
||||||
|
"no Phabricator installation is configured. To configure a ".
|
||||||
|
"Phabricator URI:\n\n".
|
||||||
|
" - set a default location with `arc set-config default <uri>`; or\n".
|
||||||
|
" - specify '--conduit-uri=uri' explicitly; or\n".
|
||||||
|
" - run 'arc' in a working copy with an '.arcconfig'.\n");
|
||||||
|
|
||||||
|
$message = phutil_console_wrap($message);
|
||||||
|
throw new ArcanistUsageException($message);
|
||||||
}
|
}
|
||||||
$workflow->establishConduit();
|
$workflow->establishConduit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -537,6 +537,10 @@ EODIFF;
|
||||||
// this directory and belong to the same project.
|
// this directory and belong to the same project.
|
||||||
|
|
||||||
$project = $this->getWorkingCopyIdentity()->getProjectID();
|
$project = $this->getWorkingCopyIdentity()->getProjectID();
|
||||||
|
if (!$project) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
$results = $conduit->callMethodSynchronous(
|
$results = $conduit->callMethodSynchronous(
|
||||||
'differential.query',
|
'differential.query',
|
||||||
$query + array(
|
$query + array(
|
||||||
|
|
|
@ -927,11 +927,11 @@ abstract class ArcanistBaseWorkflow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function readGlobalArcConfig() {
|
public static function readGlobalArcConfig() {
|
||||||
return idx(self::readUserConfigurationFile(), 'config', array());
|
return idx(self::readUserConfigurationFile(), 'config', array());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeGlobalArcConfig(array $options) {
|
public static function writeGlobalArcConfig(array $options) {
|
||||||
$config = self::readUserConfigurationFile();
|
$config = self::readUserConfigurationFile();
|
||||||
$config['config'] = $options;
|
$config['config'] = $options;
|
||||||
self::writeUserConfigurationFile($config);
|
self::writeUserConfigurationFile($config);
|
||||||
|
@ -1102,12 +1102,21 @@ abstract class ArcanistBaseWorkflow {
|
||||||
return $this->repositoryEncoding;
|
return $this->repositoryEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$default = 'UTF-8';
|
||||||
|
|
||||||
|
$project_id = $this->getWorkingCopy()->getProjectID();
|
||||||
|
if (!$project_id) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
$project_info = $this->getConduit()->callMethodSynchronous(
|
$project_info = $this->getConduit()->callMethodSynchronous(
|
||||||
'arcanist.projectinfo',
|
'arcanist.projectinfo',
|
||||||
array(
|
array(
|
||||||
'name' => $this->getWorkingCopy()->getProjectID(),
|
'name' => $project_id,
|
||||||
));
|
));
|
||||||
$this->repositoryEncoding = nonempty($project_info['encoding'], 'UTF-8');
|
|
||||||
|
$this->repositoryEncoding = nonempty($project_info['encoding'], $default);
|
||||||
|
|
||||||
return $this->repositoryEncoding;
|
return $this->repositoryEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,14 +127,17 @@ EOTEXT
|
||||||
|
|
||||||
$actually_close = true;
|
$actually_close = true;
|
||||||
if ($is_finalize) {
|
if ($is_finalize) {
|
||||||
$project_info = $conduit->callMethodSynchronous(
|
$project_id = $this->getWorkingCopy()->getProjectID();
|
||||||
'arcanist.projectinfo',
|
if ($project_id) {
|
||||||
array(
|
$project_info = $conduit->callMethodSynchronous(
|
||||||
'name' => $this->getWorkingCopy()->getProjectID(),
|
'arcanist.projectinfo',
|
||||||
));
|
array(
|
||||||
if ($project_info['tracked'] ||
|
'name' => $project_id,
|
||||||
$revision['status'] != $status_accepted) {
|
));
|
||||||
$actually_close = false;
|
if ($project_info['tracked'] ||
|
||||||
|
$revision['status'] != $status_accepted) {
|
||||||
|
$actually_close = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($actually_close) {
|
if ($actually_close) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ EOTEXT
|
||||||
public function run() {
|
public function run() {
|
||||||
$argv = $this->getArgument('argv');
|
$argv = $this->getArgument('argv');
|
||||||
|
|
||||||
$config = $this->readGlobalArcConfig();
|
$config = self::readGlobalArcConfig();
|
||||||
if ($argv) {
|
if ($argv) {
|
||||||
$keys = $argv;
|
$keys = $argv;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -53,7 +53,7 @@ EOTEXT
|
||||||
throw new ArcanistUsageException("Specify a key and a value.");
|
throw new ArcanistUsageException("Specify a key and a value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$config = $this->readGlobalArcConfig();
|
$config = self::readGlobalArcConfig();
|
||||||
|
|
||||||
$key = $argv[0];
|
$key = $argv[0];
|
||||||
$val = $argv[1];
|
$val = $argv[1];
|
||||||
|
@ -65,7 +65,7 @@ EOTEXT
|
||||||
|
|
||||||
if (!strlen($val)) {
|
if (!strlen($val)) {
|
||||||
unset($config[$key]);
|
unset($config[$key]);
|
||||||
$this->writeGlobalArcConfig($config);
|
self::writeGlobalArcConfig($config);
|
||||||
|
|
||||||
if ($old === null) {
|
if ($old === null) {
|
||||||
echo "Deleted key '{$key}'.\n";
|
echo "Deleted key '{$key}'.\n";
|
||||||
|
@ -74,7 +74,7 @@ EOTEXT
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$config[$key] = $val;
|
$config[$key] = $val;
|
||||||
$this->writeGlobalArcConfig($config);
|
self::writeGlobalArcConfig($config);
|
||||||
|
|
||||||
if ($old === null) {
|
if ($old === null) {
|
||||||
echo "Set key '{$key}' = '{$val}'.\n";
|
echo "Set key '{$key}' = '{$val}'.\n";
|
||||||
|
|
|
@ -40,6 +40,23 @@ final class ArcanistWorkingCopyIdentity {
|
||||||
$project_root = $dir;
|
$project_root = $dir;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$project_root) {
|
||||||
|
foreach (Filesystem::walkToRoot($path) as $dir) {
|
||||||
|
$try = array(
|
||||||
|
$dir.'/.svn',
|
||||||
|
$dir.'/.hg',
|
||||||
|
$dir.'/.git',
|
||||||
|
);
|
||||||
|
foreach ($try as $trydir) {
|
||||||
|
if (Filesystem::pathExists($trydir)) {
|
||||||
|
$project_root = $dir;
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new ArcanistWorkingCopyIdentity($project_root, $config);
|
return new ArcanistWorkingCopyIdentity($project_root, $config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue