private string GetDotnetPackageRelativePath(DotNetDistributionParameters parms)
        {
            switch (parms.Runtime)
            {
            case DotNetRuntime.NETCore:
                return(m_filesystem.Path.Combine("shared", "Microsoft.NETCore.App"));

            case DotNetRuntime.AspNetCore:
                return(m_filesystem.Path.Combine("shared", "Microsoft.AspNetCore.App"));

            default:
                throw BadRuntime(parms.Runtime);
            }
        }
        private string GetAssetName(DotNetDistributionParameters parms)
        {
            switch (parms.Runtime)
            {
            case DotNetRuntime.NETCore:
                return(".NET Core Runtime");

            case DotNetRuntime.AspNetCore:
                return("ASP.NET Core Runtime");

            default:
                throw BadRuntime(parms.Runtime);
            }
        }
        private Uri BuildLatestVersionLink(DotNetDistributionParameters parms, string feed, string channel)
        {
            var ext = GetArchiveExtension(parms);

            switch (parms.Runtime)
            {
            case DotNetRuntime.NETCore:
                return(new Uri($"{feed}/Runtime/{channel}/latest.version"));

            case DotNetRuntime.AspNetCore:
                return(new Uri($"{feed}/aspnetcore/Runtime/{channel}/latest.version"));

            default:
                throw BadRuntime(parms.Runtime);
            }
        }
        private Uri BuildDownloadLink(DotNetDistributionParameters parms, string feed, string specificVersion, string arch)
        {
            var ext = GetArchiveExtension(parms);

            switch (parms.Runtime)
            {
            case DotNetRuntime.NETCore:
                return(new Uri($"{feed}/Runtime/{specificVersion}/dotnet-runtime-{specificVersion}-{parms.Platform}-{arch}.{ext}"));

            case DotNetRuntime.AspNetCore:
                return(new Uri($"{feed}/aspnetcore/Runtime/{specificVersion}/aspnetcore-runtime-{specificVersion}-{parms.Platform}-{arch}.{ext}"));

            default:
                throw BadRuntime(parms.Runtime);
            }
        }
        private string GetArchiveExtension(DotNetDistributionParameters parms)
        {
            var platform = parms.Platform?.ToLower();

            if (platform == DotNetPlatform.Windows)
            {
                return("zip");
            }
            else if (platform == DotNetPlatform.MacOS || platform == DotNetPlatform.Linux)
            {
                return("tar.gz");
            }
            else
            {
                throw BadPlatform(platform);
            }
        }
        private async Task <string> ResolveVersion(DotNetDistributionParameters parms, string requestedVersion)
        {
            string resolvedVersion;

            var s = requestedVersion.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            if (s.Length == 2)
            {
                var channel = requestedVersion;

                parms.Log?.Invoke($"Looking for latest version in series {channel}...");

                var uri     = BuildLatestVersionLink(parms, parms.UncachedFeed, channel);
                var tmpPath = m_filesystem.Path.GetTempFileName();

                await DownloadFile(uri, tmpPath);

                var versionText = m_filesystem.File.ReadAllText(tmpPath);

                var entries = versionText.Split(new string[0], StringSplitOptions.RemoveEmptyEntries);

                var commitHash = entries[0];
                resolvedVersion = entries[1];

                parms.Log?.Invoke($"Found {resolvedVersion} ({commitHash})");
            }
            else if (s.Length == 3)
            {
                resolvedVersion = requestedVersion;
            }
            else
            {
                throw new DotNetCoreInstallerException($"Unhandled or unrecognized requested version syntax: {requestedVersion}");
            }

            return(resolvedVersion);
        }
        public async Task InstallStandalone(DotNetDistributionParameters parms)
        {
            try
            {
                var assetName = GetAssetName(parms);
                var dotnetPackageRelativePath = GetDotnetPackageRelativePath(parms);
                var arch = parms.Architecture;

                parms.Log?.Invoke($"Install of {assetName} {parms.Platform}-{arch} v{parms.Version} requested.");

                var pkgRoot = m_filesystem.Path.Combine(parms.InstallDir, dotnetPackageRelativePath);
                if (m_filesystem.Directory.Exists(pkgRoot))
                {
                    var matchingVersions = m_filesystem.Directory.GetDirectories(pkgRoot, parms.Version + "*");
                    if (!parms.Force && matchingVersions.Length > 0)
                    {
                        // There may be more than one matching version, but there is also
                        // at least the first one; this message may be incomplete but it
                        // is true and sufficient for the purpose.
                        parms.Log?.Invoke($"Skipping installation: {assetName} version {Path.GetFileName(matchingVersions[0])} is already installed at {parms.InstallDir}.");
                        return;
                    }
                }

                var specificVersion = await ResolveVersion(parms, parms.Version);

                var uri     = BuildDownloadLink(parms, parms.CachedFeed, specificVersion, arch);
                var pkgPath = m_filesystem.Path.Combine(parms.InstallDir, dotnetPackageRelativePath, specificVersion);

                if (!parms.Force && m_filesystem.Directory.Exists(pkgPath))
                {
                    parms.Log?.Invoke($"Skipping installation: {assetName} version {specificVersion} is already installed.");
                    return;
                }

                parms.Log?.Invoke($"Installing {assetName} {parms.Platform}-{arch} v{specificVersion} to {parms.InstallDir}...");

                // NOTE: Forward slashes are allowed on Windows and required on Unixes,
                // so just always use them here instead of trying to adapt.
                var installDir = Path.GetFullPath(parms.InstallDir).Replace('\\', '/');
                m_filesystem.Directory.CreateDirectory(parms.InstallDir);

                var zipPath = m_filesystem.Path.GetTempFileName() + GetArchiveExtension(parms);

                await DownloadFile(uri, zipPath);
                await ExtractFile(zipPath, parms.InstallDir, parms.Force);

                if (!m_filesystem.Directory.Exists(pkgPath))
                {
                    throw new DotNetCoreInstallerException($"{assetName} version {specificVersion} failed to install with an unknown error.");
                }

                m_filesystem.File.Delete(zipPath);

                parms.Log?.Invoke($"Installation Complete.");
            }
            catch (Exception exc) when(!(exc is DotNetCoreInstallerException))
            {
                throw new DotNetCoreInstallerException("Unexpected error during installation.  See the inner exception.", exc);
            }
        }
