'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create and update libphutil libraries.
|
|
|
|
*
|
|
|
|
* This workflow is unusual and involves reexecuting 'arc liberate' as a
|
|
|
|
* subprocess with "--remap" and "--verify". This is because there is no way
|
|
|
|
* to unload or reload a library, so every process is stuck with the library
|
|
|
|
* definition it had when it first loaded. This is normally fine, but
|
|
|
|
* problematic in this case because 'arc liberate' modifies library definitions.
|
|
|
|
*
|
|
|
|
* @group workflow
|
|
|
|
*/
|
2012-01-31 21:07:05 +01:00
|
|
|
final class ArcanistLiberateWorkflow extends ArcanistBaseWorkflow {
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
|
Make Arcanist workflow names explicit
Summary:
Currently, adding a new workflow requires you to override ArcanistConfiguration, which is messy. Instead, just load everything that extends ArcanistBaseWorkflow.
Remove all the rules tying workflow names to class names through arcane incantations.
This has a very small performance cost in that we need to load every Workflow class every time now, but we don't hit __init__ and such anymore and it was pretty negligible on my machine (98ms vs 104ms or something).
Test Plan: Ran "arc help", "arc which", "arc diff", etc.
Reviewers: edward, vrana, btrahan
Reviewed By: edward
CC: aran, zeeg
Differential Revision: https://secure.phabricator.com/D3691
2012-10-17 17:35:03 +02:00
|
|
|
public function getWorkflowName() {
|
|
|
|
return 'liberate';
|
|
|
|
}
|
|
|
|
|
2012-03-05 19:02:37 +01:00
|
|
|
public function getCommandSynopses() {
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
return phutil_console_format(<<<EOTEXT
|
|
|
|
**liberate** [__path__]
|
2012-03-05 19:02:37 +01:00
|
|
|
EOTEXT
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCommandHelp() {
|
|
|
|
return phutil_console_format(<<<EOTEXT
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
Supports: libphutil
|
|
|
|
Create or update a libphutil library, generating required metadata
|
2011-08-02 19:12:36 +02:00
|
|
|
files like \__init__.php.
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
EOTEXT
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getArguments() {
|
|
|
|
return array(
|
|
|
|
'all' => array(
|
|
|
|
'help' =>
|
|
|
|
"Drop the module cache before liberating. This will completely ".
|
|
|
|
"reanalyze the entire library. Thorough, but slow!",
|
|
|
|
),
|
|
|
|
'force-update' => array(
|
|
|
|
'help' =>
|
|
|
|
"Force the library map to be updated, even in the presence of ".
|
|
|
|
"lint errors.",
|
|
|
|
),
|
|
|
|
'remap' => array(
|
|
|
|
'hide' => true,
|
|
|
|
'help' =>
|
|
|
|
"Internal. Run the remap step of liberation. You do not need to ".
|
|
|
|
"run this unless you are debugging the workflow.",
|
|
|
|
),
|
|
|
|
'verify' => array(
|
|
|
|
'hide' => true,
|
|
|
|
'help' =>
|
|
|
|
"Internal. Run the verify step of liberation. You do not need to ".
|
|
|
|
"run this unless you are debugging the workflow.",
|
|
|
|
),
|
2012-05-30 23:18:11 +02:00
|
|
|
'upgrade' => array(
|
|
|
|
'hide' => true,
|
|
|
|
'help' => "Experimental. Upgrade library to v2.",
|
|
|
|
),
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
'*' => 'argv',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function run() {
|
|
|
|
$argv = $this->getArgument('argv');
|
|
|
|
if (count($argv) > 1) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Provide only one path to 'arc liberate'. The path should be a ".
|
|
|
|
"directory where you want to create or update a libphutil library.");
|
|
|
|
} else if (count($argv) == 0) {
|
|
|
|
$path = getcwd();
|
|
|
|
} else {
|
|
|
|
$path = reset($argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
$is_remap = $this->getArgument('remap');
|
|
|
|
$is_verify = $this->getArgument('verify');
|
|
|
|
|
|
|
|
$path = Filesystem::resolvePath($path);
|
|
|
|
|
|
|
|
if (Filesystem::pathExists($path) && is_dir($path)) {
|
|
|
|
$init = id(new FileFinder($path))
|
|
|
|
->withPath('*/__phutil_library_init__.php')
|
|
|
|
->find();
|
|
|
|
} else {
|
|
|
|
$init = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($init) {
|
|
|
|
if (count($init) > 1) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Specified directory contains more than one libphutil library. Use ".
|
|
|
|
"a more specific path.");
|
|
|
|
}
|
|
|
|
$path = Filesystem::resolvePath(dirname(reset($init)), $path);
|
|
|
|
} else {
|
|
|
|
$found = false;
|
|
|
|
foreach (Filesystem::walkToRoot($path) as $dir) {
|
|
|
|
if (Filesystem::pathExists($dir.'/__phutil_library_init__.php')) {
|
|
|
|
$path = $dir;
|
2012-06-21 20:52:16 +02:00
|
|
|
$found = true;
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$found) {
|
|
|
|
echo "No library currently exists at that path...\n";
|
|
|
|
$this->liberateCreateDirectory($path);
|
|
|
|
$this->liberateCreateLibrary($path);
|
2012-08-23 00:27:13 +02:00
|
|
|
return;
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-30 23:18:11 +02:00
|
|
|
$version = $this->getLibraryFormatVersion($path);
|
|
|
|
switch ($version) {
|
|
|
|
case 1:
|
|
|
|
if ($this->getArgument('upgrade')) {
|
|
|
|
return $this->upgradeLibrary($path);
|
|
|
|
}
|
2012-06-26 21:40:42 +02:00
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"This library is using libphutil v1, which is no longer supported. ".
|
|
|
|
"Run 'arc liberate --upgrade' to upgrade to v2.");
|
2012-05-30 23:18:11 +02:00
|
|
|
case 2:
|
|
|
|
if ($this->getArgument('upgrade')) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Can't upgrade a v2 library!");
|
|
|
|
}
|
|
|
|
return $this->liberateVersion2($path);
|
|
|
|
default:
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Unknown library version '{$version}'!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getLibraryFormatVersion($path) {
|
|
|
|
$map_file = $path.'/__phutil_library_map__.php';
|
|
|
|
if (!Filesystem::pathExists($map_file)) {
|
|
|
|
// Default to library v1.
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
$map = Filesystem::readFile($map_file);
|
|
|
|
|
|
|
|
$matches = null;
|
|
|
|
if (preg_match('/@phutil-library-version (\d+)/', $map, $matches)) {
|
|
|
|
return (int)$matches[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function liberateVersion2($path) {
|
|
|
|
$bin = $this->getScriptPath('scripts/phutil_rebuild_map.php');
|
|
|
|
|
|
|
|
return phutil_passthru(
|
2013-03-11 02:08:14 +01:00
|
|
|
'php %s %C %s',
|
2012-05-30 23:18:11 +02:00
|
|
|
$bin,
|
|
|
|
$this->getArgument('all') ? '--drop-cache' : '',
|
|
|
|
$path);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function upgradeLibrary($path) {
|
|
|
|
$inits = id(new FileFinder($path))
|
|
|
|
->withPath('*/__init__.php')
|
|
|
|
->withType('f')
|
|
|
|
->find();
|
|
|
|
|
|
|
|
echo "Removing __init__.php files...\n";
|
|
|
|
foreach ($inits as $init) {
|
|
|
|
Filesystem::remove($path.'/'.$init);
|
|
|
|
}
|
|
|
|
|
|
|
|
echo "Upgrading library to v2...\n";
|
|
|
|
$this->liberateVersion2($path);
|
|
|
|
}
|
|
|
|
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
private function liberateCreateDirectory($path) {
|
|
|
|
if (Filesystem::pathExists($path)) {
|
|
|
|
if (!is_dir($path)) {
|
|
|
|
throw new ArcanistUsageException(
|
|
|
|
"Provide a directory to create or update a libphutil library in.");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
echo "The directory '{$path}' does not exist.";
|
|
|
|
if (!phutil_console_confirm('Do you want to create it?')) {
|
|
|
|
throw new ArcanistUsageException("Cancelled.");
|
|
|
|
}
|
|
|
|
|
|
|
|
execx('mkdir -p %s', $path);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function liberateCreateLibrary($path) {
|
|
|
|
$init_path = $path.'/__phutil_library_init__.php';
|
|
|
|
if (Filesystem::pathExists($init_path)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
echo "Creating new libphutil library in '{$path}'.\n";
|
|
|
|
echo "Choose a name for the new library.\n";
|
|
|
|
do {
|
|
|
|
$name = phutil_console_prompt('What do you want to name this library?');
|
2012-07-26 03:37:25 +02:00
|
|
|
if (preg_match('/^[a-z-]+$/', $name)) {
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
break;
|
|
|
|
} else {
|
2012-07-26 03:37:25 +02:00
|
|
|
echo "Library name should contain only lowercase letters and ".
|
|
|
|
"hyphens.\n";
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
}
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
$template =
|
|
|
|
"<?php\n\n".
|
|
|
|
"phutil_register_library('{$name}', __FILE__);\n";
|
|
|
|
|
2012-08-23 00:27:13 +02:00
|
|
|
echo "Writing '__phutil_library_init__.php' to '{$path}'...\n";
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
Filesystem::writeFile($init_path, $template);
|
2012-08-23 00:27:13 +02:00
|
|
|
$this->liberateVersion2($path);
|
'arc liberate', convenience wrapper for various libphutil operations
Summary:
The story for creating and maintaining libphutil libraries and modules
is pretty terrible right now: you need to know a bunch of secret scripts and
dark magic. Provide 'arc liberate' which endeavors to always do the right thing
and put a library in the correct state.
Test Plan:
Ran liberate on libphutil, arcanist, phabricator; created new
libphutil libraries, added classes to them, liberated everything, introduced
errors etc and liberated that stuff, nothing was obviously broken in a terrible
way..?
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, epriestley
Differential Revision: 269
2011-05-12 01:30:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function getScriptPath($script) {
|
|
|
|
$root = dirname(phutil_get_library_root('arcanist'));
|
|
|
|
return $root.'/'.$script;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|