]>
Commit | Line | Data |
---|---|---|
ea6245d2 | 1 | #!/usr/bin/env python3 |
95455ae4 TZ |
2 | # |
3 | # Copyright (c) 2013, Intel Corporation. | |
95455ae4 | 4 | # |
f8c9c511 | 5 | # SPDX-License-Identifier: GPL-2.0-only |
95455ae4 TZ |
6 | # |
7 | # DESCRIPTION 'wic' is the OpenEmbedded Image Creator that users can | |
8 | # use to generate bootable images. Invoking it without any arguments | |
9 | # will display help screens for the 'wic' command and list the | |
10 | # available 'wic' subcommands. Invoking a subcommand without any | |
11 | # arguments will likewise display help screens for the specified | |
12 | # subcommand. Please use that interface for detailed help. | |
13 | # | |
14 | # AUTHORS | |
15 | # Tom Zanussi <tom.zanussi (at] linux.intel.com> | |
16 | # | |
a0f8cb7e | 17 | __version__ = "0.2.0" |
95455ae4 | 18 | |
b11bfadb | 19 | # Python Standard Library modules |
95455ae4 TZ |
20 | import os |
21 | import sys | |
4fe9635c | 22 | import argparse |
95455ae4 | 23 | import logging |
0507ec4c | 24 | import subprocess |
8db6f74b EB |
25 | |
26 | from collections import namedtuple | |
9d86eb2e | 27 | from distutils import spawn |
95455ae4 | 28 | |
b11bfadb | 29 | # External modules |
dcea30b8 | 30 | scripts_path = os.path.dirname(os.path.realpath(__file__)) |
95455ae4 | 31 | lib_path = scripts_path + '/lib' |
59b1eefb | 32 | sys.path.insert(0, lib_path) |
8aba1fd0 CRSF |
33 | import scriptpath |
34 | scriptpath.add_oe_lib_path() | |
9d86eb2e | 35 | |
89df0d31 CRSF |
36 | # Check whether wic is running within eSDK environment |
37 | sdkroot = scripts_path | |
38 | if os.environ.get('SDKTARGETSYSROOT'): | |
39 | while sdkroot != '' and sdkroot != os.sep: | |
40 | if os.path.exists(os.path.join(sdkroot, '.devtoolbase')): | |
03fa13a2 CRSF |
41 | # Set BUILDDIR for wic to work within eSDK |
42 | os.environ['BUILDDIR'] = sdkroot | |
89df0d31 CRSF |
43 | # .devtoolbase only exists within eSDK |
44 | # If found, initialize bitbake path for eSDK environment and append to PATH | |
45 | sdkroot = os.path.join(os.path.dirname(scripts_path), 'bitbake', 'bin') | |
46 | os.environ['PATH'] += ":" + sdkroot | |
47 | break | |
48 | sdkroot = os.path.dirname(sdkroot) | |
49 | ||
9d86eb2e EB |
50 | bitbake_exe = spawn.find_executable('bitbake') |
51 | if bitbake_exe: | |
8aba1fd0 | 52 | bitbake_path = scriptpath.add_bitbake_lib_path() |
0507ec4c | 53 | import bb |
95455ae4 | 54 | |
15442d07 | 55 | from wic import WicError |
df906f3c | 56 | from wic.misc import get_bitbake_var, BB_VARS |
5dc02d57 EB |
57 | from wic import engine |
58 | from wic import help as hlp | |
95455ae4 | 59 | |
f7d9e33a EB |
60 | |
61 | def wic_logger(): | |
62 | """Create and convfigure wic logger.""" | |
63 | logger = logging.getLogger('wic') | |
64 | logger.setLevel(logging.INFO) | |
65 | ||
66 | handler = logging.StreamHandler() | |
67 | ||
68 | formatter = logging.Formatter('%(levelname)s: %(message)s') | |
69 | handler.setFormatter(formatter) | |
70 | ||
71 | logger.addHandler(handler) | |
72 | ||
73 | return logger | |
74 | ||
75 | logger = wic_logger() | |
76 | ||
719d093c JHFF |
77 | def rootfs_dir_to_args(krootfs_dir): |
78 | """ | |
79 | Get a rootfs_dir dict and serialize to string | |
80 | """ | |
81 | rootfs_dir = '' | |
872cb0d5 | 82 | for key, val in krootfs_dir.items(): |
719d093c | 83 | rootfs_dir += ' ' |
872cb0d5 | 84 | rootfs_dir += '='.join([key, val]) |
719d093c JHFF |
85 | return rootfs_dir.strip() |
86 | ||
719d093c | 87 | |
4fe9635c AR |
88 | class RootfsArgAction(argparse.Action): |
89 | def __init__(self, **kwargs): | |
90 | super().__init__(**kwargs) | |
91 | ||
92 | def __call__(self, parser, namespace, value, option_string=None): | |
93 | if not "rootfs_dir" in vars(namespace) or \ | |
94 | not type(namespace.__dict__['rootfs_dir']) is dict: | |
95 | namespace.__dict__['rootfs_dir'] = {} | |
96 | ||
97 | if '=' in value: | |
98 | (key, rootfs_dir) = value.split('=') | |
99 | else: | |
100 | key = 'ROOTFS_DIR' | |
101 | rootfs_dir = value | |
719d093c | 102 | |
4fe9635c | 103 | namespace.__dict__['rootfs_dir'][key] = rootfs_dir |
95455ae4 | 104 | |
4fe9635c AR |
105 | |
106 | def wic_create_subcommand(options, usage_str): | |
95455ae4 TZ |
107 | """ |
108 | Command-line handling for image creation. The real work is done | |
109 | by image.engine.wic_create() | |
110 | """ | |
0507ec4c | 111 | if options.build_rootfs and not bitbake_exe: |
131629ca | 112 | raise WicError("Can't build rootfs as bitbake is not in the $PATH") |
9d86eb2e | 113 | |
98912687 EB |
114 | if not options.image_name: |
115 | missed = [] | |
116 | for val, opt in [(options.rootfs_dir, 'rootfs-dir'), | |
117 | (options.bootimg_dir, 'bootimg-dir'), | |
118 | (options.kernel_dir, 'kernel-dir'), | |
119 | (options.native_sysroot, 'native-sysroot')]: | |
120 | if not val: | |
121 | missed.append(opt) | |
122 | if missed: | |
b7c19f1e EB |
123 | raise WicError("The following build artifacts are not specified: %s" % |
124 | ", ".join(missed)) | |
9116a17e | 125 | |
d4652335 EB |
126 | if options.image_name: |
127 | BB_VARS.default_image = options.image_name | |
128 | else: | |
95455ae4 TZ |
129 | options.build_check = False |
130 | ||
abdfad1c EB |
131 | if options.vars_dir: |
132 | BB_VARS.vars_dir = options.vars_dir | |
133 | ||
f7d9e33a | 134 | if options.build_check and not engine.verify_build_env(): |
b7c19f1e | 135 | raise WicError("Couldn't verify build environment, exiting") |
95455ae4 | 136 | |
f7d9e33a EB |
137 | if options.debug: |
138 | logger.setLevel(logging.DEBUG) | |
139 | ||
95455ae4 | 140 | if options.image_name: |
75ae0b7c EB |
141 | if options.build_rootfs: |
142 | argv = ["bitbake", options.image_name] | |
143 | if options.debug: | |
144 | argv.append("--debug") | |
145 | ||
f7d9e33a | 146 | logger.info("Building rootfs...\n") |
0507ec4c | 147 | subprocess.check_call(argv) |
75ae0b7c | 148 | |
3abe23bd EB |
149 | rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", options.image_name) |
150 | kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE", options.image_name) | |
afc486b6 | 151 | bootimg_dir = get_bitbake_var("STAGING_DATADIR", options.image_name) |
33ca15b9 EB |
152 | |
153 | native_sysroot = options.native_sysroot | |
154 | if options.vars_dir and not native_sysroot: | |
155 | native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", options.image_name) | |
75ae0b7c EB |
156 | else: |
157 | if options.build_rootfs: | |
b7c19f1e EB |
158 | raise WicError("Image name is not specified, exiting. " |
159 | "(Use -e/--image-name to specify it)") | |
0d005d09 EB |
160 | native_sysroot = options.native_sysroot |
161 | ||
522ac218 | 162 | if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)): |
f7d9e33a | 163 | logger.info("Building wic-tools...\n") |
0507ec4c | 164 | subprocess.check_call(["bitbake", "wic-tools"]) |
0d005d09 | 165 | native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools") |
522ac218 EB |
166 | |
167 | if not native_sysroot: | |
168 | raise WicError("Unable to find the location of the native tools sysroot") | |
75ae0b7c | 169 | |
4fe9635c | 170 | wks_file = options.wks_file |
95455ae4 TZ |
171 | |
172 | if not wks_file.endswith(".wks"): | |
13416c19 | 173 | wks_file = engine.find_canned_image(scripts_path, wks_file) |
95455ae4 | 174 | if not wks_file: |
b7c19f1e EB |
175 | raise WicError("No image named %s found, exiting. (Use 'wic list images' " |
176 | "to list available images, or specify a fully-qualified OE " | |
4fe9635c | 177 | "kickstart (.wks) filename)" % options.wks_file) |
95455ae4 | 178 | |
95455ae4 | 179 | if not options.image_name: |
719d093c JHFF |
180 | rootfs_dir = '' |
181 | if 'ROOTFS_DIR' in options.rootfs_dir: | |
182 | rootfs_dir = options.rootfs_dir['ROOTFS_DIR'] | |
95455ae4 TZ |
183 | bootimg_dir = options.bootimg_dir |
184 | kernel_dir = options.kernel_dir | |
185 | native_sysroot = options.native_sysroot | |
719d093c | 186 | if rootfs_dir and not os.path.isdir(rootfs_dir): |
131629ca | 187 | raise WicError("--rootfs-dir (-r) not found, exiting") |
24a585e3 | 188 | if not os.path.isdir(bootimg_dir): |
b7c19f1e | 189 | raise WicError("--bootimg-dir (-b) not found, exiting") |
24a585e3 | 190 | if not os.path.isdir(kernel_dir): |
b7c19f1e | 191 | raise WicError("--kernel-dir (-k) not found, exiting") |
24a585e3 | 192 | if not os.path.isdir(native_sysroot): |
b7c19f1e | 193 | raise WicError("--native-sysroot (-n) not found, exiting") |
a5b9ccad TZ |
194 | else: |
195 | not_found = not_found_dir = "" | |
196 | if not os.path.isdir(rootfs_dir): | |
197 | (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir) | |
a5b9ccad TZ |
198 | elif not os.path.isdir(kernel_dir): |
199 | (not_found, not_found_dir) = ("kernel-dir", kernel_dir) | |
200 | elif not os.path.isdir(native_sysroot): | |
201 | (not_found, not_found_dir) = ("native-sysroot", native_sysroot) | |
202 | if not_found: | |
203 | if not not_found_dir: | |
204 | not_found_dir = "Completely missing artifact - wrong image (.wks) used?" | |
b7c19f1e | 205 | logger.info("Build artifacts not found, exiting.") |
f7d9e33a EB |
206 | logger.info(" (Please check that the build artifacts for the machine") |
207 | logger.info(" selected in local.conf actually exist and that they") | |
208 | logger.info(" are the correct artifacts for the image (.wks file)).\n") | |
b7c19f1e | 209 | raise WicError("The artifact that couldn't be found was %s:\n %s", not_found, not_found_dir) |
95455ae4 | 210 | |
719d093c JHFF |
211 | krootfs_dir = options.rootfs_dir |
212 | if krootfs_dir is None: | |
ee71acc6 EB |
213 | krootfs_dir = {} |
214 | krootfs_dir['ROOTFS_DIR'] = rootfs_dir | |
719d093c JHFF |
215 | |
216 | rootfs_dir = rootfs_dir_to_args(krootfs_dir) | |
217 | ||
f7d9e33a | 218 | logger.info("Creating image(s)...\n") |
6b81c898 | 219 | engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir, |
f9f72c50 | 220 | native_sysroot, options) |
95455ae4 TZ |
221 | |
222 | ||
223 | def wic_list_subcommand(args, usage_str): | |
224 | """ | |
af0a6d54 EB |
225 | Command-line handling for listing available images. |
226 | The real work is done by image.engine.wic_list() | |
95455ae4 | 227 | """ |
af0a6d54 | 228 | if not engine.wic_list(args, scripts_path): |
b7c19f1e | 229 | raise WicError("Bad list arguments, exiting") |
95455ae4 TZ |
230 | |
231 | ||
ba461346 EB |
232 | def wic_ls_subcommand(args, usage_str): |
233 | """ | |
234 | Command-line handling for list content of images. | |
235 | The real work is done by engine.wic_ls() | |
236 | """ | |
237 | engine.wic_ls(args, args.native_sysroot) | |
238 | ||
f0dcf39d EB |
239 | def wic_cp_subcommand(args, usage_str): |
240 | """ | |
241 | Command-line handling for copying files/dirs to images. | |
242 | The real work is done by engine.wic_cp() | |
243 | """ | |
244 | engine.wic_cp(args, args.native_sysroot) | |
ba461346 | 245 | |
f8e42c13 EB |
246 | def wic_rm_subcommand(args, usage_str): |
247 | """ | |
248 | Command-line handling for removing files/dirs from images. | |
249 | The real work is done by engine.wic_rm() | |
250 | """ | |
251 | engine.wic_rm(args, args.native_sysroot) | |
252 | ||
ac5fc0d6 EB |
253 | def wic_write_subcommand(args, usage_str): |
254 | """ | |
255 | Command-line handling for writing images. | |
256 | The real work is done by engine.wic_write() | |
257 | """ | |
258 | engine.wic_write(args, args.native_sysroot) | |
259 | ||
4fe9635c | 260 | def wic_help_subcommand(args, usage_str): |
d03f39a9 | 261 | """ |
4fe9635c AR |
262 | Command-line handling for help subcommand to keep the current |
263 | structure of the function definitions. | |
d03f39a9 TZ |
264 | """ |
265 | pass | |
266 | ||
267 | ||
4fe9635c AR |
268 | def wic_help_topic_subcommand(usage_str, help_str): |
269 | """ | |
270 | Display function for help 'sub-subcommands'. | |
271 | """ | |
272 | print(help_str) | |
273 | return | |
274 | ||
275 | ||
d03f39a9 TZ |
276 | wic_help_topic_usage = """ |
277 | """ | |
278 | ||
4fe9635c | 279 | helptopics = { |
136137ec TZ |
280 | "plugins": [wic_help_topic_subcommand, |
281 | wic_help_topic_usage, | |
4fe9635c | 282 | hlp.wic_plugins_help], |
13416c19 | 283 | "overview": [wic_help_topic_subcommand, |
136137ec | 284 | wic_help_topic_usage, |
13416c19 EB |
285 | hlp.wic_overview_help], |
286 | "kickstart": [wic_help_topic_subcommand, | |
136137ec | 287 | wic_help_topic_usage, |
13416c19 | 288 | hlp.wic_kickstart_help], |
4fe9635c AR |
289 | "create": [wic_help_topic_subcommand, |
290 | wic_help_topic_usage, | |
291 | hlp.wic_create_help], | |
ba461346 EB |
292 | "ls": [wic_help_topic_subcommand, |
293 | wic_help_topic_usage, | |
294 | hlp.wic_ls_help], | |
f0dcf39d EB |
295 | "cp": [wic_help_topic_subcommand, |
296 | wic_help_topic_usage, | |
297 | hlp.wic_cp_help], | |
f8e42c13 EB |
298 | "rm": [wic_help_topic_subcommand, |
299 | wic_help_topic_usage, | |
300 | hlp.wic_rm_help], | |
ac5fc0d6 EB |
301 | "write": [wic_help_topic_subcommand, |
302 | wic_help_topic_usage, | |
303 | hlp.wic_write_help], | |
4fe9635c AR |
304 | "list": [wic_help_topic_subcommand, |
305 | wic_help_topic_usage, | |
306 | hlp.wic_list_help] | |
95455ae4 TZ |
307 | } |
308 | ||
309 | ||
4fe9635c AR |
310 | def wic_init_parser_create(subparser): |
311 | subparser.add_argument("wks_file") | |
312 | ||
313 | subparser.add_argument("-o", "--outdir", dest="outdir", default='.', | |
314 | help="name of directory to create image in") | |
2e7314ac PB |
315 | subparser.add_argument("-w", "--workdir", |
316 | help="temporary workdir to use for intermediate files") | |
4fe9635c AR |
317 | subparser.add_argument("-e", "--image-name", dest="image_name", |
318 | help="name of the image to use the artifacts from " | |
319 | "e.g. core-image-sato") | |
320 | subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction, | |
321 | help="path to the /rootfs dir to use as the " | |
322 | ".wks rootfs source") | |
323 | subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir", | |
324 | help="path to the dir containing the boot artifacts " | |
325 | "(e.g. /EFI or /syslinux dirs) to use as the " | |
326 | ".wks bootimg source") | |
327 | subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir", | |
328 | help="path to the dir containing the kernel to use " | |
329 | "in the .wks bootimg") | |
330 | subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot", | |
331 | help="path to the native sysroot containing the tools " | |
332 | "to use to build the image") | |
333 | subparser.add_argument("-s", "--skip-build-check", dest="build_check", | |
334 | action="store_false", default=True, help="skip the build check") | |
335 | subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs") | |
336 | subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"), | |
337 | dest='compressor', | |
338 | help="compress image with specified compressor") | |
339 | subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap") | |
00420ec4 FB |
340 | subparser.add_argument("--no-fstab-update" ,action="store_true", |
341 | help="Do not change fstab file.") | |
4fe9635c AR |
342 | subparser.add_argument("-v", "--vars", dest='vars_dir', |
343 | help="directory with <image>.env files that store " | |
344 | "bitbake variables") | |
345 | subparser.add_argument("-D", "--debug", dest="debug", action="store_true", | |
346 | default=False, help="output debug information") | |
f24c3538 DM |
347 | subparser.add_argument("-i", "--imager", dest="imager", |
348 | default="direct", help="the wic imager plugin") | |
4fe9635c AR |
349 | return |
350 | ||
351 | ||
352 | def wic_init_parser_list(subparser): | |
353 | subparser.add_argument("list_type", | |
354 | help="can be 'images' or 'source-plugins' " | |
355 | "to obtain a list. " | |
356 | "If value is a valid .wks image file") | |
357 | subparser.add_argument("help_for", default=[], nargs='*', | |
358 | help="If 'list_type' is a valid .wks image file " | |
359 | "this value can be 'help' to show the help information " | |
360 | "defined inside the .wks file") | |
361 | return | |
362 | ||
8db6f74b EB |
363 | def imgtype(arg): |
364 | """ | |
365 | Custom type for ArgumentParser | |
366 | Converts path spec to named tuple: (image, partition, path) | |
367 | """ | |
368 | image = arg | |
369 | part = path = None | |
370 | if ':' in image: | |
371 | image, part = image.split(':') | |
372 | if '/' in part: | |
373 | part, path = part.split('/', 1) | |
df5152c8 EB |
374 | if not path: |
375 | path = '/' | |
8db6f74b EB |
376 | |
377 | if not os.path.isfile(image): | |
378 | err = "%s is not a regular file or symlink" % image | |
379 | raise argparse.ArgumentTypeError(err) | |
380 | ||
381 | return namedtuple('ImgType', 'image part path')(image, part, path) | |
382 | ||
383 | def wic_init_parser_ls(subparser): | |
384 | subparser.add_argument("path", type=imgtype, | |
385 | help="image spec: <image>[:<vfat partition>[<path>]]") | |
386 | subparser.add_argument("-n", "--native-sysroot", | |
387 | help="path to the native sysroot containing the tools") | |
4fe9635c | 388 | |
df5152c8 EB |
389 | def imgpathtype(arg): |
390 | img = imgtype(arg) | |
391 | if img.part is None: | |
392 | raise argparse.ArgumentTypeError("partition number is not specified") | |
393 | return img | |
394 | ||
395 | def wic_init_parser_cp(subparser): | |
396 | subparser.add_argument("src", | |
bd669c18 CYL |
397 | help="image spec: <image>:<vfat partition>[<path>] or <file>") |
398 | subparser.add_argument("dest", | |
399 | help="image spec: <image>:<vfat partition>[<path>] or <file>") | |
df5152c8 EB |
400 | subparser.add_argument("-n", "--native-sysroot", |
401 | help="path to the native sysroot containing the tools") | |
402 | ||
234b20ae EB |
403 | def wic_init_parser_rm(subparser): |
404 | subparser.add_argument("path", type=imgpathtype, | |
405 | help="path: <image>:<vfat partition><path>") | |
406 | subparser.add_argument("-n", "--native-sysroot", | |
407 | help="path to the native sysroot containing the tools") | |
5cb7a329 CYL |
408 | subparser.add_argument("-r", dest="recursive_delete", action="store_true", default=False, |
409 | help="remove directories and their contents recursively, " | |
410 | " this only applies to ext* partition") | |
234b20ae | 411 | |
ac5fc0d6 EB |
412 | def expandtype(rules): |
413 | """ | |
414 | Custom type for ArgumentParser | |
415 | Converts expand rules to the dictionary {<partition>: size} | |
416 | """ | |
417 | if rules == 'auto': | |
418 | return {} | |
419 | result = {} | |
a210e28b | 420 | for rule in rules.split(','): |
ac5fc0d6 EB |
421 | try: |
422 | part, size = rule.split(':') | |
423 | except ValueError: | |
424 | raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule) | |
425 | ||
426 | if not part.isdigit(): | |
427 | raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule) | |
428 | ||
429 | # validate size | |
430 | multiplier = 1 | |
431 | for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]: | |
432 | if size.upper().endswith(suffix): | |
433 | multiplier = mult | |
434 | size = size[:-1] | |
435 | break | |
436 | if not size.isdigit(): | |
437 | raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule) | |
438 | ||
439 | result[int(part)] = int(size) * multiplier | |
440 | ||
441 | return result | |
442 | ||
443 | def wic_init_parser_write(subparser): | |
444 | subparser.add_argument("image", | |
445 | help="path to the wic image") | |
446 | subparser.add_argument("target", | |
447 | help="target file or device") | |
448 | subparser.add_argument("-e", "--expand", type=expandtype, | |
449 | help="expand rules: auto or <partition>:<size>[,<partition>:<size>]") | |
450 | subparser.add_argument("-n", "--native-sysroot", | |
451 | help="path to the native sysroot containing the tools") | |
452 | ||
4fe9635c AR |
453 | def wic_init_parser_help(subparser): |
454 | helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage) | |
455 | for helptopic in helptopics: | |
456 | helpparsers.add_parser(helptopic, help=helptopics[helptopic][2]) | |
457 | return | |
458 | ||
459 | ||
460 | subcommands = { | |
461 | "create": [wic_create_subcommand, | |
462 | hlp.wic_create_usage, | |
463 | hlp.wic_create_help, | |
464 | wic_init_parser_create], | |
465 | "list": [wic_list_subcommand, | |
466 | hlp.wic_list_usage, | |
467 | hlp.wic_list_help, | |
468 | wic_init_parser_list], | |
ba461346 EB |
469 | "ls": [wic_ls_subcommand, |
470 | hlp.wic_ls_usage, | |
471 | hlp.wic_ls_help, | |
472 | wic_init_parser_ls], | |
f0dcf39d EB |
473 | "cp": [wic_cp_subcommand, |
474 | hlp.wic_cp_usage, | |
475 | hlp.wic_cp_help, | |
476 | wic_init_parser_cp], | |
f8e42c13 EB |
477 | "rm": [wic_rm_subcommand, |
478 | hlp.wic_rm_usage, | |
479 | hlp.wic_rm_help, | |
480 | wic_init_parser_rm], | |
ac5fc0d6 EB |
481 | "write": [wic_write_subcommand, |
482 | hlp.wic_write_usage, | |
483 | hlp.wic_write_help, | |
484 | wic_init_parser_write], | |
4fe9635c AR |
485 | "help": [wic_help_subcommand, |
486 | wic_help_topic_usage, | |
487 | hlp.wic_help_help, | |
488 | wic_init_parser_help] | |
489 | } | |
490 | ||
491 | ||
492 | def init_parser(parser): | |
493 | parser.add_argument("--version", action="version", | |
494 | version="%(prog)s {version}".format(version=__version__)) | |
4e23b22b RB |
495 | parser.add_argument("-D", "--debug", dest="debug", action="store_true", |
496 | default=False, help="output debug information") | |
497 | ||
4fe9635c AR |
498 | subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage) |
499 | for subcmd in subcommands: | |
500 | subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2]) | |
501 | subcommands[subcmd][3](subparser) | |
502 | ||
d29d553c CYL |
503 | class WicArgumentParser(argparse.ArgumentParser): |
504 | def format_help(self): | |
505 | return hlp.wic_help | |
4fe9635c | 506 | |
8cb9ac37 | 507 | def main(argv): |
d29d553c | 508 | parser = WicArgumentParser( |
4fe9635c | 509 | description="wic version %s" % __version__) |
95455ae4 | 510 | |
4fe9635c | 511 | init_parser(parser) |
95455ae4 | 512 | |
4fe9635c | 513 | args = parser.parse_args(argv) |
d29d553c | 514 | |
4e23b22b RB |
515 | if args.debug: |
516 | logger.setLevel(logging.DEBUG) | |
95455ae4 | 517 | |
4fe9635c AR |
518 | if "command" in vars(args): |
519 | if args.command == "help": | |
520 | if args.help_topic is None: | |
95455ae4 | 521 | parser.print_help() |
4fe9635c AR |
522 | elif args.help_topic in helptopics: |
523 | hlpt = helptopics[args.help_topic] | |
524 | hlpt[0](hlpt[1], hlpt[2]) | |
525 | return 0 | |
95455ae4 | 526 | |
bd669c18 CYL |
527 | # validate wic cp src and dest parameter to identify which one of it is |
528 | # image and cast it into imgtype | |
529 | if args.command == "cp": | |
530 | if ":" in args.dest: | |
531 | args.dest = imgtype(args.dest) | |
532 | elif ":" in args.src: | |
533 | args.src = imgtype(args.src) | |
534 | else: | |
535 | raise argparse.ArgumentTypeError("no image or partition number specified.") | |
536 | ||
ebd9f7b1 | 537 | return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands) |
95455ae4 TZ |
538 | |
539 | ||
540 | if __name__ == "__main__": | |
541 | try: | |
e5e2c18c EB |
542 | sys.exit(main(sys.argv[1:])) |
543 | except WicError as err: | |
b7c19f1e | 544 | print() |
f7d9e33a | 545 | logger.error(err) |
e5e2c18c | 546 | sys.exit(1) |