void CleanupBeforeInstall()
 {
     foreach (string dir in allRuntimes.OutputDirectories)
     {
         Utilities.DeleteDirectorySilent(dir);
     }
 }
Esempio n. 2
0
        async Task <bool> DownloadAndUpackIfNeeded(Context context, string name, string customUrl, string localPath, string archiveFileName, string destinationDirectory)
        {
            if (File.Exists(localPath))
            {
                Log.StatusLine($"{name} archive already downloaded");
            }
            else
            {
                Utilities.DeleteFileSilent(localPath);

                var url = string.IsNullOrEmpty(customUrl) ?
                          new Uri(Configurables.Urls.MonoArchive_BaseUri, archiveFileName) :
                          new Uri(customUrl);
                Log.StatusLine($"Downloading {name} archive from {url}");

                (bool success, ulong size, HttpStatusCode status) = await Utilities.GetDownloadSizeWithStatus(url);

                if (!success)
                {
                    if (status == HttpStatusCode.NotFound)
                    {
                        Log.Info($"{name} archive URL not found");
                    }
                    else
                    {
                        Log.Info($"Failed to obtain {name} archive size. HTTP status code: {status} ({(int)status})");
                    }
                    Log.InfoLine(". Mono runtimes will be rebuilt");
                    return(false);
                }

                DownloadStatus downloadStatus = Utilities.SetupDownloadStatus(context, size, context.InteractiveSession);
                Log.StatusLine($"  {context.Characters.Link} {url}", ConsoleColor.White);
                await Download(context, url, localPath, $"{name} Archive", archiveFileName, downloadStatus);

                if (!File.Exists(localPath))
                {
                    Log.InfoLine($"Download of {name} archive from {url} failed, Mono will be rebuilt");
                    return(false);
                }
            }

            string tempDir = $"{destinationDirectory}.tmp";

            if (!await Utilities.Unpack(localPath, tempDir, cleanDestinatioBeforeUnpacking: true))
            {
                Utilities.DeleteDirectorySilent(destinationDirectory);
                Log.WarningLine($"Failed to unpack {name} archive {localPath}, Mono will be rebuilt");
                return(false);
            }

            Log.DebugLine($"Moving unpacked Mono archive from {tempDir} to {destinationDirectory}");
            try {
                Utilities.MoveDirectoryContentsRecursively(tempDir, destinationDirectory, resetFileTimestamp: true);
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
            }

            return(true);
        }
Esempio n. 3
0
        bool InstallBCL(Context context)
        {
            string redistListDir = MonoRuntimesHelpers.BCLRedistListDestinationDir;

            foreach (KeyValuePair <BclFileTarget, string> kvp in MonoRuntimesHelpers.BCLDestinationDirs)
            {
                Utilities.CreateDirectory(kvp.Value);
            }

            foreach (KeyValuePair <BclFileTarget, string> kvp in MonoRuntimesHelpers.BCLFacadesDestinationDirs)
            {
                Utilities.CreateDirectory(kvp.Value);
            }

            Utilities.CreateDirectory(redistListDir);

            StatusStep(context, "Installing Android BCL assemblies");
            InstallBCLFiles(allRuntimes.BclFilesToInstall);

            StatusStep(context, "Installing Designer Host BCL assemblies");
            InstallBCLFiles(allRuntimes.DesignerHostBclFilesToInstall);

            StatusStep(context, "Installing Designer Windows BCL assemblies");
            InstallBCLFiles(allRuntimes.DesignerWindowsBclFilesToInstall);

            Utilities.DeleteDirectorySilent(Configurables.Paths.BCLWindowsOutputDir);

            return(GenerateFrameworkList(
                       context,
                       MonoRuntimesHelpers.FrameworkListPath,
                       MonoRuntimesHelpers.BCLDestinationDirs [BclFileTarget.Android],
                       MonoRuntimesHelpers.BCLFacadesDestinationDirs [BclFileTarget.Android]
                       ));
        }
