Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions Squirrel.sln
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionLevel", "SolutionLevel", "{ED657D2C-F8A0-4012-A64F-7367D41BE4D2}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
build.ps1 = build.ps1
.github\workflows\build.yml = .github\workflows\build.yml
src\Directory.Build.props = src\Directory.Build.props
Squirrel.entitlements = Squirrel.entitlements
vendor\wix\template.wxs = vendor\wix\template.wxs
version.json = version.json
.github\workflows\build.yml = .github\workflows\build.yml
build.ps1 = build.ps1
Squirrel.entitlements = Squirrel.entitlements
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Setup", "src\Setup\Setup.vcxproj", "{6B406985-B2E1-4FED-A405-BD0694D68E93}"
Expand All @@ -26,14 +26,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrel.CommandLine", "src
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubExecutable", "src\StubExecutable\StubExecutable.vcxproj", "{611A03D4-4CDE-4DA0-B151-DE6FAFFB8B8C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update.OSX", "src\Update.OSX\Update.OSX.csproj", "{A63B2CDA-5ECC-461C-9B1F-54CF4709ACBD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squirrel.CommandLine.Tests", "test\Squirrel.CommandLine.Tests\Squirrel.CommandLine.Tests.csproj", "{519EAB50-47B8-425F-8B20-AB9548F220B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -72,6 +74,10 @@ Global
{9E769C7E-A54C-4844-8362-727D37BB1578}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E769C7E-A54C-4844-8362-727D37BB1578}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E769C7E-A54C-4844-8362-727D37BB1578}.Release|Any CPU.Build.0 = Release|Any CPU
{519EAB50-47B8-425F-8B20-AB9548F220B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{519EAB50-47B8-425F-8B20-AB9548F220B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{519EAB50-47B8-425F-8B20-AB9548F220B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{519EAB50-47B8-425F-8B20-AB9548F220B4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
28 changes: 28 additions & 0 deletions src/Squirrel.CommandLine/BaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using Squirrel.SimpleSplat;

namespace Squirrel.CommandLine
{
public class BaseCommand : Command
{
protected static IFullLogger Log = SquirrelLocator.CurrentMutable.GetService<ILogManager>().GetLogger(typeof(BaseOptions));

public Option<DirectoryInfo> ReleaseDirectory { get; }

protected BaseCommand(string name, string description)
: base(name, description)
{
ReleaseDirectory = new Option<DirectoryInfo>(new[] { "-r", "--releaseDir" }, "Output directory for Squirrel packages") {
ArgumentHelpName = "DIRECTORY"
};
Add(ReleaseDirectory);
}

private protected void SetOptionsValues(InvocationContext context, BaseOptions options)
{
options.releaseDir = context.ParseResult.GetValueForOption(ReleaseDirectory)?.FullName;
}
}
}
9 changes: 9 additions & 0 deletions src/Squirrel.CommandLine/Bitness.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Squirrel.CommandLine
{
public enum Bitness
{
Unknown,
x86,
x64
}
}
96 changes: 96 additions & 0 deletions src/Squirrel.CommandLine/Deployment/GitHubCommands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System.CommandLine;
using Squirrel.CommandLine.Sync;
using System.CommandLine.Invocation;
using System.Threading.Tasks;
using System;

namespace Squirrel.CommandLine.Deployment
{
public class GitHubBaseCommand : BaseCommand
{
public Option<Uri> RepoUrl { get; }
public Option<string> Token { get; }

protected GitHubBaseCommand(string name, string description)
: base(name, description)
{
RepoUrl = new Option<Uri>("--repoUrl", "Full url to the github repository\nexample: 'https://github.com/myname/myrepo'.") {
IsRequired = true
};
RepoUrl.MustBeValidHttpUri();
Add(RepoUrl);

Token = new Option<string>("--token", "OAuth token to use as login credentials.");
Add(Token);
}

private protected void SetOptionsValues(InvocationContext context, SyncGithubOptions options)
{
base.SetOptionsValues(context, options);
options.repoUrl = context.ParseResult.GetValueForOption(RepoUrl)?.AbsoluteUri;
options.token = context.ParseResult.GetValueForOption(Token);
}
}

public class GitHubDownloadCommand : GitHubBaseCommand
{
public Option<bool> Pre { get; }

public GitHubDownloadCommand()
: base("github", "Download latest release from GitHub repository.")
{
Pre = new Option<bool>("--pre", "Get latest pre-release instead of stable.");
Add(Pre);

this.SetHandler(Execute);
}

private protected new void SetOptionsValues(InvocationContext context, SyncGithubOptions options)
{
base.SetOptionsValues(context, options);
options.pre = context.ParseResult.GetValueForOption(Pre);
}

private async Task Execute(InvocationContext context)
{
SyncGithubOptions options = new();
SetOptionsValues(context, options);
await new GitHubRepository(options).DownloadRecentPackages();
}
}

public class GitHubUploadCommand : GitHubBaseCommand
{
public Option<bool> Publish { get; }
public Option<string> ReleaseName { get; }

public GitHubUploadCommand()
: base("github", "Upload latest release to a GitHub repository.")
{
Publish = new Option<bool>("--publish", "Publish release instead of creating draft.");
Add(Publish);

ReleaseName = new Option<string>("--releaseName", "A custom {NAME} for created release.") {
ArgumentHelpName = "NAME"
};
Add(ReleaseName);

this.SetHandler(Execute);
}

//Intentionally hiding base member
private protected new void SetOptionsValues(InvocationContext context, SyncGithubOptions options)
{
base.SetOptionsValues(context, options);
options.publish = context.ParseResult.GetValueForOption(Publish);
options.releaseName = context.ParseResult.GetValueForOption(ReleaseName);
}

private async Task Execute(InvocationContext context)
{
SyncGithubOptions options = new();
SetOptionsValues(context, options);
await new GitHubRepository(options).UploadMissingPackages();
}
}
}
39 changes: 39 additions & 0 deletions src/Squirrel.CommandLine/Deployment/HttpCommands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Threading.Tasks;
using Squirrel.CommandLine.Sync;

namespace Squirrel.CommandLine.Deployment
{
public class HttpDownloadCommand : BaseCommand
{
public Option<Uri> Url { get; }

public HttpDownloadCommand()
: base("http", "Download latest release from a HTTP source.")
{
Url = new Option<Uri>("--url", "Url to download remote releases from.") {
ArgumentHelpName = "URL",
IsRequired = true,
};
Url.MustBeValidHttpUri();
Add(Url);

this.SetHandler(Execute);
}

private protected void SetOptionsValues(InvocationContext context, SyncHttpOptions options)
{
base.SetOptionsValues(context, options);
options.url = context.ParseResult.GetValueForOption(Url)?.AbsoluteUri;
}

public async Task Execute(InvocationContext context)
{
SyncHttpOptions options = new();
SetOptionsValues(context, options);
await new SimpleWebRepository(options).DownloadRecentPackages();
}
}
}
132 changes: 132 additions & 0 deletions src/Squirrel.CommandLine/Deployment/S3Commands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Threading.Tasks;
using Squirrel.CommandLine.Sync;

namespace Squirrel.CommandLine.Deployment
{
public class S3BaseCommand : BaseCommand
{
public Option<string> KeyId { get; }
public Option<string> Secret { get; }
public Option<string> Region { get; }
public Option<string> Endpoint { get; }
public Option<string> Bucket { get; }
public Option<string> PathPrefix { get; }

protected S3BaseCommand(string name, string description)
: base(name, description)
{
KeyId = new Option<string>("--keyId", "Authentication identifier or access key.") {
ArgumentHelpName = "IDENTIFIER",
IsRequired = true
};
Add(KeyId);

Secret = new Option<string>("--secret", "Authentication secret key.") {
ArgumentHelpName = "KEY",
IsRequired = true
};
Add(Secret);

Region = new Option<string>("--region", "AWS service region (eg. us-west-1).") {
ArgumentHelpName = "REGION"
};
Region.AddValidator(result => {
for (var i = 0; i < result.Tokens.Count; i++) {
var region = result.Tokens[i].Value;
if (!string.IsNullOrWhiteSpace(region)) {
var r = Amazon.RegionEndpoint.GetBySystemName(result.Tokens[0].Value);
if (r is null || r.DisplayName == "Unknown") {
result.ErrorMessage = $"Region '{region}' lookup failed, is this a valid AWS region?";
}
} else {
result.ErrorMessage = "A region value is required";
}
}
});
Add(Region);

Endpoint = new Option<string>("--endpoint", "Custom service url (backblaze, digital ocean, etc).") {
ArgumentHelpName = "URL"
};
Add(Endpoint);

Bucket = new Option<string>("--bucket", "Name of the S3 bucket.") {
ArgumentHelpName = "NAME",
IsRequired = true
};
Add(Bucket);

PathPrefix = new Option<string>("--pathPrefix", "A sub-folder used for files in the bucket, for creating release channels (eg. 'stable' or 'dev').") {
ArgumentHelpName = "PREFIX"
};
Add(PathPrefix);

this.AreMutuallyExclusive(Region, Endpoint)
.AtLeastOneRequired(Region, Endpoint);
}

private protected void SetOptionsValues(InvocationContext context, SyncS3Options options)
{
base.SetOptionsValues(context, options);
options.keyId = context.ParseResult.GetValueForOption(KeyId);
options.secret = context.ParseResult.GetValueForOption(Secret);
options.region = context.ParseResult.GetValueForOption(Region);
options.endpoint = context.ParseResult.GetValueForOption(Endpoint);
options.bucket = context.ParseResult.GetValueForOption(Bucket);
options.pathPrefix = context.ParseResult.GetValueForOption(PathPrefix);
}
}

public class S3DownloadCommand : S3BaseCommand
{
public S3DownloadCommand()
: base("s3", "Download latest release from an S3 bucket.")
{
this.SetHandler(Execute);
}

private async Task Execute(InvocationContext context)
{
SyncS3Options options = new();
SetOptionsValues(context, options);
await new S3Repository(options).DownloadRecentPackages();
}
}

public class S3UploadCommand : S3BaseCommand
{
public Option<bool> Overwrite { get; }
public Option<int> KeepMaxReleases { get; }

public S3UploadCommand()
: base("s3", "Upload releases to an S3 bucket.")
{
Overwrite = new Option<bool>("--overwrite", "Replace remote files if local files have changed.");
Add(Overwrite);

KeepMaxReleases = new Option<int>("--keepMaxReleases", "Apply a retention policy which keeps only the specified number of old versions in remote source.") {
ArgumentHelpName = "NUMBER"
};
Add(KeepMaxReleases);

this.SetHandler(Execute);
}

//Intentionally hiding base member
private protected new void SetOptionsValues(InvocationContext context, SyncS3Options options)
{
base.SetOptionsValues(context, options);
options.overwrite = context.ParseResult.GetValueForOption(Overwrite);
options.keepMaxReleases = context.ParseResult.GetValueForOption(KeepMaxReleases);
}

private async Task Execute(InvocationContext context)
{
SyncS3Options options = new();
SetOptionsValues(context, options);
await new S3Repository(options).UploadMissingPackages();
}
}
}
Loading