diff --git a/.github/skills/update-androidsdk-packages/SKILL.md b/.github/skills/update-androidsdk-packages/SKILL.md
index 3083692cb17..07891797b99 100644
--- a/.github/skills/update-androidsdk-packages/SKILL.md
+++ b/.github/skills/update-androidsdk-packages/SKILL.md
@@ -60,7 +60,7 @@ do not update it unattended; report the ambiguity instead.
**5. Command-line tools are a coordinated product dependency.** Do not update only the bootstrap
pins. A command-line-tools bump must also update
`src/Xamarin.Installer.Build.Tasks/Xamarin.Installer.Common.props` and the matching latest entry in
-`src/Xamarin.Installer.AndroidSDK/Feeds/AndroidManifestFeed_d18.0.xml`, including every published
+`tools/workload-dependencies/AndroidManifestFeed_d18.0.xml`, including every published
host/architecture archive. Confirm `CodeGenerator.targets` tracks the property file that supplies
`AndroidCommandLineToolsVersion`. If the automated workflow is not authorized to change every
required file, stop and report the coordinated update instead of opening a partial PR.
diff --git a/.github/skills/update-androidsdk-packages/references/package-catalog.md b/.github/skills/update-androidsdk-packages/references/package-catalog.md
index c0c5d624ada..445d9b86514 100644
--- a/.github/skills/update-androidsdk-packages/references/package-catalog.md
+++ b/.github/skills/update-androidsdk-packages/references/package-catalog.md
@@ -9,7 +9,7 @@ drift as the skill is used.
|---|---|---|---|---|
| build-tools | `build-tools` | `XABuildToolsVersion`, `XABuildToolsFolder` | `XABuildToolsHashMacOS/Linux/Windows` | `build-tools_r$(XABuildToolsVersion)_{macosx,linux,windows}.zip` |
| platform-tools | `platform-tools` | `XAPlatformToolsVersion` | `XAPlatformToolsHashMacOS/Linux/Windows` | `platform-tools_r$(XAPlatformToolsVersion)-{darwin,linux,win}.zip` |
-| cmdline-tools | `cmdline-tools` | `CommandLineToolsFolder`, `CommandLineToolsVersion`; shipped `AndroidCommandLineToolsVersion` in `src/Xamarin.Installer.Build.Tasks/Xamarin.Installer.Common.props` | `XACmdlineToolsHashMacOS`, `XACmdlineToolsHashMacOSArm64`, `XACmdlineToolsHashLinux/Windows` | `commandlinetools-{mac_x86_64,mac_arm64,linux,win}-$(CommandLineToolsVersion).zip`; also update the latest entry in `src/Xamarin.Installer.AndroidSDK/Feeds/AndroidManifestFeed_d18.0.xml` |
+| cmdline-tools | `cmdline-tools` | `CommandLineToolsFolder`, `CommandLineToolsVersion`; shipped `AndroidCommandLineToolsVersion` in `src/Xamarin.Installer.Build.Tasks/Xamarin.Installer.Common.props` | `XACmdlineToolsHashMacOS`, `XACmdlineToolsHashMacOSArm64`, `XACmdlineToolsHashLinux/Windows` | `commandlinetools-{mac_x86_64,mac_arm64,linux,win}-$(CommandLineToolsVersion).zip`; also update the latest entry in `tools/workload-dependencies/AndroidManifestFeed_d18.0.xml` |
| cmake | `cmake;` | `AndroidCmakeVersion` | `XACmakeHashMacOS/Linux/Windows` | `cmake-$(AndroidCmakeVersion)-{darwin,linux,windows}.zip` |
| emulator | `emulator` | `EmulatorVersion`, `EmulatorPkgRevision` | `XAEmulatorHashMacOSx64`, `XAEmulatorHashMacOSArm64`, `XAEmulatorHashLinux/Windows` | `emulator-{darwin_x64,darwin_aarch64,linux_x64,windows_x64}-$(EmulatorVersion).zip`; also drives a synthesized `package.xml` via `package.xml.in` |
| API 29 system image | `sys-img/android` manifest, `path="system-images;android-29;default;{x86_64,arm64-v8a}"` | (fixed `x86_64-29_r08*`/`arm64-v8a-29_r08` filenames — check manifest for a newer `rNN` if refreshing) | `XASystemImageHashMacOSx64/MacOSArm64/Linux/Windows` | `{x86_64,arm64-v8a}-29_r08{-darwin,-linux,-windows,}.zip` under `sys-img/android/` |
diff --git a/Directory.Build.props b/Directory.Build.props
index b4f653c3796..ce0c678b014 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -67,8 +67,6 @@
<_AllowProjectWarnings Condition=" '$(MSBuildProjectFile)' == 'NativeAOT.csproj' ">true
<_AllowProjectWarnings Condition=" '$(MSBuildProjectFile)' == 'TestRunner.Core.NET.csproj' ">true
<_AllowProjectWarnings Condition=" '$(MSBuildProjectFile)' == 'Xamarin.Android.JcwGen-Tests.csproj' ">true
- <_AllowProjectWarnings Condition=" '$(MSBuildProjectFile)' == 'Xamarin.Installer.AndroidSDK.csproj' ">true
- <_AllowProjectWarnings Condition=" '$(MSBuildProjectFile)' == 'Xamarin.Installer.Common.csproj' ">true
true
diff --git a/Documentation/docs-mobile/TOC.yml b/Documentation/docs-mobile/TOC.yml
index 0a3c9377d2a..809177138e0 100644
--- a/Documentation/docs-mobile/TOC.yml
+++ b/Documentation/docs-mobile/TOC.yml
@@ -430,6 +430,12 @@
href: messages/xa5302.md
- name: XA5305
href: messages/xa5305.md
+ - name: XA5306
+ href: messages/xa5306.md
+ - name: XA5307
+ href: messages/xa5307.md
+ - name: XA5308
+ href: messages/xa5308.md
- name: "XA6xxx: Internal tools"
href: "messages/index.md#xa6xxx-internal-tools"
- name: "XAccc7xxx: Unhandled MSBuild exceptions"
diff --git a/Documentation/docs-mobile/building-apps/build-properties.md b/Documentation/docs-mobile/building-apps/build-properties.md
index 0a4a5a68cd5..cf9a47047dd 100644
--- a/Documentation/docs-mobile/building-apps/build-properties.md
+++ b/Documentation/docs-mobile/building-apps/build-properties.md
@@ -944,33 +944,15 @@ If you want detailed output from the tool you can add the following to the
## AndroidManifestType
-An enum-style property with valid values of `Xamarin` or `GoogleV2`.
-This controls which repository is used by the
-[`InstallAndroidDependencies`](build-targets.md#installandroiddependencies)
-target to determine which Android packages and package versions are
-available and can be installed.
-
-`Xamarin` is the **Approved List (Recommended)** repository within the
-[Visual Studio SDK Manager](/xamarin/android/get-started/installation/android-sdk?tabs=windows#repository-selection).
-
-`GoogleV2` is the **Full List (Unsupported)** repository within the
-[Visual Studio SDK Manager](/xamarin/android/get-started/installation/android-sdk?tabs=windows#repository-selection).
-
-If `$(AndroidManifestType)` is not set, then `Xamarin` is used.
+This property was removed in .NET 12 and has no effect.
+The [`InstallAndroidDependencies`](build-targets.md#installandroiddependencies)
+target now uses the Android CLI to install Android SDK packages.
## AndroidManifestSource
-A string property that specifies an absolute URI or an existing local file path
-for the repository manifest used by the
-[`InstallAndroidDependencies`](build-targets.md#installandroiddependencies)
-target. When this property is not set, the default repository manifest selected
-by `$(AndroidManifestType)` is used.
-
-For example:
-
-```xml
-https://example.com/AndroidManifestFeed.xml
-```
+This property was removed in .NET 12 and has no effect.
+The [`InstallAndroidDependencies`](build-targets.md#installandroiddependencies)
+target now uses the Android CLI to install Android SDK packages.
## AndroidManifestPlaceholders
diff --git a/Documentation/docs-mobile/building-apps/build-targets.md b/Documentation/docs-mobile/building-apps/build-targets.md
index 65dfdd5f59c..73fb4016e54 100644
--- a/Documentation/docs-mobile/building-apps/build-targets.md
+++ b/Documentation/docs-mobile/building-apps/build-targets.md
@@ -157,6 +157,19 @@ MSBuild /t:Install ProjectName.csproj /p:AdbTarget=-e
Calls the [`GetAndroidDependencies`](#getandroiddependencies) target, then installs
the Android SDK packages specified in the `@(AndroidDependency)` item group.
+The Android SDK packages are installed with Google's
+[Android CLI](https://developer.android.com/tools/agents/android-cli)
+(`android sdk install`). The target downloads a pinned version of the Android CLI
+from Google into a per-user cache. Before it runs the Android CLI, the target
+makes sure that the SHA-256 hash of the file is the same as the hash included with
+the .NET for Android SDK. The Android CLI is available for Windows x64, macOS (x64
+and Arm64), and Linux (x64 and Arm64).
+
+The Android CLI accepts the Android SDK licenses without a prompt. Thus, if Android SDK
+packages must be installed, this target fails unless you set `$(AcceptAndroidSDKLicenses)`
+to `true`. Before you set this
+property, read the [Android SDK License Agreement](https://developer.android.com/studio/terms).
+
Before it extracts a downloaded Microsoft OpenJDK archive, this target verifies
the archive's detached digital signature. The signing key must match the trusted
key hash included with the .NET for Android SDK. Missing or invalid signatures
@@ -173,13 +186,16 @@ you will get the following error:
error MSB4057: The target "InstallAndroidDependencies" does not exist in the project.
```
-The `AndroidSdkDirectory` and `JavaSdkDirectory` properties are required as we need to know where to install the required components. These directories can be empty or existing. Sdk components
-will be installed on top on an existing sdk installation.
+The `AndroidSdkDirectory` and `JavaSdkDirectory` properties set where the components are installed.
+These directories can be empty or existing. Sdk components will be installed on top of an existing sdk installation.
+If a property is not set, the build looks for an existing installation, the same as a normal build.
+If it finds no installation, `AndroidSdkDirectory` uses the `ANDROID_HOME` or `ANDROID_SDK_ROOT` environment variable.
+If those are also not set, the default is `%LOCALAPPDATA%\Android\Sdk` on Windows, `~/Library/Android/sdk` on macOS,
+and `~/Android/Sdk` on Linux.
+`JavaSdkDirectory` uses the `JAVA_HOME` or `JDK_HOME` environment variable.
+If those are also not set, the default is `%LOCALAPPDATA%\Android\jdk-` on Windows and
+`~/Library/Android/microsoft-.jdk` on macOS. On Linux, you must set `JavaSdkDirectory` or `JAVA_HOME`.
-The [`$(AndroidManifestType)`](build-properties.md#androidmanifesttype)
-MSBuild property controls which
-[Visual Studio SDK Manager repository](/xamarin/android/get-started/installation/android-sdk?tabs=windows#repository-selection)
-is used for package name and package version detection, and URLs to download.
## Publish
diff --git a/Documentation/docs-mobile/messages/index.md b/Documentation/docs-mobile/messages/index.md
index 638566e1a6c..d8b547c2b79 100644
--- a/Documentation/docs-mobile/messages/index.md
+++ b/Documentation/docs-mobile/messages/index.md
@@ -282,6 +282,9 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla
+ [XA5303](xa5303.md): Failed to parse 'DescriptorIndex' metadata value '{value}' for assembly '{assembly}'.
+ [XA5304](xa5304.md): Invalid AssemblyStore compression level '{level}'. The value must be between {min} and {max}.
+ [XA5305](xa5305.md): Could not verify the Microsoft OpenJDK archive signature.
++ [XA5306](xa5306.md): The Android CLI is not available for this operating system and architecture.
++ [XA5307](xa5307.md): The SHA-256 hash of the downloaded Android CLI is not correct.
++ [XA5308](xa5308.md): The Android CLI failed while it installed Android SDK packages.
## XA6xxx: Internal tools
diff --git a/Documentation/docs-mobile/messages/xa5306.md b/Documentation/docs-mobile/messages/xa5306.md
new file mode 100644
index 00000000000..73ceebcd148
--- /dev/null
+++ b/Documentation/docs-mobile/messages/xa5306.md
@@ -0,0 +1,30 @@
+---
+title: .NET for Android error XA5306
+description: XA5306 error code
+ms.date: 11/12/2026
+f1_keywords:
+ - "XA5306"
+---
+
+# .NET for Android error XA5306
+
+## Example messages
+
+```text
+error XA5306: The Android CLI is not available for this operating system and architecture: `{os}` `{architecture}`.
+```
+
+## Issue
+
+`InstallAndroidDependencies` installs Android SDK packages with Google's
+[Android CLI](https://developer.android.com/tools/agents/android-cli). Google
+does not publish the Android CLI for the current operating system and processor
+architecture. The Android CLI is available for Windows x64, macOS (x64 and
+Arm64), and Linux (x64 and Arm64).
+
+## Solution
+
+Run `InstallAndroidDependencies` on a supported operating system and
+architecture. Alternatively, install the Android SDK packages with Android
+Studio or the Android SDK command-line tools, and set `$(AndroidSdkDirectory)`
+to that Android SDK.
diff --git a/Documentation/docs-mobile/messages/xa5307.md b/Documentation/docs-mobile/messages/xa5307.md
new file mode 100644
index 00000000000..d8040fac891
--- /dev/null
+++ b/Documentation/docs-mobile/messages/xa5307.md
@@ -0,0 +1,30 @@
+---
+title: .NET for Android error XA5307
+description: XA5307 error code
+ms.date: 11/12/2026
+f1_keywords:
+ - "XA5307"
+---
+
+# .NET for Android error XA5307
+
+## Example messages
+
+```text
+error XA5307: The Android CLI downloaded from `{url}` has SHA-256 `{actual}`, but SHA-256 `{expected}` was expected. The Android CLI will not be used.
+```
+
+## Issue
+
+`InstallAndroidDependencies` downloads a pinned version of Google's
+[Android CLI](https://developer.android.com/tools/agents/android-cli). Before it
+runs the Android CLI, it makes sure that the SHA-256 hash of the downloaded file
+is the same as the hash included with the .NET for Android SDK. The hashes are
+different, so the Android CLI is not used. A proxy that changes downloads, an
+incomplete download, or a changed file on the server can cause this error.
+
+## Solution
+
+Check network access to the download URL, and try again. Use an up-to-date
+.NET for Android SDK. If the error continues, report it with the URL and both
+hashes. Do not use an Android CLI whose hash is not correct.
diff --git a/Documentation/docs-mobile/messages/xa5308.md b/Documentation/docs-mobile/messages/xa5308.md
new file mode 100644
index 00000000000..502f0dd61a0
--- /dev/null
+++ b/Documentation/docs-mobile/messages/xa5308.md
@@ -0,0 +1,29 @@
+---
+title: .NET for Android error XA5308
+description: XA5308 error code
+ms.date: 11/12/2026
+f1_keywords:
+ - "XA5308"
+---
+
+# .NET for Android error XA5308
+
+## Example messages
+
+```text
+error XA5308: The Android CLI failed with exit code {code} while it installed Android SDK packages. Output:
+{output}
+```
+
+## Issue
+
+`InstallAndroidDependencies` runs `android sdk install` from Google's
+[Android CLI](https://developer.android.com/tools/agents/android-cli) to install
+Android SDK packages. The Android CLI stopped with an error. The error message
+includes the last part of the Android CLI output.
+
+## Solution
+
+Read the Android CLI output in the error message. Make sure that you can write
+to `$(AndroidSdkDirectory)`, that you have network access, and that the disk has
+sufficient free space. Then try again.
diff --git a/Documentation/guides/InstallBuildsFromMain.md b/Documentation/guides/InstallBuildsFromMain.md
index 05585c78550..d1753db7607 100644
--- a/Documentation/guides/InstallBuildsFromMain.md
+++ b/Documentation/guides/InstallBuildsFromMain.md
@@ -49,7 +49,7 @@ On Windows, if your Android SDK is located in `C:\Program Files
administrator to run:
```dotnetcli
-> dotnet build -t:InstallAndroidDependencies -p:AndroidManifestType=GoogleV2 -p:AcceptAndroidSDKLicenses=true
+> dotnet build -t:InstallAndroidDependencies -p:AcceptAndroidSDKLicenses=true
```
*On macOS, you might not even need `sudo` for this command.*
diff --git a/Microsoft.Android.slnx b/Microsoft.Android.slnx
index 7764be2f0a6..e1a23adbce9 100644
--- a/Microsoft.Android.slnx
+++ b/Microsoft.Android.slnx
@@ -44,9 +44,7 @@
-
-
diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets
index 2f3c4fa0890..8c62ac6e89a 100644
--- a/build-tools/installers/create-installers.targets
+++ b/build-tools/installers/create-installers.targets
@@ -136,19 +136,13 @@
- <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)ICSharpCode.SharpZipLib.dll" />
- <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)ICSharpCode.SharpZipLib.pdb" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Build.Debugging.Tasks.dll" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Build.Debugging.Tasks.pdb" />
<_MSBuildFiles Include="@(_LocalizationLanguages->'$(MicrosoftAndroidSdkOutDir)%(Identity)\Xamarin.Android.Build.Debugging.Tasks.resources.dll')" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Common.Debugging.props" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Common.Debugging.targets" />
- <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.AndroidSDK.dll" />
- <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.AndroidSDK.pdb" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.Build.Tasks.dll" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.Build.Tasks.pdb" />
- <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.Common.dll" />
- <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.Common.pdb" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.Common.props" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Installer.Common.targets" />
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index 7dc2ff30d89..f9411fa933d 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -2,7 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Security.Cryptography;
+using System.Net;
+using System.Net.Http;
using System.Text;
using System.Threading;
using System.Xml.Linq;
@@ -10,13 +11,10 @@
using Microsoft.Android.Build.Tasks;
using Xamarin.Android.Tasks;
using Xamarin.Android.Tools;
-using Xamarin.Installer.AndroidSDK;
-using Xamarin.Installer.AndroidSDK.Common;
-using Xamarin.Installer.AndroidSDK.Manager;
-using Xamarin.Installer.Common;
using Xamarin.ProjectTools;
using Microsoft.Build.Framework;
-using System.IO.Compression;
+using Microsoft.Build.Utilities;
+using Xamarin.Installer.Build.Tasks;
namespace Xamarin.Android.Build.Tests
{
@@ -26,30 +24,16 @@ public class AndroidDependenciesTests : BaseTest
{
[Test]
[NonParallelizable] // Do not run environment modifying tests in parallel.
- public void InstallAndroidDependenciesTest ([Values ("GoogleV2", "Xamarin")] string manifestType, [Values (AndroidRuntime.CoreCLR, AndroidRuntime.NativeAOT)] AndroidRuntime runtime)
+ public void InstallAndroidDependenciesTest ([Values (AndroidRuntime.CoreCLR, AndroidRuntime.NativeAOT)] AndroidRuntime runtime)
{
bool isRelease = runtime == AndroidRuntime.NativeAOT;
if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) {
return;
}
- // The GoogleV2 manifest from Google doesn't have an ndk-bundle component,
- // so the NDK dependency can't be resolved for runtimes that require it.
- if (manifestType == "GoogleV2" && runtime == AndroidRuntime.NativeAOT) {
- Assert.Ignore ("GoogleV2 manifest does not have an ndk-bundle component for NativeAOT");
- }
- if (manifestType == "GoogleV2") {
- InstallGoogleV2Dependencies ();
- return;
- }
-
- // Set to true when we are marking a new Android API level as stable, but it has not
- // been added to the Xamarin manifest yet.
- var xamarin_manifest_needs_updating = false;
-
var oldSdkPath = Environment.GetEnvironmentVariable ("TEST_ANDROID_SDK_PATH");
var oldJdkPath = Environment.GetEnvironmentVariable ("TEST_ANDROID_JDK_PATH");
- var outdatedCommandLineToolsRevision = new Version (19, 0);
+
try {
string sdkPath = Path.Combine (Root, "temp", TestName, "android-sdk");
string jdkPath = Path.Combine (Root, "temp", TestName, "android-jdk");
@@ -62,13 +46,10 @@ public void InstallAndroidDependenciesTest ([Values ("GoogleV2", "Xamarin")] str
proj.SetRuntime (runtime);
var buildArgs = new List {
"AcceptAndroidSDKLicenses=true",
- $"AndroidManifestType={manifestType}",
+
// This integration test downloads the SDK, JDK and (for NativeAOT) NDK from scratch.
"AndroidDependencyInstallationTimeout=30",
};
- var manifestPath = Path.Combine (XABuildPaths.TopDirectory, "src", "Xamarin.Installer.AndroidSDK", "Feeds", "AndroidManifestFeed_d18.0.xml");
- Assert.IsTrue (File.Exists (manifestPath), $"Xamarin manifest does not exist at '{manifestPath}'.");
- buildArgs.Add ($"AndroidManifestSource={manifestPath}");
using (var b = CreateApkBuilder ()) {
b.Verbosity = LoggerVerbosity.Detailed;
@@ -103,9 +84,6 @@ public void InstallAndroidDependenciesTest ([Values ("GoogleV2", "Xamarin")] str
Directory.CreateDirectory (path);
}
- var commandLineToolsPath = Path.Combine (sdkPath, "cmdline-tools", "latest");
- Directory.CreateDirectory (commandLineToolsPath);
- File.WriteAllText (Path.Combine (commandLineToolsPath, "source.properties"), $"Pkg.Revision={outdatedCommandLineToolsRevision}");
if (b.Build (proj, parameters: buildArgs.ToArray ())) {
installSucceeded = true;
@@ -118,30 +96,12 @@ public void InstallAndroidDependenciesTest ([Values ("GoogleV2", "Xamarin")] str
}
Assert.IsTrue (installSucceeded, $"InstallAndroidDependencies should have succeeded within {maxInstallAttempts} attempts.");
- var sourceProperties = Path.Combine (sdkPath, "cmdline-tools", "latest", "source.properties");
- var revisionProperty = File.ReadLines (sourceProperties)
- .First (line => line.StartsWith ("Pkg.Revision", StringComparison.Ordinal));
- int separator = revisionProperty.IndexOf ('=');
- Assert.GreaterOrEqual (separator, 0, "The command-line tools revision property should contain a value.");
- var installedRevision = Version.Parse (revisionProperty.Substring (separator + 1).Trim ());
- Assert.Greater (installedRevision.CompareTo (outdatedCommandLineToolsRevision), 0, "The outdated command-line tools installation should have been updated.");
-
- // When dependencies can not be resolved/installed a warning will be present in build output:
- // Dependency `platform-tools` should have been installed but could not be resolved.
- var depFailedMessage = "should have been installed but could not be resolved";
- bool failedToInstall = b.LastBuildOutput.ContainsText (depFailedMessage);
-
- // If we don't think the Xamarin manifest has been updated to contain the new API level:
- // - Don't error if we got the expected failure
- // - Error if didn't get a failure, because we need to update this test
- if (manifestType == "Xamarin" && xamarin_manifest_needs_updating) {
- if (!failedToInstall)
- Assert.Fail ("We didn't expect the Xamarin manifest to have the requested component. If the manifest has been updated, change 'InstallAndroidDependenciesTest.xamarin_manifest_needs_updating' to be 'false'. ");
+ FileAssert.Exists (Path.Combine (sdkPath, "cmdline-tools", "21.0", "source.properties"));
- return;
- }
-
- if (failedToInstall) {
+ // When a package is not installed, a warning is present in the build output:
+ // The Android CLI did not install Android SDK package `platform-tools` into `...`.
+ var depFailedMessage = "The Android CLI did not install Android SDK package";
+ if (b.LastBuildOutput.ContainsText (depFailedMessage)) {
var sb = new StringBuilder ();
foreach (var line in b.LastBuildOutput) {
if (line.Contains (depFailedMessage)) {
@@ -167,321 +127,6 @@ public void InstallAndroidDependenciesTest ([Values ("GoogleV2", "Xamarin")] str
}
}
- void InstallGoogleV2Dependencies ()
- {
- string sdkPath = Path.Combine (Root, "temp", TestName, "android-sdk");
- if (Directory.Exists (sdkPath))
- Directory.Delete (sdkPath, recursive: true);
- Directory.CreateDirectory (sdkPath);
-
- var fixture = new GoogleV2Fixture ();
- string platformToolsVersion = GetCurrentPlatformToolsVersion (fixture.RepositoryManifest);
- var installer = new AndroidSDKInstaller (
- fixture.Helpers,
- AndroidManifestType.GoogleV2,
- fixture.ManifestUrl,
- fixture.AddonsListUrl,
- fixture.RepositoryBaseUrl);
- installer.Discover (new List { sdkPath });
-
- var sdk = installer.FindInstance (sdkPath);
- Assert.IsNotNull (sdk, $"The synthetic Android SDK should be discovered at '{sdkPath}'.");
-
- var requested = new [] {
- (path: $"platforms;android-{GoogleV2Fixture.PlatformVersion}", version: (string) null),
- (path: $"build-tools;{GoogleV2Fixture.BuildToolsVersion}", version: GoogleV2Fixture.BuildToolsVersion),
- (path: "platform-tools", version: platformToolsVersion),
- (path: $"cmdline-tools;{GoogleV2Fixture.CommandLineToolsVersion}", version: GoogleV2Fixture.CommandLineToolsVersion),
- };
- var components = new List ();
- foreach (var dependency in requested) {
- var version = dependency.version == null ? null : new AndroidRevision (dependency.version);
- var component = sdk.Components.FirstOrDefault (c => c.Path == dependency.path && (version == null || c.Revision == version));
- Assert.IsNotNull (component, $"The synthetic repository should contain '{dependency.path}/{dependency.version}'.");
- components.Add (component);
- }
-
- var installationSet = installer.GetInstallationSet (sdk, components);
- CollectionAssert.AreEquivalent (
- requested.Select (dependency => dependency.path).Append (GoogleV2Fixture.FixtureDependencyPath),
- installationSet.Select (component => component.Path),
- "The installation set should contain direct and transitive GoogleV2 dependencies.");
-
- var downloads = installer.GetDownloadItems (installationSet);
- fixture.PrepareDownloads (downloads, Path.Combine (Root, "temp", TestName, "downloads"));
- foreach (var download in downloads)
- Assert.IsTrue (download.IsDownloadValid (), $"Checksum validation should succeed for '{download.Url}'.");
-
- var licenses = installationSet
- .Select (component => component.License)
- .Where (license => license != null)
- .Distinct ()
- .ToList ();
- Assert.AreEqual (1, licenses.Count, "The synthetic GoogleV2 license should be parsed.");
- Assert.AreEqual ("android-sdk-license", licenses [0].ID);
- installer.Install (sdk, installationSet);
-
- string javaSdkPath = AndroidSdkResolver.GetJavaSdkPath ();
- Assert.IsTrue (Directory.Exists (javaSdkPath), $"The configured local JDK should exist at '{javaSdkPath}'.");
- installer.AcceptLicensesAsync (sdk, licenses, CancellationToken.None, javaSdkPath, throwsErrorIfValidationFailed: true)
- .GetAwaiter ().GetResult ();
- Assert.IsTrue (File.Exists (Path.Combine (sdkPath, "cmdline-tools", GoogleV2Fixture.CommandLineToolsVersion, "bin", "sdkmanager-invoked.txt")),
- "The synthetic sdkmanager should be invoked to accept licenses.");
- Assert.IsTrue (installer.IsLicenseAccepted (sdk, licenses [0]), "The synthetic GoogleV2 license should be accepted.");
- fixture.AssertInstallation (sdkPath);
- }
-
- static string GetCurrentPlatformToolsVersion (XDocument manifest)
- {
- var platformToolsPackage = manifest.Root.Elements ("remotePackage")
- .Where (e => "platform-tools" == (string) e.Attribute("path") &&
- "android-sdk-preview-license" != (string) e.Element ("uses-license")?.Attribute ("ref"))
- .FirstOrDefault ();
- Assert.IsNotNull (platformToolsPackage, "The GoogleV2 manifest should contain a stable platform-tools package.");
-
- var revision = platformToolsPackage.Element ("revision");
- Assert.IsNotNull (revision, "The stable platform-tools package should contain a revision.");
-
- return $"{revision.Element ("major")?.Value}.{revision.Element ("minor")?.Value}.{revision.Element ("micro")?.Value}";
- }
-
- sealed class GoogleV2Fixture
- {
- public const string PlatformToolsVersion = "99.0.1";
- public const string BuildToolsVersion = "37.0.0";
- public const string CommandLineToolsVersion = "22.0";
- public const string PlatformVersion = "37.0";
- public const string FixtureDependencyPath = "extras;googlev2-fixture";
-
- readonly Dictionary archives = new Dictionary ();
- readonly List requests = new List ();
- readonly List expectedRequests = new List {
- "/repository2-3.xml",
- "/addons_list-5.xml",
- "/addon.xml",
- "/platform-tools.zip",
- "/build-tools.zip",
- "/command-line-tools.zip",
- "/platform.zip",
- "/fixture-dependency.zip",
- };
-
- public FixtureHelpers Helpers { get; }
- public Uri RepositoryBaseUrl { get; } = new Uri ("https://googlev2-fixture.test/");
- public Uri ManifestUrl => new Uri (RepositoryBaseUrl, "repository2-3.xml");
- public Uri AddonsListUrl => new Uri (RepositoryBaseUrl, "addons_list-5.xml");
- public XDocument RepositoryManifest { get; }
-
- public GoogleV2Fixture ()
- {
- Helpers = new FixtureHelpers (requests);
- var platformToolsArchive = CreateArchive (
- ("platform-tools/source.properties", $"Pkg.Revision={PlatformToolsVersion}"),
- ("platform-tools/fixture-marker.txt", "synthetic platform-tools"));
- var buildToolsArchive = CreateArchive (
- ($"android-{BuildToolsVersion}/source.properties", $"Pkg.Revision={BuildToolsVersion}"),
- ($"android-{BuildToolsVersion}/fixture-marker.txt", "synthetic build-tools"));
- var platformArchive = CreateArchive (
- ($"android-{PlatformVersion}/source.properties", "Pkg.Revision=1"),
- ($"android-{PlatformVersion}/android.jar", "synthetic android.jar"));
- var fixtureDependencyArchive = CreateArchive (
- ("googlev2-fixture/source.properties", "Pkg.Revision=1"),
- ("googlev2-fixture/nested/fixture-marker.txt", "synthetic transitive dependency"));
- var sdkManagerName = TestEnvironment.IsWindows ? "sdkmanager.bat" : "sdkmanager";
- var sdkManagerContents = TestEnvironment.IsWindows
- ? "@echo off\r\necho invoked>sdkmanager-invoked.txt\r\necho Accepted\r\nexit /b 0\r\n"
- : "#!/bin/sh\necho invoked > sdkmanager-invoked.txt\necho Accepted\nexit 0\n";
- var commandLineToolsArchive = CreateCommandLineToolsArchive (
- ("cmdline-tools/source.properties", $"Pkg.Revision={CommandLineToolsVersion}"),
- ($"cmdline-tools/bin/{sdkManagerName}", sdkManagerContents));
-
- AddArchive ("platform-tools.zip", platformToolsArchive);
- AddArchive ("build-tools.zip", buildToolsArchive);
- AddArchive ("platform.zip", platformArchive);
- AddArchive ("fixture-dependency.zip", fixtureDependencyArchive);
- AddArchive ("command-line-tools.zip", commandLineToolsArchive);
- RepositoryManifest = CreateRepositoryManifest (
- platformToolsArchive,
- buildToolsArchive,
- platformArchive,
- fixtureDependencyArchive,
- commandLineToolsArchive);
- Helpers.AddResponse (ManifestUrl, RepositoryManifest.ToString (SaveOptions.DisableFormatting));
- Helpers.AddResponse (AddonsListUrl, CreateAddonsListManifest ());
- Helpers.AddResponse (new Uri (RepositoryBaseUrl, "addon.xml"), "");
- }
-
- public void PrepareDownloads (IEnumerable downloads, string directory)
- {
- if (Directory.Exists (directory))
- Directory.Delete (directory, recursive: true);
- Directory.CreateDirectory (directory);
-
- foreach (var download in downloads) {
- requests.Add (download.Url.AbsolutePath);
- Assert.IsTrue (archives.TryGetValue (download.Url, out byte [] contents),
- $"Unexpected GoogleV2 fixture archive '{download.Url}'.");
- string path = Path.Combine (directory, Path.GetFileName (download.Url.LocalPath));
- File.WriteAllBytes (path, contents);
- download.DownloadedFilePath = path;
- }
- }
-
- public void AssertInstallation (string sdkPath)
- {
- AssertFixtureFile (sdkPath, "platform-tools", "fixture-marker.txt");
- AssertFixtureFile (sdkPath, "build-tools", BuildToolsVersion, "fixture-marker.txt");
- AssertFixtureFile (sdkPath, "cmdline-tools", CommandLineToolsVersion, "source.properties");
- AssertFixtureFile (sdkPath, "platforms", $"android-{PlatformVersion}", "android.jar");
- AssertFixtureFile (sdkPath, "extras", "googlev2-fixture", "nested", "fixture-marker.txt");
-
- CollectionAssert.AreEquivalent (expectedRequests, requests,
- "GoogleV2 should only access the expected in-memory fixture resources.");
- }
-
- void AddArchive (string name, byte [] contents)
- {
- archives.Add (new Uri (RepositoryBaseUrl, name), contents);
- }
-
- static void AssertFixtureFile (string sdkPath, params string [] parts)
- {
- var path = parts.Aggregate (sdkPath, Path.Combine);
- Assert.IsTrue (File.Exists (path), $"Expected synthetic GoogleV2 fixture file '{path}' to be installed.");
- Assert.IsTrue (File.Exists (Path.Combine (Path.GetDirectoryName (path), "package.xml")) ||
- File.Exists (Path.Combine (Path.GetDirectoryName (Path.GetDirectoryName (path)), "package.xml")),
- $"Expected a package.xml next to the installed GoogleV2 fixture '{path}'.");
- }
-
- XDocument CreateRepositoryManifest (
- byte [] platformToolsArchive,
- byte [] buildToolsArchive,
- byte [] platformArchive,
- byte [] fixtureDependencyArchive,
- byte [] commandLineToolsArchive)
- {
- XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
- return new XDocument (
- new XElement ("repository",
- new XAttribute (XNamespace.Xmlns + "xsi", xsi),
- new XElement ("license", new XAttribute ("id", "android-sdk-license"), "Synthetic test license"),
- new XElement ("channel", new XAttribute ("id", "channel-0"), "stable"),
- CreatePackage ("platform-tools", PlatformToolsVersion, "platform-tools.zip", platformToolsArchive),
- CreatePackage ($"build-tools;{BuildToolsVersion}", BuildToolsVersion, "build-tools.zip", buildToolsArchive),
- CreatePackage ($"cmdline-tools;{CommandLineToolsVersion}", CommandLineToolsVersion, "command-line-tools.zip", commandLineToolsArchive),
- CreatePackage (
- $"platforms;android-{PlatformVersion}",
- "1.0.0",
- "platform.zip",
- platformArchive,
- new XElement ("dependencies",
- new XElement ("dependency",
- new XAttribute ("path", FixtureDependencyPath)))),
- CreatePackage (FixtureDependencyPath, "1.0.0", "fixture-dependency.zip", fixtureDependencyArchive)
- )
- );
- }
-
- XElement CreatePackage (string path, string version, string archiveName, byte [] archive, XElement dependencies = null)
- {
- XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
- return new XElement ("remotePackage",
- new XAttribute ("path", path),
- new XElement ("type-details", new XAttribute (xsi + "type", "genericDetailsType")),
- CreateRevision (version),
- new XElement ("display-name", $"Synthetic {path}"),
- new XElement ("uses-license", new XAttribute ("ref", "android-sdk-license")),
- new XElement ("channelRef", new XAttribute ("ref", "channel-0")),
- dependencies,
- new XElement ("archives",
- new XElement ("archive",
- new XElement ("complete",
- new XElement ("size", archive.Length),
- new XElement ("checksum", new XAttribute ("type", "sha256"), Files.ToHexString (SHA256.HashData (archive)).ToLowerInvariant ()),
- new XElement ("url", new Uri (RepositoryBaseUrl, archiveName))))));
- }
-
- static XElement CreateRevision (string version)
- {
- var fields = version.Split ('.').Select (int.Parse).ToArray ();
- return new XElement ("revision",
- new XElement ("major", fields [0]),
- fields.Length > 1 ? new XElement ("minor", fields [1]) : null,
- fields.Length > 2 ? new XElement ("micro", fields [2]) : null);
- }
-
- string CreateAddonsListManifest ()
- {
- XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
- return new XDocument (
- new XElement ("sdk-addons-list",
- new XAttribute (XNamespace.Xmlns + "xsi", xsi),
- new XAttribute (XNamespace.Xmlns + "sdk", "http://schemas.android.com/sdk/android/repo/addons-list/3"),
- new XElement ("site",
- new XAttribute (xsi + "type", "sdk:addonSiteType"),
- new XElement ("displayName", "Synthetic add-on repository"),
- new XElement ("url", new Uri (RepositoryBaseUrl, "addon.xml"))))
- ).ToString (SaveOptions.DisableFormatting);
- }
-
- static byte [] CreateArchive (params (string path, string contents) [] entries)
- {
- using (var stream = new MemoryStream ()) {
- using (var archive = new ZipArchive (stream, ZipArchiveMode.Create, leaveOpen: true)) {
- foreach (var entry in entries) {
- using var writer = new StreamWriter (archive.CreateEntry (entry.path).Open (), new UTF8Encoding (false));
- writer.Write (entry.contents);
- }
- }
- return stream.ToArray ();
- }
- }
-
- static byte [] CreateCommandLineToolsArchive (
- (string path, string contents) sourceProperties,
- (string path, string contents) sdkManager)
- {
- using (var stream = new MemoryStream ()) {
- using (var archive = new ZipArchive (stream, ZipArchiveMode.Create, leaveOpen: true)) {
- using (var writer = new StreamWriter (archive.CreateEntry (sourceProperties.path).Open (), new UTF8Encoding (false)))
- writer.Write (sourceProperties.contents);
- var entry = archive.CreateEntry (sdkManager.path);
- entry.ExternalAttributes = ((int)(UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
- UnixFileMode.GroupRead | UnixFileMode.GroupExecute |
- UnixFileMode.OtherRead | UnixFileMode.OtherExecute) | 0x8000) << 16;
- using var scriptWriter = new StreamWriter (entry.Open (), new UTF8Encoding (false));
- scriptWriter.Write (sdkManager.contents);
- }
- return stream.ToArray ();
- }
- }
-
- }
-
- sealed class FixtureHelpers : Helper, IHelpers
- {
- readonly Dictionary responses = new Dictionary ();
- readonly List requests;
-
- public FixtureHelpers (List requests)
- {
- this.requests = requests;
- }
-
- public void AddResponse (Uri uri, string contents)
- {
- responses.Add (uri, contents);
- }
-
- bool IHelpers.DownloadToString (Uri url, out string output)
- {
- requests.Add (url.AbsolutePath);
- if (!responses.TryGetValue (url, out output))
- throw new InvalidOperationException ($"Unexpected GoogleV2 fixture manifest '{url}'.");
- return true;
- }
- }
-
[TestCase (AndroidRuntime.CoreCLR, false, false, false)]
[TestCase (AndroidRuntime.CoreCLR, false, true, true)]
[TestCase (AndroidRuntime.NativeAOT, true, false, true)]
@@ -604,6 +249,65 @@ public void GetDependencyWhenSDKIsMissingTest ([Values] bool createSdkDirectory,
}
}
+ [Test]
+ public void InstallAndroidDependenciesPassesPackagesToAndroidCli ()
+ {
+ var root = Path.Combine (Root, "temp", TestName);
+ if (Directory.Exists (root))
+ Directory.Delete (root, recursive: true);
+ Directory.CreateDirectory (root);
+
+ // A fake Android CLI that writes its arguments to args.txt.
+ string cli;
+ if (OperatingSystem.IsWindows ()) {
+ cli = Path.Combine (root, "android.cmd");
+ File.WriteAllText (cli, "@echo %* > \"%~dp0args.txt\"\r\n");
+ } else {
+ cli = Path.Combine (root, "android");
+ File.WriteAllText (cli, "#!/bin/sh\necho \"$@\" > \"$(dirname \"$0\")/args.txt\"\n");
+ File.SetUnixFileMode (cli, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
+ }
+
+ var errors = new List ();
+ var task = new InstallAndroidDependencies {
+ BuildEngine = new MockBuildEngine (TestContext.Out, errors, [], []),
+ AndroidSdkPath = Path.Combine (root, "sdk"),
+ AcceptAndroidSDKLicenses = true,
+ InstallJavaDependencies = false,
+ AndroidCliPath = cli,
+ JavaDependencies = [],
+ Dependencies = [
+ new TaskItem ("build-tools/37.0.0", new Dictionary { { "Version", "37.0.0" } }),
+ new TaskItem ("platform-tools", new Dictionary { { "Version", "37.0.1" } }),
+ new TaskItem ("ndk-bundle", new Dictionary { { "Version", "27.2.12479018" } }),
+ new TaskItem ("platforms/android-37.0"),
+ ],
+ };
+ Assert.IsTrue (task.Execute (), string.Join (Environment.NewLine, errors.Select (e => e.Message)));
+
+ var args = File.ReadAllText (Path.Combine (root, "args.txt")).Trim ();
+ StringAssert.Contains ($"--no-metrics --sdk={Path.Combine (root, "sdk")} sdk install", args);
+ StringAssert.EndsWith ("build-tools/37.0.0 platform-tools@37.0.1 ndk/27.2.12479018 platforms/android-37.0", args);
+ }
+
+ [Test]
+ public async System.Threading.Tasks.Task UnknownJdkVersionIsNotValid ()
+ {
+ // aka.ms sends an unknown link to an HTML page on bing.com with status 200.
+ using (var client = new HttpClient (new HtmlHandler ())) {
+ var archive = await new JavaDependencyInstaller ().GetFirstValidJdkArchiveWithVersion (client, "21.0.99", CancellationToken.None);
+ Assert.IsNull (archive);
+ }
+ }
+
+ sealed class HtmlHandler : HttpMessageHandler
+ {
+ protected override System.Threading.Tasks.Task SendAsync (HttpRequestMessage request, CancellationToken cancellationToken) =>
+ System.Threading.Tasks.Task.FromResult (new HttpResponseMessage (HttpStatusCode.OK) {
+ Content = new StringContent ("", Encoding.UTF8, "text/html"),
+ });
+ }
+
static readonly XNamespace MSBuildXmlns = "http://schemas.microsoft.com/developer/msbuild/2003";
static string GetExpectedBuildToolsVersion ()
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/OpenJdkSignatureTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/OpenJdkSignatureTests.cs
index c7c52f40d39..21d67b8c1b4 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/OpenJdkSignatureTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/OpenJdkSignatureTests.cs
@@ -12,7 +12,6 @@
using System.Xml.Linq;
using Microsoft.Build.Framework;
using NUnit.Framework;
-using Xamarin.Installer.AndroidSDK.Common;
using Xamarin.Installer.Build.Tasks;
using Xamarin.ProjectTools;
@@ -200,7 +199,7 @@ public void CancelledVerification (bool skip)
Assert.Throws (() => Verify (archiveBytes, Sign (), cancellationToken: new CancellationToken (true)));
using (var client = new HttpClient (new SignatureHandler ([], []))) {
var task = new InstallAndroidDependencies { SkipSignCheck = skip };
- Assert.ThrowsAsync (async () => await task.VerifyJavaArchiveAsync (client, new Archive ("windows"), new CancellationToken (true)));
+ Assert.ThrowsAsync (async () => await task.VerifyJavaArchiveAsync (client, new Archive (), new CancellationToken (true)));
}
}
@@ -223,7 +222,7 @@ public void HttpTimeoutReportsVerificationError (bool keyRequest)
var task = new VerificationTask {
BuildEngine = engine,
Client = client,
- Archive = new Archive ("windows") { Url = new Uri ("https://example.test/jdk.zip") },
+ Archive = new Archive () { Url = new Uri ("https://example.test/jdk.zip") },
};
Assert.IsFalse (task.Execute ());
Assert.IsTrue (handler.Blocked);
@@ -243,7 +242,7 @@ public void CallerCancellationDuringVerificationPropagates (bool keyRequest)
using (var client = new HttpClient (handler) { Timeout = Timeout.InfiniteTimeSpan }) {
var engine = CreateBuildEngine ();
var task = new InstallAndroidDependencies { BuildEngine = engine };
- var archive = new Archive ("windows") { Url = new Uri ("https://example.test/jdk.zip") };
+ var archive = new Archive () { Url = new Uri ("https://example.test/jdk.zip") };
Assert.CatchAsync (async () => await task.VerifyJavaArchiveAsync (client, archive, source.Token));
Assert.IsTrue (handler.Blocked);
Assert.IsTrue (source.IsCancellationRequested);
@@ -465,7 +464,7 @@ public void BypassDefaultsToFalseAndTargetForwardsPrivateProperty ()
public async Task PublishedMicrosoftArchive ()
{
using (var client = new HttpClient { Timeout = TimeSpan.FromMinutes (10) }) {
- var archive = new Archive ("windows") {
+ var archive = new Archive () {
Url = new Uri ("https://aka.ms/download-jdk/microsoft-jdk-21.0.8-windows-x64.zip"),
DownloadedFilePath = Path.GetTempFileName (),
};
@@ -547,7 +546,7 @@ static bool RunVerificationTask (SignatureHandler handler, MockBuildEngine engin
var task = new VerificationTask {
BuildEngine = engine,
Client = client,
- Archive = new Archive ("windows") {
+ Archive = new Archive () {
Url = new Uri ("https://example.test/jdk.tar.gz?token=test"),
DownloadedFilePath = path,
},
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
index ba0219e2184..4bbfedfb8a6 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
@@ -24,7 +24,6 @@
-
diff --git a/src/Xamarin.Installer.AndroidSDK/CodeGenerator.targets b/src/Xamarin.Installer.AndroidSDK/CodeGenerator.targets
deleted file mode 100644
index 9bd54768669..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/CodeGenerator.targets
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- $(MSBuildThisFileDirectory)..\Xamarin.Installer.Build.Tasks\Xamarin.Installer.Common.props
-
-
-
-
- $(IntermediateOutputPath)RequiredComponentVersions.cs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/AssemblyInfo.cs b/src/Xamarin.Installer.AndroidSDK/Properties/AssemblyInfo.cs
deleted file mode 100644
index 7222449168a..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("Xamarin Android SDK Installer")]
-[assembly: AssemblyDescription("Xamarin Android SDK Installer")]
-[assembly: AssemblyProduct("Xamarin Android SDK Manager")]
-[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)]
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.Designer.cs b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.Designer.cs
deleted file mode 100644
index c6dfd39f781..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace Xamarin.Installer.AndroidSDK.Properties {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xamarin.Installer.AndroidSDK.Properties.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized string similar to Accept Android licenses failed: Android SDK not found.
- ///
- internal static string AccepLicensesFailedAndroidSDKNotFound {
- get {
- return ResourceManager.GetString("AccepLicensesFailedAndroidSDKNotFound", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Accept Android licenses failed: cmdline-tools not found.
- ///
- internal static string AccepLicensesFailedCMDLineToolsNotFound {
- get {
- return ResourceManager.GetString("AccepLicensesFailedCMDLineToolsNotFound", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Accept Android licenses failed: Java SDK not found.
- ///
- internal static string AccepLicensesFailedJavaSDKNotFound {
- get {
- return ResourceManager.GetString("AccepLicensesFailedJavaSDKNotFound", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Component installation failed.
- ///
- internal static string ComponentInstallationFailed {
- get {
- return ResourceManager.GetString("ComponentInstallationFailed", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Failure to load component properties file.
- ///
- internal static string FailedToLoadSourceProperties {
- get {
- return ResourceManager.GetString("FailedToLoadSourceProperties", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to An error occurred trying to accept Android licenses.
- ///
- internal static string GoogleAccepLicensesFailed {
- get {
- return ResourceManager.GetString("GoogleAccepLicensesFailed", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to No suitable component archive found..
- ///
- internal static string NoSuitableArchiveFound {
- get {
- return ResourceManager.GetString("NoSuitableArchiveFound", resourceCulture);
- }
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.cs.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.cs.resx
deleted file mode 100644
index b01eed2459a..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.cs.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Instalace komponenty se nezdařila.
-
-
- Nepovedlo se načíst soubor vlastností komponenty.
-
-
- Nenašel se žádný vhodný archiv komponent.
-
-
- Při pokusu o přijetí licencí pro Android došlo k chybě.
-
-
- Nepovedlo se přijmout licence na Android: nenalezena sada Android SDK
-
-
- Nepovedlo se přijmout licence na Android: nenalezena sada Java SDK
-
-
- Nepovedlo se přijmout licence pro Android: nenalezeny nástroje příkazového řádku
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.de.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.de.resx
deleted file mode 100644
index 4c3daa050aa..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.de.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Fehler beim Installieren der Komponente.
-
-
- Fehler beim Laden der Datei mit den Komponenteneigenschaften.
-
-
- Es wurde kein geeignetes Komponentenarchiv gefunden.
-
-
- Fehler beim Akzeptieren von Android-Lizenzen
-
-
- Fehler beim Akzeptieren von Android-Lizenzen: Android SDK nicht gefunden
-
-
- Fehler beim Akzeptieren von Android-Lizenzen: Java SDK nicht gefunden
-
-
- Fehler beim Akzeptieren von Android-Lizenzen: cmdline-Tools nicht gefunden
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.es.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.es.resx
deleted file mode 100644
index cbd83a51b89..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.es.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Fallo en la instalación de componentes
-
-
- Error al cargar el archivo de propiedades del componente
-
-
- No se encontró ningún archivo de componentes adecuado.
-
-
- Error al intentar aceptar licencias de Android
-
-
- Error al aceptar licencias de Android: no se encontró el SDK de Android
-
-
- Error al aceptar licencias de Android: no se encontró el SDK de Java
-
-
- Error al aceptar licencias de Android: cmdline-tools no encontrado
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.fr.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.fr.resx
deleted file mode 100644
index 58ab878a959..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.fr.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Échec de l'installation du composant.
-
-
- Échec du chargement du fichier des propriétés du composant
-
-
- Aucune archive de composant appropriée n’a été trouvée.
-
-
- Désolé, une erreur s’est produite lors de la tentative d’acceptation des licences Android.
-
-
- Échec de l’acceptation des licences Android : Android SDK introuvable
-
-
- Échec de l’acceptation des licences Android : SDK Java introuvable
-
-
- Échec de l’acceptation des licences Android : outils de ligne de commande introuvables
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.it.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.it.resx
deleted file mode 100644
index 455c9a46ba6..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.it.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- L'installazione del componente non è riuscita
-
-
- Si è verificato un errore durante il caricamento del file delle proprietà del componente
-
-
- Non sono stati trovati archivi di componenti appropriati.
-
-
- Si è verificato un errore durante il tentativo di accettare le licenze di Android
-
-
- L'accettazione delle licenze Android non è riuscita: Android SDK non trovato
-
-
- L'accettazione delle licenze Android non è riuscita: Java SDK non trovato
-
-
- Accettazione delle licenze Android non riuscita: cmdline-tools non trovato
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ja.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ja.resx
deleted file mode 100644
index 15ff2df1c16..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ja.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- コンポーネントをインストールできませんでした。
-
-
- コンポーネント プロパティ ファイルの読み込みに失敗しました
-
-
- 適切なコンポーネント アーカイブが見つかりませんでした。
-
-
- Android ライセンスを承諾しようとしてエラーが発生しました。
-
-
- Android ライセンスの承諾に失敗しました: Android SDK が見つかりません
-
-
- Android ライセンスの承諾に失敗しました: Java SDK が見つかりません
-
-
- Android ライセンスの承諾に失敗しました: cmdline-tools が見つかりません
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ko.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ko.resx
deleted file mode 100644
index d6f2995c361..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ko.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 구성 요소 설치 실패
-
-
- 구성 요소 속성 파일 로드 실패
-
-
- 적절한 구성 요소 보관함을 찾을 수 없습니다.
-
-
- Android 라이선스를 수락하는 동안 오류 발생
-
-
- Android 라이선스 수락 실패: Android SDK를 찾을 수 없음
-
-
- Android 라이선스 수락 실패: Java SDK를 찾을 수 없음
-
-
- Android 라이선스 수락 실패: cmdline-tools를 찾을 수 없음
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.pl.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.pl.resx
deleted file mode 100644
index 89745f6389e..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.pl.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Instalacja składników nie powiodła się
-
-
- Nie można załadować pliku właściwości składników
-
-
- Nie znaleziono odpowiedniego archiwum składników.
-
-
- Wystąpił błąd podczas próby zaakceptowania licencji dla systemu Android
-
-
- Zaakceptuj licencje dla systemu Android nie powiodło się: nie znaleziono zestawu Android SDK dla języka Java
-
-
- Zaakceptuj licencje dla systemu Android nie powiodło się: nie znaleziono zestawu SDK dla języka Java
-
-
- Zaakceptuj licencje dla systemu Android nie powiodło się: nie znaleziono narzędzi cmdline
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.pt-BR.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.pt-BR.resx
deleted file mode 100644
index ec57b754bc4..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.pt-BR.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- A instalação do componente falhou
-
-
- Falha ao carregar o arquivo de propriedades do componente
-
-
- Nenhum arquivo de componente adequado encontrado.
-
-
- Ocorreu um erro ao tentar aceitar licenças do Android
-
-
- Falha ao aceitar licenças do Android: SDK do Android não encontrado
-
-
- Falha ao aceitar licenças do Android: SDK do Java não encontrado
-
-
- Falha ao aceitar licenças do Android: cmdline-tools não encontrado
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.resx
deleted file mode 100644
index cbed730e388..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Component installation failed
-
-
- Failure to load component properties file
-
-
- No suitable component archive found.
-
-
- An error occurred trying to accept Android licenses
-
-
- Accept Android licenses failed: Android SDK not found
-
-
- Accept Android licenses failed: Java SDK not found
-
-
- Accept Android licenses failed: cmdline-tools not found
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ru.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ru.resx
deleted file mode 100644
index 64e260b60a8..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.ru.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Сбой установки компонента
-
-
- Не удалось загрузить файл свойств компонента
-
-
- Подходящий архив компонентов не найден.
-
-
- Произошла ошибка при попытке принять лицензии Android
-
-
- Не удалось принять лицензии Android: пакет SDK для Android не найден
-
-
- Не удалось принять лицензии Android: пакет SDK для Java не найден
-
-
- Не удалось принять лицензии Android: инструменты командной строки не найдены
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.tr.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.tr.resx
deleted file mode 100644
index d8e1e647c10..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.tr.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Bileşen yükleme işlemi başarısız oldu
-
-
- Bileşen özellikleri dosyası yüklenemedi
-
-
- Uygun bileşen arşivi bulunamadı.
-
-
- Android lisansları kabul edilmeye çalışılırken hata oluştu
-
-
- Android lisansları kabul edilemedi: Android SDK bulunamadı
-
-
- Android lisansları kabul edilemedi: Java SDK bulunamadı
-
-
- Android lisansları kabul edilemedi: cmdline-tools bulunamadı
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.zh-Hans.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.zh-Hans.resx
deleted file mode 100644
index b8003c18edd..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.zh-Hans.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 组件安装失败
-
-
- 无法加载组件属性文件
-
-
- 找不到合适的组件存档。
-
-
- 尝试接受 Android 许可证时出错。
-
-
- 接受 Android 许可证失败: 找不到 Android SDK
-
-
- 接受 Android 许可证失败: 找不到 Java SDK
-
-
- 接受 Android 许可证失败: 找不到 cmdline-tools
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.zh-Hant.resx b/src/Xamarin.Installer.AndroidSDK/Properties/Resources.zh-Hant.resx
deleted file mode 100644
index 9bd9bbf05f5..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Properties/Resources.zh-Hant.resx
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 元件安裝失敗
-
-
- 無法載入元件內容檔案
-
-
- 找不到適合的元件保存。
-
-
- 嘗試接受 Android 授權時發生錯誤
-
-
- 接受 Android 授權失敗: 找不到 Android SDK
-
-
- 接受 Android 授權失敗: 找不到 JAVA SDK
-
-
- 接受 Android 授權失敗: 找不到 Cmdline-tools
-
-
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK.csproj b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK.csproj
deleted file mode 100644
index a62ec7972dd..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK.csproj
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
- $(NoWarn);CA1305;CS1591
-
-
- netstandard2.0
- 12
- false
- WINDOWS;$(DefineConstants)
- false
- $(MicrosoftAndroidSdkOutDir)
-
-
- bin\Debug\Xamarin.Installer.AndroidSDK.xml
-
-
- bin\Release\Xamarin.Installer.AndroidSDK.xml
-
-
-
-
- true
- $(CodeSigningFile)
-
-
- Xamarin.Installer.AndroidSDK
- Assembly for Xamarin.Installer.AndroidSDK
-
-
-
-
-
- Properties\AssemblyInfoTemplate.cs
-
-
- True
- True
- Resources.resx
-
-
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
-
-
-
-
- TargetFramework=netstandard2.0
-
-
-
-
-
-
-
- runtime
- All
-
-
- 1.0.0
-
-
-
-
-
-
-
-
-
-
-
-
- $(MSBuildThisFileDirectory)..\..\build-tools\android-platform-support\version.txt
-
-
-
-
-
-
-
-
-
-
- Microsoft400
-
-
- Microsoft400
-
-
-
-
-
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidAddonDependencyInfo.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidAddonDependencyInfo.cs
deleted file mode 100644
index e83e57b20fa..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidAddonDependencyInfo.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-namespace Xamarin.Installer.AndroidSDK
-{
- class AndroidAddonDependencyInfo
- {
- public string ApiLevel { get; set; }
- public string NameId { get; set; }
- public string NameDisplay { get; set; }
- public string VendorId { get; set; }
- public string VendorDisplay { get; set; }
- public bool Unsure { get; set; }
- }
-}
-
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidComponentType.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidComponentType.cs
deleted file mode 100644
index bbb5fbfb33f..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidComponentType.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Android component type. This serves as an easier way to find what type an instance of
- /// represents.
- ///
- public enum AndroidComponentType
- {
- ///
- /// Component is an addon
- ///
- Addon,
-
- ///
- /// Component is an extra addition to the SDK
- ///
- Extra,
-
- ///
- /// A generic component
- ///
- Generic,
-
- ///
- /// A Maven component
- ///
- Maven,
-
- ///
- /// An API level (platform) component
- ///
- Platform,
-
- ///
- /// A source component
- ///
- Source,
-
- ///
- /// A system image component
- ///
- SystemImage,
-
- ///
- /// Unknown type of the component
- ///
- Unknown = 1000
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidExtensions.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidExtensions.cs
deleted file mode 100644
index 345e9419507..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidExtensions.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- static class AndroidExtensions
- {
- public static bool GetPkgRevision (this IDictionary props, out string original, out AndroidRevision parsed, string packageName = null)
- {
- original = null;
- parsed = null;
-
- packageName = packageName.SafeTrim ();
- if (!String.IsNullOrEmpty (packageName))
- packageName = String.Format ("'{0}' ", packageName);
-
- if (props == null) {
- Logger.Debug ("No properties object, cannot obtain Android package {0}revision", packageName);
- return false;
- }
-
- string rev;
- if (!props.GetProperty("Pkg.Revision", out rev) || String.IsNullOrEmpty (rev)) {
- Logger.Debug ("Android package {0}has no revision defined", packageName);
- return false;
- }
-
- original = rev;
- var arev = new AndroidRevision (rev, false);
- parsed = arev.IsValid ? arev : null;
-
- return parsed != null;
- }
-
- public static Version TryParseAsAndroidVersion (this string av, bool returnDefaultZeros = false)
- {
- if (String.IsNullOrEmpty (av))
- goto returnDefault;
-
- if (av.IndexOf ('.') < 0) {
- int v;
-
- if (!Int32.TryParse (av, out v)) {
- Logger.Info ("Version is not an integer: {0}", av);
- goto returnDefault;
- }
-
- return new Version (v, 0).CloneFillWithZeros ();
- }
-
- Version ver;
- if (!Version.TryParse (av, out ver)) {
- Logger.Info ("Package revision is not a valid version: {0}", av);
- goto returnDefault;
- }
-
- return ver.CloneFillWithZeros ();
-
- returnDefault:
- return returnDefaultZeros ? new Version (0, 0, 0, 0) : null;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidManifestType.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidManifestType.cs
deleted file mode 100644
index 7eb6a76b3b0..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidManifestType.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Author:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Android manifest type.
- ///
- public enum AndroidManifestType
- {
- ///
- /// New (as of 2016) Google repository manifest format (e.g. http://dl-ssl.google.com/android/repository/repository2-1.xml)
- ///
- GoogleV2,
-
- ///
- /// Xamarin manifest format (https://aka.ms/AndroidManifestFeed/d17-12)
- ///
- Xamarin,
-
- ///
- /// Doesn't access the Internet at all. Instead it looks for local repositories and attempts to read information about
- /// all the installed components. The returned information can (and will) be incomplete - information about channels is
- /// unavailable for locally installed packages, as well as download URLs of the archives. Care must be taken when
- /// accessing properties so that no null reference exceptions are thrown.
- ///
- Local,
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidRevision.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidRevision.cs
deleted file mode 100644
index a639b6cfe4f..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidRevision.cs
+++ /dev/null
@@ -1,354 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-using System.Text;
-
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Represents Android component revision. Only the component is guaranteed to be present.
- ///
- public sealed class AndroidRevision : IEquatable , IComparable
- {
- ///
- /// Gets the major revision number
- ///
- /// Major revision number
- public int Major { get; private set; }
-
- ///
- /// Gets the minor revision number. Value is valid if it's equal or higer than zero.
- ///
- /// Minor revision number
- public int Minor { get; private set; }
-
- ///
- /// Gets the micro revision number. Value is valid if it's equal or higer than zero.
- ///
- /// Micro revision number
- public int Micro { get; private set; }
-
- ///
- /// Gets the minor preview number. Value is valid if it's equal or higer than zero.
- ///
- /// Preview revision number
- public int Preview { get; private set; }
-
- ///
- /// Indicates whether or not this revision instance represents a valid revision
- ///
- /// true if valid; otherwise, false.
- public bool IsValid => Major > 0;
-
- ///
- /// If set to true, indicates that should consider comparing only
- /// the and properties.
- ///
- /// true to compare only major and minor components; otherwise, false.
- public bool ConsiderOnlyMajorMinor { get; set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Major revision number (required, must be higher than or equal to zero)
- /// Minor revision number (optional)
- /// Micro revision number (optional)
- /// Preview revision number (optional)
- /// If set to true throw an exception if revision is invalid.
- public AndroidRevision (int major, int minor = -1, int micro = -1, int preview = -1, bool throwIfInvalid = true)
- {
- Init (major, minor, micro, preview, throwIfInvalid);
- }
-
- ///
- /// Initializes a new instance of the class. Attempts to
- /// parse the revision string passed in the parameter.
- ///
- /// Revision string to parse
- /// If set to true throw an exception if revision is invalid.
- public AndroidRevision (string rev, bool throwIfInvalid = true)
- {
- if (String.IsNullOrEmpty (rev))
- goto setDefault;
-
- if (rev.IndexOf ('.') < 0) {
- int v;
-
- if (!Int32.TryParse (rev, out v)) {
- Logger.Info ($"Version is not an integer: {rev}");
- goto setDefault;
- }
-
- Init (v, throwIfInvalid: throwIfInvalid);
- return;
- }
-
- Version ver;
- if (!Version.TryParse (rev, out ver)) {
- Logger.Info ($"Package revision is not a valid version: {rev}");
- goto setDefault;
- }
-
- Init (ver.Major, ver.Minor, ver.Build, ver.Revision, throwIfInvalid);
- return;
-
- setDefault:
- Init (0, throwIfInvalid: throwIfInvalid);
- }
-
- public AndroidRevision (AndroidRevision other, bool throwIfInvalid = true)
- {
- if (other == null)
- throw new ArgumentNullException (nameof (other));
- Init (other.Major, other.Minor, other.Micro, other.Preview, throwIfInvalid);
- }
-
- void Init (int major, int minor = -1, int micro = -1, int preview = -1, bool throwIfInvalid = true)
- {
- if (major < 0 && throwIfInvalid)
- throw new ArgumentOutOfRangeException(nameof(major), "Must not be less than zero");
-
- Major = EnsureValidValue (major);
- Minor = EnsureValidValue (minor);
- Micro = EnsureValidValue (micro);
- Preview = EnsureValidValue (preview);
- }
-
- int EnsureValidValue (int value)
- {
- if (value < 0)
- return -1;
- return value;
- }
-
- ///
- /// Returns a that represents the current in the standard
- /// dotted format.
- ///
- /// A that represents the current .
- public override string ToString ()
- {
- var sb = new StringBuilder ();
- sb.Append (Major);
- AppendValue (Minor, sb);
- AppendValue (Micro, sb);
- AppendValue (Preview, sb);
-
- return sb.ToString ();
- }
-
- void AppendValue (int value, StringBuilder sb)
- {
- if (value < 0)
- return;
- sb.Append ('.');
- sb.Append (value);
- }
-
- ///
- /// Determines whether the specified is equal to the
- /// current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals (AndroidRevision other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals (this, other))
- return true;
-
- if (Major != other.Major)
- return false;
-
- if (Minor != other.Minor)
- return false;
-
- if (ConsiderOnlyMajorMinor)
- return true;
-
- if (Micro != other.Micro)
- return false;
-
- return Preview == other.Preview;
- }
-
- public bool EqualsValid(AndroidRevision other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals(this, other))
- return true;
-
- if (!IsValid || !other.IsValid)
- return false;
-
- if (Major != other.Major)
- return false;
-
- if (Minor == -1 || other.Minor == -1)
- return true;
- if (Minor != other.Minor)
- return false;
-
- if (Micro == -1 || other.Micro == -1)
- return true;
- if (Micro != other.Micro)
- return false;
-
- if (Preview == -1 || other.Preview == -1)
- return true;
- return Preview == other.Preview;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidRevision);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = Major.GetHashCode ();
- hashCode = hashCode.XorWith (Minor);
- hashCode = hashCode.XorWith (Micro);
- return hashCode.XorWith (Preview);
- }
-
- ///
- /// Compares this instance of to another one.
- ///
- ///
- ///
- /// -
- /// 1if this instance is bigger than
- ///
- /// -
- /// 0if this instance is equal to
- ///
- /// -
- /// -1if this instance is smaller than
- ///
- ///
">
- /// Other.
- public int CompareTo (AndroidRevision other)
- {
- if (other == null)
- return 1;
-
- if (Major != other.Major)
- return Major > other.Major ? 1 : -1;
-
- if (Minor != other.Minor)
- return Minor > other.Minor ? 1 : -1;
-
- if (Micro != other.Micro)
- return Micro > other.Micro ? 1 : -1;
-
- if (Preview != other.Preview)
- return Preview > other.Preview ? 1 : -1;
-
- return 0;
- }
-
- ///
- /// Determines whether a specified instance of is equal to
- /// another specified .
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if rev1 and rev2 are equal; otherwise, false.
- public static bool operator == (AndroidRevision rev1, AndroidRevision rev2)
- {
- if (Object.ReferenceEquals (rev1, null)) {
- return Object.ReferenceEquals (rev2, null);
- }
-
- return rev1.Equals (rev2);
- }
-
- ///
- /// Determines whether a specified instance of is not equal
- /// to another specified .
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if rev1 and rev2 are not equal; otherwise, false.
- public static bool operator != (AndroidRevision rev1, AndroidRevision rev2)
- {
- return !(rev1 == rev2);
- }
-
- ///
- /// Determines whether one specified is lower than another
- /// specfied .
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if rev1 is lower than rev2; otherwise, false.
- public static bool operator < (AndroidRevision rev1, AndroidRevision rev2)
- {
- if (rev1 == null)
- throw new ArgumentNullException (nameof (rev1));
- return rev1.CompareTo (rev2) < 0;
- }
-
- ///
- /// Determines whether one specified is lower than or equal
- /// to another specfied .
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if rev1 is lower than or equal to rev2; otherwise, false.
- public static bool operator <= (AndroidRevision rev1, AndroidRevision rev2)
- {
- if (rev1 == null)
- throw new ArgumentNullException (nameof (rev1));
- return rev1.CompareTo (rev2) <= 0;
- }
-
- ///
- /// Determines whether one specified is greater than
- /// another specfied .
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if rev1 is greater than rev2; otherwise, false.
- public static bool operator > (AndroidRevision rev1, AndroidRevision rev2)
- {
- return rev2 < rev1;
- }
-
- ///
- /// Determines whether one specified is greater than or
- /// equal to another specfied .
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if rev1 is greater than or equal to rev2; otherwise, false.
- public static bool operator >= (AndroidRevision rev1, AndroidRevision rev2)
- {
- return rev2 <= rev1;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKComponentInstallationResult.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKComponentInstallationResult.cs
deleted file mode 100644
index 70696d21450..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKComponentInstallationResult.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using System;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- public class AndroidSDKComponentInstallationResult
- {
- public enum States
- {
- None,
- UserCancelled,
- DownloadError,
- InstallationError,
- UninstallationError,
- DownloadedSuccessfully,
- InstalledSuccessfully,
- UninstalledSuccessfully,
- Success,
-
- LicensesNotAccepted,
- LicensesAccepted,
- LicensesNotRequired,
- LicensesAcceptanceFailed
- }
-
- public bool Success { get; set; }
- public States State { get; set; }
-
- public Exception Exception { get; set; }
-
- public AndroidSDKComponentInstallationResult (bool success, Exception exception = null)
- : this (success ? States.Success : States.None, exception, success)
- {
- }
-
- public AndroidSDKComponentInstallationResult (States state, Exception exception = null, bool? success = null)
- {
- State = state;
- Exception = exception;
- Success = success.HasValue ? success.Value : state.IsSuccessful ();
- }
-
- ///
- /// Use instead if you need to handle null values
- ///
- public override string ToString ()
- {
- return this.ToReadableString ();
- }
- }
-
- public static class AndroidSDKComponentInstallationResultExtensions
- {
- public static bool IsSuccessful(this AndroidSDKComponentInstallationResult.States state)
- {
- return state == AndroidSDKComponentInstallationResult.States.Success
- || state == AndroidSDKComponentInstallationResult.States.DownloadedSuccessfully
- || state == AndroidSDKComponentInstallationResult.States.InstalledSuccessfully
- || state == AndroidSDKComponentInstallationResult.States.UninstalledSuccessfully
- || state == AndroidSDKComponentInstallationResult.States.LicensesAccepted
- || state == AndroidSDKComponentInstallationResult.States.LicensesNotRequired;
- }
-
- ///
- /// This method supports null input values
- ///
- public static string ToReadableString (this AndroidSDKComponentInstallationResult result)
- {
- return result == null ? "undefined" :
- (result.Success ? "success"
- : (
- "fail" + (!String.IsNullOrEmpty (result.Exception?.Message) ? $": \"{result.Exception.Message}\"" : String.Empty)
- )) + $" ({result.State})";
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKContext.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKContext.cs
deleted file mode 100644
index c2be0dce8ae..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKContext.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
-
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- public class AndroidSDKContext
- {
- static readonly object instanceCreationLock = new object ();
-
- public static readonly AndroidSDKContext Instance;
-
- public AndroidSDKPlatform Platform { get; set; }
-
- public string HostArch { get; set; }
-
- public string BaseTemporaryDirectory { get; set; }
-
- public string UserName {
- get {
- if (CommonUtilities.Helpers == null)
- throw new InvalidOperationException ("Internal error: CommonUtilities.Helpers must be initialized first");
- if (String.IsNullOrEmpty (CommonUtilities.Helpers.UserName))
- throw new InvalidOperationException ("Internal error: CommonUtilities.Helpers.UserName must have a valid value");
- return CommonUtilities.Helpers.UserName;
- }
- }
-
- // Just a convenience to make initialization more straightforward
- public string ProductName {
- get { return CommonUtilities.ProductName; }
- set { CommonUtilities.ProductName = value; }
- }
-
- static AndroidSDKContext ()
- {
- lock (instanceCreationLock) {
- if (Instance != null)
- return;
-
- Instance = new AndroidSDKContext {
- BaseTemporaryDirectory = Path.Combine(Path.GetTempPath(), "Xamarin"),
- Platform = DeterminePlatform(),
- HostArch = DetermineHostArch()
- };
- }
- }
-
- static AndroidSDKPlatform DeterminePlatform ()
- {
- switch (Environment.OSVersion.Platform) {
- case PlatformID.MacOSX:
- return AndroidSDKPlatform.Mac;
-
- // We only care about distinction between OSX and Linux, since that's the only
- // difference that matters in the Android SDK repository context
- case PlatformID.Unix:
- return IsRunningOnMac () ? AndroidSDKPlatform.Mac : AndroidSDKPlatform.Linux;
-
- default:
- return AndroidSDKPlatform.Windows; // another simplification that'll do
- }
- }
-
- static string DetermineHostArch()
- {
- switch (RuntimeInformation.OSArchitecture)
- {
- case Architecture.X86:
- return "x86";
- case Architecture.X64:
- return "x64";
- case Architecture.Arm64:
- return "aarch64";
- default:
- return "";
- }
- }
-
- [DllImport ("libc")]
- static extern int uname (IntPtr buf);
-
- //From Managed.Windows.Forms/XplatUI
- static bool IsRunningOnMac ()
- {
- IntPtr buf = IntPtr.Zero;
- try {
- buf = Marshal.AllocHGlobal (8192);
- // This is a hacktastic way of getting sysname from uname ()
- if (uname (buf) == 0) {
- string os = Marshal.PtrToStringAnsi (buf);
- if (os == "Darwin")
- return true;
- }
- } catch {
- // ignore
- } finally {
- if (buf != IntPtr.Zero)
- Marshal.FreeHGlobal (buf);
- }
- return false;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKInstaller.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKInstaller.cs
deleted file mode 100644
index f6e9a433318..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKInstaller.cs
+++ /dev/null
@@ -1,810 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Xml.Linq;
-
-using Xamarin.Android.Tools;
-using Xamarin.Installer.AndroidSDK.Common;
-using Xamarin.Installer.AndroidSDK.Xamarin;
-using Xamarin.Installer.AndroidSDK.GoogleV2;
-using Xamarin.Installer.AndroidSDK.LocalSDK;
-using Xamarin.Installer.Common;
-using Xamarin.Installer.AndroidSDK.Manager;
-using System.Threading.Tasks;
-using System.Threading;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Android SDK installer class is the class to be used by the client software to perform all the
- /// operations of updating or installing the SDK.
- ///
- public class AndroidSDKInstaller : IParserErrorHandler
- {
- List discoveredInstances;
- StringComparer filesystemComparer;
- StringComparison filesystemComparison;
- Uri _manifestURL;
- Uri _googleAddonsListURL;
- Uri _googleRepositoryBaseURL;
- bool _useManifestCaching;
- string defaultAndroidSdkPath;
- string[] allAndroidSdkPaths;
- string defaultJavaSdkPath;
- bool installationPathsDiscovered;
-
- ///
- /// Initializes a new instance of the class. The caller is
- /// required to pass an instance of class that implements the interface.
- ///
- /// Instance of a class implementing the IHelpers interface
- /// AndroidManifestType.Xamarin if the installer is to use the
- /// Xamarin Android SDK manifest, AndroidManifestType.GoogleV1 or AndroidManifestType.GoogleV2
- /// to use the official Google Android SDK manifest
- /// URL of the repository manifest (optional)
- /// Google repository only: URL of the addon manifest (optional)
- /// Google repository only: base URL of the repository
- /// If true, load local manifest when offline
- /// Instance of a class implementing the interface (optional)
- public AndroidSDKInstaller (IHelpers helpers, AndroidManifestType manifestType = AndroidManifestType.Xamarin, Uri manifestURL = null, Uri googleAddonsListURL = null, Uri googleRepositoryBaseURL = null, bool useManifestCaching = false, ILicensesStorage licensesStorage = null)
- {
- CommonUtilities.Helpers = helpers ?? new Helper();
- AndroidManifestType = manifestType;
-
- _manifestURL = manifestURL;
- _googleAddonsListURL = googleAddonsListURL;
- _googleRepositoryBaseURL = googleRepositoryBaseURL;
- _useManifestCaching = useManifestCaching;
-
- LicensesStorage = licensesStorage ?? new AndroidLicensesStorage();
-
- CreateRepository (manifestType, manifestURL, googleAddonsListURL, googleRepositoryBaseURL, useManifestCaching);
-
- filesystemComparer = helpers.IsCaseSensitiveFileSystem ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
- filesystemComparison = helpers.IsCaseSensitiveFileSystem ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
- }
-
- void EnsureInstallationPathsDiscovered ()
- {
- if (installationPathsDiscovered)
- return;
-
- AndroidSdkInfo.DiscoverInstallationPaths (out defaultAndroidSdkPath, out allAndroidSdkPaths, out defaultJavaSdkPath,
- logger: (level, message) => Logger.Debug ($"[{level}] {message}"));
- installationPathsDiscovered = true;
- }
-
- public Repository Repository { get; private set; }
-
- public ILicensesStorage LicensesStorage { get; private set; }
-
- public bool IgnoreArchiveChecksumErrors { get; set; }
-
- ///
- /// Raised whenever the installer wants to show a message to the user. Used only by the Install*
- /// family of methods.
- ///
- public event EventHandler InstallationProgress;
-
- ///
- /// Gets the repository manifest URL as detected and used by the current installer instance.
- ///
- /// The repository manifest URL
- public Uri RepositoryManifestURL {
- get { return Repository?.ManifestURL; }
- }
-
- ///
- /// After calling this list will contain all the instances of Android SDK
- /// detected on the system. Note that if there are no instances found a default one will be created
- /// and stored in this list.
- ///
- /// The discovered Android SDK instances.
- public IList DiscoveredSdkInstances {
- get { return discoveredInstances; }
- }
-
- ///
- /// Gets list of all the channels retrieved from the various repository manifests. Currently all of the
- /// Android SDK manifests defined the same 4 channels () but it is possible that
- /// there might be differences between manifests in the future.
- ///
- /// The channels.
- public IList Channels {
- get { return Repository?.Channels?.Values?.ToList (); }
- }
-
- ///
- /// Sets or gets the Android manifest type for this instance (see )
- ///
- public AndroidManifestType AndroidManifestType { get; }
-
- ///
- /// Gets the repository state. If true, it is using local manifest,
- /// and should be updated as soon as connection is established.
- ///
- public bool IsOffline => Repository.IsOffline;
-
- void CreateRepository (AndroidManifestType manifestType, Uri manifestURL, Uri googleAddonsListURL, Uri googleRepositoryBaseURL, bool useManifestCaching)
- {
- switch (manifestType) {
- case AndroidManifestType.Xamarin:
- Repository = new XamarinRepository (manifestURL, useManifestCaching);
- break;
-
- case AndroidManifestType.GoogleV2:
- Repository = new GoogleV2Repository (this, manifestURL, googleAddonsListURL, googleRepositoryBaseURL, useManifestCaching);
- break;
-
- case AndroidManifestType.Local:
- Repository = new LocalSDKRepository (this);
- break;
-
- default:
- throw new InvalidOperationException ($"Unsupported manifest type {manifestType}");
- }
- }
-
- ///
- /// Given a full filesystem path attempts to find and return a corresponding instance.
- ///
- /// The instance corresponding to the path.
- /// Full path for which to find a corresponding SDK instance. If null, default path will be used.
- public AndroidSdkInstance FindInstance (string forPath)
- {
- if (forPath == null) {
- EnsureInstallationPathsDiscovered ();
- forPath = defaultAndroidSdkPath;
- }
-
- if (String.IsNullOrEmpty (forPath))
- throw new ArgumentException ("must not be an empty string", nameof (forPath));
-
- string path = Path.GetFullPath (forPath);
- if (discoveredInstances == null || discoveredInstances.Count == 0) {
- return null;
- }
-
- return discoveredInstances.FirstOrDefault (sdk => string.Equals (sdk.Path, path, filesystemComparison));
- }
-
- ///
- ///
- /// Refreshes the state of all the components given a particular Android SDK . By default the method
- /// doesn't re-download or re-parse the manifest(s) but instead it performs detection of each of the components in the
- /// instance, thus updating their state. If, however, is set to true the repository manifests,
- /// if any, will be fetched and reparsed.
- ///
- ///
- /// If is true then the may have its set of components changed - new
- /// ones can be added and old ones can be changed (only their metadata will change, the component instance won't change).
- ///
- ///
- ///
- /// If is true then the method will start a full detection cycle. This means that the
- /// will be modified - all of its components will be replaced with fresh instances. This is to ensure that
- /// the metadata in the components is 100% accurate. By default full detection is not performed.
- ///
- ///
- /// Android SDK instance
- /// Perform update from the local filesystem, if true, update from remote manifests otherwise
- /// If true, perform full detection of all the components after refreshing the instance
- public void RefreshState (AndroidSdkInstance instance, bool localOnly = true, bool performFullDetection = false)
- {
- if (instance == null)
- throw new ArgumentNullException (nameof (instance));
- if (!localOnly)
- {
- try
- {
- Repository.Parse();
- }
- catch (Exception e)
- {
- LogParserError("AndroidSDK.RefreshState", e);
- return;
- }
- }
- Repository.Refresh (instance);
-
- if (performFullDetection)
- DetectSdkComponents (instance);
- }
-
- ///
- /// Downloads the current Android SDK repository manifest () and uses it to disover/detect
- /// all instances of Android SDK on the system. It uses the system-dependent default location as well as the locations stored
- /// in the paths discovered by . Additionally, it can include extra paths passed in
- /// the list. If no Android SDK instance is detected on the system a default one will be created.
- /// All the discovered instances are returned by the property.
- ///
- /// If is set to true (the default), the discovered instances replace the ones currently stored in
- /// the list returned by the property. Otherwise the newly discovered instances are appended
- /// to the list.
- ///
- /// The method returns true if detection was successful, false to indicate a "soft" error (one which lets the caller
- /// retry the operation, most likely a networking issue) and it can throw exceptions for "hard" errors.
- ///
- /// Custom Android SDK locations (optional).
- /// Perform detection from scratch if set to true (optional)
- /// Handler to be called whenever any component in the SDK instance changes its state
- public bool Discover (List sdkLocations = null, bool fromScratch = true, EventHandler instanceComponentStatusChangeHandler = null)
- {
- if (fromScratch || !Repository.Parsed) {
- if (fromScratch)
- CreateRepository (AndroidManifestType, _manifestURL, _googleAddonsListURL, _googleRepositoryBaseURL, _useManifestCaching);
- try
- {
- Repository.Parse();
- }
- catch (Exception e)
- {
- LogParserError("AndroidSDK.Discover", e);
- return false;
- }
- }
-
- var sdkInstances = new Dictionary (filesystemComparer);
- if (!fromScratch && discoveredInstances != null) {
- discoveredInstances.ForEach (instance => {
- if (instance == null || sdkInstances.ContainsKey (instance.Path))
- return;
- sdkInstances [instance.Path] = instance;
- });
- }
-
- var sdkPaths = new List ();
-
- EnsureInstallationPathsDiscovered ();
- sdkPaths.AddRange (allAndroidSdkPaths);
-
- if (sdkLocations != null)
- sdkPaths.AddRange (sdkLocations);
-
-
- sdkPaths = sdkPaths.Distinct ().ToList ();
-
- string defaultPath = defaultAndroidSdkPath ?? sdkPaths.FirstOrDefault ();
- foreach (string path in sdkPaths) {
- if (String.IsNullOrEmpty (path))
- continue;
- string asdkPath = Path.GetFullPath (path);
- if (sdkInstances.ContainsKey (asdkPath))
- continue;
-
- var sdkInstance = new AndroidSdkInstance {
- Path = asdkPath,
- IsDefault = string.Equals (path, defaultPath, filesystemComparison)
- };
- if (instanceComponentStatusChangeHandler != null) {
- sdkInstance.ComponentStatusChanged -= instanceComponentStatusChangeHandler;
- sdkInstance.ComponentStatusChanged += instanceComponentStatusChangeHandler;
- }
-
- DetectSdkComponents (sdkInstance);
-
- sdkInstances [asdkPath] = sdkInstance;
- }
-
- if (fromScratch || discoveredInstances == null)
- discoveredInstances = sdkInstances.Values.ToList ();
- else {
- sdkInstances.Values.ToList ().ForEach (instance => {
- if (discoveredInstances.Contains (instance))
- return;
- discoveredInstances.Add (instance);
- });
- }
- if (discoveredInstances.Count == 1)
- discoveredInstances [0].Selected = true;
- else if (discoveredInstances.Any () && !discoveredInstances.Any (item => item.Selected)) {
- // Make sure we have a selected sdk in any case as the interaction is optional
- // Select default location if its valid, select sdk with latest version otherwise
- var defaultInstance = discoveredInstances.FirstOrDefault (item => item.IsDefault);
- if (defaultInstance != null && (defaultInstance.Version.Major > 0 || !discoveredInstances.Any (item => item.Version.Major > 0)))
- defaultInstance.Selected = true;
- else
- discoveredInstances.OrderByDescending (item => item.Version).First ().Selected = true;
- }
-
- return true;
- }
-
- ///
- /// Gets the license with the ID specified in . The ID usually comes from
- ///
- ///
- /// The license identified by or an empty string if license with this ID is not found.
- /// License identifier. Required, must not be null
- public string GetLicense (string licenseId)
- {
- if (licenseId == null)
- throw new ArgumentNullException (nameof (licenseId));
-
- return Repository.GetLicense (licenseId)?.Text;
- }
-
- ///
- /// Returns a list of licenses for all the components passed in the
- /// parameter or, if it's null or empty, for all the outdated components in the specified
- /// .
- ///
- /// List of licenses or null if no licenses were available
- /// Android SDK instance.
- /// List of components to install (optional)
- public IList GetLicenses (AndroidSdkInstance instance, IList componentsToInstall = null)
- {
- if (instance == null)
- throw new ArgumentNullException (nameof (instance));
-
- IList < IAndroidComponent > components = null;
- if (componentsToInstall == null || componentsToInstall.Count == 0)
- components = instance.Components.AllOutdated ();
-
- if (components == null || components.Count == 0)
- return null;
-
- var ret = new List ();
- foreach (IAndroidComponent component in components) {
- License license = component?.License;
- if (license == null || ret.Contains (license))
- continue;
- ret.Add (license);
- }
-
- return ret.Count > 0 ? ret : null;
- }
-
- ///
- /// Gets a list of download items for all of the components passed in the parameter. After a
- /// successful download the calling party must set to the on-disk path of the
- /// downloaded file thus marking the instance as installable.
- ///
- /// List of archives to download
- /// List of components to get download items for
- public IList GetDownloadItems (IList components)
- {
- if (components == null || components.Count == 0)
- return null;
-
- var ret = new List ();
- foreach (IAndroidComponent component in components.Where (c => c != null && c.Archives != null && c.Archives.Count > 0)) {
- ret.AddRange (component.Archives.Where (a => a != null && a.Url != null).Select (a => ResetForDownload (a)));
- }
- return ret;
-
- Archive ResetForDownload (Archive archive)
- {
- archive.DownloadedFilePath = null;
- return archive;
- }
- }
-
- ///
- /// Gets a list of download items for all the outdated or missing components in the passed . After a
- /// successful download the calling party must set to the on-disk path of the
- /// downloaded file thus marking the instance as installable. The method considers
- /// before
- ///
- /// List of archives to download
- /// Android SDK instance
- /// If true, include missing components
- public IList GetDownloadItems (AndroidSdkInstance instance, bool includeMissing = false)
- {
- if (instance == null)
- return null;
- IList components = instance.ComponentsForInstallation ?? instance.Components;
- return GetDownloadItems (includeMissing ? components?.AllOutdatedOrMissing () : components?.AllOutdated ());
- }
-
- void OnInstallationProgress (bool isInitialEvent, float progress, string format, params object[] args)
- {
- if (InstallationProgress == null)
- return;
-
- string message;
- if (format == null)
- message = String.Empty;
- else if (args == null || args.Length == 0)
- message = format;
- else
- message = String.Format (format, args);
- InstallationProgress (this, new InstallationProgressEventArgs { Message = message, Progress = progress, IsInitialEvent = isInitialEvent });
- }
-
- ///
- ///
- /// Gets the set of components available for installation given the particular .
- /// If is null or empty, the outdated components from the
- /// will be considered for inclusion in the set. If the
- /// parameter is null or empty, only the default channel (stable) packages will be considered.
- ///
- ///
- /// Each component's dependencies will be added to the resulting set. It is possible that certain components
- /// (for instance build tools or emulators) will be found in the returned set more than once because they match
- /// the criteria (e.g. all the included versions are higher than the one detected on the system) or because they
- /// are dependent upon by one or more of the other components.
- ///
- ///
- /// Caller must decide which packages to eventually install if there are duplicates in the returned set.
- ///
- ///
- /// List of components that are candidates for installation in the given SDK instance
- /// Android SDK instance
- /// Components to install.
- /// Allowed channels.
- public IList GetInstallationSet (AndroidSdkInstance instance, IList componentsToInstall = null, HashSet allowedChannels = null)
- {
- if (instance == null)
- throw new ArgumentNullException (nameof (instance));
-
- if (componentsToInstall == null || componentsToInstall.Count == 0)
- componentsToInstall = instance.Components.AllOutdated ();
-
- if (componentsToInstall.Count == 0)
- return null;
-
- if (allowedChannels == null || allowedChannels.Count == 0) {
- allowedChannels = new HashSet {
- Repository.DefaultChannel
- };
- }
-
- var components = new List ();
- foreach (IAndroidComponent c in componentsToInstall) {
- AddComponentToSet (instance, c, components, allowedChannels);
- }
-
- return components;
- }
-
- ///
- /// Performs installation of all the components in the specified . The
- /// parameter must not be null or empty and it must contain all the components the hosting application needs to install - no dependency
- /// checking is performed by this method. It is advised to call the method prior to calling this one.
- /// Before installing anything the method checks all the archives in all the passed components, including checksum verification, to make sure they are installable.
- /// Checksum failures can be explicitly ignored with ; other archive validation still applies.
- /// If any invalid archive is found no installation is done. This is to prevent partially successful installations, potentially breaking the SDK
- /// instance. If is set to true and an invalid archive is found then the method
- /// will throw an exception, otherwise it will return without performing installation. All the issues are logged.
- ///
- /// Android SDK instance.
- /// Components to install
- /// Throw an exception if any component with invalid archives is found, if set to true
- /// Progress monitor (optional)
- public void Install (AndroidSdkInstance instance, IList componentsToInstall, bool throwIfInvalidComponentsFound = true,
- IProgressMonitor monitor = null)
- {
- if (instance == null)
- throw new ArgumentNullException (nameof (instance));
-
- if (componentsToInstall == null)
- throw new ArgumentNullException (nameof (componentsToInstall));
-
- //throw new Exception("A test install inner exception.");
-
- if (componentsToInstall.Count == 0)
- return;
-
- // This is a separate step so that we can report all the issues at the same time as well as prevent
- // installing of any components if even a single archive isn't valid.
- bool haveArchiveIssues = false;
- foreach (IAndroidComponent c in componentsToInstall) {
- // If it happens simply ignore the component silently
- if (c == null || c.Archives == null || c.Archives.Count == 0)
- continue;
-
- bool haveInvalidArchives = false;
- bool checkPlatform = !(c.Info is AndroidComponentInfoSystemImage);
- foreach (Archive a in c.Archives) {
- if (a == null || !a.WasDownloaded || a.IsInstallable (checkPlatform: checkPlatform))
- continue;
- if (IgnoreArchiveChecksumErrors && a.IsInstallable (verifyChecksum: false, checkPlatform: checkPlatform)) {
- Logger.Action ($"Continuing installation of Android SDK archive '{a.Url}' despite a checksum verification failure because the checksum override is enabled. The archive may be damaged or modified.");
- continue;
- }
- haveInvalidArchives = true;
- }
-
- if (haveInvalidArchives) {
- haveArchiveIssues = true;
- Logger.Warning ($"Android SDK component '{c.DetailedDescription}' reports issues with downloaded archive(s)");
- }
- }
-
- if (haveArchiveIssues) {
- Logger.Error ($"Certain Android SDK components encountered issues with the downloaded archives");
- if (throwIfInvalidComponentsFound)
- throw new InvalidOperationException ("Found issues with one or more Android SDK Components. Unable to continue.");
- return;
- }
-
- foreach (IAndroidComponent c in componentsToInstall)
- InstallComponent (c, instance, monitor);
- }
-
- ///
- /// Removes the components listed in from the specified .
- ///
- /// Android SDK instance.
- /// Components to remove
- public void Remove (AndroidSdkInstance instance, IList componentsToRemove)
- {
- if (instance == null)
- throw new ArgumentNullException (nameof (instance));
-
- if (componentsToRemove == null)
- throw new ArgumentNullException (nameof (componentsToRemove));
-
- //throw new Exception("Uninstall inner test exception.");
-
- if (componentsToRemove.Count == 0)
- return;
-
- foreach (IAndroidComponent c in componentsToRemove) {
- if (c == null)
- continue;
-
- Repository.Remove (c, instance.Path);
- }
- }
-
- void AddComponentToSet (AndroidSdkInstance instance, IAndroidComponent component, List componentSet, HashSet allowedChannels)
- {
- if (component == null) {
- Logger.Debug ("Skipping null component");
- return;
- }
- if (!component.ForceInstallation && component.Present && !component.NeedsUpdate) {
- Logger.Debug ($"Skipping component '{component.DetailedDescription}' as it is already present and up-to-date");
- return;
- }
- if (allowedChannels != null && !allowedChannels.Contains (component.Channel)) {
- var channels = string.Join (", ", allowedChannels.Select (c => c.Name));
- Logger.Debug ($"Skipping component '{component.DetailedDescription}' in channel '{component.Channel?.Name}' as it is not in the allowed channels ({channels})");
- return;
- }
- if (componentSet.Contains (component)) {
- Logger.Debug ($"Skipping component '{component.DetailedDescription}' as it is already in the set");
- return;
- }
-
- Logger.Debug ($"Adding component '{component.DetailedDescription}'");
- componentSet.Add (component);
-
- string hostOS = AndroidUtilities.GetPlatformOS ();
- if (component.Dependencies != null) {
- foreach (Dependency dep in component.Dependencies) {
- if (dep == null || String.IsNullOrEmpty (dep.Path))
- continue;
- Logger.Debug ($"{component.DetailedDescription} depends on: '{dep.Path}'{GetMinimumRevisionString (dep)}");
- IList deps = instance.Components.AllWithPath (dep.Path, dep.MinRevision);
- if (deps == null || deps.Count == 0) {
- Logger.Debug ($"{component.DetailedDescription}: dependency package '{dep.Path}' not found");
- continue;
- }
- string instances = GetPluralForm (deps.Count, "instance", "instances");
- Logger.Debug ($"{component.DetailedDescription}: found {deps.Count} {instances} of '{dep.Path}'");
- foreach (IAndroidComponent dc in deps) {
- if (dc == component)
- continue;
- AddComponentToSet (instance, dc, componentSet, allowedChannels);
- }
- }
- }
- }
-
- string GetPluralForm (int count, string singular, string plural)
- {
- return count == 1 ? singular : plural;
- }
-
- string GetMinimumRevisionString (Dependency dep)
- {
- if (dep?.MinRevision == null)
- return ", any revision";
- return $", minimum revision {dep.MinRevision}";
- }
-
- void InstallComponent (IAndroidComponent c, AndroidSdkInstance instance, IProgressMonitor monitor = null)
- {
- if (c == null || (!c.ForceInstallation && c.Present && !c.NeedsUpdate) || (c.Archives == null || c.Archives.Count == 0))
- return;
- var component = c as BasePackage;
- if (component == null)
- throw new InvalidOperationException ($"Internal error: unexpected component type {c.GetType ()}");
-
- int installSubComponentIndex = 0;
- bool isMonitorWithTotalProgress;
- if (monitor is MonitorWithTotalProgress wrapperMonitor)
- isMonitorWithTotalProgress = wrapperMonitor.IsMonitorWithTotalProgress;
- else if (monitor is IProgressMonitorWithTotalProgress) {
- monitor = new MonitorWithTotalProgress (monitor, 1);
- isMonitorWithTotalProgress = true;
- } else
- isMonitorWithTotalProgress = false;
-
- if (isMonitorWithTotalProgress && ((MonitorWithTotalProgress) monitor).IsMonitorWithTotalProgress) {
- ((MonitorWithTotalProgress) monitor).State = MonitorWithTotalProgress.States.Install;
- ((MonitorWithTotalProgress) monitor).SubComponentsCount = component.Archives.Count;
- }
-
- // In theory there should be just a single archive in each component, but we never know really...
- foreach (Archive archive in component.Archives) {
- // We can skip the checksum verification, it was done earlier
- // Don't check platform if the component is system-image
- if (!archive.IsInstallable (false, checkPlatform: !(component.Info is AndroidComponentInfoSystemImage)))
- continue;
-
- string progressMsgFormat = CommonUtilities.Helpers.GetString ("Installing {0}");
- string componentName = component.DetailedDescription;
-
- InstallationProgressEventArgs.InstallationProgressActionDelegate progressCallback =
- delegate (float progress) {
- //Logger.Debug($"[InstallationProgressActionDelegate] will report progress: {progress}");
- OnInstallationProgress (false, progress, progressMsgFormat, componentName);
- monitor?.ReportProgress ((long) progress);
- };
-
- OnInstallationProgress (true, 0f, progressMsgFormat, componentName);
-
- monitor?.BeginStep (String.Format (progressMsgFormat, componentName), 100);
-
- if (isMonitorWithTotalProgress && ((MonitorWithTotalProgress) monitor).IsMonitorWithTotalProgress) {
- ((MonitorWithTotalProgress) monitor).SubComponentIndex = installSubComponentIndex++;
- }
-
- Repository.Install (component, archive.DownloadedFilePath, instance.Path, progressCallback);
- monitor?.EndStep (new AndroidSDKComponentInstallationResult (AndroidSDKComponentInstallationResult.States.InstalledSuccessfully));
- }
- }
-
- void DetectSdkComponents (AndroidSdkInstance sdkInstance)
- {
- if (String.IsNullOrEmpty (sdkInstance.Path))
- throw new InvalidOperationException ("Internal error: Android SDK instance without associated path");
-
- Logger.Debug ($"Detecting Android SDK in '{sdkInstance.Path}'");
- Repository.Detect (sdkInstance);
-
- var sourcePropsFileName = "source.properties";
- string path = Path.Combine (sdkInstance.Path, Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, sourcePropsFileName);
- if (!File.Exists (path)) {
- path = Path.Combine (sdkInstance.Path, Constants.ComponentPaths.ToolsObsolete, sourcePropsFileName);
- }
-
- var props = AndroidUtilities.ReadAndroidProperties (path);
-
- if (!props.GetPkgRevision (out string origRev, out AndroidRevision instv)) {
- sdkInstance.Version = new AndroidRevision (0, 0, 0, 0);
- sdkInstance.VersionString = "r0";
- Logger.Debug ("Could not retrieve Pkg.Revision from {0}, r0 assumed", path);
- return;
- }
- sdkInstance.VersionString = "r" + origRev;
- sdkInstance.Version = instv;
-
- // The paths currently overlap with the contents of the tools package, but this can change hence the
- // code duplication
- List sdkExistenceCheckPaths;
- switch (AndroidSDKContext.Instance.Platform) {
- case AndroidSDKPlatform.Linux:
- case AndroidSDKPlatform.Mac:
- sdkExistenceCheckPaths = new List {
- Path.Combine (Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, "bin", "avdmanager"),
- Path.Combine (Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, "bin", "lint"),
- Path.Combine (Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, "bin", "sdkmanager"),
- };
- break;
-
- case AndroidSDKPlatform.Windows:
- sdkExistenceCheckPaths = new List {
- Path.Combine (Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, "bin", "avdmanager.bat"),
- Path.Combine (Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, "bin", "lint.bat"),
- Path.Combine (Constants.ComponentPaths.Tools, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion, "bin", "sdkmanager.bat"),
- };
- break;
-
- default:
- throw new InvalidOperationException ("Unsupported platform");
- }
-
- bool someFound = AndroidUtilities.CheckWheterFilesExist (sdkInstance.Path, "Android SDK Core", sdkExistenceCheckPaths, out double percentFound);
- if (!someFound || percentFound < 100.0) {
- if (someFound)
- Logger.Info ("'Android SDK Core' has less than 100% of its files on disk. Update is necessary.");
- }
- }
-
- void IParserErrorHandler.OnRecoverableError (ParserErrorLevel recommendedLevel, Uri documentUrl, XElement element, string message)
- {
- switch (recommendedLevel) {
- case ParserErrorLevel.Debug:
- Logger.Debug (message);
- break;
-
- case ParserErrorLevel.Info:
- Logger.Info (message);
- break;
-
- case ParserErrorLevel.Error:
- case ParserErrorLevel.Warning:
- Logger.Warning (message);
- break;
-
- default:
- goto case ParserErrorLevel.Info;
- }
- }
-
- void IParserErrorHandler.OnFatalError (Uri documentUrl, XElement element, string message)
- {
- Logger.Error (message);
- }
-
- static void LogParserError(string whereItHappened, Exception e)
- {
- Logger.Error($"[{whereItHappened}]: Failure parsing Android manifest: {e.Message}");
- Logger.Error($"[{whereItHappened}]: This is usually due to bad XML in one or more of the SDK manifests.");
- }
-
- ///
- /// Returns if the license was accepted in this Android SDK
- ///
- /// Android SDK instance.
- /// license to check
- /// true if the license is accepted, false otherwise
- public bool IsLicenseAccepted(AndroidSdkInstance instance, License license)
- {
- if (instance == null || license == null)
- {
- return false;
- }
-
- return this.LicensesStorage.IsLicenseAccepted(instance.Path, license);
- }
-
- ///
- /// Accept licenses
- ///
- /// Android SDK instance.
- /// list of licenses to accept
- /// cancellation token
- /// log file path
- /// path to java sdk
- /// if true, throws an exception if license validation fails
- public Task AcceptLicensesAsync(AndroidSdkInstance instance, IEnumerable licenses, CancellationToken token, string javaSdkPath = null, string logPath = null, bool throwsErrorIfValidationFailed = false)
- {
- if (instance != null) {
- var androidSdkPath = instance.Path;
- var javaPath = javaSdkPath;
- if (string.IsNullOrEmpty (javaPath)) {
- EnsureInstallationPathsDiscovered ();
- javaPath = defaultJavaSdkPath;
- }
-
- // try use the preferred cmdline-tools
- var cmdlineToolsRoot = Path.Combine(androidSdkPath, Constants.ComponentPaths.Tools);
- var cmdLineToolsPath = Path.Combine(cmdlineToolsRoot, Constants.RequiredComponentVersions.RequiredCommandLineToolsVersion);
- var cmdLineToolsPropertiesFilePath = Path.Combine(cmdLineToolsPath, "source.properties");
- if (!File.Exists(cmdLineToolsPropertiesFilePath))
- {
- // try use the latest cmdline-tools installed
- if (Directory.Exists(cmdlineToolsRoot))
- {
- cmdLineToolsPath = Directory.EnumerateDirectories(cmdlineToolsRoot).OrderBy(d => Path.GetFileName(d)).LastOrDefault();
- }
- else
- {
- cmdLineToolsPath = string.Empty;
- }
- }
-
- return LicensesStorage.AcceptLicensesAsync(androidSdkPath, javaPath, cmdLineToolsPath, licenses, token, logPath, throwsErrorIfValidationFailed);
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKPlatform.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKPlatform.cs
deleted file mode 100644
index 70ed0748ce8..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKPlatform.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- public enum AndroidSDKPlatform
- {
- Linux,
- Mac,
- Windows,
- Any,
- Unknown
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSdkInstance.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSdkInstance.cs
deleted file mode 100644
index c6a503d4b8e..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSdkInstance.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Xamarin.Installer.AndroidSDK.Common;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Describes a single Android SDK instance on the user's machine
- ///
- public sealed class AndroidSdkInstance
- {
- ulong? downloadSize;
- IList components;
-
- ///
- /// Occurs when component status changes.
- ///
- public event EventHandler ComponentStatusChanged;
-
- ///
- /// List of all the components that can be or are installed in this SDK instance.
- /// The caller needs to determine whether or not they desire all of them to be actually installed.
- ///
- /// List of all SDK components for this instance
- public IList Components {
- get { return components; }
- internal set {
- components = value;
- HookComponentEvents (components);
- }
- }
-
- ///
- /// A convenience property to store only components selected for installation as opposed to
- /// which has all the components loaded from the manifest. This
- /// property is used by the unified installer.
- ///
- /// The components for installation.
- public IList ComponentsForInstallation { get; set; }
-
- ///
- /// Indicates whether this instance corresponds to the default Android SDK location
- ///
- /// true if this instance corresponds to the default Android SDK location; otherwise, false.
- public bool IsDefault { get; internal set; }
-
- ///
- /// Indicates whether this instance corresponds to the official Android SDK location. Official location is, in fact, found
- /// only on Windows when the .exe Android SDK installer was used.
- ///
- /// true if this instance is official; otherwise, false.
- public bool IsOfficial { get; internal set; }
-
- ///
- /// Indicates whether this instance corresponds to a location specified by the user in the Unified Installer.
- ///
- /// true if this instance is user location; otherwise, false.
- public bool IsUserLocation { get; set; }
-
- ///
- /// Path to this instance's directory on disk. Note that the directory might not exist yet.
- ///
- /// Instance directory path.
- public string Path { get; internal set; }
-
- ///
- /// Indicates whether this instance has been selected as the one to install to. Used by the unified installer.
- ///
- /// true if selected; otherwise, false.
- public bool Selected { get; set; }
-
- ///
- /// Android SDK version in string (unparsed) form. It may include additional information in additon to the actual
- /// revision/version number.
- ///
- /// The version string.
- public string VersionString { get; internal set; }
-
- ///
- /// Parsed Android SDK version. This is parsed from and includes only the numeric part.
- ///
- /// The version.
- public AndroidRevision Version { get; internal set; }
-
- ///
- /// Gets a value indicating whether this needs any updates.
- ///
- /// true if needs update; otherwise, false.
- public bool NeedsUpdate => Components != null && Components.AnyOutdated ();
-
- internal AndroidSdkInstance ()
- {}
-
- ///
- /// Computes the total download size of all components
- /// passed in the parameter. If is false
- /// (the default) a cached value will be returned for all calls following the first one. If
- /// is null or empty, all the outdated components in this instance will be included in calculation.
- ///
- /// The total download size.
- /// Components to install (optional)
- /// Use cached value of the download size if true.
- public ulong GetDownloadSize (IList componentsToInstall = null, bool refresh = false)
- {
- if (!refresh && downloadSize.HasValue)
- return downloadSize.Value;
-
- if (componentsToInstall == null || componentsToInstall.Count == 0)
- componentsToInstall = Components.AllOutdated ();
-
- downloadSize = 0;
- if (componentsToInstall.Count == 0)
- return 0;
-
- ulong ret = 0;
- foreach (IAndroidComponent component in componentsToInstall) {
- if (component == null)
- continue;
- foreach (Archive archive in component.Archives) {
- if (archive == null)
- continue;
- ret += archive.Size;
- }
- };
-
- downloadSize = ret;
- return ret;
- }
-
- void HookComponentEvents (IList components)
- {
- if (components == null || components.Count == 0)
- return;
-
- foreach (IAndroidComponent c in components) {
- c.StatusChanged -= OnStatusChanged;
- c.StatusChanged += OnStatusChanged;
- }
- }
-
- void OnStatusChanged (object sender, AndroidComponentStatusChangeEventArgs args)
- {
- if (ComponentStatusChanged == null)
- return;
-
- ComponentStatusChanged (this, args);
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSystemImageAbi.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSystemImageAbi.cs
deleted file mode 100644
index 16b8b641501..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSystemImageAbi.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Android SDK System Image ABI
- ///
- public enum AndroidSystemImageAbi
- {
- ///
- /// System Image for the x86 architecture
- ///
- X86,
-
- ///
- /// System Image for the x86_64 architecture
- ///
- X86_64,
-
- ///
- /// System Image for the MIPS architecture
- ///
- Mips,
-
- ///
- /// System Image for the arm-v7a architecture
- ///
- ARMV7a,
-
- ///
- /// System Image for the arm64-v8a architecture
- ///
- ARM64V8a,
-
- ///
- /// Represents any ABI
- ///
- Any = 1000
- }
-}
-
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidUtilities.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidUtilities.cs
deleted file mode 100644
index d9287a76dd0..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidUtilities.cs
+++ /dev/null
@@ -1,492 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Xml;
-
-using Xamarin.Installer.AndroidSDK.Properties;
-using Xamarin.Installer.Common;
-using Xamarin.Installer.AndroidSDK.Common;
-using System.Text;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// A collection of Android SDK utilities
- ///
- public static class AndroidUtilities
- {
- const string PLACEHOLDER_DELIMITER = "|";
-
- static readonly Regex ndkNameRegex = new Regex (@"android-ndk-r(?\d+)(?\w*)-\w*", RegexOptions.Compiled);
-
- ///
- /// Parses a string with embedded placeholders to render a full directory path. Placeholders are
- /// placed between pipe characters and their names come from members of the
- /// enumeration.
- ///
- /// pattern to parse
- ///
- public static string ParseDirectoryWithSpecialFolderPlaceholders (string dirPattern)
- {
- dirPattern = dirPattern.SafeTrim ();
- if (String.IsNullOrEmpty (dirPattern))
- return String.Empty;
-
- string ret = dirPattern;
-
- // A dumb way, but it's all we need
- foreach (string name in Enum.GetNames (typeof (Environment.SpecialFolder))) {
- string ph = PLACEHOLDER_DELIMITER + name + PLACEHOLDER_DELIMITER;
- // We only replace the placeholder at the start of the value, since that's the only place where it makes sense
- if (ret.IndexOf (ph, StringComparison.Ordinal) != 0)
- continue;
- ret = ret.Replace (ph, Environment.GetFolderPath ((Environment.SpecialFolder)Enum.Parse (typeof (Environment.SpecialFolder), name)));
- }
-
- return ret;
- }
-
- ///
- /// Reads Java properties from the specified file
- ///
- /// path to the properties file
- /// collection of property names and values.
- public static Dictionary ReadAndroidProperties (string sourcePropertiesPath)
- => ReadAndroidProperties (sourcePropertiesPath, detectEncodingFromByteOrderMarks: false);
-
- internal static Dictionary ReadAndroidProperties (string sourcePropertiesPath, bool detectEncodingFromByteOrderMarks)
- {
- if (String.IsNullOrEmpty (sourcePropertiesPath) || !File.Exists (sourcePropertiesPath))
- return new Dictionary (StringComparer.Ordinal);
-
- try {
- using (var fs = File.Open (sourcePropertiesPath, FileMode.Open, FileAccess.Read, FileShare.Read))
- using (var reader = new StreamReader (fs, Encoding.GetEncoding (28591), detectEncodingFromByteOrderMarks)) {
- return ReadProperties (reader);
- }
- } catch (Exception ex) {
- Logger.Exception ("Failed to read Android properties from {0}", ex, sourcePropertiesPath);
- throw new InvalidOperationException (Resources.FailedToLoadSourceProperties, ex);
- }
- }
-
- static Dictionary ReadProperties (TextReader reader)
- {
- var properties = new Dictionary (StringComparer.Ordinal);
- int ch = reader.Read ();
- while (ch != -1) {
- if (IsWhitespace (ch) || ch is '\r' or '\n') {
- ch = reader.Read ();
- continue;
- }
- if (ch is '#' or '!') {
- while (ch != -1 && ch is not ('\r' or '\n'))
- ch = reader.Read ();
- continue;
- }
-
- string key = ReadPart (isKey: true);
- SkipWhitespace ();
- if (ch is '=' or ':') {
- ch = reader.Read ();
- SkipWhitespace ();
- }
- properties [key] = ReadPart (isKey: false);
- }
- return properties;
-
- string ReadPart (bool isKey)
- {
- var part = new StringBuilder ();
- while (ch != -1 && ch is not ('\r' or '\n') && !(isKey && (IsWhitespace (ch) || ch is '=' or ':'))) {
- if (ch != '\\') {
- part.Append ((char)ch);
- ch = reader.Read ();
- continue;
- }
-
- ch = reader.Read ();
- if (ch is '\r' or '\n') {
- if (ch == '\r' && reader.Peek () == '\n')
- reader.Read ();
- ch = reader.Read ();
- SkipWhitespace ();
- continue;
- }
- if (ch == 'u') {
- int value = 0;
- for (int i = 0; i < 4; i++) {
- int digit = reader.Read ();
- // Preserve the legacy reader's acceptance of letters beyond hexadecimal digits.
- int digitValue = digit switch {
- >= '0' and <= '9' => digit - '0',
- >= 'a' and <= 'z' => digit - 'a' + 10,
- >= 'A' and <= 'Z' => digit - 'A' + 10,
- _ => throw new FormatException ("Invalid Unicode character."),
- };
- value = (value << 4) + digitValue;
- }
- part.Append ((char)value);
- } else {
- // A trailing escape historically decodes end of input as U+FFFF.
- part.Append (ch switch {
- 't' => '\t',
- 'r' => '\r',
- 'n' => '\n',
- 'f' => '\f',
- _ => (char)ch,
- });
- }
- ch = reader.Read ();
- }
- return part.ToString ();
- }
-
- void SkipWhitespace ()
- {
- while (IsWhitespace (ch))
- ch = reader.Read ();
- }
-
- static bool IsWhitespace (int character) => character is ' ' or '\t' or '\f';
- }
-
- ///
- /// Installs (unpacks) the specified Android SDK ZIP archive () in the directory
- /// specified in the parameter. You can pass more path segments following the
- /// parameter, they will be used to construct the final path rooted at
- ///
- /// name of the archive/component, for informational purposes
- /// path to the ZIP archive
- /// top directory in which to install the archive
- /// optional path segments to append to to form the archive installation path
- ///
- public static bool InstallArchive (string name, string archivePath, string targetBasePath, params string[] targetPaths)
- {
- return InstallArchive (name, archivePath, false, targetBasePath, targetPaths);
- }
-
- ///
- /// Installs (unpacks) the specified Android SDK ZIP archive () in the directory
- /// specified in the parameter. You can pass more path segments following the
- /// parameter, they will be used to construct the final path rooted at
- /// If is set to true, the archive is unzipped without first creating a backup of the possibly existing
- /// target directory. This is used to install the main (distribution) archive of the Android SDK.
- ///
- /// name of the archive/component, for informational purposes
- /// path to the ZIP archive
- /// archive is the main/root archive of the Android SDK
- /// top directory in which to install the archive
- /// optional path segments to append to to form the archive installation path
- ///
- public static bool InstallArchive (string name, string archivePath, bool mainArchive, string targetBasePath, params string[] targetPaths)
- {
- string destDir;
- return InstallArchive (out destDir, name, archivePath, mainArchive, false, targetBasePath, targetPaths);
- }
-
- ///
- /// Installs (unpacks) the specified Android SDK ZIP archive () in the directory
- /// specified in the parameter. You can pass more path segments following the
- /// parameter, they will be used to construct the final path rooted at
- /// If is set to true, the archive is unzipped without first creating a backup of the possibly existing
- /// target directory. This is used to install the main (distribution) archive of the Android SDK.
- /// If is false then the method copies only the contents of the toplevel directory of the archive, instead of the
- /// entire contents of the archive. This is used with Android SDK archives who contain a single root directory and their target directory on disk is named differently.
- ///
- /// set to the destination directory on exit
- /// name of the archive/component, for informational purposes
- /// path to the ZIP archive
- /// archive is the main/root archive of the Android SDK
- /// include the archive's top-level directory in the copy if true, copy just its contents otherwise
- /// top directory in which to install the archive
- /// optional path segments to append to to form the archive installation path
- /// true if copy was successful, false otherwise
- public static bool InstallArchive (out string destinationDirectory, string name, string archivePath, bool mainArchive, bool includeZipRootInCopy, string targetBasePath, params string[] targetPaths)
- {
- destinationDirectory = null;
- Logger.Info ("Installing Android archive '{0}'", name);
- if (String.IsNullOrEmpty ("archivePath"))
- throw new ArgumentNullException ("archivePath");
- if (String.IsNullOrEmpty (targetBasePath))
- throw new ArgumentNullException ("targetBasePath");
-
- var rnd = new Random ();
- string componentUnzippedPath = null;
-
- // A small race here but I think we can accept the risks :)
- string temporaryPath = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
- try {
- componentUnzippedPath = CommonUtilities.Helpers.Unzip (temporaryPath, archivePath, AndroidSDKContext.Instance.UserName).RemoveTrailingDirectorySeparator ();
- } catch (Exception ex) {
- Logger.Exception (String.Format ("Exception caught while unzipping '{0}' in '{1}'", archivePath, temporaryPath), ex);
- componentUnzippedPath = null;
- }
-
- if (String.IsNullOrEmpty (componentUnzippedPath)) {
- Logger.SetOperationStatus (OperationStatus.Failure);
- Logger.Error ("Attempt to unzip Android archive '{0}' found in {1} failed.", name, archivePath);
- return false;
- }
-
- Logger.Debug ("Android archive '{0}' unpacked in directory '{1}'", name, componentUnzippedPath);
- destinationDirectory = CombinePaths (targetBasePath, targetPaths);
- if (includeZipRootInCopy)
- destinationDirectory = Path.Combine (destinationDirectory, Path.GetFileName (componentUnzippedPath));
- Logger.Debug ("Archive's destination path: {0}", destinationDirectory);
- string oldDestinationPath = null;
-
- if (!mainArchive && Directory.Exists (destinationDirectory)) {
- oldDestinationPath = destinationDirectory + ".old" + rnd.Next (Int32.MaxValue);
- Logger.Info ("Moving old directory '{0}' to '{1}'", destinationDirectory, oldDestinationPath);
- CommonUtilities.MoveDirectory (destinationDirectory, oldDestinationPath);
- }
-
- bool ret = true;
- try {
- int idx = destinationDirectory.LastIndexOf (Path.DirectorySeparatorChar);
- string leadingPath;
- if (idx > 1)
- leadingPath = destinationDirectory.Substring (0, idx);
- else
- leadingPath = destinationDirectory;
-
- if (!Directory.Exists (leadingPath)) {
- Logger.Info ("Creating Android component's parent path '{0}'", leadingPath);
- Directory.CreateDirectory (leadingPath);
- }
- Logger.Info ("Moving component to its destination path.");
-
- CommonUtilities.MoveDirectory (componentUnzippedPath, destinationDirectory, overwrite: true);
- } catch (Exception e) {
- ret = false;
- Logger.Exception ("Failure to move component to its destination path. Exception was thrown.", e);
- if (!String.IsNullOrEmpty (oldDestinationPath) && Directory.Exists (oldDestinationPath)) {
- Logger.Error ("Attempting to clean up.");
- Logger.Error ("Trying to remove directory '{0}'", destinationDirectory);
- CommonUtilities.DeleteDirectoryRecursively (destinationDirectory);
-
- try {
- CommonUtilities.MoveDirectory (oldDestinationPath, destinationDirectory);
- } catch (Exception ex) {
- // ignore
- Logger.Exception ("Failed to rename directory '{0}' to '{1}'", ex, oldDestinationPath, destinationDirectory);
- }
- }
- }
-
- bool logError = false;
- Exception rex = null;
- try {
- CommonUtilities.DeleteDirectoryRecursively (temporaryPath);
- if (!String.IsNullOrEmpty (oldDestinationPath))
- logError = !CommonUtilities.DeleteDirectoryRecursively (oldDestinationPath);
- } catch (Exception e) {
- logError = true;
- ret = false;
- rex = e;
- // ignore
- }
- if (logError) {
- string message = String.Format ("Failed to remove old destination directory '{0}'. User will have to remove it manually.", oldDestinationPath);
- if (rex != null)
- Logger.Exception (message, rex);
- else
- Logger.Error (message);
- }
-
- return ret;
- }
-
- internal static string CombinePaths (string targetBasePath, params string[] targetPaths)
- {
- if (targetPaths == null || targetPaths.Length == 0)
- return targetBasePath;
- else {
- var allPaths = new List ();
- allPaths.Add (targetBasePath);
- allPaths.AddRange (targetPaths);
- return Path.Combine (allPaths.ToArray ());
- }
- }
-
- internal static bool ParsePlatformVersion (string source, out Version version, out string versionTag)
- {
- version = null;
- versionTag = String.Empty;
-
- source = (source ?? String.Empty).Trim ();
- if (String.IsNullOrEmpty (source))
- return false;
-
- try {
- if (source.Length >= 3) { // The minimum valid version is X.Y
- version = Version.Parse (source);
- return true;
- }
- } catch (FormatException) {
- // ignore - google introduced version numbers with letters in them, we deal with it below
- }
-
- string validVersion = null;
- for (int i = 0; i < source.Length; i++) {
- char ch = source[i];
- if (ch == '.' || Char.IsDigit (ch))
- continue;
-
- validVersion = source.Substring (0, i);
- versionTag = source.Substring (i);
- }
-
- if (!String.IsNullOrEmpty (validVersion))
- version = Version.Parse (validVersion);
-
- return true;
- }
-
- public static string GetPlatformOS ()
- {
- return PlatformToString (AndroidSDKContext.Instance.Platform);
- }
-
- public static string PlatformToString (AndroidSDKPlatform platform)
- {
- switch (platform) {
- case AndroidSDKPlatform.Linux:
- return "linux";
-
- case AndroidSDKPlatform.Mac:
- return "macosx";
-
- case AndroidSDKPlatform.Windows:
- return "windows";
-
- case AndroidSDKPlatform.Unknown:
- case AndroidSDKPlatform.Any:
- return String.Empty;
-
- default:
- throw new InvalidOperationException ($"Unknown SDK platform: {platform}");
- }
- }
-
- internal static AndroidSDKPlatform GetPlatformFromOS (string osName)
- {
- osName = osName?.Trim ();
- if (String.IsNullOrEmpty (osName)) // Some archives aren't OS-specific
- return AndroidSDKPlatform.Any;
-
- if (string.Equals (osName, "linux", StringComparison.OrdinalIgnoreCase))
- return AndroidSDKPlatform.Linux;
-
- if (string.Equals (osName, "macosx", StringComparison.OrdinalIgnoreCase))
- return AndroidSDKPlatform.Mac;
-
- if (string.Equals (osName, "windows", StringComparison.OrdinalIgnoreCase))
- return AndroidSDKPlatform.Windows;
-
- return AndroidSDKPlatform.Unknown;
- }
-
- internal static bool CheckWheterFilesExist (string root, string ownerName, List paths, out double percentFound)
- {
- percentFound = 0;
- int found = 0;
- if (paths == null || paths.Count == 0)
- return false;
-
- foreach (string p in paths) {
- string path = p.SafeTrim ();
- if (String.IsNullOrEmpty (path))
- continue;
- path = Path.Combine (root, path);
- if (File.Exists (path))
- found++;
- else
- Logger.Info ("File '{0}' not found for '{1}'", path, ownerName);
- }
-
- if (found == 0)
- return false;
-
- percentFound = ((double)found * 100.0) / (double)paths.Count;
-
- return true;
- }
-
- internal static AndroidSystemImageAbi StringToAbi (string abi)
- {
- abi = abi.SafeTrim ();
- if (String.IsNullOrEmpty (abi))
- return AndroidComponentInfoSystemImage.DefaultAbi;
-
- if (string.Equals ("arm64-v8a", abi, StringComparison.OrdinalIgnoreCase))
- return AndroidSystemImageAbi.ARM64V8a;
-
- if (string.Equals ("armeabi-v7a", abi, StringComparison.OrdinalIgnoreCase))
- return AndroidSystemImageAbi.ARMV7a;
-
- if (string.Equals ("mips", abi, StringComparison.OrdinalIgnoreCase))
- return AndroidSystemImageAbi.Mips;
-
- if (string.Equals ("x86", abi, StringComparison.OrdinalIgnoreCase))
- return AndroidSystemImageAbi.X86;
-
- if (string.Equals ("x86_64", abi, StringComparison.OrdinalIgnoreCase))
- return AndroidSystemImageAbi.X86_64;
-
- throw new ArgumentOutOfRangeException (String.Format ("Unknown ABI '{0}'", abi));
- }
-
- ///
- /// Utility method to work around Google's decision not to include NDK version in the Android SDK repository manifest v11. Parsing is
- /// performed with the assumption that the NDK archive name follows a certain convention that matches the
- /// android-ndk-r(?<ver>\d+)(?<tag>\w*)-\w* regex.
- ///
- /// manifest XML element for the NDK node
- /// namespace manager initialized for the repository manifest
- /// Base URL to use when the NDK element has only relative URLs
- /// receives the NDK release, if parse is successful (just the number)
- /// receives the NDK release tag, if parse is successful (just the trailing non-digit characters)
- public static void ParseNDKVersionFromGoogleManifest (XmlElement element, XmlNamespaceManager nsmgr, Uri baseURL, out string release, out string releaseTag)
- {
- // Conveniently, google don't include NDK version in the manifest, why bother? We'll need to try to parse
- // the URL for name...
- XmlNodeList urls = element.SelectNodes ("sdk:archives/sdk:archive/sdk:url", nsmgr);
- if (urls == null || urls.Count == 0)
- throw new InvalidOperationException ("Android SDK manifest has NDK element without URLs, unable to determine NDK version");
-
- Uri url = null;
- foreach (XmlNode n in urls) {
- string uri;
- var urlElement = n as XmlElement;
- if (n == null)
- continue;
- uri = urlElement.InnerXml.SafeTrim ();
- if (String.IsNullOrEmpty (uri))
- continue;
- if (!Uri.TryCreate (uri, UriKind.RelativeOrAbsolute, out url))
- continue;
- break;
- }
-
- if (url == null)
- throw new InvalidOperationException ("Android SDK manifest has NDK element without valid URLs, unable to determine NDK version");
-
- if (!url.IsAbsoluteUri)
- url = new Uri (baseURL, url);
-
- string ndkName = Path.GetFileName (url.LocalPath).SafeTrim ();
- if (String.IsNullOrEmpty (ndkName))
- throw new InvalidOperationException ("Android SDK has NDK element without valid archive name in the URL, unable to determine NDK version");
-
- Match match = ndkNameRegex.Match (ndkName);
- if (!match.Success)
- throw new InvalidOperationException ("Android SDK has NDK element with URLs in unsupported format, unable to determine NDK version");
-
- release = match.Groups["ver"].Value;
- releaseTag = match.Groups["tag"].Value;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfo.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfo.cs
deleted file mode 100644
index 16a5ac1d580..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfo.cs
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Base class for all the types containing detailed information about specific component groups/kinds.
- ///
- public abstract class AndroidComponentInfo : IEquatable
- {
- ///
- /// Gets the component type name. The name corresponds to the Google SDK remote package type, not the .NET one.
- ///
- /// Type name
- public string Type { get; }
-
- ///
- /// Gets the printable detailed description of the package type.
- ///
- /// Detailed type description
- public string DetailedDescription => GetDetailedDescription ();
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Type name (required to be not null and not empty).
- protected AndroidComponentInfo (string type)
- {
- if (String.IsNullOrEmpty (type))
- throw new ArgumentException ("must not be null or empty", nameof (type));
-
- Type = type;
- }
-
- ///
- /// Builds and returns the detailed description of the component type.
- ///
- /// Detailed type description
- protected abstract string GetDetailedDescription ();
-
- internal void WritePackageXmlInfo (XmlWriter writer, Repository repository)
- {
- writer.WriteStartElement ("type-details");
- writer.WriteAttributeString ("xmlns", "xsi", null, repository.GetNamespaceUri ("xsi"));
- writer.WriteAttributeString ("xsi", "type", null, Type);
-
- WritePackageXmlInfoDetails (writer, repository);
-
- writer.WriteEndElement (); // type-details
- }
-
- ///
- /// Writes XML representation of the package vendor data.
- ///
- /// XML writer
- /// Vendor data
- protected void WritePackageXmlVendor (XmlWriter writer, PackageVendor vendor)
- {
- writer.WriteStartElement ("vendor");
- writer.WriteStartElement ("id");
- writer.WriteString (vendor?.ID ?? String.Empty);
- writer.WriteEndElement (); // id
-
- writer.WriteStartElement ("display");
- writer.WriteString (vendor?.Display ?? String.Empty);
- writer.WriteEndElement (); // display
- writer.WriteEndElement (); // vendor
- }
-
- ///
- /// Writes XML representation of the package tag data.
- ///
- /// XML Writer
- /// Tag data
- protected void WritePackageXmlTag (XmlWriter writer, PackageTag tag)
- {
- writer.WriteStartElement ("tag");
- writer.WriteStartElement ("id");
- writer.WriteString (tag?.ID ?? String.Empty);
- writer.WriteEndElement (); // id
-
- writer.WriteStartElement ("display");
- writer.WriteString (tag?.Display ?? String.Empty);
- writer.WriteEndElement (); // display
- writer.WriteEndElement (); // tag
- }
-
- internal virtual void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- }
-
- ///
- /// Determines whether the specified is equal
- /// to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to
- /// the current ; otherwise, false.
- public bool Equals (AndroidComponentInfo other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals (this, other))
- return true;
-
- return string.Equals (Type, other.Type, StringComparison.Ordinal);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfo);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
- if (Type == null)
- return hashCode;
-
- return hashCode.XorWith (Type.GetHashCode ());
- }
-
- ///
- /// A helper to compare two strings.
- ///
- /// true, if strings are equal, false otherwise.
- /// first string
- /// second string
- protected bool AreEqual (string one, string two)
- {
- if (one == null)
- return two == null;
-
- return string.Equals (one, two, StringComparison.Ordinal);
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoAddon.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoAddon.cs
deleted file mode 100644
index 4279feef629..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoAddon.cs
+++ /dev/null
@@ -1,179 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about the addon Android component
- ///
- public class AndroidComponentInfoAddon : AndroidComponentInfo, IAndroidApiLevel, IEquatable
- {
- string detailedDescription;
-
- ///
- /// Gets the API level.
- ///
- /// The API level.
- public string ApiLevel { get; }
-
- ///
- /// Gets the platform source code name.
- ///
- /// Platfor code name
- public string CodeName { get; }
-
- ///
- /// Gets the tag associated with the system image
- ///
- /// Package tag
- public PackageTag Tag { get; }
-
- ///
- /// Gets system image vendor information
- ///
- /// System image vendor
- public PackageVendor Vendor { get; }
-
- ///
- /// List of libraries shipped with this addon
- ///
- /// Libraries shipped with this addon
- public IList Libraries { get; }
-
- internal AndroidComponentInfoAddon(string type, string apiLevel, string codeName, PackageTag tag, PackageVendor vendor, IList libraries) : base (type)
- {
- if (String.IsNullOrEmpty (apiLevel))
- throw new ArgumentException ("must not be null or empty", nameof (apiLevel));
-
- ApiLevel = apiLevel;
- CodeName = codeName;
- Tag = tag;
- Vendor = vendor;
- Libraries = libraries;
- }
-
- internal override void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- writer.WriteStartElement ("api-level");
- writer.WriteString (ApiLevel ?? String.Empty);
- writer.WriteEndElement (); // api-level
-
- writer.WriteStartElement ("codename");
- writer.WriteString (CodeName ?? String.Empty);
- writer.WriteEndElement (); // codename
-
- WritePackageXmlVendor (writer, Vendor);
- WritePackageXmlTag (writer, Tag);
-
- writer.WriteStartElement ("libraries");
- if (Libraries != null && Libraries.Count > 0) {
- foreach (PackageLibrary lib in Libraries) {
- if (lib == null)
- continue;
- writer.WriteStartElement ("library");
- writer.WriteAttributeString ("localJarPath", lib?.LocalJarPath ?? String.Empty);
- writer.WriteAttributeString ("name", lib?.Name ?? String.Empty);
- writer.WriteStartElement ("description");
- writer.WriteString (lib?.Description ?? String.Empty);
- writer.WriteEndElement (); // description
- writer.WriteEndElement (); // library
- }
- }
- writer.WriteEndElement (); // libraries
- }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Description
- protected override string GetDetailedDescription ()
- {
- if (detailedDescription != null)
- return detailedDescription;
-
- var desc = new List ();
- if (!String.IsNullOrEmpty (ApiLevel))
- desc.Add ($"API {ApiLevel}");
- if (!String.IsNullOrEmpty (CodeName))
- desc.Add ($"\"{CodeName}\"");
- if (!String.IsNullOrEmpty (Vendor?.Display))
- desc.Add ($"({Vendor.Display})");
-
- if (desc.Count > 0)
- detailedDescription = $"Addon: {String.Join (" ", desc)}";
- else
- detailedDescription = String.Empty;
- return detailedDescription;
- }
-
- ///
- /// Determines whether the specified is
- /// equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal
- /// to the current ; otherwise, false.
- public bool Equals (AndroidComponentInfoAddon other)
- {
- if (!Equals ((AndroidComponentInfo)other))
- return false;
-
- if (!AreEqual (ApiLevel, other.ApiLevel))
- return false;
-
- if (Tag != other.Tag)
- return false;
-
- if (Vendor != other.Vendor)
- return false;
-
- if (!AreEqual (CodeName, other.CodeName))
- return false;
-
- return Libraries.AreEqual (other.Libraries);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoAddon);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (ApiLevel != null)
- hashCode = hashCode.XorWith (ApiLevel.GetHashCode ());
-
- if (CodeName != null)
- hashCode = hashCode.XorWith (CodeName.GetHashCode ());
-
- if (Tag != null)
- hashCode = hashCode.XorWith (Tag.GetHashCode ());
-
- if (Vendor != null)
- hashCode = hashCode.XorWith (Vendor.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoExtra.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoExtra.cs
deleted file mode 100644
index 3e225819f12..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoExtra.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about the extra Android component
- ///
- public class AndroidComponentInfoExtra : AndroidComponentInfo, IEquatable
- {
- string detailedDescription;
-
- ///
- /// Gets system image vendor information
- ///
- /// System image vendor
- public PackageVendor Vendor { get; }
-
- internal AndroidComponentInfoExtra (string type, PackageVendor vendor) : base (type)
- {
- Vendor = vendor;
- }
-
- internal override void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- WritePackageXmlVendor (writer, Vendor);
- }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Description
- protected override string GetDetailedDescription ()
- {
- if (detailedDescription != null)
- return detailedDescription;
-
- var desc = new List ();
- if (!String.IsNullOrEmpty (Vendor?.Display))
- desc.Add ($"({Vendor.Display})");
-
- if (desc.Count > 0)
- detailedDescription = $"Extra: {String.Join (" ", desc)}";
- else
- detailedDescription = String.Empty;
- return detailedDescription;
- }
-
- ///
- /// Determines whether the specified is
- /// equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal
- /// to the current ; otherwise, false.
- public bool Equals (AndroidComponentInfoExtra other)
- {
- if (!Equals ((AndroidComponentInfo)other))
- return false;
-
- if (Vendor != other.Vendor)
- return false;
- return true;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoExtra);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (Vendor != null)
- hashCode = hashCode.XorWith (Vendor.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoGeneric.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoGeneric.cs
deleted file mode 100644
index 71e3debcda3..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoGeneric.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about a generic component.
- ///
-#pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
- public class AndroidComponentInfoGeneric : AndroidComponentInfo, IEquatable
-#pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
- {
- public AndroidComponentInfoGeneric (string type) : base (type)
- {}
-
- ///
- /// Builds and returns the detailed description of the component type. .
- /// This override returns an empty string.
- ///
- /// Detailed type description
- protected override string GetDetailedDescription ()
- {
- return String.Empty;
- }
-
- ///
- /// Determines whether the specified is
- /// equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is
- /// equal to the current ; otherwise, false.
- public bool Equals (AndroidComponentInfoGeneric other)
- {
- return Equals ((AndroidComponentInfo)other);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoGeneric);
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoMaven.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoMaven.cs
deleted file mode 100644
index 66e114dc684..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoMaven.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about the Maven Android component
- ///
- public class AndroidComponentInfoMaven : AndroidComponentInfo, IEquatable
- {
- string detailedDescription;
-
- ///
- /// Gets system image vendor information
- ///
- /// System image vendor
- public PackageVendor Vendor { get; }
-
- internal AndroidComponentInfoMaven (string type, PackageVendor vendor) : base (type)
- {
- Vendor = vendor;
- }
-
- internal override void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- WritePackageXmlVendor (writer, Vendor);
- }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Description
- protected override string GetDetailedDescription ()
- {
- if (detailedDescription != null)
- return detailedDescription;
-
- var desc = new List ();
- if (!String.IsNullOrEmpty (Vendor?.Display))
- desc.Add ($"({Vendor.Display})");
-
- if (desc.Count > 0)
- detailedDescription = $"Maven: {String.Join (" ", desc)}";
- else
- detailedDescription = String.Empty;
- return detailedDescription;
- }
-
- ///
- /// Determines whether the specified is
- /// equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal
- /// to the current ; otherwise, false.
- public bool Equals (AndroidComponentInfoMaven other)
- {
- if (!Equals ((AndroidComponentInfo)other))
- return false;
-
- if (Vendor != other.Vendor)
- return false;
- return true;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoMaven);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (Vendor != null)
- hashCode = hashCode.XorWith (Vendor.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoPlatform.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoPlatform.cs
deleted file mode 100644
index c97d8c889fe..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoPlatform.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about the API level (platform) component
- ///
- public class AndroidComponentInfoPlatform : AndroidComponentInfo, IAndroidApiLevel,IEquatable
- {
- string detailedDescription;
-
- ///
- /// Gets the API level
- ///
- /// The API level.
- public string ApiLevel { get; }
-
- ///
- /// Gets the platform code name.
- ///
- /// Platfor code name
- public string CodeName { get; }
-
- ///
- /// Gets the layout library API version
- ///
- /// Layout library API version
- public string LayoutLibApi { get; }
-
- ///
- /// Description of the API level.
- ///
- /// Platform description.
- public string Description { get; internal set; }
-
- ///
- /// Is the Platform API level a preview?
- ///
- /// if the Platform is not API stable.
- public bool Preview { get; internal set; }
-
- internal AndroidComponentInfoPlatform (string type, string apiLevel, string codeName, string layoutLibApi) : base (type)
- {
- if (String.IsNullOrEmpty (apiLevel))
- throw new ArgumentException ("must not be null or empty", nameof (apiLevel));
- if (String.IsNullOrEmpty (layoutLibApi))
- throw new ArgumentException ("must not be null or empty", nameof (layoutLibApi));
-
- ApiLevel = apiLevel;
- CodeName = codeName;
- LayoutLibApi = layoutLibApi;
- }
-
- internal override void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- writer.WriteStartElement ("api-level");
- writer.WriteString (ApiLevel ?? String.Empty);
- writer.WriteEndElement (); // api-level
-
- writer.WriteStartElement ("codename");
- writer.WriteString (CodeName ?? String.Empty);
- writer.WriteEndElement (); // codename
-
- writer.WriteStartElement ("preview");
- writer.WriteString (Preview.ToString ());
- writer.WriteEndElement (); // preview
-
- writer.WriteStartElement ("layoutlib");
- writer.WriteAttributeString ("api", ApiLevel ?? String.Empty);
- writer.WriteEndElement (); // layoutlib
- }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Description
- protected override string GetDetailedDescription ()
- {
- if (detailedDescription != null)
- return detailedDescription;
-
- var desc = new List ();
- if (!String.IsNullOrEmpty (ApiLevel))
- desc.Add ($"API {ApiLevel}");
- if (!String.IsNullOrEmpty (CodeName))
- desc.Add ($"\"{CodeName}\"");
-
- if (desc.Count > 0)
- detailedDescription = $"Platform: {String.Join (" ", desc)}";
- else
- detailedDescription = String.Empty;
- return detailedDescription;
- }
-
- ///
- /// Determines whether the specified is
- /// equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is
- /// equal to the current ; otherwise, false.
- public bool Equals (AndroidComponentInfoPlatform other)
- {
- if (!Equals ((AndroidComponentInfo)other))
- return false;
-
- if (!AreEqual (ApiLevel, other.ApiLevel))
- return false;
-
- if (!AreEqual (CodeName, other.CodeName))
- return false;
-
- if (Preview != other.Preview)
- return false;
-
- return AreEqual (LayoutLibApi, other.LayoutLibApi);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoPlatform);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (ApiLevel != null)
- hashCode = hashCode.XorWith (ApiLevel.GetHashCode ());
-
- if (CodeName != null)
- hashCode = hashCode.XorWith (CodeName.GetHashCode ());
-
- hashCode = hashCode.XorWith (Preview.GetHashCode ());
-
- if (LayoutLibApi != null)
- hashCode = hashCode.XorWith (LayoutLibApi.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSource.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSource.cs
deleted file mode 100644
index 6fa54158b01..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSource.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about the platform source code Android component
- ///
- public class AndroidComponentInfoSource : AndroidComponentInfo, IAndroidApiLevel, IEquatable
- {
- string detailedDescription;
-
- ///
- /// Gets the API level
- ///
- /// The API level.
- public string ApiLevel { get; }
-
- ///
- /// Gets the platform source code name.
- ///
- /// Platfor code name
- public string CodeName { get; }
-
- internal AndroidComponentInfoSource (string type, string apiLevel, string codeName) : base (type)
- {
- if (String.IsNullOrEmpty (apiLevel))
- throw new ArgumentException ("must not be null or empty", nameof (apiLevel));
-
- ApiLevel = apiLevel;
- CodeName = codeName;
- }
-
- internal override void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- writer.WriteStartElement ("api-level");
- writer.WriteString (ApiLevel ?? String.Empty);
- writer.WriteEndElement (); // api-level
-
- writer.WriteStartElement ("codename");
- writer.WriteString (CodeName ?? String.Empty);
- writer.WriteEndElement (); // codename
- }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Description
- protected override string GetDetailedDescription ()
- {
- if (detailedDescription != null)
- return detailedDescription;
-
- var desc = new List ();
- if (!String.IsNullOrEmpty (ApiLevel))
- desc.Add ($"API {ApiLevel}");
- if (!String.IsNullOrEmpty (CodeName))
- desc.Add ($"\"{CodeName}\"");
-
- if (desc.Count > 0)
- detailedDescription = $"Platform Source: {String.Join (" ", desc)}";
- else
- detailedDescription = String.Empty;
- return detailedDescription;
- }
-
- ///
- /// Determines whether the specified is
- /// equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal
- /// to the current ; otherwise, false.
- public bool Equals (AndroidComponentInfoSource other)
- {
- if (!Equals ((AndroidComponentInfo)other))
- return false;
-
- if (!AreEqual (ApiLevel, other.ApiLevel))
- return false;
-
- return AreEqual (CodeName, other.CodeName);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoSource);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (ApiLevel != null)
- hashCode = hashCode.XorWith (ApiLevel.GetHashCode ());
-
- if (CodeName != null)
- hashCode = hashCode.XorWith (CodeName.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSystemImage.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSystemImage.cs
deleted file mode 100644
index 9b593e82640..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSystemImage.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Information about the system image Android component
- ///
- public class AndroidComponentInfoSystemImage : AndroidComponentInfo, IAndroidApiLevel, IEquatable
- {
- ///
- /// The default architecture
- ///
- public static readonly AndroidSystemImageAbi DefaultAbi = AndroidSystemImageAbi.X86;
-
- string detailedDescription;
-
- ///
- /// System image ABI
- ///
- /// System image ABI
- public AndroidSystemImageAbi Abi { get; }
-
- ///
- /// Gets the textual version of the system image ABI
- ///
- /// Name of the ABI
- public string AbiName { get; }
-
- ///
- /// Gets the API level.
- ///
- /// The API level.
- public string ApiLevel { get; }
-
- ///
- /// Gets the platform source code name.
- ///
- /// Platfor code name
- public string CodeName { get; }
-
- ///
- /// Gets the tag associated with the system image
- ///
- /// Package tag
- public PackageTag Tag { get; }
-
- ///
- /// Gets system image vendor information
- ///
- /// System image vendor
- public PackageVendor Vendor { get; }
-
- internal AndroidComponentInfoSystemImage (string type, AndroidSystemImageAbi abi, string abiName, string apiLevel, string codeName, PackageTag tag, PackageVendor vendor) : base (type)
- {
- if (String.IsNullOrEmpty (apiLevel))
- throw new ArgumentException ("must not be null or empty", nameof (apiLevel));
-
- Abi = abi;
- AbiName = abiName;
- ApiLevel = apiLevel;
- CodeName = codeName;
- Tag = tag;
- Vendor = vendor;
- }
-
- internal override void WritePackageXmlInfoDetails (XmlWriter writer, Repository repository)
- {
- writer.WriteStartElement ("api-level");
- writer.WriteString (ApiLevel ?? String.Empty);
- writer.WriteEndElement (); // api-level
-
- writer.WriteStartElement ("codename");
- writer.WriteString (CodeName ?? String.Empty);
- writer.WriteEndElement (); // codename
-
- WritePackageXmlTag (writer, Tag);
- WritePackageXmlVendor (writer, Vendor);
-
- writer.WriteStartElement ("abi");
- writer.WriteString (GetAbiManifestString ());
- writer.WriteEndElement (); // abi
- }
-
- public string GetAbiManifestString ()
- {
- return String.IsNullOrEmpty (AbiName) ? Abi.ToString ().ToLowerInvariant () : AbiName.ToLowerInvariant ();
- }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Description
- protected override string GetDetailedDescription ()
- {
- if (detailedDescription != null)
- return detailedDescription;
-
- var desc = new List ();
- desc.Add ($"{Abi}");
- if (!String.IsNullOrEmpty (ApiLevel))
- desc.Add ($"API {ApiLevel}");
- if (!String.IsNullOrEmpty (CodeName))
- desc.Add ($"\"{CodeName}\"");
- if (!String.IsNullOrEmpty (Vendor?.Display))
- desc.Add ($"({Vendor.Display})");
-
- detailedDescription = $"System Image: {String.Join (" ", desc)}";
- return detailedDescription;
- }
-
- ///
- /// Determines whether the specified
- /// is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is
- /// equal to the current ;
- /// otherwise, false.
- public bool Equals (AndroidComponentInfoSystemImage other)
- {
- if (!Equals ((AndroidComponentInfo)other))
- return false;
-
- if (Abi != other.Abi)
- return false;
-
- if (!AreEqual (ApiLevel, other.ApiLevel))
- return false;
-
- if (Tag != other.Tag)
- return false;
-
- if (Vendor != other.Vendor)
- return false;
-
- if (!AreEqual (CodeName, other.CodeName))
- return false;
-
- return true;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as AndroidComponentInfoSystemImage);
- }
-
- ///
- /// Serves as a hash function for a
- /// object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (ApiLevel != null)
- hashCode = hashCode.XorWith (ApiLevel.GetHashCode ());
-
- if (CodeName != null)
- hashCode = hashCode.XorWith (CodeName.GetHashCode ());
-
- if (Tag != null)
- hashCode = hashCode.XorWith (Tag.GetHashCode ());
-
- if (Vendor != null)
- hashCode = hashCode.XorWith (Vendor.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatus.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatus.cs
deleted file mode 100644
index 0df9722be07..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatus.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Android component status. ,
- ///
- ///
- public enum AndroidComponentStatus
- {
- ///
- /// Component detection started
- ///
- DetectionStarted,
-
- ///
- /// Component detection completed
- ///
- DetectionEnded,
-
- ///
- /// Component installation started
- ///
- InstallationStarted,
-
- ///
- /// Component installation ended
- ///
- InstallationEnded,
-
- ///
- /// Component archive unpacking started
- ///
- UnpackingStarted,
-
- ///
- /// Component archive unpacking ended
- ///
- UnpackingEnded,
-
- ///
- /// Component removal started
- ///
- RemovalStarted,
-
- ///
- /// Component removal ended
- ///
- RemovalEnded,
-
- ///
- /// Component verification started
- ///
- VerificationStarted,
-
- ///
- /// Component verification started
- ///
- VerificationEnded,
-
- ///
- /// Component metadata (presence, version etc) changed
- ///
- MetadataUpdated
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatusChangeEventArgs.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatusChangeEventArgs.cs
deleted file mode 100644
index d2891ecff56..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatusChangeEventArgs.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Android component status change event arguments.
- ///
- public class AndroidComponentStatusChangeEventArgs : EventArgs
- {
- ///
- /// Gets the new component status.
- ///
- /// The status.
- public AndroidComponentStatus Status { get; }
-
- ///
- /// Gets the component whose status changed
- ///
- /// The component.
- public IAndroidComponent Component { get; }
-
- internal AndroidComponentStatusChangeEventArgs (AndroidComponentStatus status, IAndroidComponent component)
- {
- Component = component ?? throw new ArgumentNullException (nameof (component));
- Status = status;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidLicensesStorage.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidLicensesStorage.cs
deleted file mode 100644
index d092e906ff4..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidLicensesStorage.cs
+++ /dev/null
@@ -1,457 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using Xamarin.Installer.AndroidSDK.Properties;
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// AndroidLicensesStorage class has all the protocol to check if a License was accepted
- ///
- public class AndroidLicensesStorage : ILicensesStorage
- {
- ///
- /// Returns the path where licenses acceptance are stored
- ///
- /// Android Sdk path
- /// Directory path where the licenses acceptance are stored
- protected virtual string GetLicensesPath(string androidSdkPath)
- {
- return string.IsNullOrWhiteSpace(androidSdkPath) || !Directory.Exists(androidSdkPath) ? null : Path.Combine(androidSdkPath, "licenses");
- }
-
- ///
- /// Returns if the license was accepted in this Android SDK
- ///
- /// Android Sdk path
- /// license to check
- /// true if the license is accepted, false otherwise
- public bool IsLicenseAccepted(string androidSdkPath, License license)
- {
- if (license == null || string.IsNullOrEmpty(license.ID))
- return false;
-
- var localLicensesPath = GetLicensesPath(androidSdkPath);
- if(string.IsNullOrEmpty(localLicensesPath))
- return false;
-
- var licensePath = Path.Combine(localLicensesPath, license.ID);
- if (!File.Exists(licensePath))
- return false;
-
- var storedLicenseHash = GetLicenseHash(licensePath);
- return !string.IsNullOrEmpty(storedLicenseHash);
- }
-
- protected virtual string GetLicenseHash(License license)
- {
- if (string.IsNullOrEmpty(license?.Text))
- {
- return null;
- }
-
- var licenseText = license.Text;
-#pragma warning disable CA5350
- using (var hashAlgorithm = SHA1.Create()) // CodeQL [SM02196] Used to verify checksums provided by an external party.
- {
- var bytes = Encoding.UTF8.GetBytes(licenseText);
- var hash = string.Concat(hashAlgorithm.ComputeHash(bytes).Select(x => x.ToString("x2")));
- return hash;
- }
-#pragma warning restore CA5350
- }
-
- protected virtual string GetLicenseHash(string licensePath)
- {
- return string.IsNullOrWhiteSpace(licensePath) || !File.Exists(licensePath) ? null : File.ReadAllText(licensePath);
- }
-
- ///
- /// Accept licenses using local storage
- ///
- /// Android Sdk path
- /// Java Sdk path
- /// specific cmdLine-tools path to use
- /// list of licenses to accept
- /// cancellation token
- /// log file path
- /// if true, throws an exception if license validation fails
- public Task AcceptLicensesAsync(
- string androidSdkPath,
- string javaSdkPath,
- string cmdLineToolsPath,
- IEnumerable licenses,
- CancellationToken token,
- string logPath = null,
- bool throwsErrorIfValidationFailed = false)
- {
- return Task.Run(async () =>
- {
- var progress = new AggregateProgressSink(logPath);
-
- try
- {
- var error = ValidateAcceptLicensesArguments(androidSdkPath, javaSdkPath, cmdLineToolsPath, licenses, progress);
- if (!string.IsNullOrEmpty(error))
- {
- if (throwsErrorIfValidationFailed)
- {
- throw new NotSupportedException(error);
- }
- else
- {
- return;
- }
- }
-
- var licenseIDs = licenses.Select(x => x.ID).Distinct();
- progress.Report($"Licenses to be accepted: {string.Join("|", licenseIDs)}");
-
- // run sdkmanager from cmdline-tools to accept the licenses
- await WriteGoogleLicensesAsync(androidSdkPath, javaSdkPath, cmdLineToolsPath, licenses, token, progress);
-
- // it is required because the hash can be different than the generated by google
- // Xamarin feed licenses text can be not in sync with latest google feed licenses text
- // Xamarin feed is generated/updated on each VS release,
- // and VS releases are not in sync with the cadence of updates of Google feed
- WriteVSLicenses(androidSdkPath, licenses, token, progress);
- }
- finally
- {
- progress.Dispose();
- }
- }, token);
- }
-
- string ValidateAcceptLicensesArguments(
- string androidSdkPath,
- string javaSdkPath,
- string cmdLineToolsPath,
- IEnumerable licenses,
- AggregateProgressSink progress)
- {
- if (!licenses.Any())
- {
- progress?.Report("Android licenses acceptance discarded, no licenses to accept");
- return string.Empty;
- }
-
- if (string.IsNullOrEmpty(androidSdkPath) || !Directory.Exists(androidSdkPath))
- {
- progress?.Report(Resources.AccepLicensesFailedAndroidSDKNotFound);
- return Resources.AccepLicensesFailedAndroidSDKNotFound;
- }
-
- if (string.IsNullOrEmpty(javaSdkPath) || !Directory.Exists(javaSdkPath))
- {
- progress?.Report(Resources.AccepLicensesFailedJavaSDKNotFound);
- return Resources.AccepLicensesFailedJavaSDKNotFound;
- }
-
- if (string.IsNullOrEmpty(cmdLineToolsPath))
- {
- progress?.Report(Resources.AccepLicensesFailedCMDLineToolsNotFound);
- return Resources.AccepLicensesFailedCMDLineToolsNotFound;
- }
-
- var cmdLineToolsPropertiesFilePath = Path.Combine(cmdLineToolsPath, "source.properties");
- if (!File.Exists(cmdLineToolsPropertiesFilePath))
- {
- progress?.Report(Resources.AccepLicensesFailedCMDLineToolsNotFound);
- return Resources.AccepLicensesFailedCMDLineToolsNotFound;
- }
-
- return string.Empty;
- }
-
- protected void WriteVSLicenses(
- string androidSdkPath,
- IEnumerable licenses,
- CancellationToken token,
- AggregateProgressSink progress)
- {
- if (!licenses.Any())
- return;
-
- // creates local licenses storage folder
- if (token.IsCancellationRequested)
- return;
-
- progress.Report("Running local accept licenses process");
-
- try
- {
- var licensesPath = GetLicensesPath(androidSdkPath);
- if (!Directory.Exists(licensesPath))
- Directory.CreateDirectory(licensesPath);
-
- // save licenses
- var licensesToAccept = licenses.Where(license => !string.IsNullOrEmpty(license.ID)).GroupBy(license => license);
- foreach (var l in licensesToAccept)
- {
- if (token.IsCancellationRequested)
- return;
-
- var androidLicense = l.Key;
-
- var licensePath = Path.Combine(licensesPath, androidLicense.ID);
- var licenseHash = GetLicenseHash(androidLicense);
-
- WriteLicenseHash(licensePath, licenseHash);
- }
-
- progress.Report("Running local accept licenses process completed");
- }
- catch (Exception ex)
- {
- progress.Report($"Running local accept licenses process failed: {ex.Message}");
- }
- }
-
- protected virtual void WriteLicenseHash(string licensePath, string licenseHash)
- {
- // same format as generated by google sdkmanager licenses command
- var sb = new StringWriter();
-
- if (File.Exists(licensePath))
- {
- sb.WriteLine(""); // enter for previous line
- }
-
- sb.WriteLine(""); // force empty line
- sb.WriteLine(licenseHash); // hash
-
- File.AppendAllText(licensePath, sb.ToString());
- }
-
- protected async Task WriteGoogleLicensesAsync(
- string androidSdkPath,
- string javaSdkPath,
- string cmdLineToolsPath,
- IEnumerable licenses,
- CancellationToken token,
- AggregateProgressSink progress)
- {
- progress.Report("Running sdkmanager --licenses --verbose");
-
- var standardOutput = progress.ForOutputs;
- var standardError = progress.ForErrors;
-
- var sdkManagerApp = string.Empty;
- switch (AndroidSDKContext.Instance.Platform)
- {
- case AndroidSDKPlatform.Linux:
- case AndroidSDKPlatform.Mac:
- sdkManagerApp = "sdkmanager";
- break;
- case AndroidSDKPlatform.Windows:
- sdkManagerApp = "sdkmanager.bat";
- break;
-
- default:
- throw new InvalidOperationException("Unsupported platform");
- }
-
- var processStartInfo = new ProcessStartInfo(fileName: Path.Combine(cmdLineToolsPath, "bin", sdkManagerApp), "--licenses --verbose");
- processStartInfo.WorkingDirectory = Path.Combine(cmdLineToolsPath, "bin");
- processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
- processStartInfo.UseShellExecute = false;
- processStartInfo.RedirectStandardError = true;
- processStartInfo.RedirectStandardInput = true;
- processStartInfo.RedirectStandardOutput = true;
- processStartInfo.CreateNoWindow = true;
-
- if (!string.IsNullOrEmpty(javaSdkPath))
- {
- // Use short path (8.3 format) for JAVA_HOME on Windows to avoid batch script parsing issues
- // when paths contain parentheses like "Program Files (x86)" which break CMD.exe IF/FOR blocks.
- // See: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/2632833
- var javaHomePath = AndroidSDKContext.Instance.Platform == AndroidSDKPlatform.Windows
- ? CommonUtilities.GetShortPath(javaSdkPath)
- : javaSdkPath;
- processStartInfo.EnvironmentVariables["JAVA_HOME"] = javaHomePath;
- }
-
- var process = new Process();
- process.StartInfo = processStartInfo;
-
- bool matchLicenseId = false;
- var loadingLocalRepository = true;
-
- var inputAnswers = new ConcurrentQueue();
- inputAnswers.Enqueue("Y"); // to accept the review "Review licenses that have not been accepted (y/N)?"
-
- if (processStartInfo.RedirectStandardOutput)
- {
- process.OutputDataReceived += (sender, e) =>
- {
- if (e.Data != null)
- {
- standardOutput?.Report(e.Data);
-
- if (e.Data.Contains("(y/N)?"))
- {
- // when the message "Review licenses that have not been accepted (y/N)?" is reported the loading phase and display all licenses text ends
- loadingLocalRepository = false;
- }
-
- // try to match the license id from message: "License {id}:"
- if (loadingLocalRepository && licenses.Any(x => e.Data.Contains($"{x.ID}:")))
- {
- matchLicenseId = true;
- }
-
- if (loadingLocalRepository && e.Data.Trim().Equals("Accepted"))
- {
- // reset the match when an accepted license is detected
- matchLicenseId = false;
- }
-
- if (loadingLocalRepository && e.Data.Trim().Contains("Not yet accepted"))
- {
- // enqueue a Y/N answer
- if (matchLicenseId)
- {
- matchLicenseId = false;
- inputAnswers.Enqueue("Y");
- }
- else
- {
- inputAnswers.Enqueue("N");
- }
- }
- }
- };
- }
-
- if (processStartInfo.RedirectStandardError)
- {
- process.ErrorDataReceived += (sender, e) =>
- {
- standardError?.Report(e.Data);
- };
- }
-
- process.Start();
-
- if (processStartInfo.RedirectStandardOutput)
- process.BeginOutputReadLine();
-
- if (processStartInfo.RedirectStandardError)
- process.BeginErrorReadLine();
-
- process.StandardInput.AutoFlush = true;
-
- while (!process.HasExited)
- {
- if (token.IsCancellationRequested)
- {
- process.Kill();
- }
- else
- {
- try
- {
- if (inputAnswers.Any() && inputAnswers.TryDequeue(out var inputAnswer))
- {
- await process.StandardInput.WriteLineAsync(inputAnswer);
- }
- }
- catch (Exception e)
- {
- progress.Report(e.Message);
- }
- }
- }
-
- if (!token.IsCancellationRequested && process.ExitCode > 0)
- {
- var errorMessage = $"""
- {Resources.GoogleAccepLicensesFailed}.
- Exit code: {process.ExitCode}.
- Android SDK: '{androidSdkPath}'.
- Java SDK: '{javaSdkPath}'.
- Command-line tools: '{cmdLineToolsPath}'.
- """;
-
- if (!string.IsNullOrEmpty(standardError.Errors))
- {
- errorMessage += $" Errors: {standardError.Errors}";
- }
-
- progress.Report(errorMessage);
- throw new Exception(errorMessage);
- }
- }
-
- protected class AggregateProgressSink : IProgress, IDisposable
- {
- private StreamWriter writer;
-
- public AggregateProgressSink(string logPath)
- {
- this.ForOutputs = new OutputProgressSink(this);
- this.ForErrors = new ErrorProgressSink(this);
- this.writer = string.IsNullOrEmpty(logPath) ? null : new StreamWriter(logPath);
- }
-
- public OutputProgressSink ForOutputs { get; private set; }
-
- public ErrorProgressSink ForErrors { get; private set; }
-
- public void Report(string value)
- {
- this.writer?.WriteLine(value);
- }
-
- public void Dispose()
- {
- this.writer?.Close();
- this.writer = null;
- }
- }
-
- protected class OutputProgressSink : IProgress
- {
- private IProgress fileSink;
-
- public OutputProgressSink(IProgress fileSink)
- {
- this.fileSink = fileSink;
- }
-
- public void Report(string value)
- {
- this.fileSink.Report(value);
- }
- }
-
- protected class ErrorProgressSink : IProgress
- {
- private readonly StringBuilder allErrors = new StringBuilder();
- private readonly IProgress fileSink;
-
- public ErrorProgressSink(IProgress fileSink)
- {
- this.fileSink = fileSink;
- }
-
- public string Errors => this.allErrors.ToString();
-
- public void Report(string value)
- {
- this.fileSink.Report(value);
- this.allErrors.AppendLine(value);
- }
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Archive.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Archive.cs
deleted file mode 100644
index 00bdd36914e..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Archive.cs
+++ /dev/null
@@ -1,276 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Security.Cryptography;
-
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a single package archive
- ///
- public class Archive : ArchiveBase, IEquatable
- {
- ///
- /// Gets the collection of patches for this archive. This library currently does not support applying these
- /// patches, instead it always downloads the full archive from the specified URL
- ///
- /// The list of patches (if any)
- public IList Patches { get; set; }
-
- ///
- /// Gets a value indicating whether this was downloaded.
- /// true will be returned only if is set and refers to an existing file.
- /// Checksum is not verified when reading this property.
- ///
- /// true if archive was downloaded; otherwise, false.
- public bool WasDownloaded => !String.IsNullOrEmpty(GetDownloadPath(false));
-
- ///
- /// Gets or sets the downloaded file path. The installer assembly resets this property to null when returning archive
- /// instance from but otherwise it is responsibilty of the client code
- /// to set the property to a valid path of a downloaded archive.
- ///
- /// The downloaded file path.
- public string DownloadedFilePath { get; set; }
-
- ///
- /// Gets the Android component that owns this Archive, if any
- ///
- /// The owner component.
- public IAndroidComponent Owner { get; internal set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The host operating system.
- public Archive(string hostOS) : base(hostOS)
- {
- }
-
- ///
- /// Verifies whether the downloaded archive is indeed found on disk and whether it passes checksum verification
- /// (if is true).
- ///
- /// true, if downloaded archive is valid, false otherwise.
- /// If set to true verify the archive checksum.
- public bool IsDownloadValid(bool verifyChecksum = true)
- {
- string filePath = GetDownloadPath();
- if (String.IsNullOrEmpty(filePath))
- return false;
-
- if (!verifyChecksum)
- return true;
-
- if (!VerifyChecksum(filePath, ChecksumType, Checksum, Url))
- {
- Logger.Warning($"Downloaded file '{DownloadedFilePath}' fails checksum verification for Android SDK archive '{Url}'");
- return false;
- }
-
- return true;
- }
-
- ///
- /// Verifies against using the algorithm
- /// named by . The algorithm string is normalized (trimmed,
- /// lowercased, with a single hyphen stripped) so values such as "sha-1" / "SHA1" / "sha-256"
- /// are all accepted. A null or empty algorithm defaults to SHA-1 to match the historical
- /// manifest behavior. Unknown algorithms or hash-length mismatches log a warning and return
- /// false rather than silently falling back.
- ///
- internal static bool VerifyChecksum(string filePath, string algorithm, string hash, Uri url)
- {
- string normalized = (algorithm ?? string.Empty).Trim().ToLowerInvariant().Replace("-", string.Empty);
- string trimmedHash = hash?.Trim();
-
- if (string.IsNullOrEmpty(normalized) || normalized == "sha1")
- {
- if (!string.IsNullOrEmpty(trimmedHash) && trimmedHash.Length != 40)
- {
- Logger.Warning($"Checksum for Android SDK archive '{url}' is declared as SHA-1 but its length ({trimmedHash.Length}) is not 40 hex characters");
- return false;
- }
- return CheckSHA1(filePath, trimmedHash);
- }
-
- if (normalized == "sha256")
- {
- if (!string.IsNullOrEmpty(trimmedHash) && trimmedHash.Length != 64)
- {
- Logger.Warning($"Checksum for Android SDK archive '{url}' is declared as SHA-256 but its length ({trimmedHash.Length}) is not 64 hex characters");
- return false;
- }
- return CheckSHA256(filePath, trimmedHash);
- }
-
- Logger.Warning($"Unknown checksum algorithm '{algorithm}' declared for Android SDK archive '{url}'; refusing to verify");
- return false;
- }
-
- ///
- /// Checks whether the downloaded archive is valid (verifying the checksum if is true) and
- /// whether it can be installed on the current system.
- ///
- /// true, if the archive is installable on the current system, false otherwise.
- /// If set to true verify checksum.
- /// If set to true verify archive host os.
- public bool IsInstallable(bool verifyChecksum = true, bool checkPlatform = true)
- {
- return (!checkPlatform || IsValidForSystem()) && IsDownloadValid(verifyChecksum);
- }
-
- ///
- /// Checks whether archive's platform and host-arch are matching the current system.
- ///
- ///
- public override bool IsValidForSystem()
- {
- if (!IsPlatformValid())
- return false;
-
- if (IsHostArchValid())
- return true;
-
- // custom logic: windows emulator only have x64 archives
- return Platform == AndroidSDKPlatform.Windows &&
- (string.IsNullOrEmpty(Owner?.FileSystemPath) || (Owner.FileSystemPath.StartsWith("emulator") && HostArch.StartsWith("x")));
- }
-
- string GetDownloadPath(bool logMissing = true)
- {
- string filePath = DownloadedFilePath?.Trim();
- if (String.IsNullOrEmpty(filePath))
- return null;
-
- if (!File.Exists(filePath))
- {
- if (logMissing)
- Logger.Info($"Downloaded file '{DownloadedFilePath}' not found for Android SDK archive '{Url}'");
- return null;
- }
-
- return filePath;
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Security", "CA5350:Do Not Use Weak Cryptographic Algorithms", Justification = "Used to verify checksums provided by an external party.")]
- static bool CheckSHA1(string filePath, string sha1hash)
- {
- sha1hash = sha1hash?.Trim();
- if (String.IsNullOrEmpty(sha1hash) || sha1hash.Length != 40)
- return false;
-
- using (var sha1 = SHA1.Create())// CodeQL [SM02196] Receiving external information: Used to verify checksums provided by an external party
- {
- using (var fs = File.OpenRead(filePath))
- {
- byte[] hash = sha1.ComputeHash(fs);
- string shash = BitConverter.ToString(hash).Replace("-", "");
- return string.Equals(shash, sha1hash, StringComparison.OrdinalIgnoreCase);
- }
- }
- }
-
- static bool CheckSHA256(string filePath, string sha256hash)
- {
- sha256hash = sha256hash?.Trim();
- if (String.IsNullOrEmpty(sha256hash) || sha256hash.Length != 64)
- return false;
-
- using (var sha256 = SHA256.Create())
- {
- using (var fs = File.OpenRead(filePath))
- {
- byte[] hash = sha256.ComputeHash(fs);
- string shash = BitConverter.ToString(hash).Replace("-", "");
- return string.Equals(shash, sha256hash, StringComparison.OrdinalIgnoreCase);
- }
- }
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals(Archive other)
- {
- if (!base.Equals(other))
- return false;
-
- if (Patches == null)
- {
- if (other.Patches != null)
- return false;
- }
- else
- {
- if (other.Patches == null)
- return false;
- if (!ComparePatches(other.Patches))
- return false;
- }
-
- return true;
- }
-
- bool ComparePatches(IList otherPatches)
- {
- if (Patches.Count != otherPatches.Count)
- return false;
-
- for (int i = 0; i < otherPatches.Count; i++)
- {
- ArchivePatch localPatch = Patches[i];
- ArchivePatch otherPatch = otherPatches[i];
-
- if (localPatch == null)
- {
- if (otherPatch != null)
- return false;
- continue;
- }
-
- if (otherPatch == null)
- return false;
-
- if (!localPatch.Equals(otherPatch))
- return false;
- }
-
- return true;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals(Object obj)
- {
- return Equals(obj as Archive);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode()
- {
- int hashCode = base.GetHashCode();
- return hashCode.XorWith(Patches?.GetHashCode());
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchiveBase.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchiveBase.cs
deleted file mode 100644
index 5ace55a68f3..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchiveBase.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a single package archive
- ///
- public abstract class ArchiveBase : IArchive
- {
- public ArchiveBase(string hostOS)
- {
- HostOS = hostOS;
- Platform = AndroidUtilities.GetPlatformFromOS(hostOS);
- }
-
- ///
- /// Gets the archive size
- ///
- /// Archive size
- public ulong Size { get; set; }
-
- ///
- /// Gets the checksum of the archive. The algorithm is identified by ;
- /// when is null or empty the checksum is assumed to be SHA-1.
- ///
- /// Checksum digest as a hex string
- public string Checksum { get; set; }
-
- ///
- /// Gets the checksum algorithm declared by the manifest for ,
- /// for example sha1 or sha256. A null or empty value means SHA-1 (the historical default).
- ///
- /// Checksum algorithm name
- public string ChecksumType { get; set; }
-
- ///
- /// Gets the archive URL
- ///
- /// Archive URL
- public Uri Url { get; set; }
-
- ///
- /// Gets the target (host) operating system of the archive (if any)
- ///
- /// Host operating system
- public string HostOS { get; }
-
- ///
- /// Mapping of into one of the enumeration members
- ///
- /// Archive platform.
- public AndroidSDKPlatform Platform { get; }
-
- ///
- /// Native word size of the host operating system.
- ///
- /// Host operating system word size
- public uint HostBits { get; set; }
-
- ///
- /// CPU Architecture of the host operating system.
- ///
- /// Host operating CPU architecture
- public string HostArch { get; set; }
-
- ///
- /// Checks whether archive's platform and host-arch are matching the current system.
- ///
- ///
- public abstract bool IsValidForSystem();
-
- ///
- /// Checks whether archive's platform is matching the current system.
- ///
- ///
- public virtual bool IsPlatformValid()
- {
- return (Platform == AndroidSDKPlatform.Any || Platform == AndroidSDKContext.Instance.Platform);
- }
-
- ///
- /// Checks whether archive's host-arch is matching the current system.
- ///
- ///
- public virtual bool IsHostArchValid()
- {
- return string.IsNullOrEmpty(HostArch) || HostArch == AndroidSDKContext.Instance.HostArch;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals(IArchive other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals(this, other))
- return true;
-
- if (!string.Equals(Checksum, other.Checksum, StringComparison.Ordinal))
- return false;
-
- if (HostBits != other.HostBits)
- return false;
-
- if (!string.Equals(HostOS, other.HostOS, StringComparison.Ordinal))
- return false;
-
- if (Size != other.Size)
- return false;
-
- if (Url != other.Url)
- return false;
-
- return true;
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode()
- {
- int hashCode = base.GetHashCode();
- hashCode = hashCode.XorWith(HostBits.GetHashCode());
- hashCode = hashCode.XorWith(HostOS?.GetHashCode());
- hashCode = hashCode.XorWith(Size.GetHashCode());
- return hashCode.XorWith(Url?.GetHashCode());
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchivePatch.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchivePatch.cs
deleted file mode 100644
index ae1324e37d9..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchivePatch.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Represents a single archive patch instance.
- ///
- public sealed class ArchivePatch : IEquatable
- {
- ///
- /// Gets the revision of the parent archive this patch must be applied to.
- ///
- /// Base archive revision
- public AndroidRevision BasedOn { get; internal set; }
-
- ///
- /// Gets the patch download size
- ///
- /// The size.
- public ulong Size { get; internal set; }
-
- ///
- /// Gets the checksum of the patch. The algorithm is identified by ;
- /// when is null or empty the checksum is assumed to be SHA-1.
- ///
- /// Checksum digest as a hex string
- public string Checksum { get; internal set; }
-
- ///
- /// Gets the checksum algorithm declared by the manifest for ,
- /// for example sha1 or sha256. A null or empty value means SHA-1.
- ///
- /// Checksum algorithm name
- public string ChecksumType { get; internal set; }
-
- ///
- /// Gets the patch URL
- ///
- /// Archive URL
- public Uri Url { get; internal set; }
-
- internal ArchivePatch ()
- {
- }
-
- ///
- /// Determines whether the specified is equal to the
- /// current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the
- /// current ; otherwise, false.
- public bool Equals (ArchivePatch other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals (this, other))
- return true;
-
- if (Size != other.Size)
- return false;
-
- if (Url != other.Url)
- return false;
-
- if (!string.Equals (Checksum, other.Checksum, StringComparison.Ordinal))
- return false;
-
- if (BasedOn == null) {
- if (other.BasedOn != null)
- return false;
- } else if (BasedOn != other.BasedOn)
- return false;
-
- return true;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as ArchivePatch);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- hashCode = hashCode.XorWith (Size.GetHashCode ());
- hashCode = hashCode.XorWith (Url?.GetHashCode ());
- hashCode = hashCode.XorWith (Checksum?.GetHashCode ());
- return hashCode.XorWith (BasedOn?.GetHashCode ());
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/BasePackage.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/BasePackage.cs
deleted file mode 100644
index 6cd008f8ebc..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/BasePackage.cs
+++ /dev/null
@@ -1,911 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2018, Microsoft Corp. (https://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Xml;
-using System.Xml.Linq;
-using Xamarin.Installer.Common;
-using IOPath = System.IO.Path;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public abstract class BasePackage : IEquatable, IAndroidComponent, IAndroidComponentInternal
- {
- protected Repository Repository { get; }
- protected IList OriginalArchives { get; }
-
- public event EventHandler StatusChanged;
-
- public abstract AndroidComponentType ComponentType { get; }
- public Guid UniqueID { get; } = Guid.NewGuid();
- public bool IsEssential { get; set; }
- public bool IgnoreFailure { get; set; }
- public bool Present { get; set; }
- public bool NeedsUpdate { get; set; }
- public string Path { get; set; }
- public string FileSystemPath { get; set; }
- public bool Obsolete { get; set; }
- public bool Preview => GetPreview();
- public AndroidComponentInfo Info { get; set; }
- public AndroidRevision Revision { get; set; }
- public AndroidRevision InstalledRevision { get; set; }
- public string DisplayName { get; set; }
- public string DetailedDescription => GetDetailedDescription();
- public IList Dependencies { get; set; }
- public abstract Channel Channel { get; }
- public IList Archives { get; protected set; }
- public License License => Repository.GetLicense(LicenseID);
- public string LicenseID { get; set; }
- public Uri ManifestURL { get; }
- public IXmlLineInfo Location { get; }
- public bool ForceInstallation { get; set; }
-
- public BasePackage(Repository repository, Uri manifestURL, IXmlLineInfo location, IList archives)
- {
- Repository = repository ?? throw new ArgumentNullException(nameof(repository));
- ManifestURL = manifestURL ?? throw new ArgumentNullException(nameof(manifestURL));
- Location = location;
- OriginalArchives = archives;
- if (archives == null || archives.Count == 0)
- return;
-
- foreach (Archive archive in archives)
- {
- if (archive == null)
- continue;
- archive.Owner = this;
- }
- }
-
- public IEnumerable SupportedPlatforms
- {
- get
- {
- //todo OriginalArchives?
- foreach (var archive in Archives)
- yield return archive.Platform;
- }
- }
-
- public bool IsPlatformSpecific
- {
- get
- {
- return !Archives.Any(a => a.Platform == AndroidSDKPlatform.Any || a.Platform == AndroidSDKPlatform.Unknown);
- }
- }
-
- ///
- /// NOTE: Using in ManifestGenerator only.
- ///
- ///
- public void ExcludePlatform(AndroidSDKPlatform platform)
- {
- Archives = Archives.Where(a => a.Platform != platform).ToList();
- Dependencies = Dependencies.Where(d => d.Platform != platform).ToList();
- }
-
- protected void PopulatePlatformArchives(bool includeAllArchives)
- {
- var alist = new List();
- AndroidSDKPlatform platform = AndroidSDKContext.Instance.Platform;
-
- foreach (Archive archive in OriginalArchives)
- {
- if (archive == null || (!includeAllArchives && !archive.IsValidForSystem()))
- continue;
- alist.Add(archive);
- }
-
-
- bool IsBitsValid(uint bits) => ((bits == 64) == CommonUtilities.Helpers.Is64BitOS);
- // Remove all archives with HostBits not matching the OS Bits
- // Apply only if there is any matching in the list
- if (!includeAllArchives && alist.Count > 1 && alist.Any(a => IsBitsValid(a.HostBits)))
- {
- alist.RemoveAll(a => !IsBitsValid(a.HostBits));
- }
-
- Archives = alist.AsReadOnly();
- }
-
- protected virtual string GetDetailedDescription()
- {
- string desc = $"{DisplayName} r{Revision}";
- if (!String.IsNullOrEmpty(Info?.DetailedDescription))
- return $"{desc} [{Info?.DetailedDescription}]";
- return desc;
- }
-
- protected void OnStatusChange(AndroidComponentStatus status)
- {
- if (StatusChanged == null)
- return;
-
- StatusChanged(this, new AndroidComponentStatusChangeEventArgs(status, this));
- }
-
- public void Remove(string androidSDKRoot)
- {
- OnStatusChange(AndroidComponentStatus.RemovalStarted);
- try
- {
- PackageMetadata metadata = CreateMetadata(this);
-
- DoRemove(androidSDKRoot, retries: 5, delayInSeconds: 5);
-
- PerformDetection(androidSDKRoot, true);
- RefreshMetadata(this, false);
- }
- finally
- {
- OnStatusChange(AndroidComponentStatus.RemovalEnded);
- }
- }
-
- void DoRemove(string androidSDKRoot, int retries, int delayInSeconds)
- {
- if (String.IsNullOrEmpty(androidSDKRoot))
- throw new ArgumentException("must not be null or empty", nameof(androidSDKRoot));
-
- var ex = default(Exception);
- var success = false;
- while (!success && retries > 0)
- {
- try
- {
- DoRemove(androidSDKRoot);
- success = true;
- }
- catch (UnauthorizedAccessException uae)
- {
- ex = uae;
- retries = retries - 1;
- Thread.Sleep(TimeSpan.FromSeconds(delayInSeconds));
- delayInSeconds = delayInSeconds + 3;
- }
- }
-
- if (!success && ex != null)
- throw ex;
- }
-
- void DoRemove(string androidSDKRoot)
- {
- if (String.IsNullOrEmpty(androidSDKRoot))
- throw new ArgumentException("must not be null or empty", nameof(androidSDKRoot));
-
- string packagePath = IOPath.Combine(androidSDKRoot, FileSystemPath);
- if (File.Exists(packagePath))
- File.Delete(packagePath);
- else if (Directory.Exists(packagePath))
- Directory.Delete(packagePath, true);
- else
- return;
-
- DeleteDirTreeIfEmpty(
- new DirectoryInfo(GetRealDirectoryName(androidSDKRoot)),
- new DirectoryInfo(GetRealDirectoryName(IOPath.GetDirectoryName(packagePath)))
- );
- }
-
- public abstract void RefreshMetadata(IAndroidComponent component, bool ignoreInstalledState = true);
- protected abstract PackageMetadata CreateMetadata(BasePackage component);
-
- public void PerformDetection(string androidSDKRoot, bool isRefresh = false)
- {
- if (String.IsNullOrEmpty(androidSDKRoot))
- throw new ArgumentException("must not be null or empty", nameof(androidSDKRoot));
-
- PackageMetadata metadata = isRefresh ? CreateMetadata(this) : null;
- string description = DetailedDescription;
- Present = false;
- InstalledRevision = null;
- ForceInstallation = false;
- OnStatusChange(AndroidComponentStatus.DetectionStarted);
- try
- {
- NeedsUpdate = Detect(androidSDKRoot, description);
- }
- catch (Exception ex)
- {
- LogInfo($"Component {description} detection failed with exception. Component will be marked as outdated.");
- LogInfo(ex.ToString());
- NeedsUpdate = true;
- }
- finally
- {
- OnStatusChange(AndroidComponentStatus.DetectionEnded);
- if (MetadataChanged(metadata))
- OnStatusChange(AndroidComponentStatus.MetadataUpdated);
- }
- }
-
- // Returns `true` if the package is absent or is older than our version
- bool Detect(string androidSDKRoot, string description)
- {
- Present = false;
- string fullPath = IOPath.Combine(androidSDKRoot, FileSystemPath);
- if (!Directory.Exists(fullPath))
- {
- LogDebug($"Component {description} not present on the system");
- return true;
- }
- LogDebug($"Detecting component {description} in directory '{fullPath}'");
-
- // Treat the package as present only if we have any file with version information
- AndroidRevision instv = null;
- string manifestFile = IOPath.Combine(fullPath, "package.xml");
- if (File.Exists(manifestFile))
- {
- Present = true;
- instv = GetPackageRevision(manifestFile);
- }
-
- if (instv == null)
- {
- manifestFile = IOPath.Combine(fullPath, "source.properties");
- if (File.Exists(manifestFile))
- {
- Present = true;
- var props = AndroidUtilities.ReadAndroidProperties(manifestFile);
- string rev;
- props.GetPkgRevision(out rev, out instv, DisplayName);
- }
- }
-
- // https://bugzilla.xamarin.com/show_bug.cgi?id=59714 AndroidComponentInfoSystemImage.Abi reads Default for a x86 image
- // Try to fix system image' package.xml -> abi as it might be wrong
- if (ComponentType == AndroidComponentType.SystemImage && Present)
- {
- AndroidComponentInfoSystemImage info = (AndroidComponentInfoSystemImage)Info;
- if (info != null
- && (info.Abi == AndroidSystemImageAbi.X86
- || info.Abi == AndroidSystemImageAbi.ARMV7a
- || info.Abi == AndroidSystemImageAbi.ARM64V8a))
- {
- manifestFile = IOPath.Combine(fullPath, "package.xml");
- if (File.Exists(manifestFile))
- {
- string abi = GetAbi(manifestFile);
-
- // Rewrite the entire manifest if the abi value differs
- if (abi != null && abi != info.GetAbiManifestString())
- {
- LogWarning($"Found invalid abi \"{abi}\" (expected value: \"{info.GetAbiManifestString()}\") in \"{manifestFile}\", regenerating package.xml...");
- try
- {
- GeneratePackageXml(manifestFile);
- }
- catch (Exception ex)
- {
- if (ex is IOException || ex is UnauthorizedAccessException)
- {
- LogError($"Could not regenerate package.xml for \"{manifestFile}\" as the process might not have administrative privileges. You will need to fix the manifest manually.\nHere is the error details: {ex}");
- // Marking component as not installed
- Present = false;
- InstalledRevision = null;
- return true;
- }
- throw;
- }
- }
- }
- }
- }
-
- if (instv == null)
- {
- LogInfo($" Version information not found for component {description}");
- return true;
- }
-
- LogDebug($" Found revision {instv} on the system");
- InstalledRevision = instv;
-
- return Revision > InstalledRevision;
- }
-
- protected AndroidRevision GetPackageRevision(string manifestFile)
- {
- try
- {
- XDocument doc = XDocument.Load(manifestFile);
- XElement revision = doc.Descendants("revision")?.FirstOrDefault();
- if (revision == null)
- return null;
-
- // We should use RevisionParser but due to its requirements (parser context) it's rather
- // unwieldy, hence the code duplication here
- return new AndroidRevision(
- ParseAsInt(revision.Element("major")),
- ParseAsInt(revision.Element("minor")),
- ParseAsInt(revision.Element("micro")),
- ParseAsInt(revision.Element("preview"))
- );
- }
- catch (Exception ex)
- {
- LogDebug($"Exception caught trying to parse {manifestFile} for package version information.");
- LogDebug(ex.ToString());
- return null;
- }
- }
-
- protected string GetAbi(string manifestFile)
- {
- try
- {
- XDocument doc = XDocument.Load(manifestFile);
- XElement abi = doc.Descendants("abi")?.FirstOrDefault();
- if (abi == null)
- return null;
-
- return abi.Value;
- }
- catch (Exception ex)
- {
- LogDebug($"Exception caught trying to parse {manifestFile} for abi information.");
- LogDebug(ex.ToString());
- return null;
- }
- }
-
- protected int ParseAsInt(XElement e)
- {
- string v = e?.Value?.Trim();
- if (String.IsNullOrEmpty(v))
- return -1;
-
- int ret;
- if (!Int32.TryParse(v, out ret))
- return -1;
-
- return ret;
- }
-
- protected string GetRealDirectoryName(string path)
- {
- if (!Directory.Exists(path))
- return path;
-
- string cwd = Environment.CurrentDirectory;
- try
- {
- Directory.SetCurrentDirectory(path);
- return Environment.CurrentDirectory;
- }
- finally
- {
- Directory.SetCurrentDirectory(cwd);
- }
- }
-
- protected void DeleteDirTreeIfEmpty(DirectoryInfo stopAt, DirectoryInfo di)
- {
- if (string.Equals(stopAt.FullName, di.FullName, StringComparison.Ordinal))
- return;
-
- if (di.EnumerateFileSystemInfos().Any())
- return;
-
- DirectoryInfo parent = di.Parent;
- di.Delete();
- DeleteDirTreeIfEmpty(stopAt, parent);
- }
-
- protected virtual bool MetadataChanged(PackageMetadata metadata, bool update = false, bool ignoreInstalledState = false)
- {
- if (metadata == null)
- return false;
-
- bool haveChanges = false;
- if (!metadata.Archives.AreEqual(Archives))
- {
- if (update)
- {
- Archives = new List(metadata.Archives).AsReadOnly();
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!metadata.Dependencies.AreEqual(Dependencies))
- {
- if (update)
- {
- Dependencies = metadata.Dependencies != null ? new List(metadata.Dependencies).AsReadOnly() : null;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!string.Equals(metadata.DisplayName, DisplayName, StringComparison.Ordinal))
- {
- if (update)
- {
- DisplayName = metadata.DisplayName;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!string.Equals(metadata.FileSystemPath, FileSystemPath, StringComparison.Ordinal))
- {
- if (update)
- {
- FileSystemPath = metadata.FileSystemPath;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!AreInfosEqual(Info, metadata.Info))
- {
- if (update)
- {
- Info = metadata.Info;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!ignoreInstalledState && metadata.InstalledRevision != InstalledRevision)
- {
- if (update)
- {
- InstalledRevision = metadata.InstalledRevision;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!ignoreInstalledState && metadata.NeedsUpdate != NeedsUpdate)
- {
- if (update)
- {
- NeedsUpdate = metadata.NeedsUpdate;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (metadata.Obsolete != Obsolete)
- {
- if (update)
- {
- Obsolete = Obsolete;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!string.Equals(metadata.Path, Path, StringComparison.OrdinalIgnoreCase))
- {
- if (update)
- {
- Path = metadata.Path;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (!ignoreInstalledState && metadata.Present != Present)
- {
- if (update)
- {
- Present = metadata.Present;
- haveChanges = true;
- }
- else
- return true;
- }
-
- if (metadata.Revision != Revision)
- {
- if (update)
- {
- Revision = metadata.Revision;
- haveChanges = true;
- }
- else
- return true;
- }
-
- return haveChanges;
- }
-
- public void Install(string archivePath, string androidSDKRoot,
- InstallationProgressEventArgs.InstallationProgressActionDelegate progressCallback = null)
- {
- OnStatusChange(AndroidComponentStatus.InstallationStarted);
- try
- {
- DoInstall(archivePath, androidSDKRoot, progressCallback);
- }
- finally
- {
- OnStatusChange(AndroidComponentStatus.InstallationEnded);
- }
- }
-
- void DoInstall(string archivePath, string androidSDKRoot,
- InstallationProgressEventArgs.InstallationProgressActionDelegate progressCallback = null)
- {
- if (String.IsNullOrEmpty(archivePath))
- throw new ArgumentException("must not be null or empty", nameof(archivePath));
- if (String.IsNullOrEmpty(androidSDKRoot))
- throw new ArgumentException("must not be null or empty", nameof(androidSDKRoot));
-
- string targetDirectory = IOPath.Combine(androidSDKRoot, FileSystemPath);
- OnStatusChange(AndroidComponentStatus.UnpackingStarted);
-
- bool success = false;
- try
- {
- success = InstallArchive(DetailedDescription, archivePath, targetDirectory, progressCallback);
- }
- catch (Exception ex)
- {
- LogError($"Archive '{archivePath}' installation failed with error: {ex}");
- throw;
- }
- finally
- {
- OnStatusChange(AndroidComponentStatus.UnpackingEnded);
- }
-
- if (success)
- GeneratePackageXml(IOPath.Combine(targetDirectory, "package.xml"));
- else
- throw new InvalidOperationException("Archive installation failed.");
- }
-
- bool InstallArchive(string description, string archivePath, string targetDirectory,
- InstallationProgressEventArgs.InstallationProgressActionDelegate progressCallback = null)
- {
- //return false; // this is a test
- //throw new Exception("A test InstallArchive exception.");
- var rnd = new Random();
- string componentUnzippedPath;
-
- int moveSplitPercents = DirectorySizeMonitoringTimer.CalculateMoveProgressSplit(archivePath);
- int unzipSplitPercents = 100 - moveSplitPercents;
-
- // LogDebug ($"unzipSplitPercents: {unzipSplitPercents} | moveSplitPercents: {moveSplitPercents}");
-
- // A small race here but I think we can accept the risks :)
- string temporaryPath = IOPath.Combine(IOPath.GetTempPath(), IOPath.GetRandomFileName());
- try
- {
- componentUnzippedPath = CommonUtilities.Helpers.Unzip(temporaryPath, archivePath, AndroidSDKContext.Instance.UserName, (progress) =>
- {
- try
- {
- progressCallback?.Invoke((float)DirectorySizeMonitoringTimer.Remap(progress, 0, 100, 0, unzipSplitPercents));
- }
- catch (Exception ex)
- {
- Logger.Error($"[InstallArchive] progress callback exception: {ex}");
- }
- }).RemoveTrailingDirectorySeparator();
- }
- catch (Exception ex)
- {
- LogError($"Exception caught while unzipping '{archivePath}' in '{temporaryPath}'. {ex}");
- throw;
- }
-
- LogDebug($"Android component '{description}' unpacked in directory '{componentUnzippedPath}'");
- LogDebug($"Android component destination path: {targetDirectory}");
- string oldDestinationPath = null;
-
- if (Directory.Exists(targetDirectory))
- {
- oldDestinationPath = targetDirectory + ".old" + rnd.Next(Int32.MaxValue);
- LogInfo($"Moving old directory '{targetDirectory}' to '{oldDestinationPath}'");
-
- // We'll be on the same filesystem/volume, so we can just use this instead of recursive copy+delete
- Directory.Move(targetDirectory, oldDestinationPath);
- }
-
- bool ret = true;
- Exception exMoveDirectory = null;
- try
- {
- int idx = targetDirectory.LastIndexOf(IOPath.DirectorySeparatorChar);
- string leadingPath;
- if (idx > 1)
- leadingPath = targetDirectory.Substring(0, idx);
- else
- leadingPath = targetDirectory;
-
- if (!Directory.Exists(leadingPath))
- {
- LogInfo($"Creating Android component's parent path '{leadingPath}'");
- Directory.CreateDirectory(leadingPath);
- }
- LogInfo("Moving Android component to its destination path.");
-
- using (var monitoringTimer = new DirectorySizeMonitoringTimer(targetDirectory, componentUnzippedPath, (progress) =>
- {
- try
- {
- progressCallback?.Invoke(progress);
- }
- catch (Exception ex)
- {
- Logger.Error($"[InstallArchive] progress callback exception: {ex}");
- }
- }, remapFrom: unzipSplitPercents, remapTo: 100f))
- {
- CommonUtilities.MoveDirectory(componentUnzippedPath, targetDirectory, overwrite: true);
- }
- }
- catch (Exception e)
- {
- exMoveDirectory = e;
- ret = false;
- LogError($"Failure to move Android component to its destination path. {e}");
- if (!String.IsNullOrEmpty(oldDestinationPath) && Directory.Exists(oldDestinationPath))
- {
- LogError("Attempting to clean up.");
- LogError($"Trying to remove directory '{targetDirectory}'");
- CommonUtilities.DeleteDirectoryRecursively(targetDirectory);
-
- try
- {
- CommonUtilities.MoveDirectory(oldDestinationPath, targetDirectory);
- }
- catch (Exception ex)
- {
- // ignore
- LogError($"Failed to rename directory '{oldDestinationPath}' to '{targetDirectory}'. {ex}");
- }
- }
- }
-
- bool logError = false;
- Exception rex = null;
- try
- {
- CommonUtilities.DeleteDirectoryRecursively(temporaryPath);
- if (!String.IsNullOrEmpty(oldDestinationPath))
- logError = !CommonUtilities.DeleteDirectoryRecursively(oldDestinationPath);
- }
- catch (Exception e)
- {
- logError = true;
- ret = false;
- rex = e;
- // ignore
- }
- if (logError)
- {
- string message = $"Failed to remove old destination directory '{oldDestinationPath}'. User will have to remove it manually.";
- if (rex != null)
- LogError($"{message}. {rex}");
- else
- LogError(message);
- }
-
- if (exMoveDirectory != null)
- throw exMoveDirectory;
-
- return ret;
- }
-
- protected void GeneratePackageXml(string path)
- {
- LogDebug($"Generating {path}");
-
- var settings = new XmlWriterSettings
- {
- CloseOutput = true,
- Encoding = Encoding.UTF8,
- Indent = false,
- NamespaceHandling = NamespaceHandling.OmitDuplicates,
- NewLineHandling = NewLineHandling.None,
- OmitXmlDeclaration = false
- };
-
- using (var writer = XmlWriter.Create(path, settings))
- {
- writer.WriteStartDocument(true);
- // TODO: check if the namespace exists
- writer.WriteStartElement("sdk", "repository", Repository.GetNamespaceUri("sdk"));
- if (Repository.Namespaces != null)
- {
- foreach (var kvp in Repository.Namespaces)
- {
- if (string.Equals("xsi", kvp.Key, StringComparison.Ordinal))
- continue;
- writer.WriteAttributeString("xmlns", kvp.Key, null, kvp.Value.NamespaceName);
- }
- }
-
- writer.WriteStartElement("license");
- writer.WriteAttributeString("id", LicenseID ?? String.Empty);
- writer.WriteAttributeString("type", License?.Type ?? String.Empty);
- writer.WriteString(License?.Text ?? String.Empty);
- writer.WriteEndElement(); // license
-
- writer.WriteStartElement("localPackage");
- writer.WriteAttributeString("path", Path);
- writer.WriteAttributeString("obsolete", Obsolete ? "true" : "false");
-
- Info?.WritePackageXmlInfo(writer, Repository);
-
- writer.WriteStartElement("revision");
- if (Revision != null)
- {
- WriteRevisionPart(writer, "major", Revision.Major);
- WriteRevisionPart(writer, "minor", Revision.Minor);
- WriteRevisionPart(writer, "micro", Revision.Micro);
- WriteRevisionPart(writer, "preview", Revision.Preview);
- }
- writer.WriteEndElement(); // revision
-
- writer.WriteStartElement("display-name");
- writer.WriteString(DisplayName);
- writer.WriteEndElement(); // display-name
-
- writer.WriteStartElement("uses-license");
- writer.WriteAttributeString("ref", LicenseID ?? String.Empty);
- writer.WriteEndElement(); // uses-license
-
- if (Dependencies != null && Dependencies.Count > 0)
- {
- writer.WriteStartElement("dependencies");
- foreach (Dependency dep in Dependencies)
- {
- if (dep == null)
- continue;
- writer.WriteStartElement("dependency");
- writer.WriteAttributeString("path", dep.Path ?? String.Empty);
- writer.WriteEndElement(); //dependency
- }
- writer.WriteEndElement(); // dependencies
- }
-
- writer.WriteEndElement(); // localPackage
-
- writer.WriteEndElement(); // repository
- writer.WriteEndDocument();
- }
- }
-
- void WriteRevisionPart(XmlWriter writer, string name, int value)
- {
- if (value < 0)
- return;
-
- writer.WriteStartElement(name);
- writer.WriteValue(value);
- writer.WriteEndElement();
- }
-
- public virtual bool MatchesTo(IAndroidComponent other)
- {
- if (!(other is BasePackage))
- return false;
-
- if (ReferenceEquals(this, other))
- return true;
-
- if (IsPlatformSpecific && !SupportedPlatforms.SequenceEqual((other as BasePackage).SupportedPlatforms))
- return false;
-
- return string.Equals(Path, other.Path, StringComparison.Ordinal) &&
- Revision == other.Revision &&
- Channel == other.Channel;
- }
-
- public virtual bool BasicMetadataEquals(BasePackage other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals(this, other))
- return true;
-
- // We compare only the properties that actually matter
- if (!string.Equals(Path, other.Path, StringComparison.Ordinal))
- return false;
-
- if (!AreInfosEqual(Info, other.Info))
- return false;
-
- if (Obsolete != other.Obsolete)
- return false;
-
- if (!Revision.Equals(other.Revision))
- return false;
-
- return true;
- }
-
- bool AreInfosEqual(AndroidComponentInfo info1, AndroidComponentInfo info2)
- {
- // If only one of them is null return false
- if ((info1 == null) != (info2 == null))
- return false;
-
- if (info1 != null && !info1.Equals(info2))
- return false;
-
- return true;
- }
-
- // It's very simple in this case, we're not interested in deep comparison
- // of the two instances, but rather whether they are uniquely identified -
- // that is they have a different path+version combination.
- public virtual bool Equals(BasePackage other)
- {
- if (!BasicMetadataEquals(other))
- return false;
-
- if (UniqueID != other.UniqueID)
- return false;
-
- if (!Dependencies.AreEqual(other.Dependencies))
- return false;
-
- if (!Archives.AreEqual(other.Archives))
- return false;
-
- return true;
- }
-
- public override bool Equals(object obj)
- {
- return Equals(obj as BasePackage);
- }
-
- public override int GetHashCode()
- {
- int hashCode = base.GetHashCode();
-
- hashCode = hashCode.XorWith(UniqueID.GetHashCode());
- hashCode = hashCode.XorWith(Path?.GetHashCode());
- hashCode = hashCode.XorWith(Info?.GetHashCode());
- hashCode = hashCode.XorWith(Obsolete.GetHashCode());
- hashCode = hashCode.XorWith(Revision?.GetHashCode());
- hashCode = hashCode.XorWith(Dependencies?.GetHashCode());
- return hashCode.XorWith(Archives?.GetHashCode());
- }
-
- protected abstract void LogError(string message);
- protected abstract void LogWarning(string message);
- protected abstract void LogInfo(string message);
- protected abstract void LogDebug(string message);
-
- private bool GetPreview()
- {
- if (Info is AndroidComponentInfoPlatform platform)
- {
- return platform.Preview;
- }
- return false;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Channel.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Channel.cs
deleted file mode 100644
index 132690fad68..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Channel.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-using Xamarin.Installer.AndroidSDK.Common;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a single Android SDK channel. Google currently define 4 channels:
- ///
- /// -
- /// stable
- ///
- /// -
- /// beta
- ///
- /// -
- /// dev
- ///
- /// -
- /// canary
- ///
- ///
- /// Note however that the list is defined directly in the Android SDK manifest document and may be
- /// changed by Google at any time.
- ///
- public sealed class Channel : ItemWithID, IEquatable
- {
- ///
- /// Gets the channel name
- ///
- /// Channel name
- public string Name { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Identifier.
- /// Name.
- public Channel (string id, string name) : base (id)
- {
- if (String.IsNullOrEmpty (name))
- throw new ArgumentException ("Must not be null or empty", nameof (name));
- Name = name;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals (Channel other)
- {
- if (other == null)
- return false;
-
- return Equals (other as ItemWithID);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as Channel);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- return base.GetHashCode ();
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ConfigManager.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ConfigManager.cs
deleted file mode 100644
index fc6258a2ad4..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ConfigManager.cs
+++ /dev/null
@@ -1,118 +0,0 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Xml;
-using System.Xml.Linq;
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK.Manager
-{
- public class ConfigManager
- {
- const string AppName = "AndroidSDKManager";
- const string PropertiesRootNode = "SDKManagerProperties";
- const string PropertyNode = "Property";
-
- Dictionary properties;
-
- ///
- /// SDK Manager configuration folder path
- ///
- ///
- public static string ConfigFolder {
- get {
- string configFolder;
- if (Platform.IsMac) {
- var home = Environment.GetFolderPath (Environment.SpecialFolder.UserProfile);
- configFolder = Path.Combine (home, "Library", "Preferences");
- } else {
- configFolder = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
- if (Platform.IsWindows)
- configFolder = Path.Combine (configFolder, "Config");
- }
- return Path.Combine (configFolder, AppName);
- }
- }
-
- string filePath;
- string FilePath {
- get {
- if (filePath == null)
- filePath = Path.Combine (ConfigFolder, "properties.xml");
-
- return filePath;
- }
- }
-
- internal ConfigManager ()
- {
- LoadProperties ();
- }
-
- internal void SetProperty (string key, string value)
- {
- if (properties.ContainsKey (key)) {
- if (string.Equals (properties [key], value, StringComparison.Ordinal))
- return;
- properties.Remove (key);
- }
-
- properties.Add (key, value);
- }
-
- internal string GetProperty (string key, string defaultValue)
- {
- bool success = properties.TryGetValue (key, out string value);
- return success ? value : defaultValue;
- }
-
- void LoadProperties ()
- {
- properties = new Dictionary (StringComparer.Ordinal);
- if (!File.Exists (FilePath))
- return;
-
- try
- {
- var element = XElement.Load (FilePath);
- foreach (var node in element.Descendants (PropertyNode)) {
- var key = node.Attribute ("key").Value;
- var value = node.Attribute ("value").Value;
- if (String.IsNullOrEmpty (key))
- continue;
-
- properties.Add (key, value);
- }
- }
- catch (XmlException ex)
- {
- // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/723620
- // Overwrite the broken config with an empty xml (we write default property values there later)
- Logger.Warning ($"Failed to read the config, resetting it.\nError details: {ex}");
- SaveProperties ();
- }
- }
-
-
- internal void SaveProperties ()
- {
- var filePath = FilePath;
- if (!File.Exists (filePath)) {
- var dir = Path.GetDirectoryName (filePath);
- if (!Directory.Exists (dir))
- Directory.CreateDirectory (dir);
- }
- XmlWriter xmlWriter = XmlWriter.Create(FilePath);
-
- xmlWriter.WriteStartDocument();
- xmlWriter.WriteStartElement(PropertiesRootNode);
- foreach (var keyValue in properties) {
- xmlWriter.WriteStartElement(PropertyNode);
- xmlWriter.WriteAttributeString ("key", keyValue.Key);
- xmlWriter.WriteAttributeString ("value", keyValue.Value);
- }
- xmlWriter.WriteEndElement();
- xmlWriter.Close();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Constants.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Constants.cs
deleted file mode 100644
index 8a280aa0731..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Constants.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
- public static partial class Constants
- {
- public static class ComponentPaths
- {
- public const string BuildTools = "build-tools;";
- public const string CMake = "cmake;";
- public const string Emulator = "emulator";
- public const string LLDB = "lldb;";
- public const string NDK = "ndk-bundle";
- public const string PlatformTools = "platform-tools";
- public const string ToolsObsolete = "tools";
- public const string Tools = "cmdline-tools";
- public const string ToolsLatest = "cmdline-tools;latest";
-
- public const string Platforms = "platforms";
-
- public const string HypervisorDriver = "extras;google;Android_Emulator_Hypervisor_Driver";
- }
-
- public static partial class RequiredComponentVersions
- {
- // This class has properties which are auto generated by the GenerateRequiredComponentVersions MSBuild Target
-
- // this defaults are used by the IDEs to complete the required components on the auto-sdk process
- // values are in sync with the GetAndroidDependencies target result
- public static readonly string[] RequiredComponents = {
- $"build-tools/{RequiredBuildToolsVersion}@{RequiredBuildToolsVersion}",
- $"platform-tools@{RequiredPlatformToolsVersion}",
- $"cmdline-tools/{RequiredCommandLineToolsVersion}@{RequiredCommandLineToolsVersion}",
- };
- }
- }
-#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Dependency.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Dependency.cs
deleted file mode 100644
index 1a03177aaf5..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Dependency.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a single package dependency
- ///
- public sealed class Dependency : IEquatable
- {
- ///
- /// Manifest path to the dependency
- ///
- /// Dependency path
- public string Path { get; }
-
- ///
- /// Gets the minimum revision of the dependency package
- ///
- /// The minimum revision.
- public AndroidRevision MinRevision { get; }
-
- public AndroidSDKPlatform Platform { get; set; } = AndroidSDKPlatform.Unknown;
- public bool IsPlatformSpecific => Platform != AndroidSDKPlatform.Any && Platform != AndroidSDKPlatform.Unknown;
-
- internal Dependency (string path, AndroidRevision minRevision = null)
- {
- if (String.IsNullOrEmpty (path))
- throw new ArgumentException ("must not be null or empty", nameof (path));
-
- Path = path;
- MinRevision = minRevision;
- }
-
- internal Dependency (Dependency other)
- {
- if (other == null)
- throw new ArgumentNullException (nameof (other));
-
- Path = other.Path;
- if (other.MinRevision != null)
- MinRevision = new AndroidRevision (other.MinRevision);
- Platform = other.Platform;
- }
-
- ///
- /// Determines whether the specified is equal to the
- /// current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals (Dependency other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals (this, other))
- return true;
-
- if (!string.Equals (Path, other.Path, StringComparison.Ordinal))
- return false;
-
- if (MinRevision == null) {
- if (other.MinRevision != null)
- return false;
- } else if (!MinRevision.Equals (other.MinRevision))
- return false;
-
- return Platform == other.Platform;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as Dependency);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
- hashCode = hashCode.XorWith (Path?.GetHashCode ());
- return hashCode.XorWith (MinRevision?.GetHashCode ());
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Helper.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Helper.cs
deleted file mode 100644
index 0fe753a1deb..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Helper.cs
+++ /dev/null
@@ -1,472 +0,0 @@
-//
-// Helper.cs
-//
-// Author:
-// Vsevolod Kukol
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-
-using System;
-using System.IO;
-using System.Net;
-using System.Net.Http;
-using ICSharpCode.SharpZipLib.Zip;
-using Xamarin.Installer.Common;
-using System.Collections.Concurrent;
-using System.Threading.Tasks;
-using Xamarin.Installer.AndroidSDK.Common;
-using System.Threading;
-using System.Linq;
-
-#if !WINDOWS
-using Mono.Unix.Native;
-#endif
-
-using System.Runtime.InteropServices;
-
-namespace Xamarin.Installer.AndroidSDK.Manager
-{
- public class Helper : IHelpers
- {
- public static readonly TimeSpan HttpTimeout = TimeSpan.FromSeconds (Platform.IsWindows ? 60 : 10);
- static string homeDirectory;
- ConfigManager config = new ConfigManager ();
-
- public string CacheFolder { get; set; }
-
- readonly string manifestFilePath;
-
- static ConcurrentDictionary> stringDownloadCache = new ConcurrentDictionary> ();
-
- public Helper (string cacheFolder = null, string manifestFilePath = null)
- {
- CacheFolder = cacheFolder;
- this.manifestFilePath = manifestFilePath;
- }
-
- public static string HomeDirectory {
- get
- {
- if (string.IsNullOrEmpty(homeDirectory)) {
- homeDirectory = Environment.GetEnvironmentVariable("HOME");
- if (String.IsNullOrEmpty(homeDirectory) || !Directory.Exists(homeDirectory)) {
- homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
- }
- }
- return homeDirectory;
- }
- }
-
- string IHelpers.HomeDirectory {
- get {
- return HomeDirectory;
- }
- }
-
- public bool IsArm64
- {
- get {
- return RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
- }
- }
-
- public bool Is64BitOS {
- get {
- return Environment.Is64BitOperatingSystem;
- }
- }
-
- public bool IsCaseSensitiveFileSystem {
- get { return true; } // TODO
- }
-
- public string UserName {
- get {
- if (Platform.IsWindows)
- return Environment.UserName;
- return Environment.GetEnvironmentVariable ("USER");
- }
- }
-
- public bool DownloadToString (Uri url, out string output)
- {
-#if DEBUG
- // DEBUG: support setting XAMARIN_ANDROID_MANIFEST_URL=file:///… for local manifest authoring.
- if (url.Scheme == "file")
- {
- output = File.ReadAllText(url.LocalPath);
- return true;
- }
-#else
- // Release: only allow https://, plus the in-box file:// fallback manifest that
- // ships alongside this assembly (XamarinRepository.GetFallbackManifestUrl), or a
- // local manifest path explicitly supplied by InstallAndroidDependencies.
- if (url.Scheme == "file") {
- var assemblyDir = Path.GetDirectoryName (typeof (Helper).Assembly.Location);
- var requestedDir = Path.GetDirectoryName (url.LocalPath);
- if ((!string.IsNullOrEmpty (manifestFilePath) && string.Equals (manifestFilePath, url.LocalPath, StringComparison.OrdinalIgnoreCase)) ||
- (!string.IsNullOrEmpty (assemblyDir) && string.Equals (assemblyDir, requestedDir, StringComparison.OrdinalIgnoreCase))) {
- output = File.ReadAllText (url.LocalPath);
- return true;
- }
- Logger.Warning ($"Ignoring file:// manifest URL '{url}': file:// is only honored for an explicit local manifest path or the in-box fallback manifest in shipped builds.");
- output = null;
- return false;
- }
- if (url.Scheme != "https") {
- Logger.Warning ($"Ignoring manifest URL '{url}': only https:// URLs are honored in shipped builds.");
- output = null;
- return false;
- }
-#endif
-
- // FIXME: returning false on failure doesn't make Installer.Discover return false.
- // hence we need a hard throw on failure to detect it on higher levels
- //try {
-
- using (var client = HttpClientProvider.CreateHttpClient (url)) {
- client.Timeout = HttpTimeout;
- var req = new HttpRequestMessage (HttpMethod.Get, url);
-
- if (stringDownloadCache.TryGetValue(url, out Tuple cache)) {
- req.Headers.IfModifiedSince = cache.Item1;
- output = cache.Item2;
- }
-
- //try {
- using (var res = client.SendAsync (req, HttpCompletionOption.ResponseHeadersRead).Result) {
- if (res.StatusCode == HttpStatusCode.NotModified) {
- output = cache.Item2;
- return true;
- }
- if (res.StatusCode != HttpStatusCode.OK) {
- Logger.Warning ($"Unable to download manifest xml from {url}. Status Code: {res.StatusCode} - {(int)res.StatusCode}");
- output = null;
- return false;
- }
- output = res.Content.ReadAsStringAsync ().Result;
- DateTimeOffset? lastModified = res.Content.Headers.LastModified;
- if (lastModified.HasValue)
- stringDownloadCache[url] = Tuple.Create (lastModified.Value, output);
- return true;
- }
- //} catch (Exception ex) {
- // Logger.Exception ($"Downloading '{url}' failed", ex);
- // output = null;
- // return false;
- //}
- }
- }
-
- public string GetPathForDownloadId (Guid id)
- {
- return Path.Combine (Path.GetTempPath (), "xamarin-android-sdk", id.ToString () + ".zip");
- }
-
- public ulong GetUrlContentLength (Uri url)
- {
- using (var client = HttpClientProvider.CreateHttpClient (url)) {
- client.Timeout = HttpTimeout;
- var request = new HttpRequestMessage(HttpMethod.Head, url);
- var resp = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
- if (resp.IsSuccessStatusCode)
- return (ulong)(resp.Content.Headers.ContentLength ?? 0);
- return 0;
- }
- }
-
- public bool IsSpecialFile (string filePath)
- {
- return false;
- }
-
- public void CopySpecialFile (string source, string target)
- {
- throw new NotImplementedException ();
- }
-
- public class CustomTooLongPathException : Exception
- {
- public Exception OriginalException { get; set; }
- }
-
- public string Unzip (string baseDirectory, string archivePath, string fileOwnerName = null)
- {
- return Unzip (baseDirectory, archivePath, fileOwnerName, progressCallback: null);
- }
-
- public string Unzip (string baseDirectory, string archivePath, string fileOwnerName = null,
- InstallationProgressEventArgs.InstallationProgressActionDelegate progressCallback = null)
- {
- if (string.IsNullOrEmpty (baseDirectory))
- throw new ArgumentNullException (nameof (baseDirectory), "No base directory given, unable to unzip.");
- if (string.IsNullOrEmpty (archivePath))
- throw new ArgumentNullException (nameof (archivePath), "No ZIP archive specified.");
- Logger.Info ($"Unzipping file '{archivePath}' to directory '{baseDirectory}'");
-
- if (!Directory.Exists (baseDirectory)) {
- try {
- Directory.CreateDirectory (baseDirectory);
- // TODO: set directory owner and permissions
- } catch (Exception ex) {
- Logger.Exception ($"Failed to create base directory '{baseDirectory}' to unzip archive.", ex);
- return null;
- }
- }
-
- string lastDestPath = String.Empty;
- ZipFile zip = null;
-
- try
- {
- zip = new ZipFile (archivePath);
-
- float minProgressDelta = 5f; // percents
- float lastProgress = 0f;
- float progress;
-
- ulong totalSize = DirectorySizeMonitoringTimer.CalculateTotalSize (zip);
- ulong currentSize = 0, gradualSize;
- try {
- progressCallback?.Invoke (0f);
- } catch (Exception ex) {
- Logger.Error ($"[Unzip] progress callback exception: {ex}");
- }
-
- string fullBaseDirectory = Path.GetFullPath (baseDirectory).TrimEnd (Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
-
- foreach (ZipEntry entry in zip) {
- string destPath = Path.Combine (baseDirectory, entry.Name);
- lastDestPath = destPath;
-
- if (!Path.GetFullPath (destPath).StartsWith (fullBaseDirectory, StringComparison.OrdinalIgnoreCase)) {
- throw new Exception ($"Archive file '{archivePath}' has parent traversal in paths");
- }
-
- if (entry.IsDirectory) {
- Directory.CreateDirectory (destPath);
- SafeSetLastWriteTime (destPath, entry.DateTime);
- continue;
- }
-
- Directory.CreateDirectory (Path.GetDirectoryName (destPath));
-
- byte [] buf = new byte [4096];
- int n = 0;
- gradualSize = 0;
- ulong iteration = 0;
- using (var fs = new FileStream (destPath, FileMode.Create, FileAccess.Write, FileShare.None)) {
- using (var inZip = zip.GetInputStream (entry)) {
- while ((n = inZip.Read (buf, 0, buf.Length)) > 0) {
- fs.Write (buf, 0, n);
- gradualSize += (ulong) n;
- iteration++;
-
- if (iteration % 1000 == 0 && progressCallback != null) {
- progress = (currentSize + gradualSize) * 100f / totalSize;
- if (progress - lastProgress > minProgressDelta) {
- try {
- progressCallback?.Invoke (progress);
- } catch (Exception ex) {
- Logger.Error ($"[Unzip] progress callback exception: {ex}");
- }
- lastProgress = progress;
- }
- }
- }
- }
- currentSize += (ulong) fs.Length;
- }
- SafeSetLastWriteTime (destPath, entry.DateTime);
- SetFileAttributes (destPath, entry.IsDOSEntry, entry.ExternalFileAttributes);
- // TODO: set owner
-
- progress = currentSize * 100f / totalSize;
- if (progress - lastProgress > minProgressDelta) {
- try {
- progressCallback?.Invoke (progress);
- } catch (Exception ex) {
- Logger.Error ($"[Unzip] progress callback exception: {ex}");
- }
- lastProgress = progress;
- }
- }
-
- try {
- progressCallback?.Invoke (100f);
- } catch (Exception ex) {
- Logger.Error ($"[Unzip] progress callback exception: {ex}");
- }
- } catch (DirectoryNotFoundException ex) {
- Logger.Error ($"Unzip failed with DirectoryNotFoundException error: {ex}");
- if (lastDestPath.Length >= 240) {
- Logger.Error ($"Try enabling long paths support to resolve this issue: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/");
- throw new CustomTooLongPathException { OriginalException = ex };
- }
- throw;
- } finally {
- zip?.Close ();
- }
-
- string topDirectory = string.Empty;
- string [] entries = Directory.GetDirectories (baseDirectory);
-
- if (entries.Length == 1)
- topDirectory = entries [0];
-
- string ret = Path.GetFullPath (Path.Combine (baseDirectory, topDirectory));
- Logger.Info ($"Archive unzipped to '{ret}'");
-
- return ret;
- }
-
- static void SafeSetLastWriteTime (string path, DateTime stamp)
- {
- try {
- if (Directory.Exists (path))
- Directory.SetLastWriteTime (path, stamp);
- else if (File.Exists (path))
- File.SetLastWriteTime (path, stamp);
- } catch {
- // Just ignoring this exception, time stamp is not THAT important...
- }
- }
-
- static void SetFileAttributes (string filePath, bool dosAttributes, int zipAttributes)
- {
- if (String.IsNullOrEmpty(filePath) || !File.Exists(filePath))
- return;
- if (dosAttributes && zipAttributes != -1) {
- var fileAttributes = (FileAttributes)zipAttributes;
- fileAttributes &= (FileAttributes.Archive | FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Hidden);
- File.SetAttributes(filePath, fileAttributes);
- } else
- File.SetAttributes(filePath, FileAttributes.Normal);
-
- #if !WINDOWS
- if (Platform.IsWindows)
- return;
-
- zipAttributes = (zipAttributes >> 16);
-
- if (zipAttributes == -1)
- return;
-
- FilePermissions permissions = unchecked((FilePermissions)zipAttributes);
- if (permissions == 0) {
- // 644 octal
- permissions = FilePermissions.S_IRUSR |
- FilePermissions.S_IWUSR |
- FilePermissions.S_IRGRP |
- FilePermissions.S_IROTH;
- } else if ((permissions & FilePermissions.S_IRUSR) == 0)
- permissions |= FilePermissions.S_IRUSR; // owner must be able to read the file
-
- if (Syscall.chmod(filePath, permissions) == -1)
- throw new InvalidOperationException (String.Format("Failed to set file attributes for '{0}'. {1}",
- filePath, Stdlib.strerror(Stdlib.GetLastError())));
- #endif
- }
-
- public bool URLExists (Uri url)
- {
- throw new NotImplementedException ();
- }
-
- public string GetRegistryKeyValue (string subKeyPath, string keyName, bool check64Node)
- {
- throw new NotImplementedException ();
- }
-
- public string GetPluralString (string s, string p, int n)
- {
- return n == 1 ? s : p;
- }
-
- public string GetString (string s)
- {
- return s;
- }
-
- public string GetProperty (string key, string defaultValue = "")
- {
- return config.GetProperty (key, defaultValue);
- }
-
- public void SetProperty (string key, string value)
- {
- config.SetProperty (key, value);
- config.SaveProperties ();
- }
-
- const int NetworkCheckRetryCount = 3;
- static readonly TimeSpan NetworkCheckRetryDelay = TimeSpan.FromSeconds (1);
-
- public async Task CheckIfNetworkIsAvailableAsync ()
- {
- try {
- return await RetryIfTimeoutAsync (CheckIfNetworkAvailable, NetworkCheckRetryCount, NetworkCheckRetryDelay);
- } catch (TimeoutException) {
- return false;
- } catch (TaskCanceledException) {
- return false;
- }
- }
-
- static async Task RetryIfTimeoutAsync (Func> action, int retryCount, TimeSpan retryDelay)
- {
- for (int attempt = 0; ; attempt++) {
- try {
- return await action ().ConfigureAwait (false);
- } catch (Exception exception) when (attempt < retryCount && (exception is TimeoutException || exception is TaskCanceledException)) {
- Logger.Warning ($"[Resiliency.Polly.Policies]: Delegate has thrown {exception}, retrying...");
- }
- await Task.Delay (retryDelay).ConfigureAwait (false);
- }
- }
-
- private Uri GetUrlToCheckIfNetworkAvailable()
- {
- var customURL = Environment.GetEnvironmentVariable("ANDROID_SDK_INSTALLER_CHECK_NETWORK_URL");
- if (!string.IsNullOrEmpty(customURL) && Uri.TryCreate(customURL, UriKind.Absolute, out Uri url))
- {
- return url;
- } else
- {
- return new Uri("https://dotnet.microsoft.com/");
- }
- }
-
- async Task CheckIfNetworkAvailable ()
- {
- try {
- var uri = GetUrlToCheckIfNetworkAvailable();
- using (var client = HttpClientProvider.CreateHttpClient (uri)) {
- client.Timeout = HttpTimeout;
- var request = new HttpRequestMessage (HttpMethod.Get, uri);
- using (var response = await client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead))
- return response.IsSuccessStatusCode;
- }
- } catch (TimeoutException) {
- throw;
- } catch (TaskCanceledException) {
- throw;
- } catch (HttpRequestException) {
- return false;
- } catch (AggregateException ex) {
- foreach (var innerEx in ex.Flatten ().InnerExceptions)
- if (!(innerEx is HttpRequestException))
- Logger.Warning ($"An exception occurred while checking network availability.\n{innerEx}");
-
- if (ex.Flatten ().InnerException is TaskCanceledException)
- throw ex.Flatten ().InnerException;
-
- return false;
- } catch (Exception ex) {
- Logger.Warning ($"An exception occurred while checking network availability.\n{ex}");
- return false;
- }
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/HttpClientProvider.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/HttpClientProvider.cs
deleted file mode 100644
index 6006b032254..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/HttpClientProvider.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Http;
-using System.Net.Security;
-using System.Security.Cryptography.X509Certificates;
-
-namespace Xamarin.Installer.AndroidSDK.Manager
-{
- ///
- /// Creates a HttpClient.
- ///
- public static class HttpClientProvider
- {
- static Func httpClientFactory;
-
- ///
- /// Allows the default HttpClient creation to be overridden.
- ///
- /// Factory method used to create the HttpClient.
- public static void SetHttpClientFactory (Func factory)
- {
- httpClientFactory = factory;
- }
-
- ///
- /// Creates a new HttpClient.
- ///
- /// The HttpClient.
- /// The request url.
- /// The cookie container to use for the HttpClient.
- /// The decompression methods to use for the HttpClient.
- public static HttpClient CreateHttpClient (Uri uri, CookieContainer cookieContainer = null, DecompressionMethods automaticDecompression = DecompressionMethods.None)
- {
- if (httpClientFactory != null)
- return httpClientFactory.Invoke (uri);
-
- var handler = new HttpClientHandler
- {
- AutomaticDecompression = automaticDecompression,
- CheckCertificateRevocationList = true,
- ServerCertificateCustomValidationCallback = SslValidationCallback
- };
-
- if (cookieContainer != null)
- {
- handler.CookieContainer = cookieContainer;
- }
-
- if (WebRequest.DefaultWebProxy != null)
- handler.Proxy = WebRequest.DefaultWebProxy;
-
- var client = new HttpClient(handler);
- return client;
- }
-
- static bool SslValidationCallback(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
- {
- if (sslPolicyErrors == SslPolicyErrors.None)
- return true;
-
- if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
- return false;
-
- // If all we have is "Revocation Unknown" errors, then accept the certificate. Works around Enterprise proxy issues
- // such as the one described in https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2057013
- foreach (var status in chain.ChainStatus)
- {
- if (status.Status != X509ChainStatusFlags.NoError && status.Status != X509ChainStatusFlags.RevocationStatusUnknown)
- return false;
- }
-
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidApiLevel.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidApiLevel.cs
deleted file mode 100644
index c90169182dd..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidApiLevel.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Helper interface representing a component's API level
- ///
- public interface IAndroidApiLevel
- {
- ///
- /// Gets the API level.
- ///
- /// The API level.
- string ApiLevel { get; }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponent.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponent.cs
deleted file mode 100644
index 57a2e84ce88..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponent.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Interface fully describing a single Android component
- ///
- public interface IAndroidComponent
- {
- ///
- /// Occurs when status changes.
- ///
- event EventHandler StatusChanged;
-
- ///
- /// true if this component is required for an instance of Android SDK to work properly
- ///
- bool IsEssential { get; }
-
- ///
- /// Gets a value indicating whether this component ignores installation failures.
- ///
- /// true if installation failure is ignored; otherwise, false.
- bool IgnoreFailure { get; }
-
- ///
- /// Gets or sets a value indicating whether the component is present in the given Android SDK instance on disk.
- ///
- /// true if present; otherwise, false.
- bool Present { get; }
-
- ///
- /// Gets or sets a value indicating whether this component has to be
- /// updated. It will be set to true also of is false
- ///
- /// true if needs update; otherwise, false.
- bool NeedsUpdate { get; }
-
- ///
- /// Type of the component. This is a map from the textual type name in the repository manifest into an
- /// enumeration for easier searching and component identification
- ///
- /// The type of the component.
- AndroidComponentType ComponentType { get; }
-
- ///
- /// Gets the unique identifier of this particular instance. The ID is not persistent, it is valid only within
- /// a single installer session and used to retrieve download information from the hosting application.
- ///
- ///
- /// The unique identifier.
- Guid UniqueID { get; }
-
- ///
- /// Gets package path as found in the SDK repository manifest. Note that paths aren't necessarily unique, there
- /// may exist several packages with the same path but different version.
- ///
- /// The manifest path.
- string Path { get; }
-
- ///
- /// Gets the file system path where the package is (or will be) found, relative to the given Android SDK root
- /// directory. This is, essentially, value of the property converted to the proper path
- /// representation for the current operating system.
- ///
- /// The file system path.
- string FileSystemPath { get; }
-
- ///
- /// Gets a value indicating whether this is obsolete.
- ///
- /// true if obsolete; otherwise, false.
- bool Obsolete { get; }
-
- ///
- /// Type-specific information about this component
- ///
- /// Component type-specific information
- AndroidComponentInfo Info { get; }
-
- ///
- /// Gets the available component revision.
- ///
- /// Component revision.
- AndroidRevision Revision { get; }
-
- ///
- /// Gets the revision of the component as found in the given Android SDK root, if any.
- ///
- /// Revision of the installed component
- AndroidRevision InstalledRevision { get; }
-
- ///
- /// Gets the display name of the component
- ///
- /// Component display name
- string DisplayName { get; }
-
- ///
- /// Gets the detailed description of the component
- ///
- /// Detailed description of the component
- string DetailedDescription { get; }
-
- ///
- /// Gets the component dependencies, if any.
- ///
- /// Component dependencies
- IList Dependencies { get; }
-
- ///
- /// Gets the component channel.
- ///
- /// Component channel
- Channel Channel { get; }
-
- ///
- /// Gets the component archives. Only archives valid for the current operating system will be found here.
- ///
- /// Component archives
- IList Archives { get; }
-
- ///
- /// Gets the component license.
- ///
- /// Component license
- License License { get; }
-
- ///
- /// Gets the URL of the manifest from which the component description was loaded.
- ///
- /// The manifest URL.
- Uri ManifestURL { get; }
-
- ///
- /// Hosting application can set this to true if it wants the installer to ignore value of the
- /// property and force (re)installation of the component. This property must be set before the component is passed to the
- /// method.
- ///
- /// true to force installation; otherwise, false.
- bool ForceInstallation { get; set; }
-
- ///
- /// ID of the license the component uses
- ///
- string LicenseID { get; set; }
-
- ///
- /// Compares properties related to Path and Revision,
- /// and returns True, if they are same for the matching components.
- ///
- /// Component to compare with
- ///
- bool MatchesTo (IAndroidComponent other);
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponentInternal.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponentInternal.cs
deleted file mode 100644
index 6a28f594672..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponentInternal.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2018, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- interface IAndroidComponentInternal
- {
- void Remove (string androidSDKRoot);
- void PerformDetection (string androidSDKRoot, bool isRefresh = false);
- void RefreshMetadata (IAndroidComponent component, bool ignoreInstalledState = true);
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IArchive.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IArchive.cs
deleted file mode 100644
index f05530d9c1f..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IArchive.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public interface IArchive
- {
- ///
- /// Gets the archive size
- ///
- /// Archive size
- ulong Size { get; }
-
- ///
- /// Gets the SHA1 checksum of the archive
- ///
- /// SHA1 checksum
- string Checksum { get; }
-
- ///
- /// Gets the archive URL
- ///
- /// Archive URL
- Uri Url { get; }
-
- ///
- /// Gets the target (host) operating system of the archive (if any)
- ///
- /// Host operating system
- string HostOS { get; }
-
- ///
- /// Mapping of into one of the enumeration members
- ///
- /// Archive platform.
- AndroidSDKPlatform Platform { get; }
-
- ///
- /// Native word size of the host operating system.
- ///
- /// Host operating system word size
- uint HostBits { get; }
-
- ///
- /// CPU Architecture of the host operating system.
- ///
- /// Host operating CPU architecture
- string HostArch { get; }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IJdkComponent.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IJdkComponent.cs
deleted file mode 100644
index 0a04fb4ba7a..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IJdkComponent.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public interface IJdkComponent
- {
- Guid UniqueID { get; }
-
- string DisplayName { get; }
-
- bool Obsolete { get; }
-
- bool Preview { get; }
-
- string LicenseID { get; }
-
- PackageVendor Vendor { get; }
-
- AndroidRevision Revision { get; }
-
- ///
- /// Gets the component archives
- ///
- /// Component archives
- IList Archives { get; }
-
- IEnumerable GetValidArchivesForSystem();
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ILicensesStorage.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ILicensesStorage.cs
deleted file mode 100644
index de4ece78fc7..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ILicensesStorage.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public interface ILicensesStorage
- {
- ///
- /// Returns if the license was accepted in this Android SDK
- ///
- /// Android Sdk path
- /// license to check
- /// true if the license is accepted, false otherwise
- bool IsLicenseAccepted(string androidSdkPath, License license);
-
- ///
- /// Accept licenses
- ///
- /// Android Sdk path
- /// Java Sdk path
- /// specific cmdLine-tools path to use
- /// list of licenses to accept
- /// cancellation token
- /// log file path
- /// throw exception with arguments validation error
- Task AcceptLicensesAsync(
- string androidSdkPath,
- string javaSdkPath,
- string cmdLineToolsPath,
- IEnumerable licenses,
- CancellationToken token,
- string logPath = null,
- bool throwsErrorIfValidationFailed = false);
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithID.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithID.cs
deleted file mode 100644
index 837d55cbf7b..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithID.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Marek Habersack
-//
-// All rights reserved.
-//
-
-#nullable enable
-
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Base class for all types with a string identifier
- ///
- public abstract class ItemWithID : IEquatable
- {
- ///
- /// Gets the identifier string.
- ///
- /// The identifier string
- public string ID { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Identifier (required)
- protected ItemWithID (string id)
- {
- if (String.IsNullOrEmpty (id))
- throw new ArgumentException ("Must not be null or empty", nameof (id));
- ID = id;
- }
-
- public bool Equals (ItemWithID? other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals (this, other))
- return true;
-
- if (!string.Equals (ID, other.ID, StringComparison.Ordinal))
- return false;
-
- return true;
- }
-
- public override bool Equals (object? obj)
- {
- return Equals (obj as ItemWithID);
- }
-
- public override int GetHashCode ()
- {
- return ID?.GetHashCode () ?? 0;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithIDAndDisplay.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithIDAndDisplay.cs
deleted file mode 100644
index 5f3a4eedf72..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithIDAndDisplay.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Abstract base class for all the clases that have some sort of identifier and a display name.
- ///
- public abstract class ItemWithIDAndDisplay : ItemWithID
- {
- ///
- /// Gets the display name of the item
- ///
- /// Item display name
- public string Display { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Identifier.
- /// Display.
- protected ItemWithIDAndDisplay (string id, string display) : base (id)
- {
- Display = display ?? String.Empty;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkArchive.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkArchive.cs
deleted file mode 100644
index da3b9a016a2..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkArchive.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-#nullable enable
-
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public class JdkArchive : Archive, IEquatable
- {
- public JdkArchive(string hostOS) : base(hostOS)
- {
- }
-
- public string? PayloadFileName { get; set; }
-
- public override bool IsValidForSystem()
- {
- return IsPlatformValid() && IsHostArchValid();
- }
-
- public override bool Equals(Object? obj)
- {
- return Equals(obj as JdkArchive);
- }
-
- public bool Equals(JdkArchive? other)
- {
- if (other == null)
- return false;
-
- return base.Equals(other);
- }
-
- public override int GetHashCode()
- {
- return this.HostOS.GetHashCode();
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkPackage.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkPackage.cs
deleted file mode 100644
index 4a4e45c925a..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkPackage.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-#nullable enable
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public class JdkPackage : IJdkComponent
- {
- public JdkPackage(string displayName, bool obsolete, bool preview, string licenseId, PackageVendor vendor, AndroidRevision revision, List archives)
- {
- DisplayName = displayName;
- Obsolete = obsolete;
- Preview = preview;
- Vendor = vendor;
- Revision = revision;
- Archives = archives;
- LicenseID = licenseId;
- }
-
- public Guid UniqueID { get; } = Guid.NewGuid();
-
- public string DisplayName { get; }
-
- public bool Obsolete { get; }
-
- public bool Preview { get; }
-
- public string LicenseID { get; }
-
- public PackageVendor Vendor { get; }
-
- public AndroidRevision Revision { get; }
-
- public IList Archives { get; }
-
- public IEnumerable GetValidArchivesForSystem()
- {
- return Archives.Where(x => x.IsValidForSystem());
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/License.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/License.cs
deleted file mode 100644
index 26234b90e18..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/License.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Represents component License
- ///
- public sealed class License : ItemWithID, IEquatable
- {
- ///
- /// Content type. Currently only text is defined.
- ///
- /// Content type.
- public string Type { get; }
-
- ///
- /// Gets text of the license.
- ///
- /// License text
- public string Text { get; }
-
- internal License (string id, string type, string text) : base (id)
- {
- Type = type;
- Text = text;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals (License other)
- {
- if (other == null)
- return false;
-
- if (ReferenceEquals (this, other))
- return true;
-
- if (!string.Equals (ID, other.ID, StringComparison.Ordinal))
- return false;
-
- if (!string.Equals (Type, other.Type, StringComparison.Ordinal))
- return false;
-
- if (!string.Equals (Text, other.Text, StringComparison.Ordinal))
- return false;
-
- return true;
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as License);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = 0;
-
- hashCode = hashCode.XorWith (ID?.GetHashCode ());
- hashCode = hashCode.XorWith (Type?.GetHashCode ());
- return hashCode.XorWith (Text?.GetHashCode ());
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageLibrary.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageLibrary.cs
deleted file mode 100644
index b21f34ebdf3..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageLibrary.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a single library contained in a package
- ///
- public sealed class PackageLibrary : IEquatable
- {
- ///
- /// Gets the local path of the library JAR archive.
- ///
- /// Path to the JAR archive
- public string LocalJarPath { get; internal set; }
-
- ///
- /// Gets the library name
- ///
- /// Library name
- public string Name { get; internal set; }
-
- ///
- /// Gets the library description.
- ///
- /// The description.
- public string Description { get; internal set; }
-
- ///
- /// Determines whether the specified is equal to the
- /// current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the
- /// current ; otherwise, false.
- public bool Equals (PackageLibrary other)
- {
- if (other == null)
- return false;
-
- if (!ReferenceEquals (this, other))
- return false;
-
- return string.Equals (LocalJarPath, other.LocalJarPath, StringComparison.Ordinal);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as PackageLibrary);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (LocalJarPath != null)
- hashCode = hashCode.XorWith (LocalJarPath.GetHashCode ());
-
- if (Name != null)
- hashCode = hashCode.XorWith (Name.GetHashCode ());
-
- if (Description != null)
- hashCode = hashCode.XorWith (Description.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageMetadata.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageMetadata.cs
deleted file mode 100644
index 7ab34e8dee6..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageMetadata.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2018, Microsoft Corp. (https://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- public class PackageMetadata
- {
- public bool Present { get; set; }
- public bool NeedsUpdate { get; set; }
- public string Path { get; set; }
- public string FileSystemPath { get; set; }
- public bool Obsolete { get; set; }
- public bool Preview => GetPreview ();
- public AndroidComponentInfo Info { get; set; }
- public AndroidRevision Revision { get; set; }
- public AndroidRevision InstalledRevision { get; set; }
- public string DisplayName { get; set; }
- public IList Dependencies { get; set; }
- public IList Archives { get; set; }
- public string LicenseID { get; set; }
-
- public PackageMetadata (IAndroidComponent component)
- {
- if (component == null)
- throw new ArgumentNullException (nameof (component));
-
- Present = component.Present;
- NeedsUpdate = component.NeedsUpdate;
- Path = component.Path;
- FileSystemPath = component.FileSystemPath;
- Obsolete = component.Obsolete;
- Info = component.Info;
- Revision = component.Revision;
- InstalledRevision = component.InstalledRevision;
- DisplayName = component.DisplayName;
- Dependencies = component.Dependencies != null ? new List (component.Dependencies) : null;
- Archives = component.Archives != null ? new List (component.Archives) : null;
- LicenseID = component.LicenseID;
- }
-
- bool GetPreview ()
- {
- if (Info is AndroidComponentInfoPlatform platform) {
- return platform.Preview;
- }
- return false;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageTag.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageTag.cs
deleted file mode 100644
index efe22b3fe65..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageTag.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a package tag.
- ///
- public sealed class PackageTag : ItemWithIDAndDisplay, IEquatable
- {
- public PackageTag (string id, string display) : base (id, display)
- {}
-
- ///
- /// Determines whether the specified is equal to the
- /// current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public bool Equals (PackageTag other)
- {
- if (other == null)
- return false;
-
- if (!ReferenceEquals (this, other))
- return false;
-
- if (!string.Equals (ID, other.ID, StringComparison.Ordinal))
- return false;
-
- return string.Equals (Display, other.Display, StringComparison.Ordinal);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as PackageTag);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (ID != null)
- hashCode = hashCode.XorWith (ID.GetHashCode ());
- if (Display != null)
- hashCode = hashCode.XorWith (Display.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageVendor.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageVendor.cs
deleted file mode 100644
index 7caf450d5bd..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageVendor.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK.Common
-{
- ///
- /// Describes a package vendor
- ///
- public sealed class PackageVendor : ItemWithIDAndDisplay, IEquatable
- {
- public PackageVendor (string id, string display) : base (id, display)
- {
- }
-
- ///
- /// Determines whether the specified is equal to the
- /// current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the
- /// current ; otherwise, false.
- public bool Equals (PackageVendor other)
- {
- if (other == null)
- return false;
-
- if (!ReferenceEquals (this, other))
- return false;
-
- if (!string.Equals (ID, other.ID, StringComparison.Ordinal))
- return false;
-
- return string.Equals (Display, other.Display, StringComparison.Ordinal);
- }
-
- ///
- /// Determines whether the specified is equal to the current .
- ///
- /// The to compare with the current .
- /// true if the specified is equal to the current
- /// ; otherwise, false.
- public override bool Equals (object obj)
- {
- return Equals (obj as PackageVendor);
- }
-
- ///
- /// Serves as a hash function for a object.
- ///
- /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.
- public override int GetHashCode ()
- {
- int hashCode = base.GetHashCode ();
-
- if (ID != null)
- hashCode = hashCode.XorWith (ID.GetHashCode ());
- if (Display != null)
- hashCode = hashCode.XorWith (Display.GetHashCode ());
-
- return hashCode;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Platform.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Platform.cs
deleted file mode 100644
index 208a3645a5e..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Platform.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-#nullable enable
-
-//
-// Platform.cs
-//
-// Author:
-// Vsevolod Kukol
-//
-// Copyright (c) 2017, Microsoft, Inc
-//
-
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
-
-namespace Xamarin.Installer.AndroidSDK.Manager
-{
- public static class Platform
- {
- public readonly static bool IsWindows;
- public readonly static bool IsMac;
- public readonly static bool IsLinux;
- public static Version OSVersion { get; private set; }
-
- static Platform ()
- {
- IsWindows = Path.DirectorySeparatorChar == '\\';
- IsMac = !IsWindows && IsRunningOnMac ();
- IsLinux = !IsMac && !IsWindows;
- OSVersion = Environment.OSVersion.Version;
- }
-
- [DllImport ("libc")]
- static extern int uname (IntPtr buf);
-
- //From Managed.Windows.Forms/XplatUI
- static bool IsRunningOnMac ()
- {
- IntPtr buf = IntPtr.Zero;
- try {
- buf = Marshal.AllocHGlobal (8192);
- // This is a hacktastic way of getting sysname from uname ()
- if (uname (buf) == 0) {
- string? os = Marshal.PtrToStringAnsi (buf);
- if (os == "Darwin")
- return true;
- }
- } catch {
- } finally {
- if (buf != IntPtr.Zero)
- Marshal.FreeHGlobal (buf);
- }
- return false;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/DirectorySizeMonitoringTimer.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/DirectorySizeMonitoringTimer.cs
deleted file mode 100644
index f0d334ecba7..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/DirectorySizeMonitoringTimer.cs
+++ /dev/null
@@ -1,156 +0,0 @@
-using ICSharpCode.SharpZipLib.Zip;
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using Xamarin.Android.Tools;
-using Xamarin.Installer.Common;
-using Xamarin.Installer.AndroidSDK.Manager;
-using Timer = System.Timers.Timer;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- public class DirectorySizeMonitoringTimer : IDisposable
- {
- const int MIN_MOVE_PROGRESS_SPLIT = 10, MAX_MOVE_PROGRESS_SPLIT = 50;
- const int SMALL_NUMBER_OF_FILES = 1, BIG_NUMBER_OF_FILES = 10000;
-
- Timer timer;
- float maxProgress, targetMaxProgress;
- Action progressUpdateAction;
- bool disposed;
-
- public DirectorySizeMonitoringTimer (string targetDirectoryPath, string dirToCompareWith, Action progressUpdateAction,
- float remapFrom = 0f, float remapTo = 100f, double checkInterval = 500d)
- {
- this.progressUpdateAction = progressUpdateAction;
- maxProgress = -1f;
- targetMaxProgress = remapTo;
-
- progressUpdateAction?.Invoke (remapFrom);
-
- if (!Platform.IsMac)
- return;
-
- ulong? totalExpectedSize = null;
-
- timer = new Timer { Interval = checkInterval, AutoReset = false };
- timer.Elapsed += async (_, __) => {
- if (disposed)
- return;
-
- if (!totalExpectedSize.HasValue)
- totalExpectedSize = await GetDirectorySizeAsync (dirToCompareWith);
-
- if (disposed)
- return;
-
- var size = await GetDirectorySizeAsync (targetDirectoryPath);
- if (size > totalExpectedSize.Value)
- size = totalExpectedSize.Value;
-
- if (disposed)
- return;
-
- float progress = (float) Remap (size * 100f / totalExpectedSize.Value, 0f, 100f, remapFrom, remapTo);
- if (progress > maxProgress) {
- // Logger.Debug ($"[DirectorySizeMonitoringTimer] size: {size} / totalExpectedSize: {totalExpectedSize} --> {progress}");
- progressUpdateAction.Invoke (progress);
- maxProgress = progress;
- }
-
- if (!disposed)
- timer.Start();
- };
- timer.Start ();
- }
-
- public void Dispose ()
- {
- disposed = true;
- //Logger.Debug ($"DirectorySizeMonitoringTimer disposing");
- timer?.Stop ();
- timer?.Dispose ();
-
- if (maxProgress < targetMaxProgress)
- progressUpdateAction?.Invoke (targetMaxProgress);
-
- progressUpdateAction = null;
- }
-
- async Task GetDirectorySizeAsync (string directory)
- {
- if (!Platform.IsMac)
- return 0;
-
- var result = 0uL;
- var duCommand = "/usr/bin/du";
- var process = ProcessUtils.CreateProcessStartInfo (duCommand, "-sk", directory);
- string sizeOutput = null;
- try {
- using (var output = new StringWriter ())
- using (var error = new StringWriter ()) {
- int exitCode = await ProcessUtils.StartProcess (process, output, error, CancellationToken.None);
- if (exitCode != 0)
- throw new InvalidOperationException ($"{duCommand} exited with code {exitCode}: {error}");
- sizeOutput = output.ToString ();
- }
- } catch (Exception ex) {
- if (ex?.Message?.Contains ("No such file or directory") == true) {
- Logger.Debug ($"[DirectorySizeMonitoringTimer] WARN! Dir \"{directory}\" was removed before \"/usr/bin/du\" could calculate its size");
- } else {
- Logger.Warning ($"[DirectorySizeMonitoringTimer] ProcessUtils.StartProcess failed to execute {duCommand}.\n{ex}");
- }
- }
-
- if (!String.IsNullOrEmpty (sizeOutput)) {
- sizeOutput = sizeOutput.Replace (directory, string.Empty).Trim ();
- if (ulong.TryParse (sizeOutput, out ulong parsed)) {
- // "k" gives size in KBytes
- result = parsed * 1024;
- }
- }
- return result;
- }
-
- public static double Remap (double value, double from1, double to1, double from2, double to2)
- {
- var mapping = (value - from1) / (to1 - from1) * (to2 - from2) + from2;
- if (mapping < from2)
- mapping = from2;
- if (mapping > to2)
- mapping = to2;
- return mapping;
- }
-
- public static ulong CalculateTotalSize (ZipFile zipFile)
- {
- ulong totalSize = 0;
- foreach (ZipEntry entry in zipFile)
- totalSize += (ulong) entry.Size;
- Logger.Debug ($"[DirectorySizeMonitoringTimer] ZipFile totalSize: {totalSize}");
-
- return totalSize;
- }
-
- ///
- /// Move operation will take different time depending on number of files in an archive
- /// so we split the 100% installation progress according these values (unzip + move = 100%)
- ///
- /// The path to the archive file.
- /// Amount of percents for the Move part of the installation
- public static int CalculateMoveProgressSplit (string archivePath)
- {
- ZipFile zip = null;
- long filesCount;
- try {
- zip = new ZipFile (archivePath);
- filesCount = zip.Count;
- } finally {
- zip?.Close ();
- }
-
- return (int) Remap (filesCount, SMALL_NUMBER_OF_FILES, BIG_NUMBER_OF_FILES, MIN_MOVE_PROGRESS_SPLIT, MAX_MOVE_PROGRESS_SPLIT);
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IAndroidComponent.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IAndroidComponent.cs
deleted file mode 100644
index 4c9f17c80c2..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IAndroidComponent.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using Xamarin.Installer.AndroidSDK.Common;
-using Xamarin.Installer.AndroidSDK.GoogleV2;
-using Xamarin.Installer.AndroidSDK.Xamarin;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- partial class Extensions
- {
- internal static IAndroidComponent Clone (this IAndroidComponent component)
- {
- if (component == null)
- return null;
-
- var rp = component as RemotePackage;
- if (rp != null)
- return RemotePackage.Clone (rp);
-
- var xp = component as XamarinPackage;
- if (xp != null)
- return XamarinPackage.Clone (xp);
-
- throw new InvalidOperationException ($"Unknown component type {component.GetType ()}");
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfIAndroidComponent.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfIAndroidComponent.cs
deleted file mode 100644
index 38994109364..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfIAndroidComponent.cs
+++ /dev/null
@@ -1,266 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using Xamarin.Installer.AndroidSDK.Common;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- ///
- /// Extensions to make it easier to select components from a full component set.
- ///
- public static class PublicExtensions
- {
- ///
- /// Checks whether any components in the passed set are outdated.
- ///
- /// true, if outdated components were found, false otherwise.
- /// Components.
- public static bool AnyOutdated (this IList components)
- {
- return components?.Any (c => c != null && c.NeedsUpdate) ?? false;
- }
-
- ///
- /// Checks whether any components in the set aren't preset on the system
- ///
- /// true, if there are any missing components, false otherwise.
- /// Components.
- public static bool AnyNotInstalled (this IList components)
- {
- return components?.Any (c => c != null && !c.Present) ?? false;
- }
-
- ///
- /// Returns a list of all outdated or missing components from the passed set/
- ///
- /// The outdated or missing components.
- /// Components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllOutdatedOrMissing (this IList components, Func shouldInclude = null)
- {
- var ret = new List ();
- ret.AddRange (components.AllOutdated (shouldInclude));
- ret.AddRange (components.AllNotInstalled (shouldInclude: shouldInclude));
-
- return ret;
- }
-
- ///
- /// Gets all outdated components from the passed set. The returned list contains outdated components from all
- /// channels.
- ///
- /// List of all the outdated components
- /// Aource list of components
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllOutdated (this IList components, Func shouldInclude = null)
- {
- return components?.Where (c => c != null && c.Present && c.NeedsUpdate && (shouldInclude == null || shouldInclude (c)))?.ToList ();
- }
-
- ///
- /// Gets all installed components from the passed set. The returned list contains components from all channels
- ///
- /// List of all installed components
- /// Source list of components
- /// If set to true include outdated components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllInstalled (this IList components, bool includeOutdated = true, Func shouldInclude = null)
- {
- return components?.Where (c => c != null && c.Present && (includeOutdated || !c.NeedsUpdate) && (shouldInclude == null || shouldInclude(c)))?.ToList ();
- }
-
- ///
- /// Gets all components that aren't installed from the passed set. The returned list contains components from all channels
- ///
- /// List of or components that aren't installed
- /// Source list of components
- /// If set to true include obsolete components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllNotInstalled (this IList components, bool includeObsolete = false, Func shouldInclude = null)
- {
- return components?.Where (c => c != null && !c.Present && (includeObsolete || !c.Obsolete) && (shouldInclude == null || shouldInclude(c)))?.ToList ();
- }
-
- ///
- /// Gets all the components of the specified type from the passed set. The returned list contains components from all channels
- ///
- /// List of components of the specified type
- /// Source list of components
- /// Component type
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllOfType (this IList components, AndroidComponentType type, Func shouldInclude = null)
- {
- return GetAllOfType (components, type, shouldInclude)?.ToList ();
- }
-
- ///
- /// Gets all the platform components from the passed set.
- ///
- /// List of platform components
- /// Source list of components
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllPlatforms (this IList components, Func shouldInclude = null)
- {
- return GetAllOfType (components, AndroidComponentType.Platform, shouldInclude)?.ToList ();
- }
-
- ///
- /// Gets all the system image components from the passed set. The returned list contains components from all channels
- ///
- /// List of system image components.
- /// Source list of components
- /// Select only components that use this ABI
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllSystemImages (this IList components, AndroidSystemImageAbi forABI = AndroidSystemImageAbi.Any, Func shouldInclude = null)
- {
- return GetAllOfType (components, AndroidComponentType.SystemImage, shouldInclude)?.Where (c => forABI == AndroidSystemImageAbi.Any || (c.Info as AndroidComponentInfoSystemImage).Abi == forABI)?.ToList ();
- }
-
- ///
- /// Gets all the components that use the specified API level (platform). The returned list contains components from all channels
- ///
- /// List of components using the specified API level
- /// Source list of components
- /// API level to match.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllApiLevel (this IList components, string apiLevel = null, Func shouldInclude = null)
- {
- return GetAllApiLevel (components, apiLevel, shouldInclude)?.ToList ();
- }
-
- ///
- /// Gets all the components with a matching path. The returned list contains components from all channels
- ///
- /// List of components with a matching path
- /// Source list of components
- /// Path.
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- /// If true it will check whether the component path starts with the specified one.
- public static IList AllWithPath (this IListcomponents, string path, AndroidRevision minimumRevision = null, Func shouldInclude = null, bool matchPathStartOnly = false)
- {
- if (String.IsNullOrEmpty (path))
- return null;
-
- return components?.Where (c => c != null &&
- !String.IsNullOrEmpty (c.Path) &&
- PathMatches (c) &&
- (minimumRevision == null || c.Revision >= minimumRevision) &&
- (shouldInclude == null || shouldInclude (c)))?.ToList ();
-
- bool PathMatches (IAndroidComponent c)
- {
- if (c == null || c.Path == null)
- return false;
-
- if (matchPathStartOnly)
- return c.Path.StartsWith (path, StringComparison.Ordinal);
- return string.Equals (c.Path, path, StringComparison.Ordinal);
- }
- }
-
- ///
- /// Get all of the Build Tools components. The returned list contains components from all channels
- ///
- /// List of the Build Tools components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllBuildTools (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.BuildTools, minimumRevision, shouldInclude, true);
- }
-
- ///
- /// Get all of the Tools components. The returned list contains components from all channels
- ///
- /// List of the Tools components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllTools (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.Tools, minimumRevision, shouldInclude, true);
- }
-
- ///
- /// Get all of the Platform Tools components. The returned list contains components from all channels
- ///
- /// List of the Platform Tools components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllPlatformTools(this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.PlatformTools, minimumRevision, shouldInclude);
- }
-
- ///
- /// Get all of the Emulator components. The returned list contains components from all channels
- ///
- /// List of the Emulator components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllEmulators (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.Emulator, minimumRevision, shouldInclude);
- }
-
- ///
- /// Get all of the CMake components. The returned list contains components from all channels
- ///
- /// List of the CMake components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllCMake (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.CMake, minimumRevision, shouldInclude, true);
- }
-
- ///
- /// Get all of the LLDB components. The returned list contains components from all channels
- ///
- /// List of the LLDB components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllLLDB (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.LLDB, minimumRevision, shouldInclude, true);
- }
-
- ///
- /// Get all of the NDK components. The returned list contains components from all channels
- ///
- /// List of the Emulator components
- /// Source list of components
- /// Minimum revision of the components.
- /// An optional delegate which decides whether or not to include the component passed to it
- public static IList AllNDK (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return components.AllWithPath (Constants.ComponentPaths.NDK, minimumRevision, shouldInclude);
- }
-
- public static IList AllAddons (this IList components, AndroidRevision minimumRevision = null, Func shouldInclude = null)
- {
- return GetAllOfType (components, AndroidComponentType.Addon, shouldInclude)?.ToList ();
- }
-
- static IEnumerable GetAllApiLevel (IList components, string apiLevel, Func shouldInclude)
- {
- bool haveApiLevel = !String.IsNullOrEmpty (apiLevel);
- return components?.OfType ()?.
- Where (c => c != null && (!haveApiLevel || string.Equals(c.ApiLevel, apiLevel, StringComparison.OrdinalIgnoreCase)))?.
- Select (c => c as IAndroidComponent).
- Where (c => shouldInclude == null || shouldInclude(c));
- }
-
- static IEnumerable GetAllOfType (IList components, AndroidComponentType type, Func shouldInclude)
- {
- return components?.Where (c => c != null && c.ComponentType == type && (shouldInclude == null || shouldInclude(c)));
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfT.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfT.cs
deleted file mode 100644
index 46af9a6d574..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfT.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Marek Habersack
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- static partial class Extensions
- {
- public static bool AreEqual (this IList one, IList two)
- {
- if (one == null)
- return two == null;
- if (two == null)
- return false;
-
- if (one.Count != two.Count)
- return false;
-
- // Order of elements shouldn't matter I think
- foreach (T item in one) {
- if (!two.Contains (item))
- return false;
- }
-
- return true;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IXmlLineInfo.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IXmlLineInfo.cs
deleted file mode 100644
index bfa08892c0d..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IXmlLineInfo.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Marek Habersack
-//
-// All rights reserved.
-//
-using System;
-using System.Xml;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- static partial class Extensions
- {
- public static string AsString (this IXmlLineInfo info, string openBracket = "[", string closeBracket = "]")
- {
- if (info == null || (info.LineNumber < 0 && info.LinePosition < 0))
- return String.Empty;
- string open = openBracket ?? String.Empty;
- string close = closeBracket ?? String.Empty;
-
- return $"{open}{info.LineNumber}:{info.LinePosition}{close}";
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Int32.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Int32.cs
deleted file mode 100644
index c1b79af8572..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Int32.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Marek Habersack
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- static partial class Extensions
- {
- public static int XorWith (this int value, int? maybeValue)
- {
- if (!maybeValue.HasValue)
- return value;
-
- return XorWith (value, maybeValue.Value);
- }
-
- public static int XorWith (this int value, int otherValue)
- {
- return value ^ otherValue;
-
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Properties.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Properties.cs
deleted file mode 100644
index 267ac86a8b8..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Properties.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- static partial class Extensions
- {
- public static bool GetProperty (this IDictionary props, string name, out T result)
- {
- result = default (T);
- if (props == null)
- return false;
- if (!props.TryGetValue (name, out string value))
- return false;
- if (value != null)
- value = value.Trim ();
- if (String.IsNullOrEmpty (value))
- return false;
-
- if (typeof (T) == typeof (string)) {
- result = (T)((object)value);
- return true;
- }
-
- try {
- result = (T)Convert.ChangeType (value, typeof (T));
- } catch {
- // ignore
- return false;
- }
- return true;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.String.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.String.cs
deleted file mode 100644
index cfc4713a904..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.String.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Marek Habersack
-//
-// All rights reserved.
-//
-using System;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- static partial class Extensions
- {
- public static uint AsUInt (this string s, bool throwOnError = false)
- {
- if (String.IsNullOrEmpty (s))
- return 0;
-
- uint ret;
- if (UInt32.TryParse (s, out ret))
- return ret;
-
- if (throwOnError)
- throw new InvalidOperationException ($"Unable to convert string '{s}' to an unsigned integer");
- return 0;
- }
-
- public static ulong AsULong (this string s, bool throwOnError = false)
- {
- if (String.IsNullOrEmpty (s))
- return 0;
-
- ulong ret;
- if (UInt64.TryParse (s, out ret))
- return ret;
-
- if (throwOnError)
- throw new InvalidOperationException ($"Unable to convert string '{s}' to an unsigned long integer");
- return 0;
- }
-
- public static bool AsBool (this string s, bool throwOnError = false)
- {
- if (String.IsNullOrEmpty (s))
- return false;
-
- bool ret;
- if (Boolean.TryParse (s, out ret))
- return ret;
-
- if (throwOnError)
- throw new InvalidOperationException ($"Unable to convert string '{s}' to boolean");
-
- return false;
- }
-
- public static Uri AsUri (this string s, bool throwOnError = false)
- {
- if (String.IsNullOrEmpty (s))
- return null;
-
- Uri ret;
- if (Uri.TryCreate (s, UriKind.RelativeOrAbsolute, out ret))
- return ret;
-
- if (throwOnError)
- throw new InvalidOperationException ($"Unable to parse string '{s}' as a valid URI");
-
- return null;
- }
- }
-}
diff --git a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.XElement.cs b/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.XElement.cs
deleted file mode 100644
index ff64a9e22d8..00000000000
--- a/src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.XElement.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// Authors:
-// Marek Habersack
-//
-// Copyright (c) 2017, Microsoft Corp. (http://microsoft.com)
-//
-// All rights reserved.
-//
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Xml;
-using System.Xml.Linq;
-
-using Xamarin.Installer.Common;
-
-namespace Xamarin.Installer.AndroidSDK
-{
- public static partial class Extensions
- {
- public static void GetLineInfo (this XElement e, out int line, out int column)
- {
- IXmlLineInfo linfo = e.GetLineInfo ();
- if (linfo == null || !linfo.HasLineInfo ()) {
- line = column = -1;
- return;
- }
- line = linfo.LineNumber;
- column = linfo.LinePosition;
- }
-
- public static IXmlLineInfo GetLineInfo (this XElement e)
- {
- return e as IXmlLineInfo;
- }
-
- public static string GetLocation (this XElement e, Uri documentUrl = null)
- {
- if (e == null)
- return String.Empty;
-
- if (documentUrl == null)
- return e.GetLineInfo ().AsString ("(", ")");
-
- return $"({documentUrl} {e.GetLineInfo ().AsString ()}";
- }
-
- public static string GetChildElementValue (this XElement element, string childName)
- {
- if (element == null)
- return String.Empty;
-
- XElement child = element.Elements (childName)?.FirstOrDefault ();
- return child?.Value ?? String.Empty;
- }
-
- public static string GetAttributeValue (this XElement e, string name, bool required = true, Uri documentUrl = null)
- {
- XAttribute ret = e.GetAttribute (name);
- if (ret == null) {
- if (required)
- throw new InvalidOperationException ($"Required attribute '{name}' missing for element {e?.Name} at {e.GetLocation (documentUrl)}");
- return String.Empty;
- }
-
- return ret.Value;
- }
-
- public static XAttribute GetAttribute (this XElement e, string name)
- {
- return e?.Attribute (name);
- }
-
- public static XAttribute GetAttribute (this XElement e, XNamespace ns, string name)
- {
- return e?.Attribute (ns + name);
- }
-
- public static string GetElementValue (this XElement e)
- {
- return e?.Value?.Trim ();
- }
-
- public static void GetNamespaces (this XElement root, Uri docURL, ref Dictionary namespaces)
- {
- if (root == null || !root.HasAttributes)
- return;
-
- foreach (XAttribute attr in root.Attributes ())
- GetNamespace (root, attr, docURL, ref namespaces);
- }
-
- static void GetNamespace (XElement element, XAttribute attr, Uri docURL, ref Dictionary