2011-01-10 00:22:25 +01:00
|
|
|
#!/usr/bin/env php
|
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
Unify arguments for 'arc lint', 'arc unit'
Summary: See T645. These commands take inconsistent and overly-magical arguments
right now. Instead, make them behave consistently and allow them both to operate
on "arc <workflow> path path2 path3 ...", which is a generally useful workflow.
Test Plan: Ran "arc lint <path>", "arc unit <path>", "arc lint --rev
HEAD^^^^^^", "arc unit --rev HEAD^^^^^^^^^^^^", etc. Ran "arc diff --trace" and
verified --rev argument to child workflows.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, epriestley, btrahan
Maniphest Tasks: T645
Differential Revision: https://secure.phabricator.com/D1348
2012-01-09 21:40:50 +01:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-01-10 00:22:25 +01:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2011-12-22 19:23:29 +01:00
|
|
|
sanity_check_environment();
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
require_once dirname(__FILE__).'/__init_script__.php';
|
|
|
|
|
2011-02-19 20:36:08 +01:00
|
|
|
ini_set('memory_limit', -1);
|
|
|
|
|
2012-03-08 21:20:26 +01:00
|
|
|
$original_argv = $argv;
|
|
|
|
$args = new PhutilArgumentParser($argv);
|
|
|
|
$args->parseStandardArguments();
|
|
|
|
|
|
|
|
$argv = $args->getUnconsumedArgumentVector();
|
|
|
|
$config_trace_mode = $args->getArg('trace');
|
|
|
|
|
2011-02-19 07:17:41 +01:00
|
|
|
$force_conduit = null;
|
2012-05-22 01:45:03 +02:00
|
|
|
$force_conduit_version = null;
|
2012-03-08 21:20:26 +01:00
|
|
|
$args = $argv;
|
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;
|
2011-02-16 19:07:48 +01:00
|
|
|
} else if (preg_match('/^--load-phutil-library=(.*)$/', $arg, $matches)) {
|
|
|
|
unset($args[$key]);
|
2012-02-22 20:05:50 +01:00
|
|
|
$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];
|
2012-05-22 01:45:03 +02:00
|
|
|
} else if (preg_match('/^--conduit-version=(.*)$/', $arg, $matches)) {
|
|
|
|
unset($args[$key]);
|
|
|
|
$force_conduit_version = $matches[1];
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$args = array_values($args);
|
2011-12-24 08:48:46 +01:00
|
|
|
$working_directory = getcwd();
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
if (!$args) {
|
|
|
|
throw new ArcanistUsageException("No command provided. Try 'arc help'.");
|
|
|
|
}
|
|
|
|
|
Allow global config to load libraries and set test engines
Summary:
Khan Academy is looking into lint configuration, but doesn't use ".arcconfig" because they have a large number of repositories. Making configuration more flexible generally gives us more options for onboarding installs.
- Currently, only project config (".arcconfig") can load libraries. Allow user config ("~/.arcrc") to load libraries as well.
- Currently, only project config can set lint/unit engines. Allow user config to set default lint/unit engines.
- Add some type checking to "arc set-config".
- Add "arc set-config --show".
Test Plan:
- **load**
- Ran `arc set-config load xxx`, got error about format.
- Ran `arc set-config load ["apple"]`, got warning on running 'arc' commands (no such library) but was able to run 'arc set-config' again to clear it.
- Ran `arc set-config load ["/path/to/a/lib/src/"]`, worked.
- Ran `arc list --trace`, verified my library loaded in addition to `.arcconfig` libraries.
- Ran `arc list --load-phutil-library=xxx --trace`, verified only that library loaded.
- Ran `arc list --trace --load-phutil-library=apple --trace`, got hard error about bad library.
- Set `.arcconfig` to point at a bad library, verified hard error.
- **lint.engine** / **unit.engine**
- Removed lint engine from `.arcconfig`, ran "arc lint", got a run with specified engine.
- Removed unit engine from `.arcconfig`, ran "arc unit", got a run with specified engine.
- **--show**
- Ran `arc set-config --show`.
- **misc**
- Ran `arc get-config`.
Reviewers: csilvers, btrahan, vrana
Reviewed By: csilvers
CC: aran
Differential Revision: https://secure.phabricator.com/D2618
2012-05-31 20:41:39 +02:00
|
|
|
$global_config = ArcanistBaseWorkflow::readGlobalArcConfig();
|
2011-06-14 21:18:40 +02:00
|
|
|
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($working_directory);
|
2011-07-01 04:20:41 +02:00
|
|
|
|
Allow global config to load libraries and set test engines
Summary:
Khan Academy is looking into lint configuration, but doesn't use ".arcconfig" because they have a large number of repositories. Making configuration more flexible generally gives us more options for onboarding installs.
- Currently, only project config (".arcconfig") can load libraries. Allow user config ("~/.arcrc") to load libraries as well.
- Currently, only project config can set lint/unit engines. Allow user config to set default lint/unit engines.
- Add some type checking to "arc set-config".
- Add "arc set-config --show".
Test Plan:
- **load**
- Ran `arc set-config load xxx`, got error about format.
- Ran `arc set-config load ["apple"]`, got warning on running 'arc' commands (no such library) but was able to run 'arc set-config' again to clear it.
- Ran `arc set-config load ["/path/to/a/lib/src/"]`, worked.
- Ran `arc list --trace`, verified my library loaded in addition to `.arcconfig` libraries.
- Ran `arc list --load-phutil-library=xxx --trace`, verified only that library loaded.
- Ran `arc list --trace --load-phutil-library=apple --trace`, got hard error about bad library.
- Set `.arcconfig` to point at a bad library, verified hard error.
- **lint.engine** / **unit.engine**
- Removed lint engine from `.arcconfig`, ran "arc lint", got a run with specified engine.
- Removed unit engine from `.arcconfig`, ran "arc unit", got a run with specified engine.
- **--show**
- Ran `arc set-config --show`.
- **misc**
- Ran `arc get-config`.
Reviewers: csilvers, btrahan, vrana
Reviewed By: csilvers
CC: aran
Differential Revision: https://secure.phabricator.com/D2618
2012-05-31 20:41:39 +02:00
|
|
|
// Load additional libraries, which can provide new classes like configuration
|
|
|
|
// overrides, linters and lint engines, unit test engines, etc.
|
2011-07-01 04:20:41 +02:00
|
|
|
|
Allow global config to load libraries and set test engines
Summary:
Khan Academy is looking into lint configuration, but doesn't use ".arcconfig" because they have a large number of repositories. Making configuration more flexible generally gives us more options for onboarding installs.
- Currently, only project config (".arcconfig") can load libraries. Allow user config ("~/.arcrc") to load libraries as well.
- Currently, only project config can set lint/unit engines. Allow user config to set default lint/unit engines.
- Add some type checking to "arc set-config".
- Add "arc set-config --show".
Test Plan:
- **load**
- Ran `arc set-config load xxx`, got error about format.
- Ran `arc set-config load ["apple"]`, got warning on running 'arc' commands (no such library) but was able to run 'arc set-config' again to clear it.
- Ran `arc set-config load ["/path/to/a/lib/src/"]`, worked.
- Ran `arc list --trace`, verified my library loaded in addition to `.arcconfig` libraries.
- Ran `arc list --load-phutil-library=xxx --trace`, verified only that library loaded.
- Ran `arc list --trace --load-phutil-library=apple --trace`, got hard error about bad library.
- Set `.arcconfig` to point at a bad library, verified hard error.
- **lint.engine** / **unit.engine**
- Removed lint engine from `.arcconfig`, ran "arc lint", got a run with specified engine.
- Removed unit engine from `.arcconfig`, ran "arc unit", got a run with specified engine.
- **--show**
- Ran `arc set-config --show`.
- **misc**
- Ran `arc get-config`.
Reviewers: csilvers, btrahan, vrana
Reviewed By: csilvers
CC: aran
Differential Revision: https://secure.phabricator.com/D2618
2012-05-31 20:41:39 +02:00
|
|
|
// If the user specified "--load-phutil-library" one or more times from
|
|
|
|
// the command line, we load those libraries **instead** of whatever else
|
|
|
|
// is configured. This is basically a debugging feature to let you force
|
|
|
|
// specific libraries to load regardless of the state of the world.
|
|
|
|
if ($load) {
|
|
|
|
// Load the flag libraries. These must load, since the user specified them
|
|
|
|
// explicitly.
|
|
|
|
arcanist_load_libraries(
|
|
|
|
$load,
|
|
|
|
$must_load = true,
|
|
|
|
$lib_source = 'a "--load-phutil-library" flag',
|
|
|
|
$working_copy,
|
|
|
|
$config_trace_mode);
|
|
|
|
} else {
|
|
|
|
// Load libraries in global 'load' config, as per "arc set-config load". We
|
|
|
|
// need to fail softly if these break because errors would prevent the user
|
|
|
|
// from running "arc set-config" to correct them.
|
|
|
|
arcanist_load_libraries(
|
|
|
|
idx($global_config, 'load', array()),
|
|
|
|
$must_load = false,
|
|
|
|
$lib_source = 'the "load" setting in global config',
|
|
|
|
$working_copy,
|
|
|
|
$config_trace_mode);
|
|
|
|
|
|
|
|
// Load libraries in ".arcconfig". Libraries here must load.
|
|
|
|
arcanist_load_libraries(
|
|
|
|
$working_copy->getConfig('phutil_libraries'),
|
|
|
|
$must_load = true,
|
|
|
|
$lib_source = 'the "phutil_libraries" setting in ".arcconfig"',
|
|
|
|
$working_copy,
|
|
|
|
$config_trace_mode);
|
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) {
|
|
|
|
$config = new $config();
|
|
|
|
} else {
|
|
|
|
$config = new ArcanistConfiguration();
|
|
|
|
}
|
|
|
|
|
|
|
|
$command = strtolower($args[0]);
|
2012-02-21 22:16:52 +01:00
|
|
|
$args = array_slice($args, 1);
|
2011-01-10 00:22:25 +01:00
|
|
|
$workflow = $config->buildWorkflow($command);
|
|
|
|
if (!$workflow) {
|
2012-02-21 22:16:52 +01:00
|
|
|
|
|
|
|
// If the user has an alias, like 'arc alias dhelp diff help', look it up
|
|
|
|
// and substitute it. We do this only after trying to resolve the workflow
|
|
|
|
// normally to prevent you from doing silly things like aliasing 'alias'
|
|
|
|
// to something else.
|
|
|
|
|
2012-05-24 02:52:37 +02:00
|
|
|
$aliases = ArcanistAliasWorkflow::getAliases($working_copy);
|
2012-02-21 22:16:52 +01:00
|
|
|
list($new_command, $args) = ArcanistAliasWorkflow::resolveAliases(
|
|
|
|
$command,
|
|
|
|
$config,
|
2012-04-10 20:29:25 +02:00
|
|
|
$args,
|
|
|
|
$working_copy);
|
2012-02-21 22:16:52 +01:00
|
|
|
|
2012-05-24 02:52:37 +02:00
|
|
|
$full_alias = idx($aliases, $command, array());
|
|
|
|
$full_alias = implode(' ', $full_alias);
|
|
|
|
|
|
|
|
// Run shell command aliases.
|
|
|
|
|
|
|
|
if (ArcanistAliasWorkflow::isShellCommandAlias($new_command)) {
|
|
|
|
$shell_cmd = substr($full_alias, 1);
|
|
|
|
|
|
|
|
if ($config_trace_mode) {
|
|
|
|
echo "[alias: 'arc {$command}' -> \$ {$full_alias}]\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($args) {
|
|
|
|
$err = phutil_passthru('%C %Ls', $shell_cmd, $args);
|
|
|
|
} else {
|
|
|
|
$err = phutil_passthru('%C', $shell_cmd);
|
|
|
|
}
|
|
|
|
exit($err);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run arc command aliases.
|
|
|
|
|
2012-02-21 22:16:52 +01:00
|
|
|
if ($new_command) {
|
|
|
|
$workflow = $config->buildWorkflow($new_command);
|
2012-05-24 02:52:37 +02:00
|
|
|
if ($workflow) {
|
|
|
|
if ($config_trace_mode) {
|
|
|
|
echo "[alias: 'arc {$command}' -> 'arc {$full_alias}']\n";
|
|
|
|
}
|
|
|
|
$command = $new_command;
|
|
|
|
}
|
2012-02-21 22:16:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$workflow) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Unknown command '{$command}'. Try 'arc help'.");
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
2012-05-24 02:52:37 +02:00
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
$workflow->setArcanistConfiguration($config);
|
|
|
|
$workflow->setCommand($command);
|
2011-06-14 21:18:40 +02:00
|
|
|
$workflow->setWorkingDirectory($working_directory);
|
2012-02-21 22:16:52 +01:00
|
|
|
$workflow->parseArguments($args);
|
2011-01-10 00:22:25 +01:00
|
|
|
|
2012-05-22 01:45:03 +02:00
|
|
|
if ($force_conduit_version) {
|
|
|
|
$workflow->forceConduitVersion($force_conduit_version);
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
$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_repository_api;
|
|
|
|
|
|
|
|
if ($need_working_copy) {
|
2011-01-14 00:36:15 +01:00
|
|
|
if (!$working_copy->getProjectRoot()) {
|
|
|
|
throw new ArcanistUsageException(
|
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
2012-05-08 00:24:58 +02:00
|
|
|
"This command must be run in a Git, Mercurial or Subversion working ".
|
|
|
|
"copy.");
|
2011-01-14 00:36:15 +01:00
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
$workflow->setWorkingCopy($working_copy);
|
|
|
|
}
|
|
|
|
|
2011-07-14 00:03:40 +02:00
|
|
|
if ($force_conduit) {
|
|
|
|
$conduit_uri = $force_conduit;
|
|
|
|
} else {
|
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
2012-05-08 00:24:58 +02:00
|
|
|
if ($working_copy->getConduitURI()) {
|
|
|
|
$conduit_uri = $working_copy->getConduitURI();
|
|
|
|
} else {
|
|
|
|
$conduit_uri = idx($global_config, 'default');
|
|
|
|
}
|
2011-07-14 00:03:40 +02:00
|
|
|
}
|
|
|
|
if ($conduit_uri) {
|
|
|
|
// Set the URI path to '/api/'. TODO: Originally, I contemplated letting
|
|
|
|
// you deploy Phabricator somewhere other than the domain root, but ended
|
|
|
|
// up never pursuing that. We should get rid of all "/api/" silliness
|
|
|
|
// in things users are expected to configure. This is already happening
|
|
|
|
// to some degree, e.g. "arc install-certificate" does it for you.
|
|
|
|
$conduit_uri = new PhutilURI($conduit_uri);
|
|
|
|
$conduit_uri->setPath('/api/');
|
|
|
|
$conduit_uri = (string)$conduit_uri;
|
|
|
|
}
|
|
|
|
$workflow->setConduitURI($conduit_uri);
|
|
|
|
|
|
|
|
if ($need_conduit) {
|
2011-01-10 00:22:25 +01:00
|
|
|
if (!$conduit_uri) {
|
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
2012-05-08 00:24:58 +02:00
|
|
|
|
|
|
|
$message = phutil_console_format(
|
|
|
|
"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);
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
2011-07-14 00:03:40 +02:00
|
|
|
$workflow->establishConduit();
|
|
|
|
}
|
2011-02-06 08:32:04 +01:00
|
|
|
|
2011-07-14 00:03:40 +02:00
|
|
|
$hosts_config = idx($user_config, 'hosts', array());
|
|
|
|
$host_config = idx($hosts_config, $conduit_uri, array());
|
|
|
|
$user_name = idx($host_config, 'user');
|
|
|
|
$certificate = idx($host_config, 'cert');
|
2011-01-10 00:22:25 +01:00
|
|
|
|
2012-03-08 21:20:26 +01:00
|
|
|
$description = implode(' ', $original_argv);
|
2011-07-14 00:03:40 +02:00
|
|
|
$credentials = array(
|
|
|
|
'user' => $user_name,
|
|
|
|
'certificate' => $certificate,
|
|
|
|
'description' => $description,
|
|
|
|
);
|
|
|
|
$workflow->setConduitCredentials($credentials);
|
|
|
|
|
|
|
|
if ($need_auth) {
|
2011-06-27 05:43:24 +02:00
|
|
|
if (!$user_name || !$certificate) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
phutil_console_format(
|
|
|
|
"YOU NEED TO __INSTALL A CERTIFICATE__ TO LOGIN TO PHABRICATOR\n\n".
|
|
|
|
"You are trying to connect to '{$conduit_uri}' but do not have ".
|
|
|
|
"a certificate installed for this host. Run:\n\n".
|
|
|
|
" $ **arc install-certificate**\n\n".
|
|
|
|
"...to install one."));
|
|
|
|
}
|
2011-07-14 00:03:40 +02:00
|
|
|
$workflow->authenticateConduit();
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($need_repository_api) {
|
|
|
|
$repository_api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity(
|
|
|
|
$working_copy);
|
|
|
|
$workflow->setRepositoryAPI($repository_api);
|
|
|
|
}
|
|
|
|
|
2011-11-10 22:47:45 +01:00
|
|
|
$listeners = $working_copy->getConfig('events.listeners');
|
|
|
|
if ($listeners) {
|
|
|
|
foreach ($listeners as $listener) {
|
|
|
|
id(new $listener())->register();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
$config->willRunWorkflow($command, $workflow);
|
|
|
|
$workflow->willRunWorkflow();
|
|
|
|
$err = $workflow->run();
|
2011-07-12 23:34:27 +02:00
|
|
|
$config->didRunWorkflow($command, $workflow, $err);
|
2011-01-10 00:22:25 +01:00
|
|
|
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);
|
|
|
|
}
|
2011-12-22 19:23:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform some sanity checks against the possible diversity of PHP builds in
|
|
|
|
* the wild, like very old versions and builds that were compiled with flags
|
|
|
|
* that exclude core functionality.
|
|
|
|
*/
|
|
|
|
function sanity_check_environment() {
|
2012-04-06 21:55:05 +02:00
|
|
|
$min_version = '5.2.3';
|
2011-12-22 19:23:29 +01:00
|
|
|
$cur_version = phpversion();
|
|
|
|
if (version_compare($cur_version, $min_version, '<')) {
|
|
|
|
die_with_bad_php(
|
|
|
|
"You are running PHP version '{$cur_version}', which is older than ".
|
|
|
|
"the minimum version, '{$min_version}'. Update to at least ".
|
|
|
|
"'{$min_version}'.");
|
|
|
|
}
|
|
|
|
|
2012-03-05 19:02:37 +01:00
|
|
|
// NOTE: We don't have phutil_is_windows() yet here.
|
|
|
|
|
|
|
|
if (DIRECTORY_SEPARATOR != '/') {
|
|
|
|
$need_functions = array(
|
|
|
|
'curl_init' => array('builtin-dll', 'php_curl.dll'),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$need_functions = array(
|
2012-05-07 15:06:38 +02:00
|
|
|
'curl_init' => array(
|
|
|
|
'text',
|
|
|
|
"You need to install the cURL PHP extension, maybe with ".
|
|
|
|
"'apt-get install php5-curl' or 'yum install php53-curl' or ".
|
|
|
|
"something similar."),
|
|
|
|
'json_decode' => array('flag', '--without-json'),
|
2012-03-05 19:02:37 +01:00
|
|
|
);
|
|
|
|
}
|
2011-12-22 19:23:29 +01:00
|
|
|
|
|
|
|
$problems = array();
|
|
|
|
|
|
|
|
$config = null;
|
|
|
|
$show_config = false;
|
2012-03-05 19:02:37 +01:00
|
|
|
foreach ($need_functions as $fname => $resolution) {
|
2011-12-22 19:23:29 +01:00
|
|
|
if (function_exists($fname)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static $info;
|
|
|
|
if ($info === null) {
|
|
|
|
ob_start();
|
|
|
|
phpinfo(INFO_GENERAL);
|
|
|
|
$info = ob_get_clean();
|
|
|
|
$matches = null;
|
|
|
|
if (preg_match('/^Configure Command =>\s*(.*?)$/m', $info, $matches)) {
|
|
|
|
$config = $matches[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-05 19:02:37 +01:00
|
|
|
$generic = true;
|
|
|
|
list($what, $which) = $resolution;
|
|
|
|
|
|
|
|
if ($what == 'flag' && strpos($config, $which) !== false) {
|
2011-12-22 19:23:29 +01:00
|
|
|
$show_config = true;
|
2012-03-05 19:02:37 +01:00
|
|
|
$generic = false;
|
2011-12-22 19:23:29 +01:00
|
|
|
$problems[] =
|
2012-03-05 19:02:37 +01:00
|
|
|
"This build of PHP was compiled with the configure flag '{$which}', ".
|
2011-12-22 19:23:29 +01:00
|
|
|
"which means it does not have the function '{$fname}()'. This ".
|
|
|
|
"function is required for arc to run. Rebuild PHP without this flag. ".
|
|
|
|
"You may also be able to build or install the relevant extension ".
|
|
|
|
"separately.";
|
2012-03-05 19:02:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($what == 'builtin-dll') {
|
|
|
|
$generic = false;
|
|
|
|
$problems[] =
|
|
|
|
"Your install of PHP does not have the '{$which}' extension enabled. ".
|
|
|
|
"Edit your php.ini file and uncomment the line which reads ".
|
|
|
|
"'extension={$which}'.";
|
|
|
|
}
|
|
|
|
|
2012-05-07 15:06:38 +02:00
|
|
|
if ($what == 'text') {
|
|
|
|
$generic = false;
|
|
|
|
$problems[] = $which;
|
|
|
|
}
|
|
|
|
|
2012-03-05 19:02:37 +01:00
|
|
|
if ($generic) {
|
2011-12-22 19:23:29 +01:00
|
|
|
$problems[] =
|
|
|
|
"This build of PHP is missing the required function '{$fname}()'. ".
|
|
|
|
"Rebuild PHP or install the extension which provides '{$fname}()'.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($problems) {
|
|
|
|
if ($show_config) {
|
|
|
|
$problems[] = "PHP was built with this configure command:\n\n{$config}";
|
|
|
|
}
|
|
|
|
die_with_bad_php(implode("\n\n", $problems));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function die_with_bad_php($message) {
|
|
|
|
echo "\nPHP CONFIGURATION ERRORS\n\n";
|
|
|
|
echo $message;
|
|
|
|
echo "\n\n";
|
|
|
|
exit(1);
|
|
|
|
}
|
Allow global config to load libraries and set test engines
Summary:
Khan Academy is looking into lint configuration, but doesn't use ".arcconfig" because they have a large number of repositories. Making configuration more flexible generally gives us more options for onboarding installs.
- Currently, only project config (".arcconfig") can load libraries. Allow user config ("~/.arcrc") to load libraries as well.
- Currently, only project config can set lint/unit engines. Allow user config to set default lint/unit engines.
- Add some type checking to "arc set-config".
- Add "arc set-config --show".
Test Plan:
- **load**
- Ran `arc set-config load xxx`, got error about format.
- Ran `arc set-config load ["apple"]`, got warning on running 'arc' commands (no such library) but was able to run 'arc set-config' again to clear it.
- Ran `arc set-config load ["/path/to/a/lib/src/"]`, worked.
- Ran `arc list --trace`, verified my library loaded in addition to `.arcconfig` libraries.
- Ran `arc list --load-phutil-library=xxx --trace`, verified only that library loaded.
- Ran `arc list --trace --load-phutil-library=apple --trace`, got hard error about bad library.
- Set `.arcconfig` to point at a bad library, verified hard error.
- **lint.engine** / **unit.engine**
- Removed lint engine from `.arcconfig`, ran "arc lint", got a run with specified engine.
- Removed unit engine from `.arcconfig`, ran "arc unit", got a run with specified engine.
- **--show**
- Ran `arc set-config --show`.
- **misc**
- Ran `arc get-config`.
Reviewers: csilvers, btrahan, vrana
Reviewed By: csilvers
CC: aran
Differential Revision: https://secure.phabricator.com/D2618
2012-05-31 20:41:39 +02:00
|
|
|
|
|
|
|
|
|
|
|
function arcanist_load_libraries(
|
|
|
|
$load,
|
|
|
|
$must_load,
|
|
|
|
$lib_source,
|
|
|
|
ArcanistWorkingCopyIdentity $working_copy,
|
|
|
|
$config_trace_mode) {
|
|
|
|
|
|
|
|
if (!$load) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($load as $location) {
|
|
|
|
|
|
|
|
// Try to resolve the library location. We look in several places, in
|
|
|
|
// order:
|
|
|
|
//
|
|
|
|
// 1. Inside the working copy. This is for phutil libraries within the
|
|
|
|
// project. For instance "library/src" will resolve to
|
|
|
|
// "./library/src" if it exists.
|
|
|
|
// 2. In the same directory as the working copy. This allows you to
|
|
|
|
// check out a library alongside a working copy and reference it.
|
|
|
|
// If we haven't resolved yet, "library/src" will try to resolve to
|
|
|
|
// "../library/src" if it exists.
|
|
|
|
// 3. Using normal libphutil resolution rules. Generally, this means
|
|
|
|
// that it checks for libraries next to libphutil, then libraries
|
|
|
|
// in the PHP include_path.
|
|
|
|
//
|
|
|
|
// Note that absolute paths will just resolve absolutely through rule (1).
|
|
|
|
|
|
|
|
$resolved = false;
|
|
|
|
|
|
|
|
// Check inside the working copy. This also checks absolute paths, since
|
|
|
|
// they'll resolve absolute and just ignore the project root.
|
|
|
|
$resolved_location = Filesystem::resolvePath(
|
|
|
|
$location,
|
|
|
|
$working_copy->getProjectRoot());
|
|
|
|
if (Filesystem::pathExists($resolved_location)) {
|
|
|
|
$location = $resolved_location;
|
|
|
|
$resolved = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't find anything, check alongside the working copy.
|
|
|
|
if (!$resolved) {
|
|
|
|
$resolved_location = Filesystem::resolvePath(
|
|
|
|
$location,
|
|
|
|
dirname($working_copy->getProjectRoot()));
|
|
|
|
if (Filesystem::pathExists($resolved_location)) {
|
|
|
|
$location = $resolved_location;
|
|
|
|
$resolved = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($config_trace_mode) {
|
|
|
|
echo "Loading phutil library from '{$location}'...\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
$error = null;
|
|
|
|
try {
|
|
|
|
phutil_load_library($location);
|
|
|
|
} catch (PhutilBootloaderException $ex) {
|
|
|
|
$error = "Failed to load phutil library at location '{$location}'. ".
|
|
|
|
"This library is specified by {$lib_source}. Check that the ".
|
|
|
|
"setting is correct and the library is located in the right ".
|
|
|
|
"place.";
|
|
|
|
if ($must_load) {
|
|
|
|
throw new ArcanistUsageException($error);
|
|
|
|
} else {
|
|
|
|
file_put_contents(
|
|
|
|
'php://stderr',
|
|
|
|
phutil_console_wrap('WARNING: '.$error."\n\n"));
|
|
|
|
}
|
|
|
|
} catch (PhutilLibraryConflictException $ex) {
|
|
|
|
if ($ex->getLibrary() != 'arcanist') {
|
|
|
|
throw $ex;
|
|
|
|
}
|
|
|
|
$arc_dir = dirname(dirname(__FILE__));
|
|
|
|
$error =
|
|
|
|
"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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|