Esempio n. 4
0
        protected override async Task <bool> Execute(Context context)
        {
            string corettoInstallDir = Configurables.Paths.CorrettoInstallDir;

            if (CorrettoExistsAndIsValid(corettoInstallDir, out string installedVersion))
            {
                Log.Status("Corretto version ");
                Log.Status(installedVersion, ConsoleColor.Yellow);
                Log.StatusLine(" already installed in: ", corettoInstallDir, tailColor: ConsoleColor.Cyan);
                return(true);
            }

            Log.StatusLine($"Corretto JDK {Configurables.Defaults.CorrettoVersion} will be installed");
            Uri correttoURL = Configurables.Urls.Corretto;

            if (correttoURL == null)
            {
                throw new InvalidOperationException("Corretto URL must not be null");
            }

            string packageName      = Path.GetFileName(correttoURL.LocalPath);
            string localPackagePath = Path.Combine(Configurables.Paths.CorrettoCacheDir, packageName);

            if (!await DownloadCorretto(context, localPackagePath, correttoURL))
            {
                return(false);
            }

            string tempDir = $"{corettoInstallDir}.temp";

            try {
                if (!await Utilities.Unpack(localPackagePath, tempDir, cleanDestinatioBeforeUnpacking: true))
                {
                    Log.ErrorLine("Failed to install Corretto");
                    return(false);
                }

                string rootDirName = GetArchiveRootDirectoryName();
                string rootDir     = Path.Combine(tempDir, rootDirName);
                Log.DebugLine($"{context.OS.Type} root directory name of Corretto OpenJDK package is: {rootDirName}");
                if (!Directory.Exists(rootDir))
                {
                    Log.ErrorLine($"Corretto root directory not found after unpacking: {rootDirName}");
                    return(false);
                }

                Utilities.MoveDirectoryContentsRecursively(rootDir, corettoInstallDir);
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
                // Clean up zip after extraction if running on a hosted azure pipelines agent.
                if (context.IsRunningOnHostedAzureAgent)
                {
                    Utilities.DeleteFileSilent(localPackagePath);
                }
            }

            return(true);
        }
Esempio n. 5
0
        protected override async Task <bool> Execute(Context context)
        {
            string hostDestinationDirectory    = Configurables.Paths.HostBinutilsInstallDir;
            string windowsDestinationDirectory = Configurables.Paths.WindowsBinutilsInstallDir;

            bool hostHaveAll    = HaveAllBinutils(hostDestinationDirectory);
            bool windowsHaveAll = HaveAllBinutils(windowsDestinationDirectory, ".exe");

            if (hostHaveAll && windowsHaveAll)
            {
                Log.StatusLine("All Binutils are already installed");
                return(true);
            }

            string packageName      = Path.GetFileName(Configurables.Urls.BinutilsArchive.LocalPath);
            string localArchivePath = Path.Combine(Configurables.Paths.BinutilsCacheDir, packageName);

            if (!await DownloadBinutils(context, localArchivePath, Configurables.Urls.BinutilsArchive))
            {
                return(false);
            }

            string tempDir = Path.Combine(Path.GetTempPath(), "xaprepare-binutils");

            Utilities.DeleteDirectorySilent(tempDir);
            Utilities.CreateDirectory(tempDir);

            Log.DebugLine($"Unpacking {ProductName} archive {localArchivePath} into {tempDir}");
            if (!await Utilities.Unpack(localArchivePath, tempDir, cleanDestinatioBeforeUnpacking: true))
            {
                return(false);
            }

            if (!hostHaveAll)
            {
                CopyToDestination(context, "Host", tempDir, hostDestinationDirectory, executableExtension: ExecutableExtension);
            }

            if (!windowsHaveAll)
            {
                CopyToDestination(context, "Windows", tempDir, windowsDestinationDirectory, "windows", ".exe");
            }

            return(true);
        }
