<commit_before><?php

/**
 * Displays user's Git branches or Mercurial bookmarks
 *
 * @group workflow
 * @concrete-extensible
 */
class ArcanistFeatureWorkflow extends ArcanistBaseWorkflow {

  private $branches;

  public function getWorkflowName() {
    return 'feature';
  }

  public function getCommandSynopses() {
    return phutil_console_format(<<<EOTEXT
      **feature** [__options__]
      **feature** __name__ [__start__]
EOTEXT
      );
  }

  public function getCommandHelp() {
    return phutil_console_format(<<<EOTEXT
          Supports: git, hg
          A wrapper on 'git branch' or 'hg bookmark'. It pulls data from
          Differential and displays the revision status next to the branch name.

          By default, branches are sorted chronologically. You can sort them
          by status instead with __--by-status__.

          By default, branches that are "Closed" or "Abandoned" are not
          displayed. You can show them with __--view-all__.

          With __name__, it creates or checks out a branch. If the branch
          __name__ doesn't exist and is in format D123 then the branch of
          revision D123 is checked out.
EOTEXT
      );
  }

  public function requiresConduit() {
    return true;
  }

  public function requiresRepositoryAPI() {
    return true;
  }

  public function requiresAuthentication() {
    return true;
  }


  public function getArguments() {
    return array(
      'view-all' => array(
        'help' => 'Include closed and abandoned revisions.',
      ),
      'by-status' => array(
        'help' => 'Sort branches by status instead of time.',
      ),
      '*' => 'names',
    );
  }

  public function run() {
    $repository_api = $this->getRepositoryAPI();
    if (!($repository_api instanceof ArcanistGitAPI) &&
        !($repository_api instanceof ArcanistMercurialAPI)) {
      throw new ArcanistUsageException(
        'arc feature is only supported under Git and Mercurial.');
    }

    $names = $this->getArgument('names');
    if ($names) {
      if (count($names) > 2) {
        throw new ArcanistUsageException("Specify only one branch.");
      }
      return $this->checkoutBranch($names);
    }

    $branches = $repository_api->getAllBranches();
    if (!$branches) {
      throw new ArcanistUsageException('No branches in this working copy.');
    }

    $branches = $this->loadCommitInfo($branches);

    $revisions = $this->loadRevisions($branches);

    $this->printBranches($branches, $revisions);

    return 0;
  }

