blob: 37dfe2dc58913af168881a9f0e458e218c11bcbc [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# Copyright (c) 2013, Intel Corporation.
6# All rights reserved.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21# DESCRIPTION 'wic' is the OpenEmbedded Image Creator that users can
22# use to generate bootable images. Invoking it without any arguments
23# will display help screens for the 'wic' command and list the
24# available 'wic' subcommands. Invoking a subcommand without any
25# arguments will likewise display help screens for the specified
26# subcommand. Please use that interface for detailed help.
27#
28# AUTHORS
29# Tom Zanussi <tom.zanussi (at] linux.intel.com>
30#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031__version__ = "0.2.0"
32
33# Python Standard Library modules
34import os
35import sys
Brad Bishopd7bf8c12018-02-25 22:55:05 -050036import argparse
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037import logging
Brad Bishopd7bf8c12018-02-25 22:55:05 -050038
39from collections import namedtuple
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040from distutils import spawn
41
42# External modules
Brad Bishop316dfdd2018-06-25 12:45:53 -040043scripts_path = os.path.dirname(os.path.realpath(__file__))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044lib_path = scripts_path + '/lib'
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050045sys.path.insert(0, lib_path)
Brad Bishop316dfdd2018-06-25 12:45:53 -040046import scriptpath
47scriptpath.add_oe_lib_path()
48
49# Check whether wic is running within eSDK environment
50sdkroot = scripts_path
51if os.environ.get('SDKTARGETSYSROOT'):
52 while sdkroot != '' and sdkroot != os.sep:
53 if os.path.exists(os.path.join(sdkroot, '.devtoolbase')):
54 # Set BUILDDIR for wic to work within eSDK
55 os.environ['BUILDDIR'] = sdkroot
56 # .devtoolbase only exists within eSDK
57 # If found, initialize bitbake path for eSDK environment and append to PATH
58 sdkroot = os.path.join(os.path.dirname(scripts_path), 'bitbake', 'bin')
59 os.environ['PATH'] += ":" + sdkroot
60 break
61 sdkroot = os.path.dirname(sdkroot)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050062
63bitbake_exe = spawn.find_executable('bitbake')
64if bitbake_exe:
Brad Bishop316dfdd2018-06-25 12:45:53 -040065 bitbake_path = scriptpath.add_bitbake_lib_path()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066 from bb import cookerdata
67 from bb.main import bitbake_main, BitBakeConfigParameters
68else:
69 bitbake_main = None
70
Brad Bishop6e60e8b2018-02-01 10:27:11 -050071from wic import WicError
Brad Bishopd7bf8c12018-02-25 22:55:05 -050072from wic.misc import get_bitbake_var, BB_VARS
Patrick Williamsc124f4f2015-09-15 14:41:29 -050073from wic import engine
74from wic import help as hlp
75
Brad Bishop6e60e8b2018-02-01 10:27:11 -050076
77def wic_logger():
78 """Create and convfigure wic logger."""
79 logger = logging.getLogger('wic')
80 logger.setLevel(logging.INFO)
81
82 handler = logging.StreamHandler()
83
84 formatter = logging.Formatter('%(levelname)s: %(message)s')
85 handler.setFormatter(formatter)
86
87 logger.addHandler(handler)
88
89 return logger
90
91logger = wic_logger()
92
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093def rootfs_dir_to_args(krootfs_dir):
94 """
95 Get a rootfs_dir dict and serialize to string
96 """
97 rootfs_dir = ''
98 for key, val in krootfs_dir.items():
99 rootfs_dir += ' '
100 rootfs_dir += '='.join([key, val])
101 return rootfs_dir.strip()
102
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500103
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500104class RootfsArgAction(argparse.Action):
105 def __init__(self, **kwargs):
106 super().__init__(**kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500107
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500108 def __call__(self, parser, namespace, value, option_string=None):
109 if not "rootfs_dir" in vars(namespace) or \
110 not type(namespace.__dict__['rootfs_dir']) is dict:
111 namespace.__dict__['rootfs_dir'] = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500113 if '=' in value:
114 (key, rootfs_dir) = value.split('=')
115 else:
116 key = 'ROOTFS_DIR'
117 rootfs_dir = value
118
119 namespace.__dict__['rootfs_dir'][key] = rootfs_dir
120
121
122def wic_create_subcommand(options, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500123 """
124 Command-line handling for image creation. The real work is done
125 by image.engine.wic_create()
126 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127 if options.build_rootfs and not bitbake_main:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500128 raise WicError("Can't build rootfs as bitbake is not in the $PATH")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129
130 if not options.image_name:
131 missed = []
132 for val, opt in [(options.rootfs_dir, 'rootfs-dir'),
133 (options.bootimg_dir, 'bootimg-dir'),
134 (options.kernel_dir, 'kernel-dir'),
135 (options.native_sysroot, 'native-sysroot')]:
136 if not val:
137 missed.append(opt)
138 if missed:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500139 raise WicError("The following build artifacts are not specified: %s" %
140 ", ".join(missed))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141
142 if options.image_name:
143 BB_VARS.default_image = options.image_name
144 else:
145 options.build_check = False
146
147 if options.vars_dir:
148 BB_VARS.vars_dir = options.vars_dir
149
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500150 if options.build_check and not engine.verify_build_env():
151 raise WicError("Couldn't verify build environment, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500153 if options.debug:
154 logger.setLevel(logging.DEBUG)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155
156 if options.image_name:
157 if options.build_rootfs:
158 argv = ["bitbake", options.image_name]
159 if options.debug:
160 argv.append("--debug")
161
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500162 logger.info("Building rootfs...\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163 if bitbake_main(BitBakeConfigParameters(argv),
164 cookerdata.CookerConfiguration()):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500165 raise WicError("bitbake exited with error")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500166
167 rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", options.image_name)
168 kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE", options.image_name)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500169 bootimg_dir = get_bitbake_var("STAGING_DATADIR", options.image_name)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500170
171 native_sysroot = options.native_sysroot
172 if options.vars_dir and not native_sysroot:
173 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", options.image_name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500174 else:
175 if options.build_rootfs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500176 raise WicError("Image name is not specified, exiting. "
177 "(Use -e/--image-name to specify it)")
178 native_sysroot = options.native_sysroot
179
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500180 if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500181 logger.info("Building wic-tools...\n")
182 if bitbake_main(BitBakeConfigParameters("bitbake wic-tools".split()),
183 cookerdata.CookerConfiguration()):
184 raise WicError("bitbake wic-tools failed")
185 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500187 if not native_sysroot:
188 raise WicError("Unable to find the location of the native tools sysroot")
189
190 wks_file = options.wks_file
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500191
192 if not wks_file.endswith(".wks"):
193 wks_file = engine.find_canned_image(scripts_path, wks_file)
194 if not wks_file:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500195 raise WicError("No image named %s found, exiting. (Use 'wic list images' "
196 "to list available images, or specify a fully-qualified OE "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500197 "kickstart (.wks) filename)" % options.wks_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500198
199 if not options.image_name:
200 rootfs_dir = ''
201 if 'ROOTFS_DIR' in options.rootfs_dir:
202 rootfs_dir = options.rootfs_dir['ROOTFS_DIR']
203 bootimg_dir = options.bootimg_dir
204 kernel_dir = options.kernel_dir
205 native_sysroot = options.native_sysroot
206 if rootfs_dir and not os.path.isdir(rootfs_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500207 raise WicError("--rootfs-dir (-r) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500208 if not os.path.isdir(bootimg_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500209 raise WicError("--bootimg-dir (-b) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500210 if not os.path.isdir(kernel_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500211 raise WicError("--kernel-dir (-k) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500212 if not os.path.isdir(native_sysroot):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500213 raise WicError("--native-sysroot (-n) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500214 else:
215 not_found = not_found_dir = ""
216 if not os.path.isdir(rootfs_dir):
217 (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir)
218 elif not os.path.isdir(kernel_dir):
219 (not_found, not_found_dir) = ("kernel-dir", kernel_dir)
220 elif not os.path.isdir(native_sysroot):
221 (not_found, not_found_dir) = ("native-sysroot", native_sysroot)
222 if not_found:
223 if not not_found_dir:
224 not_found_dir = "Completely missing artifact - wrong image (.wks) used?"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500225 logger.info("Build artifacts not found, exiting.")
226 logger.info(" (Please check that the build artifacts for the machine")
227 logger.info(" selected in local.conf actually exist and that they")
228 logger.info(" are the correct artifacts for the image (.wks file)).\n")
229 raise WicError("The artifact that couldn't be found was %s:\n %s", not_found, not_found_dir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230
231 krootfs_dir = options.rootfs_dir
232 if krootfs_dir is None:
233 krootfs_dir = {}
234 krootfs_dir['ROOTFS_DIR'] = rootfs_dir
235
236 rootfs_dir = rootfs_dir_to_args(krootfs_dir)
237
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500238 logger.info("Creating image(s)...\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500239 engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500240 native_sysroot, options)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500241
242
243def wic_list_subcommand(args, usage_str):
244 """
245 Command-line handling for listing available images.
246 The real work is done by image.engine.wic_list()
247 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248 if not engine.wic_list(args, scripts_path):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500249 raise WicError("Bad list arguments, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500250
251
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500252def wic_ls_subcommand(args, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500253 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500254 Command-line handling for list content of images.
255 The real work is done by engine.wic_ls()
256 """
257 engine.wic_ls(args, args.native_sysroot)
258
259def wic_cp_subcommand(args, usage_str):
260 """
261 Command-line handling for copying files/dirs to images.
262 The real work is done by engine.wic_cp()
263 """
264 engine.wic_cp(args, args.native_sysroot)
265
266def wic_rm_subcommand(args, usage_str):
267 """
268 Command-line handling for removing files/dirs from images.
269 The real work is done by engine.wic_rm()
270 """
271 engine.wic_rm(args, args.native_sysroot)
272
273def wic_write_subcommand(args, usage_str):
274 """
275 Command-line handling for writing images.
276 The real work is done by engine.wic_write()
277 """
278 engine.wic_write(args, args.native_sysroot)
279
280def wic_help_subcommand(args, usage_str):
281 """
282 Command-line handling for help subcommand to keep the current
283 structure of the function definitions.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500284 """
285 pass
286
287
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500288def wic_help_topic_subcommand(usage_str, help_str):
289 """
290 Display function for help 'sub-subcommands'.
291 """
292 print(help_str)
293 return
294
295
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500296wic_help_topic_usage = """
297"""
298
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500299helptopics = {
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500300 "plugins": [wic_help_topic_subcommand,
301 wic_help_topic_usage,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500302 hlp.wic_plugins_help],
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500303 "overview": [wic_help_topic_subcommand,
304 wic_help_topic_usage,
305 hlp.wic_overview_help],
306 "kickstart": [wic_help_topic_subcommand,
307 wic_help_topic_usage,
308 hlp.wic_kickstart_help],
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500309 "create": [wic_help_topic_subcommand,
310 wic_help_topic_usage,
311 hlp.wic_create_help],
312 "ls": [wic_help_topic_subcommand,
313 wic_help_topic_usage,
314 hlp.wic_ls_help],
315 "cp": [wic_help_topic_subcommand,
316 wic_help_topic_usage,
317 hlp.wic_cp_help],
318 "rm": [wic_help_topic_subcommand,
319 wic_help_topic_usage,
320 hlp.wic_rm_help],
321 "write": [wic_help_topic_subcommand,
322 wic_help_topic_usage,
323 hlp.wic_write_help],
324 "list": [wic_help_topic_subcommand,
325 wic_help_topic_usage,
326 hlp.wic_list_help]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500327}
328
329
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500330def wic_init_parser_create(subparser):
331 subparser.add_argument("wks_file")
332
333 subparser.add_argument("-o", "--outdir", dest="outdir", default='.',
334 help="name of directory to create image in")
335 subparser.add_argument("-e", "--image-name", dest="image_name",
336 help="name of the image to use the artifacts from "
337 "e.g. core-image-sato")
338 subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction,
339 help="path to the /rootfs dir to use as the "
340 ".wks rootfs source")
341 subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir",
342 help="path to the dir containing the boot artifacts "
343 "(e.g. /EFI or /syslinux dirs) to use as the "
344 ".wks bootimg source")
345 subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir",
346 help="path to the dir containing the kernel to use "
347 "in the .wks bootimg")
348 subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot",
349 help="path to the native sysroot containing the tools "
350 "to use to build the image")
351 subparser.add_argument("-s", "--skip-build-check", dest="build_check",
352 action="store_false", default=True, help="skip the build check")
353 subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs")
354 subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"),
355 dest='compressor',
356 help="compress image with specified compressor")
357 subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap")
358 subparser.add_argument("--no-fstab-update" ,action="store_true",
359 help="Do not change fstab file.")
360 subparser.add_argument("-v", "--vars", dest='vars_dir',
361 help="directory with <image>.env files that store "
362 "bitbake variables")
363 subparser.add_argument("-D", "--debug", dest="debug", action="store_true",
364 default=False, help="output debug information")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800365 subparser.add_argument("-i", "--imager", dest="imager",
366 default="direct", help="the wic imager plugin")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500367 return
368
369
370def wic_init_parser_list(subparser):
371 subparser.add_argument("list_type",
372 help="can be 'images' or 'source-plugins' "
373 "to obtain a list. "
374 "If value is a valid .wks image file")
375 subparser.add_argument("help_for", default=[], nargs='*',
376 help="If 'list_type' is a valid .wks image file "
377 "this value can be 'help' to show the help information "
378 "defined inside the .wks file")
379 return
380
381def imgtype(arg):
382 """
383 Custom type for ArgumentParser
384 Converts path spec to named tuple: (image, partition, path)
385 """
386 image = arg
387 part = path = None
388 if ':' in image:
389 image, part = image.split(':')
390 if '/' in part:
391 part, path = part.split('/', 1)
392 if not path:
393 path = '/'
394
395 if not os.path.isfile(image):
396 err = "%s is not a regular file or symlink" % image
397 raise argparse.ArgumentTypeError(err)
398
399 return namedtuple('ImgType', 'image part path')(image, part, path)
400
401def wic_init_parser_ls(subparser):
402 subparser.add_argument("path", type=imgtype,
403 help="image spec: <image>[:<vfat partition>[<path>]]")
404 subparser.add_argument("-n", "--native-sysroot",
405 help="path to the native sysroot containing the tools")
406
407def imgpathtype(arg):
408 img = imgtype(arg)
409 if img.part is None:
410 raise argparse.ArgumentTypeError("partition number is not specified")
411 return img
412
413def wic_init_parser_cp(subparser):
414 subparser.add_argument("src",
415 help="source spec")
416 subparser.add_argument("dest", type=imgpathtype,
417 help="image spec: <image>:<vfat partition>[<path>]")
418 subparser.add_argument("-n", "--native-sysroot",
419 help="path to the native sysroot containing the tools")
420
421def wic_init_parser_rm(subparser):
422 subparser.add_argument("path", type=imgpathtype,
423 help="path: <image>:<vfat partition><path>")
424 subparser.add_argument("-n", "--native-sysroot",
425 help="path to the native sysroot containing the tools")
426
427def expandtype(rules):
428 """
429 Custom type for ArgumentParser
430 Converts expand rules to the dictionary {<partition>: size}
431 """
432 if rules == 'auto':
433 return {}
434 result = {}
435 for rule in rules.split('-'):
436 try:
437 part, size = rule.split(':')
438 except ValueError:
439 raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule)
440
441 if not part.isdigit():
442 raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule)
443
444 # validate size
445 multiplier = 1
446 for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]:
447 if size.upper().endswith(suffix):
448 multiplier = mult
449 size = size[:-1]
450 break
451 if not size.isdigit():
452 raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule)
453
454 result[int(part)] = int(size) * multiplier
455
456 return result
457
458def wic_init_parser_write(subparser):
459 subparser.add_argument("image",
460 help="path to the wic image")
461 subparser.add_argument("target",
462 help="target file or device")
463 subparser.add_argument("-e", "--expand", type=expandtype,
464 help="expand rules: auto or <partition>:<size>[,<partition>:<size>]")
465 subparser.add_argument("-n", "--native-sysroot",
466 help="path to the native sysroot containing the tools")
467
468def wic_init_parser_help(subparser):
469 helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage)
470 for helptopic in helptopics:
471 helpparsers.add_parser(helptopic, help=helptopics[helptopic][2])
472 return
473
474
475subcommands = {
476 "create": [wic_create_subcommand,
477 hlp.wic_create_usage,
478 hlp.wic_create_help,
479 wic_init_parser_create],
480 "list": [wic_list_subcommand,
481 hlp.wic_list_usage,
482 hlp.wic_list_help,
483 wic_init_parser_list],
484 "ls": [wic_ls_subcommand,
485 hlp.wic_ls_usage,
486 hlp.wic_ls_help,
487 wic_init_parser_ls],
488 "cp": [wic_cp_subcommand,
489 hlp.wic_cp_usage,
490 hlp.wic_cp_help,
491 wic_init_parser_cp],
492 "rm": [wic_rm_subcommand,
493 hlp.wic_rm_usage,
494 hlp.wic_rm_help,
495 wic_init_parser_rm],
496 "write": [wic_write_subcommand,
497 hlp.wic_write_usage,
498 hlp.wic_write_help,
499 wic_init_parser_write],
500 "help": [wic_help_subcommand,
501 wic_help_topic_usage,
502 hlp.wic_help_help,
503 wic_init_parser_help]
504}
505
506
507def init_parser(parser):
508 parser.add_argument("--version", action="version",
509 version="%(prog)s {version}".format(version=__version__))
510 subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage)
511 for subcmd in subcommands:
512 subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2])
513 subcommands[subcmd][3](subparser)
514
515
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500516def main(argv):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500517 parser = argparse.ArgumentParser(
518 description="wic version %s" % __version__)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500519
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500520 init_parser(parser)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500521
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500522 args = parser.parse_args(argv)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500523
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500524 if "command" in vars(args):
525 if args.command == "help":
526 if args.help_topic is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500527 parser.print_help()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500528 print()
529 print("Please specify a help topic")
530 elif args.help_topic in helptopics:
531 hlpt = helptopics[args.help_topic]
532 hlpt[0](hlpt[1], hlpt[2])
533 return 0
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500534
535 return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands)
536
537
538if __name__ == "__main__":
539 try:
540 sys.exit(main(sys.argv[1:]))
541 except WicError as err:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500542 print()
543 logger.error(err)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500544 sys.exit(1)