protected final function updateCommitData($author, $message)
 {
     $commit = $this->commit;
     $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     if (!$data) {
         $data = new PhabricatorRepositoryCommitData();
     }
     $data->setCommitID($commit->getID());
     $data->setAuthorName($author);
     $data->setCommitMessage($message);
     $repository = $this->repository;
     $detail_parser = $repository->getDetail('detail-parser', 'PhabricatorRepositoryDefaultCommitMessageDetailParser');
     if ($detail_parser) {
         PhutilSymbolLoader::loadClass($detail_parser);
         $parser_obj = newv($detail_parser, array($commit, $data));
         $parser_obj->parseCommitDetails();
     }
     $data->save();
     $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_id = $data->getCommitDetail('differential.revisionID');
     if (!$revision_id) {
         $hashes = $this->getCommitHashes($this->repository, $this->commit);
         if ($hashes) {
             $query = new DifferentialRevisionQuery();
             $query->withCommitHashes($hashes);
             $revisions = $query->execute();
             if (!empty($revisions)) {
                 $revision = $this->identifyBestRevision($revisions);
                 $revision_id = $revision->getID();
             }
         }
     }
     if ($revision_id) {
         $revision = id(new DifferentialRevision())->load($revision_id);
         if ($revision) {
             queryfx($conn_w, 'INSERT IGNORE INTO %T (revisionID, commitPHID) VALUES (%d, %s)', DifferentialRevision::TABLE_COMMIT, $revision->getID(), $commit->getPHID());
             if ($revision->getStatus() != DifferentialRevisionStatus::COMMITTED) {
                 $message = null;
                 $committer = $data->getCommitDetail('authorPHID');
                 if (!$committer) {
                     $committer = $revision->getAuthorPHID();
                     $message = 'Change committed by ' . $data->getAuthorName() . '.';
                 }
                 $editor = new DifferentialCommentEditor($revision, $committer, DifferentialAction::ACTION_COMMIT);
                 $editor->setMessage($message)->save();
             }
         }
     }
 }
 protected final function updateCommitData($author, $message, $committer = null)
 {
     $commit = $this->commit;
     $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     if (!$data) {
         $data = new PhabricatorRepositoryCommitData();
     }
     $data->setCommitID($commit->getID());
     $data->setAuthorName($author);
     $data->setCommitMessage($message);
     if ($committer) {
         $data->setCommitDetail('committer', $committer);
     }
     $repository = $this->repository;
     $detail_parser = $repository->getDetail('detail-parser', 'PhabricatorRepositoryDefaultCommitMessageDetailParser');
     if ($detail_parser) {
         $parser_obj = newv($detail_parser, array($commit, $data));
         $parser_obj->parseCommitDetails();
     }
     $author_phid = $this->lookupUser($commit, $data->getAuthorName(), $data->getCommitDetail('authorPHID'));
     $data->setCommitDetail('authorPHID', $author_phid);
     $committer_phid = $this->lookupUser($commit, $data->getCommitDetail('committer'), $data->getCommitDetail('committerPHID'));
     $data->setCommitDetail('committerPHID', $committer_phid);
     if ($author_phid != $commit->getAuthorPHID()) {
         $commit->setAuthorPHID($author_phid);
         $commit->save();
     }
     $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_id = $data->getCommitDetail('differential.revisionID');
     if (!$revision_id) {
         $hashes = $this->getCommitHashes($this->repository, $this->commit);
         if ($hashes) {
             $query = new DifferentialRevisionQuery();
             $query->withCommitHashes($hashes);
             $revisions = $query->execute();
             if (!empty($revisions)) {
                 $revision = $this->identifyBestRevision($revisions);
                 $revision_id = $revision->getID();
             }
         }
     }
     if ($revision_id) {
         $revision = id(new DifferentialRevision())->load($revision_id);
         if ($revision) {
             queryfx($conn_w, 'INSERT IGNORE INTO %T (revisionID, commitPHID) VALUES (%d, %s)', DifferentialRevision::TABLE_COMMIT, $revision->getID(), $commit->getPHID());
             $committer_phid = $data->getCommitDetail('committerPHID');
             if ($committer_phid) {
                 $handle = PhabricatorObjectHandleData::loadOneHandle($committer_phid);
                 $committer_name = '@' . $handle->getName();
             } else {
                 $committer_name = $data->getCommitDetail('committer');
             }
             $author_phid = $data->getCommitDetail('authorPHID');
             if ($author_phid) {
                 $handle = PhabricatorObjectHandleData::loadOneHandle($author_phid);
                 $author_name = '@' . $handle->getName();
             } else {
                 $author_name = $data->getAuthorName();
             }
             $commit_name = $repository->formatCommitName($commit->getCommitIdentifier());
             $info = array();
             $info[] = "authored by {$author_name}";
             if ($committer_name && $committer_name != $author_name) {
                 $info[] = "committed by {$committer_name}";
             }
             $info = implode(', ', $info);
             $message = "Closed by commit {$commit_name} ({$info}).";
             $actor_phid = nonempty($committer_phid, $author_phid, $revision->getAuthorPHID());
             $status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
             $should_close = $revision->getStatus() != $status_closed && $repository->shouldAutocloseCommit($commit, $data);
             if ($should_close) {
                 $diff = $this->attachToRevision($revision, $actor_phid);
                 $revision->setDateCommitted($commit->getEpoch());
                 $editor = new DifferentialCommentEditor($revision, $actor_phid, DifferentialAction::ACTION_CLOSE);
                 $editor->setIsDaemonWorkflow(true);
                 $vs_diff = $this->loadChangedByCommit($diff);
                 if ($vs_diff) {
                     $data->setCommitDetail('vsDiff', $vs_diff->getID());
                     $changed_by_commit = PhabricatorEnv::getProductionURI('/D' . $revision->getID() . '?vs=' . $vs_diff->getID() . '&id=' . $diff->getID() . '#toc');
                     $editor->setChangedByCommit($changed_by_commit);
                 }
                 $editor->setMessage($message)->save();
             }
         }
     }
     $data->save();
 }
 private function buildRevisionPanel()
 {
     $user = $this->getRequest()->getUser();
     $user_phid = $user->getPHID();
     $revision_query = new DifferentialRevisionQuery();
     $revision_query->withStatus(DifferentialRevisionQuery::STATUS_OPEN);
     $revision_query->withResponsibleUsers(array($user_phid));
     $revision_query->needRelationships(true);
     // NOTE: We need to unlimit this query to hit the responsible user
     // fast-path.
     $revision_query->setLimit(null);
     $revisions = $revision_query->execute();
     list($active, $waiting) = DifferentialRevisionQuery::splitResponsible($revisions, $user_phid);
     if (!$active) {
         return $this->renderMiniPanel('No Waiting Revisions', 'No revisions are waiting on you.');
     }
     $panel = new AphrontPanelView();
     $panel->setHeader('Revisions Waiting on You');
     $panel->setCaption('Revisions waiting for you for review or commit.');
     $panel->addButton(phutil_render_tag('a', array('href' => '/differential/', 'class' => 'button grey'), "View Active Revisions »"));
     $revision_view = id(new DifferentialRevisionListView())->setHighlightAge(true)->setRevisions($active)->setFields(DifferentialRevisionListView::getDefaultFields())->setUser($user)->loadAssets();
     $phids = array_merge(array($user_phid), $revision_view->getRequiredHandlePHIDs());
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $revision_view->setHandles($handles);
     $panel->appendChild($revision_view);
     return $panel;
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $authors = $request->getValue('authors');
     $ccs = $request->getValue('ccs');
     $reviewers = $request->getValue('reviewers');
     $status = $request->getValue('status');
     $order = $request->getValue('order');
     $commit_hashes = $request->getValue('commitHashes');
     $limit = $request->getValue('limit');
     $offset = $request->getValue('offset');
     $ids = $request->getValue('ids');
     $phids = $request->getValue('phids');
     $subscribers = $request->getValue('subscribers');
     $responsible_users = $request->getValue('responsibleUsers');
     $query = new DifferentialRevisionQuery();
     if ($authors) {
         $query->withAuthors($authors);
     }
     if ($ccs) {
         $query->withCCs($ccs);
     }
     if ($reviewers) {
         $query->withReviewers($reviewers);
     }
     /* TODO: Implement.
         $paths     = $request->getValue('paths');
         if ($paths) {
           foreach ($paths as $path) {
     
             // (Lookup the repository IDs.)
     
             $query->withPath($repository_id, $path);
           }
         }
      */
     if ($commit_hashes) {
         $hash_types = DifferentialRevisionHash::getTypes();
         foreach ($commit_hashes as $info) {
             list($type, $hash) = $info;
             if (empty($type) || !in_array($type, $hash_types) || empty($hash)) {
                 throw new ConduitException('ERR-INVALID-PARAMETER');
             }
         }
         $query->withCommitHashes($commit_hashes);
     }
     if ($status) {
         $query->withStatus($status);
     }
     if ($order) {
         $query->setOrder($order);
     }
     if ($limit) {
         $query->setLimit($limit);
     }
     if ($offset) {
         $query->setOffset($offset);
     }
     if ($ids) {
         $query->withIDs($ids);
     }
     if ($phids) {
         $query->withPHIDs($phids);
     }
     if ($responsible_users) {
         $query->withResponsibleUsers($responsible_users);
     }
     if ($subscribers) {
         $query->withSubscribers($subscribers);
     }
     $query->needRelationships(true);
     $query->needCommitPHIDs(true);
     $query->needDiffIDs(true);
     $query->needActiveDiffs(true);
     $revisions = $query->execute();
     $results = array();
     foreach ($revisions as $revision) {
         $diff = $revision->getActiveDiff();
         if (!$diff) {
             continue;
         }
         $id = $revision->getID();
         $results[] = array('id' => $id, 'phid' => $revision->getPHID(), 'title' => $revision->getTitle(), 'uri' => PhabricatorEnv::getProductionURI('/D' . $id), 'dateCreated' => $revision->getDateCreated(), 'dateModified' => $revision->getDateModified(), 'authorPHID' => $revision->getAuthorPHID(), 'status' => $revision->getStatus(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'sourcePath' => $diff->getSourcePath(), 'summary' => $revision->getSummary(), 'testPlan' => $revision->getTestPlan(), 'lineCount' => $revision->getLineCount(), 'diffs' => $revision->getDiffIDs(), 'commits' => $revision->getCommitPHIDs(), 'reviewers' => array_values($revision->getReviewers()), 'ccs' => array_values($revision->getCCPHIDs()));
     }
     return $results;
 }
 protected final function updateCommitData($author, $message, $committer = null)
 {
     $commit = $this->commit;
     $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     if (!$data) {
         $data = new PhabricatorRepositoryCommitData();
     }
     $data->setCommitID($commit->getID());
     $data->setAuthorName($author);
     $data->setCommitMessage($message);
     if ($committer) {
         $data->setCommitDetail('committer', $committer);
     }
     $repository = $this->repository;
     $detail_parser = $repository->getDetail('detail-parser', 'PhabricatorRepositoryDefaultCommitMessageDetailParser');
     if ($detail_parser) {
         $parser_obj = newv($detail_parser, array($commit, $data));
         $parser_obj->parseCommitDetails();
     }
     $author_phid = $this->lookupUser($commit, $data->getAuthorName(), $data->getCommitDetail('authorPHID'));
     $data->setCommitDetail('authorPHID', $author_phid);
     $committer_phid = $this->lookupUser($commit, $data->getCommitDetail('committer'), $data->getCommitDetail('committerPHID'));
     $data->setCommitDetail('committerPHID', $committer_phid);
     if ($author_phid != $commit->getAuthorPHID()) {
         $commit->setAuthorPHID($author_phid);
         $commit->save();
     }
     $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;
     $should_autoclose = $repository->shouldAutocloseCommit($commit, $data);
     $revision_id = $data->getCommitDetail('differential.revisionID');
     if (!$revision_id) {
         $hashes = $this->getCommitHashes($this->repository, $this->commit);
         if ($hashes) {
             $query = new DifferentialRevisionQuery();
             $query->withCommitHashes($hashes);
             $revisions = $query->execute();
             if (!empty($revisions)) {
                 $revision = $this->identifyBestRevision($revisions);
                 $revision_id = $revision->getID();
             }
         }
     }
     if ($revision_id) {
         $lock = PhabricatorGlobalLock::newLock(get_class($this) . ':' . $revision_id);
         $lock->lock(5 * 60);
         $revision = id(new DifferentialRevision())->load($revision_id);
         if ($revision) {
             $revision->loadRelationships();
             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) {
                 $actor_phid = nonempty($committer_phid, $author_phid, $revision->getAuthorPHID());
                 $diff = $this->attachToRevision($revision, $actor_phid);
                 $revision->setDateCommitted($commit->getEpoch());
                 $editor = new DifferentialCommentEditor($revision, $actor_phid, DifferentialAction::ACTION_CLOSE);
                 $editor->setIsDaemonWorkflow(true);
                 $vs_diff = $this->loadChangedByCommit($diff);
                 if ($vs_diff) {
                     $data->setCommitDetail('vsDiff', $vs_diff->getID());
                     $changed_by_commit = PhabricatorEnv::getProductionURI('/D' . $revision->getID() . '?vs=' . $vs_diff->getID() . '&id=' . $diff->getID() . '#toc');
                     $editor->setChangedByCommit($changed_by_commit);
                 }
                 $commit_name = $repository->formatCommitName($commit->getCommitIdentifier());
                 $committer_name = $this->loadUserName($committer_phid, $data->getCommitDetail('committer'));
                 $author_name = $this->loadUserName($author_phid, $data->getAuthorName());
                 $info = array();
                 $info[] = "authored by {$author_name}";
                 if ($committer_name && $committer_name != $author_name) {
                     $info[] = "committed by {$committer_name}";
                 }
                 $info = implode(', ', $info);
                 $editor->setMessage("Closed by commit {$commit_name} ({$info}).")->save();
             }
         }
         $lock->unlock();
     }
     if ($should_autoclose && $author_phid) {
         $user = id(new PhabricatorUser())->loadOneWhere('phid = %s', $author_phid);
         $call = new ConduitCall('differential.parsecommitmessage', array('corpus' => $message, 'partial' => true));
         $call->setUser($user);
         $result = $call->execute();
         $field_values = $result['fields'];
         $fields = DifferentialFieldSelector::newSelector()->getFieldSpecifications();
         foreach ($fields as $key => $field) {
             if (!$field->shouldAppearOnCommitMessage()) {
                 continue;
             }
             $field->setUser($user);
             $value = idx($field_values, $field->getCommitMessageKey());
             $field->setValueFromParsedCommitMessage($value);
             if ($revision) {
                 $field->setRevision($revision);
             }
             $field->didParseCommit($repository, $commit, $data);
         }
     }
     $data->save();
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $authors = $request->getValue('authors');
     $ccs = $request->getValue('ccs');
     $reviewers = $request->getValue('reviewers');
     $status = $request->getValue('status');
     $order = $request->getValue('order');
     $commit_hashes = $request->getValue('commitHashes');
     $limit = $request->getValue('limit');
     $offset = $request->getValue('offset');
     $ids = $request->getValue('ids');
     $phids = $request->getValue('phids');
     $subscribers = $request->getValue('subscribers');
     $responsible_users = $request->getValue('responsibleUsers');
     $branches = $request->getValue('branches');
     $arc_projects = $request->getValue('arcanistProjects');
     $query = new DifferentialRevisionQuery();
     if ($authors) {
         $query->withAuthors($authors);
     }
     if ($ccs) {
         $query->withCCs($ccs);
     }
     if ($reviewers) {
         $query->withReviewers($reviewers);
     }
     /* TODO: Implement.
         $paths     = $request->getValue('paths');
         if ($paths) {
           foreach ($paths as $path) {
     
             // (Lookup the repository IDs.)
     
             $query->withPath($repository_id, $path);
           }
         }
      */
     if ($commit_hashes) {
         $hash_types = ArcanistDifferentialRevisionHash::getTypes();
         foreach ($commit_hashes as $info) {
             list($type, $hash) = $info;
             if (empty($type) || !in_array($type, $hash_types) || empty($hash)) {
                 throw new ConduitException('ERR-INVALID-PARAMETER');
             }
         }
         $query->withCommitHashes($commit_hashes);
     }
     if ($status) {
         $query->withStatus($status);
     }
     if ($order) {
         $query->setOrder($order);
     }
     if ($limit) {
         $query->setLimit($limit);
     }
     if ($offset) {
         $query->setOffset($offset);
     }
     if ($ids) {
         $query->withIDs($ids);
     }
     if ($phids) {
         $query->withPHIDs($phids);
     }
     if ($responsible_users) {
         $query->withResponsibleUsers($responsible_users);
     }
     if ($subscribers) {
         $query->withSubscribers($subscribers);
     }
     if ($branches) {
         $query->withBranches($branches);
     }
     if ($arc_projects) {
         // This is sort of special-cased, but don't make arc do an extra round
         // trip.
         $projects = id(new PhabricatorRepositoryArcanistProject())->loadAllWhere('name in (%Ls)', $arc_projects);
         if (!$projects) {
             return array();
         }
         $query->withArcanistProjectPHIDs(mpull($projects, 'getPHID'));
     }
     $query->needRelationships(true);
     $query->needCommitPHIDs(true);
     $query->needDiffIDs(true);
     $query->needActiveDiffs(true);
     $revisions = $query->execute();
     $results = array();
     foreach ($revisions as $revision) {
         $diff = $revision->getActiveDiff();
         if (!$diff) {
             continue;
         }
         $id = $revision->getID();
         $result = array('id' => $id, 'phid' => $revision->getPHID(), 'title' => $revision->getTitle(), 'uri' => PhabricatorEnv::getProductionURI('/D' . $id), 'dateCreated' => $revision->getDateCreated(), 'dateModified' => $revision->getDateModified(), 'authorPHID' => $revision->getAuthorPHID(), 'status' => $revision->getStatus(), 'statusName' => ArcanistDifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'branch' => $diff->getBranch(), 'summary' => $revision->getSummary(), 'testPlan' => $revision->getTestPlan(), 'lineCount' => $revision->getLineCount(), 'diffs' => $revision->getDiffIDs(), 'commits' => $revision->getCommitPHIDs(), 'reviewers' => array_values($revision->getReviewers()), 'ccs' => array_values($revision->getCCPHIDs()));
         // TODO: This is a hacky way to put permissions on this field until we
         // have first-class support, see T838.
         if ($revision->getAuthorPHID() == $request->getUser()->getPHID()) {
             $result['sourcePath'] = $diff->getSourcePath();
         }
         $results[] = $result;
     }
     return $results;
 }