1 |
commit: 1111e063d87554087526b3f6ef43612125db9bfb |
2 |
Author: André Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Mon Mar 31 15:44:49 2014 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Mon Mar 31 15:44:49 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=1111e063 |
7 |
|
8 |
let's run on debian #1: roverlay-setup |
9 |
|
10 |
This commit adds basic support for target-specific setup |
11 |
via the "--target-type <type>" switch. |
12 |
|
13 |
So far this affects config file creation only and there are 2 choices: |
14 |
|
15 |
* "gentoo": have portage and a PORTDIR |
16 |
* "foreign" a.k.a. "not gentoo": neither portage nor PORTDIR available |
17 |
|
18 |
--- |
19 |
roverlay/config/defconfig.py | 66 ++++++++++++------ |
20 |
roverlay/setupscript/runtime.py | 148 ++++++++++++++++++++++++++++------------ |
21 |
roverlay/static/targetenv.py | 51 ++++++++++++++ |
22 |
3 files changed, 204 insertions(+), 61 deletions(-) |
23 |
|
24 |
diff --git a/roverlay/config/defconfig.py b/roverlay/config/defconfig.py |
25 |
index 4bff289..383bb96 100644 |
26 |
--- a/roverlay/config/defconfig.py |
27 |
+++ b/roverlay/config/defconfig.py |
28 |
@@ -148,7 +148,7 @@ class ConfigOption ( object ): |
29 |
class RoverlayConfigCreation ( object ): |
30 |
|
31 |
def __init__ ( self, |
32 |
- is_installed, |
33 |
+ is_installed, target_type, |
34 |
work_root = '~/roverlay', |
35 |
data_root = '/usr/share/roverlay', |
36 |
conf_root = '/etc/roverlay', |
37 |
@@ -167,7 +167,7 @@ class RoverlayConfigCreation ( object ): |
38 |
self._ctree = tree.ConfigTree() |
39 |
self._cloader = self._ctree.get_loader() |
40 |
self._verify_value = self._cloader._make_and_verify_value |
41 |
- self.reset ( is_installed=is_installed ) |
42 |
+ self.reset ( is_installed=is_installed, target_type=target_type ) |
43 |
# --- end of __init__ (...) --- |
44 |
|
45 |
def iter_options ( self ): |
46 |
@@ -189,6 +189,8 @@ class RoverlayConfigCreation ( object ): |
47 |
svalue = self.get_datadir ( value[2:] ) |
48 |
elif v == 'c': |
49 |
svalue = self.get_confdir ( value[2:] ) |
50 |
+ elif v == 'a': |
51 |
+ svalue = self.get_additions_dir ( value[2:] ) |
52 |
else: |
53 |
svalue = value |
54 |
else: |
55 |
@@ -215,7 +217,7 @@ class RoverlayConfigCreation ( object ): |
56 |
else: |
57 |
raise ConfigOptionMissing ( key ) |
58 |
|
59 |
- def reset ( self, is_installed ): |
60 |
+ def reset ( self, is_installed, target_type ): |
61 |
workdir = self.get_workdir |
62 |
datadir = self.get_datadir |
63 |
confdir = self.get_confdir |
64 |
@@ -223,15 +225,21 @@ class RoverlayConfigCreation ( object ): |
65 |
|
66 |
cachedir = _fspath_prefix_func ( self.work_root, 'cache' ) |
67 |
|
68 |
+ _NULLCONF = lambda *a, **b: None |
69 |
+ _GET_A = lambda a, b: a |
70 |
+ _GET_B = lambda a, b: b |
71 |
+ _T_TRUE = ( ConfigOption, _NULLCONF, _GET_A ) |
72 |
+ _T_FALSE = ( _NULLCONF, ConfigOption, _GET_B ) |
73 |
+ _get_setup_triple = lambda cond: ( _T_TRUE if cond else _T_FALSE ) |
74 |
|
75 |
- UNLESS_INSTALLED = lambda *a, **b: ( |
76 |
- None if is_installed else ConfigOption ( *a, **b ) |
77 |
+ IF_INSTALLED, UNLESS_INSTALLED, get_inst_val = ( |
78 |
+ _get_setup_triple ( is_installed ) |
79 |
) |
80 |
- IF_INSTALLED = lambda *a, **b: ( |
81 |
- ConfigOption ( *a, **b ) if is_installed else None |
82 |
+ IF_PORTDIR, UNLESS_PORTDIR, get_portdir_val = ( |
83 |
+ _get_setup_triple ( target_type.portdir ) |
84 |
) |
85 |
- get_val = lambda v_inst, v_standalone: ( |
86 |
- v_inst if is_installed else v_standalone |
87 |
+ IF_PORTAGE, UNLESS_PORTAGE, get_portage_val = ( |
88 |
+ _get_setup_triple ( target_type.has_portage ) |
89 |
) |
90 |
|
91 |
|
92 |
@@ -250,27 +258,35 @@ class RoverlayConfigCreation ( object ): |
93 |
use_default_desc=False |
94 |
), |
95 |
ConfigOption ( 'CACHEDIR', cachedir() ), |
96 |
- ConfigOption ( |
97 |
- 'PORTDIR', '/usr/portage', use_default_desc=False, |
98 |
+ IF_PORTDIR ( |
99 |
+ 'PORTDIR', target_type.portdir, use_default_desc=False, |
100 |
description=( |
101 |
"portage directory", |
102 |
" used to scan for valid licenses", |
103 |
), |
104 |
), |
105 |
+ UNLESS_PORTAGE ( |
106 |
+ 'EBUILD_PROG', '/usr/bin/ebuild', |
107 |
+ comment_default=True, required=False, recommended=None, |
108 |
+ description=( |
109 |
+ ' optional, but required for importing hand-written ebuilds' |
110 |
+ ' and MANIFEST_IMPLEMENTATION=ebuild (see below)' |
111 |
+ ), |
112 |
+ ), |
113 |
'', |
114 |
'# --- Logging Configuration (optional) ---', |
115 |
'', |
116 |
ConfigOption ( |
117 |
- 'LOG_LEVEL', get_val ( 'WARNING', 'INFO' ), required=False, |
118 |
+ 'LOG_LEVEL', get_inst_val ( 'WARNING', 'INFO' ), required=False, |
119 |
comment_default=is_installed, |
120 |
), |
121 |
ConfigOption ( |
122 |
- 'LOG_LEVEL_CONSOLE', get_val ( 'INFO', 'WARNING' ), |
123 |
+ 'LOG_LEVEL_CONSOLE', get_inst_val ( 'INFO', 'WARNING' ), |
124 |
required=False, comment_default=is_installed, |
125 |
use_default_desc=False, append_newline=False, |
126 |
), |
127 |
ConfigOption ( |
128 |
- 'LOG_LEVEL_FILE', get_val ( 'ERROR', 'WARNING' ), |
129 |
+ 'LOG_LEVEL_FILE', get_inst_val ( 'ERROR', 'WARNING' ), |
130 |
required=False, comment_default=is_installed, |
131 |
use_default_desc=False, append_newline=False, |
132 |
), |
133 |
@@ -350,7 +366,10 @@ class RoverlayConfigCreation ( object ): |
134 |
ConfigOption ( |
135 |
'OVERLAY_CATEGORY', 'sci-R', defaults_to=True, |
136 |
comment_default=True, required=False, use_default_desc=False, |
137 |
- description="default category for created ebuilds", |
138 |
+ description=( |
139 |
+ "default category for created ebuilds", |
140 |
+ " (usually overridden by package rules)" |
141 |
+ ) |
142 |
), |
143 |
ConfigOption ( |
144 |
'REPO_CONFIG', confdir ( 'repo.list' ), |
145 |
@@ -389,24 +408,33 @@ class RoverlayConfigCreation ( object ): |
146 |
), |
147 |
ConfigOption ( |
148 |
'USE_PORTAGE_LICENSES', 'no', required=False, |
149 |
- comment_default=True, defaults_to="yes" |
150 |
+ comment_default=target_type.portdir, defaults_to="yes" |
151 |
+ ), |
152 |
+ UNLESS_PORTDIR ( |
153 |
+ 'LICENSES_FILE', datadir ( 'licenses' ), required=True, |
154 |
+ use_default_desc=False, defaults_to="<CACHEDIR>/licenses", |
155 |
+ description=( |
156 |
+ "file that lists all known licenses (one per line)" |
157 |
+ ), |
158 |
), |
159 |
ConfigOption ( |
160 |
'CREATE_LICENSES_FILE', 'no', required=False, |
161 |
- comment_default=True, defaults_to="yes" |
162 |
+ comment_default=target_type.portdir, defaults_to="yes" |
163 |
), |
164 |
ConfigOption ( |
165 |
'NOSYNC', 'yes', required=False, comment_default=True, |
166 |
defaults_to="no", |
167 |
), |
168 |
ConfigOption ( |
169 |
- 'MANIFEST_IMPLEMENTATION', "ebuild", required=False, |
170 |
+ 'MANIFEST_IMPLEMENTATION', 'ebuild', required=False, |
171 |
use_default_desc=False, comment_default=True, defaults_to="next", |
172 |
description=( |
173 |
"Manifest file creation", |
174 |
' Available choices are \'next\' (internal, fast)', |
175 |
' and \'ebuild\' (using ebuild(1), slow, but failsafe).', |
176 |
- ), |
177 |
+ ) + get_portage_val ( |
178 |
+ (), ( ' *** \'ebuild\' needs a valid EBUILD_PROG ***', ) |
179 |
+ ) |
180 |
), |
181 |
] |
182 |
|
183 |
|
184 |
diff --git a/roverlay/setupscript/runtime.py b/roverlay/setupscript/runtime.py |
185 |
index 2afbc9f..afe9daa 100644 |
186 |
--- a/roverlay/setupscript/runtime.py |
187 |
+++ b/roverlay/setupscript/runtime.py |
188 |
@@ -17,10 +17,12 @@ import roverlay.fsutil |
189 |
import roverlay.runtime |
190 |
|
191 |
import roverlay.config.defconfig |
192 |
+import roverlay.config.entryutil |
193 |
|
194 |
import roverlay.setupscript.initenv |
195 |
import roverlay.setupscript.hookenv |
196 |
|
197 |
+import roverlay.static.targetenv |
198 |
|
199 |
|
200 |
if sys.hexversion >= 0x3000000: |
201 |
@@ -29,6 +31,12 @@ else: |
202 |
read_user_input = raw_input |
203 |
|
204 |
|
205 |
+CONFIG_FS_OPTIONS = frozenset ( |
206 |
+ k for k, v in roverlay.config.entryutil.iter_entries_with_value_type ( |
207 |
+ { 'fs_path', 'fs_abs', 'fs_dir', 'fs_file', } |
208 |
+ ) |
209 |
+) |
210 |
+ |
211 |
|
212 |
def setup_main_installed(): |
213 |
return setup_main ( True ) |
214 |
@@ -117,6 +125,25 @@ class SetupArgumentParser ( roverlay.argparser.RoverlayArgumentParser ): |
215 |
arg = self.setup_setup_minimal ( title='common options' ) |
216 |
|
217 |
arg ( |
218 |
+ '--target-type', |
219 |
+ dest = "target_type", |
220 |
+ default = roverlay.static.targetenv.DEFAULT_TARGET, |
221 |
+ metavar = "<type>", |
222 |
+ choices = roverlay.static.targetenv.TARGET_INFO, |
223 |
+ flags = self.ARG_WITH_DEFAULT, |
224 |
+ help = ( |
225 |
+ 'set the environment in which roverlay will be run' |
226 |
+ ' (choose from %(choices)s)' |
227 |
+ ) |
228 |
+ ) |
229 |
+ |
230 |
+ arg ( |
231 |
+ '--foreign', '--not-gentoo', dest="target_type", |
232 |
+ flags=self.ARG_SHARED, action="store_const", const="foreign", |
233 |
+ help="set target environment to \'foreign\'" |
234 |
+ ) |
235 |
+ |
236 |
+ arg ( |
237 |
'--output', '-O', metavar="<file|dir|->", dest='output', |
238 |
default='-', type=arg_stdout_or_fs, |
239 |
flags=self.ARG_WITH_DEFAULT, |
240 |
@@ -348,6 +375,7 @@ class SetupEnvironment ( roverlay.runtime.IndependentRuntimeEnvironment ): |
241 |
self.additions_dir = None |
242 |
self.hook_overwrite = None |
243 |
|
244 |
+ self.target_type = None |
245 |
|
246 |
# not used |
247 |
# COLUMNS = os.environ.get ( 'COLUMNS', 78 ) # should use termios/... |
248 |
@@ -359,9 +387,14 @@ class SetupEnvironment ( roverlay.runtime.IndependentRuntimeEnvironment ): |
249 |
# --- end of __init__ (...) --- |
250 |
|
251 |
def get_parser_defaults ( self ): |
252 |
+ defaults = {} |
253 |
+ |
254 |
+ if 'ROVERLAY_TARGET_TYPE' in os.environ: |
255 |
+ defaults ['target_type'] = os.environ ['ROVERLAY_TARGET_TYPE'] |
256 |
+ |
257 |
if self.is_installed(): |
258 |
instinfo = self.INSTALLINFO |
259 |
- return { |
260 |
+ defaults.update ({ |
261 |
'work_root' : instinfo ['workroot'], |
262 |
'data_root' : instinfo ['libexec'], |
263 |
'conf_root' : instinfo ['confroot'], |
264 |
@@ -369,11 +402,11 @@ class SetupEnvironment ( roverlay.runtime.IndependentRuntimeEnvironment ): |
265 |
'import_config' : 'symlink=root', |
266 |
'additions_dir' : instinfo ['workroot'] + os.sep + 'files', |
267 |
'hook_relpath' : False, |
268 |
- } |
269 |
+ }) |
270 |
else: |
271 |
assert self.prjroot |
272 |
prjroot = self.prjroot + os.sep |
273 |
- return { |
274 |
+ defaults.update ({ |
275 |
'work_root' : prjroot + 'workdir', |
276 |
'data_root' : prjroot + 'files', |
277 |
'conf_root' : prjroot + 'config', |
278 |
@@ -381,7 +414,10 @@ class SetupEnvironment ( roverlay.runtime.IndependentRuntimeEnvironment ): |
279 |
'import_config' : 'disable', |
280 |
'additions_dir' : prjroot + 'files', |
281 |
'hook_relpath' : True, |
282 |
- } |
283 |
+ }) |
284 |
+ # -- end if |
285 |
+ |
286 |
+ return defaults |
287 |
# --- end of get_parser_defaults (...) --- |
288 |
|
289 |
def create_argparser ( self ): |
290 |
@@ -425,53 +461,66 @@ class SetupEnvironment ( roverlay.runtime.IndependentRuntimeEnvironment ): |
291 |
) |
292 |
# --- end of create_new_target_config (...) --- |
293 |
|
294 |
- def _expanduser_pwd ( self, fspath ): |
295 |
- return roverlay.fsutil.pwd_expanduser ( |
296 |
- fspath, self.options ['target_uid'] |
297 |
- ) |
298 |
+ def _expanduser_pwd ( self, fspath, |
299 |
+ _expand=roverlay.fsutil.pwd_expanduser |
300 |
+ ): |
301 |
+ return _expand ( fspath, self.options ['target_uid'] ) |
302 |
# --- end of _expanduser_pwd (...) --- |
303 |
|
304 |
def create_config_file ( self, expand_user=False ): |
305 |
- def _get_prjroot_relpath ( fspath ): |
306 |
- p = os.path.relpath ( fspath, self.prjroot ) |
307 |
- if p and ( p[0] != '.' or p == '.' ): |
308 |
- return p |
309 |
- else: |
310 |
- return fspath |
311 |
- # --- end of get_prjroot_relpath (...) --- |
312 |
+ _IDENT = lambda x: x |
313 |
+ _FS_OPTIONS = CONFIG_FS_OPTIONS |
314 |
|
315 |
- get_prjroot_relpath = ( |
316 |
- _get_prjroot_relpath |
317 |
- if ( self.options ['prjroot_relpath'] and self.prjroot ) |
318 |
- else (lambda p: p) |
319 |
- ) |
320 |
+ def _unexpand ( fspath, |
321 |
+ _unexpanduser_pwd = roverlay.fsutil.pwd_unexpanduser, |
322 |
+ _target_uid = self.options ['target_uid'] |
323 |
+ ): |
324 |
+ return _unexpanduser_pwd ( fspath, _target_uid ) |
325 |
+ # --- end of _unexpand (...) --- |
326 |
+ |
327 |
+ def _get_prjroot_relpath ( fspath, |
328 |
+ _relpath=os.path.relpath, _prjroot=self.prjroot |
329 |
+ ): |
330 |
+ p = _relpath ( fspath, _prjroot ) |
331 |
+ return p if ( p and ( p[0] != '.' or p == '.' ) ) else fspath |
332 |
+ # --- end of _get_prjroot_relpath (...) --- |
333 |
+ |
334 |
+ def var_iter ( cmdline_vars ): |
335 |
+ for kv in cmdline_vars: |
336 |
+ key, sepa, value = kv.partition ( '=' ) |
337 |
+ if key and sepa: |
338 |
+ yield ( key, value ) |
339 |
+ else: |
340 |
+ raise ValueError ( "bad variable given: {!r}".format ( kv ) ) |
341 |
+ # --- end of var_iter (...) --- |
342 |
+ |
343 |
+ if self.options ['prjroot_relpath'] and self.prjroot: |
344 |
+ get_config_fspath = _get_prjroot_relpath |
345 |
+ elif expand_user: |
346 |
+ get_config_fspath = _IDENT |
347 |
+ else: |
348 |
+ get_config_fspath = _unexpand |
349 |
|
350 |
conf_creator = roverlay.config.defconfig.RoverlayConfigCreation ( |
351 |
is_installed = self.is_installed(), |
352 |
- work_root = get_prjroot_relpath ( |
353 |
- self.work_root if expand_user else self.options ['work_root'] |
354 |
- ), |
355 |
- data_root = get_prjroot_relpath ( |
356 |
- self.data_root if expand_user else self.options ['data_root'] |
357 |
- ), |
358 |
- conf_root = get_prjroot_relpath ( |
359 |
- self.user_conf_root if expand_user |
360 |
- else self.options ['private_conf_root'] |
361 |
- ), |
362 |
- additions_dir = get_prjroot_relpath ( |
363 |
- self.additions_dir if expand_user |
364 |
- else self.options ['additions_dir'] |
365 |
- ) |
366 |
+ target_type = self.target_type, |
367 |
+ work_root = get_config_fspath ( self.work_root ), |
368 |
+ data_root = get_config_fspath ( self.data_root ), |
369 |
+ conf_root = get_config_fspath ( self.user_conf_root ), |
370 |
+ additions_dir = get_config_fspath ( self.additions_dir ), |
371 |
) |
372 |
+ set_option = conf_creator.set_option |
373 |
|
374 |
- for kv in self.options ['config_vars']: |
375 |
- key, sepa, value = kv.partition ( '=' ) |
376 |
- if not sepa: |
377 |
- raise Exception ( "bad variable given: {!r}".format ( kv ) ) |
378 |
- elif key in { 'ADDITIONS_DIR', 'OVERLAY_ADDITIONS_DIR', }: |
379 |
- conf_creator.set_option ( key, get_prjroot_relpath ( value ) ) |
380 |
- else: |
381 |
- conf_creator.set_option ( key, value ) |
382 |
+ if get_config_fspath is _IDENT: |
383 |
+ for key, value in var_iter ( self.options ['config_vars'] ): |
384 |
+ set_option ( key, value ) |
385 |
+ else: |
386 |
+ for key, value in var_iter ( self.options ['config_vars'] ): |
387 |
+ if key.lower() in _FS_OPTIONS: |
388 |
+ set_option ( key, get_config_fspath ( value ) ) |
389 |
+ else: |
390 |
+ set_option ( key, value ) |
391 |
+ # -- end if |
392 |
|
393 |
return conf_creator.get_str() |
394 |
# --- end of create_config_file (...) --- |
395 |
@@ -523,6 +572,21 @@ class SetupEnvironment ( roverlay.runtime.IndependentRuntimeEnvironment ): |
396 |
) |
397 |
) |
398 |
|
399 |
+ target_type_str = options ['target_type'] |
400 |
+ try: |
401 |
+ self.target_type = ( |
402 |
+ roverlay.static.targetenv.TARGET_INFO [target_type_str] |
403 |
+ ) |
404 |
+ except KeyError: |
405 |
+ sys.stderr.write ( |
406 |
+ "invalid $ROVERLAY_TARGET_TYPE/--target-type: {!r}\n".format ( |
407 |
+ target_type_str |
408 |
+ ) |
409 |
+ ) |
410 |
+ sys.exit ( os.EX_USAGE ) |
411 |
+ # -- end try |
412 |
+ del target_type_str |
413 |
+ |
414 |
self.fs_private_virtual = roverlay.fsutil.VirtualFsOperations ( |
415 |
uid=target_uid, gid=target_gid, |
416 |
file_mode=self.PRIVATE_FILE_MODE, dir_mode=self.PRIVATE_DIR_MODE |
417 |
|
418 |
diff --git a/roverlay/static/targetenv.py b/roverlay/static/targetenv.py |
419 |
new file mode 100644 |
420 |
index 0000000..330c8ee |
421 |
--- /dev/null |
422 |
+++ b/roverlay/static/targetenv.py |
423 |
@@ -0,0 +1,51 @@ |
424 |
+# R overlay -- |
425 |
+# -*- coding: utf-8 -*- |
426 |
+# Copyright (C) 2014 André Erdmann <dywi@×××××××.de> |
427 |
+# Distributed under the terms of the GNU General Public License; |
428 |
+# either version 2 of the License, or (at your option) any later version. |
429 |
+ |
430 |
+import collections |
431 |
+ |
432 |
+ |
433 |
+# *** FIXME: doc *** |
434 |
+# gentoo means: |
435 |
+# * have PORTDIR |
436 |
+# * have ebuild(1) from portage |
437 |
+# and foreign -- "not gentoo": |
438 |
+# * don't use PORTDIR |
439 |
+# * don't use portage |
440 |
+# * use a hardcoded licenses file |
441 |
+# ... |
442 |
+# |
443 |
+ |
444 |
+DEFAULT_TARGET = "gentoo" |
445 |
+ |
446 |
+# dict: env_name(str) => defaults(TargetInfo) |
447 |
+TARGET_INFO = collections.OrderedDict() |
448 |
+ |
449 |
+#TargetInfo = collections.namedtuple ( 'TargetInfo', 'name has_portage portdir' ) |
450 |
+class TargetInfo ( object ): |
451 |
+ __instances = dict() |
452 |
+ |
453 |
+ @classmethod |
454 |
+ def get_instance ( cls, *args ): |
455 |
+ obj = cls.__instances.get ( args, None ) |
456 |
+ if obj is None: |
457 |
+ obj = cls ( *args ) |
458 |
+ cls.__instances [args] = obj |
459 |
+ return obj |
460 |
+ |
461 |
+ def __init__ ( self, name, has_portage, portdir ): |
462 |
+ super ( TargetInfo, self ).__init__() |
463 |
+ self.name = name |
464 |
+ self.has_portage = has_portage |
465 |
+ self.portdir = portdir |
466 |
+# --- end of TargetInfo --- |
467 |
+ |
468 |
+def add_entry ( name, *args ): |
469 |
+ TARGET_INFO [name] = TargetInfo.get_instance ( name, *args ) |
470 |
+# --- end of add_entry (...) --- |
471 |
+ |
472 |
+ |
473 |
+add_entry ( 'gentoo', True, "/usr/portage" ) |
474 |
+add_entry ( 'foreign', False, False ) |