protected function readValueFromRevision(DifferentialRevision $revision) { if (!$revision->getPHID()) { return array(); } return PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), DifferentialRevisionHasTaskEdgeType::EDGECONST); }
protected function readValueFromRevision(DifferentialRevision $revision) { if (!$revision->getPHID()) { return array(); } return PhabricatorSubscribersQuery::loadSubscribersForPHID($revision->getPHID()); }
protected function readValueFromRevision(DifferentialRevision $revision) { if (!$revision->getPHID()) { return array(); } $projects = PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $projects = array_reverse($projects); return $projects; }
public static function indexRevision(DifferentialRevision $rev) { $doc = new PhabricatorSearchAbstractDocument(); $doc->setPHID($rev->getPHID()); $doc->setDocumentType(PhabricatorPHIDConstants::PHID_TYPE_DREV); $doc->setDocumentTitle($rev->getTitle()); $doc->setDocumentCreated($rev->getDateCreated()); $doc->setDocumentModified($rev->getDateModified()); $doc->addField(PhabricatorSearchField::FIELD_BODY, $rev->getSummary()); $doc->addField(PhabricatorSearchField::FIELD_TEST_PLAN, $rev->getTestPlan()); $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated()); if ($rev->getStatus() != ArcanistDifferentialRevisionStatus::CLOSED && $rev->getStatus() != ArcanistDifferentialRevisionStatus::ABANDONED) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OPEN, $rev->getPHID(), PhabricatorPHIDConstants::PHID_TYPE_DREV, time()); } $comments = id(new DifferentialComment())->loadAllWhere('revisionID = %d', $rev->getID()); $inlines = id(new DifferentialInlineComment())->loadAllWhere('revisionID = %d AND commentID IS NOT NULL', $rev->getID()); $touches = array(); foreach (array_merge($comments, $inlines) as $comment) { if (strlen($comment->getContent())) { $doc->addField(PhabricatorSearchField::FIELD_COMMENT, $comment->getContent()); } $author = $comment->getAuthorPHID(); $touches[$author] = $comment->getDateCreated(); } foreach ($touches as $touch => $time) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_TOUCH, $touch, PhabricatorPHIDConstants::PHID_TYPE_USER, $time); } $rev->loadRelationships(); // If a revision needs review, the owners are the reviewers. Otherwise, the // owner is the author (e.g., accepted, rejected, closed). if ($rev->getStatus() == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) { foreach ($rev->getReviewers() as $phid) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $phid, PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateModified()); // Bogus timestamp. } } else { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated()); } $ccphids = $rev->getCCPHIDs(); $handles = id(new PhabricatorObjectHandleData($ccphids))->loadHandles(); foreach ($handles as $phid => $handle) { $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_SUBSCRIBER, $phid, $handle->getType(), $rev->getDateModified()); // Bogus timestamp. } self::reindexAbstractDocument($doc); }
public static function loadFromStorage(DifferentialRevision $revision, array $aux_fields) { $storage_keys = array_filter(mpull($aux_fields, 'getStorageKey')); $field_data = array(); if ($storage_keys) { $field_data = id(new DifferentialAuxiliaryField())->loadAllWhere('revisionPHID = %s AND name IN (%Ls)', $revision->getPHID(), $storage_keys); $field_data = mpull($field_data, 'getValue', 'getName'); } foreach ($aux_fields as $aux_field) { $aux_field->setRevision($revision); $key = $aux_field->getStorageKey(); if ($key) { $aux_field->setValueFromStorage(idx($field_data, $key)); } } return $aux_fields; }
public static function loadUnsubmittedInlineComments(PhabricatorUser $viewer, DifferentialRevision $revision) { // TODO: This probably needs to move somewhere more central as we move // away from DifferentialInlineCommentQuery, but // PhabricatorApplicationTransactionCommentQuery is currently `final` and // I'm not yet decided on how to approach that. For now, just get the PHIDs // and then execute a PHID-based query through the standard stack. $table = new DifferentialTransactionComment(); $conn_r = $table->establishConnection('r'); $phids = queryfx_all($conn_r, 'SELECT phid FROM %T WHERE revisionPHID = %s AND authorPHID = %s AND transactionPHID IS NULL', $table->getTableName(), $revision->getPHID(), $viewer->getPHID()); $phids = ipull($phids, 'phid'); if (!$phids) { return array(); } return id(new PhabricatorApplicationTransactionCommentQuery())->setTemplate(new DifferentialTransactionComment())->setViewer($viewer)->withPHIDs($phids)->execute(); }
/** * Note this code is somewhat similar to the buildPatch method in * @{class:DifferentialReviewRequestMail}. * * @return @{class:AphrontRedirectResponse} */ private function buildRawDiffResponse(DifferentialRevision $revision, array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null) { assert_instances_of($changesets, 'DifferentialChangeset'); assert_instances_of($vs_changesets, 'DifferentialChangeset'); $viewer = $this->getRequest()->getUser(); id(new DifferentialHunkQuery())->setViewer($viewer)->withChangesets($changesets)->needAttachToChangesets(true)->execute(); $diff = new DifferentialDiff(); $diff->attachChangesets($changesets); $raw_changes = $diff->buildChangesList(); $changes = array(); foreach ($raw_changes as $changedict) { $changes[] = ArcanistDiffChange::newFromDictionary($changedict); } $loader = id(new PhabricatorFileBundleLoader())->setViewer($viewer); $bundle = ArcanistBundle::newFromChanges($changes); $bundle->setLoadFileDataCallback(array($loader, 'loadFileData')); $vcs = $repository ? $repository->getVersionControlSystem() : null; switch ($vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $raw_diff = $bundle->toGitPatch(); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: default: $raw_diff = $bundle->toUnifiedDiff(); break; } $request_uri = $this->getRequest()->getRequestURI(); // this ends up being something like // D123.diff // or the verbose // D123.vs123.id123.whitespaceignore-all.diff // lame but nice to include these options $file_name = ltrim($request_uri->getPath(), '/') . '.'; foreach ($request_uri->getQueryParams() as $key => $value) { if ($key == 'download') { continue; } $file_name .= $key . $value . '.'; } $file_name .= 'diff'; $file = PhabricatorFile::buildFromFileDataOrHash($raw_diff, array('name' => $file_name, 'ttl' => 60 * 60 * 24, 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE)); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $file->attachToObject($revision->getPHID()); unset($unguarded); return $file->getRedirectResponse(); }
private function buildOperationsBox(DifferentialRevision $revision) { $viewer = $this->getViewer(); // Save a query if we can't possibly have pending operations. $repository = $revision->getRepository(); if (!$repository || !$repository->canPerformAutomation()) { return null; } $operations = id(new DrydockRepositoryOperationQuery())->setViewer($viewer)->withObjectPHIDs(array($revision->getPHID()))->withOperationStates(array(DrydockRepositoryOperation::STATE_WAIT, DrydockRepositoryOperation::STATE_WORK, DrydockRepositoryOperation::STATE_FAIL))->execute(); if (!$operations) { return null; } $operation = head(msort($operations, 'getID')); $box_view = id(new PHUIObjectBoxView())->setHeaderText(pht('Active Operations')); return id(new DrydockRepositoryOperationStatusView())->setUser($viewer)->setBoxView($box_view)->setOperation($operation); }
private function buildTransactions(DifferentialRevision $revision, DifferentialDiff $left_diff, DifferentialDiff $right_diff, array $changesets) { $viewer = $this->getRequest()->getUser(); $xactions = id(new DifferentialTransactionQuery())->setViewer($viewer)->withObjectPHIDs(array($revision->getPHID()))->needComments(true)->execute(); $timeline = id(new DifferentialTransactionView())->setUser($viewer)->setObjectPHID($revision->getPHID())->setChangesets($changesets)->setRevision($revision)->setLeftDiff($left_diff)->setRightDiff($right_diff)->setTransactions($xactions); return $timeline; }
private function buildOperationsBox(DifferentialRevision $revision) { $viewer = $this->getViewer(); // Save a query if we can't possibly have pending operations. $repository = $revision->getRepository(); if (!$repository || !$repository->canPerformAutomation()) { return null; } $operations = id(new DrydockRepositoryOperationQuery())->setViewer($viewer)->withObjectPHIDs(array($revision->getPHID()))->withIsDismissed(false)->withOperationTypes(array(DrydockLandRepositoryOperation::OPCONST))->execute(); if (!$operations) { return null; } $state_fail = DrydockRepositoryOperation::STATE_FAIL; // We're going to show the oldest operation which hasn't failed, or the // most recent failure if they're all failures. $operations = msort($operations, 'getID'); foreach ($operations as $operation) { if ($operation->getOperationState() != $state_fail) { break; } } // If we found a completed operation, don't render anything. We don't want // to show an older error after the thing worked properly. if ($operation->isDone()) { return null; } $box_view = id(new PHUIObjectBoxView())->setHeaderText(pht('Active Operations')); return id(new DrydockRepositoryOperationStatusView())->setUser($viewer)->setBoxView($box_view)->setOperation($operation); }
public function getBarrierToLanding(PhabricatorUser $viewer, DifferentialRevision $revision) { $repository = $revision->getRepository(); if (!$repository) { return array('title' => pht('No Repository'), 'body' => pht('This revision is not associated with a known repository. Only ' . 'revisions associated with a tracked repository can be landed ' . 'automatically.')); } if (!$repository->canPerformAutomation()) { return array('title' => pht('No Repository Automation'), 'body' => pht('The repository this revision is associated with ("%s") is not ' . 'configured to support automation. Configure automation for the ' . 'repository to enable revisions to be landed automatically.', $repository->getMonogram())); } // TODO: At some point we should allow installs to give "land reviewed // code" permission to more users than "push any commit", because it is // a much less powerful operation. For now, just require push so this // doesn't do anything users can't do on their own. $can_push = PhabricatorPolicyFilter::hasCapability($viewer, $repository, DiffusionPushCapability::CAPABILITY); if (!$can_push) { return array('title' => pht('Unable to Push'), 'body' => pht('You do not have permission to push to the repository this ' . 'revision is associated with ("%s"), so you can not land it.', $repository->getMonogram())); } $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; if ($revision->getStatus() != $status_accepted) { switch ($revision->getStatus()) { case ArcanistDifferentialRevisionStatus::CLOSED: return array('title' => pht('Revision Closed'), 'body' => pht('This revision has already been closed. Only open, accepted ' . 'revisions may land.')); case ArcanistDifferentialRevisionStatus::ABANDONED: return array('title' => pht('Revision Abandoned'), 'body' => pht('This revision has been abandoned. Only accepted revisions ' . 'may land.')); default: return array('title' => pht('Revision Not Accepted'), 'body' => pht('This revision is still under review. Only revisions which ' . 'have been accepted may land.')); } } // Check for other operations. Eventually this should probably be more // general (e.g., it's OK to land to multiple different branches // simultaneously) but just put this in as a sanity check for now. $other_operations = id(new DrydockRepositoryOperationQuery())->setViewer($viewer)->withObjectPHIDs(array($revision->getPHID()))->withOperationTypes(array($this->getOperationConstant()))->withOperationStates(array(DrydockRepositoryOperation::STATE_WAIT, DrydockRepositoryOperation::STATE_WORK, DrydockRepositoryOperation::STATE_DONE))->execute(); if ($other_operations) { $any_done = false; foreach ($other_operations as $operation) { if ($operation->isDone()) { $any_done = true; break; } } if ($any_done) { return array('title' => pht('Already Complete'), 'body' => pht('This revision has already landed.')); } else { return array('title' => pht('Already In Flight'), 'body' => pht('This revision is already landing.')); } } return null; }
private function getRevisionActions(DifferentialRevision $revision) { $user = $this->getRequest()->getUser(); $viewer_phid = $user->getPHID(); $viewer_is_owner = $revision->getAuthorPHID() == $viewer_phid; $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers()); $viewer_is_cc = in_array($viewer_phid, $revision->getCCPHIDs()); $viewer_is_anonymous = !$this->getRequest()->getUser()->isLoggedIn(); $status = $revision->getStatus(); $revision_id = $revision->getID(); $revision_phid = $revision->getPHID(); $links = array(); if ($viewer_is_owner) { $links[] = array('class' => 'revision-edit', 'href' => "/differential/revision/edit/{$revision_id}/", 'name' => 'Edit Revision'); } if (!$viewer_is_anonymous) { require_celerity_resource('phabricator-flag-css'); $flag = PhabricatorFlagQuery::loadUserFlag($user, $revision_phid); if ($flag) { $class = PhabricatorFlagColor::getCSSClass($flag->getColor()); $color = PhabricatorFlagColor::getColorName($flag->getColor()); $links[] = array('class' => 'flag-clear ' . $class, 'href' => '/flag/delete/' . $flag->getID() . '/', 'name' => phutil_escape_html('Remove ' . $color . ' Flag'), 'sigil' => 'workflow'); } else { $links[] = array('class' => 'flag-add phabricator-flag-ghost', 'href' => '/flag/edit/' . $revision_phid . '/', 'name' => 'Flag Revision', 'sigil' => 'workflow'); } if (!$viewer_is_owner && !$viewer_is_reviewer) { $action = $viewer_is_cc ? 'rem' : 'add'; $links[] = array('class' => $viewer_is_cc ? 'subscribe-rem' : 'subscribe-add', 'href' => "/differential/subscribe/{$action}/{$revision_id}/", 'name' => $viewer_is_cc ? 'Unsubscribe' : 'Subscribe', 'instant' => true); } else { $links[] = array('class' => 'subscribe-rem unavailable', 'name' => 'Automatically Subscribed'); } require_celerity_resource('phabricator-object-selector-css'); require_celerity_resource('javelin-behavior-phabricator-object-selector'); $links[] = array('class' => 'action-dependencies', 'name' => 'Edit Dependencies', 'href' => "/search/attach/{$revision_phid}/DREV/dependencies/", 'sigil' => 'workflow'); if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) { $links[] = array('class' => 'attach-maniphest', 'name' => 'Edit Maniphest Tasks', 'href' => "/search/attach/{$revision_phid}/TASK/", 'sigil' => 'workflow'); } if ($user->getIsAdmin()) { $links[] = array('class' => 'transcripts-metamta', 'name' => 'MetaMTA Transcripts', 'href' => "/mail/?phid={$revision_phid}"); } $links[] = array('class' => 'transcripts-herald', 'name' => 'Herald Transcripts', 'href' => "/herald/transcript/?phid={$revision_phid}"); } $request_uri = $this->getRequest()->getRequestURI(); $links[] = array('class' => 'action-download', 'name' => 'Download Raw Diff', 'href' => $request_uri->alter('download', 'true')); return $links; }
public static function loadUnsubmittedInlineComments(PhabricatorUser $viewer, DifferentialRevision $revision) { return id(new DifferentialDiffInlineCommentQuery())->setViewer($viewer)->withRevisionPHIDs(array($revision->getPHID()))->withAuthorPHIDs(array($viewer->getPHID()))->withHasTransaction(false)->withIsDeleted(false)->needReplyToComments(true)->execute(); }
public function setRevision(DifferentialRevision $revision) { $this->proxy->setRevisionPHID($revision->getPHID()); return $this; }
private function getRevisionActions(DifferentialRevision $revision) { $viewer_phid = $this->getRequest()->getUser()->getPHID(); $viewer_is_owner = $revision->getAuthorPHID() == $viewer_phid; $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers()); $viewer_is_cc = in_array($viewer_phid, $revision->getCCPHIDs()); $viewer_is_anonymous = !$this->getRequest()->getUser()->isLoggedIn(); $status = $revision->getStatus(); $revision_id = $revision->getID(); $revision_phid = $revision->getPHID(); $links = array(); if ($viewer_is_owner) { $links[] = array('class' => 'revision-edit', 'href' => "/differential/revision/edit/{$revision_id}/", 'name' => 'Edit Revision'); } if (!$viewer_is_anonymous) { if (!$viewer_is_owner && !$viewer_is_reviewer) { $action = $viewer_is_cc ? 'rem' : 'add'; $links[] = array('class' => $viewer_is_cc ? 'subscribe-rem' : 'subscribe-add', 'href' => "/differential/subscribe/{$action}/{$revision_id}/", 'name' => $viewer_is_cc ? 'Unsubscribe' : 'Subscribe', 'instant' => true); } else { $links[] = array('class' => 'subscribe-rem unavailable', 'name' => 'Automatically Subscribed'); } require_celerity_resource('phabricator-object-selector-css'); require_celerity_resource('javelin-behavior-phabricator-object-selector'); $links[] = array('class' => 'action-dependencies', 'name' => 'Edit Dependencies', 'href' => "/search/attach/{$revision_phid}/DREV/dependencies/", 'sigil' => 'workflow'); if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) { $links[] = array('class' => 'attach-maniphest', 'name' => 'Edit Maniphest Tasks', 'href' => "/search/attach/{$revision_phid}/TASK/", 'sigil' => 'workflow'); } $links[] = array('class' => 'transcripts-metamta', 'name' => 'MetaMTA Transcripts', 'href' => "/mail/?phid={$revision_phid}"); $links[] = array('class' => 'transcripts-herald', 'name' => 'Herald Transcripts', 'href' => "/herald/transcript/?phid={$revision_phid}"); } return $links; }
private function buildOperationsBox(DifferentialRevision $revision) { $viewer = $this->getViewer(); // Save a query if we can't possibly have pending operations. $repository = $revision->getRepository(); if (!$repository || !$repository->canPerformAutomation()) { return null; } $operations = id(new DrydockRepositoryOperationQuery())->setViewer($viewer)->withObjectPHIDs(array($revision->getPHID()))->withOperationStates(array(DrydockRepositoryOperation::STATE_WAIT, DrydockRepositoryOperation::STATE_WORK, DrydockRepositoryOperation::STATE_FAIL))->execute(); if (!$operations) { return null; } $operation = head(msort($operations, 'getID')); // TODO: This is completely made up for now, give it useful information and // a sweet progress bar. switch ($operation->getOperationState()) { case DrydockRepositoryOperation::STATE_WAIT: case DrydockRepositoryOperation::STATE_WORK: $severity = PHUIInfoView::SEVERITY_NOTICE; $text = pht('Some sort of repository operation is currently running.'); break; default: $severity = PHUIInfoView::SEVERITY_ERROR; $text = pht('Some sort of repository operation failed.'); break; } $info_view = id(new PHUIInfoView())->setSeverity($severity)->appendChild($text); return id(new PHUIObjectBoxView())->setHeaderText(pht('Active Operations (EXPERIMENTAL!)'))->setInfoView($info_view); }