Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9662139

Browse filesBrowse files
authored
runfiles: Apply repo mapping to Rlocation path (bazel-contrib#998)
1 parent 63379a4 commit 9662139
Copy full SHA for 9662139

File tree

6 files changed

+375
-7
lines changed
Filter options

6 files changed

+375
-7
lines changed

‎examples/bzlmod/MODULE.bazel

Copy file name to clipboardExpand all lines: examples/bzlmod/MODULE.bazel
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pip.parse(
2929
)
3030
use_repo(pip, "pip")
3131

32-
bazel_dep(name = "other_module", version = "")
32+
bazel_dep(name = "other_module", version = "", repo_name = "our_other_module")
3333
local_path_override(
3434
module_name = "other_module",
3535
path = "other_module",

‎examples/bzlmod/other_module/other_module/pkg/lib.py

Copy file name to clipboardExpand all lines: examples/bzlmod/other_module/other_module/pkg/lib.py
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ def GetRunfilePathWithCurrentRepository():
77
# For a non-main repository, the name of the runfiles directory is equal to
88
# the canonical repository name.
99
return r.Rlocation(own_repo + "/other_module/pkg/data/data.txt")
10+
11+
12+
def GetRunfilePathWithRepoMapping():
13+
return runfiles.Create().Rlocation("other_module/other_module/pkg/data/data.txt")

‎examples/bzlmod/runfiles/BUILD.bazel

Copy file name to clipboardExpand all lines: examples/bzlmod/runfiles/BUILD.bazel
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ py_test(
55
srcs = ["runfiles_test.py"],
66
data = [
77
"data/data.txt",
8-
"@other_module//other_module/pkg:data/data.txt",
8+
"@our_other_module//other_module/pkg:data/data.txt",
99
],
1010
env = {
1111
"DATA_RLOCATIONPATH": "$(rlocationpath data/data.txt)",
12-
"OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @other_module//other_module/pkg:data/data.txt)",
12+
"OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @our_other_module//other_module/pkg:data/data.txt)",
1313
},
1414
deps = [
15-
"@other_module//other_module/pkg:lib",
15+
"@our_other_module//other_module/pkg:lib",
1616
"@rules_python//python/runfiles",
1717
],
1818
)

‎examples/bzlmod/runfiles/runfiles_test.py

Copy file name to clipboardExpand all lines: examples/bzlmod/runfiles/runfiles_test.py
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,29 @@ class RunfilesTest(unittest.TestCase):
1111
def testCurrentRepository(self):
1212
self.assertEqual(runfiles.Create().CurrentRepository(), "")
1313

14+
def testRunfilesWithRepoMapping(self):
15+
data_path = runfiles.Create().Rlocation("example_bzlmod/runfiles/data/data.txt")
16+
with open(data_path) as f:
17+
self.assertEqual(f.read().strip(), "Hello, example_bzlmod!")
18+
1419
def testRunfileWithRlocationpath(self):
1520
data_rlocationpath = os.getenv("DATA_RLOCATIONPATH")
1621
data_path = runfiles.Create().Rlocation(data_rlocationpath)
1722
with open(data_path) as f:
1823
self.assertEqual(f.read().strip(), "Hello, example_bzlmod!")
1924

25+
def testRunfileInOtherModuleWithOurRepoMapping(self):
26+
data_path = runfiles.Create().Rlocation(
27+
"our_other_module/other_module/pkg/data/data.txt"
28+
)
29+
with open(data_path) as f:
30+
self.assertEqual(f.read().strip(), "Hello, other_module!")
31+
32+
def testRunfileInOtherModuleWithItsRepoMapping(self):
33+
data_path = lib.GetRunfilePathWithRepoMapping()
34+
with open(data_path) as f:
35+
self.assertEqual(f.read().strip(), "Hello, other_module!")
36+
2037
def testRunfileInOtherModuleWithCurrentRepository(self):
2138
data_path = lib.GetRunfilePathWithCurrentRepository()
2239
with open(data_path) as f:

‎python/runfiles/runfiles.py

Copy file name to clipboardExpand all lines: python/runfiles/runfiles.py
+62-3Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,12 @@ def __init__(self, strategy):
126126
# type: (Union[_ManifestBased, _DirectoryBased]) -> None
127127
self._strategy = strategy
128128
self._python_runfiles_root = _FindPythonRunfilesRoot()
129+
self._repo_mapping = _ParseRepoMapping(
130+
strategy.RlocationChecked("_repo_mapping")
131+
)
129132

130-
def Rlocation(self, path):
131-
# type: (str) -> Optional[str]
133+
def Rlocation(self, path, source_repo=None):
134+
# type: (str, Optional[str]) -> Optional[str]
132135
"""Returns the runtime path of a runfile.
133136
134137
Runfiles are data-dependencies of Bazel-built binaries and tests.
@@ -141,6 +144,13 @@ def Rlocation(self, path):
141144
142145
Args:
143146
path: string; runfiles-root-relative path of the runfile
147+
source_repo: string; optional; the canonical name of the repository
148+
whose repository mapping should be used to resolve apparent to
149+
canonical repository names in `path`. If `None` (default), the
150+
repository mapping of the repository containing the caller of this
151+
method is used. Explicitly setting this parameter should only be
152+
necessary for libraries that want to wrap the runfiles library. Use
153+
`CurrentRepository` to obtain canonical repository names.
144154
Returns:
145155
the path to the runfile, which the caller should check for existence, or
146156
None if the method doesn't know about this runfile
@@ -165,7 +175,31 @@ def Rlocation(self, path):
165175
raise ValueError('path is absolute without a drive letter: "%s"' % path)
166176
if os.path.isabs(path):
167177
return path
168-
return self._strategy.RlocationChecked(path)
178+
179+
if source_repo is None and self._repo_mapping:
180+
# Look up runfiles using the repository mapping of the caller of the
181+
# current method. If the repo mapping is empty, determining this
182+
# name is not necessary.
183+
source_repo = self.CurrentRepository(frame=2)
184+
185+
# Split off the first path component, which contains the repository
186+
# name (apparent or canonical).
187+
target_repo, _, remainder = path.partition("/")
188+
if not remainder or (source_repo, target_repo) not in self._repo_mapping:
189+
# One of the following is the case:
190+
# - not using Bzlmod, so the repository mapping is empty and
191+
# apparent and canonical repository names are the same
192+
# - target_repo is already a canonical repository name and does not
193+
# have to be mapped.
194+
# - path did not contain a slash and referred to a root symlink,
195+
# which also should not be mapped.
196+
return self._strategy.RlocationChecked(path)
197+
198+
# target_repo is an apparent repository name. Look up the corresponding
199+
# canonical repository name with respect to the current repository,
200+
# identified by its canonical name.
201+
target_canonical = self._repo_mapping[(source_repo, target_repo)]
202+
return self._strategy.RlocationChecked(target_canonical + "/" + remainder)
169203

170204
def EnvVars(self):
171205
# type: () -> Dict[str, str]
@@ -254,6 +288,31 @@ def _FindPythonRunfilesRoot():
254288
return root
255289

256290

291+
def _ParseRepoMapping(repo_mapping_path):
292+
# type: (Optional[str]) -> Dict[Tuple[str, str], str]
293+
"""Parses the repository mapping manifest."""
294+
# If the repository mapping file can't be found, that is not an error: We
295+
# might be running without Bzlmod enabled or there may not be any runfiles.
296+
# In this case, just apply an empty repo mapping.
297+
if not repo_mapping_path:
298+
return {}
299+
try:
300+
with open(repo_mapping_path, "r") as f:
301+
content = f.read()
302+
except FileNotFoundError:
303+
return {}
304+
305+
repo_mapping = {}
306+
for line in content.split("\n"):
307+
if not line:
308+
# Empty line following the last line break
309+
break
310+
current_canonical, target_local, target_canonical = line.split(",")
311+
repo_mapping[(current_canonical, target_local)] = target_canonical
312+
313+
return repo_mapping
314+
315+
257316
class _ManifestBased(object):
258317
"""`Runfiles` strategy that parses a runfiles-manifest to look up runfiles."""
259318

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.