diff options
author | Mark Schaller <mschaller@google.com> | 2015-08-13 14:29:47 +0000 |
---|---|---|
committer | Philipp Wollermann <philwo@google.com> | 2015-08-14 20:06:38 +0000 |
commit | f1eef673b5c8394c58afb755f5d8a08f546165c0 (patch) | |
tree | 9b12b8e1a96675608bfd90252ef1bcab2546fec5 /src/main/java/com/google | |
parent | 2ab3247957da0a02819ac414ca94861c0d15d5a6 (diff) |
Deserialize configured map attributes that share keys
Previously, configured attribute value flattening caused failures when
deserializing maps whose configured values had entries with the same
keys. Now, flattened maps successfully deserialize, retaining the
first entry seen for each key.
--
MOS_MIGRATED_REVID=100573192
Diffstat (limited to 'src/main/java/com/google')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java b/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java index 87286d5e72..d48c5e6bfe 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java +++ b/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java @@ -17,6 +17,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.Location; @@ -41,6 +42,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -541,17 +543,35 @@ public class PackageDeserializer { return attrPb.hasLicense() ? deserializeLicense(attrPb.getLicense()) : null; case STRING_DICT: { + // Building an immutable map will fail if the builder was given duplicate keys. These entry + // lists may contain duplicate keys if the serialized map value was configured (e.g. via + // the select function) and the different configuration values had keys in common. This is + // because serialization flattens configurable map-valued attributes. + // + // As long as serialization does this flattening, to avoid failure during deserialization, + // we dedupe entries in the list by their keys. + // TODO(bazel-team): Serialize and deserialize configured values with fidelity (without + // flattening them). ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (Build.StringDictEntry entry : attrPb.getStringDictValueList()) { - builder.put(entry.getKey(), entry.getValue()); + String key = entry.getKey(); + if (keysSeenSoFar.add(key)) { + builder.put(key, entry.getValue()); + } } return builder.build(); } case STRING_DICT_UNARY: { + // See STRING_DICT case's comment about why this dedupes entries by their keys. ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (StringDictUnaryEntry entry : attrPb.getStringDictUnaryValueList()) { - builder.put(entry.getKey(), entry.getValue()); + String key = entry.getKey(); + if (keysSeenSoFar.add(key)) { + builder.put(key, entry.getValue()); + } } return builder.build(); } @@ -560,17 +580,27 @@ public class PackageDeserializer { return deserializeFilesetEntries(attrPb.getFilesetListValueList()); case LABEL_LIST_DICT: { + // See STRING_DICT case's comment about why this dedupes entries by their keys. ImmutableMap.Builder<String, List<Label>> builder = ImmutableMap.builder(); + HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (Build.LabelListDictEntry entry : attrPb.getLabelListDictValueList()) { - builder.put(entry.getKey(), deserializeLabels(entry.getValueList())); + String key = entry.getKey(); + if (keysSeenSoFar.add(key)) { + builder.put(key, deserializeLabels(entry.getValueList())); + } } return builder.build(); } case STRING_LIST_DICT: { + // See STRING_DICT case's comment about why this dedupes entries by their keys. ImmutableMap.Builder<String, List<String>> builder = ImmutableMap.builder(); + HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (Build.StringListDictEntry entry : attrPb.getStringListDictValueList()) { - builder.put(entry.getKey(), ImmutableList.copyOf(entry.getValueList())); + String key = entry.getKey(); + if (keysSeenSoFar.add(key)) { + builder.put(key, ImmutableList.copyOf(entry.getValueList())); + } } return builder.build(); } |