Skip to content

Commit

Permalink
[8.1.0] Add repository_ctx.original_name (#25191)
Browse files Browse the repository at this point in the history
This new attribute contains the original value of the `name` attribute
at the instantiation site of the repo rule (e.g., `rctx.original_name`
would be `foo` if `rctx.name` is `+ext+foo`).

Fixes #24467

Closes #25121.

RELNOTES: Added `repository_ctx.original_name`, which contains the
original value of the `name` attribute as specified at the repo rule
call site.

PiperOrigin-RevId: 722731393
Change-Id: I2f7dada0c44b6bd4c0d2622fa1e97223382a8547 
(cherry picked from commit 8bcfb06)

Fixes #25147
  • Loading branch information
fmeum authored Feb 5, 2025
1 parent 45589ad commit b016ff3
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.StructProvider;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.repository.RepositoryFetchProgress;
import com.google.devtools.build.lib.rules.repository.NeedsSkyframeRestartException;
Expand Down Expand Up @@ -143,11 +144,33 @@ public ImmutableMap<RepoRecordedInput.DirTree, String> getRecordedDirTreeInputs(
@StarlarkMethod(
name = "name",
structField = true,
doc = "The name of the external repository created by this rule.")
doc =
"The canonical name of the external repository created by this rule. This name is"
+ " guaranteed to be unique among all external repositories, but its exact format is"
+ " not specified. Use <a href='#original_name'><code>original_name</code></a>"
+ " instead to get the name that was originally specified as the <code>name</code>"
+ " when this repository rule was instantiated.")
public String getName() {
return rule.getName();
}

@StarlarkMethod(
name = "original_name",
structField = true,
doc =
"The name that was originally specified as the <code>name</code> attribute when this"
+ " repository rule was instantiated. This name is not necessarily unique among"
+ " external repositories. Use <a href='#name'><code>name</code></a> instead to get"
+ " the canonical name of the external repository.")
public String getOriginalName() {
String originalName = (String) rule.getAttr("$original_name", Type.STRING);
// The original name isn't set for WORKSPACE-defined repositories as well as repositories
// backing Bazel modules. In case of the former, the original name is the same as the name, in
// the latter the original name doesn't matter as the restricted set of rules that can back
// Bazel modules do not use the name.
return originalName != null ? originalName : rule.getName();
}

@StarlarkMethod(
name = "workspace_root",
structField = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public StarlarkCallable repositoryRule(
builder.setCallStack(
callstack.subList(0, callstack.size() - 1)); // pop 'repository_rule' itself

builder.addAttribute(attr("$original_name", STRING).defaultValue("").build());
builder.addAttribute(attr("$local", BOOLEAN).defaultValue(local).build());
builder.addAttribute(attr("$configure", BOOLEAN).defaultValue(configure).build());
if (thread.getSemantics().getBool(BuildLanguageOptions.EXPERIMENTAL_REPO_REMOTE_EXEC)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ public SkyValue compute(SkyKey skyKey, Environment env)
Optional<RepoSpec> repoSpec = checkRepoFromNonRegistryOverrides(root, repositoryName);
if (repoSpec.isPresent()) {
return createRuleFromSpec(
repoSpec.get(), repositoryName, basicMainRepoMapping, starlarkSemantics, env);
repoSpec.get(),
repositoryName,
/* originalName= */ null,
basicMainRepoMapping,
starlarkSemantics,
env);
}

// BazelDepGraphValue is affected by repos found in Step 1, therefore it should NOT
Expand All @@ -116,7 +121,12 @@ public SkyValue compute(SkyKey skyKey, Environment env)
repoSpec = checkRepoFromBazelModules(bazelDepGraphValue, repositoryName);
if (repoSpec.isPresent()) {
return createRuleFromSpec(
repoSpec.get(), repositoryName, basicMainRepoMapping, starlarkSemantics, env);
repoSpec.get(),
repositoryName,
/* originalName= */ null,
basicMainRepoMapping,
starlarkSemantics,
env);
}

// Step 3: look for the repo from module extension evaluation results.
Expand All @@ -142,7 +152,7 @@ public SkyValue compute(SkyKey skyKey, Environment env)
}
RepoSpec extRepoSpec = extensionValue.generatedRepoSpecs().get(internalRepo);
return createRuleFromSpec(
extRepoSpec, repositoryName, basicMainRepoMapping, starlarkSemantics, env);
extRepoSpec, repositoryName, internalRepo, basicMainRepoMapping, starlarkSemantics, env);
}

