Add Workflows to PhutilArgumentParser

Summary:
Provides a way to build commands that operate in several modes, like "git" and "arc" do.

Basically, we add a new parseWorkflows(workflows) method to PhutilArgumentParser. It works like this:

  $args = new PhutilArgumentParser($argv);
  $args->parsePartial(/* global options */); // Optional, for options all workflows accept.
  $workflow = $args->parseWorkflows(
    array(
      /* ... */
    ));

You provide a list of PhutilArgumentWorkflow objects to parseWorkflows(). There are two ways to write those objects:

  - Lightweight: Instantiate and configure a PhutilArgumentWorkflow to put options and behavior in the script.
  - Heavyweight: Extend PhutilArgumentWorkflow to put all the options and behavior in a class.

The intent is to provide a balance between making this useful for scripting (so you can have a self-contained script that still uses workflows) and for building larger CLI tools like arc.

To build a lightweight workflow, do this:

  $workflow = id(new PhutilArgumentWorkflow())
    ->setName('example')
    ->setSynopsis('...')
    ->setArguments(
      array(
        /* Takes specs just like parse() and parsePartial(). */
      ));

To build a heavyweight workflow, do this:

  class ExampleWorkflow extends PhutilArgumentWorkflow {

    protected function didConstruct() {
      $this->setName('...');
      $this->setSynopsis('...');
    }

    public function isExecutable() {
      return true;
    }

    public function execute(PhutilArgumentParser $args) {
      /* do things when user types "./script.php example" */
      return 0;
    }
  }

With lightweight workflows (which return false from isExecutable()), parseWorkflows() will return the workflow the user selected.
With heavyweight workflows (which return true from isExecutable()), parseWorkflows() will run the workflow and exit with an appropriate status code.

A builtin PhutilHelpArgumentWorkflow allows you to make "script.php help [workflow]" work easily.

I also wrote a simple "calculator" example that should be a good reference.

Test Plan: I've converted `phd`, but want to test/doc/unit test this more thoroughly.

Reviewers: davidreuss, btrahan, vrana, jungejason

Reviewed By: davidreuss

CC: aran, epriestley

Maniphest Tasks: T345

Differential Revision: https://secure.phabricator.com/D1640
Don't highlight documents containing word rainbow by rainbow

Summary: It caused us some troubles because some serious business document was displayed as rainbow to our serious business partners (MFA rainbow.com).

Test Plan: Display document with the word 'rainbow'.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin

Differential Revision: https://secure.phabricator.com/D2324
When testing __destruct() code, call it explicitly

Summary: HipHop hides Exceptions thrown

Test Plan: Ran the CI tests; they now work as expected.

Reviewers: jungejason, epriestley

Reviewed By: epriestley

CC: epriestley, aran

Differential Revision: https://secure.phabricator.com/D2362
Remove commit template from libphutil

Summary: This is out of date, unnecessary, and supplied by the server now. The documentation no longer references it.

Test Plan: Grepped for references.

Reviewers: btrahan, vrana

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D2386
Minor, improve an error message.
Disable `xdebug.max_nesting_level` in __init_script__.php

Summary:
  - See T1192.
  - Do all the environment stuff //before// including code.
  - Do output buffer stuff first since it will completely silence any errors in the other things.

Test Plan:
  - Set `xdebug.max_nesting_level` to 5, ran "arc". After this change, no error.

Reviewers: btrahan, jungejason

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1192

Differential Revision: https://secure.phabricator.com/D2414
Add "LinesOfALargeExecFuture" abstraction

Summary:
  - This is for D2457.
  - We have an existing `LinesOfALargeFile` class for buffered, line-oriented processing of large input streams.
  - Splits existing `LinesOfALargeFile` class into abstract `LinesOfALarge` and concrete `LinesOfALargeFile`.
  - Changes next() algorithm to be iterative rather than recursive.
  - Allows the user to specify a line delimiter character.
  - Adds concrete subclass `LinesOfALargeExecFuture`.
  - Document and cover all three classes.

Test Plan: Ran unit tests.

Reviewers: csilvers, btrahan

Reviewed By: csilvers

CC: aran

Differential Revision: https://secure.phabricator.com/D2459
Minor doc updates

