Indefero

Indefero Commit Details


Date:2010-08-29 18:01:25 (14 years 3 months ago)
Author:Thomas Keller
Branch:develop, feature-issue_links, feature.better-home, feature.content-md5, feature.diff-whitespace, feature.download-md5, feature.issue-links, feature.issue-of-others, feature.issue-summary, feature.search-filter, feature.webrepos, feature.wiki-default-page, master, release-1.1, release-1.2, release-1.3
Commit:b648e6f7a72f84d49db67a03c7b6822105876253
Parents: 194dcad0e3e76372b3d42348d8aed58f6b09c1cd
Message:- 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

Changes:

File differences

src/IDF/Middleware.php
111111
112112
113113
114
114
115115
116116
117117
$request->project);
$c = array_merge($c, $request->rights);
}
$c['usherConfigured'] = Pluf::f("mtn_usher", null) !== null;
$c['usherConfigured'] = Pluf::f("mtn_usher_conf", null) !== null;
return $c;
}
src/IDF/Plugin/SyncMonotone.php
4141
4242
4343
44
45
44
45
46
47
48
49
50
51
52
4653
4754
4855
......
5259
5360
5461
55
56
62
63
5764
5865
5966
6067
6168
62
63
64
69
70
6571
66
72
6773
6874
6975
7076
71
72
77
78
79
80
81
82
83
84
7385
74
86
7587
7688
77
78
89
90
91
92
93
7994
8095
8196
8297
8398
84
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
85126
86127
87
88
89
128
90129
91130
92131
93
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
94169
95170
96171
......
98173
99174
100175
101
176
102177
103178
104179
......
121196
122197
123198
124
199
200
201
202
125203
126204
127205
128206
129207
130208
131
209
132210
133211
134212
213
214
215
135216
136217
137218
}
/**
* 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();
}
}
src/IDF/Scm/Monotone/Usher.php
2121
2222
2323
24
25
2426
2527
2628
......
190192
191193
192194
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
195219
196220
197
198
221
199222
200223
201224
202225
203
226
204227
205228
206229
207
230
208231
209232
210233
211
234
212235
213236
214237
215238
216239
217240
218
241
219242
220243
221
222
244
223245
224246
225247
......
232254
233255
234256
235
257
236258
237259
238260
#
# ***** END LICENSE BLOCK ***** */
require_once(dirname(__FILE__) . "/BasicIO.php");
/**
* Connects with the admininistrative interface of usher,
* the monotone proxy. This class contains only static methods because
private static function _triggerCommand($cmd)
{
$uc = Pluf::f('mtn_usher');
if (empty($uc['host'])) {
$uc = Pluf::f('mtn_usher_conf', false);
if (!$uc || !is_readable($uc)) {
throw new IDF_Scm_Exception(
'"mtn_usher_conf" is not configured or not readable'
);
}
$parsed_config =
IDF_Scm_Monotone_BasicIO::parse(file_get_contents($uc));
$host = $port = $user = $pass = null;
foreach ($parsed_config as $stanza) {
foreach ($stanza as $line) {
if ($line['key'] == 'adminaddr') {
list($host, $port) = explode(":", @$line['values'][0]);
break;
}
if ($line['key'] == 'userpass') {
$user = @$line['values'][0];
$pass = @$line['values'][1];
}
}
}
if (empty($host)) {
throw new IDF_Scm_Exception('usher host is empty');
}
if (!preg_match('/^\d+$/', $uc['port']) ||
$uc['port'] == 0)
if (!preg_match('/^\d+$/', $port))
{
throw new IDF_Scm_Exception('usher port is invalid');
}
if (empty($uc['user'])) {
if (empty($user)) {
throw new IDF_Scm_Exception('usher user is empty');
}
if (empty($uc['pass'])) {
if (empty($pass)) {
throw new IDF_Scm_Exception('usher pass is empty');
}
$sock = @fsockopen($uc['host'], $uc['port'], $errno, $errstr);
$sock = @fsockopen($host, $port, $errno, $errstr);
if (!$sock) {
throw new IDF_Scm_Exception(
"could not connect to usher: $errstr ($errno)"
);
}
fwrite($sock, 'USERPASS '.$uc['user'].' '.$uc['pass']."\n");
fwrite($sock, 'USERPASS '.$user.' '.$pass."\n");
if (feof($sock)) {
throw new IDF_Scm_Exception(
'usher closed the connection - probably wrong admin '.
'username or password'
'usher closed the connection - this should not happen'
);
}
$out = rtrim($out);
if ($out == 'unknown command') {
throw new IDF_Scm_Exception("unknown command: $cmd");
throw new IDF_Scm_Exception('unknown command: '.$cmd);
}
return $out;
src/IDF/conf/idf.php-dist
7878
7979
8080
81
81
82
8283
8384
85
8486
8587
8688
......
9496
9597
9698
97
99
100
101
102
103
104
105
106
107
98108
99109
100110
101
111
112
113
114
102115
103
104
105
106
107
116
117
118
119
120
121
122
108123
109
110
124
125
126
127
111128
112
113
114129
115
116
130
131
117132
118133
119134
......
143158
144159
145160
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
161164
165
162166
163167
164168
# Additional options for the started monotone process
$cfg['mtn_opts'] = array('--no-workspace', '--norc');
#
# You can setup monotone for use with indefero in two ways:
# You can setup monotone for use with indefero in several ways. The
# two most-used should be:
#
# 1) One database for everything:
#
# Set 'mtn_repositories' below to a fixed database path, such as
# '/home/mtn/repositories/all_projects.mtn'
#
# the database
#
# 2) One database for every project with 'usher':
# Set 'mtn_remote_url' below to a string which matches your setup.
#
# Download and configure 'usher'
# (mtn clone mtn://monotone.ca?net.venge.monotone.contrib.usher)
# which acts as proxy in front of all single project databases.
# Create a basic configuration file for it and add a secret admin
# username and password. Finally, point the below variable
# 'mtn_usher_conf' to this configuration file.
#
# Then set 'mtn_remote_url' below to a string which matches your setup.
# Again, the '%s' placeholder will be expanded to the project's
# short name. Note that 'mtn_remote_url' is used as internal
# URI (to access the data for indefero) as well as external URI
# (for end users) at the same time.
# (for end users) at the same time. 'mtn_repositories' should then
# point to a directory where all project-related files (databases,
# keys, configurations) are kept, as these are automatically created
# on project creation by IDF.
#
# Then download and configure 'usher'
# (mtn clone mtn://monotone.ca?net.venge.monotone.contrib.usher)
# which acts as proxy in front of all single project databases.
# Usher's server names should be mapped to the project's short names,
# so you end up with something like this for every project:
# Example: 'mtn_repositories' is configured to be '/var/monotone/%s'
#
# - IDF tries to create /var/monotone/<projectname> as root directory
# - The database is placed in as /var/monotone/<projectname>/database.mtn
# - The server key is put into /var/monotone/<projectname>/keys and
# is named "<projectname>-server@<host>", where host is the host part
# of 'mtn_remote_url'
#
# server "project"
# local "-d" "/home/mtn/repositories/project.mtn" "*"
# therefor /var/monotone MUST be read/writable for the www user and all
# files which are created underknees MUST be read/writable by the user
# who is executing the usher instance! The best way to achieve this is with
# default (POSIX) ACLs on /var/monotone.
#
# Alternatively if you assign every project a unique DNS such as
# 'project.my-hosting.biz', you can also configure it like this:
#
# host "project.my-hosting.biz"
# local "-d" "/home/mtn/repositories/project.mtn" "*"
# You could also choose to setup usher by hand, i.e. with individual
# databases, in this case leave 'mtn_usher_conf' below commented out.
#
# Pro: - read and write access can be granted per project
# - no database locking issues
$cfg['mtn_db_access'] = 'remote';
#
# If configured, this allows basic control of a running usher process
# via the forge administration
#
# 'host' and 'port' must be set to the specific bits from usher's
# configured 'adminaddr', 'user' and 'pass' must match the values set for
# the configured 'userpass' combination. The 'rcfile' variable must point
# to the full (writable) path of the usher configuration file which gets
# updated when new projects are added
#
#$cfg['mtn_usher'] = array(
# 'host' => 'localhost',
# 'port' => 12345,
# 'user' => 'admin',
# 'pass' => 'admin',
# 'rcfile' => '/path/to/usher.conf',
#);
# via the forge administration. The variable must point to the full (writable)
# path of the usher configuration file which gets updated when new projects
# are added
#
#$cfg['mtn_usher_conf'] = '/path/to/usher.conf';
# Mercurial repositories path
#$cfg['mercurial_repositories'] = '/home/mercurial/repositories/%s';
src/IDF/conf/urls.php
386386
387387
388388
389
389
390390
391391
392392
'model' => 'IDF_Views_Admin',
'method' => 'userUpdate');
if (Pluf::f("mtn_usher", null) !== null)
if (Pluf::f("mtn_usher_conf", null) !== null)
{
$ctl[] = array('regex' => '#^/admin/usher/$#',
'base' => $base,

Archive Download the corresponding diff file

Page rendered in 0.09979s using 13 queries.