private static Optional<RepoSpec> checkRepoFromNonRegistryOverrides(
Expand All @@ -168,6 +178,7 @@ private Optional<RepoSpec> checkRepoFromBazelModules(
private BzlmodRepoRuleValue createRuleFromSpec(
RepoSpec repoSpec,
RepositoryName repositoryName,
@Nullable String originalName,
RepositoryMapping basicMainRepoMapping,
StarlarkSemantics starlarkSemantics,
Environment env)
Expand All @@ -177,11 +188,13 @@ private BzlmodRepoRuleValue createRuleFromSpec(
return null;
}

var attributes =
var attributesBuilder =
ImmutableMap.<String, Object>builder()
.putAll(repoSpec.attributes().attributes())
.put("name", repositoryName.getName())
.buildOrThrow();
.put("name", repositoryName.getName());
if (originalName != null) {
attributesBuilder.put("$original_name", originalName);
}
try {
Rule rule =
BzlmodRepoRuleCreator.createRule(
Expand All @@ -194,7 +207,7 @@ private BzlmodRepoRuleValue createRuleFromSpec(
StarlarkThread.callStackEntry(
"BzlmodRepoRuleFunction.createRuleFromSpec", Location.BUILTIN)),
ruleClass,
attributes);
attributesBuilder.buildOrThrow());
return new BzlmodRepoRuleValue(rule.getPackage(), rule.getName());
} catch (InvalidRuleException e) {
throw new BzlmodRepoRuleFunctionException(e, Transience.PERSISTENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ public void setup() throws Exception {
" ctx.file('WORKSPACE')",
" ctx.file('BUILD')",
" ctx.file('data.bzl', 'data = '+json.encode(ctx.attr.data))",
" ctx.file(",
" 'names.bzl',",
" 'names='+json.encode({",
" 'name': ctx.name,",
" 'original_name': ctx.original_name,",
" })",
" )",
"data_repo = repository_rule(",
" implementation=_data_repo_impl,",
" attrs={'data':attr.string()})");
Expand Down Expand Up @@ -328,8 +335,12 @@ public void simpleExtension() throws Exception {
scratch.file(
workspaceRoot.getRelative("data.bzl").getPathString(),
"load('@foo//:data.bzl', foo_data='data')",
"load('@foo//:names.bzl', foo_names='names')",
"load('@bar//:data.bzl', bar_data='data')",
"data = 'foo:'+foo_data+' bar:'+bar_data");
"load('@bar//:names.bzl', bar_names='names')",
"data = 'foo:'+foo_data+' bar:'+bar_data",
"names = 'foo:'+foo_names['name']+' bar:'+bar_names['name']",
"original_names = 'foo:'+foo_names['original_name']+' bar:'+bar_names['original_name']");

SkyKey skyKey = BzlLoadValue.keyForBuild(Label.parseCanonical("//:data.bzl"));
EvaluationResult<BzlLoadValue> result =
Expand All @@ -338,6 +349,10 @@ public void simpleExtension() throws Exception {
throw result.getError().getException();
}
assertThat(result.get(skyKey).getModule().getGlobal("data")).isEqualTo("foo:fu bar:ba");
assertThat(result.get(skyKey).getModule().getGlobal("names"))
.isEqualTo("foo:+ext+foo bar:+ext+bar");
assertThat(result.get(skyKey).getModule().getGlobal("original_names"))
.isEqualTo("foo:foo bar:bar");
}

@Test
Expand Down Expand Up @@ -2896,30 +2911,45 @@ public void innate() throws Exception {
workspaceRoot.getRelative("MODULE.bazel").getPathString(),
"bazel_dep(name='foo',version='1.0')",
"data_repo = use_repo_rule('@foo//:repo.bzl', 'data_repo')",
"data_repo(name='data', data='get up at 6am.')");
"data_repo(name='data1', data='get up at 6am.')");
scratch.file(workspaceRoot.getRelative("BUILD").getPathString());
scratch.file(
workspaceRoot.getRelative("data.bzl").getPathString(),
"load('@data//:data.bzl', self_data='data')",
"load('@data1//:data.bzl', self_data='data')",
"load('@data1//:names.bzl', self_names='names')",
"load('@foo//:data.bzl', foo_data='data')",
"data=self_data+' '+foo_data");
"load('@foo//:names.bzl', foo_names='names')",
"data=self_data+' '+foo_data",
"names=self_names['name']+' '+foo_names['name']",
"original_names=self_names['original_name']+' '+foo_names['original_name']");