Summary:
Sort all the symbols in libphutil into groups.

Also fix a broken unit test -- under normal PHP, we can't assign $log, or it won't be destructed until the end of the function.

Test Plan: Generated, read documentation.

Reviewers: btrahan, edward, jungejason

Reviewed By: jungejason

CC: aran

Differential Revision: https://secure.phabricator.com/D2462
Add HTTP queries to profiler

Summary:
My primary motivation is to see elasticsearch in DarkConsole.

I'm not sure if this is not too broad.
It will also make sense to add this to HTTPSFuture.
The consequence is that every Conduit call will have at least two entries in profiler. I'm not sure if it isn't too much noice.

Test Plan: Look at DarkConsole after searching with elasticsearch.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin

Differential Revision: https://secure.phabricator.com/D2464
Throw exceptions from Future resolveAll()

Summary: `FutureIterator::resolveAll()` doesn't throw exceptions because `next()` only gets a next future without resolving it.

Test Plan:
  Futures($futures)->resolveAll();

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin, jungejason

Differential Revision: https://secure.phabricator.com/D2480
Allow language guesser to guess diffs correctly

Summary: We can pretty reliably guess when a file is a diff by looking for characteristic diff markers.

Test Plan: Ran unit tests.

Reviewers: btrahan, vrana, jungejason

Reviewed By: jungejason

CC: aran

Differential Revision: https://secure.phabricator.com/D2515
Load all functions when loading a libphutil library

Summary: We can't autoload these, so just load them at startup. This means we don't need to write dependencies for them into __init__.php, which moves us closer to being able to remove __init__.php.

Test Plan: Ran "arc diff", loaded Phabricator.

Reviewers: vrana, btrahan, jungejason

Reviewed By: vrana

CC: aran

Maniphest Tasks: T1103

Differential Revision: https://secure.phabricator.com/D2545
Use gmake instead of make if its available to make it compile on FreeBSD

Summary: Use gmake instead of make if its available

Test Plan: I've tried it on FreeBSD, Ubuntu and CentOS

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, epriestley

Differential Revision: https://secure.phabricator.com/D2546
Add a console highlighter and language guesser

Summary: Pygments has a console highlighter but it doesn't handle path prefixes and doesn't ephasize comments enough. Add a fancier highlighter and a guesser.

Test Plan: {F11792}

Reviewers: btrahan, vrana, jungejason

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D2539
Provide information about wrong value passed to assert_instances_of()

Test Plan:
  assert_instances_of(array(1), 'stdClass');
  assert_instances_of(array(new stdClass), 'C');
  assert_instances_of(array(new stdClass), 'stdClass');

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin

Differential Revision: https://secure.phabricator.com/D2554
Minor, escape console output after parsing so quotes don't trigger the "#" comment rule.
Revert "Load all functions when loading a libphutil library"

Summary:
This reverts commit 3475788eddcace2eb71665a50565d74deaef62e0.

We can't do this without doing more comprehensive changes at the same time. There are two problems:

  - We may load some function which, e.g., does "new X()" in its implementation, triggering an include of a module which defines class X. This class may extend a class in another library which hasn't loaded yet. We could fix this problem by ignoring `phutil_require_module()` during function autoload, but can't fix the next one.
  - We may load some function which is defined in a module which also defines some class X, which extends a class in another library which hasn't loaded yet.

We need to wait to land this to avoid triggering these problems.

Test Plan: Strict revert.

Reviewers: nh, vrana, btrahan

Reviewed By: nh

CC: aran

Maniphest Tasks: T1103

Differential Revision: https://secure.phabricator.com/D2556
Avoid E_NOTICE

Auditors: epriestley
Move Futures() to a separate file

Summary: Also use `assert_instances_of()`.

Test Plan: `arc liberate`

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin

Maniphest Tasks: T1103

Differential Revision: https://secure.phabricator.com/D2563
Create a script for killing __init__.php

Summary:
Maybe we should integrate it in `arc liberate`.
Maybe it should support non-Git repositories.
But this is all I have.

Test Plan: Run it on Arcanist and Diviner.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin

Maniphest Tasks: T1103

Differential Revision: https://secure.phabricator.com/D2566