From c96782cdea16de0d2bfe0ad208eccdb3dc1fb715 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Fri, 19 Jul 2024 17:09:16 +0200 Subject: [PATCH 1/2] app: project: Improve forall * Add environment variables when running forall for each project. * Add a "cwd" argument to execute the command in different directory Signed-off-by: Pieter De Gendt --- src/west/app/project.py | 30 ++++++++++++++++++++++++++++-- src/west/manifest.py | 1 + 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/west/app/project.py b/src/west/app/project.py index 0ffe1e5a..ec8a8c21 100644 --- a/src/west/app/project.py +++ b/src/west/app/project.py @@ -1598,6 +1598,18 @@ def __init__(self): Runs a shell (on a Unix OS) or batch (on Windows) command within the repository of each of the specified PROJECTs. + The following variables are set when running your command: + WEST_PROJECT_NAME + WEST_PROJECT_PATH + WEST_PROJECT_ABSPATH (depends on topdir) + WEST_PROJECT_REVISION + WEST_PROJECT_URL + WEST_PROJECT_REMOTE + + Use proper escaping, for example: + + west forall -c "echo \\$WEST_PROJECT_NAME" + If the command has multiple words, you must quote the -c option to prevent the shell from splitting it up. Since the command is run through the shell, you can use @@ -1615,6 +1627,9 @@ def do_add_parser(self, parser_adder): epilog=ACTIVE_CLONED_PROJECTS_HELP) parser.add_argument('-c', dest='subcommand', metavar='COMMAND', required=True) + parser.add_argument('-C', dest='cwd', + help='''run commands from this directory; + defaults to each project's paths if omitted''') parser.add_argument('-a', '--all', action='store_true', help='include inactive projects'), parser.add_argument('-g', '--group', dest='groups', @@ -1631,13 +1646,24 @@ def do_add_parser(self, parser_adder): def do_run(self, args, user_args): failed = [] group_set = set(args.groups) + env = os.environ.copy() for project in self._cloned_projects(args, only_active=not args.all): if group_set and not group_set.intersection(set(project.groups)): continue + + env["WEST_PROJECT_NAME"] = project.name + env["WEST_PROJECT_PATH"] = project.path + env["WEST_PROJECT_ABSPATH"] = project.abspath if project.abspath else '' + env["WEST_PROJECT_REVISION"] = project.revision + env["WEST_PROJECT_URL"] = project.url + env["WEST_PROJECT_REMOTE"] = project.remote_name + + cwd = args.cwd if args.cwd else project.abspath + self.banner( f'running "{args.subcommand}" in {project.name_and_path}:') - rc = subprocess.Popen(args.subcommand, shell=True, - cwd=project.abspath).wait() + rc = subprocess.Popen(args.subcommand, shell=True, env=env, + cwd=cwd).wait() if rc: failed.append(project) self._handle_failed(args, failed) diff --git a/src/west/manifest.py b/src/west/manifest.py index 4cabef51..57041eff 100644 --- a/src/west/manifest.py +++ b/src/west/manifest.py @@ -1145,6 +1145,7 @@ def __init__(self, path: Optional[PathType] = None, self.url: str = '' self.submodules = False self.revision: str = 'HEAD' + self.remote_name: str = '' self.clone_depth: Optional[int] = None self.groups = [] self.userdata: Optional[Any] = userdata From 196310688eeb6f8d302d0ff837a3828461531066 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Fri, 19 Jul 2024 22:08:27 +0200 Subject: [PATCH 2/2] tests: Add forall test cases Test using the environment variables in forall Signed-off-by: Pieter De Gendt --- tests/test_project.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/test_project.py b/tests/test_project.py index 985669f0..9a648775 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -16,7 +16,7 @@ from west.manifest import ImportFlag as MIF from conftest import create_branch, create_workspace, create_repo, \ add_commit, add_tag, check_output, cmd, GIT, rev_parse, \ - check_proj_consistency + check_proj_consistency, WINDOWS assert 'TOXTEMPDIR' in os.environ, "you must run these tests using tox" @@ -378,6 +378,16 @@ def test_forall(west_init_tmpdir): '=== running "echo foo" in net-tools (net-tools):', 'foo'] + # Use environment variables + + env_var = "%WEST_PROJECT_NAME%" if WINDOWS else "$WEST_PROJECT_NAME" + + assert cmd(f'forall -c "echo {env_var}"').splitlines() == [ + f'=== running "echo {env_var}" in manifest (zephyr):', + 'manifest', + f'=== running "echo {env_var}" in net-tools (net-tools):', + 'net-tools'] + cmd('update Kconfiglib') assert cmd('forall -c "echo foo"').splitlines() == [ '=== running "echo foo" in manifest (zephyr):',