registry.addModule(
createModuleKey("foo", "1.0"),
"module(name='foo',version='1.0')",
"data_repo = use_repo_rule('//:repo.bzl', 'data_repo')",
"data_repo(name='data', data='go to bed at 11pm.')");
"data_repo(name='data2', data='go to bed at 11pm.')");
scratch.file(modulesRoot.getRelative("foo+1.0/WORKSPACE").getPathString());
scratch.file(modulesRoot.getRelative("foo+1.0/BUILD").getPathString());
scratch.file(
modulesRoot.getRelative("foo+1.0/data.bzl").getPathString(),
"load('@data//:data.bzl',repo_data='data')",
"load('@data2//:data.bzl',repo_data='data')",
"data=repo_data");
scratch.file(
modulesRoot.getRelative("foo+1.0/names.bzl").getPathString(),
"load('@data2//:names.bzl',repo_names='names')",
"names=repo_names");
scratch.file(
modulesRoot.getRelative("foo+1.0/repo.bzl").getPathString(),
"def _data_repo_impl(ctx):",
" ctx.file('BUILD.bazel')",
" ctx.file('data.bzl', 'data='+json.encode(ctx.attr.data))",
" ctx.file(",
" 'names.bzl',",
" 'names='+json.encode({",
" 'name': ctx.name,",
" 'original_name': ctx.original_name,",
" })",
" )",
"data_repo = repository_rule(",
" implementation=_data_repo_impl, attrs={'data':attr.string()})");

Expand All @@ -2931,6 +2961,9 @@ public void innate() throws Exception {
}
assertThat(result.get(skyKey).getModule().getGlobal("data"))
.isEqualTo("get up at 6am. go to bed at 11pm.");
assertThat(result.get(skyKey).getModule().getGlobal("names"))
.isEqualTo("+_repo_rules+data1 foo++_repo_rules+data2");
assertThat(result.get(skyKey).getModule().getGlobal("original_names")).isEqualTo("data1 data2");
}

@Test
Expand Down
22 changes: 12 additions & 10 deletions src/test/py/bazel/bzlmod/mod_command_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,13 +467,13 @@ def testShowModuleAndExtensionReposFromBaseModule(self):
self.assertRegex(stdout.pop(4), r'^ integrity = ".*",$')
self.assertRegex(stdout.pop(19), r'^ path = ".*",$')
# lines after 'Rule data_repo defined at (most recent call last):'
stdout.pop(32)
stdout.pop(42)
self.assertRegex(stdout.pop(47), r'^ urls = \[".*"\],$')
self.assertRegex(stdout.pop(47), r'^ integrity = ".*",$')
stdout.pop(33)
stdout.pop(44)
self.assertRegex(stdout.pop(49), r'^ urls = \[".*"\],$')
self.assertRegex(stdout.pop(49), r'^ integrity = ".*",$')
# lines after '# Rule http_archive defined at (most recent call last):'
stdout.pop(13)
stdout.pop(55)
stdout.pop(57)
self.assertListEqual(
stdout,
[
Expand Down Expand Up @@ -507,30 +507,32 @@ def testShowModuleAndExtensionReposFromBaseModule(self):
'# <builtin>',
'data_repo(',
' name = "ext++ext+repo3",',
' _original_name = "repo3",',
' data = "requested repo",',
')',
'# Rule ext++ext+repo3 instantiated at (most recent call last):',
'# <builtin> in <toplevel>',
'# Rule data_repo defined at (most recent call last):',
# pop(32)
# pop(33)
'',
'## @my_repo4:',
'# <builtin>',
'data_repo(',
' name = "ext++ext+repo4",',
' _original_name = "repo4",',
' data = "requested repo",',
')',
'# Rule ext++ext+repo4 instantiated at (most recent call last):',
'# <builtin> in <toplevel>',
'# Rule data_repo defined at (most recent call last):',
# pop(42)
# pop(44)
'',
'## bar@2.0:',
'# <builtin>',
'http_archive(',
' name = "bar+",',
# pop(47) -- urls=[...]
# pop(47) -- integrity=...
# pop(49) -- urls=[...]
# pop(49) -- integrity=...
' strip_prefix = "",',
' remote_file_urls = {},',
' remote_file_integrity = {},',
Expand All @@ -540,7 +542,7 @@ def testShowModuleAndExtensionReposFromBaseModule(self):
'# Rule bar+ instantiated at (most recent call last):',
'# <builtin> in <toplevel>',
'# Rule http_archive defined at (most recent call last):',
# pop(55)
# pop(57)
'',
],
'wrong output in the show query for module and extension-generated'
Expand Down

0 comments on commit b016ff3

Please # to comment.