| }␊ | 
| ␊ | 
| /**␊ | 
| * 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();␊ | 
| }␊ | 
| }␊ |