Skip to content

Commit

Permalink
Make lockfile version parsing more robust
Browse files Browse the repository at this point in the history
Instead of using a regex, get the lockfile version by parsing the
lockfile as arbitrary JSON and then later fit it to the expected schema.
  • Loading branch information
fmeum committed Nov 11, 2023
1 parent 07a571f commit 6adbd18
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.server.FailureDetails.ExternalDeps.Code;
import com.google.devtools.build.lib.skyframe.PrecomputedValue.Precomputed;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
Expand All @@ -36,20 +35,23 @@
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.InputStreamReader;
import java.util.Optional;
import javax.annotation.Nullable;

/** Reads the contents of the lock file into its value. */
public class BazelLockFileFunction implements SkyFunction {

public static final Precomputed<LockfileMode> LOCKFILE_MODE = new Precomputed<>("lockfile_mode");

private static final Pattern LOCKFILE_VERSION_PATTERN =
Pattern.compile("\"lockFileVersion\":\\s*(\\d+)");
private static final String LOCK_FILE_VERSION_KEY = "lockFileVersion";

private final Path rootDirectory;

Expand Down Expand Up @@ -99,17 +101,29 @@ public SkyValue compute(SkyKey skyKey, Environment env)
public static BazelLockFileValue getLockfileValue(RootedPath lockfilePath) throws IOException {
BazelLockFileValue bazelLockFileValue;
try {
String json = FileSystemUtils.readContent(lockfilePath.asPath(), UTF_8);
Matcher matcher = LOCKFILE_VERSION_PATTERN.matcher(json);
int version = matcher.find() ? Integer.parseInt(matcher.group(1)) : -1;
Gson gson =
GsonTypeAdapterUtil.createLockFileGson(
lockfilePath
.asPath()
.getParentDirectory()
.getRelative(LabelConstants.MODULE_DOT_BAZEL_FILE_NAME));
JsonObject jsonObject;
try (var reader =
new BufferedReader(
new InputStreamReader(lockfilePath.asPath().getInputStream(), UTF_8))) {
jsonObject = gson.fromJson(reader, JsonObject.class);
}
int version;
try {
version =
Optional.ofNullable(jsonObject.get(LOCK_FILE_VERSION_KEY))
.orElse(new JsonPrimitive(-1))
.getAsInt();
} catch (NumberFormatException e) {
version = -1;
}
if (version == BazelLockFileValue.LOCK_FILE_VERSION) {
bazelLockFileValue =
GsonTypeAdapterUtil.createLockFileGson(
lockfilePath
.asPath()
.getParentDirectory()
.getRelative(LabelConstants.MODULE_DOT_BAZEL_FILE_NAME))
.fromJson(json, BazelLockFileValue.class);
bazelLockFileValue = gson.fromJson(jsonObject, BazelLockFileValue.class);
} else {
// This is an old version, needs to be updated
// Keep old version to recognize the problem in error mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ public void invalidLockfileMalformed() throws Exception {
Pattern.quote(
"Failed to read and parse the MODULE.bazel.lock file with error:"
+ " java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at"
+ " line 1 column 129 path $.flags.allowedYankedVersions")
+ " path $.flags.allowedYankedVersions")
+ ".*"
+ Pattern.quote("Try deleting it and rerun the build."),
Pattern.DOTALL);
Expand Down

0 comments on commit 6adbd18

Please sign in to comment.