diff --git a/resources/celerity/map.php b/resources/celerity/map.php index df11037696..d10f117847 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '0e3cf785', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => 'ba768cdb', + 'core.pkg.css' => 'da792a0f', 'core.pkg.js' => '845355f4', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '5c459f92', @@ -114,7 +114,7 @@ return array( 'rsrc/css/application/tokens/tokens.css' => 'ce5a50bd', 'rsrc/css/application/uiexample/example.css' => 'b4795059', 'rsrc/css/core/core.css' => '1b29ed61', - 'rsrc/css/core/remarkup.css' => 'c286eaef', + 'rsrc/css/core/remarkup.css' => '7d3ebc86', 'rsrc/css/core/syntax.css' => '548567f6', 'rsrc/css/core/z-index.css' => 'ac3bfcd4', 'rsrc/css/diviner/diviner-shared.css' => '4bd263b0', @@ -798,7 +798,7 @@ return array( 'phabricator-object-selector-css' => 'ee77366f', 'phabricator-phtize' => '2f1db1ed', 'phabricator-prefab' => '5793d835', - 'phabricator-remarkup-css' => 'c286eaef', + 'phabricator-remarkup-css' => '7d3ebc86', 'phabricator-search-results-css' => '9ea70ace', 'phabricator-shaped-request' => '995f5102', 'phabricator-slowvote-css' => '1694baed', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index fa3eaabe7a..41ae62ed5d 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4653,8 +4653,6 @@ phutil_register_library_map(array( 'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php', 'PhabricatorRepositoryURI' => 'applications/repository/storage/PhabricatorRepositoryURI.php', 'PhabricatorRepositoryURIIndex' => 'applications/repository/storage/PhabricatorRepositoryURIIndex.php', - 'PhabricatorRepositoryURINormalizer' => 'applications/repository/data/PhabricatorRepositoryURINormalizer.php', - 'PhabricatorRepositoryURINormalizerTestCase' => 'applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php', 'PhabricatorRepositoryURIPHIDType' => 'applications/repository/phid/PhabricatorRepositoryURIPHIDType.php', 'PhabricatorRepositoryURIQuery' => 'applications/repository/query/PhabricatorRepositoryURIQuery.php', 'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php', @@ -11407,8 +11405,6 @@ phutil_register_library_map(array( 'PhabricatorConduitResultInterface', ), 'PhabricatorRepositoryURIIndex' => 'PhabricatorRepositoryDAO', - 'PhabricatorRepositoryURINormalizer' => 'Phobject', - 'PhabricatorRepositoryURINormalizerTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryURIPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryURIQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase', diff --git a/src/applications/fact/daemon/PhabricatorFactDaemon.php b/src/applications/fact/daemon/PhabricatorFactDaemon.php index 29c7904547..4b4f7da368 100644 --- a/src/applications/fact/daemon/PhabricatorFactDaemon.php +++ b/src/applications/fact/daemon/PhabricatorFactDaemon.php @@ -6,7 +6,7 @@ final class PhabricatorFactDaemon extends PhabricatorDaemon { protected function run() { $this->setEngines(PhabricatorFactEngine::loadAllEngines()); - while (!$this->shouldExit()) { + do { PhabricatorCaches::destroyRequestCache(); $iterators = $this->getAllApplicationIterators(); @@ -14,9 +14,14 @@ final class PhabricatorFactDaemon extends PhabricatorDaemon { $this->processIteratorWithCursor($iterator_name, $iterator); } - $this->log(pht('Zzz...')); - $this->sleep(15); - } + $sleep_duration = 60; + + if ($this->shouldHibernate($sleep_duration)) { + break; + } + + $this->sleep($sleep_duration); + } while (!$this->shouldExit()); } public static function getAllApplicationIterators() { diff --git a/src/applications/harbormaster/storage/HarbormasterBuildable.php b/src/applications/harbormaster/storage/HarbormasterBuildable.php index aabfd49eb9..df8451d842 100644 --- a/src/applications/harbormaster/storage/HarbormasterBuildable.php +++ b/src/applications/harbormaster/storage/HarbormasterBuildable.php @@ -366,6 +366,10 @@ final class HarbormasterBuildable ->setKey('isManual') ->setType('bool') ->setDescription(pht('True if this is a manual buildable.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('uri') + ->setType('uri') + ->setDescription(pht('View URI for the buildable.')), ); } @@ -377,6 +381,7 @@ final class HarbormasterBuildable 'value' => $this->getBuildableStatus(), ), 'isManual' => (bool)$this->getIsManualBuildable(), + 'uri' => PhabricatorEnv::getURI($this->getURI()), ); } diff --git a/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php b/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php deleted file mode 100644 index 935d78fea5..0000000000 --- a/src/applications/repository/data/PhabricatorRepositoryURINormalizer.php +++ /dev/null @@ -1,165 +0,0 @@ -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)) { - return ''; - } - - $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 "" 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 ''; - } - - // 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 ''; - } - } - - return $domain; - } - - -} diff --git a/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php b/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php deleted file mode 100644 index 8ab54a23a4..0000000000 --- a/src/applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php +++ /dev/null @@ -1,81 +0,0 @@ - '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( - '/' => '', - '/path/to/local/repo.git' => '', - 'ssh://user@domain.com/path.git' => 'domain.com', - 'ssh://user@DOMAIN.COM/path.git' => 'domain.com', - 'http://'.$base_domain.'/diffusion/X/' => '', - 'ssh://'.$ssh_domain.'/diffusion/X/' => '', - 'git@'.$ssh_domain.':bananas.git' => '', - ); - - $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)); - } - } - -} diff --git a/src/applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php b/src/applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php index 2fc1abbf34..c3e4169b53 100644 --- a/src/applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php +++ b/src/applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php @@ -290,13 +290,13 @@ final class PhabricatorRepositoryDiscoveryEngine $remote_root = (string)($xml->entry[0]->repository[0]->root[0]); $expect_root = $repository->getSubversionPathURI(); - $normal_type_svn = PhabricatorRepositoryURINormalizer::TYPE_SVN; + $normal_type_svn = ArcanistRepositoryURINormalizer::TYPE_SVN; - $remote_normal = id(new PhabricatorRepositoryURINormalizer( + $remote_normal = id(new ArcanistRepositoryURINormalizer( $normal_type_svn, $remote_root))->getNormalizedPath(); - $expect_normal = id(new PhabricatorRepositoryURINormalizer( + $expect_normal = id(new ArcanistRepositoryURINormalizer( $normal_type_svn, $expect_root))->getNormalizedPath(); diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php index 21465393f7..9150c692b6 100644 --- a/src/applications/repository/query/PhabricatorRepositoryQuery.php +++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php @@ -689,10 +689,13 @@ final class PhabricatorRepositoryQuery // or an `svn+ssh` URI, we could deduce how to normalize it. However, this // would be more complicated and it's not clear if it matters in practice. - $types = PhabricatorRepositoryURINormalizer::getAllURITypes(); + $domain_map = PhabricatorRepositoryURI::getURINormalizerDomainMap(); + + $types = ArcanistRepositoryURINormalizer::getAllURITypes(); foreach ($this->uris as $uri) { foreach ($types as $type) { - $normalized_uri = new PhabricatorRepositoryURINormalizer($type, $uri); + $normalized_uri = new ArcanistRepositoryURINormalizer($type, $uri); + $normalized_uri->setDomainMap($domain_map); $normalized_uris[] = $normalized_uri->getNormalizedURI(); } } diff --git a/src/applications/repository/storage/PhabricatorRepositoryURI.php b/src/applications/repository/storage/PhabricatorRepositoryURI.php index 8b1de62dd6..98c08baa00 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryURI.php +++ b/src/applications/repository/storage/PhabricatorRepositoryURI.php @@ -196,19 +196,22 @@ final class PhabricatorRepositoryURI $map = array( PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => - PhabricatorRepositoryURINormalizer::TYPE_GIT, + ArcanistRepositoryURINormalizer::TYPE_GIT, PhabricatorRepositoryType::REPOSITORY_TYPE_SVN => - PhabricatorRepositoryURINormalizer::TYPE_SVN, + ArcanistRepositoryURINormalizer::TYPE_SVN, PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => - PhabricatorRepositoryURINormalizer::TYPE_MERCURIAL, + ArcanistRepositoryURINormalizer::TYPE_MERCURIAL, ); $type = $map[$vcs]; $display = (string)$this->getDisplayURI(); - $normal_uri = new PhabricatorRepositoryURINormalizer($type, $display); + $normalizer = new ArcanistRepositoryURINormalizer($type, $display); - return $normal_uri->getNormalizedURI(); + $domain_map = self::getURINormalizerDomainMap(); + $normalizer->setDomainMap($domain_map); + + return $normalizer->getNormalizedURI(); } public function getDisplayURI() { @@ -735,4 +738,27 @@ final class PhabricatorRepositoryURI return array(); } + public static function getURINormalizerDomainMap() { + $domain_map = array(); + + // See T13435. If the domain for a repository URI is same as the install + // base URI, store it as a "" 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(); + $domain_map[''] = $base_domain; + + // 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)) { + $domain_map[''] = $ssh_host; + } + + return $domain_map; + } + } diff --git a/src/docs/user/userguide/arcanist.diviner b/src/docs/user/userguide/arcanist.diviner index f6ccc3550f..e8d6bcd5ed 100644 --- a/src/docs/user/userguide/arcanist.diviner +++ b/src/docs/user/userguide/arcanist.diviner @@ -132,10 +132,13 @@ able to use: == Installing Tab Completion == -If you use `bash`, you can set up tab completion by adding something like this -to your `.bashrc`, `.profile` or similar: +If you use `bash`, you can set up tab completion by running this command: - source /path/to/arcanist/resources/shell/bash-completion + $ arc shell-complete + +This will install shell completion into your current shell. After installing, +you may need to start a new shell (or open a new terminal window) to pick up +the updated configuration. == Configuration == diff --git a/src/infrastructure/diff/prose/PhutilProseDifferenceEngine.php b/src/infrastructure/diff/prose/PhutilProseDifferenceEngine.php index 15af82fabd..a5494aa05f 100644 --- a/src/infrastructure/diff/prose/PhutilProseDifferenceEngine.php +++ b/src/infrastructure/diff/prose/PhutilProseDifferenceEngine.php @@ -148,7 +148,7 @@ final class PhutilProseDifferenceEngine extends Phobject { // whitespace at the end. $matches = null; - preg_match('/^(\s*)(.*?)(\s*)\z/', $result, $matches); + preg_match('/^(\s*)(.*?)(\s*)\z/s', $result, $matches); if (strlen($matches[1])) { $results[] = $matches[1]; diff --git a/src/infrastructure/diff/prose/__tests__/PhutilProseDiffTestCase.php b/src/infrastructure/diff/prose/__tests__/PhutilProseDiffTestCase.php index 88a64de620..823fef650a 100644 --- a/src/infrastructure/diff/prose/__tests__/PhutilProseDiffTestCase.php +++ b/src/infrastructure/diff/prose/__tests__/PhutilProseDiffTestCase.php @@ -30,6 +30,14 @@ final class PhutilProseDiffTestCase ), pht('Remove Paragraph')); + $this->assertProseParts( + 'xxx', + "xxxyyy\n.zzz", + array( + '= xxx', + "+ yyy\n.zzz", + ), + pht('Amend paragraph, and add paragraph starting with punctuation')); // Without smoothing, the alogorithm identifies that "shark" and "cat" // both contain the letter "a" and tries to express this as a very diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css index 6e1c4b3627..1688da31f0 100644 --- a/webroot/rsrc/css/core/remarkup.css +++ b/webroot/rsrc/css/core/remarkup.css @@ -86,6 +86,7 @@ padding: 1px 4px; border-radius: 3px; white-space: pre-wrap; + line-break: anywhere; } /* NOTE: You can currently produce this with [[link | `name`]]. Restore the