public function execute(PhutilArgumentParser $args)
 {
     $commits = $this->loadCommits($args, 'commits');
     if (!$commits) {
         throw new PhutilArgumentUsageException(pht('Specify one or more commits to resolve users for.'));
     }
     $console = PhutilConsole::getConsole();
     foreach ($commits as $commit) {
         $repo = $commit->getRepository();
         $name = $repo->formatCommitName($commit->getCommitIdentifier());
         $console->writeOut("%s\n", pht('Examining commit %s...', $name));
         $refs_raw = DiffusionQuery::callConduitWithDiffusionRequest($this->getViewer(), DiffusionRequest::newFromDictionary(array('repository' => $repo, 'user' => $this->getViewer())), 'diffusion.querycommits', array('repositoryPHID' => $repo->getPHID(), 'phids' => array($commit->getPHID()), 'bypassCache' => true));
         if (empty($refs_raw['data'])) {
             throw new Exception(pht('Unable to retrieve details for commit "%s"!', $commit->getPHID()));
         }
         $ref = DiffusionCommitRef::newFromConduitResult(head($refs_raw['data']));
         $author = $ref->getAuthor();
         $console->writeOut("%s\n", pht('Raw author string: %s', coalesce($author, 'null')));
         if ($author !== null) {
             $handle = $this->resolveUser($commit, $author);
             if ($handle) {
                 $console->writeOut("%s\n", pht('Phabricator user: %s', $handle->getFullName()));
             } else {
                 $console->writeOut("%s\n", pht('Unable to resolve a corresponding Phabricator user.'));
             }
         }
         $committer = $ref->getCommitter();
         $console->writeOut("%s\n", pht('Raw committer string: %s', coalesce($committer, 'null')));
         if ($committer !== null) {
             $handle = $this->resolveUser($commit, $committer);
             if ($handle) {
                 $console->writeOut("%s\n", pht('Phabricator user: %s', $handle->getFullName()));
             } else {
                 $console->writeOut("%s\n", pht('Unable to resolve a corresponding Phabricator user.'));
             }
         }
     }
     return 0;
 }
 protected final function updateCommitData(DiffusionCommitRef $ref)
 {
     $commit = $this->commit;
     $author = $ref->getAuthor();
     $message = $ref->getMessage();
     $committer = $ref->getCommitter();
     $hashes = $ref->getHashes();
     $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     if (!$data) {
         $data = new PhabricatorRepositoryCommitData();
     }
     $data->setCommitID($commit->getID());
     $data->setAuthorName(id(new PhutilUTF8StringTruncator())->setMaximumBytes(255)->truncateString((string) $author));
     $data->setCommitDetail('authorName', $ref->getAuthorName());
     $data->setCommitDetail('authorEmail', $ref->getAuthorEmail());
     $data->setCommitDetail('authorPHID', $this->resolveUserPHID($commit, $author));
     $data->setCommitMessage($message);
     if (strlen($committer)) {
         $data->setCommitDetail('committer', $committer);
         $data->setCommitDetail('committerName', $ref->getCommitterName());
         $data->setCommitDetail('committerEmail', $ref->getCommitterEmail());
         $data->setCommitDetail('committerPHID', $this->resolveUserPHID($commit, $committer));
     }
     $repository = $this->repository;
     $author_phid = $data->getCommitDetail('authorPHID');
     $committer_phid = $data->getCommitDetail('committerPHID');
     $user = new PhabricatorUser();
     if ($author_phid) {
         $user = $user->loadOneWhere('phid = %s', $author_phid);
     }
     $differential_app = 'PhabricatorDifferentialApplication';
     $revision_id = null;
     $low_level_query = null;
     if (PhabricatorApplication::isClassInstalled($differential_app)) {
         $low_level_query = id(new DiffusionLowLevelCommitFieldsQuery())->setRepository($repository)->withCommitRef($ref);
         $field_values = $low_level_query->execute();
         $revision_id = idx($field_values, 'revisionID');
         if (!empty($field_values['reviewedByPHIDs'])) {
             $data->setCommitDetail('reviewerPHID', reset($field_values['reviewedByPHIDs']));
         }
         $data->setCommitDetail('differential.revisionID', $revision_id);
     }
     if ($author_phid != $commit->getAuthorPHID()) {
         $commit->setAuthorPHID($author_phid);
     }
     $commit->setSummary($data->getSummary());
     $commit->save();
     // Figure out if we're going to try to "autoclose" related objects (e.g.,
     // close linked tasks and related revisions) and, if not, record why we
     // aren't. Autoclose can be disabled for various reasons at the repository
     // or commit levels.
     $force_autoclose = idx($this->getTaskData(), 'forceAutoclose', false);
     if ($force_autoclose) {
         $autoclose_reason = PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED;
     } else {
         $autoclose_reason = $repository->shouldSkipAutocloseCommit($commit);
     }
     $data->setCommitDetail('autocloseReason', $autoclose_reason);
     $should_autoclose = $force_autoclose || $repository->shouldAutocloseCommit($commit);
     // When updating related objects, we'll act under an omnipotent user to
     // ensure we can see them, but take actions as either the committer or
     // author (if we recognize their accounts) or the Diffusion application
     // (if we do not).
     $actor = PhabricatorUser::getOmnipotentUser();
     $acting_as_phid = nonempty($committer_phid, $author_phid, id(new PhabricatorDiffusionApplication())->getPHID());
     $conn_w = id(new DifferentialRevision())->establishConnection('w');
     // NOTE: The `differential_commit` table has a unique ID on `commitPHID`,
     // preventing more than one revision from being associated with a commit.
     // Generally this is good and desirable, but with the advent of hash
     // tracking we may end up in a situation where we match several different
     // revisions. We just kind of ignore this and pick one, we might want to
     // revisit this and do something differently. (If we match several revisions
     // someone probably did something very silly, though.)
     $revision = null;
     if ($revision_id) {
         $revision_query = id(new DifferentialRevisionQuery())->withIDs(array($revision_id))->setViewer($actor)->needReviewerStatus(true)->needActiveDiffs(true);
         $revision = $revision_query->executeOne();
         if ($revision) {
             if (!$data->getCommitDetail('precommitRevisionStatus')) {
                 $data->setCommitDetail('precommitRevisionStatus', $revision->getStatus());
             }
             $commit_drev = DiffusionCommitHasRevisionEdgeType::EDGECONST;
             id(new PhabricatorEdgeEditor())->addEdge($commit->getPHID(), $commit_drev, $revision->getPHID())->save();
             queryfx($conn_w, 'INSERT IGNORE INTO %T (revisionID, commitPHID) VALUES (%d, %s)', DifferentialRevision::TABLE_COMMIT, $revision->getID(), $commit->getPHID());
             $status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
             $should_close = $revision->getStatus() != $status_closed && $should_autoclose;
             if ($should_close) {
                 $commit_close_xaction = id(new DifferentialTransaction())->setTransactionType(DifferentialTransaction::TYPE_ACTION)->setNewValue(DifferentialAction::ACTION_CLOSE)->setMetadataValue('isCommitClose', true);
                 $commit_close_xaction->setMetadataValue('commitPHID', $commit->getPHID());
                 $commit_close_xaction->setMetadataValue('committerPHID', $committer_phid);
                 $commit_close_xaction->setMetadataValue('committerName', $data->getCommitDetail('committer'));
                 $commit_close_xaction->setMetadataValue('authorPHID', $author_phid);
                 $commit_close_xaction->setMetadataValue('authorName', $data->getAuthorName());
                 if ($low_level_query) {
                     $commit_close_xaction->setMetadataValue('revisionMatchData', $low_level_query->getRevisionMatchData());
                     $data->setCommitDetail('revisionMatchData', $low_level_query->getRevisionMatchData());
                 }
                 $diff = $this->generateFinalDiff($revision, $acting_as_phid);
                 $vs_diff = $this->loadChangedByCommit($revision, $diff);
                 $changed_uri = null;
                 if ($vs_diff) {
                     $data->setCommitDetail('vsDiff', $vs_diff->getID());
                     $changed_uri = PhabricatorEnv::getProductionURI('/D' . $revision->getID() . '?vs=' . $vs_diff->getID() . '&id=' . $diff->getID() . '#toc');
                 }
                 $xactions = array();
                 $xactions[] = id(new DifferentialTransaction())->setTransactionType(DifferentialTransaction::TYPE_UPDATE)->setIgnoreOnNoEffect(true)->setNewValue($diff->getPHID())->setMetadataValue('isCommitUpdate', true);
                 $xactions[] = $commit_close_xaction;
                 $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_DAEMON, array());
                 $editor = id(new DifferentialTransactionEditor())->setActor($actor)->setActingAsPHID($acting_as_phid)->setContinueOnMissingFields(true)->setContentSource($content_source)->setChangedPriorToCommitURI($changed_uri)->setIsCloseByCommit(true);
                 try {
                     $editor->applyTransactions($revision, $xactions);
                 } catch (PhabricatorApplicationTransactionNoEffectException $ex) {
                     // NOTE: We've marked transactions other than the CLOSE transaction
                     // as ignored when they don't have an effect, so this means that we
                     // lost a race to close the revision. That's perfectly fine, we can
                     // just continue normally.
                 }
             }
         }
     }
     if ($should_autoclose) {
         $this->closeTasks($actor, $acting_as_phid, $repository, $commit, $message);
     }
     $data->save();
     $commit->writeImportStatusFlag(PhabricatorRepositoryCommit::IMPORTED_MESSAGE);
 }