@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

When creating or updating a revision, infer the repository from the diff

Summary:
Ref T603. When a diff is attached to a revision, try to guess the repository if possible. In cases where we succeed, this automatically gives us intuitive policy behavior (i.e., you can see a revision if you can see the repository the change is against).

I pulled this into a funky little "Lookup" class for two reasons:

- It's used in two places;
- I anticipate that we might need to add some sort of `explainWhy()` method if users find the heuristics confusing.

Test Plan: Created and updated revisions, saw them pick up the correct repository association. Ran Herald dry run against associable and nonassociable revisions, saw correct values populate.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T603

Differential Revision: https://secure.phabricator.com/D7147

+128 -16
+2
src/__phutil_library_map__.php
··· 395 395 'DifferentialRemarkupRule' => 'applications/differential/remarkup/DifferentialRemarkupRule.php', 396 396 'DifferentialReplyHandler' => 'applications/differential/mail/DifferentialReplyHandler.php', 397 397 'DifferentialRepositoryFieldSpecification' => 'applications/differential/field/specification/DifferentialRepositoryFieldSpecification.php', 398 + 'DifferentialRepositoryLookup' => 'applications/differential/query/DifferentialRepositoryLookup.php', 398 399 'DifferentialResultsTableView' => 'applications/differential/view/DifferentialResultsTableView.php', 399 400 'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/DifferentialRevertPlanFieldSpecification.php', 400 401 'DifferentialReviewRequestMail' => 'applications/differential/mail/DifferentialReviewRequestMail.php', ··· 2470 2471 'DifferentialRemarkupRule' => 'PhabricatorRemarkupRuleObject', 2471 2472 'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler', 2472 2473 'DifferentialRepositoryFieldSpecification' => 'DifferentialFieldSpecification', 2474 + 'DifferentialRepositoryLookup' => 'Phobject', 2473 2475 'DifferentialResultsTableView' => 'AphrontView', 2474 2476 'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification', 2475 2477 'DifferentialReviewRequestMail' => 'DifferentialMail',
+10
src/applications/differential/editor/DifferentialRevisionEditor.php
··· 126 126 } 127 127 $this->diff = $diff; 128 128 $this->comments = $comments; 129 + 130 + $repository = id(new DifferentialRepositoryLookup()) 131 + ->setViewer($this->getActor()) 132 + ->setDiff($diff) 133 + ->lookupRepository(); 134 + 135 + if ($repository) { 136 + $this->getRevision()->setRepositoryPHID($repository->getPHID()); 137 + } 138 + 129 139 return $this; 130 140 } 131 141
+83
src/applications/differential/query/DifferentialRepositoryLookup.php
··· 1 + <?php 2 + 3 + /** 4 + * Guess which tracked repository a diff comes from. 5 + */ 6 + final class DifferentialRepositoryLookup extends Phobject { 7 + 8 + private $viewer; 9 + private $diff; 10 + 11 + public function setDiff(DifferentialDiff $diff) { 12 + $this->diff = $diff; 13 + return $this; 14 + } 15 + 16 + public function setViewer(PhabricatorUser $viewer) { 17 + $this->viewer = $viewer; 18 + return $this; 19 + } 20 + 21 + public function lookupRepository() { 22 + $viewer = $this->viewer; 23 + $diff = $this->diff; 24 + 25 + // Look for an explicit Arcanist project. 26 + if ($diff->getArcanistProjectPHID()) { 27 + $project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere( 28 + 'phid = %s', 29 + $diff->getArcanistProjectPHID()); 30 + if ($project && $project->getRepositoryID()) { 31 + $repositories = id(new PhabricatorRepositoryQuery()) 32 + ->setViewer($viewer) 33 + ->withIDs(array($project->getRepositoryID())) 34 + ->execute(); 35 + if ($repositories) { 36 + return head($repositories); 37 + } 38 + } 39 + } 40 + 41 + // Look for a repository UUID. 42 + if ($diff->getRepositoryUUID()) { 43 + $repositories = id(new PhabricatorRepositoryQuery()) 44 + ->setViewer($viewer) 45 + ->withUUIDs($diff->getRepositoryUUID()) 46 + ->execute(); 47 + if ($repositories) { 48 + return head($repositories); 49 + } 50 + } 51 + 52 + // Look for the base commit in Git and Mercurial. 53 + $vcs = $diff->getSourceControlSystem(); 54 + $vcs_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT; 55 + $vcs_hg = PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL; 56 + if ($vcs == $vcs_git || $vcs == $vcs_hg) { 57 + $base = $diff->getSourceControlBaseRevision(); 58 + if ($base) { 59 + $commits = id(new DiffusionCommitQuery()) 60 + ->setViewer($viewer) 61 + ->withIdentifiers(array($base)) 62 + ->execute(); 63 + $commits = mgroup($commits, 'getRepositoryID'); 64 + if (count($commits) == 1) { 65 + $repository_id = key($commits); 66 + $repositories = id(new PhabricatorRepositoryQuery()) 67 + ->setViewer($viewer) 68 + ->withIDs(array($repository_id)) 69 + ->execute(); 70 + if ($repositories) { 71 + return head($repositories); 72 + } 73 + } 74 + } 75 + } 76 + 77 + // TODO: Compare SVN remote URIs? Compare Git/Hg remote URIs? Add 78 + // an explicit option to `.arcconfig`? 79 + 80 + return null; 81 + } 82 + 83 + }
+20 -16
src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
··· 106 106 107 107 public function loadRepository() { 108 108 if ($this->repository === null) { 109 - $diff = $this->diff; 110 - 111 - $repository = false; 109 + $this->repository = false; 112 110 113 111 // TODO: (T603) Implement policy stuff in Herald. 112 + $viewer = PhabricatorUser::getOmnipotentUser(); 114 113 115 - if ($diff->getRepositoryUUID()) { 116 - $repository = id(new PhabricatorRepository())->loadOneWhere( 117 - 'uuid = %s', 118 - $diff->getRepositoryUUID()); 114 + $revision = $this->revision; 115 + if ($revision->getRepositoryPHID()) { 116 + $repositories = id(new PhabricatorRepositoryQuery()) 117 + ->setViewer($viewer) 118 + ->withPHIDs(array($revision->getRepositoryPHID())) 119 + ->execute(); 120 + if ($repositories) { 121 + $this->repository = head($repositories); 122 + return $this->repository; 123 + } 119 124 } 120 125 121 - if (!$repository && $diff->getArcanistProjectPHID()) { 122 - $project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere( 123 - 'phid = %s', 124 - $diff->getArcanistProjectPHID()); 125 - if ($project && $project->getRepositoryID()) { 126 - $repository = id(new PhabricatorRepository())->load( 127 - $project->getRepositoryID()); 128 - } 126 + $repository = id(new DifferentialRepositoryLookup()) 127 + ->setViewer($viewer) 128 + ->setDiff($this->diff) 129 + ->lookupRepository(); 130 + if ($repository) { 131 + $this->repository = $repository; 132 + return $this->repository; 129 133 } 130 134 131 - $this->repository = $repository; 135 + $repository = false; 132 136 } 133 137 return $this->repository; 134 138 }
+13
src/applications/repository/query/PhabricatorRepositoryQuery.php
··· 7 7 private $phids; 8 8 private $callsigns; 9 9 private $types; 10 + private $uuids; 10 11 11 12 const STATUS_OPEN = 'status-open'; 12 13 const STATUS_CLOSED = 'status-closed'; ··· 44 45 45 46 public function withTypes(array $types) { 46 47 $this->types = $types; 48 + return $this; 49 + } 50 + 51 + public function withUUIDs(array $uuids) { 52 + $this->uuids = $uuids; 47 53 return $this; 48 54 } 49 55 ··· 297 303 $conn_r, 298 304 'r.versionControlSystem IN (%Ls)', 299 305 $this->types); 306 + } 307 + 308 + if ($this->uuids) { 309 + $where[] = qsprintf( 310 + $conn_r, 311 + 'r.uuid IN (%Ls)', 312 + $this->uuids); 300 313 } 301 314 302 315 $where[] = $this->buildPagingClause($conn_r);