Add --shortcuts property to cli and pass through to nuspec

This commit is contained in:
Caelan Sayler
2024-05-24 16:50:40 +01:00
parent 242f5a9283
commit d4fc0d62f9
8 changed files with 76 additions and 28 deletions

View File

@@ -91,6 +91,8 @@ public class PackTask : MSBuildAsyncTask
public string? Categories { get; set; }
public string? Shortcuts { get; set; }
protected override async Task<bool> ExecuteAsync(CancellationToken cancellationToken)
{
//System.Diagnostics.Debugger.Launch();

View File

@@ -22,6 +22,7 @@
<VelopackPackTitle Condition="'$(VelopackPackTitle)' == ''">$(Product)</VelopackPackTitle>
<VelopackPackAuthors Condition="'$(VelopackPackAuthors)' == ''">$(Authors)</VelopackPackAuthors>
<VelopackTargetRuntime Condition="'$(VelopackTargetRuntime)' == ''">$(RuntimeIdentifier)</VelopackTargetRuntime>
<VelopackShortcuts Condition="'$(VelopackShortcuts)' == ''">Desktop,StartMenuRoot</VelopackShortcuts>
<!-- Allows a cross platform app (eg. Avalonia) to specify all three via csproj and have them applied correctly -->
<!-- TODO: this should probably switch based on the target RID and not the current OS, but we currently don't
@@ -88,6 +89,7 @@
SignParallel="$(VelopackSignParallel)"
SignTemplate="$(VelopackSignTemplate)"
Categories="$(VelopackCategories)"
Shortcuts="$(VelopackShortcuts)"
/>
</Target>

View File

@@ -36,6 +36,10 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions>
Log.Info("Skipping VelopackApp.Build.Run() check.");
}
// add nuspec metadata
ExtraNuspecMetadata["runtimeDependencies"] = GetRuntimeDependencies();
ExtraNuspecMetadata["shortcutLocations"] = GetShortcutLocations();
// copy files to temp dir, so we can modify them
var dir = TempDir.CreateSubdirectory("PreprocessPackDirWin");
CopyFiles(new DirectoryInfo(packDir), dir, progress, true);
@@ -76,7 +80,32 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions>
return Task.FromResult(packDir);
}
protected override string GetRuntimeDependencies()
protected string GetShortcutLocations()
{
if (String.IsNullOrWhiteSpace(Options.Shortcuts))
return null;
try {
var shortcuts = Options.Shortcuts.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.Select(x => (ShortcutLocation) Enum.Parse(typeof(ShortcutLocation), x, true))
.ToList();
if (shortcuts.Count == 0)
return null;
var shortcutString = string.Join(",", shortcuts.Select(x => x.ToString()));
Log.Debug($"Shortcut Locations: {shortcutString}");
return shortcutString;
} catch (Exception ex) {
throw new UserInfoException(
$"Invalid shortcut locations '{Options.Shortcuts}'. " +
$"Valid values for comma delimited list are: {string.Join(", ", Enum.GetNames(typeof(ShortcutLocation)))}." +
$"Error was {ex.Message}");
}
}
protected string GetRuntimeDependencies()
{
if (string.IsNullOrWhiteSpace(Options.Runtimes))
return "";

View File

@@ -21,4 +21,6 @@ public class WindowsPackOptions : WindowsReleasifyOptions, INugetPackCommand, IP
public bool NoPortable { get; set; }
public bool NoInst { get; set; }
public string Shortcuts { get; set; }
}

View File

