WIP UpdateMac binary

This commit is contained in:
Caelan Sayler
2022-05-07 11:11:51 +01:00
parent 5d33f1fc0e
commit 757cd4e08e
8 changed files with 303 additions and 19 deletions

View File

@@ -28,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubExecutable", "src\StubE
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squirrel.CommandLine.OSX", "src\Squirrel.CommandLine.OSX\Squirrel.CommandLine.OSX.csproj", "{5ECCE39A-56E3-4EA8-8F55-CE59979B6B6B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update.OSX", "src\Update.OSX\Update.OSX.csproj", "{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CIBuild|Any CPU = CIBuild|Any CPU
@@ -440,6 +442,54 @@ Global
{5ECCE39A-56E3-4EA8-8F55-CE59979B6B6B}.Release|x64.Build.0 = Release|Any CPU
{5ECCE39A-56E3-4EA8-8F55-CE59979B6B6B}.Release|x86.ActiveCfg = Release|Any CPU
{5ECCE39A-56E3-4EA8-8F55-CE59979B6B6B}.Release|x86.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|Any CPU.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|Any CPU.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|Mixed Platforms.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|x64.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|x64.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|x86.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.CIBuild|x86.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|Any CPU.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|Any CPU.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|Mixed Platforms.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|x64.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|x64.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|x86.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Coverage|x86.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|x64.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|x64.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|x86.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Debug|x86.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|Any CPU.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|x64.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|x64.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|x86.ActiveCfg = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Debug|x86.Build.0 = Debug|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|Any CPU.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|Any CPU.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|Mixed Platforms.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|x64.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|x64.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|x86.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Mono Release|x86.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|Any CPU.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|x64.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|x64.Build.0 = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|x86.ActiveCfg = Release|Any CPU
{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -40,7 +40,7 @@ namespace Squirrel.CommandLine
IsValidFile(nameof(icon), ".icns");
var exe = Path.Combine(packDirectory, exeName);
if (!File.Exists(exe)) // || !MachOUtils.IsMachOImage(exe))
if (!File.Exists(exe) || !MachOUtils.IsMachOImage(exe))
throw new OptionValidationException($"Could not find mach-o executable at '{exe}'.");
}
}

View File

@@ -1,4 +1,4 @@
// See https://aka.ms/new-console-template for more information
// See https://aka.ms/new-console-template for more information
using System;
using System.Collections.Generic;
using System.IO;
@@ -19,8 +19,8 @@ namespace Squirrel.CommandLine
{
var commands = new CommandSet {
"[ Package Authoring ]",
{ "bundle", "Reads a build directory and creates a OSX '.app' bundle", new BundleOptions(), Bundle },
{ "pack", "Convert a '.app' bundle into a Squirrel release", new PackOptions(), Pack },
{ "bundle", "Convert a build directory into a OSX '.app' bundle", new BundleOptions(), Bundle },
{ "pack", "Create a Squirrel release from a '.app' bundle", new PackOptions(), Pack },
};
return SquirrelHost.Run(args, commands);
@@ -40,9 +40,17 @@ namespace Squirrel.CommandLine
var _ = Utility.GetTempDir(TempDir, out var tmp);
var packId = plist.ObjectForKey("CFBundleIdentifier").ToString();
var packVersion = plist.ObjectForKey("CFBundleVersion").ToString();
var packTitle = plist.ObjectForKey("CFBundleName").ToString();
string getpStr(string name)
{
var res = plist.ObjectForKey(name);
if (res == null)
throw new Exception($"Did not find required key '{name}' in Info.plist");
return res.ToString();
}
var packId = getpStr("CFBundleIdentifier");
var packVersion = getpStr("CFBundleVersion");
var packTitle = getpStr("CFBundleName");
var nupkgPath = NugetConsole.CreatePackageFromMetadata(
tmp, options.package, packId, packTitle, packTitle,
@@ -55,19 +63,20 @@ namespace Squirrel.CommandLine
}
var rp = new ReleasePackageBuilder(nupkgPath);
//var newPkgPath = rp.CreateReleasePackage(TempDir, Path.Combine(options.releaseDir, rp.SuggestedReleaseFileName), 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 contentsDir = Path.Combine(libDir, "Contents");
// File.Copy(nuspecPath, Path.Combine(contentsDir, "current.version"));
//});
var newPkgPath = rp.CreateReleasePackage(TempDir, Path.Combine(options.releaseDir, rp.SuggestedReleaseFileName), 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 contentsDir = Path.Combine(libDir, "Contents");
File.Copy(nuspecPath, Path.Combine(contentsDir, "current.version"));
File.Copy(HelperExe.UpdatePath, Path.Combine(contentsDir, "UpdateMac"));
});
// we are not currently making any modifications to the package
// so we can just copy it to the right place. uncomment the above otherwise.
var newPkgPath = Path.Combine(targetDir, rp.SuggestedReleaseFileName);
File.Move(rp.InputPackageFile, newPkgPath);
//var newPkgPath = Path.Combine(targetDir, rp.SuggestedReleaseFileName);
//File.Move(rp.InputPackageFile, newPkgPath);
var prev = ReleasePackageBuilder.GetPreviousRelease(previousReleases, rp, targetDir);
if (prev != null && !options.noDelta) {
@@ -76,7 +85,7 @@ namespace Squirrel.CommandLine
Path.Combine(di.FullName, rp.SuggestedReleaseFileName.Replace("full", "delta")), TempDir);
}
ReleaseEntry.WriteReleaseFile(previousReleases.Concat(new [] { ReleaseEntry.GenerateFromFile(newPkgPath) }), releaseFilePath);
ReleaseEntry.WriteReleaseFile(previousReleases.Concat(new[] { ReleaseEntry.GenerateFromFile(newPkgPath) }), releaseFilePath);
Log.Info("Done");
}

