public static function indexCommit(PhabricatorRepositoryCommit $commit)
 {
     $commit_data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
     $date_created = $commit->getEpoch();
     $commit_message = $commit_data->getCommitMessage();
     $author_phid = $commit_data->getCommitDetail('authorPHID');
     $repository = id(new PhabricatorRepository())->loadOneWhere('id = %d', $commit->getRepositoryID());
     if (!$repository) {
         return;
     }
     $title = 'r' . $repository->getCallsign() . $commit->getCommitIdentifier() . " " . $commit_data->getSummary();
     $doc = new PhabricatorSearchAbstractDocument();
     $doc->setPHID($commit->getPHID());
     $doc->setDocumentType(PhabricatorPHIDConstants::PHID_TYPE_CMIT);
     $doc->setDocumentCreated($date_created);
     $doc->setDocumentModified($date_created);
     $doc->setDocumentTitle($title);
     $doc->addField(PhabricatorSearchField::FIELD_BODY, $commit_message);
     if ($author_phid) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR, $author_phid, PhabricatorPHIDConstants::PHID_TYPE_USER, $date_created);
     }
     $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY, $repository->getPHID(), PhabricatorPHIDConstants::PHID_TYPE_REPO, $date_created);
     $comments = id(new PhabricatorAuditComment())->loadAllWhere('targetPHID = %s', $commit->getPHID());
     foreach ($comments as $comment) {
         if (strlen($comment->getContent())) {
             $doc->addField(PhabricatorSearchField::FIELD_COMMENT, $comment->getContent());
         }
     }
     self::reindexAbstractDocument($doc);
 }
 public function newBranchFromCommit(PhabricatorRepositoryCommit $cut_point, $branch_date, $symbolic_name = null)
 {
     $template = $this->releephProject->getDetail('branchTemplate');
     if (!$template) {
         $template = ReleephBranchTemplate::getRequiredDefaultTemplate();
     }
     $cut_point_handle = id(new PhabricatorHandleQuery())->setViewer($this->requireActor())->withPHIDs(array($cut_point->getPHID()))->executeOne();
     list($name, $errors) = id(new ReleephBranchTemplate())->setCommitHandle($cut_point_handle)->setBranchDate($branch_date)->setReleephProjectName($this->releephProject->getName())->interpolate($template);
     $basename = last(explode('/', $name));
     $table = id(new ReleephBranch());
     $transaction = $table->openTransaction();
     $branch = id(new ReleephBranch())->setName($name)->setBasename($basename)->setReleephProjectID($this->releephProject->getID())->setCreatedByUserPHID($this->requireActor()->getPHID())->setCutPointCommitPHID($cut_point->getPHID())->setIsActive(1)->setDetail('branchDate', $branch_date)->save();
     /**
      * Steal the symbolic name from any other branch that has it (in this
      * project).
      */
     if ($symbolic_name) {
         $others = id(new ReleephBranch())->loadAllWhere('releephProjectID = %d', $this->releephProject->getID());
         foreach ($others as $other) {
             if ($other->getSymbolicName() == $symbolic_name) {
                 $other->setSymbolicName(null)->save();
             }
         }
         $branch->setSymbolicName($symbolic_name)->save();
     }
     $table->saveTransaction();
     return $branch;
 }
 public function didParseCommit(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data)
 {
     $user = id(new PhabricatorUser())->loadOneWhere('phid = %s', $data->getCommitDetail('authorPHID'));
     if (!$user) {
         return;
     }
     $prefixes = array('resolves' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 'fixes' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 'wontfix' => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, 'wontfixes' => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, 'spite' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 'spites' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 'invalidate' => ManiphestTaskStatus::STATUS_CLOSED_INVALID, 'invaldiates' => ManiphestTaskStatus::STATUS_CLOSED_INVALID, 'close' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 'closes' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 'ref' => null, 'refs' => null, 'references' => null, 'cf.' => null);
     $suffixes = array('as resolved' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 'as fixed' => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, 'as wontfix' => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, 'as spite' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 'out of spite' => ManiphestTaskStatus::STATUS_CLOSED_SPITE, 'as invalid' => ManiphestTaskStatus::STATUS_CLOSED_INVALID, '' => null);
     $prefix_regex = array();
     foreach ($prefixes as $prefix => $resolution) {
         $prefix_regex[] = preg_quote($prefix, '/');
     }
     $prefix_regex = implode('|', $prefix_regex);
     $suffix_regex = array();
     foreach ($suffixes as $suffix => $resolution) {
         $suffix_regex[] = preg_quote($suffix, '/');
     }
     $suffix_regex = implode('|', $suffix_regex);
     $matches = null;
     $ok = preg_match_all("/({$prefix_regex})\\s+T(\\d+)\\s*({$suffix_regex})/i", $this->renderValueForCommitMessage($is_edit = false), $matches, PREG_SET_ORDER);
     if (!$ok) {
         return;
     }
     foreach ($matches as $set) {
         $prefix = strtolower($set[1]);
         $task_id = (int) $set[2];
         $suffix = strtolower($set[3]);
         $status = idx($suffixes, $suffix);
         if (!$status) {
             $status = idx($prefixes, $prefix);
         }
         $tasks = id(new ManiphestTaskQuery())->withTaskIDs(array($task_id))->execute();
         $task = idx($tasks, $task_id);
         if (!$task) {
             // Task doesn't exist, or the user can't see it.
             continue;
         }
         id(new PhabricatorEdgeEditor())->setUser($user)->addEdge($task->getPHID(), PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT, $commit->getPHID())->save();
         if (!$status) {
             // Text like "Ref T123", don't change the task status.
             continue;
         }
         if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) {
             // Task is already closed.
             continue;
         }
         $commit_name = $repository->formatCommitName($commit->getCommitIdentifier());
         $call = new ConduitCall('maniphest.update', array('id' => $task->getID(), 'status' => $status, 'comments' => "Closed by commit {$commit_name}."));
         $call->setUser($user);
         $call->execute();
     }
 }
 private function loadCommitProperties(PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data, array $parents, array $audit_requests)
 {
     assert_instances_of($parents, 'PhabricatorRepositoryCommit');
     $viewer = $this->getRequest()->getUser();
     $commit_phid = $commit->getPHID();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $edge_query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($commit_phid))->withEdgeTypes(array(DiffusionCommitHasTaskEdgeType::EDGECONST, DiffusionCommitHasRevisionEdgeType::EDGECONST, DiffusionCommitRevertsCommitEdgeType::EDGECONST, DiffusionCommitRevertedByCommitEdgeType::EDGECONST));
     $edges = $edge_query->execute();
     $task_phids = array_keys($edges[$commit_phid][DiffusionCommitHasTaskEdgeType::EDGECONST]);
     $revision_phid = key($edges[$commit_phid][DiffusionCommitHasRevisionEdgeType::EDGECONST]);
     $reverts_phids = array_keys($edges[$commit_phid][DiffusionCommitRevertsCommitEdgeType::EDGECONST]);
     $reverted_by_phids = array_keys($edges[$commit_phid][DiffusionCommitRevertedByCommitEdgeType::EDGECONST]);
     $phids = $edge_query->getDestinationPHIDs(array($commit_phid));
     if ($data->getCommitDetail('authorPHID')) {
         $phids[] = $data->getCommitDetail('authorPHID');
     }
     if ($data->getCommitDetail('reviewerPHID')) {
         $phids[] = $data->getCommitDetail('reviewerPHID');
     }
     if ($data->getCommitDetail('committerPHID')) {
         $phids[] = $data->getCommitDetail('committerPHID');
     }
     if ($parents) {
         foreach ($parents as $parent) {
             $phids[] = $parent->getPHID();
         }
     }
     // NOTE: We should never normally have more than a single push log, but
     // it can occur naturally if a commit is pushed, then the branch it was
     // on is deleted, then the commit is pushed again (or through other similar
     // chains of events). This should be rare, but does not indicate a bug
     // or data issue.
     // NOTE: We never query push logs in SVN because the commiter is always
     // the pusher and the commit time is always the push time; the push log
     // is redundant and we save a query by skipping it.
     $push_logs = array();
     if ($repository->isHosted() && !$repository->isSVN()) {
         $push_logs = id(new PhabricatorRepositoryPushLogQuery())->setViewer($viewer)->withRepositoryPHIDs(array($repository->getPHID()))->withNewRefs(array($commit->getCommitIdentifier()))->withRefTypes(array(PhabricatorRepositoryPushLog::REFTYPE_COMMIT))->execute();
         foreach ($push_logs as $log) {
             $phids[] = $log->getPusherPHID();
         }
     }
     $handles = array();
     if ($phids) {
         $handles = $this->loadViewerHandles($phids);
     }
     $props = array();
     if ($commit->getAuditStatus()) {
         $status = PhabricatorAuditCommitStatusConstants::getStatusName($commit->getAuditStatus());
         $tag = id(new PHUITagView())->setType(PHUITagView::TYPE_STATE)->setName($status);
         switch ($commit->getAuditStatus()) {
             case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
                 $tag->setBackgroundColor(PHUITagView::COLOR_ORANGE);
                 break;
             case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
                 $tag->setBackgroundColor(PHUITagView::COLOR_RED);
                 break;
             case PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED:
                 $tag->setBackgroundColor(PHUITagView::COLOR_BLUE);
                 break;
             case PhabricatorAuditCommitStatusConstants::FULLY_AUDITED:
                 $tag->setBackgroundColor(PHUITagView::COLOR_GREEN);
                 break;
         }
         $props['Status'] = $tag;
     }
     if ($audit_requests) {
         $user_requests = array();
         $other_requests = array();
         foreach ($audit_requests as $audit_request) {
             if ($audit_request->isUser()) {
                 $user_requests[] = $audit_request;
             } else {
                 $other_requests[] = $audit_request;
             }
         }
         if ($user_requests) {
             $props['Auditors'] = $this->renderAuditStatusView($user_requests);
         }
         if ($other_requests) {
             $props['Project/Package Auditors'] = $this->renderAuditStatusView($other_requests);
         }
     }
     $author_phid = $data->getCommitDetail('authorPHID');
     $author_name = $data->getAuthorName();
     if (!$repository->isSVN()) {
         $authored_info = id(new PHUIStatusItemView());
         // TODO: In Git, a distinct authorship date is available. When present,
         // we should show it here.
         if ($author_phid) {
             $authored_info->setTarget($handles[$author_phid]->renderLink());
         } else {
             if (strlen($author_name)) {
                 $authored_info->setTarget($author_name);
             }
         }
         $props['Authored'] = id(new PHUIStatusListView())->addItem($authored_info);
     }
     $committed_info = id(new PHUIStatusItemView())->setNote(phabricator_datetime($commit->getEpoch(), $viewer));
     $committer_phid = $data->getCommitDetail('committerPHID');
     $committer_name = $data->getCommitDetail('committer');
     if ($committer_phid) {
         $committed_info->setTarget($handles[$committer_phid]->renderLink());
     } else {
         if (strlen($committer_name)) {
             $committed_info->setTarget($committer_name);
         } else {
             if ($author_phid) {
                 $committed_info->setTarget($handles[$author_phid]->renderLink());
             } else {
                 if (strlen($author_name)) {
                     $committed_info->setTarget($author_name);
                 }
             }
         }
     }
     $props['Committed'] = id(new PHUIStatusListView())->addItem($committed_info);
     if ($push_logs) {
         $pushed_list = new PHUIStatusListView();
         foreach ($push_logs as $push_log) {
             $pushed_item = id(new PHUIStatusItemView())->setTarget($handles[$push_log->getPusherPHID()]->renderLink())->setNote(phabricator_datetime($push_log->getEpoch(), $viewer));
             $pushed_list->addItem($pushed_item);
         }
         $props['Pushed'] = $pushed_list;
     }
     $reviewer_phid = $data->getCommitDetail('reviewerPHID');
     if ($reviewer_phid) {
         $props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
     }
     if ($revision_phid) {
         $props['Differential Revision'] = $handles[$revision_phid]->renderLink();
     }
     if ($parents) {
         $parent_links = array();
         foreach ($parents as $parent) {
             $parent_links[] = $handles[$parent->getPHID()]->renderLink();
         }
         $props['Parents'] = phutil_implode_html(" · ", $parent_links);
     }
     $props['Branches'] = phutil_tag('span', array('id' => 'commit-branches'), pht('Unknown'));
     $props['Tags'] = phutil_tag('span', array('id' => 'commit-tags'), pht('Unknown'));
     $callsign = $repository->getCallsign();
     $root = '/diffusion/' . $callsign . '/commit/' . $commit->getCommitIdentifier();
     Javelin::initBehavior('diffusion-commit-branches', array($root . '/branches/' => 'commit-branches', $root . '/tags/' => 'commit-tags'));
     $refs = $this->buildRefs($drequest);
     if ($refs) {
         $props['References'] = $refs;
     }
     if ($reverts_phids) {
         $props[pht('Reverts')] = $viewer->renderHandleList($reverts_phids);
     }
     if ($reverted_by_phids) {
         $props[pht('Reverted By')] = $viewer->renderHandleList($reverted_by_phids);
     }
     if ($task_phids) {
         $task_list = array();
         foreach ($task_phids as $phid) {
             $task_list[] = $handles[$phid]->renderLink();
         }
         $task_list = phutil_implode_html(phutil_tag('br'), $task_list);
         $props['Tasks'] = $task_list;
     }
     return $props;
 }
 public static function getMailThreading(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit)
 {
     return array('diffusion-audit-' . $commit->getPHID(), 'Commit r' . $repository->getCallsign() . $commit->getCommitIdentifier());
 }
    public function parseCommit(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit)
    {
        if ($repository->getDetail('herald-disabled')) {
            return;
        }
        $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere('commitID = %d', $commit->getID());
        $rules = HeraldRule::loadAllByContentTypeWithFullData(HeraldContentTypeConfig::CONTENT_TYPE_COMMIT);
        $adapter = new HeraldCommitAdapter($repository, $commit, $data);
        $engine = new HeraldEngine();
        $effects = $engine->applyRules($rules, $adapter);
        $engine->applyEffects($effects, $adapter);
        $email_phids = $adapter->getEmailPHIDs();
        if (!$email_phids) {
            return;
        }
        $xscript = $engine->getTranscript();
        $commit_name = $adapter->getHeraldName();
        $revision = $adapter->loadDifferentialRevision();
        $name = null;
        if ($revision) {
            $name = ' ' . $revision->getTitle();
        }
        $author_phid = $data->getCommitDetail('authorPHID');
        $reviewer_phid = $data->getCommitDetail('reviewerPHID');
        $phids = array_filter(array($author_phid, $reviewer_phid));
        $handles = array();
        if ($phids) {
            $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
        }
        if ($author_phid) {
            $author_name = $handles[$author_phid]->getName();
        } else {
            $author_name = $data->getAuthorName();
        }
        if ($reviewer_phid) {
            $reviewer_name = $handles[$reviewer_phid]->getName();
        } else {
            $reviewer_name = null;
        }
        $who = implode(', ', array_filter(array($author_name, $reviewer_name)));
        $description = $data->getCommitMessage();
        $details = PhabricatorEnv::getProductionURI('/' . $commit_name);
        $differential = $revision ? PhabricatorEnv::getProductionURI('/D' . $revision->getID()) : 'No revision.';
        $files = $adapter->loadAffectedPaths();
        sort($files);
        $files = implode("\n  ", $files);
        $xscript_id = $xscript->getID();
        $manage_uri = PhabricatorEnv::getProductionURI('/herald/view/commits/');
        $why_uri = PhabricatorEnv::getProductionURI('/herald/transcript/' . $xscript_id . '/');
        $body = <<<EOBODY
DESCRIPTION
{$description}

DETAILS
  {$details}

DIFFERENTIAL REVISION
  {$differential}

AFFECTED FILES
  {$files}

MANAGE HERALD COMMIT RULES
  {$manage_uri}

WHY DID I GET THIS EMAIL?
  {$why_uri}

EOBODY;
        $subject = "[Herald/Commit] {$commit_name} ({$who}){$name}";
        $mailer = new PhabricatorMetaMTAMail();
        $mailer->setRelatedPHID($commit->getPHID());
        $mailer->addTos($email_phids);
        $mailer->setSubject($subject);
        $mailer->setBody($body);
        $mailer->addHeader('X-Herald-Rules', $xscript->getXHeraldRulesHeader());
        if ($author_phid) {
            $mailer->setFrom($author_phid);
        }
        $mailer->saveAndSend();
    }
 private function renderHeadsupActionList(PhabricatorRepositoryCommit $commit)
 {
     $user = $this->getRequest()->getUser();
     $actions = array();
     require_celerity_resource('phabricator-flag-css');
     $flag = PhabricatorFlagQuery::loadUserFlag($user, $commit->getPHID());
     if ($flag) {
         $class = PhabricatorFlagColor::getCSSClass($flag->getColor());
         $color = PhabricatorFlagColor::getColorName($flag->getColor());
         $action = new AphrontHeadsupActionView();
         $action->setClass('flag-clear ' . $class);
         $action->setURI('/flag/delete/' . $flag->getID() . '/');
         $action->setName('Remove ' . $color . ' Flag');
         $action->setWorkflow(true);
         $actions[] = $action;
     } else {
         $action = new AphrontHeadsupActionView();
         $action->setClass('phabricator-flag-ghost');
         $action->setURI('/flag/edit/' . $commit->getPHID() . '/');
         $action->setName('Flag Commit');
         $action->setWorkflow(true);
         $actions[] = $action;
     }
     require_celerity_resource('phabricator-object-selector-css');
     require_celerity_resource('javelin-behavior-phabricator-object-selector');
     $action = new AphrontHeadsupActionView();
     $action->setName('Edit Maniphest Tasks');
     $action->setURI('/search/attach/' . $commit->getPHID() . '/TASK/edge/');
     $action->setWorkflow(true);
     $action->setClass('attach-maniphest');
     $actions[] = $action;
     if ($user->getIsAdmin()) {
         $action = new AphrontHeadsupActionView();
         $action->setName('MetaMTA Transcripts');
         $action->setURI('/mail/?phid=' . $commit->getPHID());
         $action->setClass('transcripts-metamta');
         $actions[] = $action;
     }
     $action = new AphrontHeadsupActionView();
     $action->setName('Herald Transcripts');
     $action->setURI('/herald/transcript/?phid=' . $commit->getPHID());
     $action->setClass('transcripts-herald');
     $actions[] = $action;
     $action_list = new AphrontHeadsupActionListView();
     $action_list->setActions($actions);
     return $action_list;
 }
 private function closeTasks(PhabricatorUser $actor, $acting_as, PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, $message)
 {
     $maniphest = 'PhabricatorManiphestApplication';
     if (!PhabricatorApplication::isClassInstalled($maniphest)) {
         return;
     }
     $prefixes = ManiphestTaskStatus::getStatusPrefixMap();
     $suffixes = ManiphestTaskStatus::getStatusSuffixMap();
     $matches = id(new ManiphestCustomFieldStatusParser())->parseCorpus($message);
     $task_statuses = array();
     foreach ($matches as $match) {
         $prefix = phutil_utf8_strtolower($match['prefix']);
         $suffix = phutil_utf8_strtolower($match['suffix']);
         $status = idx($suffixes, $suffix);
         if (!$status) {
             $status = idx($prefixes, $prefix);
         }
         foreach ($match['monograms'] as $task_monogram) {
             $task_id = (int) trim($task_monogram, 'tT');
             $task_statuses[$task_id] = $status;
         }
     }
     if (!$task_statuses) {
         return;
     }
     $tasks = id(new ManiphestTaskQuery())->setViewer($actor)->withIDs(array_keys($task_statuses))->needProjectPHIDs(true)->execute();
     foreach ($tasks as $task_id => $task) {
         $xactions = array();
         $edge_type = ManiphestTaskHasCommitEdgeType::EDGECONST;
         $edge_xaction = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_type)->setNewValue(array('+' => array($commit->getPHID() => $commit->getPHID())));
         $status = $task_statuses[$task_id];
         if ($status) {
             if ($task->getStatus() != $status) {
                 $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_STATUS)->setMetadataValue('commitPHID', $commit->getPHID())->setNewValue($status);
                 $edge_xaction->setMetadataValue('commitPHID', $commit->getPHID());
             }
         }
         $xactions[] = $edge_xaction;
         $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_DAEMON, array());
         $editor = id(new ManiphestTransactionEditor())->setActor($actor)->setActingAsPHID($acting_as)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setUnmentionablePHIDMap(array($commit->getPHID() => $commit->getPHID()))->setContentSource($content_source);
         $editor->applyTransactions($task, $xactions);
     }
 }
 private function buildComments(PhabricatorRepositoryCommit $commit)
 {
     $viewer = $this->getRequest()->getUser();
     $xactions = id(new PhabricatorAuditTransactionQuery())->setViewer($viewer)->withObjectPHIDs(array($commit->getPHID()))->needComments(true)->execute();
     $path_ids = array();
     foreach ($xactions as $xaction) {
         if ($xaction->hasComment()) {
             $path_id = $xaction->getComment()->getPathID();
             if ($path_id) {
                 $path_ids[] = $path_id;
             }
         }
     }
     $path_map = array();
     if ($path_ids) {
         $path_map = id(new DiffusionPathQuery())->withPathIDs($path_ids)->execute();
         $path_map = ipull($path_map, 'path', 'id');
     }
     return id(new PhabricatorAuditTransactionView())->setUser($viewer)->setObjectPHID($commit->getPHID())->setPathMap($path_map)->setTransactions($xactions);
 }
 private function publishFeedStory(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data)
 {
     if (time() > $commit->getEpoch() + 24 * 60 * 60) {
         // Don't publish stories that are more than 24 hours old, to avoid
         // ridiculous levels of feed spam if a repository is imported without
         // disabling feed publishing.
         return;
     }
     $author_phid = $commit->getAuthorPHID();
     $committer_phid = $data->getCommitDetail('committerPHID');
     $publisher = new PhabricatorFeedStoryPublisher();
     $publisher->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_COMMIT);
     $publisher->setStoryData(array('commitPHID' => $commit->getPHID(), 'summary' => $data->getSummary(), 'authorName' => $data->getAuthorName(), 'authorPHID' => $author_phid, 'committerName' => $data->getCommitDetail('committer'), 'committerPHID' => $committer_phid));
     $publisher->setStoryTime($commit->getEpoch());
     $publisher->setRelatedPHIDs(array_filter(array($author_phid, $committer_phid)));
     if ($author_phid) {
         $publisher->setStoryAuthorPHID($author_phid);
     }
     $publisher->publish();
 }
 private function renderHeadsupActionList(PhabricatorRepositoryCommit $commit, PhabricatorRepository $repository)
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $actions = array();
     // TODO -- integrate permissions into whether or not this action is shown
     $uri = '/diffusion/' . $repository->getCallSign() . '/commit/' . $commit->getCommitIdentifier() . '/edit/';
     $action = new AphrontHeadsupActionView();
     $action->setClass('action-edit');
     $action->setURI($uri);
     $action->setName('Edit Commit');
     $action->setWorkflow(false);
     $actions[] = $action;
     require_celerity_resource('phabricator-flag-css');
     $flag = PhabricatorFlagQuery::loadUserFlag($user, $commit->getPHID());
     if ($flag) {
         $class = PhabricatorFlagColor::getCSSClass($flag->getColor());
         $color = PhabricatorFlagColor::getColorName($flag->getColor());
         $action = new AphrontHeadsupActionView();
         $action->setClass('flag-clear ' . $class);
         $action->setURI('/flag/delete/' . $flag->getID() . '/');
         $action->setName('Remove ' . $color . ' Flag');
         $action->setWorkflow(true);
         $actions[] = $action;
     } else {
         $action = new AphrontHeadsupActionView();
         $action->setClass('phabricator-flag-ghost');
         $action->setURI('/flag/edit/' . $commit->getPHID() . '/');
         $action->setName('Flag Commit');
         $action->setWorkflow(true);
         $actions[] = $action;
     }
     require_celerity_resource('phabricator-object-selector-css');
     require_celerity_resource('javelin-behavior-phabricator-object-selector');
     $action = new AphrontHeadsupActionView();
     $action->setName('Edit Maniphest Tasks');
     $action->setURI('/search/attach/' . $commit->getPHID() . '/TASK/edge/');
     $action->setWorkflow(true);
     $action->setClass('attach-maniphest');
     $actions[] = $action;
     if ($user->getIsAdmin()) {
         $action = new AphrontHeadsupActionView();
         $action->setName('MetaMTA Transcripts');
         $action->setURI('/mail/?phid=' . $commit->getPHID());
         $action->setClass('transcripts-metamta');
         $actions[] = $action;
     }
     $action = new AphrontHeadsupActionView();
     $action->setName('Herald Transcripts');
     $action->setURI('/herald/transcript/?phid=' . $commit->getPHID());
     $action->setClass('transcripts-herald');
     $actions[] = $action;
     $action = new AphrontHeadsupActionView();
     $action->setName('Download Raw Diff');
     $action->setURI($request->getRequestURI()->alter('diff', true));
     $action->setClass('action-download');
     $actions[] = $action;
     $action_list = new AphrontHeadsupActionListView();
     $action_list->setActions($actions);
     return $action_list;
 }
 private function buildPropertyListView(PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data, array $audit_requests)
 {
     $viewer = $this->getViewer();
     $commit_phid = $commit->getPHID();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $view = id(new PHUIPropertyListView())->setUser($this->getRequest()->getUser());
     $edge_query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($commit_phid))->withEdgeTypes(array(DiffusionCommitHasTaskEdgeType::EDGECONST, DiffusionCommitHasRevisionEdgeType::EDGECONST, DiffusionCommitRevertsCommitEdgeType::EDGECONST, DiffusionCommitRevertedByCommitEdgeType::EDGECONST));
     $edges = $edge_query->execute();
     $task_phids = array_keys($edges[$commit_phid][DiffusionCommitHasTaskEdgeType::EDGECONST]);
     $revision_phid = key($edges[$commit_phid][DiffusionCommitHasRevisionEdgeType::EDGECONST]);
     $reverts_phids = array_keys($edges[$commit_phid][DiffusionCommitRevertsCommitEdgeType::EDGECONST]);
     $reverted_by_phids = array_keys($edges[$commit_phid][DiffusionCommitRevertedByCommitEdgeType::EDGECONST]);
     $phids = $edge_query->getDestinationPHIDs(array($commit_phid));
     if ($data->getCommitDetail('authorPHID')) {
         $phids[] = $data->getCommitDetail('authorPHID');
     }
     if ($data->getCommitDetail('reviewerPHID')) {
         $phids[] = $data->getCommitDetail('reviewerPHID');
     }
     if ($data->getCommitDetail('committerPHID')) {
         $phids[] = $data->getCommitDetail('committerPHID');
     }
     // NOTE: We should never normally have more than a single push log, but
     // it can occur naturally if a commit is pushed, then the branch it was
     // on is deleted, then the commit is pushed again (or through other similar
     // chains of events). This should be rare, but does not indicate a bug
     // or data issue.
     // NOTE: We never query push logs in SVN because the commiter is always
     // the pusher and the commit time is always the push time; the push log
     // is redundant and we save a query by skipping it.
     $push_logs = array();
     if ($repository->isHosted() && !$repository->isSVN()) {
         $push_logs = id(new PhabricatorRepositoryPushLogQuery())->setViewer($viewer)->withRepositoryPHIDs(array($repository->getPHID()))->withNewRefs(array($commit->getCommitIdentifier()))->withRefTypes(array(PhabricatorRepositoryPushLog::REFTYPE_COMMIT))->execute();
         foreach ($push_logs as $log) {
             $phids[] = $log->getPusherPHID();
         }
     }
     $handles = array();
     if ($phids) {
         $handles = $this->loadViewerHandles($phids);
     }
     $props = array();
     if ($audit_requests) {
         $user_requests = array();
         $other_requests = array();
         foreach ($audit_requests as $audit_request) {
             if (!$audit_request->isInteresting()) {
                 continue;
             }
             if ($audit_request->isUser()) {
                 $user_requests[] = $audit_request;
             } else {
                 $other_requests[] = $audit_request;
             }
         }
         if ($user_requests) {
             $view->addProperty(pht('Auditors'), $this->renderAuditStatusView($user_requests));
         }
         if ($other_requests) {
             $view->addProperty(pht('Group Auditors'), $this->renderAuditStatusView($other_requests));
         }
     }
     $author_phid = $data->getCommitDetail('authorPHID');
     $author_name = $data->getAuthorName();
     $author_epoch = $data->getCommitDetail('authorEpoch');
     $committed_info = id(new PHUIStatusItemView())->setNote(phabricator_datetime($commit->getEpoch(), $viewer));
     $committer_phid = $data->getCommitDetail('committerPHID');
     $committer_name = $data->getCommitDetail('committer');
     if ($committer_phid) {
         $committed_info->setTarget($handles[$committer_phid]->renderLink());
     } else {
         if (strlen($committer_name)) {
             $committed_info->setTarget($committer_name);
         } else {
             if ($author_phid) {
                 $committed_info->setTarget($handles[$author_phid]->renderLink());
             } else {
                 if (strlen($author_name)) {
                     $committed_info->setTarget($author_name);
                 }
             }
         }
     }
     $committed_list = new PHUIStatusListView();
     $committed_list->addItem($committed_info);
     $view->addProperty(pht('Committed'), $committed_list);
     if ($push_logs) {
         $pushed_list = new PHUIStatusListView();
         foreach ($push_logs as $push_log) {
             $pushed_item = id(new PHUIStatusItemView())->setTarget($handles[$push_log->getPusherPHID()]->renderLink())->setNote(phabricator_datetime($push_log->getEpoch(), $viewer));
             $pushed_list->addItem($pushed_item);
         }
         $view->addProperty(pht('Pushed'), $pushed_list);
     }
     $reviewer_phid = $data->getCommitDetail('reviewerPHID');
     if ($reviewer_phid) {
         $view->addProperty(pht('Reviewer'), $handles[$reviewer_phid]->renderLink());
     }
     if ($revision_phid) {
         $view->addProperty(pht('Differential Revision'), $handles[$revision_phid]->renderLink());
     }
     $parents = $this->getCommitParents();
     if ($parents) {
         $view->addProperty(pht('Parents'), $viewer->renderHandleList(mpull($parents, 'getPHID')));
     }
     if ($this->getCommitExists()) {
         $view->addProperty(pht('Branches'), phutil_tag('span', array('id' => 'commit-branches'), pht('Unknown')));
         $view->addProperty(pht('Tags'), phutil_tag('span', array('id' => 'commit-tags'), pht('Unknown')));
         $identifier = $commit->getCommitIdentifier();
         $root = $repository->getPathURI("commit/{$identifier}");
         Javelin::initBehavior('diffusion-commit-branches', array($root . '/branches/' => 'commit-branches', $root . '/tags/' => 'commit-tags'));
     }
     $refs = $this->getCommitRefs();
     if ($refs) {
         $ref_links = array();
         foreach ($refs as $ref_data) {
             $ref_links[] = phutil_tag('a', array('href' => $ref_data['href']), $ref_data['ref']);
         }
         $view->addProperty(pht('References'), phutil_implode_html(', ', $ref_links));
     }
     if ($reverts_phids) {
         $view->addProperty(pht('Reverts'), $viewer->renderHandleList($reverts_phids));
     }
     if ($reverted_by_phids) {
         $view->addProperty(pht('Reverted By'), $viewer->renderHandleList($reverted_by_phids));
     }
     if ($task_phids) {
         $task_list = array();
         foreach ($task_phids as $phid) {
             $task_list[] = $handles[$phid]->renderLink();
         }
         $task_list = phutil_implode_html(phutil_tag('br'), $task_list);
         $view->addProperty(pht('Tasks'), $task_list);
     }
     return $view;
 }
 public static function getMailThreading(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit)
 {
     return array('diffusion-audit-' . $commit->getPHID(), pht('Commit %s', $commit->getMonogram()));
 }
 /**
  * Find audit requests in the "Auditors" field if it is present and trigger
  * explicit audit requests.
  */
 private function createAuditsFromCommitMessage(PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data)
 {
     $message = $data->getCommitMessage();
     $matches = null;
     if (!preg_match('/^Auditors:\\s*(.*)$/im', $message, $matches)) {
         return;
     }
     $phids = DifferentialFieldSpecification::parseCommitMessageObjectList($matches[1], $include_mailables = false, $allow_partial = true);
     if (!$phids) {
         return;
     }
     $requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere('commitPHID = %s', $commit->getPHID());
     $requests = mpull($requests, null, 'getAuditorPHID');
     foreach ($phids as $phid) {
         if (isset($requests[$phid])) {
             continue;
         }
         $request = new PhabricatorRepositoryAuditRequest();
         $request->setCommitPHID($commit->getPHID());
         $request->setAuditorPHID($phid);
         $request->setAuditStatus(PhabricatorAuditStatusConstants::AUDIT_REQUESTED);
         $request->setAuditReasons(array('Requested by Author'));
         $request->save();
         $requests[$phid] = $request;
     }
     $commit->updateAuditStatus($requests);
     $commit->save();
 }