-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- With this we can get the repospec directly from the module not the registry (no need for internet access) - Since Repospec & Tag classes have an "attributes" field that can hold starlark values, an adapter was needed to serialize/deserialize starlark values PiperOrigin-RevId: 523364539 Change-Id: Ifcdf0c6b4b6fbbcdae9c14a4b0cd7f53ae91c161
- Loading branch information
1 parent
036991e
commit 23518b8
Showing
34 changed files
with
530 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
src/main/java/com/google/devtools/build/lib/bazel/bzlmod/AttributeValues.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright 2023 The Bazel Authors. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
package com.google.devtools.build.lib.bazel.bzlmod; | ||
|
||
import com.google.auto.value.AutoValue; | ||
import com.google.common.collect.Maps; | ||
import com.ryanharter.auto.value.gson.GenerateTypeAdapter; | ||
import java.util.List; | ||
import java.util.Map; | ||
import net.starlark.java.eval.Dict; | ||
import net.starlark.java.eval.Starlark; | ||
|
||
/** Wraps a dictionary of attribute names and values. Always uses a dict to represent them */ | ||
@AutoValue | ||
@GenerateTypeAdapter | ||
public abstract class AttributeValues { | ||
|
||
public static AttributeValues create(Dict<String, Object> attribs) { | ||
return new AutoValue_AttributeValues(attribs); | ||
} | ||
|
||
public static AttributeValues create(Map<String, Object> attribs) { | ||
return new AutoValue_AttributeValues( | ||
Dict.immutableCopyOf(Maps.transformValues(attribs, AttributeValues::valueToStarlark))); | ||
} | ||
|
||
public abstract Dict<String, Object> attributes(); | ||
|
||
// TODO(salmasamy) this is a copy of Attribute::valueToStarlark, Maybe think of a better place? | ||
private static Object valueToStarlark(Object x) { | ||
// Is x a non-empty string_list_dict? | ||
if (x instanceof Map) { | ||
Map<?, ?> map = (Map<?, ?>) x; | ||
if (!map.isEmpty() && map.values().iterator().next() instanceof List) { | ||
Dict.Builder<Object, Object> dict = Dict.builder(); | ||
for (Map.Entry<?, ?> e : map.entrySet()) { | ||
dict.put(e.getKey(), Starlark.fromJava(e.getValue(), null)); | ||
} | ||
return dict.buildImmutable(); | ||
} | ||
} | ||
// For all other attribute values, shallow conversion is safe. | ||
return Starlark.fromJava(x, null); | ||
} | ||
} |
156 changes: 156 additions & 0 deletions
156
src/main/java/com/google/devtools/build/lib/bazel/bzlmod/AttributeValuesAdapter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// Copyright 2023 The Bazel Authors. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
package com.google.devtools.build.lib.bazel.bzlmod; | ||
|
||
import com.google.devtools.build.lib.cmdline.Label; | ||
import com.google.gson.JsonArray; | ||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonNull; | ||
import com.google.gson.JsonObject; | ||
import com.google.gson.JsonParser; | ||
import com.google.gson.JsonPrimitive; | ||
import com.google.gson.TypeAdapter; | ||
import com.google.gson.stream.JsonReader; | ||
import com.google.gson.stream.JsonWriter; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import net.starlark.java.eval.Dict; | ||
import net.starlark.java.eval.EvalException; | ||
import net.starlark.java.eval.Mutability; | ||
import net.starlark.java.eval.Starlark; | ||
import net.starlark.java.eval.StarlarkInt; | ||
import net.starlark.java.eval.StarlarkList; | ||
|
||
/** Helps serialize/deserialize {@link AttributeValues}, which contains Starlark values. */ | ||
public class AttributeValuesAdapter extends TypeAdapter<AttributeValues> { | ||
|
||
@Override | ||
public void write(JsonWriter out, AttributeValues attributeValues) throws IOException { | ||
JsonObject jsonObject = new JsonObject(); | ||
for (Map.Entry<String, Object> entry : attributeValues.attributes().entrySet()) { | ||
jsonObject.add(entry.getKey(), serializeObject(entry.getValue())); | ||
} | ||
out.jsonValue(jsonObject.toString()); | ||
} | ||
|
||
@Override | ||
public AttributeValues read(JsonReader in) throws IOException { | ||
JsonObject jsonObject = JsonParser.parseReader(in).getAsJsonObject(); | ||
Dict.Builder<String, Object> dict = Dict.builder(); | ||
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { | ||
dict.put(entry.getKey(), deserializeObject(entry.getValue())); | ||
} | ||
return AttributeValues.create(dict.buildImmutable()); | ||
} | ||
|
||
/** | ||
* Starlark Object Types Bool Integer String Label List (Int, label, string) Dict (String,list) & | ||
* (Label, String) | ||
*/ | ||
private JsonElement serializeObject(Object obj) { | ||
if (obj.equals(Starlark.NONE)) { | ||
return JsonNull.INSTANCE; | ||
} else if (obj instanceof Boolean) { | ||
return new JsonPrimitive((Boolean) obj); | ||
} else if (obj instanceof StarlarkInt) { | ||
try { | ||
return new JsonPrimitive(((StarlarkInt) obj).toInt("serialization into the lockfile")); | ||
} catch (EvalException e) { | ||
throw new IllegalArgumentException("Unable to parse StarlarkInt to Integer: " + e); | ||
} | ||
} else if (obj instanceof String || obj instanceof Label) { | ||
return new JsonPrimitive(serializeObjToString(obj)); | ||
} else if (obj instanceof Dict) { | ||
JsonObject jsonObject = new JsonObject(); | ||
for (Map.Entry<?, ?> entry : ((Dict<?, ?>) obj).entrySet()) { | ||
jsonObject.add(serializeObjToString(entry.getKey()), serializeObject(entry.getValue())); | ||
} | ||
return jsonObject; | ||
} else if (obj instanceof StarlarkList) { | ||
JsonArray jsonArray = new JsonArray(); | ||
for (Object item : (StarlarkList<?>) obj) { | ||
jsonArray.add(serializeObject(item)); | ||
} | ||
return jsonArray; | ||
} else { | ||
throw new IllegalArgumentException("Unsupported type: " + obj.getClass()); | ||
} | ||
} | ||
|
||
private Object deserializeObject(JsonElement json) { | ||
if (json == null || json.isJsonNull()) { | ||
return Starlark.NONE; | ||
} else if (json.isJsonPrimitive()) { | ||
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive(); | ||
if (jsonPrimitive.isBoolean()) { | ||
return jsonPrimitive.getAsBoolean(); | ||
} else if (jsonPrimitive.isNumber()) { | ||
return StarlarkInt.of(jsonPrimitive.getAsInt()); | ||
} else if (jsonPrimitive.isString()) { | ||
return deserializeStringToObject(jsonPrimitive.getAsString()); | ||
} else { | ||
throw new IllegalArgumentException("Unsupported JSON primitive: " + jsonPrimitive); | ||
} | ||
} else if (json.isJsonObject()) { | ||
JsonObject jsonObject = json.getAsJsonObject(); | ||
Dict.Builder<Object, Object> dict = Dict.builder(); | ||
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { | ||
dict.put(deserializeStringToObject(entry.getKey()), deserializeObject(entry.getValue())); | ||
} | ||
return dict.buildImmutable(); | ||
} else if (json.isJsonArray()) { | ||
JsonArray jsonArray = json.getAsJsonArray(); | ||
List<Object> list = new ArrayList<>(); | ||
for (JsonElement item : jsonArray) { | ||
list.add(deserializeObject(item)); | ||
} | ||
return StarlarkList.copyOf(Mutability.IMMUTABLE, list); | ||
} else { | ||
throw new IllegalArgumentException("Unsupported JSON element: " + json); | ||
} | ||
} | ||
|
||
/** | ||
* Serializes an object (Label or String) to String A label is converted to a String as it is. A | ||
* String is being modified with a delimiter to be easily differentiated from the label when | ||
* deserializing. | ||
* | ||
* @param obj String or Label | ||
* @return serialized object | ||
*/ | ||
private String serializeObjToString(Object obj) { | ||
if (obj instanceof Label) { | ||
return ((Label) obj).getUnambiguousCanonicalForm(); | ||
} | ||
return "--" + obj; | ||
} | ||
|
||
/** | ||
* Deserializes a string to either a label or a String depending on the prefix. A string will have | ||
* a delimiter at the start, else it is converted to a label. | ||
* | ||
* @param value String to be deserialized | ||
* @return Object of type String of Label | ||
*/ | ||
private Object deserializeStringToObject(String value) { | ||
if (value.startsWith("--")) { | ||
return value.substring(2); | ||
} | ||
return Label.parseCanonicalUnchecked(value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
23518b8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bazel-io flag