aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java63
1 files changed, 35 insertions, 28 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
index 3ee002a98d..34b424b521 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
@@ -36,9 +36,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
-/**
- * Handles the Merging of ParsedAndroidData.
- */
+/** Handles the Merging of ParsedAndroidData. */
public class AndroidDataMerger {
private static final Logger logger = Logger.getLogger(AndroidDataMerger.class.getCanonicalName());
@@ -128,7 +126,6 @@ public class AndroidDataMerger {
}
}
}
-
}
static class NoopSourceChecker implements SourceChecker {
@@ -152,8 +149,7 @@ public class AndroidDataMerger {
/** Creates a merger with a custom deduplicator and a default {@link ExecutorService}. */
public static AndroidDataMerger createWithDefaultThreadPool(SourceChecker deDuplicator) {
- return new AndroidDataMerger(deDuplicator,
- MoreExecutors.newDirectExecutorService());
+ return new AndroidDataMerger(deDuplicator, MoreExecutors.newDirectExecutorService());
}
/** Creates a merger with a custom deduplicator and an {@link ExecutorService}. */
@@ -224,18 +220,20 @@ public class AndroidDataMerger {
/**
* Merges DataResources into an UnwrittenMergedAndroidData.
- * <p>
- * This method has two basic states, library and binary. These are distinguished by
+ *
+ * <p>This method has two basic states, library and binary. These are distinguished by
* allowPrimaryOverrideAll, which allows the primary data to overwrite any value in the closure, a
* trait associated with binaries, as a binary is a leaf node. The other semantics are slightly
* more complicated: a given resource can be overwritten only if it resides in the direct
* dependencies of primary data. This forces an explicit simple priority for each resource,
* instead of the more subtle semantics of multiple layers of libraries with potential overwrites.
- * <p>
- * The UnwrittenMergedAndroidData contains only one of each DataKey in both the direct and
+ *
+ * <p>The UnwrittenMergedAndroidData contains only one of each DataKey in both the direct and
* transitive closure.
*
- * The merge semantics for overwriting resources (non id and styleable) are as follows: <pre>
+ * <p>The merge semantics for overwriting resources (non id and styleable) are as follows:
+ *
+ * <pre>
* Key:
* A(): package A
* A(foo): package A with resource symbol foo
@@ -266,22 +264,24 @@ public class AndroidDataMerger {
* A(foo),B(foo) -> C() -> D(foo) == Valid
* A() -> B(foo),C(foo) -> D(foo) == Valid
* </pre>
- * <p>
- * Combining resources are much simpler -- since a combining (id and styleable) resource does not
- * get replaced when redefined, they are simply combined: <pre>
+ *
+ * <p>Combining resources are much simpler -- since a combining (id and styleable) resource does
+ * not get replaced when redefined, they are simply combined:
+ *
+ * <pre>
* A(foo) -> B(foo) -> C(foo) == Valid
- *
+ *
* </pre>
- *
+ *
* @param transitive The transitive dependencies to merge.
* @param direct The direct dependencies to merge.
* @param primaryData The primary data to merge against.
* @param allowPrimaryOverrideAll Boolean that indicates if the primary data will be considered
- * the ultimate source of truth, provided it doesn't conflict with itself.
+ * the ultimate source of truth, provided it doesn't conflict with itself.
* @return An UnwrittenMergedAndroidData, containing DataResource objects that can be written to
- * disk for aapt processing or serialized for future merge passes.
+ * disk for aapt processing or serialized for future merge passes.
* @throws MergingException if there are merge conflicts or issues with parsing resources from
- * primaryData.
+ * primaryData.
*/
UnwrittenMergedAndroidData merge(
ParsedAndroidData transitive,
@@ -314,6 +314,8 @@ public class AndroidDataMerger {
final KeyValueConsumers primaryConsumers = primaryBuilder.consumers();
final Set<MergeConflict> conflicts = new HashSet<>();
+
+ // Find all internal conflicts.
conflicts.addAll(parsedPrimary.conflicts());
for (MergeConflict conflict : Iterables.concat(direct.conflicts(), transitive.conflicts())) {
if (allowPrimaryOverrideAll
@@ -326,7 +328,12 @@ public class AndroidDataMerger {
// overwriting resources
for (Entry<DataKey, DataResource> entry : parsedPrimary.iterateOverwritableEntries()) {
- primaryConsumers.overwritingConsumer.consume(entry.getKey(), entry.getValue());
+ if (direct.containsOverwritable(entry.getKey())) {
+ primaryConsumers.overwritingConsumer.consume(
+ entry.getKey(), entry.getValue().overwrite(direct.getOverwritable(entry.getKey())));
+ } else {
+ primaryConsumers.overwritingConsumer.consume(entry.getKey(), entry.getValue());
+ }
}
for (Map.Entry<DataKey, DataResource> entry : direct.iterateOverwritableEntries()) {
@@ -379,7 +386,12 @@ public class AndroidDataMerger {
// assets
for (Entry<DataKey, DataAsset> entry : parsedPrimary.iterateAssetEntries()) {
- primaryConsumers.assetConsumer.consume(entry.getKey(), entry.getValue());
+ if (direct.containsAsset(entry.getKey())) {
+ primaryConsumers.assetConsumer.consume(
+ entry.getKey(), entry.getValue().overwrite(direct.getAsset(entry.getKey())));
+ } else {
+ primaryConsumers.assetConsumer.consume(entry.getKey(), entry.getValue());
+ }
}
for (Map.Entry<DataKey, DataAsset> entry : direct.iterateAssetEntries()) {
@@ -412,9 +424,7 @@ public class AndroidDataMerger {
if (!conflicts.isEmpty()) {
List<String> messages = new ArrayList<>();
for (MergeConflict conflict : conflicts) {
- if (!conflict.first().equals(conflict.second())
- && !deDuplicator.checkEquality(
- conflict.first().source(), conflict.second().source())) {
+ if (conflict.isValidWith(deDuplicator)) {
messages.add(conflict.toConflictMessage());
}
}
@@ -423,11 +433,8 @@ public class AndroidDataMerger {
logger.warning(Joiner.on("").join(messages));
}
}
-
return UnwrittenMergedAndroidData.of(
- primaryManifest,
- primaryBuilder.build(),
- transitiveBuilder.build());
+ primaryManifest, primaryBuilder.build(), transitiveBuilder.build());
} catch (IOException e) {
throw MergingException.wrapException(e).build();
}