binman: Make the tooldir configurable
Add a command-line argument for setting the tooldir, so that the default can be overridden. Add this directory to the toolpath automatically. Create the directory if it does not already exist. Put the default in the argument parser instead of the class, so that it is more obvious. Update a few tests that expect the utility name to be provided without any path (e.g. 'futility'), so they can accept a path, e.g. /path/to/futility Update the documentation and add a few tests. Improve the help for --toolpath while we are here. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
@@ -1415,7 +1415,15 @@ You can also use `--fetch all` to fetch all tools or `--fetch <tool>` to fetch
|
|||||||
a particular tool. Some tools are built from source code, in which case you will
|
a particular tool. Some tools are built from source code, in which case you will
|
||||||
need to have at least the `build-essential` and `git` packages installed.
|
need to have at least the `build-essential` and `git` packages installed.
|
||||||
|
|
||||||
Tools are fetched into the `~/.binman-tools` directory.
|
Tools are fetched into the `~/.binman-tools` directory. This directory is
|
||||||
|
automatically added to the toolpath so there is no need to use `--toolpath` to
|
||||||
|
specify it. If you want to use these tools outside binman, you may want to
|
||||||
|
add this directory to your `PATH`. For example, if you use bash, add this to
|
||||||
|
the end of `.bashrc`::
|
||||||
|
|
||||||
|
PATH="$HOME/.binman-tools:$PATH"
|
||||||
|
|
||||||
|
To select a custom directory, use the `--tooldir` option.
|
||||||
|
|
||||||
Bintool Documentation
|
Bintool Documentation
|
||||||
=====================
|
=====================
|
||||||
@@ -1435,8 +1443,9 @@ Binman commands and arguments
|
|||||||
|
|
||||||
Usage::
|
Usage::
|
||||||
|
|
||||||
binman [-h] [-B BUILD_DIR] [-D] [-H] [--toolpath TOOLPATH] [-T THREADS]
|
binman [-h] [-B BUILD_DIR] [-D] [--tooldir TOOLDIR] [-H]
|
||||||
[--test-section-timeout] [-v VERBOSITY] [-V]
|
[--toolpath TOOLPATH] [-T THREADS] [--test-section-timeout]
|
||||||
|
[-v VERBOSITY] [-V]
|
||||||
{build,bintool-docs,entry-docs,ls,extract,replace,test,tool} ...
|
{build,bintool-docs,entry-docs,ls,extract,replace,test,tool} ...
|
||||||
|
|
||||||
Binman provides the following commands:
|
Binman provides the following commands:
|
||||||
@@ -1461,11 +1470,13 @@ Options:
|
|||||||
-D, --debug
|
-D, --debug
|
||||||
Enabling debugging (provides a full traceback on error)
|
Enabling debugging (provides a full traceback on error)
|
||||||
|
|
||||||
|
--tooldir TOOLDIR Set the directory to store tools
|
||||||
|
|
||||||
-H, --full-help
|
-H, --full-help
|
||||||
Display the README file
|
Display the README file
|
||||||
|
|
||||||
--toolpath TOOLPATH
|
--toolpath TOOLPATH
|
||||||
Add a path to the directories containing tools
|
Add a path to the list of directories containing tools
|
||||||
|
|
||||||
-T THREADS, --threads THREADS
|
-T THREADS, --threads THREADS
|
||||||
Number of threads to use (0=single-thread). Note that -T0 is useful for
|
Number of threads to use (0=single-thread). Note that -T0 is useful for
|
||||||
|
@@ -51,8 +51,9 @@ class Bintool:
|
|||||||
# List of bintools to regard as missing
|
# List of bintools to regard as missing
|
||||||
missing_list = []
|
missing_list = []
|
||||||
|
|
||||||
# Directory to store tools
|
# Directory to store tools. Note that this set up by set_tool_dir() which
|
||||||
tooldir = os.path.join(os.getenv('HOME'), '.binman-tools')
|
# must be called before this class is used.
|
||||||
|
tooldir = ''
|
||||||
|
|
||||||
def __init__(self, name, desc, version_regex=None, version_args='-V'):
|
def __init__(self, name, desc, version_regex=None, version_args='-V'):
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -113,6 +114,11 @@ class Bintool:
|
|||||||
obj = cls(name)
|
obj = cls(name)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_tool_dir(cls, pathname):
|
||||||
|
"""Set the path to use to store and find tools"""
|
||||||
|
cls.tooldir = pathname
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
"""Show a line of information about a bintool"""
|
"""Show a line of information about a bintool"""
|
||||||
if self.is_present():
|
if self.is_present():
|
||||||
@@ -210,6 +216,7 @@ class Bintool:
|
|||||||
if result is not True:
|
if result is not True:
|
||||||
fname, tmpdir = result
|
fname, tmpdir = result
|
||||||
dest = os.path.join(self.tooldir, self.name)
|
dest = os.path.join(self.tooldir, self.name)
|
||||||
|
os.makedirs(self.tooldir, exist_ok=True)
|
||||||
print(f"- writing to '{dest}'")
|
print(f"- writing to '{dest}'")
|
||||||
shutil.move(fname, dest)
|
shutil.move(fname, dest)
|
||||||
if tmpdir:
|
if tmpdir:
|
||||||
|
@@ -134,8 +134,10 @@ class TestBintool(unittest.TestCase):
|
|||||||
dirname = os.path.join(self._indir, 'download_dir')
|
dirname = os.path.join(self._indir, 'download_dir')
|
||||||
os.mkdir(dirname)
|
os.mkdir(dirname)
|
||||||
fname = os.path.join(dirname, 'downloaded')
|
fname = os.path.join(dirname, 'downloaded')
|
||||||
|
|
||||||
|
# Rely on bintool to create this directory
|
||||||
destdir = os.path.join(self._indir, 'dest_dir')
|
destdir = os.path.join(self._indir, 'dest_dir')
|
||||||
os.mkdir(destdir)
|
|
||||||
dest_fname = os.path.join(destdir, '_testing')
|
dest_fname = os.path.join(destdir, '_testing')
|
||||||
self.seq = 0
|
self.seq = 0
|
||||||
|
|
||||||
@@ -344,6 +346,9 @@ class TestBintool(unittest.TestCase):
|
|||||||
|
|
||||||
def test_failed_command(self):
|
def test_failed_command(self):
|
||||||
"""Check that running a command that does not exist returns None"""
|
"""Check that running a command that does not exist returns None"""
|
||||||
|
destdir = os.path.join(self._indir, 'dest_dir')
|
||||||
|
os.mkdir(destdir)
|
||||||
|
with unittest.mock.patch.object(bintool.Bintool, 'tooldir', destdir):
|
||||||
btool = Bintool.create('_testing')
|
btool = Bintool.create('_testing')
|
||||||
result = btool.run_cmd_result('fred')
|
result = btool.run_cmd_result('fred')
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
import os
|
||||||
from binman import state
|
from binman import state
|
||||||
|
|
||||||
def make_extract_parser(subparsers):
|
def make_extract_parser(subparsers):
|
||||||
@@ -80,8 +81,11 @@ controlled by a description in the board device tree.'''
|
|||||||
help='Enabling debugging (provides a full traceback on error)')
|
help='Enabling debugging (provides a full traceback on error)')
|
||||||
parser.add_argument('-H', '--full-help', action='store_true',
|
parser.add_argument('-H', '--full-help', action='store_true',
|
||||||
default=False, help='Display the README file')
|
default=False, help='Display the README file')
|
||||||
|
parser.add_argument('--tooldir', type=str,
|
||||||
|
default=os.path.join(os.getenv('HOME'), '.binman-tools'),
|
||||||
|
help='Set the directory to store tools')
|
||||||
parser.add_argument('--toolpath', type=str, action='append',
|
parser.add_argument('--toolpath', type=str, action='append',
|
||||||
help='Add a path to the directories containing tools')
|
help='Add a path to the list of directories containing tools')
|
||||||
parser.add_argument('-T', '--threads', type=int,
|
parser.add_argument('-T', '--threads', type=int,
|
||||||
default=None, help='Number of threads to use (0=single-thread)')
|
default=None, help='Number of threads to use (0=single-thread)')
|
||||||
parser.add_argument('--test-section-timeout', action='store_true',
|
parser.add_argument('--test-section-timeout', action='store_true',
|
||||||
|
@@ -650,6 +650,14 @@ def Binman(args):
|
|||||||
from binman.image import Image
|
from binman.image import Image
|
||||||
from binman import state
|
from binman import state
|
||||||
|
|
||||||
|
tool_paths = []
|
||||||
|
if args.toolpath:
|
||||||
|
tool_paths += args.toolpath
|
||||||
|
if args.tooldir:
|
||||||
|
tool_paths.append(args.tooldir)
|
||||||
|
tools.set_tool_paths(tool_paths or None)
|
||||||
|
bintool.Bintool.set_tool_dir(args.tooldir)
|
||||||
|
|
||||||
if args.cmd in ['ls', 'extract', 'replace', 'tool']:
|
if args.cmd in ['ls', 'extract', 'replace', 'tool']:
|
||||||
try:
|
try:
|
||||||
tout.init(args.verbosity)
|
tout.init(args.verbosity)
|
||||||
@@ -667,7 +675,6 @@ def Binman(args):
|
|||||||
allow_resize=not args.fix_size, write_map=args.map)
|
allow_resize=not args.fix_size, write_map=args.map)
|
||||||
|
|
||||||
if args.cmd == 'tool':
|
if args.cmd == 'tool':
|
||||||
tools.set_tool_paths(args.toolpath)
|
|
||||||
if args.list:
|
if args.list:
|
||||||
bintool.Bintool.list_all()
|
bintool.Bintool.list_all()
|
||||||
elif args.fetch:
|
elif args.fetch:
|
||||||
@@ -719,7 +726,6 @@ def Binman(args):
|
|||||||
try:
|
try:
|
||||||
tools.set_input_dirs(args.indir)
|
tools.set_input_dirs(args.indir)
|
||||||
tools.prepare_output_dir(args.outdir, args.preserve)
|
tools.prepare_output_dir(args.outdir, args.preserve)
|
||||||
tools.set_tool_paths(args.toolpath)
|
|
||||||
state.SetEntryArgs(args.entry_arg)
|
state.SetEntryArgs(args.entry_arg)
|
||||||
state.SetThreads(args.threads)
|
state.SetThreads(args.threads)
|
||||||
|
|
||||||
|
@@ -1750,7 +1750,7 @@ class TestFunctional(unittest.TestCase):
|
|||||||
|
|
||||||
def _HandleGbbCommand(self, pipe_list):
|
def _HandleGbbCommand(self, pipe_list):
|
||||||
"""Fake calls to the futility utility"""
|
"""Fake calls to the futility utility"""
|
||||||
if pipe_list[0][0] == 'futility':
|
if 'futility' in pipe_list[0][0]:
|
||||||
fname = pipe_list[0][-1]
|
fname = pipe_list[0][-1]
|
||||||
# Append our GBB data to the file, which will happen every time the
|
# Append our GBB data to the file, which will happen every time the
|
||||||
# futility command is called.
|
# futility command is called.
|
||||||
@@ -1812,7 +1812,7 @@ class TestFunctional(unittest.TestCase):
|
|||||||
self._hash_data is False, it writes VBLOCK_DATA, else it writes a hash
|
self._hash_data is False, it writes VBLOCK_DATA, else it writes a hash
|
||||||
of the input data (here, 'input.vblock').
|
of the input data (here, 'input.vblock').
|
||||||
"""
|
"""
|
||||||
if pipe_list[0][0] == 'futility':
|
if 'futility' in pipe_list[0][0]:
|
||||||
fname = pipe_list[0][3]
|
fname = pipe_list[0][3]
|
||||||
with open(fname, 'wb') as fd:
|
with open(fname, 'wb') as fd:
|
||||||
if self._hash_data:
|
if self._hash_data:
|
||||||
@@ -6386,6 +6386,23 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
|||||||
self.assertEqual(['u-boot', 'atf-2'],
|
self.assertEqual(['u-boot', 'atf-2'],
|
||||||
fdt_util.GetStringList(node, 'loadables'))
|
fdt_util.GetStringList(node, 'loadables'))
|
||||||
|
|
||||||
|
def testTooldir(self):
|
||||||
|
"""Test that we can specify the tooldir"""
|
||||||
|
with test_util.capture_sys_output() as (stdout, stderr):
|
||||||
|
self.assertEqual(0, self._DoBinman('--tooldir', 'fred',
|
||||||
|
'tool', '-l'))
|
||||||
|
self.assertEqual('fred', bintool.Bintool.tooldir)
|
||||||
|
|
||||||
|
# Check that the toolpath is updated correctly
|
||||||
|
self.assertEqual(['fred'], tools.tool_search_paths)
|
||||||
|
|
||||||
|
# Try with a few toolpaths; the tooldir should be at the end
|
||||||
|
with test_util.capture_sys_output() as (stdout, stderr):
|
||||||
|
self.assertEqual(0, self._DoBinman(
|
||||||
|
'--toolpath', 'mary', '--toolpath', 'anna', '--tooldir', 'fred',
|
||||||
|
'tool', '-l'))
|
||||||
|
self.assertEqual(['mary', 'anna', 'fred'], tools.tool_search_paths)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Reference in New Issue
Block a user