mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-12 16:46:15 +01:00
8756d82cf6
Summary: I'm pretty sure that `@group` annotations are useless now... see D9855. Also fixed various other minor issues. Test Plan: Eye-ball it. Reviewers: #blessed_reviewers, epriestley, chad Reviewed By: #blessed_reviewers, epriestley Subscribers: epriestley, Korvin, hach-que Differential Revision: https://secure.phabricator.com/D9859
320 lines
8.2 KiB
PHP
320 lines
8.2 KiB
PHP
<?php
|
|
|
|
final class ReleephRequest extends ReleephDAO
|
|
implements
|
|
PhabricatorPolicyInterface,
|
|
PhabricatorCustomFieldInterface {
|
|
|
|
protected $branchID;
|
|
protected $requestUserPHID;
|
|
protected $details = array();
|
|
protected $userIntents = array();
|
|
protected $inBranch;
|
|
protected $pickStatus;
|
|
protected $mailKey;
|
|
|
|
/**
|
|
* The object which is being requested. Normally this is a commit, but it
|
|
* might also be a revision. In the future, it could be a repository branch
|
|
* or an external object (like a GitHub pull request).
|
|
*/
|
|
protected $requestedObjectPHID;
|
|
|
|
// Information about the thing being requested
|
|
protected $requestCommitPHID;
|
|
|
|
// Information about the last commit to the releeph branch
|
|
protected $commitIdentifier;
|
|
protected $commitPHID;
|
|
|
|
|
|
private $customFields = self::ATTACHABLE;
|
|
private $branch = self::ATTACHABLE;
|
|
private $requestedObject = self::ATTACHABLE;
|
|
|
|
|
|
/* -( Constants and helper methods )--------------------------------------- */
|
|
|
|
const INTENT_WANT = 'want';
|
|
const INTENT_PASS = 'pass';
|
|
|
|
const PICK_PENDING = 1; // old
|
|
const PICK_FAILED = 2;
|
|
const PICK_OK = 3;
|
|
const PICK_MANUAL = 4; // old
|
|
const REVERT_OK = 5;
|
|
const REVERT_FAILED = 6;
|
|
|
|
public function shouldBeInBranch() {
|
|
return
|
|
$this->getPusherIntent() == self::INTENT_WANT &&
|
|
/**
|
|
* We use "!= pass" instead of "== want" in case the requestor intent is
|
|
* not present. In other words, only revert if the requestor explicitly
|
|
* passed.
|
|
*/
|
|
$this->getRequestorIntent() != self::INTENT_PASS;
|
|
}
|
|
|
|
/**
|
|
* Will return INTENT_WANT if any pusher wants this request, and no pusher
|
|
* passes on this request.
|
|
*/
|
|
public function getPusherIntent() {
|
|
$product = $this->getBranch()->getProduct();
|
|
|
|
if (!$product->getPushers()) {
|
|
return self::INTENT_WANT;
|
|
}
|
|
|
|
$found_pusher_want = false;
|
|
foreach ($this->userIntents as $phid => $intent) {
|
|
if ($product->isAuthoritativePHID($phid)) {
|
|
if ($intent == self::INTENT_PASS) {
|
|
return self::INTENT_PASS;
|
|
}
|
|
|
|
$found_pusher_want = true;
|
|
}
|
|
}
|
|
|
|
if ($found_pusher_want) {
|
|
return self::INTENT_WANT;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function getRequestorIntent() {
|
|
return idx($this->userIntents, $this->requestUserPHID);
|
|
}
|
|
|
|
public function getStatus() {
|
|
return $this->calculateStatus();
|
|
}
|
|
|
|
public function getMonogram() {
|
|
return 'Y'.$this->getID();
|
|
}
|
|
|
|
public function getBranch() {
|
|
return $this->assertAttached($this->branch);
|
|
}
|
|
|
|
public function attachBranch(ReleephBranch $branch) {
|
|
$this->branch = $branch;
|
|
return $this;
|
|
}
|
|
|
|
public function getRequestedObject() {
|
|
return $this->assertAttached($this->requestedObject);
|
|
}
|
|
|
|
public function attachRequestedObject($object) {
|
|
$this->requestedObject = $object;
|
|
return $this;
|
|
}
|
|
|
|
private function calculateStatus() {
|
|
if ($this->shouldBeInBranch()) {
|
|
if ($this->getInBranch()) {
|
|
return ReleephRequestStatus::STATUS_PICKED;
|
|
} else {
|
|
return ReleephRequestStatus::STATUS_NEEDS_PICK;
|
|
}
|
|
} else {
|
|
if ($this->getInBranch()) {
|
|
return ReleephRequestStatus::STATUS_NEEDS_REVERT;
|
|
} else {
|
|
$has_been_in_branch = $this->getCommitIdentifier();
|
|
// Regardless of why we reverted something, always say reverted if it
|
|
// was once in the branch.
|
|
if ($has_been_in_branch) {
|
|
return ReleephRequestStatus::STATUS_REVERTED;
|
|
} else if ($this->getPusherIntent() === ReleephRequest::INTENT_PASS) {
|
|
// Otherwise, if it has never been in the branch, explicitly say why:
|
|
return ReleephRequestStatus::STATUS_REJECTED;
|
|
} else if ($this->getRequestorIntent() === ReleephRequest::INTENT_WANT) {
|
|
return ReleephRequestStatus::STATUS_REQUESTED;
|
|
} else {
|
|
return ReleephRequestStatus::STATUS_ABANDONED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* -( Lisk mechanics )----------------------------------------------------- */
|
|
|
|
public function getConfiguration() {
|
|
return array(
|
|
self::CONFIG_AUX_PHID => true,
|
|
self::CONFIG_SERIALIZATION => array(
|
|
'details' => self::SERIALIZATION_JSON,
|
|
'userIntents' => self::SERIALIZATION_JSON,
|
|
),
|
|
) + parent::getConfiguration();
|
|
}
|
|
|
|
public function generatePHID() {
|
|
return PhabricatorPHID::generateNewPHID(
|
|
ReleephPHIDTypeRequest::TYPECONST);
|
|
}
|
|
|
|
public function save() {
|
|
if (!$this->getMailKey()) {
|
|
$this->setMailKey(Filesystem::readRandomCharacters(20));
|
|
}
|
|
return parent::save();
|
|
}
|
|
|
|
|
|
/* -( Helpful accessors )--------------------------------------------------- */
|
|
|
|
|
|
public function getDetail($key, $default = null) {
|
|
return idx($this->getDetails(), $key, $default);
|
|
}
|
|
|
|
public function setDetail($key, $value) {
|
|
$this->details[$key] = $value;
|
|
return $this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the commit PHIDs this request is requesting.
|
|
*
|
|
* NOTE: For now, this always returns one PHID.
|
|
*
|
|
* @return list<phid> Commit PHIDs requested by this request.
|
|
*/
|
|
public function getCommitPHIDs() {
|
|
return array(
|
|
$this->requestCommitPHID,
|
|
);
|
|
}
|
|
|
|
public function getReason() {
|
|
// Backward compatibility: reason used to be called comments
|
|
$reason = $this->getDetail('reason');
|
|
if (!$reason) {
|
|
return $this->getDetail('comments');
|
|
}
|
|
return $reason;
|
|
}
|
|
|
|
/**
|
|
* Allow a null summary, and fall back to the title of the commit.
|
|
*/
|
|
public function getSummaryForDisplay() {
|
|
$summary = $this->getDetail('summary');
|
|
|
|
if (!strlen($summary)) {
|
|
$commit = $this->loadPhabricatorRepositoryCommit();
|
|
if ($commit) {
|
|
$summary = $commit->getSummary();
|
|
}
|
|
}
|
|
|
|
if (!strlen($summary)) {
|
|
$summary = pht('None');
|
|
}
|
|
|
|
return $summary;
|
|
}
|
|
|
|
/* -( Loading external objects )------------------------------------------- */
|
|
|
|
public function loadPhabricatorRepositoryCommit() {
|
|
return $this->loadOneRelative(
|
|
new PhabricatorRepositoryCommit(),
|
|
'phid',
|
|
'getRequestCommitPHID');
|
|
}
|
|
|
|
public function loadPhabricatorRepositoryCommitData() {
|
|
$commit = $this->loadPhabricatorRepositoryCommit();
|
|
if ($commit) {
|
|
return $commit->loadOneRelative(
|
|
new PhabricatorRepositoryCommitData(),
|
|
'commitID');
|
|
}
|
|
}
|
|
|
|
|
|
/* -( State change helpers )----------------------------------------------- */
|
|
|
|
public function setUserIntent(PhabricatorUser $user, $intent) {
|
|
$this->userIntents[$user->getPHID()] = $intent;
|
|
return $this;
|
|
}
|
|
|
|
|
|
/* -( Migrating to status-less ReleephRequests )--------------------------- */
|
|
|
|
protected function didReadData() {
|
|
if ($this->userIntents === null) {
|
|
$this->userIntents = array();
|
|
}
|
|
}
|
|
|
|
public function setStatus($value) {
|
|
throw new Exception('`status` is now deprecated!');
|
|
}
|
|
|
|
/* -( Make magic Lisk methods private )------------------------------------ */
|
|
|
|
private function setUserIntents(array $ar) {
|
|
return parent::setUserIntents($ar);
|
|
}
|
|
|
|
|
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
|
|
|
|
|
public function getCapabilities() {
|
|
return array(
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
);
|
|
}
|
|
|
|
public function getPolicy($capability) {
|
|
return $this->getBranch()->getPolicy($capability);
|
|
}
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
return $this->getBranch()->hasAutomaticCapability($capability, $viewer);
|
|
}
|
|
|
|
public function describeAutomaticCapability($capability) {
|
|
return pht(
|
|
'Pull requests have the same policies as the branches they are '.
|
|
'requested against.');
|
|
}
|
|
|
|
|
|
|
|
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
|
|
|
|
|
public function getCustomFieldSpecificationForRole($role) {
|
|
return PhabricatorEnv::getEnvConfig('releeph.fields');
|
|
}
|
|
|
|
public function getCustomFieldBaseClass() {
|
|
return 'ReleephFieldSpecification';
|
|
}
|
|
|
|
public function getCustomFields() {
|
|
return $this->assertAttached($this->customFields);
|
|
}
|
|
|
|
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
|
|
$this->customFields = $fields;
|
|
return $this;
|
|
}
|
|
|
|
|
|
}
|