2011-01-10 00:22:25 +01:00
|
|
|
#!/usr/bin/env php
|
|
|
|
<?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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
require_once dirname(__FILE__).'/__init_script__.php';
|
|
|
|
|
|
|
|
phutil_require_module('phutil', 'conduit/client');
|
|
|
|
phutil_require_module('phutil', 'console');
|
|
|
|
phutil_require_module('phutil', 'future/exec');
|
|
|
|
phutil_require_module('phutil', 'filesystem');
|
2011-01-13 00:45:17 +01:00
|
|
|
phutil_require_module('phutil', 'symbols');
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
phutil_require_module('arcanist', 'exception/usage');
|
|
|
|
phutil_require_module('arcanist', 'configuration');
|
|
|
|
phutil_require_module('arcanist', 'workingcopyidentity');
|
|
|
|
phutil_require_module('arcanist', 'repository/api/base');
|
|
|
|
|
2011-02-19 20:36:08 +01:00
|
|
|
ini_set('memory_limit', -1);
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
$config_trace_mode = false;
|
2011-02-19 07:17:41 +01:00
|
|
|
$force_conduit = null;
|
2011-01-10 00:22:25 +01:00
|
|
|
$args = array_slice($argv, 1);
|
2011-02-16 19:07:48 +01:00
|
|
|
$load = array();
|
|
|
|
$matches = null;
|
2011-01-10 00:22:25 +01:00
|
|
|
foreach ($args as $key => $arg) {
|
|
|
|
if ($arg == '--') {
|
|
|
|
break;
|
|
|
|
} else if ($arg == '--trace') {
|
|
|
|
unset($args[$key]);
|
|
|
|
$config_trace_mode = true;
|
2011-02-17 08:41:03 +01:00
|
|
|
} else if ($arg == '--no-ansi') {
|
|
|
|
unset($args[$key]);
|
|
|
|
PhutilConsoleFormatter::disableANSI(true);
|
2011-02-16 19:07:48 +01:00
|
|
|
} else if (preg_match('/^--load-phutil-library=(.*)$/', $arg, $matches)) {
|
|
|
|
unset($args[$key]);
|
|
|
|
$load['?'] = $matches[1];
|
2011-02-19 07:17:41 +01:00
|
|
|
} else if (preg_match('/^--conduit-uri=(.*)$/', $arg, $matches)) {
|
|
|
|
unset($args[$key]);
|
|
|
|
$force_conduit = $matches[1];
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-03 04:31:40 +01:00
|
|
|
// The POSIX extension is not available by default in some PHP installs.
|
|
|
|
if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
|
2011-02-17 08:41:03 +01:00
|
|
|
PhutilConsoleFormatter::disableANSI(true);
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
$args = array_values($args);
|
2011-06-14 21:18:40 +02:00
|
|
|
$working_directory = $_SERVER['PWD'];
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
if ($config_trace_mode) {
|
2011-05-17 01:07:10 +02:00
|
|
|
PhutilServiceProfiler::installEchoListener();
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$args) {
|
|
|
|
throw new ArcanistUsageException("No command provided. Try 'arc help'.");
|
|
|
|
}
|
|
|
|
|
2011-06-14 21:18:40 +02:00
|
|
|
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($working_directory);
|
2011-02-16 19:07:48 +01:00
|
|
|
if ($load) {
|
|
|
|
$libs = $load;
|
|
|
|
} else {
|
|
|
|
$libs = $working_copy->getConfig('phutil_libraries');
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
if ($libs) {
|
|
|
|
foreach ($libs as $name => $location) {
|
|
|
|
if ($config_trace_mode) {
|
|
|
|
echo "Loading phutil library '{$name}' from '{$location}'...\n";
|
|
|
|
}
|
2011-02-25 01:34:27 +01:00
|
|
|
$resolved_location = Filesystem::resolvePath(
|
2011-01-10 00:22:25 +01:00
|
|
|
$location,
|
|
|
|
$working_copy->getProjectRoot());
|
2011-02-25 01:34:27 +01:00
|
|
|
if (Filesystem::pathExists($resolved_location)) {
|
|
|
|
$location = $resolved_location;
|
|
|
|
}
|
2011-04-05 01:26:46 +02:00
|
|
|
try {
|
|
|
|
phutil_load_library($location);
|
|
|
|
} catch (PhutilBootloaderException $ex) {
|
|
|
|
$error_msg = sprintf(
|
|
|
|
'Failed to load library "%s" at location "%s". Please check the '.
|
|
|
|
'"phutil_libraries" setting in your .arcconfig file. Refer to page '.
|
|
|
|
'http://phabricator.com/docs/arcanist/article/'.
|
|
|
|
'Setting_Up_.arcconfig.html for more info.',
|
|
|
|
$name,
|
|
|
|
$location);
|
|
|
|
throw new ArcanistUsageException($error_msg);
|
2011-05-19 19:13:44 +02:00
|
|
|
} catch (PhutilLibraryConflictException $ex) {
|
|
|
|
if ($ex->getLibrary() != 'arcanist') {
|
|
|
|
throw $ex;
|
|
|
|
}
|
|
|
|
|
|
|
|
$arc_dir = dirname(dirname(__FILE__));
|
|
|
|
$error_msg =
|
|
|
|
"You are trying to run one copy of Arcanist on another copy of ".
|
|
|
|
"Arcanist. This operation is not supported. To execute Arcanist ".
|
|
|
|
"operations against this working copy, run './bin/arc' (from the ".
|
|
|
|
"current working copy) not some other copy of 'arc' (you ran one ".
|
|
|
|
"from '{$arc_dir}').";
|
|
|
|
|
|
|
|
throw new ArcanistUsageException($error_msg);
|
2011-04-05 01:26:46 +02:00
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
}
|
2011-02-06 08:32:04 +01:00
|
|
|
|
2011-06-14 21:18:40 +02:00
|
|
|
$user_config = ArcanistBaseWorkflow::readUserConfigurationFile();
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
$config = $working_copy->getConfig('arcanist_configuration');
|
|
|
|
if ($config) {
|
2011-01-13 00:45:17 +01:00
|
|
|
PhutilSymbolLoader::loadClass($config);
|
2011-01-10 00:22:25 +01:00
|
|
|
$config = new $config();
|
|
|
|
} else {
|
|
|
|
$config = new ArcanistConfiguration();
|
|
|
|
}
|
|
|
|
|
|
|
|
$command = strtolower($args[0]);
|
|
|
|
$workflow = $config->buildWorkflow($command);
|
|
|
|
if (!$workflow) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Unknown command '{$command}'. Try 'arc help'.");
|
|
|
|
}
|
|
|
|
$workflow->setArcanistConfiguration($config);
|
|
|
|
$workflow->setCommand($command);
|
2011-06-14 21:18:40 +02:00
|
|
|
$workflow->setWorkingDirectory($working_directory);
|
2011-01-10 00:22:25 +01:00
|
|
|
$workflow->parseArguments(array_slice($args, 1));
|
|
|
|
|
|
|
|
$need_working_copy = $workflow->requiresWorkingCopy();
|
|
|
|
$need_conduit = $workflow->requiresConduit();
|
|
|
|
$need_auth = $workflow->requiresAuthentication();
|
|
|
|
$need_repository_api = $workflow->requiresRepositoryAPI();
|
|
|
|
|
|
|
|
$need_conduit = $need_conduit ||
|
|
|
|
$need_auth;
|
|
|
|
$need_working_copy = $need_working_copy ||
|
|
|
|
$need_conduit ||
|
|
|
|
$need_repository_api;
|
|
|
|
|
|
|
|
if ($need_working_copy) {
|
2011-01-14 00:36:15 +01:00
|
|
|
if (!$working_copy->getProjectRoot()) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"There is no '.arcconfig' file in this directory or any parent ".
|
|
|
|
"directory. Create a '.arcconfig' file to configure this project ".
|
|
|
|
"for use with Arcanist.");
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
$workflow->setWorkingCopy($working_copy);
|
|
|
|
}
|
|
|
|
|
2011-02-06 08:32:04 +01:00
|
|
|
$set_guid = false;
|
2011-01-10 00:22:25 +01:00
|
|
|
if ($need_conduit) {
|
2011-02-19 07:17:41 +01:00
|
|
|
|
|
|
|
if ($force_conduit) {
|
|
|
|
$conduit_uri = $force_conduit;
|
|
|
|
} else {
|
|
|
|
$conduit_uri = $working_copy->getConduitURI();
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
if (!$conduit_uri) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"No Conduit URI is specified in the .arcconfig file for this project. ".
|
|
|
|
"Specify the Conduit URI for the host Differential is running on.");
|
|
|
|
}
|
|
|
|
$conduit = new ConduitClient($conduit_uri);
|
|
|
|
$workflow->setConduit($conduit);
|
2011-02-06 08:32:04 +01:00
|
|
|
|
2011-02-06 07:44:30 +01:00
|
|
|
$hosts_config = idx($user_config, 'hosts', array());
|
|
|
|
$host_config = idx($hosts_config, $conduit_uri, array());
|
2011-06-22 09:12:55 +02:00
|
|
|
$user_name = idx($host_config, 'user');
|
2011-02-06 07:44:30 +01:00
|
|
|
$certificate = idx($host_config, 'cert');
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
$description = implode(' ', $argv);
|
2011-03-16 23:17:07 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
$connection = $conduit->callMethodSynchronous(
|
|
|
|
'conduit.connect',
|
|
|
|
array(
|
|
|
|
'client' => 'arc',
|
|
|
|
'clientVersion' => 2,
|
|
|
|
'clientDescription' => php_uname('n').':'.$description,
|
|
|
|
'user' => $user_name,
|
|
|
|
'certificate' => $certificate,
|
|
|
|
));
|
|
|
|
} catch (ConduitClientException $ex) {
|
|
|
|
if ($ex->getErrorCode() == 'ERR-NO-CERTIFICATE') {
|
2011-04-10 22:09:31 +02:00
|
|
|
$message =
|
2011-06-20 15:01:46 +02:00
|
|
|
"\n".
|
2011-04-10 22:09:31 +02:00
|
|
|
phutil_console_format(
|
|
|
|
"YOU NEED TO __INSTALL A CERTIFICATE__ TO LOGIN TO PHABRICATOR").
|
|
|
|
"\n\n".
|
2011-06-20 15:01:46 +02:00
|
|
|
phutil_console_format(
|
|
|
|
" To do this, run: **arc install-certificate**").
|
2011-04-10 22:09:31 +02:00
|
|
|
"\n\n".
|
2011-06-20 15:01:46 +02:00
|
|
|
"The server '{$conduit_uri}' rejected your request:".
|
|
|
|
"\n".
|
|
|
|
$ex->getMessage();
|
2011-04-10 22:09:31 +02:00
|
|
|
throw new ArcanistUsageException($message);
|
2011-03-16 23:17:07 +01:00
|
|
|
} else {
|
|
|
|
throw $ex;
|
|
|
|
}
|
|
|
|
}
|
2011-02-06 08:32:04 +01:00
|
|
|
|
2011-02-06 07:44:30 +01:00
|
|
|
$workflow->setUserName($user_name);
|
|
|
|
$user_phid = idx($connection, 'userPHID');
|
|
|
|
if ($user_phid) {
|
2011-02-06 08:32:04 +01:00
|
|
|
$set_guid = true;
|
2011-02-06 07:44:30 +01:00
|
|
|
$workflow->setUserGUID($user_phid);
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($need_repository_api) {
|
|
|
|
$repository_api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity(
|
|
|
|
$working_copy);
|
|
|
|
$workflow->setRepositoryAPI($repository_api);
|
|
|
|
}
|
|
|
|
|
2011-02-06 08:32:04 +01:00
|
|
|
if ($need_auth && !$set_guid) {
|
2011-01-10 00:22:25 +01:00
|
|
|
$user_name = getenv('USER');
|
|
|
|
$user_find_future = $conduit->callMethod(
|
|
|
|
'user.find',
|
|
|
|
array(
|
|
|
|
'aliases' => array(
|
|
|
|
$user_name,
|
|
|
|
),
|
|
|
|
));
|
|
|
|
$user_guids = $user_find_future->resolve();
|
|
|
|
if (empty($user_guids[$user_name])) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Username '{$user_name}' is not recognized.");
|
|
|
|
}
|
|
|
|
|
|
|
|
$user_guid = $user_guids[$user_name];
|
|
|
|
$workflow->setUserGUID($user_guid);
|
|
|
|
$workflow->setUserName($user_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
$config->willRunWorkflow($command, $workflow);
|
|
|
|
$workflow->willRunWorkflow();
|
|
|
|
$err = $workflow->run();
|
|
|
|
if ($err == 0) {
|
|
|
|
$config->didRunWorkflow($command, $workflow);
|
|
|
|
}
|
|
|
|
exit($err);
|
|
|
|
|
|
|
|
} catch (ArcanistUsageException $ex) {
|
|
|
|
echo phutil_console_format(
|
|
|
|
"**Usage Exception:** %s\n",
|
|
|
|
$ex->getMessage());
|
|
|
|
if ($config_trace_mode) {
|
|
|
|
echo "\n";
|
|
|
|
throw $ex;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
if ($config_trace_mode) {
|
|
|
|
throw $ex;
|
|
|
|
}
|
|
|
|
|
|
|
|
echo phutil_console_format(
|
|
|
|
"\n**Exception:**\n%s\n%s\n",
|
|
|
|
$ex->getMessage(),
|
|
|
|
"(Run with --trace for a full exception trace.)");
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
}
|