Пример #8
0
        public static int Main(string[] args)
        {
            ConsoleColor.Enable();

            var app = new CommandLineApplication();

            app.Name        = "dotnet install";
            app.Description = "Performs standalone .NET Core installation.";
            app.HelpOption("-h|--help");
            app.ExtendedHelpText = @"
              The -v option is required.  Passing just a major and minor
              version will cause the app to download the latest published
              version in that series.

              Example: ""-v 2.1.4"" will install exactly version 2.1.4
                       ""-v 2.1"" may install 2.1.0, 2.1.6, etc. - whatever
                       the latest in the 2.1 series is.
            ";

            var installDirOption = app.Option("-i|--install-dir <INSTALL>", "Where to install", CommandOptionType.SingleValue);
            var runtimeOption    = app.Option("-r|--runtime <RUNTIME>", "The runtime to install (dotnet or aspnet)", CommandOptionType.SingleValue);
            var platformOption   = app.Option("-p|--platform <PLATFORM>", "The platform to install for (win, osx, linux or android)", CommandOptionType.SingleValue);
            var archOption       = app.Option("-a|--arch <ARCH>", "The OS architecture to install for (x64 or x86)", CommandOptionType.SingleValue);
            var versionOption    = app.Option("-v|--version <PLATFORM>", "What version to install (e.g., 2.1 or 2.1.4)", CommandOptionType.SingleValue);
            var forceOption      = app.Option("-f|--force ", "Force reinstallation", CommandOptionType.NoValue);

            app.OnExecute(async() =>
            {
                try
                {
                    var installDir = installDirOption.Value() ?? Directory.GetCurrentDirectory();
                    var runtime    = GetRuntime(runtimeOption.Value());
                    var platform   = platformOption.Value() ?? GetCurrentPlatform();
                    var arch       = archOption.Value() ?? GetCurrentArchitecture();
                    var version    = versionOption.Value() ?? throw new UsageException("The -v|--version parameter is required.");

                    installDir = Path.GetFullPath(installDir);

                    var parms = new DotNetDistributionParameters(installDir, platform, arch, version)
                    {
                        Force   = forceOption.HasValue(),
                        Runtime = runtime,
                        Log     = (s) => Log(s)
                    };

                    var installer = new DotNetCoreInstaller();
                    await installer.InstallStandalone(parms);
                }
                catch (UsageException exc)
                {
                    Console.Error.WriteLine($"{Red("Error: ")} {exc.Message}");
                    Console.Error.WriteLine($"Try: {White("dotnet install -h")}");
                }
                catch (Exception exc)
                {
                    var e = exc;
                    while (e != null)
                    {
                        Console.Error.WriteLine($"{Red("Exception:")} {e.Message}");
                        Console.Error.WriteLine(Gray(e.StackTrace));
                        Console.Error.WriteLine();

                        e = e.InnerException;
                    }
                }

                return(0);
            });

            return(app.Execute(args));
        }