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

Allow Git and Mercurial repositories to be cloned with names in the URI

Summary:
Ref T4175. This allows these URIs to all be valid for Git and Mercurial:

/diffusion/X/
/diffusion/X/anything.git
/diffusion/X/anything/

This mostly already works, it just needed a few tweaks.

Test Plan: Cloned git and hg working copies using HTTP and SSH.

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T4175

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

+63 -12
+4 -6
src/applications/diffusion/controller/DiffusionRepositoryController.php
··· 551 551 switch ($repository->getVersionControlSystem()) { 552 552 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 553 553 $command = csprintf( 554 - 'git clone %s %s', 555 - $uri, 556 - $repository->getCloneName()); 554 + 'git clone %s', 555 + $uri); 557 556 break; 558 557 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 559 558 $command = csprintf( 560 - 'hg clone %s %s', 561 - $uri, 562 - $repository->getCloneName()); 559 + 'hg clone %s', 560 + $uri); 563 561 break; 564 562 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 565 563 $command = csprintf(
+7 -1
src/applications/diffusion/controller/DiffusionRepositoryDefaultController.php
··· 6 6 // NOTE: This controller is just here to make sure we call 7 7 // willBeginExecution() on any /diffusion/X/ URI, so we can intercept 8 8 // `git`, `hg` and `svn` HTTP protocol requests. 9 - return new Aphront404Response(); 9 + 10 + // If we made it here, it's probably because the user copy-pasted a 11 + // clone URI with "/anything.git" at the end into their web browser. 12 + // Send them to the canonical repository URI. 13 + 14 + return id(new AphrontRedirectResponse()) 15 + ->setURI($this->getDiffusionRequest()->getRepository()->getURI()); 10 16 } 11 17 }
+28 -4
src/applications/diffusion/controller/DiffusionServeController.php
··· 51 51 if (!preg_match($regex, (string)$uri, $matches)) { 52 52 return null; 53 53 } 54 + 54 55 return $matches['callsign']; 55 56 } 56 57 ··· 244 245 switch ($repository->getVersionControlSystem()) { 245 246 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 246 247 $service = $request->getStr('service'); 247 - $path = $this->getRequestDirectoryPath(); 248 + $path = $this->getRequestDirectoryPath($repository); 248 249 // NOTE: Service names are the reverse of what you might expect, as they 249 250 // are from the point of view of the server. The main read service is 250 251 // "git-upload-pack", and the main write service is "git-receive-pack". ··· 282 283 PhabricatorUser $viewer) { 283 284 $request = $this->getRequest(); 284 285 285 - $request_path = $this->getRequestDirectoryPath(); 286 + $request_path = $this->getRequestDirectoryPath($repository); 286 287 $repository_root = $repository->getLocalPath(); 287 288 288 289 // Rebuild the query string to strip `__magic__` parameters and prevent ··· 351 352 return id(new DiffusionGitResponse())->setGitData($stdout); 352 353 } 353 354 354 - private function getRequestDirectoryPath() { 355 + private function getRequestDirectoryPath(PhabricatorRepository $repository) { 355 356 $request = $this->getRequest(); 356 357 $request_path = $request->getRequestURI()->getPath(); 357 - return preg_replace('@^/diffusion/[A-Z]+@', '', $request_path); 358 + $base_path = preg_replace('@^/diffusion/[A-Z]+@', '', $request_path); 359 + 360 + // For Git repositories, strip an optional directory component if it 361 + // isn't the name of a known Git resource. This allows users to clone 362 + // repositories as "/diffusion/X/anything.git", for example. 363 + if ($repository->isGit()) { 364 + $known = array( 365 + 'info', 366 + 'git-upload-pack', 367 + 'git-receive-pack', 368 + ); 369 + 370 + foreach ($known as $key => $path) { 371 + $known[$key] = preg_quote($path, '@'); 372 + } 373 + 374 + $known = implode('|', $known); 375 + 376 + if (preg_match('@^/([^/]+)/('.$known.')(/|$)@', $base_path)) { 377 + $base_path = preg_replace('@^/([^/]+)@', '', $base_path); 378 + } 379 + } 380 + 381 + return $base_path; 358 382 } 359 383 360 384 private function authenticateHTTPRepositoryUser(
+9
src/applications/repository/data/PhabricatorRepositoryURINormalizer.php
··· 108 108 break; 109 109 } 110 110 111 + // If this is a Phabricator URI, strip it down to the callsign. We mutably 112 + // allow you to clone repositories as "/diffusion/X/anything.git", for 113 + // example. 114 + 115 + $matches = null; 116 + if (preg_match('@^(diffusion/[A-Z]+)@', $path, $matches)) { 117 + $path = $matches[1]; 118 + } 119 + 111 120 return $path; 112 121 } 113 122
+2
src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php
··· 16 16 'user@domain.com:path/repo/' => 'path/repo', 17 17 'file:///path/to/local/repo.git' => 'path/to/local/repo', 18 18 '/path/to/local/repo.git' => 'path/to/local/repo', 19 + 'ssh://something.com/diffusion/X/anything.git' => 'diffusion/X', 20 + 'ssh://something.com/diffusion/X/' => 'diffusion/X', 19 21 ); 20 22 21 23 $type_git = PhabricatorRepositoryURINormalizer::TYPE_GIT;
+13 -1
src/applications/repository/storage/PhabricatorRepository.php
··· 833 833 $uri->setProtocol('ssh'); 834 834 } 835 835 836 + if ($this->isGit()) { 837 + $uri->setPath($uri->getPath().$this->getCloneName().'.git'); 838 + } else if ($this->isHg()) { 839 + $uri->setPath($uri->getPath().$this->getCloneName().'/'); 840 + } 841 + 836 842 $ssh_user = PhabricatorEnv::getEnvConfig('diffusion.ssh-user'); 837 843 if ($ssh_user) { 838 844 $uri->setUser($ssh_user); ··· 861 867 return null; 862 868 } 863 869 864 - 865 870 $uri = PhabricatorEnv::getProductionURI($this->getURI()); 871 + $uri = new PhutilURI($uri); 872 + 873 + if ($this->isGit()) { 874 + $uri->setPath($uri->getPath().$this->getCloneName().'.git'); 875 + } else if ($this->isHg()) { 876 + $uri->setPath($uri->getPath().$this->getCloneName().'/'); 877 + } 866 878 867 879 return $uri; 868 880 }