Skip to content

Commit 41072ec

Browse files
authored
Merge pull request googlesamples#456 from googlesamples/bugfix/duplicate-dependencies-gradle-template
activating highest version in duplicate dependencies.
2 parents 30b4f92 + bc2ebf9 commit 41072ec

File tree

6 files changed

+275
-10
lines changed

6 files changed

+275
-10
lines changed

source/AndroidResolver/src/GradleResolver.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ private void LogMissingDependenciesError(List<string> missingArtifacts) {
105105
}
106106
}
107107

108+
/// <summary>
109+
/// Get package spec from a dependency.
110+
/// </summary>
111+
/// <param name="dependency">Dependency instance to query for package spec.</param>
112+
internal static string DependencyToPackageSpec(Dependency dependency) {
113+
return dependency.Version.ToUpper() == "LATEST" ?
114+
dependency.VersionlessKey + ":+" : dependency.Key;
115+
}
116+
108117
/// <summary>
109118
/// From a list of dependencies generate a list of Maven / Gradle / Ivy package spec
110119
/// strings.
@@ -116,8 +125,7 @@ internal static Dictionary<string, string> DependenciesToPackageSpecs(
116125
var sourcesByPackageSpec = new Dictionary<string, string>();
117126
foreach (var dependency in dependencies) {
118127
// Convert the legacy "LATEST" version spec to a Gradle version spec.
119-
var packageSpec = dependency.Version.ToUpper() == "LATEST" ?
120-
dependency.VersionlessKey + ":+" : dependency.Key;
128+
var packageSpec = DependencyToPackageSpec(dependency);
121129
var source = CommandLine.SplitLines(dependency.CreatedBy)[0];
122130
string sources;
123131
if (sourcesByPackageSpec.TryGetValue(packageSpec, out sources)) {

source/AndroidResolver/src/PlayServicesResolver.cs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,15 +2191,56 @@ internal static IList<string> GradleDependenciesLines(
21912191
// https://docs.gradle.org/3.4/release-notes.html#the-java-library-plugin
21922192
// https://developer.android.com/studio/releases/gradle-plugin#3-0-0
21932193
var version = GradleVersion;
2194+
var versionComparer = new Dependency.VersionComparer();
21942195
var includeStatement =
21952196
!String.IsNullOrEmpty(version) &&
2196-
(new Dependency.VersionComparer()).Compare("3.4", version) >= 0 ?
2197+
versionComparer.Compare("3.4", version) >= 0 ?
21972198
"implementation" : "compile";
21982199
if (includeDependenciesBlock) lines.Add("dependencies {");
2200+
// Build a map of dependencies with the max version of that dependency.
2201+
// If different packages have different versions of the same dependency,
2202+
// we want to activate only the highest version but still include the
2203+
// other versions as commented out dependency lines.
2204+
var dependenciesMaxVersions = new Dictionary<string, Dependency>();
2205+
// Maintain a set of packages which we want to comment out.
2206+
HashSet<string> packageSpecStringsToComment = new HashSet<string>();
2207+
foreach( var dependency in dependencies) {
2208+
Dependency dependencyMaxVersion;
2209+
if (dependenciesMaxVersions.TryGetValue(dependency.VersionlessKey, out dependencyMaxVersion)){
2210+
if(versionComparer.Compare(dependency.Version, dependencyMaxVersion.Version) < 0) {
2211+
dependenciesMaxVersions[dependency.VersionlessKey] = dependency;
2212+
// We found a new larger version. Comment out older one
2213+
// Build a single item list since `GetPackageSpecs`
2214+
// accepts an IEnumerable type.
2215+
var packageSpecString = GradleResolver.DependencyToPackageSpec(dependencyMaxVersion);
2216+
packageSpecStringsToComment.Add(packageSpecString);
2217+
}
2218+
else {
2219+
// Dependency version is smaller than current max.
2220+
var packageSpecString = GradleResolver.DependencyToPackageSpec(dependency);
2221+
packageSpecStringsToComment.Add(packageSpecString);
2222+
}
2223+
}
2224+
else {
2225+
// First time encountering this dependency.
2226+
dependenciesMaxVersions[dependency.VersionlessKey] = dependency;
2227+
}
2228+
}
21992229
foreach (var packageSpecAndSources in GetPackageSpecs(dependencies: dependencies)) {
2200-
lines.Add(String.Format(
2201-
" {0} '{1}' // {2}", includeStatement, packageSpecAndSources.Key,
2202-
packageSpecAndSources.Value));
2230+
string line = " ";
2231+
if (packageSpecStringsToComment.Contains(packageSpecAndSources.Key)) {
2232+
PlayServicesResolver.Log(
2233+
String.Format(
2234+
"Ignoring duplicate package {0} with older version.",
2235+
packageSpecAndSources.Key),
2236+
level: LogLevel.Info
2237+
);
2238+
line += "// ";
2239+
}
2240+
line += String.Format(
2241+
"{0} '{1}' // {2}", includeStatement, packageSpecAndSources.Key,
2242+
packageSpecAndSources.Value);
2243+
lines.Add(line);
22032244
}
22042245
if (includeDependenciesBlock) lines.Add("}");
22052246
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<dependencies>
2+
<androidPackages>
3+
<!-- Duplicate entry for package with a different version (higher). -->
4+
<androidPackage spec="com.google.android.gms:play-services-base:18.0.1" />
5+
<!-- Duplicate entry for package with a different version (lower). -->
6+
<androidPackage spec="com.google.android.gms:play-services-base:12.0.1" />
7+
<!-- Duplicate entry for package with a different version (wildcard). -->
8+
<androidPackage spec="com.google.firebase:firebase-app-unity:5.+"/>
9+
<!-- Duplicate entry for package with the exact same version. -->
10+
<androidPackage spec="com.android.support:support-annotations:26.1.0"/>
11+
</androidPackages>
12+
</dependencies>
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
2+
3+
buildscript {
4+
repositories {
5+
jcenter()
6+
google()
7+
}
8+
9+
dependencies {
10+
classpath 'com.android.tools.build:gradle:3.0.1'
11+
}
12+
}
13+
14+
allprojects {
15+
repositories {
16+
flatDir {
17+
dirs 'libs'
18+
}
19+
}
20+
}
21+
22+
// Android Resolver Repos Start
23+
([rootProject] + (rootProject.subprojects as List)).each { project ->
24+
project.repositories {
25+
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
26+
maven {
27+
url "https://maven.google.com"
28+
}
29+
maven {
30+
url "file:///my/nonexistant/test/repo" // Assets/ExternalDependencyManager/Editor/TestDependencies.xml:17
31+
}
32+
maven {
33+
url (unityProjectPath + "/project_relative_path/repo") // Assets/ExternalDependencyManager/Editor/TestDependencies.xml:17
34+
}
35+
maven {
36+
url (unityProjectPath + "/Assets/GeneratedLocalRepo/Firebase/m2repository") // Assets/ExternalDependencyManager/Editor/TestDependencies.xml:10
37+
}
38+
mavenLocal()
39+
jcenter()
40+
mavenCentral()
41+
}
42+
}
43+
// Android Resolver Repos End
44+
apply plugin: 'com.android.application'
45+
46+
dependencies {
47+
implementation fileTree(dir: 'libs', include: ['*.jar'])
48+
// Android Resolver Dependencies Start
49+
compile 'com.android.support:support-annotations:26.1.0' // Assets/ExternalDependencyManager/Editor/TestDependencies.xml:4
50+
// compile 'com.google.android.gms:play-services-base:12.0.1' // Assets/ExternalDependencyManager/Editor/TestAdditionalDuplicateDependencies.xml:6
51+
// compile 'com.google.android.gms:play-services-base:15.0.1' // Assets/ExternalDependencyManager/Editor/TestAdditionalDependencies.xml:3
52+
compile 'com.google.android.gms:play-services-base:18.0.1' // Assets/ExternalDependencyManager/Editor/TestAdditionalDuplicateDependencies.xml:4
53+
// compile 'com.google.firebase:firebase-app-unity:5.+' // Assets/ExternalDependencyManager/Editor/TestAdditionalDuplicateDependencies.xml:8
54+
compile 'com.google.firebase:firebase-app-unity:5.1.1' // Assets/ExternalDependencyManager/Editor/TestDependencies.xml:10
55+
compile 'com.google.firebase:firebase-common:16.0.0' // Google.AndroidResolverIntegrationTests.SetupDependencies
56+
compile 'org.test.psr:classifier:1.0.1:foo@aar' // Assets/ExternalDependencyManager/Editor/TestDependencies.xml:12
57+
// Android Resolver Dependencies End
58+
**DEPS**}
59+
60+
// Android Resolver Exclusions Start
61+
android {
62+
packagingOptions {
63+
exclude ('lib/unsupported/libFirebaseCppApp-5.1.1.so')
64+
}
65+
}
66+
// Android Resolver Exclusions End
67+
android {
68+
compileSdkVersion **APIVERSION**
69+
buildToolsVersion '**BUILDTOOLS**'
70+
71+
defaultConfig {
72+
minSdkVersion **MINSDKVERSION**
73+
targetSdkVersion **TARGETSDKVERSION**
74+
applicationId '**APPLICATIONID**'
75+
ndk {
76+
abiFilters **ABIFILTERS**
77+
}
78+
versionCode **VERSIONCODE**
79+
versionName '**VERSIONNAME**'
80+
}
81+
82+
lintOptions {
83+
abortOnError false
84+
}
85+
86+
aaptOptions {
87+
noCompress '.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**
88+
}**SIGN**
89+
90+
buildTypes {
91+
debug {
92+
minifyEnabled **MINIFY_DEBUG**
93+
useProguard **PROGUARD_DEBUG**
94+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD**
95+
jniDebuggable true
96+
}
97+
release {
98+
minifyEnabled **MINIFY_RELEASE**
99+
useProguard **PROGUARD_RELEASE**
100+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD****SIGNCONFIG**
101+
}
102+
}**PACKAGING_OPTIONS****SPLITS**
103+
**BUILT_APK_LOCATION**
104+
}**SPLITS_VERSION_CODE****SOURCE_BUILD_SETUP**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
2+
3+
buildscript {
4+
repositories {
5+
jcenter()
6+
google()
7+
}
8+
9+
dependencies {
10+
classpath 'com.android.tools.build:gradle:3.0.1'
11+
}
12+
}
13+
14+
allprojects {
15+
repositories {
16+
flatDir {
17+
dirs 'libs'
18+
}
19+
}
20+
}
21+
22+
apply plugin: 'com.android.application'
23+
24+
dependencies {
25+
implementation fileTree(dir: 'libs', include: ['*.jar'])
26+
**DEPS**}
27+
28+
android {
29+
compileSdkVersion **APIVERSION**
30+
buildToolsVersion '**BUILDTOOLS**'
31+
32+
defaultConfig {
33+
minSdkVersion **MINSDKVERSION**
34+
targetSdkVersion **TARGETSDKVERSION**
35+
applicationId '**APPLICATIONID**'
36+
ndk {
37+
abiFilters **ABIFILTERS**
38+
}
39+
versionCode **VERSIONCODE**
40+
versionName '**VERSIONNAME**'
41+
}
42+
43+
lintOptions {
44+
abortOnError false
45+
}
46+
47+
aaptOptions {
48+
noCompress '.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**
49+
}**SIGN**
50+
51+
buildTypes {
52+
debug {
53+
minifyEnabled **MINIFY_DEBUG**
54+
useProguard **PROGUARD_DEBUG**
55+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD**
56+
jniDebuggable true
57+
}
58+
release {
59+
minifyEnabled **MINIFY_RELEASE**
60+
useProguard **PROGUARD_RELEASE**
61+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD****SIGNCONFIG**
62+
}
63+
}**PACKAGING_OPTIONS****SPLITS**
64+
**BUILT_APK_LOCATION**
65+
}**SPLITS_VERSION_CODE****SOURCE_BUILD_SETUP**

source/AndroidResolver/test/src/AndroidResolverIntegrationTests.cs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ public class AndroidResolverIntegrationTests {
4444
/// </summary>
4545
private const string ADDITIONAL_DEPENDENCIES_FILENAME = "TestAdditionalDependencies";
4646

47+
/// <summary>
48+
/// The name of the file, without extension, that will serve as a template for dynamically
49+
/// adding additional dependencies with a duplicate package with a different version.
50+
/// </summary>
51+
private const string ADDITIONAL_DUPLICATE_DEPENDENCIES_FILENAME = "TestAdditionalDuplicateDependencies";
52+
4753
/// <summary>
4854
/// Disabled application Gradle template file.
4955
/// </summary>
@@ -129,6 +135,29 @@ public static void ConfigureTestCases() {
129135
});
130136
}
131137
},
138+
new IntegrationTester.TestCase {
139+
Name = "ResolveForGradleBuildSystemWithDuplicatePackages",
140+
Method = (testCase, testCaseComplete) => {
141+
ClearAllDependencies();
142+
SetupDependencies();
143+
// Add 2 additional dependency files (each file contains a single package
144+
// but with different versions).
145+
UpdateAdditionalDependenciesFile(true, ADDITIONAL_DEPENDENCIES_FILENAME);
146+
UpdateAdditionalDependenciesFile(true, ADDITIONAL_DUPLICATE_DEPENDENCIES_FILENAME);
147+
148+
ResolveWithGradleTemplate(
149+
GRADLE_TEMPLATE_DISABLED,
150+
"ExpectedArtifacts/NoExport/GradleTemplateDuplicatePackages",
151+
testCase, testCaseComplete,
152+
otherExpectedFiles: new [] {
153+
"Assets/GeneratedLocalRepo/Firebase/m2repository/com/google/" +
154+
"firebase/firebase-app-unity/5.1.1/firebase-app-unity-5.1.1.aar" },
155+
filesToIgnore: new HashSet<string> {
156+
Path.GetFileName(GRADLE_TEMPLATE_LIBRARY_DISABLED),
157+
Path.GetFileName(GRADLE_TEMPLATE_PROPERTIES_DISABLED)
158+
});
159+
}
160+
},
132161
new IntegrationTester.TestCase {
133162
Name = "ResolverForGradleBuildSystemWithTemplateUsingJetifier",
134163
Method = (testCase, testCaseComplete) => {
@@ -474,7 +503,8 @@ private static void ClearAllDependencies() {
474503
GooglePlayServices.SettingsDialog.PatchPropertiesTemplateGradle = false;
475504

476505
PlayServicesSupport.ResetDependencies();
477-
UpdateAdditionalDependenciesFile(false);
506+
UpdateAdditionalDependenciesFile(false, ADDITIONAL_DEPENDENCIES_FILENAME);
507+
UpdateAdditionalDependenciesFile(false, ADDITIONAL_DUPLICATE_DEPENDENCIES_FILENAME);
478508
}
479509

480510
/// <summary>
@@ -565,14 +595,18 @@ private static void CompareKeyValuePairLists(
565595
/// </summary>
566596
/// <param name="addDependencyFile">If true, will copy the template file to an XML file if it
567597
/// doesn't exist. If false, delete the XML file if it exists.</param>
568-
private static void UpdateAdditionalDependenciesFile(bool addDependencyFile) {
598+
/// <param name="filename">Name of the template file (without extension) to
599+
/// create an XML from. </param>
600+
private static void UpdateAdditionalDependenciesFile(
601+
bool addDependencyFile,
602+
string filename=ADDITIONAL_DEPENDENCIES_FILENAME) {
569603
string currentDirectory = Directory.GetCurrentDirectory();
570604
string editorPath = Path.Combine(currentDirectory,
571605
"Assets/ExternalDependencyManager/Editor/");
572606

573-
string templateFilePath = Path.Combine(editorPath, ADDITIONAL_DEPENDENCIES_FILENAME +
607+
string templateFilePath = Path.Combine(editorPath, filename+
574608
".template");
575-
string xmlFilePath = Path.Combine(editorPath, ADDITIONAL_DEPENDENCIES_FILENAME + ".xml");
609+
string xmlFilePath = Path.Combine(editorPath, filename+ ".xml");
576610
if (addDependencyFile && !File.Exists(xmlFilePath)) {
577611
if (!File.Exists(templateFilePath)) {
578612
UnityEngine.Debug.LogError("Could not find file: " + templateFilePath);

0 commit comments

Comments
 (0)