1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 21:40:55 +01:00

Add Mercurial repository configuration and local pull support

Summary: No actual parsing/import yet, but now you can define and pull Mercurial
repositories. I merged most of the local pull code so we can share it between
hg/git.

Test Plan:
  - Created a new Mercurial repository to track Codeigniter off Bitbucket
  - Edited / saved / etc.
  - Launched the mercurial pull daemon, it pulled the repo. Killed and
relaunched, it updated the repo.
  - Launched the git fetch deamon, it still works correctly.

Reviewers: Makinde, aran, jungejason, tuomaspelkonen

Reviewed By: Makinde

CC: aran, Makinde

Differential Revision: 793
This commit is contained in:
epriestley 2011-08-09 12:47:46 -07:00
parent 03fb1887d3
commit 4da43b31a3
12 changed files with 240 additions and 81 deletions

View file

@ -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',
),
));

View file

@ -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',

View file

@ -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');
}

View file

@ -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()) {

View file

@ -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');

View file

@ -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
'<h1>Remote URI</h1>'.
'<div class="aphront-form-inset">');
$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 '.
'<tt>git@github.com:example/example.git</tt> or '.
'<tt>ssh://user@host.com/git/example.git</tt>';
$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 '.
'<tt>git@github.com:example/example.git</tt>, <tt> '.
'<tt>ssh://user@host.com/git/example.git</tt>';
} else if ($is_mercurial) {
$instructions =
'Enter the URI to clone this repository from. It should look '.
'something like <tt>ssh://user@host.com/hg/example</tt>';
}
$form->appendChild(
'<p class="aphront-form-instructions">'.$instructions.'</p>');
} 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(
'<div class="aphront-form-instructions">'.
@ -479,13 +508,13 @@ class PhabricatorRepositoryEditController
'<h1>Importing Repository Information</h1>'.
'<div class="aphront-form-inset">');
if ($is_git) {
if ($has_local) {
$form->appendChild(
'<p class="aphront-form-instructions">Select a path on local disk '.
'which the daemons should <tt>git clone</tt> the repository into. '.
'This must be readable and writable by the daemons, and readable by '.
'the webserver. The daemons will <tt>git fetch</tt> and keep this '.
'repository up to date.</p>');
'which the daemons should <tt>'.$clone_command.'</tt> the repository '.
'into. This must be readable and writable by the daemons, and '.
'readable by the webserver. The daemons will <tt>'.$fetch_command.
'</tt> and keep this repository up to date.</p>');
$form->appendChild(
id(new AphrontFormTextControl())
->setName('path')
@ -523,7 +552,15 @@ class PhabricatorRepositoryEditController
'<h1>Application Configuration</h1>'.
'<div class="aphront-form-inset">');
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 <strong>remote</strong> branch to show in Diffusion.'));
}

View file

@ -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);
}
}

View file

@ -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');

View file

@ -0,0 +1,34 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorRepositoryMercurialPullDaemon
extends PhabricatorRepositoryPullLocalDaemon {
protected function getSupportedRepositoryType() {
return PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL;
}
protected function executeCreate($remote_uri, $local_path) {
execx('hg clone %s %s', $remote_uri, rtrim($local_path, '/'));
}
protected function executeUpdate($remote_uri, $local_path) {
execx('(cd %s && hg pull -u)', $local_path);
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'applications/repository/daemon/pulllocal');
phutil_require_module('phutil', 'future/exec');
phutil_require_source('PhabricatorRepositoryMercurialPullDaemon.php');

View file

@ -0,0 +1,68 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class PhabricatorRepositoryPullLocalDaemon
extends PhabricatorRepositoryDaemon {
abstract protected function getSupportedRepositoryType();
abstract protected function executeCreate($remote_uri, $local_path);
abstract protected function executeUpdate($remote_uri, $local_path);
final public function run() {
$repository = $this->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));
}
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'applications/repository/daemon/base');
phutil_require_module('phutil', 'filesystem');
phutil_require_module('phutil', 'future/exec');
phutil_require_source('PhabricatorRepositoryPullLocalDaemon.php');