Page MenuHomePhorge

No OneTemporary

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

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)

Event Timeline