77Parser and abstract data types for west manifests.
88'''
99
10+ import copy
1011import enum
1112import errno
1213import logging
@@ -182,6 +183,34 @@ def _err(message):
182183_logger = logging .getLogger (__name__ )
183184
184185
186+ # Representation of import-modifications
187+
188+
189+ class ImportModifications :
190+ """Represents `import-modifications` within a manifest."""
191+
192+ def __init__ (self , manifest_data : dict | None = None ):
193+ """Initialize a new ImportModifications instance."""
194+ self .url_replaces : list [tuple [str , str ]] = []
195+ self .append (manifest_data or {})
196+
197+ def append (self , manifest_data : dict ):
198+ """Append values from a manifest data (dictionary) to this instance."""
199+ for kind , values in manifest_data .get ('import-modifications' , {}).items ():
200+ if kind == 'url-replace' :
201+ self .url_replaces += [(v ['old' ], v ['new' ]) for v in values ]
202+
203+ def merge (self , other ):
204+ """Merge another ImportModifications instance into this one."""
205+ if not isinstance (other , ImportModifications ):
206+ raise TypeError (f"Unsupported type'{ type (other ).__name__ } '" )
207+ self .url_replaces += other .url_replaces
208+
209+ def copy (self ):
210+ """Return a deep copy of this instance."""
211+ return copy .deepcopy (self )
212+
213+
185214# Type for the submodule value passed through the manifest file.
186215class Submodule (NamedTuple ):
187216 '''Represents a Git submodule within a project.'''
@@ -456,6 +485,9 @@ class _import_ctx(NamedTuple):
456485 # Bit vector of flags that modify import behavior.
457486 import_flags : 'ImportFlag'
458487
488+ # import-modifications
489+ modifications : ImportModifications
490+
459491
460492def _imap_filter_allows (imap_filter : ImapFilterFnType , project : 'Project' ) -> bool :
461493 # imap_filter(project) if imap_filter is not None; True otherwise.
@@ -2052,6 +2084,7 @@ def get_option(option, default=None):
20522084 current_repo_abspath = current_repo_abspath ,
20532085 project_importer = project_importer ,
20542086 import_flags = import_flags ,
2087+ modifications = ImportModifications (),
20552088 )
20562089
20572090 def _recursive_init (self , ctx : _import_ctx ):
@@ -2074,6 +2107,10 @@ def _load_validated(self) -> None:
20742107
20752108 manifest_data = self ._ctx .current_data ['manifest' ]
20762109
2110+ # append values from resolved manifest_data to current context
2111+ new_modifications = ImportModifications (manifest_data )
2112+ self ._ctx .modifications .merge (new_modifications )
2113+
20772114 schema_version = str (manifest_data .get ('version' , SCHEMA_VERSION ))
20782115
20792116 # We want to make an ordered map from project names to
@@ -2322,6 +2359,7 @@ def _import_pathobj_from_self(self, pathobj_abs: Path, pathobj: Path) -> None:
23222359 current_abspath = pathobj_abs ,
23232360 current_relpath = pathobj ,
23242361 current_data = pathobj_abs .read_text (encoding = Manifest .encoding ),
2362+ modifications = self ._ctx .modifications .copy (),
23252363 )
23262364 try :
23272365 Manifest (topdir = self .topdir , internal_import_ctx = child_ctx )
@@ -2452,6 +2490,13 @@ def _load_project(self, pd: dict, url_bases: dict[str, str], defaults: _defaults
24522490 else :
24532491 self ._malformed (f'project { name } has no remote or url and no default remote is set' )
24542492
2493+ # modify the url
2494+ if url :
2495+ url_replaces = self ._ctx .modifications .url_replaces
2496+ for url_replace in reversed (url_replaces ):
2497+ old , new = url_replace
2498+ url = url .replace (old , new )
2499+
24552500 # The project's path needs to respect any import: path-prefix,
24562501 # regardless of self._ctx.import_flags. The 'ignore' type flags
24572502 # just mean ignore the imported data. The path-prefix in this
@@ -2672,6 +2717,7 @@ def _import_data_from_project(
26722717 # We therefore use a separate list for tracking them
26732718 # from our current list.
26742719 manifest_west_commands = [],
2720+ modifications = self ._ctx .modifications .copy (),
26752721 )
26762722 try :
26772723 submanifest = Manifest (topdir = self .topdir , internal_import_ctx = child_ctx )
0 commit comments