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(); }