blob: b4b7212cfa020ae2d83e911d1f3e14f42a09aeaa [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 Bishop40320b12019-03-26 16:08:25 -040038import subprocess
Brad Bishopd7bf8c12018-02-25 22:55:05 -050039
40from collections import namedtuple
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041from distutils import spawn
42
43# External modules
Brad Bishop316dfdd2018-06-25 12:45:53 -040044scripts_path = os.path.dirname(os.path.realpath(__file__))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045lib_path = scripts_path + '/lib'
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050046sys.path.insert(0, lib_path)
Brad Bishop316dfdd2018-06-25 12:45:53 -040047import scriptpath
48scriptpath.add_oe_lib_path()
49
50# Check whether wic is running within eSDK environment
51sdkroot = scripts_path
52if os.environ.get('SDKTARGETSYSROOT'):
53 while sdkroot != '' and sdkroot != os.sep:
54 if os.path.exists(os.path.join(sdkroot, '.devtoolbase')):
55 # Set BUILDDIR for wic to work within eSDK
56 os.environ['BUILDDIR'] = sdkroot
57 # .devtoolbase only exists within eSDK
58 # If found, initialize bitbake path for eSDK environment and append to PATH
59 sdkroot = os.path.join(os.path.dirname(scripts_path), 'bitbake', 'bin')
60 os.environ['PATH'] += ":" + sdkroot
61 break
62 sdkroot = os.path.dirname(sdkroot)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050063
64bitbake_exe = spawn.find_executable('bitbake')
65if bitbake_exe:
Brad Bishop316dfdd2018-06-25 12:45:53 -040066 bitbake_path = scriptpath.add_bitbake_lib_path()
Brad Bishop40320b12019-03-26 16:08:25 -040067 import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050068
Brad Bishop6e60e8b2018-02-01 10:27:11 -050069from wic import WicError
Brad Bishopd7bf8c12018-02-25 22:55:05 -050070from wic.misc import get_bitbake_var, BB_VARS
Patrick Williamsc124f4f2015-09-15 14:41:29 -050071from wic import engine
72from wic import help as hlp
73
Brad Bishop6e60e8b2018-02-01 10:27:11 -050074
75def wic_logger():
76 """Create and convfigure wic logger."""
77 logger = logging.getLogger('wic')
78 logger.setLevel(logging.INFO)
79
80 handler = logging.StreamHandler()
81
82 formatter = logging.Formatter('%(levelname)s: %(message)s')
83 handler.setFormatter(formatter)
84
85 logger.addHandler(handler)
86
87 return logger
88
89logger = wic_logger()
90
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091def rootfs_dir_to_args(krootfs_dir):
92 """
93 Get a rootfs_dir dict and serialize to string
94 """
95 rootfs_dir = ''
96 for key, val in krootfs_dir.items():
97 rootfs_dir += ' '
98 rootfs_dir += '='.join([key, val])
99 return rootfs_dir.strip()
100
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500102class RootfsArgAction(argparse.Action):
103 def __init__(self, **kwargs):
104 super().__init__(**kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500105
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500106 def __call__(self, parser, namespace, value, option_string=None):
107 if not "rootfs_dir" in vars(namespace) or \
108 not type(namespace.__dict__['rootfs_dir']) is dict:
109 namespace.__dict__['rootfs_dir'] = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500111 if '=' in value:
112 (key, rootfs_dir) = value.split('=')
113 else:
114 key = 'ROOTFS_DIR'
115 rootfs_dir = value
116
117 namespace.__dict__['rootfs_dir'][key] = rootfs_dir
118
119
120def wic_create_subcommand(options, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500121 """
122 Command-line handling for image creation. The real work is done
123 by image.engine.wic_create()
124 """
Brad Bishop40320b12019-03-26 16:08:25 -0400125 if options.build_rootfs and not bitbake_exe:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500126 raise WicError("Can't build rootfs as bitbake is not in the $PATH")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127
128 if not options.image_name:
129 missed = []
130 for val, opt in [(options.rootfs_dir, 'rootfs-dir'),
131 (options.bootimg_dir, 'bootimg-dir'),
132 (options.kernel_dir, 'kernel-dir'),
133 (options.native_sysroot, 'native-sysroot')]:
134 if not val:
135 missed.append(opt)
136 if missed:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500137 raise WicError("The following build artifacts are not specified: %s" %
138 ", ".join(missed))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139
140 if options.image_name:
141 BB_VARS.default_image = options.image_name
142 else:
143 options.build_check = False
144
145 if options.vars_dir:
146 BB_VARS.vars_dir = options.vars_dir
147
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500148 if options.build_check and not engine.verify_build_env():
149 raise WicError("Couldn't verify build environment, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500150
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500151 if options.debug:
152 logger.setLevel(logging.DEBUG)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500153
154 if options.image_name:
155 if options.build_rootfs:
156 argv = ["bitbake", options.image_name]
157 if options.debug:
158 argv.append("--debug")
159
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500160 logger.info("Building rootfs...\n")
Brad Bishop40320b12019-03-26 16:08:25 -0400161 subprocess.check_call(argv)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500162
163 rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", options.image_name)
164 kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE", options.image_name)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500165 bootimg_dir = get_bitbake_var("STAGING_DATADIR", options.image_name)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500166
167 native_sysroot = options.native_sysroot
168 if options.vars_dir and not native_sysroot:
169 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", options.image_name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500170 else:
171 if options.build_rootfs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500172 raise WicError("Image name is not specified, exiting. "
173 "(Use -e/--image-name to specify it)")
174 native_sysroot = options.native_sysroot
175
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500176 if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500177 logger.info("Building wic-tools...\n")
Brad Bishop40320b12019-03-26 16:08:25 -0400178 subprocess.check_call(["bitbake", "wic-tools"])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500179 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500180
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500181 if not native_sysroot:
182 raise WicError("Unable to find the location of the native tools sysroot")
183
184 wks_file = options.wks_file
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500185
186 if not wks_file.endswith(".wks"):
187 wks_file = engine.find_canned_image(scripts_path, wks_file)
188 if not wks_file:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500189 raise WicError("No image named %s found, exiting. (Use 'wic list images' "
190 "to list available images, or specify a fully-qualified OE "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500191 "kickstart (.wks) filename)" % options.wks_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500192
193 if not options.image_name:
194 rootfs_dir = ''
195 if 'ROOTFS_DIR' in options.rootfs_dir:
196 rootfs_dir = options.rootfs_dir['ROOTFS_DIR']
197 bootimg_dir = options.bootimg_dir
198 kernel_dir = options.kernel_dir
199 native_sysroot = options.native_sysroot
200 if rootfs_dir and not os.path.isdir(rootfs_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500201 raise WicError("--rootfs-dir (-r) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500202 if not os.path.isdir(bootimg_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500203 raise WicError("--bootimg-dir (-b) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500204 if not os.path.isdir(kernel_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205 raise WicError("--kernel-dir (-k) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206 if not os.path.isdir(native_sysroot):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500207 raise WicError("--native-sysroot (-n) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500208 else:
209 not_found = not_found_dir = ""
210 if not os.path.isdir(rootfs_dir):
211 (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir)
212 elif not os.path.isdir(kernel_dir):
213 (not_found, not_found_dir) = ("kernel-dir", kernel_dir)
214 elif not os.path.isdir(native_sysroot):
215 (not_found, not_found_dir) = ("native-sysroot", native_sysroot)
216 if not_found:
217 if not not_found_dir:
218 not_found_dir = "Completely missing artifact - wrong image (.wks) used?"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500219 logger.info("Build artifacts not found, exiting.")
220 logger.info(" (Please check that the build artifacts for the machine")
221 logger.info(" selected in local.conf actually exist and that they")
222 logger.info(" are the correct artifacts for the image (.wks file)).\n")
223 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 -0500224
225 krootfs_dir = options.rootfs_dir
226 if krootfs_dir is None:
227 krootfs_dir = {}
228 krootfs_dir['ROOTFS_DIR'] = rootfs_dir
229
230 rootfs_dir = rootfs_dir_to_args(krootfs_dir)
231
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500232 logger.info("Creating image(s)...\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500234 native_sysroot, options)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235
236
237def wic_list_subcommand(args, usage_str):
238 """
239 Command-line handling for listing available images.
240 The real work is done by image.engine.wic_list()
241 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500242 if not engine.wic_list(args, scripts_path):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500243 raise WicError("Bad list arguments, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500244
245
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500246def wic_ls_subcommand(args, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500247 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500248 Command-line handling for list content of images.
249 The real work is done by engine.wic_ls()
250 """
251 engine.wic_ls(args, args.native_sysroot)
252
253def wic_cp_subcommand(args, usage_str):
254 """
255 Command-line handling for copying files/dirs to images.
256 The real work is done by engine.wic_cp()
257 """
258 engine.wic_cp(args, args.native_sysroot)
259
260def wic_rm_subcommand(args, usage_str):
261 """
262 Command-line handling for removing files/dirs from images.
263 The real work is done by engine.wic_rm()
264 """
265 engine.wic_rm(args, args.native_sysroot)
266
267def wic_write_subcommand(args, usage_str):
268 """
269 Command-line handling for writing images.
270 The real work is done by engine.wic_write()
271 """
272 engine.wic_write(args, args.native_sysroot)
273
274def wic_help_subcommand(args, usage_str):
275 """
276 Command-line handling for help subcommand to keep the current
277 structure of the function definitions.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500278 """
279 pass
280
281
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500282def wic_help_topic_subcommand(usage_str, help_str):
283 """
284 Display function for help 'sub-subcommands'.
285 """
286 print(help_str)
287 return
288
289
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500290wic_help_topic_usage = """
291"""
292
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500293helptopics = {
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500294 "plugins": [wic_help_topic_subcommand,
295 wic_help_topic_usage,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500296 hlp.wic_plugins_help],
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500297 "overview": [wic_help_topic_subcommand,
298 wic_help_topic_usage,
299 hlp.wic_overview_help],
300 "kickstart": [wic_help_topic_subcommand,
301 wic_help_topic_usage,
302 hlp.wic_kickstart_help],
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500303 "create": [wic_help_topic_subcommand,
304 wic_help_topic_usage,
305 hlp.wic_create_help],
306 "ls": [wic_help_topic_subcommand,
307 wic_help_topic_usage,
308 hlp.wic_ls_help],
309 "cp": [wic_help_topic_subcommand,
310 wic_help_topic_usage,
311 hlp.wic_cp_help],
312 "rm": [wic_help_topic_subcommand,
313 wic_help_topic_usage,
314 hlp.wic_rm_help],
315 "write": [wic_help_topic_subcommand,
316 wic_help_topic_usage,
317 hlp.wic_write_help],
318 "list": [wic_help_topic_subcommand,
319 wic_help_topic_usage,
320 hlp.wic_list_help]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500321}
322
323
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500324def wic_init_parser_create(subparser):
325 subparser.add_argument("wks_file")
326
327 subparser.add_argument("-o", "--outdir", dest="outdir", default='.',
328 help="name of directory to create image in")
329 subparser.add_argument("-e", "--image-name", dest="image_name",
330 help="name of the image to use the artifacts from "
331 "e.g. core-image-sato")
332 subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction,
333 help="path to the /rootfs dir to use as the "
334 ".wks rootfs source")
335 subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir",
336 help="path to the dir containing the boot artifacts "
337 "(e.g. /EFI or /syslinux dirs) to use as the "
338 ".wks bootimg source")
339 subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir",
340 help="path to the dir containing the kernel to use "
341 "in the .wks bootimg")
342 subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot",
343 help="path to the native sysroot containing the tools "
344 "to use to build the image")
345 subparser.add_argument("-s", "--skip-build-check", dest="build_check",
346 action="store_false", default=True, help="skip the build check")
347 subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs")
348 subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"),
349 dest='compressor',
350 help="compress image with specified compressor")
351 subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap")
352 subparser.add_argument("--no-fstab-update" ,action="store_true",
353 help="Do not change fstab file.")
354 subparser.add_argument("-v", "--vars", dest='vars_dir',
355 help="directory with <image>.env files that store "
356 "bitbake variables")
357 subparser.add_argument("-D", "--debug", dest="debug", action="store_true",
358 default=False, help="output debug information")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800359 subparser.add_argument("-i", "--imager", dest="imager",
360 default="direct", help="the wic imager plugin")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500361 return
362
363
364def wic_init_parser_list(subparser):
365 subparser.add_argument("list_type",
366 help="can be 'images' or 'source-plugins' "
367 "to obtain a list. "
368 "If value is a valid .wks image file")
369 subparser.add_argument("help_for", default=[], nargs='*',
370 help="If 'list_type' is a valid .wks image file "
371 "this value can be 'help' to show the help information "
372 "defined inside the .wks file")
373 return
374
375def imgtype(arg):
376 """
377 Custom type for ArgumentParser
378 Converts path spec to named tuple: (image, partition, path)
379 """
380 image = arg
381 part = path = None
382 if ':' in image:
383 image, part = image.split(':')
384 if '/' in part:
385 part, path = part.split('/', 1)
386 if not path:
387 path = '/'
388
389 if not os.path.isfile(image):
390 err = "%s is not a regular file or symlink" % image
391 raise argparse.ArgumentTypeError(err)
392
393 return namedtuple('ImgType', 'image part path')(image, part, path)
394
395def wic_init_parser_ls(subparser):
396 subparser.add_argument("path", type=imgtype,
397 help="image spec: <image>[:<vfat partition>[<path>]]")
398 subparser.add_argument("-n", "--native-sysroot",
399 help="path to the native sysroot containing the tools")
400
401def imgpathtype(arg):
402 img = imgtype(arg)
403 if img.part is None:
404 raise argparse.ArgumentTypeError("partition number is not specified")
405 return img
406
407def wic_init_parser_cp(subparser):
408 subparser.add_argument("src",
409 help="source spec")
410 subparser.add_argument("dest", type=imgpathtype,
411 help="image spec: <image>:<vfat partition>[<path>]")
412 subparser.add_argument("-n", "--native-sysroot",
413 help="path to the native sysroot containing the tools")
414
415def wic_init_parser_rm(subparser):
416 subparser.add_argument("path", type=imgpathtype,
417 help="path: <image>:<vfat partition><path>")
418 subparser.add_argument("-n", "--native-sysroot",
419 help="path to the native sysroot containing the tools")
420
421def expandtype(rules):
422 """
423 Custom type for ArgumentParser
424 Converts expand rules to the dictionary {<partition>: size}
425 """
426 if rules == 'auto':
427 return {}
428 result = {}
429 for rule in rules.split('-'):
430 try:
431 part, size = rule.split(':')
432 except ValueError:
433 raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule)
434
435 if not part.isdigit():
436 raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule)
437
438 # validate size
439 multiplier = 1
440 for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]:
441 if size.upper().endswith(suffix):
442 multiplier = mult
443 size = size[:-1]
444 break
445 if not size.isdigit():
446 raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule)
447
448 result[int(part)] = int(size) * multiplier
449
450 return result
451
452def wic_init_parser_write(subparser):
453 subparser.add_argument("image",
454 help="path to the wic image")
455 subparser.add_argument("target",
456 help="target file or device")
457 subparser.add_argument("-e", "--expand", type=expandtype,
458 help="expand rules: auto or <partition>:<size>[,<partition>:<size>]")
459 subparser.add_argument("-n", "--native-sysroot",
460 help="path to the native sysroot containing the tools")
461
462def wic_init_parser_help(subparser):
463 helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage)
464 for helptopic in helptopics:
465 helpparsers.add_parser(helptopic, help=helptopics[helptopic][2])
466 return
467
468
469subcommands = {
470 "create": [wic_create_subcommand,
471 hlp.wic_create_usage,
472 hlp.wic_create_help,
473 wic_init_parser_create],
474 "list": [wic_list_subcommand,
475 hlp.wic_list_usage,
476 hlp.wic_list_help,
477 wic_init_parser_list],
478 "ls": [wic_ls_subcommand,
479 hlp.wic_ls_usage,
480 hlp.wic_ls_help,
481 wic_init_parser_ls],
482 "cp": [wic_cp_subcommand,
483 hlp.wic_cp_usage,
484 hlp.wic_cp_help,
485 wic_init_parser_cp],
486 "rm": [wic_rm_subcommand,
487 hlp.wic_rm_usage,
488 hlp.wic_rm_help,
489 wic_init_parser_rm],
490 "write": [wic_write_subcommand,
491 hlp.wic_write_usage,
492 hlp.wic_write_help,
493 wic_init_parser_write],
494 "help": [wic_help_subcommand,
495 wic_help_topic_usage,
496 hlp.wic_help_help,
497 wic_init_parser_help]
498}
499
500
501def init_parser(parser):
502 parser.add_argument("--version", action="version",
503 version="%(prog)s {version}".format(version=__version__))
504 subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage)
505 for subcmd in subcommands:
506 subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2])
507 subcommands[subcmd][3](subparser)
508
509
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500510def main(argv):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500511 parser = argparse.ArgumentParser(
512 description="wic version %s" % __version__)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500513
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500514 init_parser(parser)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500515
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500516 args = parser.parse_args(argv)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500517
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500518 if "command" in vars(args):
519 if args.command == "help":
520 if args.help_topic is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500521 parser.print_help()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500522 print()
523 print("Please specify a help topic")
524 elif args.help_topic in helptopics:
525 hlpt = helptopics[args.help_topic]
526 hlpt[0](hlpt[1], hlpt[2])
527 return 0
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500528
529 return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands)
530
531
532if __name__ == "__main__":
533 try:
534 sys.exit(main(sys.argv[1:]))
535 except WicError as err:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500536 print()
537 logger.error(err)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500538 sys.exit(1)