Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2890786
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
8 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/resources/sql/autopatches/20191028.uriindex.01.rebuild.php b/resources/sql/autopatches/20191028.uriindex.01.rebuild.php
new file mode 100644
index 0000000000..c9bd3d97ca
--- /dev/null
+++ b/resources/sql/autopatches/20191028.uriindex.01.rebuild.php
@@ -0,0 +1,4 @@
+<?php
+
+PhabricatorRebuildIndexesWorker::rebuildObjectsWithQuery(
+ 'PhabricatorRepositoryQuery');
diff --git a/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php b/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php
index a29d110a67..935d78fea5 100644
--- a/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php
+++ b/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php
@@ -1,140 +1,165 @@
<?php
/**
* Normalize repository URIs. For example, these URIs are generally equivalent
* and all point at the same repository:
*
* ssh://user@host/repo
* ssh://user@host/repo/
* ssh://user@host:22/repo
* user@host:/repo
* ssh://user@host/repo.git
*
* This class can be used to normalize URIs like this, in order to detect
* alternate spellings of the same repository URI. In particular, the
* @{method:getNormalizedPath} method will return:
*
* repo
*
* ...for all of these URIs. Generally, usage looks like this:
*
* $norm_a = new PhabricatorRepositoryURINormalizer($type, $uri_a);
* $norm_b = new PhabricatorRepositoryURINormalizer($type, $uri_b);
*
* if ($norm_a->getNormalizedPath() == $norm_b->getNormalizedPath()) {
* // URIs appear to point at the same repository.
* } else {
* // URIs are very unlikely to be the same repository.
* }
*
* Because a repository can be hosted at arbitrarily many arbitrary URIs, there
* is no way to completely prevent false negatives by only examining URIs
* (that is, repositories with totally different URIs could really be the same).
* However, normalization is relatively aggressive and false negatives should
* be rare: if normalization says two URIs are different repositories, they
* probably are.
*
* @task normal Normalizing URIs
*/
final class PhabricatorRepositoryURINormalizer extends Phobject {
const TYPE_GIT = 'git';
const TYPE_SVN = 'svn';
const TYPE_MERCURIAL = 'hg';
private $type;
private $uri;
public function __construct($type, $uri) {
switch ($type) {
case self::TYPE_GIT:
case self::TYPE_SVN:
case self::TYPE_MERCURIAL:
break;
default:
throw new Exception(pht('Unknown URI type "%s"!', $type));
}
$this->type = $type;
$this->uri = $uri;
}
public static function getAllURITypes() {
return array(
self::TYPE_GIT,
self::TYPE_SVN,
self::TYPE_MERCURIAL,
);
}
/* -( Normalizing URIs )--------------------------------------------------- */
/**
* @task normal
*/
public function getPath() {
switch ($this->type) {
case self::TYPE_GIT:
$uri = new PhutilURI($this->uri);
return $uri->getPath();
case self::TYPE_SVN:
case self::TYPE_MERCURIAL:
$uri = new PhutilURI($this->uri);
if ($uri->getProtocol()) {
return $uri->getPath();
}
return $this->uri;
}
}
public function getNormalizedURI() {
return $this->getNormalizedDomain().'/'.$this->getNormalizedPath();
}
/**
* @task normal
*/
public function getNormalizedPath() {
$path = $this->getPath();
$path = trim($path, '/');
switch ($this->type) {
case self::TYPE_GIT:
$path = preg_replace('/\.git$/', '', $path);
break;
case self::TYPE_SVN:
case self::TYPE_MERCURIAL:
break;
}
// If this is a Phabricator URI, strip it down to the callsign. We mutably
// allow you to clone repositories as "/diffusion/X/anything.git", for
// example.
$matches = null;
if (preg_match('@^(diffusion/(?:[A-Z]+|\d+))@', $path, $matches)) {
$path = $matches[1];
}
return $path;
}
public function getNormalizedDomain() {
$domain = null;
$uri = new PhutilURI($this->uri);
$domain = $uri->getDomain();
if (!strlen($domain)) {
- $domain = '<void>';
+ return '<void>';
}
- return phutil_utf8_strtolower($domain);
+ $domain = phutil_utf8_strtolower($domain);
+
+ // See T13435. If the domain for a repository URI is same as the install
+ // base URI, store it as a "<base-uri>" token instead of the actual domain
+ // so that the index does not fall out of date if the install moves.
+
+ $base_uri = PhabricatorEnv::getURI('/');
+ $base_uri = new PhutilURI($base_uri);
+ $base_domain = $base_uri->getDomain();
+ $base_domain = phutil_utf8_strtolower($base_domain);
+ if ($domain === $base_domain) {
+ return '<base-uri>';
+ }
+
+ // Likewise, store a token for the "SSH Host" domain so it can be changed
+ // without requiring an index rebuild.
+
+ $ssh_host = PhabricatorEnv::getEnvConfig('diffusion.ssh-host');
+ if (strlen($ssh_host)) {
+ $ssh_host = phutil_utf8_strtolower($ssh_host);
+ if ($domain === $ssh_host) {
+ return '<ssh-host>';
+ }
+ }
+
+ return $domain;
}
}
diff --git a/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php b/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php
index 81dd735562..8ab54a23a4 100644
--- a/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php
+++ b/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php
@@ -1,51 +1,81 @@
<?php
final class PhabricatorRepositoryURINormalizerTestCase
extends PhabricatorTestCase {
public function testGitURINormalizer() {
$cases = array(
'ssh://user@domain.com/path.git' => 'path',
'https://user@domain.com/path.git' => 'path',
'git@domain.com:path.git' => 'path',
'ssh://user@gitserv002.com/path.git' => 'path',
'ssh://htaft@domain.com/path.git' => 'path',
'ssh://user@domain.com/bananas.git' => 'bananas',
'git@domain.com:bananas.git' => 'bananas',
'user@domain.com:path/repo' => 'path/repo',
'user@domain.com:path/repo/' => 'path/repo',
'file:///path/to/local/repo.git' => 'path/to/local/repo',
'/path/to/local/repo.git' => 'path/to/local/repo',
'ssh://something.com/diffusion/X/anything.git' => 'diffusion/X',
'ssh://something.com/diffusion/X/' => 'diffusion/X',
);
$type_git = PhabricatorRepositoryURINormalizer::TYPE_GIT;
foreach ($cases as $input => $expect) {
$normal = new PhabricatorRepositoryURINormalizer($type_git, $input);
$this->assertEqual(
$expect,
$normal->getNormalizedPath(),
pht('Normalized Git path for "%s".', $input));
}
}
+ public function testDomainURINormalizer() {
+ $base_domain = 'base.phabricator.example.com';
+ $ssh_domain = 'ssh.phabricator.example.com';
+
+ $env = PhabricatorEnv::beginScopedEnv();
+ $env->overrideEnvConfig('phabricator.base-uri', 'http://'.$base_domain);
+ $env->overrideEnvConfig('diffusion.ssh-host', $ssh_domain);
+
+ $cases = array(
+ '/' => '<void>',
+ '/path/to/local/repo.git' => '<void>',
+ 'ssh://user@domain.com/path.git' => 'domain.com',
+ 'ssh://user@DOMAIN.COM/path.git' => 'domain.com',
+ 'http://'.$base_domain.'/diffusion/X/' => '<base-uri>',
+ 'ssh://'.$ssh_domain.'/diffusion/X/' => '<ssh-host>',
+ 'git@'.$ssh_domain.':bananas.git' => '<ssh-host>',
+ );
+
+ $type_git = PhabricatorRepositoryURINormalizer::TYPE_GIT;
+
+ foreach ($cases as $input => $expect) {
+ $normal = new PhabricatorRepositoryURINormalizer($type_git, $input);
+
+ $this->assertEqual(
+ $expect,
+ $normal->getNormalizedDomain(),
+ pht('Normalized domain for "%s".', $input));
+ }
+ }
+
public function testSVNURINormalizer() {
$cases = array(
'file:///path/to/repo' => 'path/to/repo',
'file:///path/to/repo/' => 'path/to/repo',
);
$type_svn = PhabricatorRepositoryURINormalizer::TYPE_SVN;
foreach ($cases as $input => $expect) {
$normal = new PhabricatorRepositoryURINormalizer($type_svn, $input);
$this->assertEqual(
$expect,
$normal->getNormalizedPath(),
pht('Normalized SVN path for "%s".', $input));
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 14:06 (3 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1125350
Default Alt Text
(8 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment