Skip to content

Commit

Permalink
Hash local overrides Module files into the lockfile
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 525405790
Change-Id: I7c9b26469c889435ed4adc4a49197c10e0284af0
  • Loading branch information
SalmaSamy authored and copybara-github committed Apr 19, 2023
1 parent 1acc7a8 commit ba1cd13
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableMap.toImmutableMap;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableBiMap;
Expand All @@ -42,6 +43,8 @@
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;

/**
Expand All @@ -68,6 +71,7 @@ public SkyValue compute(SkyKey skyKey, Environment env)
}
LockfileMode lockfileMode = BazelLockFileFunction.LOCKFILE_MODE.get(env);

ImmutableMap<String, String> localOverrideHashes = null;
ImmutableMap<ModuleKey, Module> depGraph = null;
BzlmodFlagsAndEnvVars flags = null;

Expand All @@ -82,11 +86,18 @@ public SkyValue compute(SkyKey skyKey, Environment env)
if (flags == null) { // unable to read environment variables
return null;
}
localOverrideHashes = getLocalOverridesHashes(root.getOverrides(), env);
if (localOverrideHashes == null) { // trying to read override module
return null;
}

if (root.getModuleFileHash().equals(lockFile.getModuleFileHash())
&& flags.equals(lockFile.getFlags())) {
&& flags.equals(lockFile.getFlags())
&& localOverrideHashes.equals(lockFile.getLocalOverrideHashes())) {
depGraph = lockFile.getModuleDepGraph();
} else if (lockfileMode.equals(LockfileMode.ERROR)) {
List<String> diffLockfile = lockFile.getDiffLockfile(root.getModuleFileHash(), flags);
List<String> diffLockfile =
lockFile.getDiffLockfile(root.getModuleFileHash(), localOverrideHashes, flags);
throw new BazelDepGraphFunctionException(
ExternalDepsException.withMessage(
Code.BAD_MODULE,
Expand All @@ -105,7 +116,7 @@ public SkyValue compute(SkyKey skyKey, Environment env)
depGraph = selectionResult.getResolvedDepGraph();
if (lockfileMode.equals(LockfileMode.UPDATE)) {
BazelLockFileFunction.updateLockedModule(
root.getModuleFileHash(), depGraph, rootDirectory, flags);
rootDirectory, root.getModuleFileHash(), flags, localOverrideHashes, depGraph);
}
}

Expand All @@ -128,8 +139,29 @@ public SkyValue compute(SkyKey skyKey, Environment env)
}

@Nullable
public static BzlmodFlagsAndEnvVars getFlagsAndEnvVars(Environment env)
throws InterruptedException {
@VisibleForTesting
static ImmutableMap<String, String> getLocalOverridesHashes(
Map<String, ModuleOverride> overrides, Environment env) throws InterruptedException {
ImmutableMap.Builder<String, String> localOverrideHashes = new ImmutableMap.Builder<>();
for (Entry<String, ModuleOverride> entry : overrides.entrySet()) {
if (entry.getValue() instanceof LocalPathOverride) {
ModuleFileValue moduleValue =
(ModuleFileValue)
env.getValue(
ModuleFileValue.key(
ModuleKey.create(entry.getKey(), Version.EMPTY), entry.getValue()));
if (moduleValue == null) {
return null;
}
localOverrideHashes.put(entry.getKey(), moduleValue.getModuleFileHash());
}
}
return localOverrideHashes.buildOrThrow();
}

@VisibleForTesting
@Nullable
static BzlmodFlagsAndEnvVars getFlagsAndEnvVars(Environment env) throws InterruptedException {
ClientEnvironmentValue allowedYankedVersionsFromEnv =
(ClientEnvironmentValue)
env.getValue(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ public class BazelLockFileFunction implements SkyFunction {

private static final BazelLockFileValue EMPTY_LOCKFILE =
BazelLockFileValue.create(
BazelLockFileValue.LOCK_FILE_VERSION, "", EMPTY_FLAGS, ImmutableMap.of());
BazelLockFileValue.LOCK_FILE_VERSION,
"",
EMPTY_FLAGS,
ImmutableMap.of(),
ImmutableMap.of());

public BazelLockFileFunction(Path rootDirectory) {
this.rootDirectory = rootDirectory;
Expand Down Expand Up @@ -86,21 +90,26 @@ public SkyValue compute(SkyKey skyKey, Environment env)
/**
* Updates the stored module in the lock file (ModuleHash, Flags & Dependency graph)
*
* @param hashedModule The hash of the current module file
* @param moduleFileHash The hash of the current module file
* @param resolvedDepGraph The resolved dependency graph from the module file
*/
public static void updateLockedModule(
String hashedModule,
ImmutableMap<ModuleKey, Module> resolvedDepGraph,
Path rootDirectory,
BzlmodFlagsAndEnvVars flags)
String moduleFileHash,
BzlmodFlagsAndEnvVars flags,
ImmutableMap<String, String> localOverrideHashes,
ImmutableMap<ModuleKey, Module> resolvedDepGraph)
throws BazelDepGraphFunctionException {
RootedPath lockfilePath =
RootedPath.toRootedPath(Root.fromPath(rootDirectory), LabelConstants.MODULE_LOCKFILE_NAME);

BazelLockFileValue value =
BazelLockFileValue.create(
BazelLockFileValue.LOCK_FILE_VERSION, hashedModule, flags, resolvedDepGraph);
BazelLockFileValue.LOCK_FILE_VERSION,
moduleFileHash,
flags,
localOverrideHashes,
resolvedDepGraph);
try {
FileSystemUtils.writeContent(lockfilePath.asPath(), UTF_8, LOCKFILE_GSON.toJson(value));
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.google.devtools.build.skyframe.SkyValue;
import com.ryanharter.auto.value.gson.GenerateTypeAdapter;
import java.util.ArrayList;
import java.util.Map;

/**
* The result of reading the lockfile. Contains the lockfile version, module hash, definitions of
Expand All @@ -42,8 +43,10 @@ public static BazelLockFileValue create(
int lockFileVersion,
String moduleFileHash,
BzlmodFlagsAndEnvVars flags,
ImmutableMap<String, String> localOverrideHashes,
ImmutableMap<ModuleKey, Module> moduleDepGraph) {
return new AutoValue_BazelLockFileValue(lockFileVersion, moduleFileHash, flags, moduleDepGraph);
return new AutoValue_BazelLockFileValue(
lockFileVersion, moduleFileHash, flags, localOverrideHashes, moduleDepGraph);
}

/** Current version of the lock file */
Expand All @@ -55,37 +58,33 @@ public static BazelLockFileValue create(
/** Command line flags and environment variables that can affect the resolution */
public abstract BzlmodFlagsAndEnvVars getFlags();

/** Module hash of each local path override in the root module file */
public abstract ImmutableMap<String, String> getLocalOverrideHashes();

/** The post-selection dep graph retrieved from the lock file. */
public abstract ImmutableMap<ModuleKey, Module> getModuleDepGraph();

/** Returns the difference between the lockfile and the current module & flags */
public ArrayList<String> getDiffLockfile(String moduleFileHash, BzlmodFlagsAndEnvVars flags) {
public ArrayList<String> getDiffLockfile(
String moduleFileHash,
ImmutableMap<String, String> localOverrideHashes,
BzlmodFlagsAndEnvVars flags) {
ArrayList<String> diffLockfile = new ArrayList<>();
if (!moduleFileHash.equals(getModuleFileHash())) {
diffLockfile.add("the root MODULE.bazel has been modified");
}
if (!flags.cmdRegistries().equals(getFlags().cmdRegistries())) {
diffLockfile.add("the value of --registry flag has been modified");
}
if (!flags.cmdModuleOverrides().equals(getFlags().cmdModuleOverrides())) {
diffLockfile.add("the value of --override_module flag has been modified");
}
if (!flags.allowedYankedVersions().equals(getFlags().allowedYankedVersions())) {
diffLockfile.add("the value of --allow_yanked_versions flag has been modified");
}
if (!flags.envVarAllowedYankedVersions().equals(getFlags().envVarAllowedYankedVersions())) {
diffLockfile.add(
"the value of BZLMOD_ALLOW_YANKED_VERSIONS environment variable has been modified");
}
if (flags.ignoreDevDependency() != getFlags().ignoreDevDependency()) {
diffLockfile.add("the value of --ignore_dev_dependency flag has been modified");
}
if (!flags.directDependenciesMode().equals(getFlags().directDependenciesMode())) {
diffLockfile.add("the value of --check_direct_dependencies flag has been modified");
}
if (!flags.compatibilityMode().equals(getFlags().compatibilityMode())) {
diffLockfile.add("the value of --check_bazel_compatibility flag has been modified");
diffLockfile.addAll(getFlags().getDiffFlags(flags));

for (Map.Entry<String, String> entry : localOverrideHashes.entrySet()) {
String currentValue = entry.getValue();
String lockfileValue = getLocalOverrideHashes().get(entry.getKey());
// If the lockfile value is null, the module hash would be different anyway
if (lockfileValue != null && !currentValue.equals(lockfileValue)) {
diffLockfile.add(
"The MODULE.bazel file has changed for the overriden module: " + entry.getKey());
}
}

return diffLockfile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.ryanharter.auto.value.gson.GenerateTypeAdapter;
import java.util.ArrayList;

/** Stores the values of flags and environment variables that affect the resolution */
@AutoValue
Expand Down Expand Up @@ -63,4 +64,31 @@ public static BzlmodFlagsAndEnvVars create(

/** Error level of bazel compatability check */
public abstract String compatibilityMode();

public ArrayList<String> getDiffFlags(BzlmodFlagsAndEnvVars flags) {
ArrayList<String> diffFlags = new ArrayList<>();
if (!flags.cmdRegistries().equals(cmdRegistries())) {
diffFlags.add("the value of --registry flag has been modified");
}
if (!flags.cmdModuleOverrides().equals(cmdModuleOverrides())) {
diffFlags.add("the value of --override_module flag has been modified");
}
if (!flags.allowedYankedVersions().equals(allowedYankedVersions())) {
diffFlags.add("the value of --allow_yanked_versions flag has been modified");
}
if (!flags.envVarAllowedYankedVersions().equals(envVarAllowedYankedVersions())) {
diffFlags.add(
"the value of BZLMOD_ALLOW_YANKED_VERSIONS environment variable has been modified");
}
if (flags.ignoreDevDependency() != ignoreDevDependency()) {
diffFlags.add("the value of --ignore_dev_dependency flag has been modified");
}
if (!flags.directDependenciesMode().equals(directDependenciesMode())) {
diffFlags.add("the value of --check_direct_dependencies flag has been modified");
}
if (!flags.compatibilityMode().equals(compatibilityMode())) {
diffFlags.add("the value of --check_bazel_compatibility flag has been modified");
}
return diffFlags;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public SkyValue compute(SkyKey skyKey, Environment env)
if (getModuleFileResult == null) {
return null;
}
String moduleFileHash =
new Fingerprint().addBytes(getModuleFileResult.moduleFileContents).hexDigestAndReset();

ModuleFileGlobals moduleFileGlobals =
execModuleFile(
Expand Down Expand Up @@ -140,7 +142,7 @@ public SkyValue compute(SkyKey skyKey, Environment env)
throw errorf(Code.BAD_MODULE, "The MODULE.bazel file of %s declares overrides", moduleKey);
}

return NonRootModuleFileValue.create(module);
return NonRootModuleFileValue.create(module, moduleFileHash);
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ public abstract class ModuleFileValue implements SkyValue {
*/
public abstract Module getModule();

/** The hash string of Module.bazel (using SHA256) */
public abstract String getModuleFileHash();

/** The {@link ModuleFileValue} for non-root modules. */
@AutoValue
public abstract static class NonRootModuleFileValue extends ModuleFileValue {

public static NonRootModuleFileValue create(Module module) {
return new AutoValue_ModuleFileValue_NonRootModuleFileValue(module);
public static NonRootModuleFileValue create(Module module, String moduleFileHash) {
return new AutoValue_ModuleFileValue_NonRootModuleFileValue(module, moduleFileHash);
}
}

Expand All @@ -53,10 +56,6 @@ public static NonRootModuleFileValue create(Module module) {
*/
@AutoValue
public abstract static class RootModuleFileValue extends ModuleFileValue {

/** The hash string of Module.bazel (using SHA256) */
public abstract String getModuleFileHash();

/**
* The overrides specified by the evaluated module file. The key is the module name and the
* value is the override itself.
Expand Down
Loading

0 comments on commit ba1cd13

Please sign in to comment.