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); } }
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)); }