mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 11:30:55 +01:00
Support slightly prettier repository URIs in Diffusion
Summary: Fixes T4245. When a repository has a short name, use `/source/shortname/` as its primary URI. Test Plan: - Cloned Git repositories from shortnames via HTTP and SSH. - Cloned Mercurial repositories from shortnames via HTTP and SSH. - Cloned Subversion repositories from shortnames via SSH. - Browsed Git, Mercurial and Subversion repositories. - Added and removed short names to various repositories. Reviewers: chad Reviewed By: chad Maniphest Tasks: T4245 Differential Revision: https://secure.phabricator.com/D16851
This commit is contained in:
parent
c9e140e283
commit
6a62fca950
11 changed files with 110 additions and 100 deletions
|
@ -46,30 +46,9 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
return array(
|
$repository_routes = array(
|
||||||
'/(?:'.
|
'/' => array(
|
||||||
'r(?P<repositoryCallsign>[A-Z]+)'.
|
|
||||||
'|'.
|
|
||||||
'R(?P<repositoryID>[1-9]\d*):'.
|
|
||||||
')(?P<commit>[a-f0-9]+)'
|
|
||||||
=> 'DiffusionCommitController',
|
|
||||||
|
|
||||||
'/diffusion/' => array(
|
|
||||||
$this->getQueryRoutePattern()
|
|
||||||
=> 'DiffusionRepositoryListController',
|
|
||||||
$this->getEditRoutePattern('edit/') =>
|
|
||||||
'DiffusionRepositoryEditController',
|
|
||||||
'pushlog/' => array(
|
|
||||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DiffusionPushLogListController',
|
|
||||||
'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController',
|
|
||||||
),
|
|
||||||
'(?:'.
|
|
||||||
'(?P<repositoryCallsign>[A-Z]+)'.
|
|
||||||
'|'.
|
|
||||||
'(?P<repositoryID>[1-9]\d*)'.
|
|
||||||
')/' => array(
|
|
||||||
'' => 'DiffusionRepositoryController',
|
'' => 'DiffusionRepositoryController',
|
||||||
|
|
||||||
'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController',
|
'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController',
|
||||||
'change/(?P<dblob>.*)' => 'DiffusionChangeController',
|
'change/(?P<dblob>.*)' => 'DiffusionChangeController',
|
||||||
'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
|
'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
|
||||||
|
@ -107,13 +86,35 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
||||||
'pathtree/(?P<dblob>.*)' => 'DiffusionPathTreeController',
|
'pathtree/(?P<dblob>.*)' => 'DiffusionPathTreeController',
|
||||||
),
|
),
|
||||||
|
|
||||||
// NOTE: This must come after the rule above; it just gives us a
|
// NOTE: This must come after the rules above; it just gives us a
|
||||||
// catch-all for serving repositories over HTTP. We must accept
|
// catch-all for serving repositories over HTTP. We must accept requests
|
||||||
// requests without the trailing "/" because SVN commands don't
|
// without the trailing "/" because SVN commands don't necessarily
|
||||||
// necessarily include it.
|
// include it.
|
||||||
'(?:(?P<repositoryCallsign>[A-Z]+)|(?P<repositoryID>[1-9]\d*))'.
|
'(?:/.*)?' => 'DiffusionRepositoryDefaultController',
|
||||||
'(?:/.*)?'
|
);
|
||||||
=> 'DiffusionRepositoryDefaultController',
|
|
||||||
|
return array(
|
||||||
|
'/(?:'.
|
||||||
|
'r(?P<repositoryCallsign>[A-Z]+)'.
|
||||||
|
'|'.
|
||||||
|
'R(?P<repositoryID>[1-9]\d*):'.
|
||||||
|
')(?P<commit>[a-f0-9]+)'
|
||||||
|
=> 'DiffusionCommitController',
|
||||||
|
|
||||||
|
'/source/(?P<repositoryShortName>[^/.]+)(?P<dotgit>\.git)?'
|
||||||
|
=> $repository_routes,
|
||||||
|
|
||||||
|
'/diffusion/' => array(
|
||||||
|
$this->getQueryRoutePattern()
|
||||||
|
=> 'DiffusionRepositoryListController',
|
||||||
|
$this->getEditRoutePattern('edit/') =>
|
||||||
|
'DiffusionRepositoryEditController',
|
||||||
|
'pushlog/' => array(
|
||||||
|
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DiffusionPushLogListController',
|
||||||
|
'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController',
|
||||||
|
),
|
||||||
|
'(?P<repositoryCallsign>[A-Z]+)' => $repository_routes,
|
||||||
|
'(?P<repositoryID>[1-9]\d*)' => $repository_routes,
|
||||||
|
|
||||||
'inline/' => array(
|
'inline/' => array(
|
||||||
'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
|
'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
|
||||||
|
|
|
@ -90,6 +90,11 @@ abstract class DiffusionController extends PhabricatorController {
|
||||||
protected function getRepositoryIdentifierFromRequest(
|
protected function getRepositoryIdentifierFromRequest(
|
||||||
AphrontRequest $request) {
|
AphrontRequest $request) {
|
||||||
|
|
||||||
|
$short_name = $request->getURIData('repositoryShortName');
|
||||||
|
if (strlen($short_name)) {
|
||||||
|
return $short_name;
|
||||||
|
}
|
||||||
|
|
||||||
$identifier = $request->getURIData('repositoryCallsign');
|
$identifier = $request->getURIData('repositoryCallsign');
|
||||||
if (strlen($identifier)) {
|
if (strlen($identifier)) {
|
||||||
return $identifier;
|
return $identifier;
|
||||||
|
|
|
@ -16,6 +16,7 @@ final class DiffusionLastModifiedController extends DiffusionController {
|
||||||
$drequest = $this->getDiffusionRequest();
|
$drequest = $this->getDiffusionRequest();
|
||||||
|
|
||||||
$paths = $request->getStr('paths');
|
$paths = $request->getStr('paths');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$paths = phutil_json_decode($paths);
|
$paths = phutil_json_decode($paths);
|
||||||
} catch (PhutilJSONParserException $ex) {
|
} catch (PhutilJSONParserException $ex) {
|
||||||
|
|
|
@ -88,6 +88,13 @@ final class DiffusionServeController extends DiffusionController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the request was for a path like "/source/libphutil.git" but the
|
||||||
|
// repository is not a Git repository, reject the request.
|
||||||
|
$type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
|
||||||
|
if ($request->getURIData('dotgit') && ($vcs !== $type_git)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return $vcs;
|
return $vcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +614,9 @@ final class DiffusionServeController extends DiffusionController {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$request_path = $request->getRequestURI()->getPath();
|
$request_path = $request->getRequestURI()->getPath();
|
||||||
|
|
||||||
$info = PhabricatorRepository::parseRepositoryServicePath($request_path);
|
$info = PhabricatorRepository::parseRepositoryServicePath(
|
||||||
|
$request_path,
|
||||||
|
$repository->getVersionControlSystem());
|
||||||
$base_path = $info['path'];
|
$base_path = $info['path'];
|
||||||
|
|
||||||
// For Git repositories, strip an optional directory component if it
|
// For Git repositories, strip an optional directory component if it
|
||||||
|
|
|
@ -15,7 +15,9 @@ final class DiffusionGitLFSAuthenticateWorkflow
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function identifyRepository() {
|
protected function identifyRepository() {
|
||||||
return $this->loadRepositoryWithPath($this->getLFSPathArgument());
|
return $this->loadRepositoryWithPath(
|
||||||
|
$this->getLFSPathArgument(),
|
||||||
|
PhabricatorRepositoryType::REPOSITORY_TYPE_GIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getLFSPathArgument() {
|
private function getLFSPathArgument() {
|
||||||
|
|
|
@ -17,7 +17,9 @@ abstract class DiffusionGitSSHWorkflow
|
||||||
protected function identifyRepository() {
|
protected function identifyRepository() {
|
||||||
$args = $this->getArgs();
|
$args = $this->getArgs();
|
||||||
$path = head($args->getArg('dir'));
|
$path = head($args->getArg('dir'));
|
||||||
return $this->loadRepositoryWithPath($path);
|
return $this->loadRepositoryWithPath(
|
||||||
|
$path,
|
||||||
|
PhabricatorRepositoryType::REPOSITORY_TYPE_GIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function waitForGitClient() {
|
protected function waitForGitClient() {
|
||||||
|
|
|
@ -27,7 +27,9 @@ final class DiffusionMercurialServeSSHWorkflow
|
||||||
protected function identifyRepository() {
|
protected function identifyRepository() {
|
||||||
$args = $this->getArgs();
|
$args = $this->getArgs();
|
||||||
$path = $args->getArg('repository');
|
$path = $args->getArg('repository');
|
||||||
return $this->loadRepositoryWithPath($path);
|
return $this->loadRepositoryWithPath(
|
||||||
|
$path,
|
||||||
|
PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function executeRepositoryOperations() {
|
protected function executeRepositoryOperations() {
|
||||||
|
|
|
@ -161,18 +161,19 @@ abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadRepositoryWithPath($path) {
|
protected function loadRepositoryWithPath($path, $vcs) {
|
||||||
$viewer = $this->getUser();
|
$viewer = $this->getUser();
|
||||||
|
|
||||||
$info = PhabricatorRepository::parseRepositoryServicePath($path);
|
$info = PhabricatorRepository::parseRepositoryServicePath($path, $vcs);
|
||||||
if ($info === null) {
|
if ($info === null) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
pht(
|
pht(
|
||||||
'Unrecognized repository path "%s". Expected a path like "%s" '.
|
'Unrecognized repository path "%s". Expected a path like "%s", '.
|
||||||
'or "%s".',
|
'"%s", or "%s".',
|
||||||
$path,
|
$path,
|
||||||
'/diffusion/X/',
|
'/diffusion/X/',
|
||||||
'/diffusion/123/'));
|
'/diffusion/123/',
|
||||||
|
'/source/thaumaturgy.git'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$identifier = $info['identifier'];
|
$identifier = $info['identifier'];
|
||||||
|
|
|
@ -117,7 +117,9 @@ final class DiffusionSubversionServeSSHWorkflow
|
||||||
$uri = $struct[2]['value'];
|
$uri = $struct[2]['value'];
|
||||||
$path = $this->getPathFromSubversionURI($uri);
|
$path = $this->getPathFromSubversionURI($uri);
|
||||||
|
|
||||||
return $this->loadRepositoryWithPath($path);
|
return $this->loadRepositoryWithPath(
|
||||||
|
$path,
|
||||||
|
PhabricatorRepositoryType::REPOSITORY_TYPE_SVN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -563,6 +563,11 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getURI() {
|
public function getURI() {
|
||||||
|
$short_name = $this->getRepositorySlug();
|
||||||
|
if (strlen($short_name)) {
|
||||||
|
return "/source/{$short_name}/";
|
||||||
|
}
|
||||||
|
|
||||||
$callsign = $this->getCallsign();
|
$callsign = $this->getCallsign();
|
||||||
if (strlen($callsign)) {
|
if (strlen($callsign)) {
|
||||||
return "/diffusion/{$callsign}/";
|
return "/diffusion/{$callsign}/";
|
||||||
|
@ -573,7 +578,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPathURI($path) {
|
public function getPathURI($path) {
|
||||||
return $this->getURI().$path;
|
return $this->getURI().ltrim($path, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCommitURI($identifier) {
|
public function getCommitURI($identifier) {
|
||||||
|
@ -586,14 +591,22 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
return "/R{$id}:{$identifier}";
|
return "/R{$id}:{$identifier}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function parseRepositoryServicePath($request_path) {
|
public static function parseRepositoryServicePath($request_path, $vcs) {
|
||||||
|
|
||||||
// NOTE: In Mercurial over SSH, the path will begin without a leading "/",
|
// NOTE: In Mercurial over SSH, the path will begin without a leading "/",
|
||||||
// so we're matching it optionally.
|
// so we're matching it optionally.
|
||||||
|
|
||||||
|
if ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
|
||||||
|
$maybe_git = '(?:\\.git)?';
|
||||||
|
} else {
|
||||||
|
$maybe_git = null;
|
||||||
|
}
|
||||||
|
|
||||||
$patterns = array(
|
$patterns = array(
|
||||||
'(^'.
|
'(^'.
|
||||||
'(?P<base>/?diffusion/(?P<identifier>[A-Z]+|[0-9]\d*))'.
|
'(?P<base>/?(?:diffusion|source)/(?P<identifier>[^/.]+))'.
|
||||||
'(?P<path>(?:/.*)?)'.
|
$maybe_git.
|
||||||
|
'(?P<path>(?:/|.*)?)'.
|
||||||
'\z)',
|
'\z)',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -624,28 +637,15 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
public function getCanonicalPath($request_path) {
|
public function getCanonicalPath($request_path) {
|
||||||
$standard_pattern =
|
$standard_pattern =
|
||||||
'(^'.
|
'(^'.
|
||||||
'(?P<prefix>/diffusion/)'.
|
'(?P<prefix>/(?:diffusion|source)/)'.
|
||||||
'(?P<identifier>[^/]+)'.
|
'(?P<identifier>[^/]+)'.
|
||||||
'(?P<suffix>(?:/.*)?)'.
|
'(?P<suffix>(?:/.*)?)'.
|
||||||
'\z)';
|
'\z)';
|
||||||
|
|
||||||
$matches = null;
|
$matches = null;
|
||||||
if (preg_match($standard_pattern, $request_path, $matches)) {
|
if (preg_match($standard_pattern, $request_path, $matches)) {
|
||||||
$prefix = $matches['prefix'];
|
|
||||||
|
|
||||||
$callsign = $this->getCallsign();
|
|
||||||
if ($callsign) {
|
|
||||||
$identifier = $callsign;
|
|
||||||
} else {
|
|
||||||
$identifier = $this->getID();
|
|
||||||
}
|
|
||||||
|
|
||||||
$suffix = $matches['suffix'];
|
$suffix = $matches['suffix'];
|
||||||
if (!strlen($suffix)) {
|
return $this->getPathURI($suffix);
|
||||||
$suffix = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $prefix.$identifier.$suffix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$commit_pattern =
|
$commit_pattern =
|
||||||
|
@ -724,18 +724,6 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
return $this->getCommitURI($commit);
|
return $this->getCommitURI($commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$identifier = $this->getID();
|
|
||||||
|
|
||||||
$callsign = $this->getCallsign();
|
|
||||||
if ($callsign !== null) {
|
|
||||||
$identifier = $callsign;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen($identifier)) {
|
|
||||||
$identifier = phutil_escape_uri_path_component($identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen($path)) {
|
if (strlen($path)) {
|
||||||
$path = ltrim($path, '/');
|
$path = ltrim($path, '/');
|
||||||
$path = str_replace(array(';', '$'), array(';;', '$$'), $path);
|
$path = str_replace(array(';', '$'), array(';;', '$$'), $path);
|
||||||
|
@ -766,13 +754,13 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
case 'lint':
|
case 'lint':
|
||||||
case 'pathtree':
|
case 'pathtree':
|
||||||
case 'refs':
|
case 'refs':
|
||||||
$uri = "/diffusion/{$identifier}/{$action}/{$path}{$commit}{$line}";
|
$uri = $this->getPathURI("/{$action}/{$path}{$commit}{$line}");
|
||||||
break;
|
break;
|
||||||
case 'branch':
|
case 'branch':
|
||||||
if (strlen($path)) {
|
if (strlen($path)) {
|
||||||
$uri = "/diffusion/{$identifier}/repository/{$path}";
|
$uri = $this->getPathURI("/repository/{$path}");
|
||||||
} else {
|
} else {
|
||||||
$uri = "/diffusion/{$identifier}/";
|
$uri = $this->getPathURI();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'external':
|
case 'external':
|
||||||
|
@ -2108,9 +2096,6 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
$has_callsign = ($this->getCallsign() !== null);
|
$has_callsign = ($this->getCallsign() !== null);
|
||||||
$has_shortname = ($this->getRepositorySlug() !== null);
|
$has_shortname = ($this->getRepositorySlug() !== null);
|
||||||
|
|
||||||
// TODO: For now, never enable these because they don't work yet.
|
|
||||||
$has_shortname = false;
|
|
||||||
|
|
||||||
$identifier_map = array(
|
$identifier_map = array(
|
||||||
PhabricatorRepositoryURI::BUILTIN_IDENTIFIER_CALLSIGN => $has_callsign,
|
PhabricatorRepositoryURI::BUILTIN_IDENTIFIER_CALLSIGN => $has_callsign,
|
||||||
PhabricatorRepositoryURI::BUILTIN_IDENTIFIER_SHORTNAME => $has_shortname,
|
PhabricatorRepositoryURI::BUILTIN_IDENTIFIER_SHORTNAME => $has_shortname,
|
||||||
|
|
|
@ -125,8 +125,8 @@ final class PhabricatorRepositoryURI
|
||||||
$other_uris = $repository->getURIs();
|
$other_uris = $repository->getURIs();
|
||||||
|
|
||||||
$identifier_value = array(
|
$identifier_value = array(
|
||||||
self::BUILTIN_IDENTIFIER_CALLSIGN => 3,
|
self::BUILTIN_IDENTIFIER_SHORTNAME => 3,
|
||||||
self::BUILTIN_IDENTIFIER_SHORTNAME => 2,
|
self::BUILTIN_IDENTIFIER_CALLSIGN => 2,
|
||||||
self::BUILTIN_IDENTIFIER_ID => 1,
|
self::BUILTIN_IDENTIFIER_ID => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue