]>
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 |
3966cbf5 | 25 | import shutil |
8db6f74b EB |
26 | |
27 | from collections import namedtuple | |
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 | ||
3966cbf5 | 50 | bitbake_exe = shutil.which('bitbake') |
9d86eb2e | 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 | ||
10681022 BP |
162 | if options.kernel_dir: |
163 | kernel_dir = options.kernel_dir | |
164 | ||
522ac218 | 165 | if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)): |
f7d9e33a | 166 | logger.info("Building wic-tools...\n") |
0507ec4c | 167 | subprocess.check_call(["bitbake", "wic-tools"]) |
0d005d09 | 168 | native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools") |
522ac218 EB |
169 | |
170 | if not native_sysroot: | |
171 | raise WicError("Unable to find the location of the native tools sysroot") | |
75ae0b7c | 172 | |
4fe9635c | 173 | wks_file = options.wks_file |
95455ae4 TZ |
174 | |
175 | if not wks_file.endswith(".wks"): | |
13416c19 | 176 | wks_file = engine.find_canned_image(scripts_path, wks_file) |
95455ae4 | 177 | if not wks_file: |
b7c19f1e EB |
178 | raise WicError("No image named %s found, exiting. (Use 'wic list images' " |
179 | "to list available images, or specify a fully-qualified OE " | |
4fe9635c | 180 | "kickstart (.wks) filename)" % options.wks_file) |
95455ae4 | 181 | |
95455ae4 | 182 | if not options.image_name: |
719d093c JHFF |
183 | rootfs_dir = '' |
184 | if 'ROOTFS_DIR' in options.rootfs_dir: | |
185 | rootfs_dir = options.rootfs_dir['ROOTFS_DIR'] | |
95455ae4 TZ |
186 | bootimg_dir = options.bootimg_dir |
187 | kernel_dir = options.kernel_dir | |
188 | native_sysroot = options.native_sysroot | |
719d093c | 189 | if rootfs_dir and not os.path.isdir(rootfs_dir): |
131629ca | 190 | raise WicError("--rootfs-dir (-r) not found, exiting") |
24a585e3 | 191 | if not os.path.isdir(bootimg_dir): |
b7c19f1e | 192 | raise WicError("--bootimg-dir (-b) not found, exiting") |
24a585e3 | 193 | if not os.path.isdir(kernel_dir): |
b7c19f1e | 194 | raise WicError("--kernel-dir (-k) not found, exiting") |
24a585e3 | 195 | if not os.path.isdir(native_sysroot): |
b7c19f1e | 196 | raise WicError("--native-sysroot (-n) not found, exiting") |
a5b9ccad TZ |
197 | else: |
198 | not_found = not_found_dir = "" | |
199 | if not os.path.isdir(rootfs_dir): | |
200 | (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir) | |
a5b9ccad TZ |
201 | elif not os.path.isdir(kernel_dir): |
202 | (not_found, not_found_dir) = ("kernel-dir", kernel_dir) | |
203 | elif not os.path.isdir(native_sysroot): | |
204 | (not_found, not_found_dir) = ("native-sysroot", native_sysroot) | |
205 | if not_found: | |
206 | if not not_found_dir: | |
207 | not_found_dir = "Completely missing artifact - wrong image (.wks) used?" | |
b7c19f1e | 208 | logger.info("Build artifacts not found, exiting.") |
f7d9e33a EB |
209 | logger.info(" (Please check that the build artifacts for the machine") |
210 | logger.info(" selected in local.conf actually exist and that they") | |
211 | logger.info(" are the correct artifacts for the image (.wks file)).\n") | |
e104c2b1 | 212 | raise WicError("The artifact that couldn't be found was %s:\n %s" % (not_found, not_found_dir)) |
95455ae4 | 213 | |
719d093c JHFF |
214 | krootfs_dir = options.rootfs_dir |
215 | if krootfs_dir is None: | |
ee71acc6 EB |
216 | krootfs_dir = {} |
217 | krootfs_dir['ROOTFS_DIR'] = rootfs_dir | |
719d093c JHFF |
218 | |
219 | rootfs_dir = rootfs_dir_to_args(krootfs_dir) | |
220 | ||
f7d9e33a | 221 | logger.info("Creating image(s)...\n") |
6b81c898 | 222 | engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir, |
f9f72c50 | 223 | native_sysroot, options) |
95455ae4 TZ |
224 | |
225 | ||
226 | def wic_list_subcommand(args, usage_str): | |
227 | """ | |
af0a6d54 EB |
228 | Command-line handling for listing available images. |
229 | The real work is done by image.engine.wic_list() | |
95455ae4 | 230 | """ |
af0a6d54 | 231 | if not engine.wic_list(args, scripts_path): |
b7c19f1e | 232 | raise WicError("Bad list arguments, exiting") |
95455ae4 TZ |
233 | |
234 | ||
ba461346 EB |
235 | def wic_ls_subcommand(args, usage_str): |
236 | """ | |
237 | Command-line handling for list content of images. | |
238 | The real work is done by engine.wic_ls() | |
239 | """ | |
240 | engine.wic_ls(args, args.native_sysroot) | |
241 | ||
f0dcf39d EB |
242 | def wic_cp_subcommand(args, usage_str): |
243 | """ | |
244 | Command-line handling for copying files/dirs to images. | |
245 | The real work is done by engine.wic_cp() | |
246 | """ | |
247 | engine.wic_cp(args, args.native_sysroot) | |
ba461346 | 248 | |
f8e42c13 EB |
249 | def wic_rm_subcommand(args, usage_str): |
250 | """ | |
251 | Command-line handling for removing files/dirs from images. | |
252 | The real work is done by engine.wic_rm() | |
253 | """ | |
254 | engine.wic_rm(args, args.native_sysroot) | |
255 | ||
ac5fc0d6 EB |
256 | def wic_write_subcommand(args, usage_str): |
257 | """ | |
258 | Command-line handling for writing images. | |
259 | The real work is done by engine.wic_write() | |
260 | """ | |
261 | engine.wic_write(args, args.native_sysroot) | |
262 | ||
4fe9635c | 263 | def wic_help_subcommand(args, usage_str): |
d03f39a9 | 264 | """ |
4fe9635c AR |
265 | Command-line handling for help subcommand to keep the current |
266 | structure of the function definitions. | |
d03f39a9 TZ |
267 | """ |
268 | pass | |
269 | ||
270 | ||
4fe9635c AR |
271 | def wic_help_topic_subcommand(usage_str, help_str): |
272 | """ | |
273 | Display function for help 'sub-subcommands'. | |
274 | """ | |
275 | print(help_str) | |
276 | return | |
277 | ||
278 | ||
d03f39a9 TZ |
279 | wic_help_topic_usage = """ |
280 | """ | |
281 | ||
4fe9635c | 282 | helptopics = { |
136137ec TZ |
283 | "plugins": [wic_help_topic_subcommand, |
284 | wic_help_topic_usage, | |
4fe9635c | 285 | hlp.wic_plugins_help], |
13416c19 | 286 | "overview": [wic_help_topic_subcommand, |
136137ec | 287 | wic_help_topic_usage, |
13416c19 EB |
288 | hlp.wic_overview_help], |
289 | "kickstart": [wic_help_topic_subcommand, | |
136137ec | 290 | wic_help_topic_usage, |
13416c19 | 291 | hlp.wic_kickstart_help], |
4fe9635c AR |
292 | "create": [wic_help_topic_subcommand, |
293 | wic_help_topic_usage, | |
294 | hlp.wic_create_help], | |
ba461346 EB |
295 | "ls": [wic_help_topic_subcommand, |
296 | wic_help_topic_usage, | |
297 | hlp.wic_ls_help], | |
f0dcf39d EB |
298 | "cp": [wic_help_topic_subcommand, |
299 | wic_help_topic_usage, | |
300 | hlp.wic_cp_help], | |
f8e42c13 EB |
301 | "rm": [wic_help_topic_subcommand, |
302 | wic_help_topic_usage, | |
303 | hlp.wic_rm_help], | |
ac5fc0d6 EB |
304 | "write": [wic_help_topic_subcommand, |
305 | wic_help_topic_usage, | |
306 | hlp.wic_write_help], | |
4fe9635c AR |
307 | "list": [wic_help_topic_subcommand, |
308 | wic_help_topic_usage, | |
309 | hlp.wic_list_help] | |
95455ae4 TZ |
310 | } |
311 | ||
312 | ||
4fe9635c AR |
313 | def wic_init_parser_create(subparser): |
314 | subparser.add_argument("wks_file") | |
315 | ||
316 | subparser.add_argument("-o", "--outdir", dest="outdir", default='.', | |
317 | help="name of directory to create image in") | |
2e7314ac PB |
318 | subparser.add_argument("-w", "--workdir", |
319 | help="temporary workdir to use for intermediate files") | |
4fe9635c AR |
320 | subparser.add_argument("-e", "--image-name", dest="image_name", |
321 | help="name of the image to use the artifacts from " | |
322 | "e.g. core-image-sato") | |
323 | subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction, | |
324 | help="path to the /rootfs dir to use as the " | |
325 | ".wks rootfs source") | |
326 | subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir", | |
327 | help="path to the dir containing the boot artifacts " | |
328 | "(e.g. /EFI or /syslinux dirs) to use as the " | |
329 | ".wks bootimg source") | |
330 | subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir", | |
331 | help="path to the dir containing the kernel to use " | |
332 | "in the .wks bootimg") | |
333 | subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot", | |
334 | help="path to the native sysroot containing the tools " | |
335 | "to use to build the image") | |
336 | subparser.add_argument("-s", "--skip-build-check", dest="build_check", | |
337 | action="store_false", default=True, help="skip the build check") | |
338 | subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs") | |
339 | subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"), | |
340 | dest='compressor', | |
341 | help="compress image with specified compressor") | |
342 | subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap") | |
00420ec4 FB |
343 | subparser.add_argument("--no-fstab-update" ,action="store_true", |
344 | help="Do not change fstab file.") | |
4fe9635c AR |
345 | subparser.add_argument("-v", "--vars", dest='vars_dir', |
346 | help="directory with <image>.env files that store " | |
347 | "bitbake variables") | |
348 | subparser.add_argument("-D", "--debug", dest="debug", action="store_true", | |
349 | default=False, help="output debug information") | |
f24c3538 DM |
350 | subparser.add_argument("-i", "--imager", dest="imager", |
351 | default="direct", help="the wic imager plugin") | |
f81b188b KK |
352 | subparser.add_argument("--extra-space", type=int, dest="extra_space", |
353 | default=0, help="additional free disk space to add to the image") | |
4fe9635c AR |
354 | return |
355 | ||
356 | ||
357 | def wic_init_parser_list(subparser): | |
358 | subparser.add_argument("list_type", | |
359 | help="can be 'images' or 'source-plugins' " | |
360 | "to obtain a list. " | |
361 | "If value is a valid .wks image file") | |
362 | subparser.add_argument("help_for", default=[], nargs='*', | |
363 | help="If 'list_type' is a valid .wks image file " | |
364 | "this value can be 'help' to show the help information " | |
365 | "defined inside the .wks file") | |
366 | return | |
367 | ||
8db6f74b EB |
368 | def imgtype(arg): |
369 | """ | |
370 | Custom type for ArgumentParser | |
371 | Converts path spec to named tuple: (image, partition, path) | |
372 | """ | |
373 | image = arg | |
374 | part = path = None | |
375 | if ':' in image: | |
376 | image, part = image.split(':') | |
377 | if '/' in part: | |
378 | part, path = part.split('/', 1) | |
df5152c8 EB |
379 | if not path: |
380 | path = '/' | |
8db6f74b EB |
381 | |
382 | if not os.path.isfile(image): | |
383 | err = "%s is not a regular file or symlink" % image | |
384 | raise argparse.ArgumentTypeError(err) | |
385 | ||
386 | return namedtuple('ImgType', 'image part path')(image, part, path) | |
387 | ||
388 | def wic_init_parser_ls(subparser): | |
389 | subparser.add_argument("path", type=imgtype, | |
390 | help="image spec: <image>[:<vfat partition>[<path>]]") | |
391 | subparser.add_argument("-n", "--native-sysroot", | |
392 | help="path to the native sysroot containing the tools") | |
4fe9635c | 393 | |
df5152c8 EB |
394 | def imgpathtype(arg): |
395 | img = imgtype(arg) | |
396 | if img.part is None: | |
397 | raise argparse.ArgumentTypeError("partition number is not specified") | |
398 | return img | |
399 | ||
400 | def wic_init_parser_cp(subparser): | |
401 | subparser.add_argument("src", | |
bd669c18 CYL |
402 | help="image spec: <image>:<vfat partition>[<path>] or <file>") |
403 | subparser.add_argument("dest", | |
404 | help="image spec: <image>:<vfat partition>[<path>] or <file>") | |
df5152c8 EB |
405 | subparser.add_argument("-n", "--native-sysroot", |
406 | help="path to the native sysroot containing the tools") | |
407 | ||
234b20ae EB |
408 | def wic_init_parser_rm(subparser): |
409 | subparser.add_argument("path", type=imgpathtype, | |
410 | help="path: <image>:<vfat partition><path>") | |
411 | subparser.add_argument("-n", "--native-sysroot", | |
412 | help="path to the native sysroot containing the tools") | |
5cb7a329 CYL |
413 | subparser.add_argument("-r", dest="recursive_delete", action="store_true", default=False, |
414 | help="remove directories and their contents recursively, " | |
415 | " this only applies to ext* partition") | |
234b20ae | 416 | |
ac5fc0d6 EB |
417 | def expandtype(rules): |
418 | """ | |
419 | Custom type for ArgumentParser | |
420 | Converts expand rules to the dictionary {<partition>: size} | |
421 | """ | |
422 | if rules == 'auto': | |
423 | return {} | |
424 | result = {} | |
a210e28b | 425 | for rule in rules.split(','): |
ac5fc0d6 EB |
426 | try: |
427 | part, size = rule.split(':') | |
428 | except ValueError: | |
429 | raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule) | |
430 | ||
431 | if not part.isdigit(): | |
432 | raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule) | |
433 | ||
434 | # validate size | |
435 | multiplier = 1 | |
436 | for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]: | |
437 | if size.upper().endswith(suffix): | |
438 | multiplier = mult | |
439 | size = size[:-1] | |
440 | break | |
441 | if not size.isdigit(): | |
442 | raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule) | |
443 | ||
444 | result[int(part)] = int(size) * multiplier | |
445 | ||
446 | return result | |
447 | ||
448 | def wic_init_parser_write(subparser): | |
449 | subparser.add_argument("image", | |
450 | help="path to the wic image") | |
451 | subparser.add_argument("target", | |
452 | help="target file or device") | |
453 | subparser.add_argument("-e", "--expand", type=expandtype, | |
454 | help="expand rules: auto or <partition>:<size>[,<partition>:<size>]") | |
455 | subparser.add_argument("-n", "--native-sysroot", | |
456 | help="path to the native sysroot containing the tools") | |
457 | ||
4fe9635c AR |
458 | def wic_init_parser_help(subparser): |
459 | helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage) | |
460 | for helptopic in helptopics: | |
461 | helpparsers.add_parser(helptopic, help=helptopics[helptopic][2]) | |
462 | return | |
463 | ||
464 | ||
465 | subcommands = { | |
466 | "create": [wic_create_subcommand, | |
467 | hlp.wic_create_usage, | |
468 | hlp.wic_create_help, | |
469 | wic_init_parser_create], | |
470 | "list": [wic_list_subcommand, | |
471 | hlp.wic_list_usage, | |
472 | hlp.wic_list_help, | |
473 | wic_init_parser_list], | |
ba461346 EB |
474 | "ls": [wic_ls_subcommand, |
475 | hlp.wic_ls_usage, | |
476 | hlp.wic_ls_help, | |
477 | wic_init_parser_ls], | |
f0dcf39d EB |
478 | "cp": [wic_cp_subcommand, |
479 | hlp.wic_cp_usage, | |
480 | hlp.wic_cp_help, | |
481 | wic_init_parser_cp], | |
f8e42c13 EB |
482 | "rm": [wic_rm_subcommand, |
483 | hlp.wic_rm_usage, | |
484 | hlp.wic_rm_help, | |
485 | wic_init_parser_rm], | |
ac5fc0d6 EB |
486 | "write": [wic_write_subcommand, |
487 | hlp.wic_write_usage, | |
488 | hlp.wic_write_help, | |
489 | wic_init_parser_write], | |
4fe9635c AR |
490 | "help": [wic_help_subcommand, |
491 | wic_help_topic_usage, | |
492 | hlp.wic_help_help, | |
493 | wic_init_parser_help] | |
494 | } | |
495 | ||
496 | ||
497 | def init_parser(parser): | |
498 | parser.add_argument("--version", action="version", | |
499 | version="%(prog)s {version}".format(version=__version__)) | |
4e23b22b RB |
500 | parser.add_argument("-D", "--debug", dest="debug", action="store_true", |
501 | default=False, help="output debug information") | |
502 | ||
4fe9635c AR |
503 | subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage) |
504 | for subcmd in subcommands: | |
505 | subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2]) | |
506 | subcommands[subcmd][3](subparser) | |
507 | ||
d29d553c CYL |
508 | class WicArgumentParser(argparse.ArgumentParser): |
509 | def format_help(self): | |
510 | return hlp.wic_help | |
4fe9635c | 511 | |
8cb9ac37 | 512 | def main(argv): |
d29d553c | 513 | parser = WicArgumentParser( |
4fe9635c | 514 | description="wic version %s" % __version__) |
95455ae4 | 515 | |
4fe9635c | 516 | init_parser(parser) |
95455ae4 | 517 | |
4fe9635c | 518 | args = parser.parse_args(argv) |
d29d553c | 519 | |
4e23b22b RB |
520 | if args.debug: |
521 | logger.setLevel(logging.DEBUG) | |
95455ae4 | 522 | |
4fe9635c AR |
523 | if "command" in vars(args): |
524 | if args.command == "help": | |
525 | if args.help_topic is None: | |
95455ae4 | 526 | parser.print_help() |
4fe9635c AR |
527 | elif args.help_topic in helptopics: |
528 | hlpt = helptopics[args.help_topic] | |
529 | hlpt[0](hlpt[1], hlpt[2]) | |
530 | return 0 | |
95455ae4 | 531 | |
bd669c18 CYL |
532 | # validate wic cp src and dest parameter to identify which one of it is |
533 | # image and cast it into imgtype | |
534 | if args.command == "cp": | |
535 | if ":" in args.dest: | |
536 | args.dest = imgtype(args.dest) | |
537 | elif ":" in args.src: | |
538 | args.src = imgtype(args.src) | |
539 | else: | |
540 | raise argparse.ArgumentTypeError("no image or partition number specified.") | |
541 | ||
ebd9f7b1 | 542 | return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands) |
95455ae4 TZ |
543 | |
544 | ||
545 | if __name__ == "__main__": | |
546 | try: | |
e5e2c18c EB |
547 | sys.exit(main(sys.argv[1:])) |
548 | except WicError as err: | |
b7c19f1e | 549 | print() |
f7d9e33a | 550 | logger.error(err) |
e5e2c18c | 551 | sys.exit(1) |