  private function checkoutBranch(array $names) {
    $api = $this->getRepositoryAPI();

    if ($api instanceof ArcanistMercurialAPI) {
      $command = 'update %s';
    } else {
      $command = 'checkout %s';
    }

    $err = 1;

    $branches = $api->getAllBranches();
    if (in_array(reset($names), ipull($branches, 'name'))) {
      list($err, $stdout, $stderr) = $api->execManualLocal(
        $command,
        reset($names));
    }

    if ($err) {
      $match = null;
      if (preg_match('/^D(\d+)$/', reset($names), $match)) {
        try {
          $diff = $this->getConduit()->callMethodSynchronous(
            'differential.getdiff',
            array(
              'revision_id' => $match[1],
            ));

          if ($diff['branch'] != '') {
            $names[0] = $diff['branch'];
            list($err, $stdout, $stderr) = $api->execManualLocal(
              $command,
              reset($names));
          }
        } catch (ConduitException $ex) {
        }
      }
    }

    if ($err) {
      if ($api instanceof ArcanistMercurialAPI) {
        $rev = '';
        if (isset($names[1])) {
          $rev = csprintf('-r %s', $names[1]);
        }

        $exec = $api->execManualLocal(
          'bookmark %C %s',
          $rev,
          $names[0]);

        if (!$exec[0] && isset($names[1])) {
          $api->execxLocal('update %s', $names[0]);
        }
      } else {
        $exec = $api->execManualLocal(
          'checkout -b %Ls',
          $names);<commit_msg>`arc feature` set up git tracking branch<commit_after><?php

/**
 * Displays user's Git branches or Mercurial bookmarks
 *
 * @group workflow
 * @concrete-extensible
 */
class ArcanistFeatureWorkflow extends ArcanistBaseWorkflow {

  private $branches;

  public function getWorkflowName() {
    return 'feature';
  }

  public function getCommandSynopses() {
    return phutil_console_format(<<<EOTEXT
      **feature** [__options__]
      **feature** __name__ [__start__]
EOTEXT
      );
  }

  public function getCommandHelp() {
    return phutil_console_format(<<<EOTEXT
          Supports: git, hg
          A wrapper on 'git branch' or 'hg bookmark'. It pulls data from
          Differential and displays the revision status next to the branch name.

          By default, branches are sorted chronologically. You can sort them
          by status instead with __--by-status__.

          By default, branches that are "Closed" or "Abandoned" are not
          displayed. You can show them with __--view-all__.

          With __name__, it creates or checks out a branch. If the branch
          __name__ doesn't exist and is in format D123 then the branch of
          revision D123 is checked out.
EOTEXT
      );
  }

  public function requiresConduit() {
    return true;
  }

  public function requiresRepositoryAPI() {
    return true;
  }

  public function requiresAuthentication() {
    return true;
  }


  public function getArguments() {
    return array(
      'view-all' => array(
        'help' => 'Include closed and abandoned revisions.',
      ),
      'by-status' => array(
        'help' => 'Sort branches by status instead of time.',
      ),
      '*' => 'names',
    );
  }

  public function run() {
    $repository_api = $this->getRepositoryAPI();
    if (!($repository_api instanceof ArcanistGitAPI) &&
        !($repository_api instanceof ArcanistMercurialAPI)) {
      throw new ArcanistUsageException(
        'arc feature is only supported under Git and Mercurial.');
    }

    $names = $this->getArgument('names');
    if ($names) {
      if (count($names) > 2) {
        throw new ArcanistUsageException("Specify only one branch.");
      }
      return $this->checkoutBranch($names);
    }

    $branches = $repository_api->getAllBranches();
    if (!$branches) {
      throw new ArcanistUsageException('No branches in this working copy.');
    }

    $branches = $this->loadCommitInfo($branches);

    $revisions = $this->loadRevisions($branches);

    $this->printBranches($branches, $revisions);

    return 0;
  }

  private function checkoutBranch(array $names) {
    $api = $this->getRepositoryAPI();

    if ($api instanceof ArcanistMercurialAPI) {
      $command = 'update %s';
    } else {
      $command = 'checkout %s';
    }

    $err = 1;

    $branches = $api->getAllBranches();
    if (in_array(reset($names), ipull($branches, 'name'))) {
      list($err, $stdout, $stderr) = $api->execManualLocal(
        $command,
        reset($names));
    }

    if ($err) {
      $match = null;
      if (preg_match('/^D(\d+)$/', reset($names), $match)) {
        try {
          $diff = $this->getConduit()->callMethodSynchronous(
            'differential.getdiff',
            array(
              'revision_id' => $match[1],
            ));

          if ($diff['branch'] != '') {
            $names[0] = $diff['branch'];
            list($err, $stdout, $stderr) = $api->execManualLocal(
              $command,
              reset($names));
          }
        } catch (ConduitException $ex) {
        }
      }
    }

    if ($err) {
      if ($api instanceof ArcanistMercurialAPI) {
        $rev = '';
        if (isset($names[1])) {
          $rev = csprintf('-r %s', $names[1]);
        }

        $exec = $api->execManualLocal(
          'bookmark %C %s',
          $rev,
          $names[0]);

        if (!$exec[0] && isset($names[1])) {
          $api->execxLocal('update %s', $names[0]);
        }
      } else {
        $exec = $api->execManualLocal(
          'checkout --track -b %Ls',
          $names);
{'fraction_non_alphanumeric': 0.1350784047413261, 'fraction_numerical': 0.004198049141869367, 'mean_word_length': 2.298045602605863, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5437949', 'n_tokens_mistral': 2499, 'n_tokens_neox': 2417, 'n_words': 638}