scripts: west_commands: refactor build.py
This is a prep work patch for adding another command. Refactor
build.py to use a new Forceable superclass and find_build_dir() helper
routine. Fix a help string while we are here.
Signed-off-by: Marti Bolivar <marti@foundries.io>
diff --git a/scripts/west_commands/zephyr_ext_common.py b/scripts/west_commands/zephyr_ext_common.py
new file mode 100644
index 0000000..bf9d7b7
--- /dev/null
+++ b/scripts/west_commands/zephyr_ext_common.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2018 Foundries.io
+#
+# SPDX-License-Identifier: Apache-2.0
+
+'''Helpers shared by multiple west extension command modules.
+
+Note that common helpers used by the flash and debug extension
+commands are in run_common -- that's for common code used by
+commands which specifically execute runners.'''
+
+import os
+
+from west import log
+from west.build import DEFAULT_BUILD_DIR, is_zephyr_build
+from west.commands import WestCommand
+
+BUILD_DIR_DESCRIPTION = '''\
+Explicitly sets the build directory. If not given and the current
+directory is a Zephyr build directory, it will be used; otherwise,
+"{}" is assumed.'''.format(DEFAULT_BUILD_DIR)
+
+
+def find_build_dir(dir):
+ '''Heuristic for finding a build directory.
+
+ If the given argument is truthy, it is returned. Otherwise, if
+ the current working directory is a build directory, it is
+ returned. Otherwise, west.build.DEFAULT_BUILD_DIR is returned.'''
+ if dir:
+ build_dir = dir
+ else:
+ cwd = os.getcwd()
+ if is_zephyr_build(cwd):
+ build_dir = cwd
+ else:
+ build_dir = DEFAULT_BUILD_DIR
+ return os.path.abspath(build_dir)
+
+
+class Forceable(WestCommand):
+ '''WestCommand subclass for commands with a --force option.'''
+
+ def add_force_arg(self, parser):
+ '''Add a -f / --force option to the parser.'''
+ parser.add_argument('-f', '--force', action='store_true',
+ help='Ignore any errors and try to proceed')
+
+ def check_force(self, cond, msg):
+ '''Abort if the command needs to be forced and hasn't been.
+
+ The "forced" predicate must be in self.args.forced.
+
+ If cond and self.args.force are both False, scream and die
+ with message msg. Otherwise, return. That is, "cond" is a
+ condition which means everything is OK; if it's False, only
+ self.args.force being True can allow execution to proceed.
+ '''
+ if not (cond or self.args.force):
+ log.err(msg)
+ log.die('refusing to proceed without --force due to above error')