mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
First version of the 'csq' tool
This commit is contained in:
@@ -32,6 +32,10 @@ EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update.OSX", "src\Update.OSX\Update.OSX.csproj", "{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squirrel.Tool", "src\Squirrel.Tool\Squirrel.Tool.csproj", "{9E769C7E-A54C-4844-8362-727D37BB1578}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6B406985-B2E1-4FED-A405-BD0694D68E93} = {6B406985-B2E1-4FED-A405-BD0694D68E93}
|
||||
{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C} = {611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Squirrel.CommandLine
|
||||
AddSearchPath(SquirrelRuntimeInfo.BaseDirectory, "..", "..", "..", "vendor", "wix");
|
||||
#endif
|
||||
AddSearchPath(SquirrelRuntimeInfo.BaseDirectory, "bin");
|
||||
AddSearchPath(SquirrelRuntimeInfo.BaseDirectory, "wix");
|
||||
}
|
||||
|
||||
public static void AddSearchPath(params string[] pathParts)
|
||||
@@ -81,8 +82,7 @@ namespace Squirrel.CommandLine
|
||||
.Where(d => !String.IsNullOrEmpty(d))
|
||||
.Distinct()
|
||||
.Select(d => Path.Combine(d, toFind))
|
||||
.Where(d => File.Exists(d) || (File.Exists(d + ".exe") && SquirrelRuntimeInfo.IsWindows))
|
||||
.Select(d => File.Exists(d + ".exe") ? d + ".exe" : d)
|
||||
.Where(d => File.Exists(d))
|
||||
.Select(Path.GetFullPath);
|
||||
|
||||
if (predicate != null)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -11,21 +10,19 @@ using Squirrel.SimpleSplat;
|
||||
namespace Squirrel.CommandLine.OSX
|
||||
{
|
||||
[SupportedOSPlatform("osx")]
|
||||
class Program
|
||||
class CommandsOSX
|
||||
{
|
||||
static IFullLogger Log => SquirrelLocator.Current.GetService<ILogManager>().GetLogger(typeof(Program));
|
||||
static IFullLogger Log => SquirrelLocator.Current.GetService<ILogManager>().GetLogger(typeof(CommandsOSX));
|
||||
|
||||
public static int MainOSX(string[] args)
|
||||
public static CommandSet GetCommands()
|
||||
{
|
||||
var commands = new CommandSet {
|
||||
return new CommandSet {
|
||||
"[ Package Authoring ]",
|
||||
{ "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);
|
||||
}
|
||||
|
||||
|
||||
private static void Pack(PackOptions options)
|
||||
{
|
||||
var targetDir = options.releaseDir ?? Path.Combine(".", "Releases");
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Squirrel.CommandLine
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
if (SquirrelRuntimeInfo.IsWindows)
|
||||
return Windows.Program.MainWindows(args);
|
||||
|
||||
if (SquirrelRuntimeInfo.IsOSX)
|
||||
return OSX.Program.MainOSX(args);
|
||||
|
||||
throw new NotSupportedException("Unsupported OS: " + SquirrelRuntimeInfo.SystemOsName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>SquirrelCli</AssemblyName>
|
||||
<NoWarn>$(NoWarn);CA2007</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -10,55 +10,70 @@ using Squirrel.SimpleSplat;
|
||||
|
||||
namespace Squirrel.CommandLine
|
||||
{
|
||||
internal class SquirrelHost
|
||||
public class SquirrelHost
|
||||
{
|
||||
#pragma warning disable CS0436 // Type conflicts with imported type
|
||||
public static string DisplayVersion => ThisAssembly.AssemblyInformationalVersion + (ThisAssembly.IsPublicRelease ? "" : " (prerelease)");
|
||||
public static string FileVersion => ThisAssembly.AssemblyFileVersion;
|
||||
#pragma warning restore CS0436 // Type conflicts with imported type
|
||||
|
||||
public static int Run(string[] args, CommandSet packageCommands)
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
var logger = ConsoleLogger.RegisterLogger();
|
||||
|
||||
bool help = false;
|
||||
bool verbose = false;
|
||||
string xplat = null;
|
||||
var globalOptions = new OptionSet() {
|
||||
{ "h|?|help", "Ignores all other arguments and shows help text", _ => help = true },
|
||||
{ "verbose", "Print extra diagnostic logging", _ => verbose = true },
|
||||
{ "x|xplat=", "Select {PLATFORM} to cross-compile for (eg. win, osx)", v => xplat = v },
|
||||
{ "verbose", "Print all diagnostic messages", _ => verbose = true },
|
||||
};
|
||||
|
||||
var exeName = Path.GetFileName(SquirrelRuntimeInfo.EntryExePath);
|
||||
string sqUsage =
|
||||
$"Squirrel {DisplayVersion}, tool for creating and deploying Squirrel releases" + Environment.NewLine +
|
||||
$"Squirrel {SquirrelRuntimeInfo.SquirrelDisplayVersion}, tool for creating and deploying Squirrel releases" + Environment.NewLine +
|
||||
$"Usage: {exeName} [verb] [--option:value]";
|
||||
|
||||
var commands = new CommandSet {
|
||||
"",
|
||||
sqUsage,
|
||||
"",
|
||||
"[ Global Options ]",
|
||||
globalOptions.GetHelpText().TrimEnd(),
|
||||
"",
|
||||
packageCommands,
|
||||
//"[ Package Authoring ]",
|
||||
//{ "pack", "Creates a Squirrel release from a folder containing application files", new PackOptions(), Pack },
|
||||
//{ "releasify", "Take an existing nuget package and convert it into a Squirrel release", new ReleasifyOptions(), Releasify },
|
||||
"",
|
||||
"[ Package Deployment / Syncing ]",
|
||||
{ "s3-down", "Download releases from S3 compatible API", new SyncS3Options(), o => Download(new S3Repository(o)) },
|
||||
{ "s3-up", "Upload releases to S3 compatible API", new SyncS3Options(), o => Upload(new S3Repository(o)) },
|
||||
{ "http-down", "Download releases from an HTTP source", new SyncHttpOptions(), o => Download(new SimpleWebRepository(o)) },
|
||||
{ "github-down", "Download releases from GitHub", new SyncGithubOptions(), o => Download(new GitHubRepository(o)) },
|
||||
//"",
|
||||
//"[ Examples ]",
|
||||
//$" {exeName} pack ",
|
||||
//$" ",
|
||||
};
|
||||
|
||||
try {
|
||||
globalOptions.Parse(args);
|
||||
|
||||
if (xplat == null)
|
||||
xplat = SquirrelRuntimeInfo.SystemOsName;
|
||||
|
||||
CommandSet packageCommands;
|
||||
|
||||
switch (xplat.ToLower()) {
|
||||
case "win":
|
||||
case "windows":
|
||||
if (!SquirrelRuntimeInfo.IsWindows)
|
||||
logger.Write("Cross-compiling will cause some features of Squirrel to be disabled.", LogLevel.Warn);
|
||||
packageCommands = Windows.CommandsWindows.GetCommands();
|
||||
break;
|
||||
|
||||
case "mac":
|
||||
case "osx":
|
||||
case "macos":
|
||||
if (!SquirrelRuntimeInfo.IsOSX)
|
||||
logger.Write("Cross-compiling will cause some features of Squirrel to be disabled.", LogLevel.Warn);
|
||||
packageCommands = OSX.CommandsOSX.GetCommands();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported OS platform: " + xplat);
|
||||
}
|
||||
|
||||
var commands = new CommandSet {
|
||||
"",
|
||||
sqUsage,
|
||||
"",
|
||||
"[ Global Options ]",
|
||||
globalOptions.GetHelpText().TrimEnd(),
|
||||
"",
|
||||
packageCommands,
|
||||
"",
|
||||
"[ Package Deployment / Syncing ]",
|
||||
{ "s3-down", "Download releases from S3 compatible API", new SyncS3Options(), o => Download(new S3Repository(o)) },
|
||||
{ "s3-up", "Upload releases to S3 compatible API", new SyncS3Options(), o => Upload(new S3Repository(o)) },
|
||||
{ "http-down", "Download releases from an HTTP source", new SyncHttpOptions(), o => Download(new SimpleWebRepository(o)) },
|
||||
{ "github-down", "Download releases from GitHub", new SyncGithubOptions(), o => Download(new GitHubRepository(o)) },
|
||||
};
|
||||
|
||||
if (verbose) {
|
||||
logger.Level = LogLevel.Debug;
|
||||
}
|
||||
@@ -66,20 +81,21 @@ namespace Squirrel.CommandLine
|
||||
if (help) {
|
||||
commands.WriteHelp();
|
||||
return 0;
|
||||
} else {
|
||||
// parse cli and run command
|
||||
commands.Execute(args);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} catch (Exception ex) when (ex is OptionValidationException || ex is OptionException) {
|
||||
// if the arguments fail to validate, print argument help
|
||||
Console.WriteLine();
|
||||
logger.Write(ex.Message, LogLevel.Error);
|
||||
commands.WriteHelp();
|
||||
Console.WriteLine();
|
||||
logger.Write(ex.Message, LogLevel.Error);
|
||||
return -1;
|
||||
try {
|
||||
// parse cli and run command
|
||||
commands.Execute(args);
|
||||
return 0;
|
||||
} catch (Exception ex) when (ex is OptionValidationException || ex is OptionException) {
|
||||
// if the arguments fail to validate, print argument help
|
||||
Console.WriteLine();
|
||||
logger.Write(ex.Message, LogLevel.Error);
|
||||
commands.WriteHelp();
|
||||
Console.WriteLine();
|
||||
logger.Write(ex.Message, LogLevel.Error);
|
||||
return -1;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// for other errors, just print the error and short usage instructions
|
||||
Console.WriteLine();
|
||||
@@ -95,4 +111,4 @@ namespace Squirrel.CommandLine
|
||||
|
||||
static void Download<T>(T repo) where T : IPackageRepository => repo.DownloadRecentPackages().GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,21 +16,19 @@ using Squirrel.SimpleSplat;
|
||||
namespace Squirrel.CommandLine.Windows
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
class Program : IEnableLogger
|
||||
class CommandsWindows : IEnableLogger
|
||||
{
|
||||
static IFullLogger Log => SquirrelLocator.Current.GetService<ILogManager>().GetLogger(typeof(Program));
|
||||
static IFullLogger Log => SquirrelLocator.Current.GetService<ILogManager>().GetLogger(typeof(CommandsWindows));
|
||||
|
||||
public static int MainWindows(string[] args)
|
||||
public static CommandSet GetCommands()
|
||||
{
|
||||
var commands = new CommandSet {
|
||||
return new CommandSet {
|
||||
"[ Package Authoring ]",
|
||||
{ "pack", "Creates a Squirrel release from a folder containing application files", new PackOptions(), Pack },
|
||||
{ "releasify", "Take an existing nuget package and convert it into a Squirrel release", new ReleasifyOptions(), Releasify },
|
||||
};
|
||||
|
||||
return SquirrelHost.Run(args, commands);
|
||||
}
|
||||
|
||||
|
||||
static void Pack(PackOptions options)
|
||||
{
|
||||
using (Utility.GetTempDirectory(out var tmp)) {
|
||||
@@ -136,7 +134,7 @@ namespace Squirrel.CommandLine.Windows
|
||||
// warning if the installed SquirrelLib version is not the same as Squirrel.exe
|
||||
StringFileInfo sqLib = null;
|
||||
try {
|
||||
var myFileVersion = new NuGetVersion(SquirrelHost.FileVersion).Version;
|
||||
var myFileVersion = new NuGetVersion(SquirrelRuntimeInfo.SquirrelFileVersion).Version;
|
||||
sqLib = Directory.EnumerateFiles(libDir, "SquirrelLib.dll")
|
||||
.Select(f => { StringFileInfo.ReadVersionInfo(f, out var fi); return fi; })
|
||||
.FirstOrDefault(fi => fi.FileVersion != myFileVersion);
|
||||
@@ -146,7 +144,7 @@ namespace Squirrel.CommandLine.Windows
|
||||
if (sqLib != null) {
|
||||
Log.Warn(
|
||||
$"SquirrelLib.dll {sqLib.FileVersion} is installed in provided package, " +
|
||||
$"but current Squirrel.exe version is {SquirrelHost.DisplayVersion} ({SquirrelHost.FileVersion}). " +
|
||||
$"but current Squirrel.exe version is {SquirrelRuntimeInfo.SquirrelDisplayVersion} ({SquirrelRuntimeInfo.SquirrelFileVersion}). " +
|
||||
$"The LIB version and CLI tool version must be the same to build releases " +
|
||||
$"or the application may fail to update properly.");
|
||||
}
|
||||
@@ -1,75 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using Microsoft.Build.Construction;
|
||||
using Squirrel.CommandLine;
|
||||
|
||||
namespace Squirrel.Tool
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
static int Main(string[] args)
|
||||
{
|
||||
var packageName = "Clowd.Squirrel";
|
||||
// var dependencies = Directory.EnumerateFiles(Environment.CurrentDirectory, "*.sln", SearchOption.TopDirectoryOnly)
|
||||
// .SelectMany(GetProjectsFromSln)
|
||||
// .Distinct()
|
||||
// .SelectMany(proj => GetSquirrelVersionsFromProject(packageName, proj))
|
||||
// .Distinct()
|
||||
// .ToArray();
|
||||
|
||||
var dependencies = GetSquirrelVersionsFromProject(packageName);
|
||||
|
||||
if (dependencies.Length == 0)
|
||||
throw new Exception("Clowd.Squirrel package was not found to be installed in the current solution.");
|
||||
|
||||
if (dependencies.Length > 1)
|
||||
throw new Exception("Found multiple versions of Clowd.Squirrel installed in current solution. " +
|
||||
"Please consolidate to a single version: " + string.Join(", ", dependencies));
|
||||
|
||||
var toolExecutable = SquirrelRuntimeInfo.SystemOsName switch {
|
||||
"windows" => "Squirrel.exe",
|
||||
"osx" => "SquirrelMac",
|
||||
_ => throw new NotSupportedException("OS not supported: " + SquirrelRuntimeInfo.SystemOsName),
|
||||
};
|
||||
if (args.Contains("--csq-embedded-only")) {
|
||||
return SquirrelHost.Main(args);
|
||||
}
|
||||
|
||||
var packages = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
|
||||
var toolPath = Path.Combine(packages, packageName.ToLower(), dependencies.First(), "tools", toolExecutable);
|
||||
Console.WriteLine($"Squirrel Locator {SquirrelRuntimeInfo.SquirrelDisplayVersion}");
|
||||
|
||||
Process.Start(toolPath, args);
|
||||
var packageName = "Clowd.Squirrel";
|
||||
var dependencies = GetPackageVersionsFromCurrentDir(packageName).Distinct().ToArray();
|
||||
|
||||
if (dependencies.Length == 0) {
|
||||
Console.WriteLine("Clowd.Squirrel package was not found to be installed in the current working dir/project.");
|
||||
Console.WriteLine($"Using bundled Squirrel {SquirrelRuntimeInfo.SquirrelDisplayVersion}");
|
||||
return SquirrelHost.Main(args);
|
||||
}
|
||||
|
||||
if (dependencies.Length > 1) {
|
||||
throw new Exception("Found multiple versions of Clowd.Squirrel installed in current working dir/project. " +
|
||||
"Please consolidate to a single version: " + string.Join(", ", dependencies));
|
||||
}
|
||||
|
||||
var packages = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
|
||||
|
||||
var targetVersion = dependencies.First();
|
||||
Console.WriteLine("Attempting to locate Squirrel " + targetVersion + " (installed in current working dir)");
|
||||
|
||||
var dllName = "csq.dll";
|
||||
var exeName = "Squirrel.exe";
|
||||
var toolDllPath = Path.Combine(packages, packageName.ToLower(), targetVersion, "tools", dllName);
|
||||
var toolExePath = Path.Combine(packages, packageName.ToLower(), targetVersion, "tools", exeName);
|
||||
|
||||
Process p;
|
||||
|
||||
if (File.Exists(toolDllPath)) {
|
||||
Console.WriteLine("Running at: " + toolDllPath);
|
||||
p = Process.Start("dotnet", new[] { dllName, "--csq-embedded-only" }.Concat(args));
|
||||
} else if (File.Exists(toolExePath)) {
|
||||
if (!SquirrelRuntimeInfo.IsWindows)
|
||||
throw new NotSupportedException($"The installed version {targetVersion} does not support this operating system. Please update.");
|
||||
Console.WriteLine("Running at: " + toolExePath);
|
||||
p = Process.Start(toolExePath, args);
|
||||
} else {
|
||||
throw new Exception("Unable to locate Squirrel " + targetVersion);
|
||||
}
|
||||
|
||||
p.WaitForExit();
|
||||
return p.ExitCode;
|
||||
}
|
||||
|
||||
// static string[] GetProjectsFromSln(string solutionFile)
|
||||
// {
|
||||
// var result = ProcessUtil.InvokeProcess("dotnet", new[] { "sln", solutionFile, "list" }, null, CancellationToken.None);
|
||||
// var proj = result.StdOutput
|
||||
// .Split('\r', '\n')
|
||||
// .Select(s => s.TrimEnd())
|
||||
// .Where(s => s.EndsWith(".csproj", StringComparison.InvariantCultureIgnoreCase))
|
||||
// .Select(s => s.Trim())
|
||||
// .ToArray();
|
||||
//
|
||||
// return proj;
|
||||
// }
|
||||
|
||||
static string[] GetSquirrelVersionsFromProject(string packageName)
|
||||
static IEnumerable<string> GetPackageVersionsFromCurrentDir(string packageName)
|
||||
{
|
||||
//dotnet list "$PSScriptRoot\src\Clowd\Clowd.csproj" package
|
||||
var result = ProcessUtil.InvokeProcess("dotnet", new[] { "list", "package" }, null, CancellationToken.None);
|
||||
Console.WriteLine(result.StdOutput);
|
||||
|
||||
var escapedName = Regex.Escape(packageName);
|
||||
var matches = Regex.Matches(result.StdOutput, $@"(?m){escapedName}.*\s(\d{{1,3}}\.\d{{1,3}}\.\d.*?)$");
|
||||
foreach (var projFile in Directory.EnumerateFiles(Environment.CurrentDirectory, "*.csproj", SearchOption.AllDirectories)) {
|
||||
var proj = ProjectRootElement.Open(projFile);
|
||||
if (proj == null) continue;
|
||||
|
||||
if (matches.Count == 0)
|
||||
return new string[0];
|
||||
ProjectItemElement item = proj.Items.FirstOrDefault(i => i.ItemType == "PackageReference" && i.Include == packageName);
|
||||
if (item == null) continue;
|
||||
|
||||
var outp = matches.Select(m => m.Groups[1].Value.Trim()).Distinct().ToArray();
|
||||
Console.WriteLine(String.Join(", ", outp));
|
||||
Console.WriteLine(String.Join(", ", outp));
|
||||
Console.WriteLine(String.Join(", ", outp));
|
||||
return outp;
|
||||
var version = item.Children.FirstOrDefault(x => x.ElementName == "Version") as ProjectMetadataElement;
|
||||
if (version == null) continue;
|
||||
|
||||
yield return version.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>true</IsPackable>
|
||||
<AssemblyName>csq</AssemblyName>
|
||||
<PackageId>csq</PackageId>
|
||||
@@ -19,9 +19,19 @@
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Description>A .NET Core Tool that uses the Squirrel framework to create installers and update packages for dotnet applications.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\vendor\**" Pack="true" PackagePath="tools\net6.0\any\" />
|
||||
<None Include="..\..\build\$(Configuration)\Win32\Setup.exe" Pack="true" PackagePath="tools\net6.0\any\" />
|
||||
<None Include="..\..\build\$(Configuration)\Win32\StubExecutable.exe" Pack="true" PackagePath="tools\net6.0\any\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Squirrel\Squirrel.csproj" />
|
||||
<ProjectReference Include="..\Squirrel.CommandLine\Squirrel.CommandLine.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -66,6 +66,12 @@ namespace Squirrel
|
||||
/// </summary>
|
||||
public static class SquirrelRuntimeInfo
|
||||
{
|
||||
/// <summary> The current compiled Squirrel display version. </summary>
|
||||
public static string SquirrelDisplayVersion => ThisAssembly.AssemblyInformationalVersion + (ThisAssembly.IsPublicRelease ? "" : " (prerelease)");
|
||||
|
||||
/// <summary> The current compiled Squirrel assembly file version. </summary>
|
||||
public static string SquirrelFileVersion => ThisAssembly.AssemblyFileVersion;
|
||||
|
||||
/// <summary> The path on disk of the entry assembly. </summary>
|
||||
public static string EntryExePath { get; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user