Skip to content

Commit bebc716

Browse files
committed
app: more versatile initialization for path in config
in case a manifest file is contained into some sub directories, the command to init a workspace locally should be ``` west init -l sub1/sub2 --mf west.yml ``` but in that case, the west top dir is going to be into `sub1` which is an issue. one workaround is to use: ``` west init -l sub1 --mf sub2/west.yml ``` but in that case, the config is initialized incorrectly: `manifest.path` contains only `sub1` and `manifest.file` is `sub2/west.yml`. `manifest.path` should contain a path, even if `--mf` is a relative path. `manifest.file` should only contain the filename. this change allows any usage so that the workspace top dir is created next to `sub1` and the manifest repo can be located into nested directories Signed-off-by: Cyril Fougeray <[email protected]>
1 parent 361004d commit bebc716

File tree

1 file changed

+40
-18
lines changed

1 file changed

+40
-18
lines changed

src/west/app/project.py

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
)
3737
from west.manifest import is_group as is_project_group
3838

39+
3940
#
4041
# Project-related or multi-repo commands, like "init", "update",
4142
# "diff", etc.
@@ -73,7 +74,7 @@ def _projects(self, ids, only_cloned=False):
7374
return self.manifest.get_projects(ids, only_cloned=only_cloned)
7475
except ValueError as ve:
7576
if len(ve.args) != 2:
76-
raise # not directly raised by get_projects()
77+
raise # not directly raised by get_projects()
7778

7879
# Die with an error message on unknown or uncloned projects.
7980
unknown, uncloned = ve.args
@@ -143,6 +144,7 @@ def has_output():
143144

144145
return has_output()
145146

147+
146148
class Init(_ProjectCommand):
147149

