| }␊ |
| ␊ |
| /**␊ |
| * 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␊ |
| */␊ |
|
| 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 project path %s already exists.'), $projectpath␊ |
| ));␊ |
| }␊ |
| ␊ |
| if (!mkdir($projectpath)) {␊ |
| throw new IDF_Scm_Exception(sprintf(␊ |
| __('The repository %s already exists.'), $dbfile␊ |
| __('The project path %s could not be created.'), $projectpath␊ |
| ));␊ |
| }␊ |
| $return = 0;␊ |
| $output = array();␊ |
| ␊ |
| //␊ |
| // 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(␊ |
| __('The database file %s could not be created.'), $dbfile␊ |
| ));␊ |
| }␊ |
| ␊ |
| //␊ |
| // 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(␊ |
| __('Could not create repository %s - please check '.␊ |
| 'your error log for details.'),␊ |
| $dbfile␊ |
| __('The server key %s could not be created.'), $keyname␊ |
| ));␊ |
| }␊ |
| ␊ |
| $usher_rc = file_get_contents($usher_config['rcfile']);␊ |
| //␊ |
| // 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);␊ |
|
| 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()␊ |
| ));␊ |
| }␊ |
| ␊ |
|
| ␊ |
| $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();␊ |
| }␊ |
| }␊ |