Skip to content

Commit 7570e23

Browse files
marc-hbpdgendt
authored andcommitted
configuration: anchor relative WEST_CONFIG_x paths to "west topdir"
Fixes zephyrproject-rtos#871. This could strictly speaking be considered as a backwards-compatible change, but I don't think it should because: 1. who in their sane mind would have intentionally relied on the behavior of their west commands to change depending on the current directory!? I think it is still very unlikely, but: 2. it's a bit more likely that some people always run west commands from their topdir directory _and_ leveraged that to saved a little bit of typing with a relative WEST_CONFIG_x definition(s). Or, maybe even used the same relative $WEST_CONFIG_x value across workspaces, i.e: topdir1/$WEST_CONFIG_x and topdir2/$WEST_CONFIG_x, etc. ? This commit breaks 1. but preserves 2. To be clear: this commit still does not "condone" relative WEST_CONFIG_x values; I don't think we should document that. But it makes their behavior _deterministic_ which is what matters. Signed-off-by: Marc Herbert <[email protected]>
1 parent a8ea1d7 commit 7570e23

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

src/west/configuration.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,15 @@ def __init__(self, topdir: PathType | None = None):
175175

176176
local_path = _location(ConfigFile.LOCAL, topdir=topdir, find_local=False) or None
177177

178-
self._system_path = Path(_location(ConfigFile.SYSTEM))
179-
self._global_path = Path(_location(ConfigFile.GLOBAL))
178+
self._system_path = Path(_location(ConfigFile.SYSTEM, topdir=topdir))
179+
self._global_path = Path(_location(ConfigFile.GLOBAL, topdir=topdir))
180180
self._local_path = Path(local_path) if local_path is not None else None
181181

182182
self._system = _InternalCF.from_path(self._system_path)
183183
self._global = _InternalCF.from_path(self._global_path)
184184
self._local = _InternalCF.from_path(self._local_path)
185185

186-
def get_paths(self, location: ConfigFile = ConfigFile.ALL):
186+
def get_paths(self, location: ConfigFile = ConfigFile.ALL) -> list[Path]:
187187
ret = []
188188
if self._global and location in [ConfigFile.GLOBAL, ConfigFile.ALL]:
189189
ret.append(self._global.path)
@@ -587,7 +587,22 @@ def delete_config(
587587
raise KeyError(f'{section}.{key}')
588588

589589

590+
def _rel_topdir_to_abs(p: PathType, topdir: PathType | None) -> str:
591+
# Converts a path relative to topdir to an absolute path.
592+
# , returns absolute paths unchanged.
593+
if os.path.isabs(p):
594+
return str(p)
595+
if topdir is None:
596+
raise WestNotFound(f"'{p}' is relative but 'west topdir' is not defined")
597+
return str(os.path.join(topdir, p))
598+
599+
590600
def _location(cfg: ConfigFile, topdir: PathType | None = None, find_local: bool = True) -> str:
601+
# Return the WEST_CONFIG_x environment variable if defined, or the
602+
# OS-specific default value. Anchors relative paths to
603+
# "topdir". Does _not_ check whether the file exists or if it is
604+
# readable or actually interact with the filesystem in any way.
605+
#
591606
# Making this a function that gets called each time you ask for a
592607
# configuration file makes it respect updated environment
593608
# variables (such as XDG_CONFIG_HOME, PROGRAMDATA) if they're set
@@ -607,7 +622,7 @@ def _location(cfg: ConfigFile, topdir: PathType | None = None, find_local: bool
607622
raise ValueError('ConfigFile.ALL has no location')
608623
elif cfg == ConfigFile.SYSTEM:
609624
if 'WEST_CONFIG_SYSTEM' in env:
610-
return env['WEST_CONFIG_SYSTEM']
625+
return _rel_topdir_to_abs(env['WEST_CONFIG_SYSTEM'], topdir)
611626

612627
plat = platform.system()
613628

@@ -637,15 +652,15 @@ def _location(cfg: ConfigFile, topdir: PathType | None = None, find_local: bool
637652
raise ValueError('unsupported platform ' + plat)
638653
elif cfg == ConfigFile.GLOBAL:
639654
if 'WEST_CONFIG_GLOBAL' in env:
640-
return env['WEST_CONFIG_GLOBAL']
655+
return _rel_topdir_to_abs(env['WEST_CONFIG_GLOBAL'], topdir)
641656

642657
if platform.system() == 'Linux' and 'XDG_CONFIG_HOME' in env:
643658
return os.path.join(env['XDG_CONFIG_HOME'], 'west', 'config')
644659

645660
return os.fspath(Path.home() / '.westconfig')
646661
elif cfg == ConfigFile.LOCAL:
647662
if 'WEST_CONFIG_LOCAL' in env:
648-
return env['WEST_CONFIG_LOCAL']
663+
return _rel_topdir_to_abs(env['WEST_CONFIG_LOCAL'], topdir)
649664

650665
if topdir:
651666
return os.fspath(Path(topdir) / WEST_DIR / 'config')

0 commit comments

Comments
 (0)