Added the Mercurial repository serving synchronization.
This fixes ticket 79.
This commit is contained in:
parent
023cd73ebf
commit
0eeef34908
@ -101,9 +101,12 @@ To upgrade:
|
|||||||
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d -u
|
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d -u
|
||||||
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d
|
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d
|
||||||
|
|
||||||
## Subversion Repository Synchronization
|
## Repository Synchronization
|
||||||
|
|
||||||
The documentation is available in the `doc/syncsvn.mdtext` file.
|
The documentation is available in the `doc` folder.
|
||||||
|
|
||||||
|
* Subversion: `doc/syncsvn.mdtext`.
|
||||||
|
* Mercurial: `doc/syncmercurial.mdtext`.
|
||||||
|
|
||||||
## For the Apache Webserver Users
|
## For the Apache Webserver Users
|
||||||
|
|
||||||
|
64
doc/syncmercurial.mdtext
Normal file
64
doc/syncmercurial.mdtext
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Plugin SyncMercurial by Benjamin Jorand
|
||||||
|
|
||||||
|
The SyncMercurial plugin allows the direct creation and synchronisation of
|
||||||
|
mercurial repositories with the InDefero database. The repositories will be
|
||||||
|
published by hgwebdir.cgi using HTTP. It also handles private repositories.
|
||||||
|
|
||||||
|
SyncMercurial is adapted from SyncSvn by Baptiste Michaud.
|
||||||
|
|
||||||
|
## To Contact the Author
|
||||||
|
|
||||||
|
Benjamin Jorand <benjamin.jorand@gmail.com>
|
||||||
|
|
||||||
|
## Apache configuration
|
||||||
|
|
||||||
|
The simple way to share Mercurial repositories is to publish them
|
||||||
|
using HTTP and `hgwebdir.cgi`.
|
||||||
|
|
||||||
|
It first requires a config file called hgweb.config in the same
|
||||||
|
directory where you put hgwebdir.cgi (for example,
|
||||||
|
`/home/indefero/scripts`):
|
||||||
|
|
||||||
|
[collections]
|
||||||
|
/home/indefero/repositories/mercurial/ = /home/indefero/repositories/mercurial/
|
||||||
|
|
||||||
|
Then configure a vhost this way :
|
||||||
|
|
||||||
|
ScriptAliasMatch ^/hg(.*) /home/indefero/scripts/hgwebdir.cgi$1
|
||||||
|
<Directory /home/indefero/scripts>
|
||||||
|
Options +ExecCGI
|
||||||
|
AuthName "Restricted"
|
||||||
|
AuthType Basic
|
||||||
|
AuthUserFile /home/indefero/auth/.htpasswd
|
||||||
|
<Limit PUT POST>
|
||||||
|
Require valid-user
|
||||||
|
</Limit>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
Enable the authentification for private repositories :
|
||||||
|
|
||||||
|
Include /home/indefero/scripts/private_indefero.conf
|
||||||
|
|
||||||
|
## InDefero configuration
|
||||||
|
|
||||||
|
First, you need to install the File_Passwd PEAR package:
|
||||||
|
|
||||||
|
$ sudo pear install File_Passwd
|
||||||
|
|
||||||
|
Then, based on the paths provided in the Apache configuration, you
|
||||||
|
need to put the following lines in your configuration file:
|
||||||
|
|
||||||
|
$cfg['idf_plugin_syncmercurial_passwd_file'] = '/home/indefero/auth/.htpasswd';
|
||||||
|
$cfg['idf_plugin_syncmercurial_path'] = '/home/indefero/repositories/mercurial';
|
||||||
|
$cfg['idf_plugin_syncmercurial_private_include'] = '/home/indefero/scripts/private_indefero.conf';
|
||||||
|
$cfg['idf_plugin_syncmercurial_private_notify'] = '/home/indefero/tmp/notify.tmp';
|
||||||
|
$cfg['idf_plugin_syncmercurial_private_url'] = '/hg/%s';
|
||||||
|
|
||||||
|
## Cron configuration
|
||||||
|
|
||||||
|
As InDefero modifies the private_indefero.conf, apache needs to be reloaded.
|
||||||
|
Each time this file is modified, a temporary file is created.
|
||||||
|
|
||||||
|
*/5 * * * * /bin/sh /home/indefero/src/cron/SyncMercurial.sh
|
||||||
|
|
||||||
|
Edit this script and add correct values to `private_notify` and `reload_cmd`.
|
10
scripts/SyncMercurial.sh
Normal file
10
scripts/SyncMercurial.sh
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
private_notify="/home/indefero/tmp/notify.tmp"
|
||||||
|
reload_cmd="/usr/sbin/apachectl -k graceful"
|
||||||
|
|
||||||
|
if [ -e $private_notify ]; then
|
||||||
|
$reload_cmd
|
||||||
|
rm -f $private_notify
|
||||||
|
fi
|
||||||
|
|
217
src/IDF/Plugin/SyncMercurial.php
Normal file
217
src/IDF/Plugin/SyncMercurial.php
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<?php
|
||||||
|
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# This file is part of InDefero, an open source project management application.
|
||||||
|
# Copyright (C) 2008 Céondo Ltd and contributors.
|
||||||
|
#
|
||||||
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# InDefero is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
# ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classes is a plugin which allows to synchronise access rights
|
||||||
|
* between indefero and mercurial web-published repositories.
|
||||||
|
*/
|
||||||
|
class IDF_Plugin_SyncMercurial
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point of the plugin.
|
||||||
|
*/
|
||||||
|
static public function entry($signal, &$params)
|
||||||
|
{
|
||||||
|
// First check for the 3 mandatory config variables.
|
||||||
|
if (!Pluf::f('idf_plugin_syncmercurial_passwd_file', false) or
|
||||||
|
!Pluf::f('idf_plugin_syncmercurial_path', false) or
|
||||||
|
!Pluf::f('idf_plugin_syncmercurial_hgrc', false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
include_once 'File/Passwd/Authdigest.php';
|
||||||
|
$plug = new IDF_Plugin_SyncMercurial();
|
||||||
|
switch ($signal) {
|
||||||
|
case 'IDF_Project::created':
|
||||||
|
$plug->processMercurialCreate($params['project']);
|
||||||
|
break;
|
||||||
|
case 'IDF_Project::membershipsUpdated':
|
||||||
|
$plug->processSyncAuthz($params['project']);
|
||||||
|
break;
|
||||||
|
case 'Pluf_User::passwordUpdated':
|
||||||
|
$plug->processSyncPasswd($params['user']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run hg init command to create the corresponding Mercurial
|
||||||
|
* repository.
|
||||||
|
*
|
||||||
|
* @param IDF_Project
|
||||||
|
* @return bool Success
|
||||||
|
*/
|
||||||
|
function processMercurialCreate($project)
|
||||||
|
{
|
||||||
|
$shortname = $project->shortname;
|
||||||
|
|
||||||
|
if (false===($mercurial_path=Pluf::f('idf_plugin_syncmercurial_path',false))) {
|
||||||
|
throw new Pluf_Exception_SettingError("'idf_plugin_syncmercurial_path' must be defined in your configuration file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists($mercurial_path.'/'.$shortname)) {
|
||||||
|
throw new Exception(sprintf(__('The repository %s already exists.'),
|
||||||
|
$mercurial_path.'/'.$shortname));
|
||||||
|
}
|
||||||
|
$return = 0;
|
||||||
|
$output = array();
|
||||||
|
$cmd = sprintf('hg init %s',
|
||||||
|
escapeshellarg($mercurial_path.'/'.$shortname));
|
||||||
|
$ll = exec($cmd, $output, $return);
|
||||||
|
return ($return == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronise an user's password.
|
||||||
|
*
|
||||||
|
* @param Pluf_User
|
||||||
|
*/
|
||||||
|
function processSyncPasswd($user)
|
||||||
|
{
|
||||||
|
$passwd_file = Pluf::f('idf_plugin_syncmercurial_passwd_file');
|
||||||
|
if (!file_exists($passwd_file) or !is_writable($passwd_file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ht = new File_Passwd_Authbasic($passwd_file);
|
||||||
|
$ht->load();
|
||||||
|
$ht->setMode(FILE_PASSWD_SHA);
|
||||||
|
if ($ht->userExists($user->login)) {
|
||||||
|
$ht->changePasswd($user->login, $this->getMercurialPass($user));
|
||||||
|
} else {
|
||||||
|
$ht->addUser($user->login, $this->getMercurialPass($user));
|
||||||
|
}
|
||||||
|
$ht->save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize the hgrc file and the passwd file for the project.
|
||||||
|
*
|
||||||
|
* @param IDF_Project
|
||||||
|
*/
|
||||||
|
function processSyncAuthz($project)
|
||||||
|
{
|
||||||
|
$this->SyncAccess($project);
|
||||||
|
$this->generateProjectPasswd($project);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the repository password for the user
|
||||||
|
*/
|
||||||
|
function getMercurialPass($user){
|
||||||
|
return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a particular project: update all passwd information
|
||||||
|
*/
|
||||||
|
function generateProjectPasswd($project)
|
||||||
|
{
|
||||||
|
$passwd_file = Pluf::f('idf_plugin_syncmercurial_passwd_file');
|
||||||
|
if (!file_exists($passwd_file) or !is_writable($passwd_file)) {
|
||||||
|
throw new Exception (sprintf(__('%s does not exist or is not writable.'), $passwd_file));
|
||||||
|
}
|
||||||
|
$ht = new File_Passwd_Authbasic($passwd_file);
|
||||||
|
$ht->setMode(FILE_PASSWD_SHA);
|
||||||
|
$ht->load();
|
||||||
|
$mem = $project->getMembershipData();
|
||||||
|
$members = array_merge((array)$mem['members'], (array)$mem['owners'],
|
||||||
|
(array)$mem['authorized']);
|
||||||
|
foreach($members as $user) {
|
||||||
|
if ($ht->userExists($user->login)) {
|
||||||
|
$ht->changePasswd($user->login, $this->getMercurialPass($user));
|
||||||
|
} else {
|
||||||
|
$ht->addUser($user->login, $this->getMercurialPass($user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ht->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the hgrc file
|
||||||
|
*/
|
||||||
|
function SyncAccess($project)
|
||||||
|
{
|
||||||
|
$shortname = $project->shortname;
|
||||||
|
$hgrc_file = Pluf::f('idf_plugin_syncmercurial_path').sprintf('/%s/.hg/hgrc', $shortname);
|
||||||
|
|
||||||
|
// Get allow_push list
|
||||||
|
$allow_push = '';
|
||||||
|
$mem = $project->getMembershipData();
|
||||||
|
foreach ($mem['owners'] as $v) {
|
||||||
|
$allow_push .= $v->login.' ';
|
||||||
|
}
|
||||||
|
foreach ($mem['members'] as $v) {
|
||||||
|
$allow_push .= $v->login.' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate hgrc content
|
||||||
|
if (is_file($hgrc_file)) {
|
||||||
|
$tmp_content = parse_ini_file($hgrc_file, true);
|
||||||
|
$tmp_content['web']['allow_push'] = $allow_push;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$tmp_content = Pluf::f('idf_plugin_syncmercurial_hgrc');
|
||||||
|
$tmp_content['web']['allow_push'] = $allow_push;
|
||||||
|
}
|
||||||
|
$fcontent = '';
|
||||||
|
foreach ($tmp_content as $key => $elem){
|
||||||
|
$fcontent .= '['.$key."]\n";
|
||||||
|
foreach ($elem as $key2 => $elem2){
|
||||||
|
$fcontent .= $key2.' = '.$elem2."\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_put_contents($hgrc_file, $fcontent, LOCK_EX);
|
||||||
|
|
||||||
|
// Generate private repository config file
|
||||||
|
$private_file = Pluf::f('idf_plugin_syncmercurial_private_include');
|
||||||
|
$notify_file = Pluf::f('idf_plugin_syncmercurial_private_notify');
|
||||||
|
$fcontent = '';
|
||||||
|
foreach (Pluf::factory('IDF_Project')->getList() as $project) {
|
||||||
|
$conf = new IDF_Conf();
|
||||||
|
$conf->setProject($project);
|
||||||
|
if ($project->private == true){
|
||||||
|
$mem = $project->getMembershipData();
|
||||||
|
$user = '';
|
||||||
|
foreach ($mem['owners'] as $v) {
|
||||||
|
$user .= $v->login.' ';
|
||||||
|
}
|
||||||
|
foreach ($mem['members'] as $v) {
|
||||||
|
$user .= $v->login.' ';
|
||||||
|
}
|
||||||
|
foreach ($mem['authorized'] as $v) {
|
||||||
|
$user .= $v->login.' ';
|
||||||
|
}
|
||||||
|
$fcontent .= '<Location '. sprintf(Pluf::f('idf_plugin_syncmercurial_private_url'), $project->shortname).'>'."\n";
|
||||||
|
$fcontent .= 'AuthType Basic'."\n";
|
||||||
|
$fcontent .= 'AuthName "Restricted"'."\n";
|
||||||
|
$fcontent .= sprintf('AuthUserFile %s', Pluf::f('idf_plugin_syncmercurial_passwd_file'))."\n";
|
||||||
|
$fcontent .= sprintf('Require user %s', $user)."\n";
|
||||||
|
$fcontent .= '</Location>'."\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_put_contents($private_file, $fcontent, LOCK_EX);
|
||||||
|
file_put_contents($notify_file, ' ', LOCK_EX);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -52,4 +52,12 @@ Pluf_Signal::connect('IDF_Project::created',
|
|||||||
Pluf_Signal::connect('Pluf_User::passwordUpdated',
|
Pluf_Signal::connect('Pluf_User::passwordUpdated',
|
||||||
array('IDF_Plugin_SyncSvn', 'entry'));
|
array('IDF_Plugin_SyncSvn', 'entry'));
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mercurial synchronization
|
||||||
|
Pluf_Signal::connect('IDF_Project::membershipsUpdated',
|
||||||
|
array('IDF_Plugin_SyncMercurial', 'entry'));
|
||||||
|
Pluf_Signal::connect('IDF_Project::created',
|
||||||
|
array('IDF_Plugin_SyncMercurial', 'entry'));
|
||||||
|
Pluf_Signal::connect('Pluf_User::passwordUpdated',
|
||||||
|
array('IDF_Plugin_SyncMercurial', 'entry'));
|
||||||
return $m;
|
return $m;
|
||||||
|
Loading…
Reference in New Issue
Block a user