Esempio n. 6
0
        async Task <bool> Unpack(string fullArchivePath, string destinationDirectory, bool cleanDestinationBeforeUnpacking = false)
        {
            // https://bintray.com/jetbrains/intellij-jdk/download_file?file_path=jbrsdk-8u202-windows-x64-b1483.37.tar.gz
            // doesn't contain a single root directory!  This causes the
            // "JetBrains root directory not found after unpacking" check to fail on Windows.
            // "Fix" things by setting destinationDirectory to contain RootDirName, allowing
            // the check to succeed.
            if (JdkVersion == Configurables.Defaults.JetBrainsOpenJDK8Version)
            {
                destinationDirectory = Path.Combine(destinationDirectory, RootDirName);
            }

            // On Windows we don't have Tar available and the Windows package is a .tar.gz
            // 7zip can unpack tar.gz but it's a two-stage process - first it decompresses the package, then it can be
            // invoked again to extract the actual tar contents.

            if (cleanDestinationBeforeUnpacking)
            {
                Utilities.DeleteDirectorySilent(destinationDirectory);
            }
            Utilities.CreateDirectory(destinationDirectory);

            var sevenZip = new SevenZipRunner(Context.Instance);

            Log.DebugLine($"Uncompressing {fullArchivePath} to {destinationDirectory}");
            if (!await sevenZip.Extract(fullArchivePath, destinationDirectory))
            {
                Log.DebugLine($"Failed to decompress {fullArchivePath}");
                return(false);
            }

            string tarPath = Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(fullArchivePath));
            bool   ret     = await sevenZip.Extract(tarPath, destinationDirectory);

            Utilities.DeleteFileSilent(tarPath);

            if (!ret)
            {
                Log.DebugLine($"Failed to extract TAR contents from {tarPath}");
                return(false);
            }

            return(true);
        }
