authoring app launch and toml file creation fixes
This commit is contained in:
@@ -48,6 +48,32 @@ public class MainViewModelTests
|
||||
Assert.Contains(validation.Warnings, warning => warning.Contains("require elevation", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyDefaults_replaces_previous_suggested_entries_without_removing_manual_entries()
|
||||
{
|
||||
var viewModel = new MainViewModel(() => null);
|
||||
viewModel.AddDirectory(@"{LocalAppData}\Manual");
|
||||
viewModel.AddFile(@"payload\manual.dll", @"{LocalAppData}\Manual\manual.dll");
|
||||
viewModel.AddPurgePath(@"{LocalAppData}\Manual");
|
||||
|
||||
viewModel.AppName = "Renamed App";
|
||||
viewModel.ApplicationFolder = "RenamedApp";
|
||||
viewModel.PrimaryPayload = @"payload\renamed.exe";
|
||||
viewModel.ApplyDefaults(resetCollections: false);
|
||||
|
||||
Assert.DoesNotContain(viewModel.Directories, directory => directory.Path == @"{LocalAppData}\CovenantSetupSample");
|
||||
Assert.DoesNotContain(viewModel.Files, file => file.Source == @"payload\sample_app.cmd");
|
||||
Assert.DoesNotContain(viewModel.PurgePaths, path => path == @"{LocalAppData}\CovenantSetupSample");
|
||||
Assert.Contains(viewModel.Directories, directory => directory.Path == @"{LocalAppData}\RenamedApp");
|
||||
Assert.Contains(viewModel.Files, file => file.Source == @"payload\renamed.exe");
|
||||
Assert.Contains(viewModel.PurgePaths, path => path == @"{LocalAppData}\RenamedApp");
|
||||
Assert.Contains(viewModel.Directories, directory => directory.Path == @"{LocalAppData}\Manual");
|
||||
Assert.Contains(viewModel.Files, file => file.Source == @"payload\manual.dll");
|
||||
Assert.Contains(viewModel.PurgePaths, path => path == @"{LocalAppData}\Manual");
|
||||
Assert.DoesNotContain("CovenantSetupSample", viewModel.TomlPreview, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("Covenant-Setup Sample App", viewModel.TomlPreview, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Packaging_is_disabled_when_covenant_setup_is_missing()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
private string _tomlPreview = string.Empty;
|
||||
private string _validationSummary = string.Empty;
|
||||
private bool _hasValidationErrors;
|
||||
private bool _suppressPreviewRefresh;
|
||||
private SuggestedManifestEntries _suggestedEntries = SuggestedManifestEntries.Empty;
|
||||
private readonly Func<CovenantSetupTool?> _locateCovenantSetupTool;
|
||||
|
||||
public MainViewModel()
|
||||
@@ -131,30 +133,52 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
|
||||
public void ApplyDefaults(bool resetCollections)
|
||||
{
|
||||
if (resetCollections)
|
||||
_suppressPreviewRefresh = true;
|
||||
try
|
||||
{
|
||||
Directories.Clear();
|
||||
Files.Clear();
|
||||
Registry.Clear();
|
||||
Shortcuts.Clear();
|
||||
Scripts.Clear();
|
||||
PurgePaths.Clear();
|
||||
PurgeRegistryBranches.Clear();
|
||||
if (resetCollections)
|
||||
{
|
||||
Directories.Clear();
|
||||
Files.Clear();
|
||||
Registry.Clear();
|
||||
Shortcuts.Clear();
|
||||
Scripts.Clear();
|
||||
PurgePaths.Clear();
|
||||
PurgeRegistryBranches.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveSuggestedEntries(_suggestedEntries);
|
||||
}
|
||||
|
||||
var suggestedEntries = BuildSuggestedEntries();
|
||||
AddSuggestedEntries(suggestedEntries);
|
||||
_suggestedEntries = suggestedEntries;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_suppressPreviewRefresh = false;
|
||||
}
|
||||
|
||||
RefreshPreview();
|
||||
}
|
||||
|
||||
private SuggestedManifestEntries BuildSuggestedEntries()
|
||||
{
|
||||
var folder = string.IsNullOrWhiteSpace(ApplicationFolder)
|
||||
? SanitizeIdentifier(AppName)
|
||||
: SanitizeIdentifier(ApplicationFolder);
|
||||
ApplicationFolder = folder;
|
||||
SetProperty(ref _applicationFolder, folder, nameof(ApplicationFolder), refreshPreview: false);
|
||||
|
||||
var root = InstallRootToken.TrimEnd('\\') + "\\" + folder;
|
||||
AddUnique(Directories, new DirectorySpec(root));
|
||||
AddUnique(Directories, new DirectorySpec(root + @"\bin"));
|
||||
AddUnique(PurgePaths, root);
|
||||
|
||||
var registryBranch = @"HKCU\Software\" + folder;
|
||||
AddUnique(PurgeRegistryBranches, registryBranch);
|
||||
AddUnique(Registry, new RegistrySpec(registryBranch, "InstallRoot", root));
|
||||
var directories = new List<DirectorySpec>
|
||||
{
|
||||
new(root),
|
||||
new(root + @"\bin")
|
||||
};
|
||||
var files = new List<FileSpec>();
|
||||
var shortcuts = new List<ShortcutSpec>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(PrimaryPayload))
|
||||
{
|
||||
@@ -162,8 +186,8 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
if (!string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
var destination = root + @"\bin\" + fileName;
|
||||
AddUnique(Files, new FileSpec(PrimaryPayload.Trim(), destination));
|
||||
AddUnique(Shortcuts, new ShortcutSpec(
|
||||
files.Add(new FileSpec(PrimaryPayload.Trim(), destination));
|
||||
shortcuts.Add(new ShortcutSpec(
|
||||
@"{Desktop}\" + AppName.Trim() + ".lnk",
|
||||
destination,
|
||||
null,
|
||||
@@ -172,7 +196,13 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
RefreshPreview();
|
||||
return new SuggestedManifestEntries(
|
||||
directories,
|
||||
files,
|
||||
[new RegistrySpec(registryBranch, "InstallRoot", root)],
|
||||
shortcuts,
|
||||
[root],
|
||||
[registryBranch]);
|
||||
}
|
||||
|
||||
public void RefreshCovenantSetupTool()
|
||||
@@ -351,7 +381,30 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
|
||||
private void CollectionChanged(object? sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshPreview();
|
||||
if (!_suppressPreviewRefresh)
|
||||
{
|
||||
RefreshPreview();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSuggestedEntries(SuggestedManifestEntries entries)
|
||||
{
|
||||
AddRangeUnique(Directories, entries.Directories);
|
||||
AddRangeUnique(Files, entries.Files);
|
||||
AddRangeUnique(Registry, entries.Registry);
|
||||
AddRangeUnique(Shortcuts, entries.Shortcuts);
|
||||
AddRangeUnique(PurgePaths, entries.PurgePaths);
|
||||
AddRangeUnique(PurgeRegistryBranches, entries.PurgeRegistryBranches);
|
||||
}
|
||||
|
||||
private void RemoveSuggestedEntries(SuggestedManifestEntries entries)
|
||||
{
|
||||
RemoveRange(Directories, entries.Directories);
|
||||
RemoveRange(Files, entries.Files);
|
||||
RemoveRange(Registry, entries.Registry);
|
||||
RemoveRange(Shortcuts, entries.Shortcuts);
|
||||
RemoveRange(PurgePaths, entries.PurgePaths);
|
||||
RemoveRange(PurgeRegistryBranches, entries.PurgeRegistryBranches);
|
||||
}
|
||||
|
||||
private static void AddTrimmed<T>(
|
||||
@@ -373,6 +426,22 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddRangeUnique<T>(ObservableCollection<T> collection, IEnumerable<T> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
AddUnique(collection, item);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveRange<T>(ICollection<T> collection, IEnumerable<T> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
collection.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static string? NullIfWhiteSpace(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
|
||||
@@ -394,4 +463,15 @@ internal sealed partial class MainViewModel : INotifyPropertyChanged
|
||||
|
||||
[GeneratedRegex(@"[^A-Za-z0-9_-]+")]
|
||||
private static partial Regex IdentifierRegex();
|
||||
|
||||
private sealed record SuggestedManifestEntries(
|
||||
IReadOnlyList<DirectorySpec> Directories,
|
||||
IReadOnlyList<FileSpec> Files,
|
||||
IReadOnlyList<RegistrySpec> Registry,
|
||||
IReadOnlyList<ShortcutSpec> Shortcuts,
|
||||
IReadOnlyList<string> PurgePaths,
|
||||
IReadOnlyList<string> PurgeRegistryBranches)
|
||||
{
|
||||
public static SuggestedManifestEntries Empty { get; } = new([], [], [], [], [], []);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user