Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/diffusion/controller/DiffusionBlameController.php b/src/applications/diffusion/controller/DiffusionBlameController.php
index 85ab393ef6..42cabbc0d9 100644
--- a/src/applications/diffusion/controller/DiffusionBlameController.php
+++ b/src/applications/diffusion/controller/DiffusionBlameController.php
@@ -1,286 +1,284 @@
<?php
final class DiffusionBlameController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$response = $this->loadDiffusionContext();
if ($response) {
return $response;
}
$viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$blame = $this->loadBlame();
$identifiers = array_fuse($blame);
if ($identifiers) {
$commits = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withRepository($repository)
->withIdentifiers($identifiers)
+ ->needIdentities(true)
->execute();
$commits = mpull($commits, null, 'getCommitIdentifier');
} else {
$commits = array();
}
$commit_map = mpull($commits, 'getCommitIdentifier', 'getPHID');
$revisions = array();
$revision_map = array();
if ($commits) {
$revision_ids = id(new DifferentialRevision())
->loadIDsByCommitPHIDs(array_keys($commit_map));
if ($revision_ids) {
$revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->withIDs($revision_ids)
->execute();
$revisions = mpull($revisions, null, 'getID');
}
foreach ($revision_ids as $commit_phid => $revision_id) {
// If the viewer can't actually see this revision, skip it.
if (!isset($revisions[$revision_id])) {
continue;
}
$revision_map[$commit_map[$commit_phid]] = $revision_id;
}
}
$base_href = (string)$drequest->generateURI(
array(
'action' => 'browse',
'stable' => true,
));
$skip_text = pht('Skip Past This Commit');
$skip_icon = id(new PHUIIconView())
->setIcon('fa-backward');
Javelin::initBehavior('phabricator-tooltips');
$handle_phids = array();
foreach ($commits as $commit) {
- $author_phid = $commit->getAuthorPHID();
- if ($author_phid) {
- $handle_phids[] = $author_phid;
- }
+ $handle_phids[] = $commit->getAuthorDisplayPHID();
}
foreach ($revisions as $revision) {
$handle_phids[] = $revision->getAuthorPHID();
}
$handles = $viewer->loadHandles($handle_phids);
$map = array();
$epochs = array();
foreach ($identifiers as $identifier) {
$revision_id = idx($revision_map, $identifier);
if ($revision_id) {
$revision = idx($revisions, $revision_id);
} else {
$revision = null;
}
$skip_href = $base_href.'?before='.$identifier;
$skip_link = javelin_tag(
'a',
array(
'href' => $skip_href,
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $skip_text,
'align' => 'E',
'size' => 300,
),
),
$skip_icon);
// We may not have a commit object for a given identifier if the commit
// has not imported yet.
// At time of writing, this can also happen if a line was part of the
// initial import: blame produces a "^abc123" identifier in Git, which
// doesn't correspond to a real commit.
$commit = idx($commits, $identifier);
$author_phid = null;
if ($commit) {
- $author_phid = $commit->getAuthorPHID();
+ $author_phid = $commit->getAuthorDisplayPHID();
}
if (!$author_phid && $revision) {
$author_phid = $revision->getAuthorPHID();
}
if (!$author_phid) {
// This means we couldn't identify an author for the commit or the
// revision. We just render a blank for alignment.
$author_style = null;
$author_href = null;
$author_sigil = null;
$author_meta = null;
} else {
$author_src = $handles[$author_phid]->getImageURI();
$author_style = 'background-image: url('.$author_src.');';
$author_href = $handles[$author_phid]->getURI();
$author_sigil = 'has-tooltip';
$author_meta = array(
'tip' => $handles[$author_phid]->getName(),
'align' => 'E',
);
}
$author_link = javelin_tag(
$author_href ? 'a' : 'span',
array(
'class' => 'phabricator-source-blame-author',
'style' => $author_style,
'href' => $author_href,
'sigil' => $author_sigil,
'meta' => $author_meta,
));
if ($commit) {
$commit_link = javelin_tag(
'a',
array(
'href' => $commit->getURI(),
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $this->renderCommitTooltip($commit, $handles),
'align' => 'E',
'size' => 600,
),
),
$commit->getLocalName());
} else {
$commit_link = null;
}
$info = array(
$author_link,
$commit_link,
);
if ($revision) {
$revision_link = javelin_tag(
'a',
array(
'href' => $revision->getURI(),
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $this->renderRevisionTooltip($revision, $handles),
'align' => 'E',
'size' => 600,
),
),
$revision->getMonogram());
$info = array(
$info,
" \xC2\xB7 ",
$revision_link,
);
}
if ($commit) {
$epoch = $commit->getEpoch();
} else {
$epoch = 0;
}
$epochs[] = $epoch;
$data = array(
'skip' => $skip_link,
'info' => hsprintf('%s', $info),
'epoch' => $epoch,
);
$map[$identifier] = $data;
}
$epoch_min = min($epochs);
$epoch_max = max($epochs);
return id(new AphrontAjaxResponse())->setContent(
array(
'blame' => $blame,
'map' => $map,
'epoch' => array(
'min' => $epoch_min,
'max' => $epoch_max,
),
));
}
private function loadBlame() {
$drequest = $this->getDiffusionRequest();
$commit = $drequest->getCommit();
$path = $drequest->getPath();
$blame_timeout = 15;
$blame = $this->callConduitWithDiffusionRequest(
'diffusion.blame',
array(
'commit' => $commit,
'paths' => array($path),
'timeout' => $blame_timeout,
));
return idx($blame, $path, array());
}
private function renderRevisionTooltip(
DifferentialRevision $revision,
$handles) {
$viewer = $this->getViewer();
$date = phabricator_date($revision->getDateModified(), $viewer);
$monogram = $revision->getMonogram();
$title = $revision->getTitle();
$header = "{$monogram} {$title}";
$author = $handles[$revision->getAuthorPHID()]->getName();
return "{$header}\n{$date} \xC2\xB7 {$author}";
}
private function renderCommitTooltip(
PhabricatorRepositoryCommit $commit,
$handles) {
$viewer = $this->getViewer();
$date = phabricator_date($commit->getEpoch(), $viewer);
$summary = trim($commit->getSummary());
$author_phid = $commit->getAuthorPHID();
if ($author_phid && isset($handles[$author_phid])) {
$author_name = $handles[$author_phid]->getName();
} else {
$author_name = null;
}
if ($author_name) {
return "{$summary}\n{$date} \xC2\xB7 {$author_name}";
} else {
return "{$summary}\n{$date}";
}
}
}
diff --git a/src/applications/diffusion/controller/DiffusionLastModifiedController.php b/src/applications/diffusion/controller/DiffusionLastModifiedController.php
index 945f8a58b5..1a31d3a2ba 100644
--- a/src/applications/diffusion/controller/DiffusionLastModifiedController.php
+++ b/src/applications/diffusion/controller/DiffusionLastModifiedController.php
@@ -1,173 +1,156 @@
<?php
final class DiffusionLastModifiedController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$response = $this->loadDiffusionContext();
if ($response) {
return $response;
}
$viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$paths = $request->getStr('paths');
try {
$paths = phutil_json_decode($paths);
} catch (PhutilJSONParserException $ex) {
return new Aphront400Response();
}
$modified_map = $this->callConduitWithDiffusionRequest(
'diffusion.lastmodifiedquery',
array(
'paths' => array_fill_keys($paths, $drequest->getCommit()),
));
if ($modified_map) {
$commit_map = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withRepository($drequest->getRepository())
->withIdentifiers(array_values($modified_map))
->needCommitData(true)
+ ->needIdentities(true)
->execute();
$commit_map = mpull($commit_map, null, 'getCommitIdentifier');
} else {
$commit_map = array();
}
$commits = array();
foreach ($paths as $path) {
$modified_at = idx($modified_map, $path);
if ($modified_at) {
$commit = idx($commit_map, $modified_at);
if ($commit) {
$commits[$path] = $commit;
}
}
}
$phids = array();
foreach ($commits as $commit) {
- $data = $commit->getCommitData();
- $phids[] = $data->getCommitDetail('authorPHID');
- $phids[] = $data->getCommitDetail('committerPHID');
+ $phids[] = $commit->getCommitterDisplayPHID();
+ $phids[] = $commit->getAuthorDisplayPHID();
}
$phids = array_filter($phids);
$handles = $this->loadViewerHandles($phids);
$branch = $drequest->loadBranch();
if ($branch && $commits) {
$lint_query = id(new DiffusionLintCountQuery())
->withBranchIDs(array($branch->getID()))
->withPaths(array_keys($commits));
if ($drequest->getLint()) {
$lint_query->withCodes(array($drequest->getLint()));
}
$lint = $lint_query->execute();
} else {
$lint = array();
}
$output = array();
foreach ($commits as $path => $commit) {
$prequest = clone $drequest;
$prequest->setPath($path);
$output[$path] = $this->renderColumns(
$prequest,
$handles,
$commit,
idx($lint, $path));
}
return id(new AphrontAjaxResponse())->setContent($output);
}
private function renderColumns(
DiffusionRequest $drequest,
array $handles,
PhabricatorRepositoryCommit $commit = null,
$lint = null) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$viewer = $this->getRequest()->getUser();
if ($commit) {
$epoch = $commit->getEpoch();
$modified = DiffusionView::linkCommit(
$drequest->getRepository(),
$commit->getCommitIdentifier());
$date = $viewer->formatShortDateTime($epoch);
} else {
$modified = '';
$date = '';
}
- $data = $commit->getCommitData();
- if ($data) {
- $author_phid = $data->getCommitDetail('authorPHID');
- if ($author_phid && isset($handles[$author_phid])) {
- $author = $handles[$author_phid]->renderLink();
- } else {
- $author = DiffusionView::renderName($data->getAuthorName());
- }
-
- $committer = $data->getCommitDetail('committer');
- if ($committer) {
- $committer_phid = $data->getCommitDetail('committerPHID');
- if ($committer_phid && isset($handles[$committer_phid])) {
- $committer = $handles[$committer_phid]->renderLink();
- } else {
- $committer = DiffusionView::renderName($committer);
- }
- if ($author != $committer) {
- $author = hsprintf('%s/%s', $author, $committer);
- }
- }
+ $author = $commit->renderAuthor($viewer, $handles);
+ $committer = $commit->renderCommitter($viewer, $handles);
- $details = DiffusionView::linkDetail(
- $drequest->getRepository(),
- $commit->getCommitIdentifier(),
- $data->getSummary());
- $details = AphrontTableView::renderSingleDisplayLine($details);
- } else {
- $author = '';
- $details = '';
+ if ($author != $committer) {
+ $author = hsprintf('%s/%s', $author, $committer);
}
+ $data = $commit->getCommitData();
+ $details = DiffusionView::linkDetail(
+ $drequest->getRepository(),
+ $commit->getCommitIdentifier(),
+ $data->getSummary());
+ $details = AphrontTableView::renderSingleDisplayLine($details);
+
+
$return = array(
'commit' => $modified,
'date' => $date,
'author' => $author,
'details' => $details,
);
if ($lint !== null) {
$return['lint'] = phutil_tag(
'a',
array(
'href' => $drequest->generateURI(array(
'action' => 'lint',
'lint' => null,
)),
),
number_format($lint));
}
// The client treats these results as markup, so make sure they have been
// escaped correctly.
foreach ($return as $key => $value) {
$return[$key] = hsprintf('%s', $value);
}
return $return;
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
index 5bb4d5b907..5d9b06e0a3 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
@@ -1,45 +1,46 @@
<?php
final class PhabricatorRepositoryIdentityPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'RIDT';
public function getTypeName() {
return pht('Repository Identity');
}
public function newObject() {
return new PhabricatorRepositoryIdentity();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryIdentityQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$identity = $objects[$phid];
$id = $identity->getID();
$name = $identity->getIdentityNameRaw();
$handle->setObjectName(pht('Identity %d', $id));
$handle->setName($name);
$handle->setURI($identity->getURI());
+ $handle->setIcon('fa-user');
}
}
}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
index bf3b796a76..4cb9def346 100644
--- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -1,842 +1,842 @@
<?php
final class PhabricatorRepositoryCommit
extends PhabricatorRepositoryDAO
implements
PhabricatorPolicyInterface,
PhabricatorFlaggableInterface,
PhabricatorProjectInterface,
PhabricatorTokenReceiverInterface,
PhabricatorSubscribableInterface,
PhabricatorMentionableInterface,
HarbormasterBuildableInterface,
HarbormasterCircleCIBuildableInterface,
HarbormasterBuildkiteBuildableInterface,
PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorFulltextInterface,
PhabricatorFerretInterface,
PhabricatorConduitResultInterface,
PhabricatorDraftInterface {
protected $repositoryID;
protected $phid;
protected $authorIdentityPHID;
protected $committerIdentityPHID;
protected $commitIdentifier;
protected $epoch;
protected $mailKey;
protected $authorPHID;
protected $auditStatus = PhabricatorAuditCommitStatusConstants::NONE;
protected $summary = '';
protected $importStatus = 0;
const IMPORTED_MESSAGE = 1;
const IMPORTED_CHANGE = 2;
const IMPORTED_OWNERS = 4;
const IMPORTED_HERALD = 8;
const IMPORTED_ALL = 15;
const IMPORTED_CLOSEABLE = 1024;
const IMPORTED_UNREACHABLE = 2048;
private $commitData = self::ATTACHABLE;
private $audits = self::ATTACHABLE;
private $repository = self::ATTACHABLE;
private $customFields = self::ATTACHABLE;
private $authorIdentity = self::ATTACHABLE;
private $committerIdentity = self::ATTACHABLE;
private $drafts = array();
private $auditAuthorityPHIDs = array();
public function attachRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
return $this;
}
public function getRepository($assert_attached = true) {
if ($assert_attached) {
return $this->assertAttached($this->repository);
}
return $this->repository;
}
public function isPartiallyImported($mask) {
return (($mask & $this->getImportStatus()) == $mask);
}
public function isImported() {
return $this->isPartiallyImported(self::IMPORTED_ALL);
}
public function isUnreachable() {
return $this->isPartiallyImported(self::IMPORTED_UNREACHABLE);
}
public function writeImportStatusFlag($flag) {
return $this->adjustImportStatusFlag($flag, true);
}
public function clearImportStatusFlag($flag) {
return $this->adjustImportStatusFlag($flag, false);
}
private function adjustImportStatusFlag($flag, $set) {
$conn_w = $this->establishConnection('w');
$table_name = $this->getTableName();
$id = $this->getID();
if ($set) {
queryfx(
$conn_w,
'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d',
$table_name,
$flag,
$id);
$this->setImportStatus($this->getImportStatus() | $flag);
} else {
queryfx(
$conn_w,
'UPDATE %T SET importStatus = (importStatus & ~%d) WHERE id = %d',
$table_name,
$flag,
$id);
$this->setImportStatus($this->getImportStatus() & ~$flag);
}
return $this;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_COLUMN_SCHEMA => array(
'commitIdentifier' => 'text40',
'mailKey' => 'bytes20',
'authorPHID' => 'phid?',
'authorIdentityPHID' => 'phid?',
'committerIdentityPHID' => 'phid?',
'auditStatus' => 'uint32',
'summary' => 'text255',
'importStatus' => 'uint32',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
'repositoryID' => array(
'columns' => array('repositoryID', 'importStatus'),
),
'authorPHID' => array(
'columns' => array('authorPHID', 'auditStatus', 'epoch'),
),
'repositoryID_2' => array(
'columns' => array('repositoryID', 'epoch'),
),
'key_commit_identity' => array(
'columns' => array('commitIdentifier', 'repositoryID'),
'unique' => true,
),
'key_epoch' => array(
'columns' => array('epoch'),
),
'key_author' => array(
'columns' => array('authorPHID', 'epoch'),
),
),
self::CONFIG_NO_MUTATE => array(
'importStatus',
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorRepositoryCommitPHIDType::TYPECONST);
}
public function loadCommitData() {
if (!$this->getID()) {
return null;
}
return id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$this->getID());
}
public function attachCommitData(
PhabricatorRepositoryCommitData $data = null) {
$this->commitData = $data;
return $this;
}
public function getCommitData() {
return $this->assertAttached($this->commitData);
}
public function attachAudits(array $audits) {
assert_instances_of($audits, 'PhabricatorRepositoryAuditRequest');
$this->audits = $audits;
return $this;
}
public function getAudits() {
return $this->assertAttached($this->audits);
}
public function hasAttachedAudits() {
return ($this->audits !== self::ATTACHABLE);
}
public function attachIdentities(
PhabricatorRepositoryIdentity $author = null,
PhabricatorRepositoryIdentity $committer = null) {
$this->authorIdentity = $author;
$this->committerIdentity = $committer;
}
public function getAuthorIdentity() {
return $this->assertAttached($this->authorIdentity);
}
public function getCommitterIdentity() {
return $this->assertAttached($this->committerIdentity);
}
public function loadAndAttachAuditAuthority(
PhabricatorUser $viewer,
$actor_phid = null) {
if ($actor_phid === null) {
$actor_phid = $viewer->getPHID();
}
// TODO: This method is a little weird and sketchy, but worlds better than
// what came before it. Eventually, this should probably live in a Query
// class.
// Figure out which requests the actor has authority over: these are user
// requests where they are the auditor, and packages and projects they are
// a member of.
if (!$actor_phid) {
$attach_key = $viewer->getCacheFragment();
$phids = array();
} else {
$attach_key = $actor_phid;
// At least currently, when modifying your own commits, you act only on
// behalf of yourself, not your packages/projects -- the idea being that
// you can't accept your own commits. This may change or depend on
// config.
$actor_is_author = ($actor_phid == $this->getAuthorPHID());
if ($actor_is_author) {
$phids = array($actor_phid);
} else {
$phids = array();
$phids[$actor_phid] = true;
$owned_packages = id(new PhabricatorOwnersPackageQuery())
->setViewer($viewer)
->withAuthorityPHIDs(array($actor_phid))
->execute();
foreach ($owned_packages as $package) {
$phids[$package->getPHID()] = true;
}
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs(array($actor_phid))
->execute();
foreach ($projects as $project) {
$phids[$project->getPHID()] = true;
}
$phids = array_keys($phids);
}
}
$this->auditAuthorityPHIDs[$attach_key] = array_fuse($phids);
return $this;
}
public function hasAuditAuthority(
PhabricatorUser $viewer,
PhabricatorRepositoryAuditRequest $audit,
$actor_phid = null) {
if ($actor_phid === null) {
$actor_phid = $viewer->getPHID();
}
if (!$actor_phid) {
$attach_key = $viewer->getCacheFragment();
} else {
$attach_key = $actor_phid;
}
$map = $this->assertAttachedKey($this->auditAuthorityPHIDs, $attach_key);
if (!$actor_phid) {
return false;
}
return isset($map[$audit->getAuditorPHID()]);
}
public function writeOwnersEdges(array $package_phids) {
$src_phid = $this->getPHID();
$edge_type = DiffusionCommitHasPackageEdgeType::EDGECONST;
$editor = new PhabricatorEdgeEditor();
$dst_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$src_phid,
$edge_type);
foreach ($dst_phids as $dst_phid) {
$editor->removeEdge($src_phid, $edge_type, $dst_phid);
}
foreach ($package_phids as $package_phid) {
$editor->addEdge($src_phid, $edge_type, $package_phid);
}
$editor->save();
return $this;
}
public function getAuditorPHIDsForEdit() {
$audits = $this->getAudits();
return mpull($audits, 'getAuditorPHID');
}
public function save() {
if (!$this->mailKey) {
$this->mailKey = Filesystem::readRandomCharacters(20);
}
return parent::save();
}
public function delete() {
$data = $this->loadCommitData();
$audits = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere('commitPHID = %s', $this->getPHID());
$this->openTransaction();
if ($data) {
$data->delete();
}
foreach ($audits as $audit) {
$audit->delete();
}
$result = parent::delete();
$this->saveTransaction();
return $result;
}
public function getDateCreated() {
// This is primarily to make analysis of commits with the Fact engine work.
return $this->getEpoch();
}
public function getURI() {
return '/'.$this->getMonogram();
}
/**
* Synchronize a commit's overall audit status with the individual audit
* triggers.
*/
public function updateAuditStatus(array $requests) {
assert_instances_of($requests, 'PhabricatorRepositoryAuditRequest');
$any_concern = false;
$any_accept = false;
$any_need = false;
foreach ($requests as $request) {
switch ($request->getAuditStatus()) {
case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
case PhabricatorAuditStatusConstants::AUDIT_REQUESTED:
$any_need = true;
break;
case PhabricatorAuditStatusConstants::ACCEPTED:
$any_accept = true;
break;
case PhabricatorAuditStatusConstants::CONCERNED:
$any_concern = true;
break;
}
}
$current_status = $this->getAuditStatus();
$status_verify = PhabricatorAuditCommitStatusConstants::NEEDS_VERIFICATION;
if ($any_concern) {
if ($current_status == $status_verify) {
// If the change is in "Needs Verification", we keep it there as
// long as any auditors still have concerns.
$status = $status_verify;
} else {
$status = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
}
} else if ($any_accept) {
if ($any_need) {
$status = PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED;
} else {
$status = PhabricatorAuditCommitStatusConstants::FULLY_AUDITED;
}
} else if ($any_need) {
$status = PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT;
} else {
$status = PhabricatorAuditCommitStatusConstants::NONE;
}
return $this->setAuditStatus($status);
}
public function getMonogram() {
$repository = $this->getRepository();
$callsign = $repository->getCallsign();
$identifier = $this->getCommitIdentifier();
if ($callsign !== null) {
return "r{$callsign}{$identifier}";
} else {
$id = $repository->getID();
return "R{$id}:{$identifier}";
}
}
public function getDisplayName() {
$repository = $this->getRepository();
$identifier = $this->getCommitIdentifier();
return $repository->formatCommitName($identifier);
}
/**
* Return a local display name for use in the context of the containing
* repository.
*
* In Git and Mercurial, this returns only a short hash, like "abcdef012345".
* See @{method:getDisplayName} for a short name that always includes
* repository context.
*
* @return string Short human-readable name for use inside a repository.
*/
public function getLocalName() {
$repository = $this->getRepository();
$identifier = $this->getCommitIdentifier();
return $repository->formatCommitName($identifier, $local = true);
}
/**
* Make a strong effort to find a way to render this commit's committer.
* This currently attempts to use @{PhabricatorRepositoryIdentity}, and
* falls back to examining the commit detail information. After we force
* the migration to using identities, update this method to remove the
* fallback. See T12164 for details.
*/
public function renderAnyCommitter(PhabricatorUser $viewer, $handles) {
$committer = $this->renderCommitter($viewer, $handles);
if ($committer) {
return $committer;
}
return $this->renderAuthor($viewer, $handles);
}
public function renderCommitter(PhabricatorUser $viewer, $handles) {
$committer_phid = $this->getCommitterDisplayPHID();
if ($committer_phid) {
return $handles[$committer_phid]->renderLink();
}
$data = $this->getCommitData();
$committer_name = $data->getCommitDetail('committer');
if (strlen($committer_name)) {
- return $committer_name;
+ return DiffusionView::renderName($committer_name);
}
return null;
}
public function renderAuthor(PhabricatorUser $viewer, $handles) {
$author_phid = $this->getAuthorDisplayPHID();
if ($author_phid) {
return $handles[$author_phid]->renderLink();
}
$data = $this->getCommitData();
$author_name = $data->getAuthorName();
if (strlen($author_name)) {
- return $author_name;
+ return DiffusionView::renderName($author_name);
}
return null;
}
public function hasCommitterIdentity() {
return ($this->getCommitterIdentity() !== null);
}
public function hasAuthorIdentity() {
return ($this->getAuthorIdentity() !== null);
}
public function getCommitterDisplayPHID() {
if ($this->hasCommitterIdentity()) {
return $this->getCommitterIdentity()->getIdentityDisplayPHID();
}
$data = $this->getCommitData();
return $data->getCommitDetail('committerPHID');
}
public function getAuthorDisplayPHID() {
if ($this->hasAuthorIdentity()) {
return $this->getAuthorIdentity()->getIdentityDisplayPHID();
}
$data = $this->getCommitData();
return $data->getCommitDetail('authorPHID');
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getRepository()->getPolicy($capability);
case PhabricatorPolicyCapability::CAN_EDIT:
return PhabricatorPolicies::POLICY_USER;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
}
public function describeAutomaticCapability($capability) {
return pht(
'Commits inherit the policies of the repository they belong to.');
}
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array(
$this->getAuthorPHID(),
);
}
/* -( Stuff for serialization )---------------------------------------------- */
/**
* NOTE: this is not a complete serialization; only the 'protected' fields are
* involved. This is due to ease of (ab)using the Lisk abstraction to get this
* done, as well as complexity of the other fields.
*/
public function toDictionary() {
return array(
'repositoryID' => $this->getRepositoryID(),
'phid' => $this->getPHID(),
'commitIdentifier' => $this->getCommitIdentifier(),
'epoch' => $this->getEpoch(),
'mailKey' => $this->getMailKey(),
'authorPHID' => $this->getAuthorPHID(),
'auditStatus' => $this->getAuditStatus(),
'summary' => $this->getSummary(),
'importStatus' => $this->getImportStatus(),
);
}
public static function newFromDictionary(array $dict) {
return id(new PhabricatorRepositoryCommit())
->loadFromArray($dict);
}
/* -( HarbormasterBuildableInterface )------------------------------------- */
public function getHarbormasterBuildableDisplayPHID() {
return $this->getHarbormasterBuildablePHID();
}
public function getHarbormasterBuildablePHID() {
return $this->getPHID();
}
public function getHarbormasterContainerPHID() {
return $this->getRepository()->getPHID();
}
public function getBuildVariables() {
$results = array();
$results['buildable.commit'] = $this->getCommitIdentifier();
$repo = $this->getRepository();
$results['repository.callsign'] = $repo->getCallsign();
$results['repository.phid'] = $repo->getPHID();
$results['repository.vcs'] = $repo->getVersionControlSystem();
$results['repository.uri'] = $repo->getPublicCloneURI();
return $results;
}
public function getAvailableBuildVariables() {
return array(
'buildable.commit' => pht('The commit identifier, if applicable.'),
'repository.callsign' =>
pht('The callsign of the repository in Phabricator.'),
'repository.phid' =>
pht('The PHID of the repository in Phabricator.'),
'repository.vcs' =>
pht('The version control system, either "svn", "hg" or "git".'),
'repository.uri' =>
pht('The URI to clone or checkout the repository from.'),
);
}
public function newBuildableEngine() {
return new DiffusionBuildableEngine();
}
/* -( HarbormasterCircleCIBuildableInterface )----------------------------- */
public function getCircleCIGitHubRepositoryURI() {
$repository = $this->getRepository();
$commit_phid = $this->getPHID();
$repository_phid = $repository->getPHID();
if ($repository->isHosted()) {
throw new Exception(
pht(
'This commit ("%s") is associated with a hosted repository '.
'("%s"). Repositories must be imported from GitHub to be built '.
'with CircleCI.',
$commit_phid,
$repository_phid));
}
$remote_uri = $repository->getRemoteURI();
$path = HarbormasterCircleCIBuildStepImplementation::getGitHubPath(
$remote_uri);
if (!$path) {
throw new Exception(
pht(
'This commit ("%s") is associated with a repository ("%s") that '.
'with a remote URI ("%s") that does not appear to be hosted on '.
'GitHub. Repositories must be hosted on GitHub to be built with '.
'CircleCI.',
$commit_phid,
$repository_phid,
$remote_uri));
}
return $remote_uri;
}
public function getCircleCIBuildIdentifierType() {
return 'revision';
}
public function getCircleCIBuildIdentifier() {
return $this->getCommitIdentifier();
}
/* -( HarbormasterBuildkiteBuildableInterface )---------------------------- */
public function getBuildkiteBranch() {
$viewer = PhabricatorUser::getOmnipotentUser();
$repository = $this->getRepository();
$branches = DiffusionQuery::callConduitWithDiffusionRequest(
$viewer,
DiffusionRequest::newFromDictionary(
array(
'repository' => $repository,
'user' => $viewer,
)),
'diffusion.branchquery',
array(
'contains' => $this->getCommitIdentifier(),
'repository' => $repository->getPHID(),
));
if (!$branches) {
throw new Exception(
pht(
'Commit "%s" is not an ancestor of any branch head, so it can not '.
'be built with Buildkite.',
$this->getCommitIdentifier()));
}
$branch = head($branches);
return 'refs/heads/'.$branch['shortName'];
}
public function getBuildkiteCommit() {
return $this->getCommitIdentifier();
}
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
public function getCustomFieldSpecificationForRole($role) {
return PhabricatorEnv::getEnvConfig('diffusion.fields');
}
public function getCustomFieldBaseClass() {
return 'PhabricatorCommitCustomField';
}
public function getCustomFields() {
return $this->assertAttached($this->customFields);
}
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
$this->customFields = $fields;
return $this;
}
/* -( PhabricatorSubscribableInterface )----------------------------------- */
public function isAutomaticallySubscribed($phid) {
// TODO: This should also list auditors, but handling that is a bit messy
// right now because we are not guaranteed to have the data. (It should not
// include resigned auditors.)
return ($phid == $this->getAuthorPHID());
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorAuditEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhabricatorAuditTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
$xactions = $timeline->getTransactions();
$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 $timeline->setPathMap($path_map);
}
/* -( PhabricatorFulltextInterface )--------------------------------------- */
public function newFulltextEngine() {
return new DiffusionCommitFulltextEngine();
}
/* -( PhabricatorFerretInterface )----------------------------------------- */
public function newFerretEngine() {
return new DiffusionCommitFerretEngine();
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('identifier')
->setType('string')
->setDescription(pht('The commit identifier.')),
);
}
public function getFieldValuesForConduit() {
// NOTE: This data should be similar to the information returned about
// commmits by "differential.diff.search" with the "commits" attachment.
return array(
'identifier' => $this->getCommitIdentifier(),
);
}
public function getConduitSearchAttachments() {
return array();
}
/* -( PhabricatorDraftInterface )------------------------------------------ */
public function newDraftEngine() {
return new DiffusionCommitDraftEngine();
}
public function getHasDraft(PhabricatorUser $viewer) {
return $this->assertAttachedKey($this->drafts, $viewer->getCacheFragment());
}
public function attachHasDraft(PhabricatorUser $viewer, $has_draft) {
$this->drafts[$viewer->getCacheFragment()] = $has_draft;
return $this;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Jan 19 2025, 21:50 (6 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1129114
Default Alt Text
(39 KB)

Event Timeline