1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 08:12:40 +01:00

"arc install-certificate", client side changes

Summary:
Provide an "install-certificate" workflow to simplify ~/.arcrc edits. See also
D460.

Test Plan:
Installed certificates via "arc install-certificate".

Reviewed By: aran
Reviewers: aran, jungejason, tuomaspelkonen
CC: aran, epriestley
Differential Revision: 465
This commit is contained in:
epriestley 2011-06-14 12:18:40 -07:00
parent 36de84eeee
commit d73179ea99
6 changed files with 212 additions and 11 deletions

View file

@ -61,6 +61,7 @@ if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
} }
$args = array_values($args); $args = array_values($args);
$working_directory = $_SERVER['PWD'];
try { try {
@ -72,7 +73,7 @@ try {
throw new ArcanistUsageException("No command provided. Try 'arc help'."); throw new ArcanistUsageException("No command provided. Try 'arc help'.");
} }
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($_SERVER['PWD']); $working_copy = ArcanistWorkingCopyIdentity::newFromPath($working_directory);
if ($load) { if ($load) {
$libs = $load; $libs = $load;
} else { } else {
@ -118,16 +119,7 @@ try {
} }
} }
$user_config = array(); $user_config = ArcanistBaseWorkflow::readUserConfigurationFile();
$user_config_path = getenv('HOME').'/.arcrc';
if (Filesystem::pathExists($user_config_path)) {
$user_config_data = Filesystem::readFile($user_config_path);
$user_config = json_decode($user_config_data, true);
if (!is_array($user_config)) {
throw new ArcanistUsageException(
"Your '~/.arcrc' file is not a valid JSON file.");
}
}
$config = $working_copy->getConfig('arcanist_configuration'); $config = $working_copy->getConfig('arcanist_configuration');
if ($config) { if ($config) {
@ -145,6 +137,7 @@ try {
} }
$workflow->setArcanistConfiguration($config); $workflow->setArcanistConfiguration($config);
$workflow->setCommand($command); $workflow->setCommand($command);
$workflow->setWorkingDirectory($working_directory);
$workflow->parseArguments(array_slice($args, 1)); $workflow->parseArguments(array_slice($args, 1));
$need_working_copy = $workflow->requiresWorkingCopy(); $need_working_copy = $workflow->requiresWorkingCopy();

View file

@ -36,6 +36,7 @@ phutil_register_library_map(array(
'ArcanistGitAPI' => 'repository/api/git', 'ArcanistGitAPI' => 'repository/api/git',
'ArcanistGitHookPreReceiveWorkflow' => 'workflow/git-hook-pre-receive', 'ArcanistGitHookPreReceiveWorkflow' => 'workflow/git-hook-pre-receive',
'ArcanistHelpWorkflow' => 'workflow/help', 'ArcanistHelpWorkflow' => 'workflow/help',
'ArcanistInstallCertificateWorkflow' => 'workflow/install-certificate',
'ArcanistLiberateLintEngine' => 'lint/engine/liberate', 'ArcanistLiberateLintEngine' => 'lint/engine/liberate',
'ArcanistLiberateWorkflow' => 'workflow/liberate', 'ArcanistLiberateWorkflow' => 'workflow/liberate',
'ArcanistLicenseLinter' => 'lint/linter/license', 'ArcanistLicenseLinter' => 'lint/linter/license',
@ -101,6 +102,7 @@ phutil_register_library_map(array(
'ArcanistGitAPI' => 'ArcanistRepositoryAPI', 'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
'ArcanistGitHookPreReceiveWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistGitHookPreReceiveWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistHelpWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistHelpWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistInstallCertificateWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLiberateLintEngine' => 'ArcanistLintEngine', 'ArcanistLiberateLintEngine' => 'ArcanistLintEngine',
'ArcanistLiberateWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistLiberateWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLicenseLinter' => 'ArcanistLinter', 'ArcanistLicenseLinter' => 'ArcanistLinter',

View file

@ -33,6 +33,7 @@ class ArcanistBaseWorkflow {
private $arcanistConfiguration; private $arcanistConfiguration;
private $parentWorkflow; private $parentWorkflow;
private $workingDirectory;
private $changeCache = array(); private $changeCache = array();
@ -91,6 +92,15 @@ class ArcanistBaseWorkflow {
return array(); return array();
} }
public function setWorkingDirectory($working_directory) {
$this->workingDirectory = $working_directory;
return $this;
}
public function getWorkingDirectory() {
return $this->workingDirectory;
}
private function setParentWorkflow($parent_workflow) { private function setParentWorkflow($parent_workflow) {
$this->parentWorkflow = $parent_workflow; $this->parentWorkflow = $parent_workflow;
return $this; return $this;
@ -627,4 +637,22 @@ class ArcanistBaseWorkflow {
return $argv; return $argv;
} }
public static function getUserConfigurationFileLocation() {
return getenv('HOME').'/.arcrc';
}
public static function readUserConfigurationFile() {
$user_config = array();
$user_config_path = self::getUserConfigurationFileLocation();
if (Filesystem::pathExists($user_config_path)) {
$user_config_data = Filesystem::readFile($user_config_path);
$user_config = json_decode($user_config_data, true);
if (!is_array($user_config)) {
throw new ArcanistUsageException(
"Your '~/.arcrc' file is not a valid JSON file.");
}
}
return $user_config;
}
} }

View file

@ -16,6 +16,7 @@ phutil_require_module('arcanist', 'parser/diff/change');
phutil_require_module('arcanist', 'repository/api/git'); phutil_require_module('arcanist', 'repository/api/git');
phutil_require_module('phutil', 'console'); phutil_require_module('phutil', 'console');
phutil_require_module('phutil', 'filesystem');
phutil_require_module('phutil', 'future/exec'); phutil_require_module('phutil', 'future/exec');

View file

@ -0,0 +1,156 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Installs arcanist certificates.
*
* @group workflow
*/
class ArcanistInstallCertificateWorkflow extends ArcanistBaseWorkflow {
public function getCommandHelp() {
return phutil_console_format(<<<EOTEXT
**install-certificate** [uri]
Supports: http, https
Installs Conduit credentials into your ~/.arcrc for the given install
of Phabricator. You need to do this before you can use 'arc', as it
enables 'arc' to link your command-line activity with your account on
the web. Run this command from within a project directory to install
that project's certificate, or specify an explicit URI (like
"https://phabricator.example.com/").
EOTEXT
);
}
public function getArguments() {
return array(
'*' => 'uri',
);
}
public function shouldShellComplete() {
return false;
}
public function requiresConduit() {
return false;
}
public function requiresWorkingCopy() {
return false;
}
public function run() {
$uri = $this->determineConduitURI();
echo "Installing certificate for '{$uri}'...\n";
$config = self::readUserConfigurationFile();
echo "Trying to connect to server...\n";
$conduit = new ConduitClient($uri);
$conduit->setTimeout(5);
try {
$conduit->callMethodSynchronous('conduit.ping', array());
} catch (Exception $ex) {
throw new ArcanistUsageException(
"Failed to connect to server: ".$ex->getMessage());
}
echo "Connection OK!\n";
$token_uri = new PhutilURI($uri);
$token_uri->setPath('/conduit/token/');
echo "\n";
echo phutil_console_format("**LOGIN TO PHABRICATOR**\n");
echo "Open this page in your browser and login to Phabricator if ".
"necessary:\n";
echo "\n";
echo " {$token_uri}\n";
echo "\n";
echo "Then paste the token on that page below.";
do {
$token = phutil_console_prompt('Paste token from that page:');
$token = trim($token);
if (strlen($token)) {
break;
}
} while (true);
echo "\n";
echo "Downloading authentication certificate...\n";
$info = $conduit->callMethodSynchronous(
'conduit.getcertificate',
array(
'token' => $token,
));
$user = $info['username'];
echo "Installing certificate for '{$user}'...\n";
$config['hosts'][$uri] = array(
'user' => $user,
'cert' => $info['certificate'],
);
$json_encoder = new PhutilJSON();
$json = $json_encoder->encodeFormatted($config);
echo "Writing ~/.arcconfig...\n";
$path = self::getUserConfigurationFileLocation();
Filesystem::writeFile($path, $json);
execx('chmod 600 %s', $path);
echo phutil_console_format(
"<bg:green>** SUCCESS! **</bg> Certificate installed.\n");
return 0;
}
private function determineConduitURI() {
$uri = $this->getArgument('uri');
if (count($uri) > 1) {
throw new ArcanistUsageException("Specify at most one URI.");
} else if (count($uri) == 1) {
$uri = reset($uri);
} else {
$working_copy = ArcanistWorkingCopyIdentity::newFromPath(
$this->getWorkingDirectory());
if (!$working_copy->getProjectRoot()) {
throw new ArcanistUsageException(
"Specify an explicit URI or run this command from within a project ".
"which is configured with a .arcconfig.");
}
$conduit_uri = $working_copy->getConduitURI();
if (!$conduit_uri) {
throw new ArcanistUsageException(
"This project's .arcconfig does not specify a Conduit URI.");
}
$uri = $conduit_uri;
}
$uri = new PhutilURI($uri);
$uri->setPath('/api/');
return (string)$uri;
}
}

View file

@ -0,0 +1,21 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('arcanist', 'exception/usage');
phutil_require_module('arcanist', 'workflow/base');
phutil_require_module('arcanist', 'workingcopyidentity');
phutil_require_module('phutil', 'conduit/client');
phutil_require_module('phutil', 'console');
phutil_require_module('phutil', 'filesystem');
phutil_require_module('phutil', 'future/exec');
phutil_require_module('phutil', 'parser/json');
phutil_require_module('phutil', 'parser/uri');
phutil_require_source('ArcanistInstallCertificateWorkflow.php');