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

Add a "Changes Since Last Action" view to Differential revisions

Summary:
Ref T13151. See PHI616. Fixes T8163.

This adds `/D123/new/`, which shows the changes to the revision since the last timeline action you took.

It also adds a link to this view to diff update emails.

Test Plan:
- Followed this link with a recent comment and no touches since update, ended up with sensible diff selections.
- Updated revision, generated email, saw an appropriate link.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13151, T8163

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

+169 -22
+4 -1
src/applications/differential/application/PhabricatorDifferentialApplication.php
··· 43 43 44 44 public function getRoutes() { 45 45 return array( 46 - '/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController', 46 + '/D(?P<id>[1-9]\d*)' => array( 47 + '' => 'DifferentialRevisionViewController', 48 + '/(?P<filter>new)/' => 'DifferentialRevisionViewController', 49 + ), 47 50 '/differential/' => array( 48 51 '(?:query/(?P<queryKey>[^/]+)/)?' 49 52 => 'DifferentialRevisionListController',
+142 -8
src/applications/differential/controller/DifferentialRevisionViewController.php
··· 6 6 private $revisionID; 7 7 private $changesetCount; 8 8 private $hiddenChangesets; 9 + private $warnings = array(); 9 10 10 11 public function shouldAllowPublic() { 11 12 return true; ··· 68 69 69 70 $revision->attachActiveDiff(last($diffs)); 70 71 71 - $diff_vs = $request->getInt('vs'); 72 - $target_id = $request->getInt('id'); 73 - $target = idx($diffs, $target_id, end($diffs)); 72 + $diff_vs = $this->getOldDiffID($revision, $diffs); 73 + if ($diff_vs instanceof AphrontResponse) { 74 + return $diff_vs; 75 + } 76 + 77 + $target_id = $this->getNewDiffID($revision, $diffs); 78 + if ($target_id instanceof AphrontResponse) { 79 + return $target_id; 80 + } 81 + 82 + $target = $diffs[$target_id]; 74 83 75 84 $target_manual = $target; 76 85 if (!$target_id) { ··· 79 88 $target_manual = $diff; 80 89 } 81 90 } 82 - } 83 - 84 - if (empty($diffs[$diff_vs])) { 85 - $diff_vs = null; 86 91 } 87 92 88 93 $repository = null; ··· 170 175 } 171 176 172 177 $handles = $this->loadViewerHandles($object_phids); 173 - $warnings = array(); 178 + $warnings = $this->warnings; 174 179 175 180 $request_uri = $request->getRequestURI(); 176 181 ··· 1310 1315 ->setUnitMessages($diff->getUnitMessages()) 1311 1316 ->setLimit(5) 1312 1317 ->setShowViewAll(true); 1318 + } 1319 + 1320 + private function getOldDiffID(DifferentialRevision $revision, array $diffs) { 1321 + assert_instances_of($diffs, 'DifferentialDiff'); 1322 + $request = $this->getRequest(); 1323 + 1324 + $diffs = mpull($diffs, null, 'getID'); 1325 + 1326 + $is_new = ($request->getURIData('filter') === 'new'); 1327 + $old_id = $request->getInt('vs'); 1328 + 1329 + // This is ambiguous, so just 404 rather than trying to figure out what 1330 + // the user expects. 1331 + if ($is_new && $old_id) { 1332 + return new Aphront404Response(); 1333 + } 1334 + 1335 + if ($is_new) { 1336 + $viewer = $this->getViewer(); 1337 + 1338 + $xactions = id(new DifferentialTransactionQuery()) 1339 + ->setViewer($viewer) 1340 + ->withObjectPHIDs(array($revision->getPHID())) 1341 + ->withAuthorPHIDs(array($viewer->getPHID())) 1342 + ->setOrder('newest') 1343 + ->setLimit(1) 1344 + ->execute(); 1345 + 1346 + if (!$xactions) { 1347 + $this->warnings[] = id(new PHUIInfoView()) 1348 + ->setTitle(pht('No Actions')) 1349 + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 1350 + ->appendChild( 1351 + pht( 1352 + 'Showing all changes because you have never taken an '. 1353 + 'action on this revision.')); 1354 + } else { 1355 + $xaction = head($xactions); 1356 + 1357 + // Find the transactions which updated this revision. We want to 1358 + // figure out which diff was active when you last took an action. 1359 + $updates = id(new DifferentialTransactionQuery()) 1360 + ->setViewer($viewer) 1361 + ->withObjectPHIDs(array($revision->getPHID())) 1362 + ->withTransactionTypes( 1363 + array( 1364 + DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE, 1365 + )) 1366 + ->setOrder('oldest') 1367 + ->execute(); 1368 + 1369 + // Sort the diffs into two buckets: those older than your last action 1370 + // and those newer than your last action. 1371 + $older = array(); 1372 + $newer = array(); 1373 + foreach ($updates as $update) { 1374 + // If you updated the revision with "arc diff", try to count that 1375 + // update as "before your last action". 1376 + if ($update->getDateCreated() <= $xaction->getDateCreated()) { 1377 + $older[] = $update->getNewValue(); 1378 + } else { 1379 + $newer[] = $update->getNewValue(); 1380 + } 1381 + } 1382 + 1383 + if (!$newer) { 1384 + $this->warnings[] = id(new PHUIInfoView()) 1385 + ->setTitle(pht('No Recent Updates')) 1386 + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 1387 + ->appendChild( 1388 + pht( 1389 + 'Showing all changes because the diff for this revision '. 1390 + 'has not been updated since your last action.')); 1391 + } else { 1392 + $older = array_fuse($older); 1393 + 1394 + // Find the most recent diff from before the last action. 1395 + $old = null; 1396 + foreach ($diffs as $diff) { 1397 + if (!isset($older[$diff->getPHID()])) { 1398 + break; 1399 + } 1400 + 1401 + $old = $diff; 1402 + } 1403 + 1404 + // It's possible we may not find such a diff: transactions may have 1405 + // been removed from the database, for example. If we miss, just 1406 + // fail into some reasonable state since 404'ing would be perplexing. 1407 + if ($old) { 1408 + $this->warnings[] = id(new PHUIInfoView()) 1409 + ->setTitle(pht('New Changes Shown')) 1410 + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 1411 + ->appendChild( 1412 + pht( 1413 + 'Showing changes since the last action you took on this '. 1414 + 'revision.')); 1415 + 1416 + $old_id = $old->getID(); 1417 + } 1418 + } 1419 + } 1420 + } 1421 + 1422 + if (isset($diffs[$old_id])) { 1423 + return $old_id; 1424 + } 1425 + 1426 + return null; 1427 + } 1428 + 1429 + private function getNewDiffID(DifferentialRevision $revision, array $diffs) { 1430 + assert_instances_of($diffs, 'DifferentialDiff'); 1431 + $request = $this->getRequest(); 1432 + 1433 + $diffs = mpull($diffs, null, 'getID'); 1434 + 1435 + $is_new = ($request->getURIData('filter') === 'new'); 1436 + $new_id = $request->getInt('id'); 1437 + 1438 + if ($is_new && $new_id) { 1439 + return new Aphront404Response(); 1440 + } 1441 + 1442 + if (isset($diffs[$new_id])) { 1443 + return $new_id; 1444 + } 1445 + 1446 + return (int)last_key($diffs); 1313 1447 } 1314 1448 1315 1449 }
+22 -12
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 624 624 $body = new PhabricatorMetaMTAMailBody(); 625 625 $body->setViewer($this->requireActor()); 626 626 627 - $revision_uri = PhabricatorEnv::getProductionURI('/D'.$object->getID()); 627 + $revision_uri = $object->getURI(); 628 + $revision_uri = PhabricatorEnv::getProductionURI($revision_uri); 629 + $new_uri = $revision_uri.'/new/'; 628 630 629 631 $this->addHeadersAndCommentsToMailBody( 630 632 $body, ··· 645 647 $this->appendInlineCommentsForMail($object, $inlines, $body); 646 648 } 647 649 650 + $update_xaction = null; 651 + foreach ($xactions as $xaction) { 652 + switch ($xaction->getTransactionType()) { 653 + case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE: 654 + $update_xaction = $xaction; 655 + break; 656 + } 657 + } 658 + 659 + if ($update_xaction) { 660 + $diff = $this->requireDiff($update_xaction->getNewValue(), true); 661 + } else { 662 + $diff = null; 663 + } 664 + 648 665 $changed_uri = $this->getChangedPriorToCommitURI(); 649 666 if ($changed_uri) { 650 667 $body->addLinkSection( ··· 654 671 655 672 $this->addCustomFieldsToMailBody($body, $object, $xactions); 656 673 674 + if (!$this->getIsNewObject()) { 675 + $body->addLinkSection(pht('CHANGES SINCE LAST ACTION'), $new_uri); 676 + } 677 + 657 678 $body->addLinkSection( 658 679 pht('REVISION DETAIL'), 659 680 $revision_uri); 660 681 661 - $update_xaction = null; 662 - foreach ($xactions as $xaction) { 663 - switch ($xaction->getTransactionType()) { 664 - case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE: 665 - $update_xaction = $xaction; 666 - break; 667 - } 668 - } 669 - 670 682 if ($update_xaction) { 671 - $diff = $this->requireDiff($update_xaction->getNewValue(), true); 672 - 673 683 $body->addTextSection( 674 684 pht('AFFECTED FILES'), 675 685 $this->renderAffectedFilesForMail($diff));
+1 -1
src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php
··· 307 307 $content = phabricator_form( 308 308 $this->getUser(), 309 309 array( 310 - 'action' => '#toc', 310 + 'action' => '/D'.$revision_id.'#toc', 311 311 ), 312 312 array( 313 313 $table,