- now that we have to configure usher's configuration file anyway,
we can skip the explicit configuration of its host and admin password, as we can directly read that from the configuration file itself - expand the SyncMonotone plugin a bit to where this actually becomes useful, i.e. create an accompanying key for each created database and also add some initial database-specific configuration - update the config docs in idf.php-dist to reflect the changes and add more details about the inner workings of the SyncMonotone plugin
This commit is contained in:
@@ -41,8 +41,15 @@ class IDF_Plugin_SyncMonotone
|
||||
}
|
||||
|
||||
/**
|
||||
* Run mtn init command to create the corresponding monotone
|
||||
* repository and add the database to the configured usher instance
|
||||
* Four steps to setup a new monotone project:
|
||||
*
|
||||
* 1) run mtn db init to initialize a new database underknees
|
||||
* 'mtn_repositories'
|
||||
* 2) create a new server key in the same directory
|
||||
* 3) write monotonerc for access control
|
||||
* 4) add the database as new local server in the usher configuration
|
||||
* 5) reload the running usher instance so it acknowledges the new
|
||||
* server
|
||||
*
|
||||
* @param IDF_Project
|
||||
*/
|
||||
@@ -52,45 +59,113 @@ class IDF_Plugin_SyncMonotone
|
||||
return;
|
||||
}
|
||||
|
||||
$repotempl = Pluf::f('mtn_repositories', false);
|
||||
if ($repotempl === false) {
|
||||
$projecttempl = Pluf::f('mtn_repositories', false);
|
||||
if ($projecttempl === false) {
|
||||
throw new IDF_Scm_Exception(
|
||||
'"mtn_repositories" must be defined in your configuration file.'
|
||||
);
|
||||
}
|
||||
|
||||
$usher_config = Pluf::f('mtn_usher', array());
|
||||
if (!array_key_exists('rcfile', $usher_config) ||
|
||||
!is_writable($usher_config['rcfile'])) {
|
||||
$usher_config = Pluf::f('mtn_usher_conf', false);
|
||||
if (!$usher_config || !is_writable($usher_config)) {
|
||||
throw new IDF_Scm_Exception(
|
||||
'"rcfile" in "mtn_usher" does not exist or is not writable.'
|
||||
'"mtn_usher_conf" does not exist or is not writable.'
|
||||
);
|
||||
}
|
||||
|
||||
$shortname = $project->shortname;
|
||||
$dbfile = sprintf($repotempl, $shortname);
|
||||
if (file_exists($dbfile)) {
|
||||
$projectpath = sprintf($projecttempl, $shortname);
|
||||
if (file_exists($projectpath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The repository %s already exists.'), $dbfile
|
||||
__('The project path %s already exists.'), $projectpath
|
||||
));
|
||||
}
|
||||
$return = 0;
|
||||
$output = array();
|
||||
|
||||
if (!mkdir($projectpath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The project path %s could not be created.'), $projectpath
|
||||
));
|
||||
}
|
||||
|
||||
//
|
||||
// step 1) create a new database
|
||||
//
|
||||
$dbfile = $projectpath.'/database.mtn';
|
||||
$cmd = sprintf(
|
||||
Pluf::f('mtn_path', 'mtn').' db init -d %s',
|
||||
escapeshellarg($dbfile)
|
||||
);
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$ll = exec($cmd, $output, $return);
|
||||
$ll = exec($cmd, $output = array(), $return = 0);
|
||||
if ($return != 0) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not create repository %s - please check '.
|
||||
'your error log for details.'),
|
||||
$dbfile
|
||||
__('The database file %s could not be created.'), $dbfile
|
||||
));
|
||||
}
|
||||
|
||||
$usher_rc = file_get_contents($usher_config['rcfile']);
|
||||
//
|
||||
// step 2) create a server key
|
||||
//
|
||||
// try to parse the key's domain part from the remote_url's host
|
||||
// name, otherwise fall back to the configured Apache server name
|
||||
$server = $_SERVER['SERVER_NAME'];
|
||||
$remote_url = Pluf::f('mtn_remote_url');
|
||||
if (($parsed = parse_url($remote_url)) !== false &&
|
||||
!empty($parsed['host'])) {
|
||||
$server = $parsed['host'];
|
||||
}
|
||||
|
||||
$keyname = $shortname.'-server@'.$server;
|
||||
$cmd = sprintf(
|
||||
Pluf::f('mtn_path', 'mtn').' au genkey --confdir=%s %s ""',
|
||||
escapeshellarg($projectpath),
|
||||
escapeshellarg($keyname)
|
||||
);
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$ll = exec($cmd, $output = array(), $return = 0);
|
||||
if ($return != 0) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The server key %s could not be created.'), $keyname
|
||||
));
|
||||
}
|
||||
|
||||
//
|
||||
// step 3) write monotonerc for access control
|
||||
// FIXME: netsync access control is still missing!
|
||||
//
|
||||
$monotonerc =<<<END
|
||||
function get_remote_automate_permitted(key_identity, command, options)
|
||||
local read_only_commands = {
|
||||
"get_corresponding_path", "get_content_changed", "tags", "branches",
|
||||
"common_ancestors", "packet_for_fdelta", "packet_for_fdata",
|
||||
"packets_for_certs", "packet_for_rdata", "get_manifest_of",
|
||||
"get_revision", "select", "graph", "children", "parents", "roots",
|
||||
"leaves", "ancestry_difference", "toposort", "erase_ancestors",
|
||||
"descendents", "ancestors", "heads", "get_file_of", "get_file",
|
||||
"interface_version", "get_attributes", "content_diff",
|
||||
"file_merge", "show_conflicts", "certs", "keys"
|
||||
}
|
||||
|
||||
for _,v in ipairs(read_only_commands) do
|
||||
if (v == command[1]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
END;
|
||||
$rcfile = $projectpath.'/monotonerc';
|
||||
|
||||
// FIXME: sanity
|
||||
$fp = fopen($rcfile, 'w');
|
||||
fwrite($fp, $monotonerc);
|
||||
fclose($fp);
|
||||
|
||||
//
|
||||
// step 4) read in and append the usher config with the new server
|
||||
//
|
||||
$usher_rc = file_get_contents($usher_config);
|
||||
$parsed_config = array();
|
||||
try {
|
||||
$parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc);
|
||||
@@ -98,7 +173,7 @@ class IDF_Plugin_SyncMonotone
|
||||
catch (Exception $e) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not parse usher configuration in "%s": %s'),
|
||||
$usher_config['rcfile'], $e->getMessage()
|
||||
$usher_config, $e->getMessage()
|
||||
));
|
||||
}
|
||||
|
||||
@@ -121,17 +196,23 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$new_server = array(
|
||||
array('key' => 'server', 'values' => array($shortname)),
|
||||
array('key' => 'local', 'values' => array('-d', $dbfile)),
|
||||
array('key' => 'local', 'values' => array(
|
||||
'--confdir', $projectpath,
|
||||
'-d', $dbfile
|
||||
)),
|
||||
);
|
||||
|
||||
$parsed_config[] = $new_server;
|
||||
$usher_rc = IDF_Scm_Monotone_BasicIO::compile($parsed_config);
|
||||
|
||||
// FIXME: more sanity - what happens on failing writes?
|
||||
$fp = fopen($usher_config['rcfile'], 'w');
|
||||
$fp = fopen($usher_config, 'w');
|
||||
fwrite($fp, $usher_rc);
|
||||
fclose($fp);
|
||||
|
||||
//
|
||||
// step 5) reload usher to pick up the new configuration
|
||||
//
|
||||
IDF_Scm_Monotone_Usher::reload();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user