Add a -V option which shows the version number of binman. For now this just uses a local 'version' file. Once the tool is packaged in some way we can figure out an approach that suits.
Signed-off-by: Simon Glass <s...@chromium.org> --- tools/binman/cmdline.py | 29 +++++++++++++++++++++++++++++ tools/binman/ftest.py | 20 ++++++++++++++++++++ tools/binman/state.py | 18 ++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py index 14ec95c25be..2229316f10e 100644 --- a/tools/binman/cmdline.py +++ b/tools/binman/cmdline.py @@ -5,7 +5,9 @@ """Command-line parser for binman""" +import argparse from argparse import ArgumentParser +import state def make_extract_parser(subparsers): """make_extract_parser: Make a subparser for the 'extract' command @@ -26,6 +28,32 @@ def make_extract_parser(subparsers): extract_parser.add_argument('-U', '--uncompressed', action='store_true', help='Output raw uncompressed data for compressed entries') + +#pylint: disable=R0903 +class BinmanVersion(argparse.Action): + """Handles the -V option to binman + + This reads the version information from a file called 'version' in the same + directory as this file. + + If not present it assumes this is running from the U-Boot tree and collects + the version from the Makefile. + + The format of the version information is three VAR = VALUE lines, for + example: + + VERSION = 2022 + PATCHLEVEL = 01 + EXTRAVERSION = -rc2 + """ + def __init__(self, nargs=0, **kwargs): + super().__init__(nargs=nargs, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + parser._print_message(f'Binman {state.GetVersion()}\n') + parser.exit() + + def ParseArgs(argv): """Parse the binman command-line arguments @@ -59,6 +87,7 @@ controlled by a description in the board device tree.''' parser.add_argument('-v', '--verbosity', default=1, type=int, help='Control verbosity: 0=silent, 1=warnings, 2=notices, ' '3=info, 4=detail, 5=debug') + parser.add_argument('-V', '--version', nargs=0, action=BinmanVersion) subparsers = parser.add_subparsers(dest='cmd') subparsers.required = True diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 6be003786e8..6a36e8f3158 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -4661,6 +4661,26 @@ class TestFunctional(unittest.TestCase): str(e.exception), "Not enough space in '.*u_boot_binman_embed_sm' for data length.*") + def testVersion(self): + """Test we can get the binman version""" + version = '(unreleased)' + self.assertEqual(version, state.GetVersion(self._indir)) + + with self.assertRaises(SystemExit): + with test_util.capture_sys_output() as (_, stderr): + self._DoBinman('-V') + self.assertEqual('Binman %s\n' % version, stderr.getvalue()) + + # Try running the tool too, just to be safe + result = self._RunBinman('-V') + self.assertEqual('Binman %s\n' % version, result.stderr) + + # Set up a version file to make sure that works + version = 'v2025.01-rc2' + tools.WriteFile(os.path.join(self._indir, 'version'), version, + binary=False) + self.assertEqual(version, state.GetVersion(self._indir)) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/state.py b/tools/binman/state.py index 9e5b8a39310..af0a65e8418 100644 --- a/tools/binman/state.py +++ b/tools/binman/state.py @@ -16,6 +16,8 @@ import os from patman import tools from patman import tout +OUR_PATH = os.path.dirname(os.path.realpath(__file__)) + # Map an dtb etype to its expected filename DTB_TYPE_FNAME = { 'u-boot-spl-dtb': 'spl/u-boot-spl.dtb', @@ -515,3 +517,19 @@ def TimingShow(): for name, seconds in duration.items(): print('%10s: %10.1fms' % (name, seconds * 1000)) + +def GetVersion(path=OUR_PATH): + """Get the version string for binman + + Args: + path: Path to 'version' file + + Returns: + str: String version, e.g. 'v2021.10' + """ + version_fname = os.path.join(path, 'version') + if os.path.exists(version_fname): + version = tools.ReadFile(version_fname, binary=False) + else: + version = '(unreleased)' + return version -- 2.34.0.rc2.393.gf8c9666880-goog