From aedfc5a5db1c4b2b80a36147c9a13b31764d91dd Mon Sep 17 00:00:00 2001 From: Paul Eggleton Date: Tue, 22 Dec 2015 17:03:11 +1300 Subject: devtool: add: allow specifying URL as positional argument Having to specify -f is a little bit ugly when a URI is distinctive enough to recognise amongst the other positional parameters, so take it as an optional positional parameter. -f/--fetch is still supported, but deprecated. Signed-off-by: Paul Eggleton Signed-off-by: Richard Purdie --- scripts/devtool | 2 ++ scripts/lib/argparse_oe.py | 16 +++++++++++++ scripts/lib/devtool/standard.py | 52 +++++++++++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/scripts/devtool b/scripts/devtool index 955495ea33..93ba58e7a9 100755 --- a/scripts/devtool +++ b/scripts/devtool @@ -280,6 +280,8 @@ def main(): if str(err): logger.error(str(err)) ret = 1 + except argparse_oe.ArgumentUsageError as ae: + parser.error_subcommand(ae.message, ae.subcommand) return ret diff --git a/scripts/lib/argparse_oe.py b/scripts/lib/argparse_oe.py index ec7eb8d191..fd866922bd 100644 --- a/scripts/lib/argparse_oe.py +++ b/scripts/lib/argparse_oe.py @@ -1,6 +1,12 @@ import sys import argparse +class ArgumentUsageError(Exception): + """Exception class you can raise (and catch) in order to show the help""" + def __init__(self, message, subcommand=None): + self.message = message + self.subcommand = subcommand + class ArgumentParser(argparse.ArgumentParser): """Our own version of argparse's ArgumentParser""" @@ -9,6 +15,16 @@ class ArgumentParser(argparse.ArgumentParser): self.print_help() sys.exit(2) + def error_subcommand(self, message, subcommand): + if subcommand: + for action in self._actions: + if isinstance(action, argparse._SubParsersAction): + for choice, subparser in action.choices.items(): + if choice == subcommand: + subparser.error(message) + return + self.error(message) + def add_subparsers(self, *args, **kwargs): ret = super(ArgumentParser, self).add_subparsers(*args, **kwargs) ret._parser_class = ArgumentSubParser diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index 6cdd44cd8d..e2496618a2 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py @@ -23,6 +23,7 @@ import shutil import tempfile import logging import argparse +import argparse_oe import scriptutils import errno from collections import OrderedDict @@ -37,16 +38,38 @@ def add(args, config, basepath, workspace): import bb import oe.recipeutils - if args.recipename and not args.srctree: - # These are positional arguments, but because we're nice, allow - # specifying source tree without name if we can detect that that - # is what the user meant + if not args.recipename and not args.srctree and not args.fetch and not args.fetchuri: + raise argparse_oe.ArgumentUsageError('At least one of recipename, srctree, fetchuri or -f/--fetch must be specified', 'add') + + # These are positional arguments, but because we're nice, allow + # specifying e.g. source tree without name, or fetch URI without name or + # source tree (if we can detect that that is what the user meant) + if '://' in args.recipename: + if not args.fetchuri: + if args.fetch: + raise DevtoolError('URI specified as positional argument as well as -f/--fetch') + args.fetchuri = args.recipename + args.recipename = '' + elif '://' in args.srctree: + if not args.fetchuri: + if args.fetch: + raise DevtoolError('URI specified as positional argument as well as -f/--fetch') + args.fetchuri = args.srctree + args.srctree = '' + elif args.recipename and not args.srctree: if os.sep in args.recipename: args.srctree = args.recipename args.recipename = None elif os.path.isdir(args.recipename): logger.warn('Ambiguous argument %s - assuming you mean it to be the recipe name') + if args.fetch: + if args.fetchuri: + raise DevtoolError('URI specified as positional argument as well as -f/--fetch') + else: + # FIXME should show a warning that -f/--fetch is deprecated here + args.fetchuri = args.fetch + if args.recipename: if args.recipename in workspace: raise DevtoolError("recipe %s is already in your workspace" % @@ -70,7 +93,7 @@ def add(args, config, basepath, workspace): tmpsrcdir = tempfile.mkdtemp(prefix='devtoolsrc', dir=srctreeparent) if srctree and os.path.exists(srctree): - if args.fetch: + if args.fetchuri: if not os.path.isdir(srctree): raise DevtoolError("Cannot fetch into source tree path %s as " "it exists and is not a directory" % @@ -79,20 +102,18 @@ def add(args, config, basepath, workspace): raise DevtoolError("Cannot fetch into source tree path %s as " "it already exists and is non-empty" % srctree) - elif not args.fetch: + elif not args.fetchuri: if args.srctree: raise DevtoolError("Specified source tree %s could not be found" % args.srctree) elif srctree: raise DevtoolError("No source tree exists at default path %s - " "either create and populate this directory, " - "or specify a path to a source tree, or use " - "the -f/--fetch option to fetch source code " - "and extract it to the source directory" % - srctree) + "or specify a path to a source tree, or a " + "URI to fetch source from" % srctree) else: raise DevtoolError("You must either specify a source tree " - "or -f to fetch source") + "or a URI to fetch source from") if args.version: if '_' in args.version or ' ' in args.version: @@ -103,8 +124,8 @@ def add(args, config, basepath, workspace): else: color = args.color extracmdopts = '' - if args.fetch: - source = args.fetch + if args.fetchuri: + source = args.fetchuri if srctree: extracmdopts += ' -x %s' % srctree else: @@ -1250,12 +1271,13 @@ def register_commands(subparsers, context): description='Adds a new recipe to the workspace to build a specified source tree. Can optionally fetch a remote URI and unpack it to create the source tree.') parser_add.add_argument('recipename', nargs='?', help='Name for new recipe to add (just name - no version, path or extension). If not specified, will attempt to auto-detect it.') parser_add.add_argument('srctree', nargs='?', help='Path to external source tree. If not specified, a subdirectory of %s will be used.' % defsrctree) + parser_add.add_argument('fetchuri', nargs='?', help='Fetch the specified URI and extract it to create the source tree') group = parser_add.add_mutually_exclusive_group() group.add_argument('--same-dir', '-s', help='Build in same directory as source', action="store_true") group.add_argument('--no-same-dir', help='Force build in a separate build directory', action="store_true") - parser_add.add_argument('--fetch', '-f', help='Fetch the specified URI and extract it to create the source tree', metavar='URI') + parser_add.add_argument('--fetch', '-f', help='Fetch the specified URI and extract it to create the source tree (deprecated - pass as positional argument instead)', metavar='URI') parser_add.add_argument('--version', '-V', help='Version to use within recipe (PV)') - parser_add.add_argument('--no-git', '-g', help='If -f/--fetch is specified, do not set up source tree as a git repository', action="store_true") + parser_add.add_argument('--no-git', '-g', help='If fetching source, do not set up source tree as a git repository', action="store_true") parser_add.add_argument('--binary', '-b', help='Treat the source tree as something that should be installed verbatim (no compilation, same directory structure). Useful with binary packages e.g. RPMs.', action='store_true') parser_add.set_defaults(func=add) -- cgit 1.2.3-korg