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

Support ID-based repository URIs, and canonicalize repository URIs

Summary:
Ref T4245. Make `/diffusion/123/` work, but redirect the user to `/diffusion/XYZ/` if the repository has a callsign.

(Right now, every repository has a callsign, so this always redirects.)

Also redirect `/R123:abcdef` if the repository has a callsign.

Also also, move the Pull garbage collector somewhere more sensible.

Test Plan:
- Added test coverage.
- Visited `/diffusion/1/`, was redirected.
- Visited `/diffusion/R1:abcdef`, was redirected.
- Browsed Diffusion normally.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4245

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

+113 -4
+1 -1
src/__phutil_library_map__.php
··· 689 689 'DiffusionPreCommitRefRepositoryHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefRepositoryHeraldField.php', 690 690 'DiffusionPreCommitRefRepositoryProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefRepositoryProjectsHeraldField.php', 691 691 'DiffusionPreCommitRefTypeHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefTypeHeraldField.php', 692 - 'DiffusionPullEventGarbageCollector' => 'applications/diffusion/DiffusionPullEventGarbageCollector.php', 692 + 'DiffusionPullEventGarbageCollector' => 'applications/diffusion/garbagecollector/DiffusionPullEventGarbageCollector.php', 693 693 'DiffusionPushCapability' => 'applications/diffusion/capability/DiffusionPushCapability.php', 694 694 'DiffusionPushEventViewController' => 'applications/diffusion/controller/DiffusionPushEventViewController.php', 695 695 'DiffusionPushLogController' => 'applications/diffusion/controller/DiffusionPushLogController.php',
src/applications/diffusion/DiffusionPullEventGarbageCollector.php src/applications/diffusion/garbagecollector/DiffusionPullEventGarbageCollector.php
+8 -3
src/applications/diffusion/application/PhabricatorDiffusionApplication.php
··· 64 64 '(?:query/(?P<queryKey>[^/]+)/)?' => 'DiffusionPushLogListController', 65 65 'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController', 66 66 ), 67 - '(?P<repositoryCallsign>[A-Z]+)/' => array( 67 + '(?:'. 68 + '(?P<repositoryCallsign>[A-Z]+)'. 69 + '|'. 70 + '(?P<repositoryID>[1-9]\d*)'. 71 + ')/' => array( 68 72 '' => 'DiffusionRepositoryController', 69 73 70 74 'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController', ··· 115 119 // catch-all for serving repositories over HTTP. We must accept 116 120 // requests without the trailing "/" because SVN commands don't 117 121 // necessarily include it. 118 - '(?P<repositoryCallsign>[A-Z]+)(?:/.*)?' => 119 - 'DiffusionRepositoryDefaultController', 122 + '(?:(?P<repositoryCallsign>[A-Z]+)|(?P<repositoryID>[1-9]\d*))'. 123 + '(?:/.*)?' 124 + => 'DiffusionRepositoryDefaultController', 120 125 121 126 'inline/' => array( 122 127 'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
+14
src/applications/diffusion/controller/DiffusionController.php
··· 64 64 return new Aphront404Response(); 65 65 } 66 66 67 + // If the client is making a request like "/diffusion/1/...", but the 68 + // repository has a different canonical path like "/diffusion/XYZ/...", 69 + // redirect them to the canonical path. 70 + 71 + $request_path = $request->getPath(); 72 + $repository = $drequest->getRepository(); 73 + 74 + $canonical_path = $repository->getCanonicalPath($request_path); 75 + if ($canonical_path !== null) { 76 + if ($canonical_path != $request_path) { 77 + return id(new AphrontRedirectResponse())->setURI($canonical_path); 78 + } 79 + } 80 + 67 81 $this->diffusionRequest = $drequest; 68 82 69 83 return null;
+49
src/applications/repository/storage/PhabricatorRepository.php
··· 687 687 return "/r{$callsign}{$identifier}"; 688 688 } 689 689 690 + public function getCanonicalPath($request_path) { 691 + $standard_pattern = 692 + '(^'. 693 + '(?P<prefix>/diffusion/)'. 694 + '(?P<identifier>[^/]+)'. 695 + '(?P<suffix>(?:/.*)?)'. 696 + '\z)'; 697 + 698 + $matches = null; 699 + if (preg_match($standard_pattern, $request_path, $matches)) { 700 + $prefix = $matches['prefix']; 701 + 702 + $callsign = $this->getCallsign(); 703 + if ($callsign) { 704 + $identifier = $callsign; 705 + } else { 706 + $identifier = $this->getID(); 707 + } 708 + 709 + $suffix = $matches['suffix']; 710 + if (!strlen($suffix)) { 711 + $suffix = '/'; 712 + } 713 + 714 + return $prefix.$identifier.$suffix; 715 + } 716 + 717 + $commit_pattern = 718 + '(^'. 719 + '(?P<prefix>/)'. 720 + '(?P<monogram>'. 721 + '(?:'. 722 + 'r(?P<repositoryCallsign>[A-Z]+)'. 723 + '|'. 724 + 'R(?P<repositoryID>[1-9]\d*):'. 725 + ')'. 726 + '(?P<commit>[a-f0-9]+)'. 727 + ')'. 728 + '\z)'; 729 + 730 + $matches = null; 731 + if (preg_match($commit_pattern, $request_path, $matches)) { 732 + $commit = $matches['commit']; 733 + return $this->getCommitURI($commit); 734 + } 735 + 736 + return null; 737 + } 738 + 690 739 public function generateURI(array $params) { 691 740 $req_branch = false; 692 741 $req_commit = false;
+41
src/applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php
··· 9 9 ); 10 10 } 11 11 12 + public function testRepositoryURICanonicalization() { 13 + $repo = id(new PhabricatorRepository()) 14 + ->makeEphemeral() 15 + ->setID(123); 16 + 17 + $tests = array( 18 + '/diffusion/123' => '/diffusion/123/', 19 + '/diffusion/123/' => '/diffusion/123/', 20 + '/diffusion/123/browse/master/' => '/diffusion/123/browse/master/', 21 + '/kangaroo/' => null, 22 + ); 23 + 24 + foreach ($tests as $input => $expect) { 25 + $this->assertEqual( 26 + $expect, 27 + $repo->getCanonicalPath($input), 28 + pht('Canonical Path (ID, No Callsign): %s', $input)); 29 + } 30 + 31 + $repo->setCallsign('XYZ'); 32 + 33 + $tests = array( 34 + '/diffusion/123' => '/diffusion/XYZ/', 35 + '/diffusion/123/' => '/diffusion/XYZ/', 36 + '/diffusion/123/browse/master/' => '/diffusion/XYZ/browse/master/', 37 + '/diffusion/XYZ' => '/diffusion/XYZ/', 38 + '/diffusion/XYZ/' => '/diffusion/XYZ/', 39 + '/diffusion/XYZ/browse/master/' => '/diffusion/XYZ/browse/master/', 40 + '/diffusion/ABC/' => '/diffusion/XYZ/', 41 + '/kangaroo/' => null, 42 + '/R1:abcdef' => '/rXYZabcdef', 43 + ); 44 + 45 + foreach ($tests as $input => $expect) { 46 + $this->assertEqual( 47 + $expect, 48 + $repo->getCanonicalPath($input), 49 + pht('Canonical Path (ID, Callsign): %s', $input)); 50 + } 51 + } 52 + 12 53 public function testURIGeneration() { 13 54 $svn = PhabricatorRepositoryType::REPOSITORY_TYPE_SVN; 14 55 $git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;