Esempio n. 7
0
        async Task <bool> Unpack(string fullArchivePath, string destinationDirectory, bool cleanDestinationBeforeUnpacking = false)
        {
            if (cleanDestinationBeforeUnpacking)
            {
                Utilities.DeleteDirectorySilent(destinationDirectory);
            }
            Utilities.CreateDirectory(destinationDirectory);

            var sevenZip = new SevenZipRunner(Context.Instance);

            Log.DebugLine($"Uncompressing {fullArchivePath} to {destinationDirectory}");
            if (!await sevenZip.Extract(fullArchivePath, destinationDirectory))
            {
                Log.DebugLine($"Failed to decompress {fullArchivePath}");
                return(false);
            }

            if (fullArchivePath.EndsWith("tar.gz", StringComparison.OrdinalIgnoreCase))
            {
                // On Windows we don't have Tar available and the Windows package is a .tar.gz
                // 7zip can unpack tar.gz but it's a two-stage process - first it decompresses the package, then it can be
                // invoked again to extract the actual tar contents.
                string tarPath = Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(fullArchivePath));
                bool   ret     = await sevenZip.Extract(tarPath, destinationDirectory);

                Utilities.DeleteFileSilent(tarPath);

                if (!ret)
                {
                    Log.DebugLine($"Failed to extract TAR contents from {tarPath}");
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 8
0
        protected override async Task <bool> Execute(Context context)
        {
            if (context.ForceRuntimesBuild)
            {
                if (osSupportsMonoBuild)
                {
                    Log.InfoLine("Rebuilding Mono runtimes as requested");
                    return(false);
                }

                Log.InfoLine($"Forced Mono runtimes rebuild requested but rebuilding on {context.OS.Type} is currently not supported.");
            }

            string localPackagePath = Configurables.Paths.BundleArchivePath;

            Log.DebugLine($"Local bundle path: {localPackagePath}");

            if (await Utilities.VerifyArchive(localPackagePath))
            {
                Log.StatusLine("Xamarin.Android Bundle archive already downloaded and valid");
            }
            else
            {
                if (!String.IsNullOrEmpty(context.XABundlePath))
                {
                    // User indicated they wanted to use a specific bundle that's supposed to be on disk. It's not (or
                    // it's invalid) and that means we have no way of getting it - we can't download the default one
                    // since that was not the intention behind overriding the location. Thus, we error out.
                    Log.DebugLine($"Bundle directory from command line: {context.XABundlePath}");
                    throw new InvalidOperationException($"Xamarin.Android bundle indicated on the command line does not exist ({context.XABundlePath})");
                }

                var bundleUrl = new Uri(BundleUriPrefix, BundleFileName);

                Log.StatusLine("Bundle URL: ", $"{bundleUrl}", tailColor: ConsoleColor.Cyan);

                HttpStatusCode status;
                bool           success;
                ulong          size;

                (success, size, status) = await Utilities.GetDownloadSizeWithStatus(bundleUrl);

                if (!success)
                {
                    if (status == HttpStatusCode.NotFound)
                    {
                        if (osSupportsMonoBuild)
                        {
                            Log.StatusLine("   not found, will need to rebuild");
                        }
                        else
                        {
                            Log.ErrorLine($"   not found, rebuilding on {context.OS.Type} is not currently supported");
                        }
                        return(false);
                    }

                    if (String.IsNullOrEmpty(bundle404Message))
                    {
                        throw new InvalidOperationException($"Failed to access bundle at {bundleUrl} (HTTP status: {status})");
                    }
                    else
                    {
                        throw new InvalidOperationException(bundle404Message);
                    }
                }

                DownloadStatus downloadStatus = Utilities.SetupDownloadStatus(context, size, context.InteractiveSession);
                Log.StatusLine($"  {context.Characters.Link} {bundleUrl}", ConsoleColor.White);
                await Download(context, bundleUrl, localPackagePath, "Xamarin.Android Bundle", Path.GetFileName(localPackagePath), downloadStatus);

                if (!File.Exists(localPackagePath))
                {
                    Log.ErrorLine($"Download of Xamarin.Android Bundle from {bundleUrl} failed.");
                    return(false);
                }
            }

            Log.StatusLine($"Unpacking bundle to {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, Configurables.Paths.BundleInstallDir)}");
            string tempDir = $"{Configurables.Paths.BundleInstallDir}-bundle.temp";

            try {
                if (!await Utilities.Unpack(localPackagePath, tempDir, cleanDestinatioBeforeUnpacking: true))
                {
                    Log.WarningLine("Failed to unpack bundle, will need to rebuild");
                    return(false);
                }

                Log.DebugLine($"Moving unpacked bundle from {tempDir} to {Configurables.Paths.BundleInstallDir}");
                Utilities.MoveDirectoryContentsRecursively(tempDir, Configurables.Paths.BundleInstallDir, resetFileTimestamp: true, ignoreDeletionErrors: true);
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
            }

            string managedRuntime     = context.Properties.GetRequiredValue(KnownProperties.ManagedRuntime);
            bool   haveManagedRuntime = !String.IsNullOrEmpty(managedRuntime);

            if (!await Utilities.BuildRemapRef(context, haveManagedRuntime, managedRuntime))
            {
                return(false);
            }

            Utilities.PropagateXamarinAndroidCecil(context);

            if (String.IsNullOrEmpty(context.XABundleCopyDir))
            {
                return(HaveEverything());
            }

            string destPackagePath = Path.Combine(context.XABundleCopyDir, Path.GetFileName(localPackagePath));

            Log.DebugLine($"Copy of the XA bundle was requested to be created at {destPackagePath}");
            if (Utilities.FileExists(destPackagePath))
            {
                Log.DebugLine("Bundle copy already exists");
                return(HaveEverything());
            }

            // Utilities.FileExists above will return `false` for a dangling symlink at `destPackagePath`, doesn't hurt
            // to remove it here just in case
            Utilities.DeleteFileSilent(destPackagePath);
            Utilities.CopyFile(localPackagePath, destPackagePath);

            return(HaveEverything());

            bool HaveEverything()
            {
                bool ret = MonoRuntimesHelpers.AllBundleItemsPresent(new Runtimes());

                if (!ret)
                {
                    Log.Instance.StatusLine($"Some bundle files are missing, download/rebuild/reinstall forced");
                }
                return(ret);
            }
        }
        protected override async Task <bool> Execute(Context context)
        {
            string localPackagePath = Configurables.Paths.AntArchivePath;

            if (await Utilities.VerifyArchive(localPackagePath))
            {
                Log.StatusLine("Ant archive already downloaded and valid");
            }
            else
            {
                Uri antUrl = new Uri(Configurables.Urls.AntBaseUri, Configurables.Paths.AntArchiveName);

                Log.StatusLine("Ant URL: ", $"{antUrl}", tailColor: ConsoleColor.Cyan);

                HttpStatusCode status;
                bool           success;
                ulong          size;

                (success, size, status) = await Utilities.GetDownloadSizeWithStatus(antUrl);

                if (!success)
                {
                    Log.ErrorLine($"Failed to access Ant at {antUrl} (HTTP status: {status})");
                    return(false);
                }

                DownloadStatus downloadStatus = Utilities.SetupDownloadStatus(context, size, context.InteractiveSession);
                Log.StatusLine($"  {context.Characters.Link} {antUrl}", ConsoleColor.White);
                await Download(context, antUrl, localPackagePath, "Apache Ant", Path.GetFileName(localPackagePath), downloadStatus);

                if (!File.Exists(localPackagePath))
                {
                    Log.ErrorLine($"Download of Xamarin.Android Bundle from {antUrl} failed.");
                    return(false);
                }
            }

            Log.StatusLine($"Unpacking Ant to {Configurables.Paths.AntInstallDir}");
            string tempDir = $"{Configurables.Paths.AntInstallDir}-ant.temp";

            try {
                if (!await Utilities.Unpack(localPackagePath, tempDir, cleanDestinatioBeforeUnpacking: true))
                {
                    Log.ErrorLine("Failed to unpack Ant");
                    return(false);
                }

                Log.DebugLine($"Moving unpacked Ant from {tempDir} to {Configurables.Paths.AntInstallDir}");

                // There should be just a single subdirectory
                List <string> subdirs = Directory.EnumerateDirectories(tempDir).ToList();
                if (subdirs.Count > 1)
                {
                    throw new InvalidOperationException($"Unexpected contents layout of the Ant archive - expected a single subdirectory, instead found {subdirs.Count}");
                }

                Utilities.MoveDirectoryContentsRecursively(subdirs [0], Configurables.Paths.AntInstallDir);
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
            }

            return(true);
        }
Esempio n. 10
0
        protected override async Task <bool> Execute(Context context)
        {
            if (Directory.Exists(Configurables.Paths.OldOpenJDKInstallDir))
            {
                Log.DebugLine($"Found old OpenJDK directory at {Configurables.Paths.OldOpenJDKInstallDir}, removing");
                Utilities.DeleteDirectorySilent(Configurables.Paths.OldOpenJDKInstallDir);
            }

            string jdkInstallDir = JdkInstallDir;

            if (OpenJDKExistsAndIsValid(jdkInstallDir, out string installedVersion))
            {
                Log.Status($"{ProductName} version ");
                Log.Status(installedVersion, ConsoleColor.Yellow);
                Log.StatusLine(" already installed in: ", jdkInstallDir, tailColor: ConsoleColor.Cyan);
                return(true);
            }

            Log.StatusLine($"{ProductName} {JdkVersion} r{JdkRelease} will be installed");
            Uri jdkURL = JdkUrl;

            if (jdkURL == null)
            {
                throw new InvalidOperationException($"{ProductName} URL must not be null");
            }

            string?packageName = GetPackageName(jdkURL);

            if (String.IsNullOrEmpty(packageName))
            {
                Log.ErrorLine($"Unable to extract file name from {ProductName} URL");
                return(false);
            }

            string localPackagePath = Path.Combine(JdkCacheDir, packageName);

            if (!await DownloadOpenJDK(context, localPackagePath, jdkURL))
            {
                return(false);
            }

            string tempDir = $"{jdkInstallDir}.temp";

            try {
                if (!await Unpack(localPackagePath, tempDir, cleanDestinationBeforeUnpacking: true))
                {
                    Log.ErrorLine($"Failed to install {ProductName}");
                    return(false);
                }

                string rootDir = Path.Combine(tempDir, RootDirName);
                if (!Directory.Exists(rootDir))
                {
                    Log.ErrorLine($"${ProductName} root directory not found after unpacking: {RootDirName}");
                    return(false);
                }

                MoveContents(rootDir, jdkInstallDir);
                File.WriteAllText(Path.Combine(jdkInstallDir, XAVersionInfoFile), $"{JdkRelease}{Environment.NewLine}");
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
                // Clean up zip after extraction if running on a hosted azure pipelines agent.
                if (context.IsRunningOnHostedAzureAgent)
                {
                    Utilities.DeleteFileSilent(localPackagePath);
                }
            }

            return(true);
        }
        protected override async Task <bool> Execute(Context context)
        {
            string sdkRoot         = context.Properties.GetRequiredValue(KnownProperties.AndroidSdkDirectory);
            string ndkRoot         = context.Properties.GetRequiredValue(KnownProperties.AndroidNdkDirectory);
            string packageCacheDir = context.Properties.GetRequiredValue(KnownProperties.AndroidToolchainCacheDirectory);

            RefreshSdk = context.ComponentsToRefresh.HasFlag(RefreshableComponent.AndroidSDK);
            RefreshNdk = context.ComponentsToRefresh.HasFlag(RefreshableComponent.AndroidNDK);

            Log.StatusLine("Android SDK location: ", sdkRoot, tailColor: Log.DestinationColor);
            Log.StatusLine("Android NDK location: ", ndkRoot, tailColor: Log.DestinationColor);
            Log.DebugLine($"Toolchain cache directory: {packageCacheDir}");

            var toolchain = new AndroidToolchain();
            var toInstall = new List <AndroidPackage> ();

            toolchain.Components.ForEach(c => Check(context, packageCacheDir, sdkRoot, c, toInstall, 4));
            if (toInstall.Count == 0)
            {
                return(GatherNDKInfo(context, ndkRoot));
            }

            Log.MessageLine();
            toInstall.ForEach(p => Log.DebugLine($"Missing Android component: {p.Component.Name}"));

            string tempDir = Path.Combine(context.Properties.GetRequiredValue(KnownProperties.AndroidToolchainDirectory), "temp");

            Log.DebugLine($"Toolchain temporary directory: {tempDir}");

            if (Directory.Exists(tempDir))
            {
                Log.DebugLine("Temporary directory exists, cleaning it up");
                Utilities.DeleteDirectorySilent(tempDir);
            }
            Directory.CreateDirectory(tempDir);

            Log.MessageLine("Installing missing components");
            var toDownload = new List <AndroidPackage> ();

            toInstall.ForEach(c => CheckPackageStatus(context, packageCacheDir, c, toDownload));

            if (toDownload.Count > 0)
            {
                ulong totalDownloadSize = 0;
                foreach (AndroidPackage pkg in toDownload)
                {
                    Log.DebugLine($"Android component '{pkg.Component.Name}' will be downloaded from {pkg.Url}");
                    (bool success, ulong size) = await Utilities.GetDownloadSize(pkg.Url);

                    if (!success)
                    {
                        continue;
                    }
                    totalDownloadSize += size;
                }

                toDownload.ForEach(p => Log.StatusLine($"  {context.Characters.Link} {p.Url}", ConsoleColor.White));

                DownloadStatus downloadStatus = Utilities.SetupDownloadStatus(context, totalDownloadSize, context.InteractiveSession);
                await Task.WhenAll(toDownload.Select(p => Download(context, p.Url, p.LocalPackagePath, p.Component.Name, p.PackageName, downloadStatus)));
            }

            foreach (AndroidPackage p in toInstall)
            {
                await Unpack(context, tempDir, p);
            }

            if (!AcceptLicenses(context, sdkRoot))
            {
                Log.ErrorLine("Failed to accept Android SDK licenses");
                return(false);
            }

            return(GatherNDKInfo(context, ndkRoot));
        }
Esempio n. 12
0
        protected override async Task <bool> Execute(Context context)
        {
            if (context.ForceRuntimesBuild)
            {
                if (osSupportsMonoBuild)
                {
                    Log.InfoLine("Rebuilding Mono runtimes as requested");
                    return(false);
                }

                Log.InfoLine($"Forced Mono runtimes rebuild requested but rebuilding on {context.OS.Type} is currently not supported.");
            }

            string localPackagePath = Path.Combine(Configurables.Paths.BundleArchivePath);

            if (await Utilities.VerifyArchive(localPackagePath))
            {
                Log.StatusLine("Xamarin.Android Bundle archive already downloaded and valid");
            }
            else
            {
                if (!String.IsNullOrEmpty(context.XABundlePath))
                {
                    // User indicated they wanted to use a specific bundle that's supposed to be on disk. It's not (or
                    // it's invalid) and that means we have no way of getting it - we can't download the default one
                    // since that was not the intention behind overriding the location. Thus, we error out.
                    throw new InvalidOperationException($"Xamarin.Android bundle indicated on the command line does not exist ({context.XABundlePath})");
                }

                var bundleUrl = new Uri(BundleUriPrefix, BundleFileName);

                Log.StatusLine("Bundle URL: ", $"{bundleUrl}", tailColor: ConsoleColor.Cyan);

                HttpStatusCode status;
                bool           success;
                ulong          size;

                (success, size, status) = await Utilities.GetDownloadSizeWithStatus(bundleUrl);

                if (!success)
                {
                    if (status == HttpStatusCode.NotFound)
                    {
                        if (osSupportsMonoBuild)
                        {
                            Log.StatusLine("   not found, will need to rebuild");
                        }
                        else
                        {
                            Log.ErrorLine($"   not found, rebuilding on {context.OS.Type} is not currently supported");
                        }
                        return(false);
                    }

                    if (String.IsNullOrEmpty(bundle404Message))
                    {
                        throw new InvalidOperationException($"Failed to access bundle at {bundleUrl} (HTTP status: {status})");
                    }
                    else
                    {
                        throw new InvalidOperationException(bundle404Message);
                    }
                }

                DownloadStatus downloadStatus = Utilities.SetupDownloadStatus(context, size, context.InteractiveSession);
                Log.StatusLine($"  {context.Characters.Link} {bundleUrl}", ConsoleColor.White);
                await Download(context, bundleUrl, localPackagePath, "Xamarin.Android Bundle", Path.GetFileName(localPackagePath), downloadStatus);

                if (!File.Exists(localPackagePath))
                {
                    Log.ErrorLine($"Download of Xamarin.Android Bundle from {bundleUrl} failed.");
                    return(false);
                }
            }

            Log.StatusLine($"Unpacking bundle to {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, Configurables.Paths.BundleInstallDir)}");
            string tempDir = $"{Configurables.Paths.BundleInstallDir}-bundle.temp";

            try {
                if (!await Utilities.Unpack(localPackagePath, tempDir, cleanDestinatioBeforeUnpacking: true))
                {
                    Log.WarningLine("Failed to unpack bundle, will need to rebuild");
                    return(false);
                }

                Log.DebugLine("Moving unpacked bundle from {tempDir} to {Configurables.Paths.Bundle_InstallDir}");
                Utilities.MoveDirectoryContentsRecursively(tempDir, Configurables.Paths.BundleInstallDir, resetFileTimestamp: true);
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
            }

            return(true);
        }
        protected override async Task <bool> Execute(Context context)
        {
            if (Directory.Exists(Configurables.Paths.OldOpenJDKInstallDir))
            {
                Log.DebugLine($"Found old OpenJDK directory at {Configurables.Paths.OldOpenJDKInstallDir}, removing");
                Utilities.DeleteDirectorySilent(Configurables.Paths.OldOpenJDKInstallDir);
            }

            string jdkInstallDir = JdkInstallDir;

            if (OpenJDKExistsAndIsValid(jdkInstallDir, out string installedVersion))
            {
                Log.Status($"{ProductName} version ");
                Log.Status(installedVersion, ConsoleColor.Yellow);
                Log.StatusLine(" already installed in: ", jdkInstallDir, tailColor: ConsoleColor.Cyan);
                return(true);
            }

            Log.StatusLine($"JetBrains JDK {JdkVersion} r{JdkRelease} will be installed");
            Uri jdkURL = JdkUrl;

            if (jdkURL == null)
            {
                throw new InvalidOperationException($"{ProductName} URL must not be null");
            }

            string[] queryParams = jdkURL.Query.TrimStart('?').Split(QuerySeparator, StringSplitOptions.RemoveEmptyEntries);
            if (queryParams.Length == 0)
            {
                Log.ErrorLine($"Unable to extract file name from {ProductName} URL as it contains no query component");
                return(false);
            }

            string?packageName = null;

            foreach (string p in queryParams)
            {
                if (!p.StartsWith(URLQueryFilePathField, StringComparison.Ordinal))
                {
                    continue;
                }

                int idx = p.IndexOf('=');
                if (idx < 0)
                {
                    Log.DebugLine($"{ProductName} URL query field '{URLQueryFilePathField}' has no value, unable to detect file name");
                    break;
                }

                packageName = p.Substring(idx + 1).Trim();
            }

            if (String.IsNullOrEmpty(packageName))
            {
                Log.ErrorLine($"Unable to extract file name from {ProductName} URL");
                return(false);
            }

            string localPackagePath = Path.Combine(JdkCacheDir, packageName);

            if (!await DownloadOpenJDK(context, localPackagePath, jdkURL))
            {
                return(false);
            }

            string tempDir = $"{jdkInstallDir}.temp";

            try {
                if (!await Unpack(localPackagePath, tempDir, cleanDestinationBeforeUnpacking: true))
                {
                    Log.ErrorLine($"Failed to install {ProductName}");
                    return(false);
                }

                string rootDir = Path.Combine(tempDir, RootDirName);
                if (!Directory.Exists(rootDir))
                {
                    Log.ErrorLine($"JetBrains root directory not found after unpacking: {RootDirName}");
                    return(false);
                }

                MoveContents(rootDir, jdkInstallDir);
                File.WriteAllText(Path.Combine(jdkInstallDir, XAVersionInfoFile), $"{JdkRelease}{Environment.NewLine}");
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
                // Clean up zip after extraction if running on a hosted azure pipelines agent.
                if (context.IsRunningOnHostedAzureAgent)
                {
                    Utilities.DeleteFileSilent(localPackagePath);
                }
            }

            return(true);
        }
Esempio n. 14
0
        async Task <(bool disabled, bool success)> ConfigureBuildAndInstall(Context context, string abiName)
        {
            if (!context.IsHostJitAbiEnabled(abiName))
            {
                Log.DebugLine($"Windows target {abiName} disabled, not building libzip");
                return(true, true);
            }

            bool   sixtyFourBit = context.Is64BitMingwHostAbi(abiName);
            string sourceDir    = context.Properties.GetRequiredValue(KnownProperties.LibZipSourceFullPath);
            string buildDir     = Path.Combine(Configurables.Paths.BuildBinDir, $"libzip-windows-{abiName}");
            string stampFile    = Path.Combine(buildDir, $".build-{context.BuildInfo.FullLibZipHash}");
            string outputPath;

            if (sixtyFourBit)
            {
                outputPath = Path.Combine("x64", LibZipName);
            }
            else
            {
                outputPath = LibZipName;
            }

            string sourceFile = Path.Combine(buildDir, "lib", LibZipName);
            string destFile   = Path.Combine(Configurables.Paths.LibZipOutputPath, outputPath);
            bool   needBuild;

            if (Utilities.FileExists(stampFile) && Utilities.FileExists(sourceFile))
            {
                Log.DebugLine($"LibZip-Windows build stamp file exists: {stampFile}");
                Log.StatusLine($"LibZip for {abiName} already built, skipping compilation");
                needBuild = false;
            }
            else
            {
                needBuild = true;
            }

            if (needBuild)
            {
                Utilities.DeleteDirectorySilent(buildDir);
                Utilities.CreateDirectory(buildDir);
                List <string> arguments = GetCmakeArguments(context, buildDir, sixtyFourBit);

                string logTag = $"libzip-windows-{abiName}";
                var    cmake  = new CMakeRunner(context);
                bool   result = await cmake.Run(
                    logTag : logTag,
                    sourceDirectory : sourceDir,
                    workingDirectory : buildDir,
                    arguments : arguments
                    );

                if (!result)
                {
                    return(false, false);
                }

                var ninja = new NinjaRunner(context);
                result = await ninja.Run(
                    logTag : logTag,
                    workingDirectory : buildDir
                    );

                if (!result)
                {
                    return(false, false);
                }
            }

            Utilities.CopyFile(sourceFile, destFile);

            if (!File.Exists(destFile))
            {
                Log.ErrorLine($"Failed to copy {sourceFile} to {destFile}");
                return(false, false);
            }

            TouchStampFile(stampFile);
            return(false, true);
        }