array( 'help' => "Include committed and abandoned revisions", ), 'by-status' => array( 'help' => 'Group output by revision status.', ), ); } public function run() { $repository_api = $this->getRepositoryAPI(); if (!($repository_api instanceof ArcanistGitAPI)) { throw new ArcanistUsageException( "arc branch is only supported under git." ); } $this->branches = BranchInfo::loadAll($repository_api); $all_revisions = array_unique( array_filter(mpull($this->branches, 'getRevisionId'))); $revision_status = $this->loadDifferentialStatuses($all_revisions); $owner = $repository_api->getRepositoryOwner(); foreach ($this->branches as $branch) { if ($branch->getCommitAuthor() != $owner) { $branch->setStatus('Not Yours'); continue; } $rev_id = $branch->getRevisionID(); if ($rev_id) { $status = idx($revision_status, $rev_id, 'Unknown Status'); $branch->setStatus($status); } else { $branch->setStatus('No Revision'); } } if (!$this->getArgument('view-all')) { $this->filterOutFinished(); } $this->printInColumns(); } /** * Makes a conduit call to differential to find out revision statuses * based on their IDs */ private function loadDifferentialStatuses($rev_ids) { $conduit = $this->getConduit(); $revision_future = $conduit->callMethod( 'differential.find', array( 'guids' => $rev_ids, 'query' => 'revision-ids', )); $revisions = array(); foreach ($revision_future->resolve() as $revision_dict) { $revisions[] = ArcanistDifferentialRevisionRef::newFromDictionary( $revision_dict); } $statuses = mpull($revisions, 'getStatusName', 'getId'); return $statuses; } /** * Removes the branches with status either committed or abandoned. */ private function filterOutFinished() { foreach ($this->branches as $id => $branch) { if ($branch->isCurrentHead() ) { continue; //never filter the current branch } $status = $branch->getStatus(); if ($status == 'Committed' || $status == 'Abandoned') { unset($this->branches[$id]); } } } public function printInColumns() { $longest_name = 0; $longest_status = 0; foreach ($this->branches as $branch) { $longest_name = max(strlen($branch->getFormattedName()), $longest_name); $longest_status = max(strlen($branch->getStatus()), $longest_status); } if ($this->getArgument('by-status')) { $by_status = mgroup($this->branches, 'getStatus'); foreach (array('Accepted', 'Needs Revision', 'Needs Review', 'No Revision') as $status) { $branches = idx($by_status, $status); if (!$branches) { continue; } echo reset($branches)->getFormattedStatus()."\n"; foreach ($branches as $branch) { $name_markdown = $branch->getFormattedName(); $subject = $branch->getCommitDisplayName(); $name_markdown = str_pad($name_markdown, $longest_name + 4, ' '); echo " $name_markdown $subject\n"; } } } else { foreach ($this->branches as $branch) { $name_markdown = $branch->getFormattedName(); $status_markdown = $branch->getFormattedStatus(); $subject = $branch->getCommitDisplayName(); $subject_pad = $longest_status - strlen($branch->getStatus()) + 4; $name_markdown = str_pad($name_markdown, $longest_name + 4, ' '); $subject = str_pad($subject, strlen($subject) + $subject_pad, ' ', STR_PAD_LEFT); echo "$name_markdown $status_markdown $subject\n"; } } } }