#pragma warning disable CS1998
        protected override async Task <bool> Execute(Context context)
        {
            var toolchainDirs = new List <string> {
                Path.GetFileName(context.Properties.GetRequiredValue(KnownProperties.AndroidSdkDirectory)),
                Path.GetFileName(context.Properties.GetRequiredValue(KnownProperties.AndroidNdkDirectory)),
            };

            var androidToolchain = new AndroidToolchain();
            var androidPackages  = new List <string> ();

            foreach (AndroidToolchainComponent component in androidToolchain.Components)
            {
                if (component == null)
                {
                    continue;
                }

                Uri pkgUrl;
                if (component.RelativeUrl != null)
                {
                    pkgUrl = new Uri(AndroidToolchain.AndroidUri, component.RelativeUrl);
                }
                else
                {
                    pkgUrl = AndroidToolchain.AndroidUri;
                }
                pkgUrl = new Uri(pkgUrl, $"{component.Name}.zip");
                androidPackages.Add($"{pkgUrl} {component.DestDir}");
            }

            var brewTaps     = new List <string> ();
            var brewPackages = new List <string> ();
            var pkgUrls      = new List <string> ();

            GatherMacPackages(brewTaps, brewPackages, pkgUrls);

            var sb = new StringBuilder(File.ReadAllText(Configurables.Paths.PackageImageDependenciesTemplate));

            sb.Replace("@TOOLCHAIN_DIRS@", MakeLines(toolchainDirs));
            sb.Replace("@PACKAGES@", MakeLines(androidPackages));
            sb.Replace("@BREW_TAPS@", MakeLines(brewTaps));
            sb.Replace("@BREWS@", MakeLines(brewPackages));
            sb.Replace("@PKG_URLS@", MakeLines(pkgUrls));

            string outputFile = Configurables.Paths.PackageImageDependenciesOutput;

            Log.StatusLine($"Generating ", outputFile, tailColor: ConsoleColor.White);
            File.WriteAllText(outputFile, sb.ToString());

            return(Utilities.MakeExecutable(outputFile, throwOnError: false));

            string MakeLines(List <string> list)
            {
                return(String.Join("\n", list));
            }
        }
        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));
        }