Skip to content

Commit

Permalink
[XABT] Allow deployment artifacts to specify mutiple JavaDependencyVe…
Browse files Browse the repository at this point in the history
…rification JavaArtifact libraries.
  • Loading branch information
jpobst committed Jul 15, 2024
1 parent 000759c commit c19adb8
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 75 deletions.
47 changes: 23 additions & 24 deletions src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,12 @@ public void AddAndroidLibraries (ITaskItem []? tasks)
{
foreach (var task in tasks.OrEmpty ()) {
var id = task.GetMetadataOrDefault ("JavaArtifact", string.Empty);
var version = task.GetMetadataOrDefault ("JavaVersion", string.Empty);

// TODO: Should raise an error if JavaArtifact is specified but JavaVersion is not
if (!id.HasValue () || !version.HasValue ())
continue;

if (version != null && MavenExtensions.TryParseArtifactWithVersion (id, version, log, out var art)) {
log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from AndroidLibrary '{3}'", art.GroupId, art.Id, art.Version, task.ItemSpec);
artifacts.Add (art.ArtifactString, art);
if (MavenExtensions.TryParseArtifacts (id, log, out var parsed)) {
foreach (var art in parsed) {
log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from AndroidLibrary '{3}'", art.GroupId, art.Id, art.Version, task.ItemSpec);
artifacts.Add (art.ArtifactString, art);
}
}
}
}
Expand All @@ -166,13 +163,15 @@ public void AddPackageReferences (ITaskItem []? tasks)
{
foreach (var task in tasks.OrEmpty ()) {

// See if JavaArtifact/JavaVersion overrides were used
if (task.TryParseJavaArtifactAndJavaVersion ("PackageReference", log, out var explicit_artifact, out var attributes_specified)) {
artifacts.Add (explicit_artifact.ArtifactString, explicit_artifact);
// See if JavaArtifact override was used
if (task.TryParseJavaArtifacts ("PackageReference", log, out var explicit_artifacts, out var attributes_specified)) {
foreach (var explicit_artifact in explicit_artifacts)
artifacts.Add (explicit_artifact.ArtifactString, explicit_artifact);

continue;
}

// If user tried to specify JavaArtifact or JavaVersion, but did it incorrectly, we do not perform any fallback
// If user tried to specify JavaArtifact, but did it incorrectly, we do not perform any fallback
if (attributes_specified)
continue;

Expand All @@ -193,13 +192,15 @@ public void AddPackageReferences (ITaskItem []? tasks)
public void AddProjectReferences (ITaskItem []? tasks)
{
foreach (var task in tasks.OrEmpty ()) {
// See if JavaArtifact/JavaVersion overrides were used
if (task.TryParseJavaArtifactAndJavaVersion ("ProjectReference", log, out var explicit_artifact, out var attributes_specified)) {
artifacts.Add (explicit_artifact.ArtifactString, explicit_artifact);
// See if JavaArtifact override was used
if (task.TryParseJavaArtifacts ("ProjectReference", log, out var explicit_artifacts, out var attributes_specified)) {
foreach (var explicit_artifact in explicit_artifacts)
artifacts.Add (explicit_artifact.ArtifactString, explicit_artifact);

continue;
}

// If user tried to specify JavaArtifact or JavaVersion, but did it incorrectly, we do not perform any fallback
// If user tried to specify JavaArtifact, but did it incorrectly, we do not perform any fallback
if (attributes_specified)
continue;

Expand All @@ -212,14 +213,12 @@ public void AddIgnoredDependencies (ITaskItem []? tasks)
{
foreach (var task in tasks.OrEmpty ()) {
var id = task.ItemSpec;
var version = task.GetRequiredMetadata ("AndroidIgnoredJavaDependency", "Version", log);

if (version is null)
continue;

if (version != null && MavenExtensions.TryParseArtifactWithVersion (id, version, log, out var art)) {
log.LogMessage ("Ignoring Java dependency '{0}:{1}' version '{2}'", art.GroupId, art.Id, art.Version);
artifacts.Add (art.ArtifactString, art);
if (MavenExtensions.TryParseArtifacts (id, log, out var parsed)) {
foreach (var art in parsed) {
log.LogMessage ("Ignoring Java dependency '{0}:{1}' version '{2}'", art.GroupId, art.Id, art.Version);
artifacts.Add (art.ArtifactString, art);
}
}
}
}
Expand Down Expand Up @@ -263,7 +262,7 @@ public MSBuildLoggingPomResolver (TaskLoggingHelper logger)

Artifact? RegisterFromTaskItem (ITaskItem item, string itemName, string filename)
{
item.TryParseJavaArtifactAndJavaVersion (itemName, logger, out var artifact, out var _);
item.TryParseJavaArtifact (itemName, logger, out var artifact, out var _);

if (!File.Exists (filename)) {
logger.LogCodedError ("XA4245", Properties.Resources.XA4245, filename);
Expand Down
6 changes: 2 additions & 4 deletions src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ public async override System.Threading.Tasks.Task RunTaskAsync ()

var result = new TaskItem (artifact_file);

result.SetMetadata ("JavaArtifact", $"{artifact.GroupId}:{artifact.Id}");
result.SetMetadata ("JavaVersion", artifact.Version);
result.SetMetadata ("JavaArtifact", artifact.VersionedArtifactString);

// Allow user to opt out of dependency verification
if (string.Compare (item.GetMetadataOrDefault ("VerifyDependencies", "true"), "false", true) == 0)
Expand All @@ -121,8 +120,7 @@ public async override System.Threading.Tasks.Task RunTaskAsync ()
var pom_item = new TaskItem (kv.Value);
var pom_artifact = Artifact.Parse (kv.Key);

pom_item.SetMetadata ("JavaArtifact", $"{pom_artifact.GroupId}:{pom_artifact.Id}");
pom_item.SetMetadata ("JavaVersion", pom_artifact.Version);
pom_item.SetMetadata ("JavaArtifact", pom_artifact.VersionedArtifactString);

additionalPoms.Add (pom_item);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -888,14 +888,9 @@ public void AndroidMavenLibrary_AllDependenciesAreVerified ()
var collection = new XamarinAndroidBindingProject ();

// Dependencies ignored by <AndroidIgnoredJavaDependency>
var concurrent = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.concurrent:concurrent-futures");
concurrent.Metadata.Add ("Version", "1.1.0");

var lifecycle = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.lifecycle:lifecycle-runtime");
lifecycle.Metadata.Add ("Version", "2.6.2");

var parcelable = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.versionedparcelable:versionedparcelable");
parcelable.Metadata.Add ("Version", "1.2.0");
var concurrent = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.concurrent:concurrent-futures:1.1.0");
var lifecycle = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.lifecycle:lifecycle-runtime:2.6.2");
var parcelable = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.versionedparcelable:versionedparcelable:1.2.0");

var proj = new XamarinAndroidBindingProject {
Jars = { item, annotations_experimental_androidlib },
Expand All @@ -905,8 +900,7 @@ public void AndroidMavenLibrary_AllDependenciesAreVerified ()

proj.AddReference (collection);
var collection_proj = proj.References.First ();
collection_proj.Metadata.Add ("JavaArtifact", "androidx.collection:collection");
collection_proj.Metadata.Add ("JavaVersion", "1.3.0");
collection_proj.Metadata.Add ("JavaArtifact", "androidx.collection:collection:1.3.0");

using var a = CreateDllBuilder ();
using var b = CreateDllBuilder ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void MalformedMicrosoftPackagesJson ()
BuildEngine = engine,
AndroidLibraries = [
CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath),
CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core", "1.0"),
CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core:1.0"),
],
MicrosoftPackagesFile = package_finder.FilePath,
};
Expand All @@ -184,7 +184,7 @@ public void DependencyFulfilledByAndroidLibrary ()
BuildEngine = engine,
AndroidLibraries = [
CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath),
CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core", "1.0"),
CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core:1.0"),
],
};

Expand All @@ -208,7 +208,7 @@ public void DependencyFulfilledByProjectReferenceExplicitMetadata ()
CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath),
],
ProjectReferences = [
CreateAndroidLibraryTaskItem ("Google.Material.Core.csproj", null, "com.google.android:material-core", "1.0"),
CreateAndroidLibraryTaskItem ("Google.Material.Core.csproj", null, "com.google.android:material-core:1.0"),
],
};

Expand All @@ -232,7 +232,7 @@ public void DependencyFulfilledByPackageReferenceExplicitMetadata ()
CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath),
],
PackageReferences = [
CreateAndroidLibraryTaskItem ("Xamarin.Google.Material.Core", null, "com.google.android:material-core", "1.0"),
CreateAndroidLibraryTaskItem ("Xamarin.Google.Material.Core", null, "com.google.android:material-core:1.0"),
],
};

Expand All @@ -256,7 +256,7 @@ public void DependencyIgnored ()
CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath),
],
IgnoredDependencies = [
CreateAndroidLibraryTaskItem ("com.google.android:material-core", rawVersion: "1.0"),
CreateAndroidLibraryTaskItem ("com.google.android:material-core:1.0"),
],
};

