Add RID parsing to Win/Osx

This commit is contained in:
Caelan Sayler
2022-12-06 00:02:15 +00:00
parent 2c828e9ce1
commit b0b4454bf6
10 changed files with 172 additions and 110 deletions

View File

@@ -10,6 +10,8 @@ namespace Squirrel.CommandLine.Commands
{
public class BaseCommand : Command
{
public string TargetRuntime { get; set; }
public DirectoryInfo ReleaseDirectory { get; private set; }
protected Option<DirectoryInfo> ReleaseDirectoryOption { get; private set; }
@@ -20,7 +22,7 @@ namespace Squirrel.CommandLine.Commands
protected BaseCommand(string name, string description, bool releaseDirMustNotBeEmpty = false)
: base(name, description)
{
ReleaseDirectoryOption = AddOption<DirectoryInfo>(new[] { "-r", "--releaseDir" }, (v) => ReleaseDirectory = v)
ReleaseDirectoryOption = AddOption<DirectoryInfo>(new[] { "-o", "--outputDir" }, (v) => ReleaseDirectory = v)
.SetDescription("Output directory for Squirrel packages.")
.SetArgumentHelpName("DIR");
ReleaseDirectoryOption.SetDefaultValue(new DirectoryInfo(".\\Releases"));

View File

@@ -11,6 +11,8 @@ namespace Microsoft.NETCore.Platforms.BuildTasks
/// </summary>
public sealed class RuntimeVersion : IComparable, IComparable<RuntimeVersion>, IEquatable<RuntimeVersion>
{
public int Major => version.Major;
private string versionString;
private Version version;
private bool hasMinor;
@@ -36,6 +38,11 @@ namespace Microsoft.NETCore.Platforms.BuildTasks
version = Version.Parse(toParse);
}
public string To3Part()
{
return $"{Math.Max(0, version.Major)}.{Math.Max(0, version.Minor)}.{Math.Max(0, version.Build)}";
}
public int CompareTo(object obj)
{
if (obj == null) {

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.NETCore.Platforms.BuildTasks;
using NuGet.Versioning;
using Squirrel.CommandLine.Commands;
using Squirrel.PropertyList;
@@ -149,14 +150,30 @@ namespace Squirrel.CommandLine.OSX
releases.AddRange(ReleaseEntry.ParseReleaseFile(File.ReadAllText(releaseFilePath, Encoding.UTF8)));
}
RuntimeCpu pkgArch = RuntimeCpu.Unknown;
string pkgMinver = null;
string fullRidString = "osx";
if (!String.IsNullOrEmpty(options.TargetRuntime)) {
var rid = RID.Parse(options.TargetRuntime);
if (rid.HasVersion) {
pkgMinver = rid.Version.To3Part();
fullRidString += rid.Version.Major;
}
if (rid.HasArchitecture && Enum.TryParse<RuntimeCpu>(rid.Architecture, true, out var rcparsed)) {
pkgArch = rcparsed;
fullRidString += "-" + rcparsed.ToString();
}
}
var rp = new ReleasePackageBuilder(nupkgPath);
var newPkgPath = rp.CreateReleasePackage(Path.Combine(releaseDir.FullName, rp.SuggestedReleaseFileName));
var suggestedName = ReleasePackageBuilder.GetSuggestedFileName(packId, packVersion, fullRidString);
var newPkgPath = rp.CreateReleasePackage((i, pkg) => Path.Combine(releaseDir.FullName, suggestedName));
Log.Info("Creating Delta Packages");
var prev = ReleasePackageBuilder.GetPreviousRelease(releases, rp, releaseDir.FullName);
if (prev != null && !options.NoDelta) {
var deltaBuilder = new DeltaPackageBuilder();
var deltaFile = Path.Combine(releaseDir.FullName, rp.SuggestedReleaseFileName.Replace("-full", "-delta"));
var deltaFile = rp.ReleasePackageFile.Replace("-full", "-delta");
var dp = deltaBuilder.CreateDeltaPackage(prev, rp, deltaFile);
releases.Add(ReleaseEntry.GenerateFromFile(deltaFile));
}

View File

@@ -1,19 +1,16 @@
using System;
using System.Diagnostics.Contracts;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using NuGet.Versioning;
using SharpCompress.Archives.Zip;
using SharpCompress.Readers;
using Squirrel.MarkdownSharp;
using Squirrel.NuGet;
using Squirrel.SimpleSplat;
using System.Threading.Tasks;
using SharpCompress.Archives.Zip;
using SharpCompress.Readers;
using NuGet.Versioning;
using System.Runtime.Versioning;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Squirrel.CommandLine
{
@@ -21,29 +18,26 @@ namespace Squirrel.CommandLine
{
string InputPackageFile { get; }
string ReleasePackageFile { get; }
string SuggestedReleaseFileName { get; }
SemanticVersion Version { get; }
}
internal class ReleasePackageBuilder : IEnableLogger, IReleasePackage
{
private Lazy<ZipPackage> _package;
public ReleasePackageBuilder(string inputPackageFile, bool isReleasePackage = false)
{
InputPackageFile = inputPackageFile;
_package = new Lazy<ZipPackage>(() => new ZipPackage(inputPackageFile));
if (isReleasePackage) {
ReleasePackageFile = inputPackageFile;
}
}
public string InputPackageFile { get; protected set; }
public string ReleasePackageFile { get; protected set; }
public string SuggestedReleaseFileName => _package.Value.FullReleaseFilename;
public string ReleasePackageFile { get; protected set; }
public string Id => ReleaseEntry.ParseEntryFileName(InputPackageFile).PackageName;
@@ -51,7 +45,14 @@ namespace Squirrel.CommandLine
internal string CreateReleasePackage(string outputFile, Func<string, string> releaseNotesProcessor = null, Action<string, ZipPackage> contentsPostProcessHook = null)
{
Contract.Requires(!String.IsNullOrEmpty(outputFile));
return CreateReleasePackage((i, p) => {
contentsPostProcessHook?.Invoke(i, p);
return outputFile;
}, releaseNotesProcessor);
}
internal string CreateReleasePackage(Func<string, ZipPackage, string> contentsPostProcessHook, Func<string, string> releaseNotesProcessor = null)
{
releaseNotesProcessor = releaseNotesProcessor ?? (x => (new Markdown()).Transform(x));
if (ReleasePackageFile != null) {
@@ -64,20 +65,6 @@ namespace Squirrel.CommandLine
// the 'releasify' command was used instead of 'pack'.
NugetUtil.ThrowIfInvalidNugetId(package.Id);
// NB: Our test fixtures use packages that aren't SemVer compliant,
// we don't really care that they aren't valid
if (!ModeDetector.InUnitTestRunner()) {
// verify that the .nuspec version is semver compliant
NugetUtil.ThrowIfVersionNotSemverCompliant(package.Version.ToString());
// verify that the suggested filename can be round-tripped as an assurance
// someone won't run across an edge case and install a broken app somehow
var idtest = ReleaseEntry.ParseEntryFileName(SuggestedReleaseFileName);
if (idtest.PackageName != package.Id || idtest.Version != package.Version) {
throw new Exception($"The package id/version could not be properly parsed, are you using special characters?");
}
}
// we can tell from here what platform(s) the package targets but given this is a
// simple package we only ever expect one entry here (crash hard otherwise)
var frameworks = package.Frameworks;
@@ -99,8 +86,7 @@ namespace Squirrel.CommandLine
"The input package file {0} must have no dependencies.", InputPackageFile));
}
this.Log().Info("Creating release package: {0} => {1}", InputPackageFile, outputFile);
this.Log().Info("Creating release from input package {0}", InputPackageFile);
using (Utility.GetTempDirectory(out var tempPath)) {
var tempDir = new DirectoryInfo(tempPath);
@@ -118,15 +104,27 @@ namespace Squirrel.CommandLine
addDeltaFilesToContentTypes(tempDir.FullName);
contentsPostProcessHook?.Invoke(tempPath, package);
var outputFile = contentsPostProcessHook.Invoke(tempPath, package);
EasyZip.CreateZipFromDirectory(outputFile, tempPath);
ReleasePackageFile = outputFile;
this.Log().Info("Package created at {0}", outputFile);
return ReleasePackageFile;
}
}
internal static string GetSuggestedFileName(string id, string version, string runtime, bool delta = false)
{
var tail = delta ? "delta" : "full";
if (String.IsNullOrEmpty(runtime)) {
return String.Format("{0}-{1}-{2}.nupkg", id, version, tail);
} else {
return String.Format("{0}-{1}-{2}-{3}.nupkg", id, version, runtime, tail);
}
}
/// <summary>
/// Given a list of releases and a specified release package, returns the release package
/// directly previous to the specified version.

View File

@@ -10,8 +10,10 @@ namespace Squirrel.CommandLine
{
public class SquirrelHost
{
public static Option<string> PlatformOption { get; }
= new Option<string>(new[] { "-x", "--xplat" }, "Select {PLATFORM} to cross-compile for (eg. win, osx).") { ArgumentHelpName = "PLATFORM" };
public static Option<string> TargetRuntime { get; }
= new Option<string>(new[] { "-r", "--runtime" }, "The target runtime to build packages for.")
.SetArgumentHelpName("RID")
.MustBeSupportedRid();
public static Option<bool> VerboseOption { get; }
= new Option<bool>("--verbose", "Print diagnostic messages.");
@@ -25,7 +27,7 @@ namespace Squirrel.CommandLine
var logger = ConsoleLogger.RegisterLogger();
RootCommand platformRootCommand = new RootCommand() {
PlatformOption,
TargetRuntime,
VerboseOption,
AddSearchPathOption,
};
@@ -33,7 +35,7 @@ namespace Squirrel.CommandLine
ParseResult parseResult = platformRootCommand.Parse(args);
string xplat = parseResult.GetValueForOption(PlatformOption) ?? SquirrelRuntimeInfo.SystemOsName;
string xplat = parseResult.GetValueForOption(TargetRuntime) ?? SquirrelRuntimeInfo.SystemOsName;
bool verbose = parseResult.GetValueForOption(VerboseOption);
if (parseResult.GetValueForOption(AddSearchPathOption) is { } searchPath) {
foreach (var v in searchPath) {
@@ -42,7 +44,7 @@ namespace Squirrel.CommandLine
}
RootCommand rootCommand = new RootCommand($"Squirrel {SquirrelRuntimeInfo.SquirrelDisplayVersion} for creating and distributing Squirrel releases.");
rootCommand.AddGlobalOption(PlatformOption);
rootCommand.AddGlobalOption(TargetRuntime);
rootCommand.AddGlobalOption(VerboseOption);
rootCommand.AddGlobalOption(AddSearchPathOption);
@@ -51,8 +53,8 @@ namespace Squirrel.CommandLine
case "windows":
if (!SquirrelRuntimeInfo.IsWindows)
logger.Write("Cross-compiling will cause some command and options of Squirrel to be unavailable.", LogLevel.Warn);
rootCommand.AddCommandWithHandler(new PackWindowsCommand(), Windows.Commands.Pack);
rootCommand.AddCommandWithHandler(new ReleasifyWindowsCommand(), Windows.Commands.Releasify);
Add(rootCommand, new PackWindowsCommand(), Windows.Commands.Pack);
Add(rootCommand, new ReleasifyWindowsCommand(), Windows.Commands.Releasify);
break;
case "mac":
@@ -60,8 +62,8 @@ namespace Squirrel.CommandLine
case "macos":
if (!SquirrelRuntimeInfo.IsOSX)
logger.Write("Cross-compiling will cause some command and options of Squirrel to be unavailable.", LogLevel.Warn);
rootCommand.AddCommandWithHandler(new BundleOsxCommand(), OSX.Commands.Bundle);
rootCommand.AddCommandWithHandler(new ReleasifyOsxCommand(), OSX.Commands.Releasify);
Add(rootCommand, new BundleOsxCommand(), OSX.Commands.Bundle);
Add(rootCommand, new ReleasifyOsxCommand(), OSX.Commands.Releasify);
break;
default:
@@ -73,41 +75,40 @@ namespace Squirrel.CommandLine
}
Command uploadCommand = new Command("upload", "Upload local package(s) to a remote update source.");
uploadCommand.AddCommandWithHandler(new S3UploadCommand(), options => S3Repository.UploadMissingPackages(options));
uploadCommand.AddCommandWithHandler(new GitHubUploadCommand(), options => GitHubRepository.UploadMissingPackages(options));
Add(uploadCommand, new S3UploadCommand(), options => S3Repository.UploadMissingPackages(options));
Add(uploadCommand, new GitHubUploadCommand(), options => GitHubRepository.UploadMissingPackages(options));
Command downloadCommand = new Command("download", "Download's the latest release from a remote update source.");
downloadCommand.AddCommandWithHandler(new HttpDownloadCommand(), options => SimpleWebRepository.DownloadRecentPackages(options));
downloadCommand.AddCommandWithHandler(new S3DownloadCommand(), options => S3Repository.DownloadRecentPackages(options));
downloadCommand.AddCommandWithHandler(new GitHubDownloadCommand(), options => GitHubRepository.DownloadRecentPackages(options));
Add(downloadCommand, new HttpDownloadCommand(), options => SimpleWebRepository.DownloadRecentPackages(options));
Add(downloadCommand, new S3DownloadCommand(), options => S3Repository.DownloadRecentPackages(options));
Add(downloadCommand, new GitHubDownloadCommand(), options => GitHubRepository.DownloadRecentPackages(options));
rootCommand.Add(uploadCommand);
rootCommand.Add(downloadCommand);
return rootCommand.Invoke(args);
}
}
public static class SquirrelHostExtensions
{
public static Command AddCommandWithHandler<T>(this Command root, T command, Action<T> execute)
where T : BaseCommand
private static Command Add<T>(Command parent, T command, Action<T> execute)
where T : BaseCommand
{
command.SetHandler((ctx) => {
command.SetProperties(ctx.ParseResult);
command.TargetRuntime = ctx.ParseResult.GetValueForOption(TargetRuntime);
execute(command);
});
root.AddCommand(command);
parent.AddCommand(command);
return command;
}
public static Command AddCommandWithHandler<T>(this Command root, T command, Func<T, Task> execute)
private static Command Add<T>(Command parent, T command, Func<T, Task> execute)
where T : BaseCommand
{
command.SetHandler((ctx) => {
command.SetProperties(ctx.ParseResult);
command.TargetRuntime = ctx.ParseResult.GetValueForOption(TargetRuntime);
return execute(command);
});
root.AddCommand(command);
parent.AddCommand(command);
return command;
}
}

View File

@@ -3,6 +3,7 @@ using System.CommandLine;
using System.CommandLine.Parsing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NuGet.Versioning;
using Squirrel.NuGet;
@@ -125,6 +126,12 @@ namespace Squirrel.CommandLine
return option;
}
public static Option<string> MustBeSupportedRid(this Option<string> option)
{
option.AddValidator(Validate.MustBeSupportedRid);
return option;
}
private static class Validate
{
public static void MustBeBetween(OptionResult result, int minimum, int maximum)
@@ -132,7 +139,7 @@ namespace Squirrel.CommandLine
for (int i = 0; i < result.Tokens.Count; i++) {
if (int.TryParse(result.Tokens[i].Value, out int value)) {
if (value is < 1 or > 1000) {
result.ErrorMessage = $"The value for {result.Token.Value} must be greater than {minimum} and less than {maximum}";
result.ErrorMessage = $"The value '{result.Token.Value}' must be greater than {minimum} and less than {maximum}";
break;
}
} else {
@@ -146,7 +153,7 @@ namespace Squirrel.CommandLine
{
for (int i = 0; i < result.Tokens.Count; i++) {
if (!string.Equals(Path.GetExtension(result.Tokens[i].Value), extension, StringComparison.InvariantCultureIgnoreCase)) {
result.ErrorMessage = $"{result.Token.Value} does not have an {extension} extension";
result.ErrorMessage = $"'{result.Token.Value}' does not have an {extension} extension";
break;
}
}
@@ -277,6 +284,15 @@ namespace Squirrel.CommandLine
}
}
}
public static void MustBeSupportedRid(OptionResult result)
{
for (int i = 0; i < result.Tokens.Count; i++) {
if (!Regex.IsMatch(result.Tokens[i].Value, @"(?<os>osx|win)\.?(?<ver>[\d\.]+)?(?:-(?<arch>(?:x|arm)\d+))?"))
result.ErrorMessage = $"Invalid or unsupported runtime '{result.Token.Value}'. Valid example: win-x64, osx-arm64.";
break;
}
}
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Linq;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.NETCore.Platforms.BuildTasks;
using Squirrel.CommandLine.Commands;
using Squirrel.NuGet;
using Squirrel.SimpleSplat;
@@ -78,12 +79,14 @@ namespace Squirrel.CommandLine.Windows
Log.Info("Creating release for package: " + file.FullName);
var rp = new ReleasePackageBuilder(file.FullName);
rp.CreateReleasePackage(Path.Combine(targetDir.FullName, rp.SuggestedReleaseFileName), contentsPostProcessHook: (pkgPath, zpkg) => {
rp.CreateReleasePackage(contentsPostProcessHook: (pkgPath, zpkg) => {
var nuspecPath = Directory.GetFiles(pkgPath, "*.nuspec", SearchOption.TopDirectoryOnly)
.ContextualSingle("package", "*.nuspec", "top level directory");
var libDir = Directory.GetDirectories(Path.Combine(pkgPath, "lib"))
.ContextualSingle("package", "'lib' folder");
var spec = NuspecManifest.ParseFromFile(nuspecPath);
foreach (var exename in options.SquirrelAwareExecutableNames) {
var exepath = Path.GetFullPath(Path.Combine(libDir, exename));
if (!File.Exists(exepath)) {
@@ -141,15 +144,37 @@ namespace Squirrel.CommandLine.Windows
"Shortcuts will be created for every binary in package.");
}
var pkgarch = SquirrelRuntimeInfo.SelectPackageArchitecture(peArch.Select(f => f.Architecture));
Log.Write($"Program: Package Architecture (detected from SquirrelAwareApp's): {pkgarch}",
pkgarch == RuntimeCpu.Unknown ? LogLevel.Warn : LogLevel.Info);
// parse runtime information
RuntimeCpu pkgArch = RuntimeCpu.Unknown;
string pkgMinver = null;
string fullRidString = "win";
// check dependencies of squirrel aware binaries for potential issues
// peparsed.ForEach(kvp => DotnetUtil.CheckDotnetReferences(kvp.Key, kvp.Value, requiredFrameworks));
if (!String.IsNullOrEmpty(options.TargetRuntime)) {
var rid = RID.Parse(options.TargetRuntime);
// store the runtime dependencies and the package architecture in nuspec (read by installer)
ZipPackage.SetSquirrelMetadata(nuspecPath, pkgarch, requiredFrameworks.Select(r => r.Id));
if (rid.HasVersion) {
pkgMinver = rid.Version.To3Part();
fullRidString += rid.Version.Major;
}
if (rid.HasArchitecture && Enum.TryParse<RuntimeCpu>(rid.Architecture, true, out var rcparsed)) {
pkgArch = rcparsed;
fullRidString += "-" + rcparsed.ToString();
}
}
// try to auto-detect architecture as it was not specified.
if (pkgArch == RuntimeCpu.Unknown) {
var pkgarchs = peArch.Select(f => f.Architecture).Distinct().ToArray();
if (pkgarchs.Length == 1) {
pkgArch = pkgarchs[0];
fullRidString += "-" + pkgArch;
} else {
Log.Error("Could not determine package CPU architecture. This will therefore not be validated during install. Fix this via the target runtime argument eg. '--runtime win-x64'");
}
}
ZipPackage.SetWindowsMetadata(nuspecPath, requiredFrameworks.Select(r => r.Id), "win", pkgMinver, pkgArch);
// create stub executable for all exe's in this package (except Squirrel!)
var exesToCreateStubFor = new DirectoryInfo(pkgPath).GetAllFilesRecursively()
@@ -205,6 +230,8 @@ namespace Squirrel.CommandLine.Windows
// copy other images to root (used by setup)
if (setupIcon != null) File.Copy(setupIcon, Path.Combine(pkgPath, "setup.ico"), true);
if (backgroundGif != null) File.Copy(backgroundGif, Path.Combine(pkgPath, "splashimage" + Path.GetExtension(backgroundGif)));
return Path.Combine(targetDir.FullName, ReleasePackageBuilder.GetSuggestedFileName(spec.Id, spec.Version.ToString(), fullRidString));
});
processed.Add(rp.ReleasePackageFile);
@@ -212,8 +239,8 @@ namespace Squirrel.CommandLine.Windows
var prev = ReleasePackageBuilder.GetPreviousRelease(previousReleases, rp, targetDir.FullName);
if (prev != null && generateDeltas) {
var deltaBuilder = new DeltaPackageBuilder();
var dp = deltaBuilder.CreateDeltaPackage(prev, rp,
Path.Combine(targetDir.FullName, rp.SuggestedReleaseFileName.Replace("full", "delta")));
var deltaOutputPath = rp.ReleasePackageFile.Replace("-full", "-delta");
var dp = deltaBuilder.CreateDeltaPackage(prev, rp, deltaOutputPath);
processed.Insert(0, dp.InputPackageFile);
}
}

View File

@@ -2,11 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using NuGet.Versioning;
using SharpCompress.Archives.Zip;
namespace Squirrel.NuGet
{
@@ -23,7 +20,7 @@ namespace Squirrel.NuGet
string ReleaseNotes { get; }
Uri IconUrl { get; }
IEnumerable<string> Tags { get; }
RuntimeCpu MachineArchitecture { get; }
RuntimeCpu Architecture { get; }
IEnumerable<FrameworkAssemblyReference> FrameworkAssemblies { get; }
IEnumerable<PackageDependencySet> DependencySets { get; }
IEnumerable<string> RuntimeDependencies { get; }
@@ -35,9 +32,8 @@ namespace Squirrel.NuGet
public string ProductDescription => Description ?? Summary ?? Title ?? Id;
public string ProductCompany => (Authors.Any() ? String.Join(", ", Authors) : Owners) ?? ProductName;
public string ProductCopyright => Copyright ?? "Copyright © " + DateTime.Now.Year.ToString() + " " + ProductCompany;
public string FullReleaseFilename => String.Format("{0}-{1}-full.nupkg", Id, Version);
public string FilePath { get; private set; }
//public string FilePath { get; private set; }
public string Id { get; private set; }
public SemanticVersion Version { get; private set; }
@@ -47,11 +43,14 @@ namespace Squirrel.NuGet
public Uri IconUrl { get; private set; }
public string Language { get; private set; }
public IEnumerable<string> Tags { get; private set; } = Enumerable.Empty<string>();
public RuntimeCpu MachineArchitecture { get; private set; }
public IEnumerable<string> RuntimeDependencies { get; private set; } = Enumerable.Empty<string>();
public IEnumerable<FrameworkAssemblyReference> FrameworkAssemblies { get; private set; } = Enumerable.Empty<FrameworkAssemblyReference>();
public IEnumerable<PackageDependencySet> DependencySets { get; private set; } = Enumerable.Empty<PackageDependencySet>();
public string OperatingSystem { get; private set; }
public string MinOperatingSystemVersion { get; private set; }
public RuntimeCpu Architecture { get; private set; }
protected string Description { get; private set; }
protected IEnumerable<string> Authors { get; private set; } = Enumerable.Empty<string>();
protected string Owners { get; private set; }
@@ -59,7 +58,6 @@ namespace Squirrel.NuGet
protected string Summary { get; private set; }
protected string Copyright { get; private set; }
private static readonly string[] ExcludePaths = new[] { "_rels", "package" };
protected NuspecManifest() { }
@@ -69,7 +67,7 @@ namespace Squirrel.NuGet
using var fs = File.OpenRead(filePath);
var nu = new NuspecManifest();
nu.ReadManifest(fs);
nu.FilePath = filePath;
//nu.FilePath = filePath;
return nu;
}
@@ -84,13 +82,18 @@ namespace Squirrel.NuGet
}
}
public static void SetSquirrelMetadata(string nuspecPath, RuntimeCpu architecture, IEnumerable<string> runtimes)
public static void SetWindowsMetadata(string nuspecPath, IEnumerable<string> runtimes, string os, string osMinVer, RuntimeCpu arch)
{
Dictionary<string, string> toSet = new();
if (architecture != RuntimeCpu.Unknown)
toSet.Add("machineArchitecture", architecture.ToString());
if (runtimes.Any())
toSet.Add("runtimeDependencies", String.Join(",", runtimes));
if (osMinVer != null)
toSet.Add("os", os);
if (osMinVer != null)
toSet.Add("osMinVer", osMinVer);
if (arch != RuntimeCpu.Unknown)
toSet.Add("arch", arch.ToString());
if (!toSet.Any())
return;
@@ -198,17 +201,22 @@ namespace Squirrel.NuGet
// ===
// the following metadata elements are added by squirrel and are not
// used by nuget.
case "machineArchitecture":
if (Enum.TryParse(value, true, out RuntimeCpu ma)) {
MachineArchitecture = ma;
}
break;
case "runtimeDependencies":
RuntimeDependencies = getCommaDelimitedValue(value);
break;
case "releaseNotesHtml":
ReleaseNotesHtml = value;
break;
case "arch":
if (Enum.TryParse(value, true, out RuntimeCpu ma)) Architecture = ma;
break;
case "os":
OperatingSystem = value;
break;
case "osMinVer":
MinOperatingSystemVersion = value;
break;
}
}

View File

@@ -1,19 +1,13 @@
using Squirrel.SimpleSplat;
using Squirrel.Json;
using System;
using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Squirrel.NuGet;
using Squirrel.Json;
using Squirrel.Lib;
using Squirrel.NuGet;
using Squirrel.SimpleSplat;
using Squirrel.Sources;
using static Squirrel.Runtimes.RuntimeInstallResult;
@@ -23,7 +17,7 @@ namespace Squirrel.Update
{
private static StartupOption opt;
private static SetupLogLogger _log;
static IFullLogger Log => SquirrelLocator.Current.GetService<ILogManager>().GetLogger(typeof(Program));
[STAThread]
@@ -32,7 +26,7 @@ namespace Squirrel.Update
// if Update.exe is double clicked from explorer, we do not want to attach a console etc.
if (args.Length == 0)
return -1;
try {
return main(args);
} catch (Exception ex) {
@@ -180,14 +174,6 @@ namespace Squirrel.Update
using var _t = Utility.GetTempDirectory(out var tempFolder);
using ISplashWindow splash = new ComposedWindow(appname, silentInstall, zp.SetupIconBytes, zp.SetupSplashBytes);
// verify that this package can be installed on this cpu architecture
if (SquirrelRuntimeInfo.IsPackageCompatibleWithCurrentOS(zp.MachineArchitecture) == false) {
splash.ShowErrorDialog("Incompatible System",
$"The current operating system uses the {SquirrelRuntimeInfo.SystemArchitecture} cpu architecture, " +
$"but this package is for {zp.MachineArchitecture} and cannot be installed on this computer.");
return;
}
var missingFrameworks = getMissingRuntimes(zp);
// prompt user to install missing dependencies
@@ -212,7 +198,7 @@ namespace Squirrel.Update
splash.SetProgressIndeterminate();
// copy package to directory
string packagePath = Path.Combine(tempFolder, zp.FullReleaseFilename);
string packagePath = Path.Combine(tempFolder, String.Format("{0}-{1}-bundled.nupkg", zp.Id, zp.Version));
fs.Position = 0;
using (var writeStream = File.Open(packagePath, FileMode.Create, FileAccess.ReadWrite))
fs.CopyTo(writeStream);
@@ -260,7 +246,7 @@ namespace Squirrel.Update
.First().PackageName;
var rootAppDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ourAppName);
Log.Info("About to install to: " + rootAppDir);
if (Directory.Exists(rootAppDir)) {
Log.Warn("Install path {0} already exists, burning it to the ground", rootAppDir);
@@ -297,7 +283,7 @@ namespace Squirrel.Update
bool ignoreDeltaUpdates = false;
Log.Info("About to update to: " + mgr.Config.RootAppDir);
retry:
retry:
try {
// 3 % (3 stages)
var updateInfo = await mgr.CheckForUpdate(intention: UpdaterIntention.Update, ignoreDeltaUpdates: ignoreDeltaUpdates,

View File

@@ -18,7 +18,7 @@ namespace Squirrel.CommandLine.Tests
BaseCommand command = new T();
var cli = GetRequiredDefaultOptions() + $"--releaseDir \"{releaseDirectory.FullName}\"";
var cli = GetRequiredDefaultOptions() + $"--outputDir \"{releaseDirectory.FullName}\"";
var parseResult = command.ParseAndApply(cli);
Assert.Equal(releaseDirectory.FullName, command.ReleaseDirectory?.FullName);