diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 83d7e1f9cc..bcc74a1c74 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -72,7 +72,7 @@ celerity_register_resource_map(array( ), 'aphront-form-view-css' => array( - 'uri' => '/res/c79fd668/rsrc/css/aphront/form-view.css', + 'uri' => '/res/16af59d8/rsrc/css/aphront/form-view.css', 'type' => 'css', 'requires' => array( @@ -1482,7 +1482,7 @@ celerity_register_resource_map(array( 'uri' => '/res/pkg/ac869011/typeahead.pkg.js', 'type' => 'js', ), - 70966590 => + 'f6422902' => array( 'name' => 'core.pkg.css', 'symbols' => @@ -1503,21 +1503,21 @@ celerity_register_resource_map(array( 13 => 'phabricator-remarkup-css', 14 => 'syntax-highlighting-css', ), - 'uri' => '/res/pkg/70966590/core.pkg.css', + 'uri' => '/res/pkg/f6422902/core.pkg.css', 'type' => 'css', ), ), 'reverse' => array( - 'aphront-crumbs-view-css' => '70966590', - 'aphront-dialog-view-css' => '70966590', - 'aphront-form-view-css' => '70966590', - 'aphront-list-filter-view-css' => '70966590', - 'aphront-panel-view-css' => '70966590', - 'aphront-side-nav-view-css' => '70966590', - 'aphront-table-view-css' => '70966590', - 'aphront-tokenizer-control-css' => '70966590', - 'aphront-typeahead-control-css' => '70966590', + 'aphront-crumbs-view-css' => 'f6422902', + 'aphront-dialog-view-css' => 'f6422902', + 'aphront-form-view-css' => 'f6422902', + 'aphront-list-filter-view-css' => 'f6422902', + 'aphront-panel-view-css' => 'f6422902', + 'aphront-side-nav-view-css' => 'f6422902', + 'aphront-table-view-css' => 'f6422902', + 'aphront-tokenizer-control-css' => 'f6422902', + 'aphront-typeahead-control-css' => 'f6422902', 'differential-changeset-view-css' => '7bf96a66', 'differential-core-view-css' => '7bf96a66', 'differential-revision-add-comment-css' => '7bf96a66', @@ -1554,13 +1554,13 @@ celerity_register_resource_map(array( 'javelin-util' => '3dbf4083', 'javelin-vector' => '3dbf4083', 'javelin-workflow' => '95c67dcd', - 'phabricator-core-buttons-css' => '70966590', - 'phabricator-core-css' => '70966590', - 'phabricator-directory-css' => '70966590', + 'phabricator-core-buttons-css' => 'f6422902', + 'phabricator-core-css' => 'f6422902', + 'phabricator-directory-css' => 'f6422902', 'phabricator-keyboard-shortcut' => '95c67dcd', 'phabricator-keyboard-shortcut-manager' => '95c67dcd', - 'phabricator-remarkup-css' => '70966590', - 'phabricator-standard-page-view' => '70966590', - 'syntax-highlighting-css' => '70966590', + 'phabricator-remarkup-css' => 'f6422902', + 'phabricator-standard-page-view' => 'f6422902', + 'syntax-highlighting-css' => 'f6422902', ), )); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index edd5b8790b..ea1f67ae29 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -575,6 +575,8 @@ phutil_register_library_map(array( 'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification', 'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive', 'PhabricatorRepositoryListController' => 'applications/repository/controller/list', + 'PhabricatorRepositoryMercurialPullDaemon' => 'applications/repository/daemon/mercurialpull', + 'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/pulllocal', 'PhabricatorRepositoryShortcut' => 'applications/repository/storage/shortcut', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/svn', 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn', @@ -1166,10 +1168,12 @@ phutil_register_library_map(array( 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', - 'PhabricatorRepositoryGitFetchDaemon' => 'PhabricatorRepositoryDaemon', + 'PhabricatorRepositoryGitFetchDaemon' => 'PhabricatorRepositoryPullLocalDaemon', 'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController', + 'PhabricatorRepositoryMercurialPullDaemon' => 'PhabricatorRepositoryPullLocalDaemon', + 'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorRepositoryDaemon', 'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', diff --git a/src/applications/repository/constants/repositorytype/PhabricatorRepositoryType.php b/src/applications/repository/constants/repositorytype/PhabricatorRepositoryType.php index 23161d1f73..87b226c476 100644 --- a/src/applications/repository/constants/repositorytype/PhabricatorRepositoryType.php +++ b/src/applications/repository/constants/repositorytype/PhabricatorRepositoryType.php @@ -18,15 +18,23 @@ final class PhabricatorRepositoryType { - const REPOSITORY_TYPE_GIT = 'git'; - const REPOSITORY_TYPE_SVN = 'svn'; + const REPOSITORY_TYPE_GIT = 'git'; + const REPOSITORY_TYPE_SVN = 'svn'; + const REPOSITORY_TYPE_MERCURIAL = 'hg'; + + public static function getAllRepositoryTypes() { + static $map = array( + self::REPOSITORY_TYPE_GIT => 'Git', + self::REPOSITORY_TYPE_SVN => 'Subversion', + + // TODO: Stabilize and remove caveat. + self::REPOSITORY_TYPE_MERCURIAL => 'Mercurial (LIMITED SUPPORT!)', + ); + return $map; + } public static function getNameForRepositoryType($type) { - static $map = array( - self::REPOSITORY_TYPE_GIT => 'Git', - self::REPOSITORY_TYPE_SVN => 'Subversion', - ); - + $map = self::getAllRepositoryTypes(); return idx($map, $type, 'Unknown'); } diff --git a/src/applications/repository/controller/create/PhabricatorRepositoryCreateController.php b/src/applications/repository/controller/create/PhabricatorRepositoryCreateController.php index 07cc277a2a..8dafb637c1 100644 --- a/src/applications/repository/controller/create/PhabricatorRepositoryCreateController.php +++ b/src/applications/repository/controller/create/PhabricatorRepositoryCreateController.php @@ -30,10 +30,7 @@ class PhabricatorRepositoryCreateController $repository = new PhabricatorRepository(); - $type_map = array( - 'git' => 'Git', - 'svn' => 'Subversion', - ); + $type_map = PhabricatorRepositoryType::getAllRepositoryTypes(); $errors = array(); if ($request->isFormPost()) { diff --git a/src/applications/repository/controller/create/__init__.php b/src/applications/repository/controller/create/__init__.php index 40ae9c1e74..e09b5a768f 100644 --- a/src/applications/repository/controller/create/__init__.php +++ b/src/applications/repository/controller/create/__init__.php @@ -7,6 +7,7 @@ phutil_require_module('phabricator', 'aphront/response/redirect'); +phutil_require_module('phabricator', 'applications/repository/constants/repositorytype'); phutil_require_module('phabricator', 'applications/repository/controller/base'); phutil_require_module('phabricator', 'applications/repository/storage/repository'); phutil_require_module('phabricator', 'view/form/base'); diff --git a/src/applications/repository/controller/edit/PhabricatorRepositoryEditController.php b/src/applications/repository/controller/edit/PhabricatorRepositoryEditController.php index f0491a10b9..801f84baec 100644 --- a/src/applications/repository/controller/edit/PhabricatorRepositoryEditController.php +++ b/src/applications/repository/controller/edit/PhabricatorRepositoryEditController.php @@ -204,6 +204,7 @@ class PhabricatorRepositoryEditController $is_git = false; $is_svn = false; + $is_mercurial = false; $e_ssh_key = null; $e_ssh_keyfile = null; @@ -215,22 +216,29 @@ class PhabricatorRepositoryEditController case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $is_svn = true; break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: + $is_mercurial = true; + break; default: throw new Exception("Unsupported VCS!"); } + $has_branches = ($is_git || $is_mercurial); + $has_local = ($is_git || $is_mercurial); + $has_http_support = $is_svn; + if ($request->isFormPost()) { $tracking = ($request->getStr('tracking') == 'enabled' ? true : false); $repository->setDetail('tracking-enabled', $tracking); $repository->setDetail('remote-uri', $request->getStr('uri')); - if ($is_git) { + if ($has_local) { $repository->setDetail('local-path', $request->getStr('path')); } $repository->setDetail( 'pull-frequency', max(1, $request->getInt('frequency'))); - if ($is_git) { + if ($has_branches) { $repository->setDetail( 'default-branch', $request->getStr('default-branch')); @@ -290,7 +298,7 @@ class PhabricatorRepositoryEditController $e_uri = null; } - if ($is_git) { + if ($has_local) { if (!$repository->getDetail('local-path')) { $e_path = 'Required'; $errors[] = "Local path is required."; @@ -319,6 +327,13 @@ class PhabricatorRepositoryEditController $error_view->appendChild( 'Tracking changes were saved. You may need to restart the daemon '. 'before changes will take effect.'); + } else if (!$repository->getDetail('tracking-enabled')) { + $error_view = new AphrontErrorView(); + $error_view->setSeverity(AphrontErrorView::SEVERITY_WARNING); + $error_view->setTitle('Repository Not Tracked'); + $error_view->appendChild( + 'Tracking is currently "Disabled" for this repository, so it will '. + 'not be imported into Phabricator. You can enable it below.'); } switch ($repository->getVersionControlSystem()) { @@ -375,12 +390,28 @@ class PhabricatorRepositoryEditController '

Remote URI

'. '
'); - $uri_label = 'Repository URI'; + $clone_command = null; + $fetch_command = null; if ($is_git) { - $instructions = - 'Enter the URI to clone this repository from. It should look like '. - 'git@github.com:example/example.git or '. - 'ssh://user@host.com/git/example.git'; + $clone_command = 'git clone'; + $fetch_command = 'git fetch'; + } else if ($is_mercurial) { + $clone_command = 'hg clone'; + $fetch_command = 'hg pull'; + } + + $uri_label = 'Repository URI'; + if ($has_local) { + if ($is_git) { + $instructions = + 'Enter the URI to clone this repository from. It should look like '. + 'git@github.com:example/example.git, '. + 'ssh://user@host.com/git/example.git'; + } else if ($is_mercurial) { + $instructions = + 'Enter the URI to clone this repository from. It should look '. + 'something like ssh://user@host.com/hg/example'; + } $form->appendChild( '

'.$instructions.'

'); } else if ($is_svn) { @@ -436,9 +467,7 @@ class PhabricatorRepositoryEditController '...specify a path on disk where the daemon should '. 'look for a private key.')); - $supports_http = $is_svn; - - if ($supports_http) { + if ($has_http_support) { $form ->appendChild( '
'. @@ -479,13 +508,13 @@ class PhabricatorRepositoryEditController '

Importing Repository Information

'. '
'); - if ($is_git) { + if ($has_local) { $form->appendChild( '

Select a path on local disk '. - 'which the daemons should git clone the repository into. '. - 'This must be readable and writable by the daemons, and readable by '. - 'the webserver. The daemons will git fetch and keep this '. - 'repository up to date.

'); + 'which the daemons should '.$clone_command.' the repository '. + 'into. This must be readable and writable by the daemons, and '. + 'readable by the webserver. The daemons will '.$fetch_command. + ' and keep this repository up to date.

'); $form->appendChild( id(new AphrontFormTextControl()) ->setName('path') @@ -523,7 +552,15 @@ class PhabricatorRepositoryEditController '

Application Configuration

'. '
'); - if ($is_git) { + if ($has_branches) { + + $default_branch_name = null; + if ($is_mercurial) { + $default_branch_name = 'default'; + } else if ($is_git) { + $default_branch_name = 'origin/master'; + } + $form ->appendChild( id(new AphrontFormTextControl()) @@ -532,7 +569,7 @@ class PhabricatorRepositoryEditController ->setValue( $repository->getDetail( 'default-branch', - 'origin/master')) + $default_branch_name)) ->setCaption( 'Default remote branch to show in Diffusion.')); } diff --git a/src/applications/repository/daemon/gitfetch/PhabricatorRepositoryGitFetchDaemon.php b/src/applications/repository/daemon/gitfetch/PhabricatorRepositoryGitFetchDaemon.php index e16a811994..aab67da028 100644 --- a/src/applications/repository/daemon/gitfetch/PhabricatorRepositoryGitFetchDaemon.php +++ b/src/applications/repository/daemon/gitfetch/PhabricatorRepositoryGitFetchDaemon.php @@ -16,40 +16,19 @@ * limitations under the License. */ -class PhabricatorRepositoryGitFetchDaemon - extends PhabricatorRepositoryDaemon { +final class PhabricatorRepositoryGitFetchDaemon + extends PhabricatorRepositoryPullLocalDaemon { - public function run() { - $repository = $this->loadRepository(); + protected function getSupportedRepositoryType() { + return PhabricatorRepositoryType::REPOSITORY_TYPE_GIT; + } - if ($repository->getVersionControlSystem() != 'git') { - throw new Exception("Not a git repository!"); - } + protected function executeCreate($remote_uri, $local_path) { + execx('git clone %s %s', $remote_uri, rtrim($local_path, '/')); + } - $tracked = $repository->getDetail('tracking-enabled'); - if (!$tracked) { - throw new Exception("Tracking is not enabled for this repository."); - } - - $local_path = $repository->getDetail('local-path'); - $remote_uri = $repository->getDetail('remote-uri'); - - if (!$local_path) { - throw new Exception("No local path is available for this repository."); - } - - while (true) { - if (!Filesystem::pathExists($local_path)) { - if (!$remote_uri) { - throw new Exception("No remote URI is available."); - } - execx('mkdir -p %s', dirname($local_path)); - execx('git clone %s %s', $remote_uri, rtrim($local_path, '/')); - } else { - execx('(cd %s && git fetch --all)', $local_path); - } - $this->sleep($repository->getDetail('pull-frequency', 15)); - } + protected function executeUpdate($remote_uri, $local_path) { + execx('(cd %s && git fetch --all)', $local_path); } } diff --git a/src/applications/repository/daemon/gitfetch/__init__.php b/src/applications/repository/daemon/gitfetch/__init__.php index 0fed3d00fb..61b3f4bad3 100644 --- a/src/applications/repository/daemon/gitfetch/__init__.php +++ b/src/applications/repository/daemon/gitfetch/__init__.php @@ -6,9 +6,9 @@ -phutil_require_module('phabricator', 'applications/repository/daemon/base'); +phutil_require_module('phabricator', 'applications/repository/constants/repositorytype'); +phutil_require_module('phabricator', 'applications/repository/daemon/pulllocal'); -phutil_require_module('phutil', 'filesystem'); phutil_require_module('phutil', 'future/exec'); diff --git a/src/applications/repository/daemon/mercurialpull/PhabricatorRepositoryMercurialPullDaemon.php b/src/applications/repository/daemon/mercurialpull/PhabricatorRepositoryMercurialPullDaemon.php new file mode 100644 index 0000000000..079e932116 --- /dev/null +++ b/src/applications/repository/daemon/mercurialpull/PhabricatorRepositoryMercurialPullDaemon.php @@ -0,0 +1,34 @@ +loadRepository(); + $expected_type = $this->getSupportedRepositoryType(); + + $repo_type = $repository->getVersionControlSystem(); + if ($repo_type != $expected_type) { + $repo_type_name = PhabricatorRepositoryType::getNameForRepositoryType( + $repo_type); + $expected_type_name = PhabricatorRepositoryType::getNameForRepositoryType( + $expected_type); + $repo_name = $repository->getName().' ('.$repository->getCallsign().')'; + throw new Exception( + "This daemon pulls '{$expected_type_name}' repositories, but the ". + "repository '{$repo_name}' is a '{$repo_type_name}' repository."); + } + + $tracked = $repository->getDetail('tracking-enabled'); + if (!$tracked) { + throw new Exception("Tracking is not enabled for this repository."); + } + + $local_path = $repository->getDetail('local-path'); + $remote_uri = $repository->getDetail('remote-uri'); + + if (!$local_path) { + throw new Exception("No local path is available for this repository."); + } + + while (true) { + if (!Filesystem::pathExists($local_path)) { + if (!$remote_uri) { + throw new Exception("No remote URI is available."); + } + execx('mkdir -p %s', dirname($local_path)); + $this->executeCreate($remote_uri, $local_path); + } else { + $this->executeUpdate($remote_uri, $local_path); + } + $this->sleep($repository->getDetail('pull-frequency', 15)); + } + } + +} diff --git a/src/applications/repository/daemon/pulllocal/__init__.php b/src/applications/repository/daemon/pulllocal/__init__.php new file mode 100644 index 0000000000..14b9e230c3 --- /dev/null +++ b/src/applications/repository/daemon/pulllocal/__init__.php @@ -0,0 +1,16 @@ +