View File

@@ -67,7 +67,7 @@ namespace Squirrel.CommandLine
using var ud = Utility.GetTempDir(TempDir, out var tempDir);
// update icon for Update.exe if requested
var bundledUpdatePath = HelperExe.UpdatePath(p => Microsoft.NET.HostModel.AppHost.HostWriter.IsBundle(p, out var _hz));
var bundledUpdatePath = HelperExe.UpdatePath;
var updatePath = Path.Combine(tempDir, "Update.exe");
if (setupIcon != null) {
DotnetUtil.UpdateSingleFileBundleIcon(TempDir, bundledUpdatePath, updatePath, setupIcon).Wait();

72
src/Update.OSX/Logging.cs Normal file
View File

@@ -0,0 +1,72 @@
using System;
using System.IO;
using NLog.Config;
using NLog.Targets;
using Squirrel.SimpleSplat;
namespace Squirrel.Update
{
class SetupLogLogger : ILogger
{
public LogLevel Level { get; set; }
private readonly NLog.Logger _log;
public SetupLogLogger(string logDirectory, bool includeActionInLogName, UpdateAction action)
{
string name, archivename;
if (includeActionInLogName || action == UpdateAction.Unset) {
name = "Squirrel.log";
archivename = "Squirrel.archive{###}.log";
} else {
name = $"Squirrel-{action}.log";
archivename = $"Squirrel-{action}.archive{{###}}.log";
}
// https://gist.github.com/chrisortman/1092889
SimpleConfigurator.ConfigureForTargetLogging(
new FileTarget() {
FileName = Path.Combine(logDirectory, name),
Layout = new NLog.Layouts.SimpleLayout("${longdate} [${level:uppercase=true}] - ${message}"),
ArchiveFileName = Path.Combine(logDirectory, archivename),
ArchiveAboveSize = 1_000_000 /* 2 MB */,
ArchiveNumbering = ArchiveNumberingMode.Sequence,
ConcurrentWrites = true, // should allow multiple processes to use the same file
KeepFileOpen = true,
MaxArchiveFiles = 1 /* MAX 2mb of log data per "action" */,
},
NLog.LogLevel.Debug
);
_log = NLog.LogManager.GetLogger("SetupLogLogger");
}
public void Write(string message, LogLevel logLevel)
{
if (logLevel < Level) {
return;
}
switch (logLevel) {
case LogLevel.Debug:
_log.Debug(message);
break;
case LogLevel.Info:
_log.Info(message);
break;
case LogLevel.Warn:
_log.Warn(message);
break;
case LogLevel.Error:
_log.Error(message);
break;
case LogLevel.Fatal:
_log.Fatal(message);
break;
default:
_log.Info(message);
break;
}
}
}
}

73
src/Update.OSX/Program.cs Normal file
View File

@@ -0,0 +1,73 @@
using System;
using Squirrel.SimpleSplat;
namespace Squirrel.Update
{
class Program : IEnableLogger
{
static StartupOption opt;
static IFullLogger Log => SquirrelLocator.Current.GetService<ILogManager>().GetLogger(typeof(Program));
[STAThread]
public static int Main(string[] args)
{
try {
return main(args);
} catch (Exception ex) {
// NB: Normally this is a terrible idea but we want to make
// sure Setup.exe above us gets the nonzero error code
Console.Error.WriteLine(ex);
return -1;
}
}
static int main(string[] args)
{
try {
opt = new StartupOption(args);
} catch (Exception ex) {
var logp = new SetupLogLogger(Utility.GetDefaultTempDirectory(null), false, UpdateAction.Unset) { Level = LogLevel.Info };
logp.Write($"Failed to parse command line options. {ex.Message}", LogLevel.Error);
throw;
}
// NB: Trying to delete the app directory while we have Setup.log
// open will actually crash the uninstaller
bool logToTemp = true;
var logDir = logToTemp ? Utility.GetDefaultTempDirectory(null) : SquirrelRuntimeInfo.BaseDirectory;
var logger = new SetupLogLogger(logDir, !logToTemp, opt.updateAction) { Level = LogLevel.Info };
SquirrelLocator.CurrentMutable.Register(() => logger, typeof(SimpleSplat.ILogger));
try {
return executeCommandLine(args);
} catch (Exception ex) {
logger.Write("Finished with unhandled exception: " + ex, LogLevel.Fatal);
throw;
}
}
static int executeCommandLine(string[] args)
{
Log.Info("Starting Squirrel Updater: " + String.Join(" ", args));
Log.Info("Updater location is: " + SquirrelRuntimeInfo.EntryExePath);
Console.WriteLine(opt.updateCurrentApp);
Console.WriteLine(opt.updateStagingDir);
if (opt.updateAction == UpdateAction.Unset) {
opt.WriteOptionDescriptions();
return -1;
}
switch (opt.updateAction) {
}
Log.Info("Finished Squirrel Updater");
return 0;
}
}
}

View File

@@ -0,0 +1,54 @@
using Mono.Options;
using System;
using System.IO;
namespace Squirrel.Update
{
enum UpdateAction
{
Unset = 0, ApplyLatest
}
internal class StartupOption
{
private readonly OptionSet optionSet;
internal UpdateAction updateAction { get; private set; } = default(UpdateAction);
internal string updateCurrentApp { get; private set; }
internal string updateStagingDir { get; private set; }
public StartupOption(string[] args)
{
optionSet = Parse(args);
}
private OptionSet Parse(string[] args)
{
var exeName = Path.GetFileName(SquirrelRuntimeInfo.EntryExePath);
var opts = new OptionSet() {
"",
#pragma warning disable CS0436 // Type conflicts with imported type
$"Squirrel Updater (OSX) ({ThisAssembly.AssemblyInformationalVersion}) installs updates for Squirrel applications",
#pragma warning restore CS0436 // Type conflicts with imported type
$"Usage: {exeName} command [OPTS]",
"",
"Commands:",
{ "apply=", "Replace {0:CURRENT} .app with the latest in {1:STAGING}",
(v1, v2) => { updateAction = UpdateAction.ApplyLatest; updateCurrentApp = v1; updateStagingDir = v2; }
},
"",
"Options:",
{ "h|?|help", "Display Help and exit", _ => {} },
};
opts.Parse(args);
return opts;
}
internal void WriteOptionDescriptions()
{
optionSet.WriteOptionDescriptions(Console.Out);
}
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Squirrel.Update</RootNamespace>
<AssemblyName>UpdateMac</AssemblyName>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols>
<PathMap>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))=./</PathMap>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squirrel\Squirrel.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.0-rc2" />
</ItemGroup>
</Project>