Expand All @@ -279,7 +279,7 @@ public void DependencyWithoutVersionFulfilled ()
BuildEngine = engine,
AndroidLibraries = [
CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath),
CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core", "1.0"),
CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core:1.0"),
],
};

Expand Down Expand Up @@ -312,18 +312,14 @@ public void DependencyWithoutVersionNotFulfilled ()
Assert.AreEqual ("Java dependency 'com.google.android:material-core' is not satisfied.", engine.Errors [0].Message);
}

TaskItem CreateAndroidLibraryTaskItem (string name, string? manifest = null, string? javaArtifact = null, string? javaVersion = null, string? rawVersion = null)
TaskItem CreateAndroidLibraryTaskItem (string name, string? manifest = null, string? javaArtifact = null)
{
var item = new TaskItem (name);

if (manifest is not null)
item.SetMetadata ("Manifest", manifest);
if (javaArtifact is not null)
item.SetMetadata ("JavaArtifact", javaArtifact);
if (javaVersion is not null)
item.SetMetadata ("JavaVersion", javaVersion);
if (rawVersion is not null)
item.SetMetadata ("Version", rawVersion);

return item;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,7 @@ public async Task MavenCentralSuccess ()

var output_item = task.ResolvedAndroidMavenLibraries! [0];

Assert.AreEqual ("com.google.auto.value:auto-value-annotations", output_item.GetMetadata ("JavaArtifact"));
Assert.AreEqual ("1.10.4", output_item.GetMetadata ("JavaVersion"));
Assert.AreEqual ("com.google.auto.value:auto-value-annotations:1.10.4", output_item.GetMetadata ("JavaArtifact"));
Assert.AreEqual (Path.Combine (temp_cache_dir, "central", "com.google.auto.value", "auto-value-annotations", "1.10.4", "auto-value-annotations-1.10.4.pom"), output_item.GetMetadata ("Manifest"));
} finally {
DeleteTempDirectory (temp_cache_dir);
Expand All @@ -164,8 +163,7 @@ public async Task MavenGoogleSuccess ()

var output_item = task.ResolvedAndroidMavenLibraries! [0];

Assert.AreEqual ("androidx.core:core", output_item.GetMetadata ("JavaArtifact"));
Assert.AreEqual ("1.12.0", output_item.GetMetadata ("JavaVersion"));
Assert.AreEqual ("androidx.core:core:1.12.0", output_item.GetMetadata ("JavaArtifact"));
Assert.AreEqual (Path.Combine (temp_cache_dir, "google", "androidx.core", "core", "1.12.0", "core-1.12.0.pom"), output_item.GetMetadata ("Manifest"));
} finally {
DeleteTempDirectory (temp_cache_dir);
Expand Down
75 changes: 53 additions & 22 deletions src/Xamarin.Android.Build.Tasks/Utilities/MavenExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
Expand All @@ -17,6 +18,7 @@ namespace Xamarin.Android.Tasks;
static class MavenExtensions
{
static readonly char [] separator = [':'];
static readonly char [] artifacts_separators = [';', ',', '\r', '\n'];

/// <summary>
/// Shortcut for !string.IsNullOrWhiteSpace (s)
Expand Down Expand Up @@ -54,47 +56,76 @@ public static bool TryParseArtifactWithVersion (string id, string version, TaskL
return true;
}

public static bool TryParseJavaArtifactAndJavaVersion (this ITaskItem task, string type, TaskLoggingHelper log, [NotNullWhen (true)] out Artifact? artifact, out bool attributesSpecified)
public static bool TryParseArtifacts (string id, TaskLoggingHelper log, out List<Artifact> artifacts)
{
artifact = null;
var item_name = task.ItemSpec;
artifacts = new List<Artifact> ();
var result = true;

// Convert "../../src/blah/Blah.csproj" to "Blah.csproj"
if (type == "ProjectReference")
item_name = Path.GetFileName (item_name);
var arts = id.Split (artifacts_separators, StringSplitOptions.RemoveEmptyEntries);

var has_artifact = task.HasMetadata ("JavaArtifact");
var has_version = task.HasMetadata ("JavaVersion");
foreach (var art in arts) {

if (Artifact.TryParse (art, out var a)) {
artifacts.Add (a);
continue;
}

log.LogCodedError ("XA4235", Properties.Resources.XA4235, art);
result = false;
}

// Lets callers know if user attempted to specify JavaArtifact or JavaVersion, even if they did it incorrectly
attributesSpecified = has_artifact || has_version;
return result;
}

if (has_artifact && !has_version) {
log.LogCodedError ("XA4243", Properties.Resources.XA4243, "JavaVersion", "JavaArtifact", type, item_name);
public static bool TryParseJavaArtifact (this ITaskItem task, string type, TaskLoggingHelper log, [NotNullWhen (true)]out Artifact? artifact, out bool attributesSpecified)
{
var result = TryParseJavaArtifacts (task, type, log, out var artifacts, out attributesSpecified);

if (!result) {
artifact = null;
return false;
}

if (!has_artifact && has_version) {
log.LogCodedError ("XA4243", Properties.Resources.XA4243, "JavaArtifact", "JavaVersion", type, item_name);
// TODO: Need a new message saying that only one JavaArtifact is allowed
if (artifacts.Count > 1) {
log.LogCodedError ("XA4243", Properties.Resources.XA4243, "JavaArtifact", type, task.ItemSpec);
artifact = null;
return false;
}

if (has_artifact && has_version) {
artifact = artifacts.FirstOrDefault ();

return artifact is not null;
}

public static bool TryParseJavaArtifacts (this ITaskItem task, string type, TaskLoggingHelper log, out List<Artifact> artifacts, out bool attributesSpecified)
{
artifacts = new List<Artifact> ();
var item_name = task.ItemSpec;

// Convert "../../src/blah/Blah.csproj" to "Blah.csproj"
if (type == "ProjectReference")
item_name = Path.GetFileName (item_name);

var has_artifact = task.HasMetadata ("JavaArtifact");

// Lets callers know if user attempted to specify JavaArtifact, even if they did it incorrectly
attributesSpecified = has_artifact;

if (has_artifact) {
var id = task.GetMetadata ("JavaArtifact");
var version = task.GetMetadata ("JavaVersion");

if (string.IsNullOrWhiteSpace (id)) {
log.LogCodedError ("XA4244", Properties.Resources.XA4244, "JavaArtifact", type, item_name);
return false;
}

if (string.IsNullOrWhiteSpace (version)) {
log.LogCodedError ("XA4244", Properties.Resources.XA4244, "JavaVersion", type, item_name);
return false;
}
if (TryParseArtifacts (id, log, out var parsed)) {
foreach (var art in parsed) {
log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from {3} '{4}' (JavaArtifact)", art.GroupId, art.Id, art.Version, type, item_name);
artifacts.Add (art);
}

if (TryParseArtifactWithVersion (id, version, log, out artifact)) {
log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from {3} '{4}' (JavaArtifact)", artifact.GroupId, artifact.Id, artifact.Version, type, item_name);
return true;
}
}
Expand Down

0 comments on commit c19adb8

Please sign in to comment.