Skip to content

Commit

Permalink
Remove user specific absolute path from lockfile
Browse files Browse the repository at this point in the history
- Store the unresolved registry string "containing %workspace% placeholder" in IndexRegistry and use it to create the remote_patches
- Later when creating the repo rule, resolve the registry path in remote_patches

fixes bazelbuild#19621

PiperOrigin-RevId: 570028910
Change-Id: I984c6b7494fb377bcf8b3568fa98c740c8618c33
  • Loading branch information
SalmaSamy authored and copybara-github committed Oct 2, 2023
1 parent 3b18d3f commit 736a068
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ public void workspaceInit(
directories,
BazelSkyframeExecutorConstants.EXTERNAL_PACKAGE_HELPER);
RegistryFactory registryFactory =
new RegistryFactoryImpl(downloadManager, clientEnvironmentSupplier);
new RegistryFactoryImpl(
directories.getWorkspace(), downloadManager, clientEnvironmentSupplier);
singleExtensionEvalFunction =
new SingleExtensionEvalFunction(directories, clientEnvironmentSupplier, downloadManager);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
* an {@code http_archive} repo rule call.
*/
public class ArchiveRepoSpecBuilder {

public static final String HTTP_ARCHIVE_PATH = "@bazel_tools//tools/build_defs/repo:http.bzl";

private final ImmutableMap.Builder<String, Object> attrBuilder;

public ArchiveRepoSpecBuilder() {
Expand Down Expand Up @@ -96,7 +99,7 @@ public ArchiveRepoSpecBuilder setArchiveType(String archiveType) {

public RepoSpec build() {
return RepoSpec.builder()
.setBzlFile("@bazel_tools//tools/build_defs/repo:http.bzl")
.setBzlFile(HTTP_ARCHIVE_PATH)
.setRuleClassName("http_archive")
.setAttributes(AttributeValues.create(attrBuilder.buildOrThrow()))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/events",
"//src/main/java/com/google/devtools/build/lib/profiler",
"//src/main/java/com/google/devtools/build/lib/util:os",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//third_party:caffeine",
"//third_party:gson",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,23 @@
* <p>For details, see <a href="https://bazel.build/external/registry">the docs</a>
*/
public class IndexRegistry implements Registry {

/** The unresolved version of the url. Ex: has %workspace% placeholder */
private final String unresolvedUri;

private final URI uri;
private final DownloadManager downloadManager;
private final Map<String, String> clientEnv;
private final Gson gson;
private volatile Optional<BazelRegistryJson> bazelRegistryJson;

public IndexRegistry(URI uri, DownloadManager downloadManager, Map<String, String> clientEnv) {
public IndexRegistry(
URI uri,
String unresolvedUri,
DownloadManager downloadManager,
Map<String, String> clientEnv) {
this.uri = uri;
this.unresolvedUri = unresolvedUri;
this.downloadManager = downloadManager;
this.clientEnv = clientEnv;
this.gson =
Expand All @@ -67,7 +76,7 @@ public IndexRegistry(URI uri, DownloadManager downloadManager, Map<String, Strin

@Override
public String getUrl() {
return uri.toString();
return unresolvedUri;
}

private String constructUrl(String base, String... segments) {
Expand Down Expand Up @@ -98,7 +107,7 @@ public Optional<ModuleFile> getModuleFile(ModuleKey key, ExtendedEventHandler ev
throws IOException, InterruptedException {
String url =
constructUrl(
getUrl(), "modules", key.getName(), key.getVersion().toString(), "MODULE.bazel");
uri.toString(), "modules", key.getName(), key.getVersion().toString(), "MODULE.bazel");
return grabFile(url, eventHandler).map(content -> ModuleFile.create(content, url));
}

Expand Down Expand Up @@ -149,12 +158,16 @@ public RepoSpec getRepoSpec(
Optional<SourceJson> sourceJson =
grabJson(
constructUrl(
getUrl(), "modules", key.getName(), key.getVersion().toString(), "source.json"),
uri.toString(),
"modules",
key.getName(),
key.getVersion().toString(),
"source.json"),
SourceJson.class,
eventHandler);
if (sourceJson.isEmpty()) {
throw new FileNotFoundException(
String.format("Module %s's source information not found in registry %s", key, getUrl()));
String.format("Module %s's source information not found in registry %s", key, uri));
}

String type = sourceJson.get().type;
Expand All @@ -177,7 +190,7 @@ private Optional<BazelRegistryJson> getBazelRegistryJson(ExtendedEventHandler ev
if (bazelRegistryJson == null) {
bazelRegistryJson =
grabJson(
constructUrl(getUrl(), "bazel_registry.json"),
constructUrl(uri.toString(), "bazel_registry.json"),
BazelRegistryJson.class,
eventHandler);
}
Expand Down Expand Up @@ -259,7 +272,7 @@ private RepoSpec createArchiveRepoSpec(
for (Map.Entry<String, String> entry : sourceJson.get().patches.entrySet()) {
remotePatches.put(
constructUrl(
getUrl(),
unresolvedUri,
"modules",
key.getName(),
key.getVersion().toString(),
Expand All @@ -286,7 +299,7 @@ public Optional<ImmutableMap<Version, String>> getYankedVersions(
throws IOException, InterruptedException {
Optional<MetadataJson> metadataJson =
grabJson(
constructUrl(getUrl(), "modules", moduleName, "metadata.json"),
constructUrl(uri.toString(), "modules", moduleName, "metadata.json"),
MetadataJson.class,
eventHandler);
if (metadataJson.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,7 @@ private GetModuleFileResult getModuleFile(
List<Registry> registryObjects = new ArrayList<>(registries.size());
for (String registryUrl : registries) {
try {
registryObjects.add(
registryFactory.getRegistryWithUrl(
registryUrl.replace("%workspace%", workspaceRoot.getPathString())));
registryObjects.add(registryFactory.getRegistryWithUrl(registryUrl));
} catch (URISyntaxException e) {
throw errorf(Code.INVALID_REGISTRY_URL, e, "Invalid registry URL");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,31 @@
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.devtools.build.lib.bazel.repository.downloader.DownloadManager;
import com.google.devtools.build.lib.vfs.Path;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.function.Supplier;

/** Prod implementation of {@link RegistryFactory}. */
public class RegistryFactoryImpl implements RegistryFactory {
private final Path workspacePath;
private final DownloadManager downloadManager;
private final Supplier<Map<String, String>> clientEnvironmentSupplier;
private final Cache<String, Registry> registries = Caffeine.newBuilder().build();

public RegistryFactoryImpl(
DownloadManager downloadManager, Supplier<Map<String, String>> clientEnvironmentSupplier) {
Path workspacePath,
DownloadManager downloadManager,
Supplier<Map<String, String>> clientEnvironmentSupplier) {
this.workspacePath = workspacePath;
this.downloadManager = downloadManager;
this.clientEnvironmentSupplier = clientEnvironmentSupplier;
}

@Override
public Registry getRegistryWithUrl(String url) throws URISyntaxException {
URI uri = new URI(url);
public Registry getRegistryWithUrl(String unresolvedUrl) throws URISyntaxException {
URI uri = new URI(unresolvedUrl.replace("%workspace%", workspacePath.getPathString()));
if (uri.getScheme() == null) {
throw new URISyntaxException(
uri.toString(), "Registry URL has no scheme -- did you mean to use file://?");
Expand All @@ -47,8 +52,10 @@ public Registry getRegistryWithUrl(String url) throws URISyntaxException {
case "https":
case "file":
return registries.get(
url,
unused -> new IndexRegistry(uri, downloadManager, clientEnvironmentSupplier.get()));
unresolvedUrl,
unused ->
new IndexRegistry(
uri, unresolvedUrl, downloadManager, clientEnvironmentSupplier.get()));
default:
throw new URISyntaxException(uri.toString(), "Unrecognized registry URL protocol");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@

package com.google.devtools.build.lib.skyframe;

import static com.google.common.collect.ImmutableMap.toImmutableMap;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.bazel.bzlmod.ArchiveRepoSpecBuilder;
import com.google.devtools.build.lib.bazel.bzlmod.AttributeValues;
import com.google.devtools.build.lib.bazel.bzlmod.BazelDepGraphValue;
import com.google.devtools.build.lib.bazel.bzlmod.BzlmodRepoRuleCreator;
import com.google.devtools.build.lib.bazel.bzlmod.BzlmodRepoRuleValue;
Expand Down Expand Up @@ -47,6 +50,7 @@
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -198,7 +202,7 @@ private BzlmodRepoRuleValue createRuleFromSpec(
env.getListener(),
"BzlmodRepoRuleFunction.createRule",
ruleClass,
repoSpec.attributes().attributes());
resolveRemotePatchesUrl(repoSpec).attributes());
return new BzlmodRepoRuleValue(rule.getPackage(), rule.getName());
} catch (InvalidRuleException e) {
throw new BzlmodRepoRuleFunctionException(e, Transience.PERSISTENT);
Expand All @@ -209,6 +213,35 @@ private BzlmodRepoRuleValue createRuleFromSpec(
}
}

/* Resolves repo specs containing remote patches that are stored with %workspace% place holder*/
@SuppressWarnings("unchecked")
private AttributeValues resolveRemotePatchesUrl(RepoSpec repoSpec) {
if (repoSpec
.getRuleClass()
.equals(ArchiveRepoSpecBuilder.HTTP_ARCHIVE_PATH + "%http_archive")) {
return AttributeValues.create(
repoSpec.attributes().attributes().entrySet().stream()
.collect(
toImmutableMap(
Map.Entry::getKey,
e -> {
if (e.getKey().equals("remote_patches")) {
Map<String, String> remotePatches = (Map<String, String>) e.getValue();
return remotePatches.keySet().stream()
.collect(
toImmutableMap(
key ->
key.replace(
"%workspace%",
directories.getWorkspace().getPathString()),
remotePatches::get));
}
return e.getValue();
})));
}
return repoSpec.attributes();
}

/** Loads modules from the given bzl file. */
private ImmutableMap<String, Module> loadBzlModules(
Environment env, String bzlFile, StarlarkSemantics starlarkSemantics)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.google.devtools.build.lib.bazel.repository.downloader.UnrecoverableHttpException;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.vfs.Path;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
Expand All @@ -60,9 +61,11 @@ public class IndexRegistryTest extends FoundationTestCase {

@Before
public void setUp() throws Exception {
Path workspaceRoot = scratch.dir("/ws");
downloadManager = new DownloadManager(new RepositoryCache(), new HttpDownloader());
registryFactory =
new RegistryFactoryImpl(downloadManager, Suppliers.ofInstance(ImmutableMap.of()));
new RegistryFactoryImpl(
workspaceRoot, downloadManager, Suppliers.ofInstance(ImmutableMap.of()));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,23 @@
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache;
import com.google.devtools.build.lib.bazel.repository.downloader.DownloadManager;
import com.google.devtools.build.lib.bazel.repository.downloader.HttpDownloader;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.vfs.Path;
import java.net.URISyntaxException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link RegistryFactory}. */
@RunWith(JUnit4.class)
public class RegistryFactoryTest {
public class RegistryFactoryTest extends FoundationTestCase {

@Test
public void badSchemes() throws Exception {
Path workspaceRoot = scratch.dir("/ws");
RegistryFactory registryFactory =
new RegistryFactoryImpl(
workspaceRoot,
new DownloadManager(new RepositoryCache(), new HttpDownloader()),
Suppliers.ofInstance(ImmutableMap.of()));
assertThrows(URISyntaxException.class, () -> registryFactory.getRegistryWithUrl("/home/www"));
Expand Down
61 changes: 49 additions & 12 deletions src/test/py/bazel/bzlmod/bazel_lockfile_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1153,10 +1153,9 @@ def testExtensionEvaluationOnlyRerunOnRelevantUsagesChanges(self):
'',
'def _ext_1_impl(ctx):',
' print("Ext 1 is being evaluated")',
(
' num_tags = len([tag for mod in ctx.modules for tag in'
' mod.tags.tag])'
),
' num_tags = len([',
' tag for mod in ctx.modules for tag in mod.tags.tag',
' ])',
' repo_rule(name="dep", value="Ext 1 saw %s tags" % num_tags)',
'',
'ext_1 = module_extension(',
Expand All @@ -1166,10 +1165,9 @@ def testExtensionEvaluationOnlyRerunOnRelevantUsagesChanges(self):
'',
'def _ext_2_impl(ctx):',
' print("Ext 2 is being evaluated")',
(
' num_tags = len([tag for mod in ctx.modules for tag in'
' mod.tags.tag])'
),
' num_tags = len([',
' tag for mod in ctx.modules for tag in mod.tags.tag',
' ])',
' repo_rule(name="dep", value="Ext 2 saw %s tags" % num_tags)',
'',
'ext_2 = module_extension(',
Expand All @@ -1179,10 +1177,9 @@ def testExtensionEvaluationOnlyRerunOnRelevantUsagesChanges(self):
'',
'def _ext_3_impl(ctx):',
' print("Ext 3 is being evaluated")',
(
' num_tags = len([tag for mod in ctx.modules for tag in'
' mod.tags.tag])'
),
' num_tags = len([',
' tag for mod in ctx.modules for tag in mod.tags.tag',
' ])',
' repo_rule(name="dep", value="Ext 3 saw %s tags" % num_tags)',
'',
'ext_3 = module_extension(',
Expand Down Expand Up @@ -1307,6 +1304,46 @@ def testExtensionEvaluationOnlyRerunOnRelevantUsagesChanges(self):
)
self.assertNotIn(ext_3_key, lockfile['moduleExtensions'])

def testLockfileWithNoUserSpecificPath(self):
self.my_registry = BazelRegistry(os.path.join(self._test_cwd, 'registry'))
patch_file = self.ScratchFile(
'ss.patch',
[
'--- a/aaa.cc',
'+++ b/aaa.cc',
'@@ -1,6 +1,6 @@',
' #include <stdio.h>',
' #include "aaa.h"',
' void hello_aaa(const std::string& caller) {',
'- std::string lib_name = "aaa@1.1-1";',
'+ std::string lib_name = "aaa@1.1-1 (remotely patched)";',
' printf("%s => %s\\n", caller.c_str(), lib_name.c_str());',
' }',
],
)
self.my_registry.createCcModule(
'ss', '1.3-1', patches=[patch_file], patch_strip=1
)

self.ScratchFile(
'MODULE.bazel',
[
'bazel_dep(name = "ss", version = "1.3-1")',
],
)
self.ScratchFile('BUILD.bazel', ['filegroup(name = "lala")'])
self.RunBazel(
['build', '--registry=file:///%workspace%/registry', '//:lala']
)

with open('MODULE.bazel.lock', 'r') as json_file:
lockfile = json.load(json_file)
remote_patches = lockfile['moduleDepGraph']['ss@1.3-1']['repoSpec'][
'attributes'
]['remote_patches']
for key in remote_patches.keys():
self.assertIn('%workspace%', key)


if __name__ == '__main__':
absltest.main()

0 comments on commit 736a068

Please sign in to comment.