@@ -30,7 +30,7 @@ public abstract class PackageBuilder<T> : ICommand<T>
protected string Channel { get; private set; }
protected string RuntimeDependencies { get; private set; }
protected Dictionary<string, string> ExtraNuspecMetadata { get; } = new();
private readonly Regex REGEX_EXCLUDES = new Regex(@".*[\\\/]createdump.*|.*\.vshost\..*|.*\.nupkg$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
@@ -91,7 +91,6 @@ public abstract class PackageBuilder<T> : ICommand<T>
using var _1 = Utility.GetTempDirectory(out var pkgTempDir);
TempDir = new DirectoryInfo(pkgTempDir);
Options = options;
RuntimeDependencies = GetRuntimeDependencies();
ConcurrentBag<(string from, string to)> filesToCopy = new();
@@ -168,11 +167,6 @@ public abstract class PackageBuilder<T> : ICommand<T>
});
}
protected virtual string GetRuntimeDependencies()
{
return null;
}
protected abstract string[] GetMainExeSearchPaths(string packDirectory, string mainExeName);
protected virtual string GenerateNuspecContent()
@@ -184,29 +178,35 @@ public abstract class PackageBuilder<T> : ICommand<T>
var releaseNotes = Options.ReleaseNotes;
var rid = Options.TargetRuntime;
string releaseNotesText = "";
string extraMetadata = "";
void addMetadata(string key, string value)
{
if (!String.IsNullOrEmpty(key) && !String.IsNullOrEmpty(value)) {
if (!SecurityElement.IsValidText(value)) {
value = $"""<![CDATA[{"\n"}{value}{"\n"}]]>""";
}
extraMetadata += $"<{key}>{value}</{key}>{Environment.NewLine}";
}
}
if (ExtraNuspecMetadata.Any()) {
foreach (var kvp in ExtraNuspecMetadata) {
addMetadata(kvp.Key, kvp.Value);
}
}
if (!String.IsNullOrEmpty(releaseNotes)) {
var markdown = File.ReadAllText(releaseNotes);
var html = Markdown.ToHtml(markdown);
releaseNotesText = $"""
<releaseNotes>{SecurityElement.Escape(markdown)}</releaseNotes>
<releaseNotesHtml><![CDATA[{"\n"}{html}{"\n"}]]></releaseNotesHtml>
""";
addMetadata("releaseNotes", markdown);
addMetadata("releaseNotesHtml", Markdown.ToHtml(markdown));
}
string osMinVersionText = "";
if (rid?.HasVersion == true) {
osMinVersionText = $"<osMinVersion>{rid.Version}</osMinVersion>";
addMetadata("osMinVersion", rid.Version.ToString());
}
string machineArchitectureText = "";
if (rid?.HasArchitecture == true) {
machineArchitectureText = $"<machineArchitecture>{rid.Architecture}</machineArchitecture>";
}
string runtimeDependenciesText = "";
if (!String.IsNullOrWhiteSpace(RuntimeDependencies)) {
runtimeDependenciesText = $"<runtimeDependencies>{RuntimeDependencies}</runtimeDependencies>";
addMetadata("machineArchitecture", rid.Architecture.ToString());
}
string nuspec = $"""
@@ -222,10 +222,7 @@ public abstract class PackageBuilder<T> : ICommand<T>
<mainExe>{MainExeName}</mainExe>
<os>{rid.BaseRID.GetOsShortName()}</os>
<rid>{rid.ToDisplay(RidDisplayType.NoVersion)}</rid>
{osMinVersionText}
{machineArchitectureText}
{releaseNotesText}
{runtimeDependenciesText}
{extraMetadata.Trim()}
</metadata>
</package>
""".Trim();

View File

@@ -16,6 +16,8 @@ public class WindowsPackCommand : PackCommand
public string SignTemplate { get; private set; }
public string Shortcuts { get; private set; }
public WindowsPackCommand()
: base("pack", "Creates a release from a folder containing application files.")
{
@@ -23,7 +25,7 @@ public class WindowsPackCommand : PackCommand
IconOption.RequiresExtension(".ico");
AddOption<string>((v) => Runtimes = v, "-f", "--framework")
.SetDescription("List of required runtimes to install during setup. example: 'net6-x64-desktop,vcredist143'.")
.SetDescription("List of required runtimes to install during setup. Example: 'net6-x64-desktop,vcredist143'.")
.SetArgumentHelpName("RUNTIMES");
AddOption<FileInfo>((v) => SplashImage = v.ToFullNameOrNull(), "-s", "--splashImage")
@@ -50,6 +52,11 @@ public class WindowsPackCommand : PackCommand
.SetHidden()
.SetDefault(10);
AddOption<string>((v) => Shortcuts = v, "--shortcuts")
.SetDescription("List of locations to install shortcuts to during setup.")
.SetArgumentHelpName("LOC")
.SetDefault("Desktop,StartMenuRoot");
if (VelopackRuntimeInfo.IsWindows) {
var signParams = AddOption<string>((v) => SignParameters = v, "--signParams", "-n")
.SetDescription("Sign files via signtool.exe using these parameters.")

View File

@@ -27,6 +27,7 @@ namespace Velopack.NuGet
public string? Title { get; private set; }
public string? Summary { get; private set; }
public string? Copyright { get; private set; }
public IEnumerable<string> ShortcutLocations { get; private set; } = Enumerable.Empty<string>();
public IEnumerable<string> Authors { get; private set; } = Enumerable.Empty<string>();
public IEnumerable<string> RuntimeDependencies { get; private set; } = Enumerable.Empty<string>();
@@ -137,6 +138,9 @@ namespace Velopack.NuGet
case "channel":
Channel = value;
break;
case "shortcutLocations":
ShortcutLocations = getCommaDelimitedValue(value);
break;
}
}

View File

@@ -18,6 +18,11 @@ namespace Velopack.Windows
[Flags]
public enum ShortcutLocation
{
/// <summary>
/// Represents no shortcut location
/// </summary>
None = 0,
/// <summary>
/// A shortcut in ProgramFiles within a publisher sub-directory
/// </summary>