@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.

Introduce DifferentialChangesetQuery and remove loadHunks()

Summary: Ref T4045. Ref T5179. This removes all non-Query hunk loads.

Test Plan:
- Viewed revisions.
- Viewed standalone changesets.
- Viewed raw old/new files.
- Viewed vs diffs.
- Enabled inline comments in mail and sent some transactions with inlines.
- Called `differential.getrawdiff`.
- Grepped for `loadHunks()`.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4045, T5179

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

+236 -77
+2
src/__phutil_library_map__.php
··· 343 343 'DifferentialChangesetOneUpTestRenderer' => 'applications/differential/render/DifferentialChangesetOneUpTestRenderer.php', 344 344 'DifferentialChangesetParser' => 'applications/differential/parser/DifferentialChangesetParser.php', 345 345 'DifferentialChangesetParserTestCase' => 'applications/differential/parser/__tests__/DifferentialChangesetParserTestCase.php', 346 + 'DifferentialChangesetQuery' => 'applications/differential/query/DifferentialChangesetQuery.php', 346 347 'DifferentialChangesetRenderer' => 'applications/differential/render/DifferentialChangesetRenderer.php', 347 348 'DifferentialChangesetTestRenderer' => 'applications/differential/render/DifferentialChangesetTestRenderer.php', 348 349 'DifferentialChangesetTwoUpRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpRenderer.php', ··· 3018 3019 'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer', 3019 3020 'DifferentialChangesetOneUpTestRenderer' => 'DifferentialChangesetTestRenderer', 3020 3021 'DifferentialChangesetParserTestCase' => 'PhabricatorTestCase', 3022 + 'DifferentialChangesetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3021 3023 'DifferentialChangesetTestRenderer' => 'DifferentialChangesetRenderer', 3022 3024 'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer', 3023 3025 'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer',
+42 -33
src/applications/differential/controller/DifferentialChangesetViewController.php
··· 23 23 $id = (int)$id; 24 24 $vs = (int)$vs; 25 25 26 - $changeset = id(new DifferentialChangeset())->load($id); 27 - if (!$changeset) { 28 - return new Aphront404Response(); 26 + $load_ids = array($id); 27 + if ($vs && ($vs != -1)) { 28 + $load_ids[] = $vs; 29 29 } 30 30 31 - // TODO: (T603) Make Changeset policy-aware. For now, just fake it 32 - // by making sure we can see the diff. 33 - $diff = id(new DifferentialDiffQuery()) 31 + $changesets = id(new DifferentialChangesetQuery()) 34 32 ->setViewer($request->getUser()) 35 - ->withIDs(array($changeset->getDiffID())) 36 - ->executeOne(); 37 - if (!$diff) { 33 + ->withIDs($load_ids) 34 + ->needHunks(true) 35 + ->execute(); 36 + $changesets = mpull($changesets, null, 'getID'); 37 + 38 + $changeset = idx($changesets, $id); 39 + if (!$changeset) { 38 40 return new Aphront404Response(); 39 41 } 40 42 43 + $vs_changeset = null; 44 + if ($vs && ($vs != -1)) { 45 + $vs_changeset = idx($changesets, $vs); 46 + if (!$vs_changeset) { 47 + return new Aphront404Response(); 48 + } 49 + } 41 50 42 51 $view = $request->getStr('view'); 43 52 if ($view) { 44 - $changeset->attachHunks($changeset->loadHunks()); 45 53 $phid = idx($changeset->getMetadata(), "$view:binary-phid"); 46 54 if ($phid) { 47 55 return id(new AphrontRedirectResponse())->setURI("/file/info/$phid/"); ··· 50 58 case 'new': 51 59 return $this->buildRawFileResponse($changeset, $is_new = true); 52 60 case 'old': 53 - if ($vs && ($vs != -1)) { 54 - $vs_changeset = id(new DifferentialChangeset())->load($vs); 55 - if ($vs_changeset) { 56 - $vs_changeset->attachHunks($vs_changeset->loadHunks()); 57 - return $this->buildRawFileResponse($vs_changeset, $is_new = true); 58 - } 61 + if ($vs_changeset) { 62 + return $this->buildRawFileResponse($vs_changeset, $is_new = true); 59 63 } 60 64 return $this->buildRawFileResponse($changeset, $is_new = false); 61 65 default: ··· 63 67 } 64 68 } 65 69 66 - if ($vs && ($vs != -1)) { 67 - $vs_changeset = id(new DifferentialChangeset())->load($vs); 68 - if (!$vs_changeset) { 69 - return new Aphront404Response(); 70 - } 71 - } 72 - 73 70 if (!$vs) { 74 71 $right = $changeset; 75 72 $left = null; ··· 103 100 } 104 101 105 102 if ($left) { 106 - $left->attachHunks($left->loadHunks()); 107 - } 108 - 109 - if ($right) { 110 - $right->attachHunks($right->loadHunks()); 111 - } 112 - 113 - if ($left) { 114 - 115 103 $left_data = $left->makeNewFile(); 116 104 if ($right) { 117 105 $right_data = $right->makeNewFile(); ··· 264 252 ), 265 253 $detail->render())); 266 254 255 + $crumbs = $this->buildApplicationCrumbs(); 256 + 257 + $revision_id = $changeset->getDiff()->getRevisionID(); 258 + if ($revision_id) { 259 + $crumbs->addTextCrumb('D'.$revision_id, '/D'.$revision_id); 260 + } 261 + 262 + $diff_id = $changeset->getDiff()->getID(); 263 + if ($diff_id) { 264 + $crumbs->addTextCrumb( 265 + pht('Diff %d', $diff_id), 266 + $this->getApplicationURI('diff/'.$diff_id)); 267 + } 268 + 269 + $crumbs->addTextCrumb($changeset->getDisplayFilename()); 270 + 271 + $box = id(new PHUIObjectBoxView()) 272 + ->setHeaderText(pht('Standalone View')) 273 + ->appendChild($panel); 274 + 267 275 return $this->buildApplicationPage( 268 276 array( 269 - $panel 277 + $crumbs, 278 + $box, 270 279 ), 271 280 array( 272 281 'title' => pht('Changeset View'),
+5 -3
src/applications/differential/controller/DifferentialRevisionViewController.php
··· 844 844 845 845 $viewer = $this->getRequest()->getUser(); 846 846 847 - foreach ($changesets as $changeset) { 848 - $changeset->attachHunks($changeset->loadHunks()); 849 - } 847 + id(new DifferentialHunkQuery()) 848 + ->setViewer($viewer) 849 + ->withChangesets($changesets) 850 + ->needAttachToChangesets(true) 851 + ->execute(); 850 852 851 853 $diff = new DifferentialDiff(); 852 854 $diff->attachChangesets($changesets);
+5 -7
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 1284 1284 $changeset_ids[$id] = $id; 1285 1285 } 1286 1286 1287 - // TODO: We should write a proper Query class for this eventually. 1288 - $changesets = id(new DifferentialChangeset())->loadAllWhere( 1289 - 'id IN (%Ld)', 1290 - $changeset_ids); 1291 1287 if ($show_context) { 1292 1288 $hunk_parser = new DifferentialHunkParser(); 1293 - foreach ($changesets as $changeset) { 1294 - $changeset->attachHunks($changeset->loadHunks()); 1295 - } 1289 + $changesets = id(new DifferentialChangesetQuery()) 1290 + ->setViewer($this->getActor()) 1291 + ->withIDs($changeset_ids) 1292 + ->needHunks(true) 1293 + ->execute(); 1296 1294 } 1297 1295 1298 1296 $inline_groups = DifferentialTransactionComment::sortAndGroupInlines(
+158
src/applications/differential/query/DifferentialChangesetQuery.php
··· 1 + <?php 2 + 3 + final class DifferentialChangesetQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 5 + 6 + private $ids; 7 + private $diffs; 8 + 9 + private $needAttachToDiffs; 10 + private $needHunks; 11 + 12 + public function withIDs(array $ids) { 13 + $this->ids = $ids; 14 + return $this; 15 + } 16 + 17 + public function withDiffs(array $diffs) { 18 + assert_instances_of($diffs, 'DifferentialDiff'); 19 + $this->diffs = $diffs; 20 + return $this; 21 + } 22 + 23 + public function needAttachToDiffs($attach) { 24 + $this->needAttachToDiffs = $attach; 25 + return $this; 26 + } 27 + 28 + public function needHunks($need) { 29 + $this->needHunks = $need; 30 + return $this; 31 + } 32 + 33 + public function willExecute() { 34 + // If we fail to load any changesets (which is possible in the case of an 35 + // empty commit) we'll never call didFilterPage(). Attach empty changeset 36 + // lists now so that we end up with the right result. 37 + if ($this->needAttachToDiffs) { 38 + foreach ($this->diffs as $diff) { 39 + $diff->attachChangesets(array()); 40 + } 41 + } 42 + } 43 + 44 + public function loadPage() { 45 + $table = new DifferentialChangeset(); 46 + $conn_r = $table->establishConnection('r'); 47 + 48 + $data = queryfx_all( 49 + $conn_r, 50 + 'SELECT * FROM %T %Q %Q %Q', 51 + $table->getTableName(), 52 + $this->buildWhereClause($conn_r), 53 + $this->buildOrderClause($conn_r), 54 + $this->buildLimitClause($conn_r)); 55 + 56 + return $table->loadAllFromArray($data); 57 + } 58 + 59 + public function willFilterPage(array $changesets) { 60 + 61 + // First, attach all the diffs we already have. We can just do this 62 + // directly without worrying about querying for them. When we don't have 63 + // a diff, record that we need to load it. 64 + if ($this->diffs) { 65 + $have_diffs = mpull($this->diffs, null, 'getID'); 66 + } else { 67 + $have_diffs = array(); 68 + } 69 + 70 + $must_load = array(); 71 + foreach ($changesets as $key => $changeset) { 72 + $diff_id = $changeset->getDiffID(); 73 + if (isset($have_diffs[$diff_id])) { 74 + $changeset->attachDiff($have_diffs[$diff_id]); 75 + } else { 76 + $must_load[$key] = $changeset; 77 + } 78 + } 79 + 80 + // Load all the diffs we don't have. 81 + $need_diff_ids = mpull($must_load, 'getDiffID'); 82 + $more_diffs = array(); 83 + if ($need_diff_ids) { 84 + $more_diffs = id(new DifferentialDiffQuery()) 85 + ->setViewer($this->getViewer()) 86 + ->setParentQuery($this) 87 + ->withIDs($need_diff_ids) 88 + ->execute(); 89 + $more_diffs = mpull($more_diffs, null, 'getID'); 90 + } 91 + 92 + // Attach the diffs we loaded. 93 + foreach ($must_load as $key => $changeset) { 94 + $diff_id = $changeset->getDiffID(); 95 + if (isset($more_diffs[$diff_id])) { 96 + $changeset->attachDiff($more_diffs[$diff_id]); 97 + } else { 98 + // We didn't have the diff, and could not load it (it does not exist, 99 + // or we can't see it), so filter this result out. 100 + unset($changesets[$key]); 101 + } 102 + } 103 + 104 + return $changesets; 105 + } 106 + 107 + public function didFilterPage(array $changesets) { 108 + if ($this->needAttachToDiffs) { 109 + $changeset_groups = mgroup($changesets, 'getDiffID'); 110 + foreach ($this->diffs as $diff) { 111 + $diff_changesets = idx($changeset_groups, $diff->getID(), array()); 112 + $diff->attachChangesets($diff_changesets); 113 + } 114 + } 115 + 116 + if ($this->needHunks) { 117 + id(new DifferentialHunkQuery()) 118 + ->setViewer($this->getViewer()) 119 + ->setParentQuery($this) 120 + ->withChangesets($changesets) 121 + ->needAttachToChangesets(true) 122 + ->execute(); 123 + } 124 + 125 + return $changesets; 126 + } 127 + 128 + private function buildWhereClause(AphrontDatabaseConnection $conn_r) { 129 + $where = array(); 130 + 131 + if ($this->diffs !== null) { 132 + $where[] = qsprintf( 133 + $conn_r, 134 + 'diffID IN (%Ld)', 135 + mpull($this->diffs, 'getID')); 136 + } 137 + 138 + if ($this->ids !== null) { 139 + $where[] = qsprintf( 140 + $conn_r, 141 + 'id IN (%Ld)', 142 + $this->ids); 143 + } 144 + 145 + $where[] = $this->buildPagingClause($conn_r); 146 + 147 + return $this->formatWhereClause($where); 148 + } 149 + 150 + public function getQueryApplicationClass() { 151 + return 'PhabricatorApplicationDifferential'; 152 + } 153 + 154 + protected function getReversePaging() { 155 + return true; 156 + } 157 + 158 + }
+7 -20
src/applications/differential/query/DifferentialDiffQuery.php
··· 88 88 } 89 89 90 90 private function loadChangesets(array $diffs) { 91 - $diff_ids = mpull($diffs, 'getID'); 92 - 93 - $changesets = id(new DifferentialChangeset())->loadAllWhere( 94 - 'diffID IN (%Ld)', 95 - $diff_ids); 96 - 97 - if ($changesets) { 98 - id(new DifferentialHunkQuery()) 99 - ->setViewer($this->getViewer()) 100 - ->setParentQuery($this) 101 - ->withChangesets($changesets) 102 - ->needAttachToChangesets(true) 103 - ->execute(); 104 - } 105 - 106 - $changeset_groups = mgroup($changesets, 'getDiffID'); 107 - foreach ($diffs as $diff) { 108 - $diff_changesets = idx($changeset_groups, $diff->getID(), array()); 109 - $diff->attachChangesets($diff_changesets); 110 - } 91 + id(new DifferentialChangesetQuery()) 92 + ->setViewer($this->getViewer()) 93 + ->setParentQuery($this) 94 + ->withDiffs($diffs) 95 + ->needAttachToDiffs(true) 96 + ->needHunks(true) 97 + ->execute(); 111 98 112 99 return $diffs; 113 100 }
+17 -14
src/applications/differential/storage/DifferentialChangeset.php
··· 62 62 return $this; 63 63 } 64 64 65 - public function loadHunks() { 66 - if (!$this->getID()) { 67 - return array(); 68 - } 69 - return id(new DifferentialHunk())->loadAllWhere( 70 - 'changesetID = %d', 71 - $this->getID()); 72 - } 73 - 74 65 public function save() { 75 66 $this->openTransaction(); 76 67 $ret = parent::save(); ··· 84 75 85 76 public function delete() { 86 77 $this->openTransaction(); 87 - foreach ($this->loadHunks() as $hunk) { 78 + 79 + $hunks = id(new DifferentialHunk())->loadAllWhere( 80 + 'changesetID = %d', 81 + $this->getID()); 82 + foreach ($hunks as $hunk) { 88 83 $hunk->delete(); 89 84 } 85 + 90 86 $this->unsavedHunks = array(); 91 87 92 88 queryfx( ··· 174 170 return false; 175 171 } 176 172 173 + public function attachDiff(DifferentialDiff $diff) { 174 + $this->diff = $diff; 175 + return $this; 176 + } 177 + 178 + public function getDiff() { 179 + return $this->assertAttached($this->diff); 180 + } 181 + 177 182 178 183 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 179 184 ··· 185 190 } 186 191 187 192 public function getPolicy($capability) { 188 - // TODO: For now, these are never queried directly through the policy 189 - // framework. Fix that up. 190 - return PhabricatorPolicies::getMostOpenPolicy(); 193 + return $this->getDiff()->getPolicy($capability); 191 194 } 192 195 193 196 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 194 - return false; 197 + return $this->getDiff()->hasAutomaticCapability($capability, $viewer); 195 198 } 196 199 197 200 public function describeAutomaticCapability($capability) {