148150
def __init__(self):
@@ -204,13 +206,13 @@ def do_add_parser(self, parser_adder):
204206
help='''manifest repository branch or tag name
205207
to check out first; cannot be combined with -l''')
206208
parser.add_argument('--mf', '--manifest-file', dest='manifest_file',
207-
help='manifest file name to use')
209+
help='manifest file name to use, relative to "directory"')
208210
parser.add_argument('-l', '--local', action='store_true',
209-
help='''use "directory" as an existing local
210-
manifest repository instead of cloning one from
211-
MANIFEST_URL; .west is created next to "directory"
212-
in this case, and manifest.path points at
213-
"directory"''')
211+
help='''use "directory" to create the workspace
212+
from a local manifest directory, instead of cloning
213+
one from MANIFEST_URL; .west is created next to
214+
"directory" in this case, and manifest.path points at
215+
the manifest file location.''')
214216
parser.add_argument('--rename-delay', type=int,
215217
help='''Number of seconds to wait before renaming
216218
some temporary directories. Some filesystems like NTFS
@@ -273,7 +275,7 @@ def local(self, args) -> Path:
273275
manifest_filename = args.manifest_file or 'west.yml'
274276
manifest_file = manifest_dir / manifest_filename
275277
topdir = manifest_dir.parent
276-
rel_manifest = manifest_dir.name
278+
rel_manifest = manifest_file.parent.relative_to(manifest_dir.parent)
277279
west_dir = topdir / WEST_DIR
278280

279281
if not manifest_file.is_file():
@@ -287,7 +289,7 @@ def local(self, args) -> Path:
287289
os.chdir(topdir)
288290
self.config = Configuration(topdir=topdir)
289291
self.config.set('manifest.path', os.fspath(rel_manifest))
290-
self.config.set('manifest.file', manifest_filename)
292+
self.config.set('manifest.file', manifest_file.name)
291293

292294
return topdir
293295

@@ -412,6 +414,7 @@ def create(self, directory: Path, exist_ok: bool = True) -> None:
412414
except Exception as e:
413415
self.die(f"Can't create {directory}: {e}")
414416

417+
415418
class List(_ProjectCommand):
416419
def __init__(self):
417420
super().__init__(
@@ -554,6 +557,7 @@ def delay(func, project):
554557

555558
self.inf(result, colorize=False)
556559

560+
557561
class ManifestCommand(_ProjectCommand):
558562
# The slightly weird naming is to avoid a conflict with
559563
# west.manifest.Manifest.
@@ -617,7 +621,7 @@ def do_run(self, args, user_args):
617621
'sort_keys': False}
618622

619623
if args.validate:
620-
pass # nothing more to do
624+
pass # nothing more to do
621625
elif args.resolve:
622626
self._die_if_manifest_project_filter('resolve')
623627
self._dump(args, manifest.as_yaml(**dump_kwargs))
@@ -647,6 +651,7 @@ def _dump(self, args, to_dump):
647651
else:
648652
sys.stdout.write(to_dump)
649653

654+
650655
class Compare(_ProjectCommand):
651656
def __init__(self):
652657
super().__init__(
@@ -809,6 +814,7 @@ def print_status(self, project):
809814
self.small_banner('status:')
810815
self.inf(textwrap.indent(cp.stdout.decode().rstrip(), ' ' * 4))
811816

817+
812818
class Diff(_ProjectCommand):
813819
def __init__(self):
814820
super().__init__(
@@ -841,7 +847,7 @@ def do_run(self, args, user_args):
841847
color = ['--color=always'] if self.color_ui else []
842848
for project in self._cloned_projects(args, only_active=not args.all):
843849
diff_commit = (
844-
['manifest-rev'] # see #719 and #747
850+
['manifest-rev'] # see #719 and #747
845851
# Special-case the manifest repository while it's
846852
# still showing up in the 'projects' list. Yet
847853
# more evidence we should tackle #327.
@@ -875,6 +881,7 @@ def do_run(self, args, user_args):
875881
elif self.verbosity <= Verbosity.INF:
876882
self.inf(f"Empty diff in {no_diff} projects.")
877883

884+
878885
class Status(_ProjectCommand):
879886
def __init__(self):
880887
super().__init__(
@@ -924,6 +931,7 @@ def do_run(self, args, user_args):
924931
failed.append(project)
925932
self._handle_failed(args, failed)
926933

934+
927935
class Update(_ProjectCommand):
928936

929937
def __init__(self):
@@ -1238,7 +1246,7 @@ def update_submodules(self, project):
12381246
project.git(['submodule', 'sync', '--recursive'])
12391247
project.git(config_opts +
12401248
['submodule', 'update', '--init',
1241-
submodules_update_strategy, '--recursive'])
1249+
submodules_update_strategy, '--recursive'])
12421250
return
12431251
else:
12441252
# Cache used so convert to a list so that --reference can be used.
@@ -1265,8 +1273,8 @@ def update_submodules(self, project):
12651273
level=Verbosity.DBG_MORE)
12661274
project.git(config_opts +
12671275
['submodule', 'update',
1268-
'--init', submodules_update_strategy,
1269-
'--recursive'] + ref + [submodule.path])
1276+
'--init', submodules_update_strategy,
1277+
'--recursive'] + ref + [submodule.path])
12701278

12711279
def update(self, project):
12721280
if self.args.stats:
@@ -1658,6 +1666,7 @@ def decide_update_strategy(self, project, sha, stats, take_stats):
16581666
def project_is_active(self, project):
16591667
return self.manifest.is_active(project, extra_filter=self.group_filter)
16601668

1669+
16611670
class ForAll(_ProjectCommand):
16621671
def __init__(self):
16631672
super().__init__(
@@ -1737,6 +1746,7 @@ def do_run(self, args, user_args):
17371746
failed.append(project)
17381747
self._handle_failed(args, failed)
17391748

1749+
17401750
GREP_EPILOG = '''
17411751
EXAMPLES
17421752
--------
@@ -1835,11 +1845,12 @@ def do_run(self, args, user_args):
18351845
18361846
west config grep.color never
18371847
'''
1848+
1849+
18381850
# color.ui limitation:
18391851
# https://github.com/zephyrproject-rtos/west/issues/651
18401852

18411853
class Grep(_ProjectCommand):
1842-
18431854
# When adding a tool, make sure to check:
18441855
#
18451856
# - the 'failed' handling below for proper exit codes
@@ -1978,6 +1989,7 @@ def tool_args(self, tool, cmdline_args):
19781989

19791990
return ret
19801991

1992+
19811993
class Topdir(_ProjectCommand):
19821994
def __init__(self):
19831995
super().__init__(
@@ -1996,6 +2008,7 @@ def do_add_parser(self, parser_adder):
19962008
def do_run(self, args, user_args):
19972009
self.inf(PurePath(self.topdir).as_posix())
19982010

2011+
19992012
class SelfUpdate(_ProjectCommand):
20002013
def __init__(self):
20012014
super().__init__(
@@ -2009,6 +2022,7 @@ def do_add_parser(self, parser_adder):
20092022
def do_run(self, args, user_args):
20102023
self.die(self.description)
20112024

2025+
20122026
#
20132027
# Private helper routines.
20142028
#
@@ -2027,11 +2041,13 @@ def _clean_west_refspace(project):
20272041
delete_ref_cmd = ['update-ref', '-d', ref]
20282042
project.git(delete_ref_cmd)
20292043

2044+
20302045
def _update_manifest_rev(project, new_manifest_rev):
20312046
project.git(['update-ref',
20322047
'-m', f'west update: moving to {new_manifest_rev}',
20332048
QUAL_MANIFEST_REV, new_manifest_rev])
20342049

2050+
20352051
def _maybe_sha(rev):
20362052
# Return true if and only if the given revision might be a SHA.
20372053

@@ -2042,6 +2058,7 @@ def _maybe_sha(rev):
20422058

20432059
return len(rev) <= 40
20442060

2061+
20452062
def _rev_type(project, rev=None):
20462063
# Returns a "refined" revision type of rev (default:
20472064
# project.revision) as one of the following strings: 'tag', 'tree',
@@ -2067,7 +2084,7 @@ def _rev_type(project, rev=None):
20672084
return 'other'
20682085
elif stdout in ('blob', 'tree', 'tag'):
20692086
return stdout
2070-
elif stdout != 'commit': # just future-proofing
2087+
elif stdout != 'commit': # just future-proofing
20712088
return 'other'
20722089

20732090
# to tell branches, lightweight tags, and commits apart, we need rev-parse.
@@ -2095,6 +2112,7 @@ def _rev_type(project, rev=None):
20952112
else:
20962113
return 'other'
20972114

2115+
20982116
def _head_ok(project):
20992117
# Returns True if the reference 'HEAD' exists and is not a tag or remote
21002118
# ref (e.g. refs/remotes/origin/HEAD).
@@ -2110,6 +2128,7 @@ def _head_ok(project):
21102128
return project.git('show-ref --quiet --head /',
21112129
check=False).returncode == 0
21122130

2131+
21132132
def projects_unknown(manifest, projects):
21142133
# Retrieve the projects with get_projects(project,
21152134
# only_cloned=False). Return a pair: (projects, unknown)
@@ -2120,12 +2139,13 @@ def projects_unknown(manifest, projects):
21202139
return (manifest.get_projects(projects, only_cloned=False), None)
21212140
except ValueError as ve:
21222141
if len(ve.args) != 2:
2123-
raise # not directly raised by get_projects()
2142+
raise # not directly raised by get_projects()
21242143
unknown = ve.args[0]
21252144
if not unknown:
2126-
raise # only_cloned is False, so this "can't happen"
2145+
raise # only_cloned is False, so this "can't happen"
21272146
return (None, unknown)
21282147

2148+
21292149
#
21302150
# Special files and directories in the west workspace.
21312151
#
@@ -2163,6 +2183,7 @@ def projects_unknown(manifest, projects):
21632183
Regardless of the above, output is limited to cloned projects.
21642184
'''
21652185

2186+
21662187
#
21672188
# Helper class for creating format string keys that are expensive or
21682189
# undesirable to compute if not needed.
@@ -2190,6 +2211,7 @@ def __format__(self, format_spec):
21902211
self.as_str = str(self.obj)
21912212
return ('{:' + format_spec + '}').format(self.as_str)
21922213

2214+
21932215
#
21942216
# Logging helpers
21952217
#

0 commit comments

Comments
 (0)