Skip to content

Commit 503a84e

Browse files
committed
Add new arguments for add command
1 parent 783336d commit 503a84e

File tree

3 files changed

+83
-13
lines changed

3 files changed

+83
-13
lines changed

src/EasySign.CommandLine/BundleWorker.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ protected bool LoadBundle(bool readOnly = true)
6060
/// <param name="statusContext">
6161
/// The status context for interacting with <see cref="AnsiConsole.Status"/>.
6262
/// </param>
63+
/// <param name="files">
64+
/// The files to add to the bundle.
65+
/// </param>
6366
/// <param name="replace">
6467
/// A value indicating whether to replace existing entries.
6568
/// </param>
69+
/// <param name="recursive">
70+
/// A value indicating whether to add files recursively.
71+
/// </param>
6672
/// <param name="continueOnError">
6773
/// A value indicating whether to continue adding files if an error occurs.
6874
/// </param>
69-
protected virtual void RunAdd(StatusContext statusContext, bool replace, bool continueOnError)
75+
protected virtual void RunAdd(StatusContext statusContext, string[] files, bool replace, bool recursive, bool continueOnError)
7076
{
7177
Logger.LogInformation("Running add command");
7278

@@ -85,13 +91,16 @@ protected virtual void RunAdd(StatusContext statusContext, bool replace, bool co
8591

8692
statusContext.Status("[yellow]Adding Files[/]");
8793

88-
Logger.LogDebug("Discovering files in the directory: {RootPath}", Bundle.RootPath);
89-
string[] foundFiles = Utilities.SafeEnumerateFiles(Bundle.RootPath, "*").ToArray();
90-
Logger.LogInformation("Discovered {FileCount} files", foundFiles.Count());
94+
if (files.Length == 0)
95+
{
96+
Logger.LogDebug("Discovering files in the directory: {RootPath}", Bundle.RootPath);
97+
files = Utilities.SafeEnumerateFiles(Bundle.RootPath, "*", recursive).ToArray();
98+
Logger.LogInformation("Discovered {FileCount} files", files.Length);
99+
}
91100

92101
Logger.LogInformation("Starting file adder multi-thread task");
93102
bool errorOccurred = false;
94-
_ = Parallel.ForEach(foundFiles, (file, state) =>
103+
_ = Parallel.ForEach(files, (file, state) =>
95104
{
96105
if (file == Bundle.BundlePath) return;
97106
string entryName = Manifest.GetNormalizedEntryName(Path.GetRelativePath(Bundle.RootPath, file));
@@ -100,12 +109,19 @@ protected virtual void RunAdd(StatusContext statusContext, bool replace, bool co
100109

101110
try
102111
{
112+
if (!Utilities.IsFileWithinRoot(file, Bundle.RootPath))
113+
{
114+
Logger.LogWarning("File {file} is outside the bundle root path", file);
115+
AnsiConsole.MarkupLine($"[{Color.Yellow}]Ignored:[/] File {file} is outside the bundle root path");
116+
return;
117+
}
118+
103119
if (Bundle.Manifest.Entries.ContainsKey(entryName))
104120
{
105121
if (!replace)
106122
{
107123
Logger.LogWarning("Entry already exists: {EntryName}", entryName);
108-
AnsiConsole.MarkupLine($"[{Color.Orange1}]Exists:[/] {entryName}");
124+
AnsiConsole.MarkupLine($"[{Color.Yellow}]Exists:[/] {entryName}");
109125
return;
110126
}
111127

src/EasySign.CommandLine/CommandProvider.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,24 +79,46 @@ public Command Add
7979
{
8080
get
8181
{
82+
Argument<string[]> filesArg = new Argument<string[]>("files", description: "Files to add to the bundle, Must be inside the bundle root path\n" +
83+
"if not specified, all files in the bundle root path will be added", parse: x =>
84+
{
85+
List<string> result = [];
86+
foreach (var file in x.Tokens.Select(t => t.Value))
87+
{
88+
if (string.IsNullOrEmpty(file)) continue;
89+
90+
result.Add(Path.GetFullPath(file));
91+
}
92+
93+
return result.ToArray();
94+
})
95+
{
96+
Arity = ArgumentArity.ZeroOrMore,
97+
};
98+
8299
Option<bool> replaceOpt = new Option<bool>("--replace", "Replace existing entries");
83100
replaceOpt.AddAlias("-r");
84101

102+
Option<bool> recursiveOpt = new Option<bool>("--recursive", "Add all files within the bundle root path recursively");
103+
recursiveOpt.AddAlias("-R");
104+
85105
Option<bool> continueOpt = new Option<bool>("--continue", "Continue adding files if an error occurs");
86106
continueOpt.AddAlias("-c");
87107

88108
Command command = new Command("add", "Create new bundle or update an existing one")
89109
{
90110
BundlePath,
111+
filesArg,
91112
replaceOpt,
113+
recursiveOpt,
92114
continueOpt,
93115
};
94116

95-
command.SetHandler((bundlePath, replace, continueOnError) =>
117+
command.SetHandler((bundlePath, files, replace, recursive, continueOnError) =>
96118
{
97119
InitializeBundle(bundlePath);
98-
Utilities.RunInStatusContext("[yellow]Preparing[/]", ctx => RunAdd(ctx, replace, continueOnError));
99-
}, BundlePath, replaceOpt, continueOpt);
120+
Utilities.RunInStatusContext("[yellow]Preparing[/]", ctx => RunAdd(ctx, files, replace, recursive, continueOnError));
121+
}, BundlePath, filesArg, replaceOpt, recursiveOpt, continueOpt);
100122

101123
return command;
102124
}

src/EasySign.CommandLine/Utilities.cs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,42 @@ public static void RunInStatusContext(string initialStatus, Action<StatusContext
2323
.Start(initialStatus, action);
2424
}
2525

26+
/// <summary>
27+
/// Checks if a file is within a specified root path.
28+
/// </summary>
29+
/// <param name="filePath">
30+
/// The file path to check.
31+
/// </param>
32+
/// <param name="rootPath">
33+
/// The root path to check against.
34+
/// </param>
35+
/// <returns>
36+
/// True if the file is within the root path; otherwise, false.
37+
/// </returns>
38+
public static bool IsFileWithinRoot(string filePath, string rootPath)
39+
{
40+
// Get the full absolute paths
41+
string absoluteFilePath = Path.GetFullPath(filePath);
42+
string absoluteRootPath = Path.GetFullPath(rootPath);
43+
44+
// Ensure the root path ends with a directory separator
45+
if (!absoluteRootPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
46+
{
47+
absoluteRootPath += Path.DirectorySeparatorChar;
48+
}
49+
50+
// Check if the file path starts with the root path (using OrdinalIgnoreCase for case-insensitive comparison on Windows)
51+
return absoluteFilePath.StartsWith(absoluteRootPath, StringComparison.OrdinalIgnoreCase);
52+
}
53+
2654
/// <summary>
2755
/// Safely enumerates files in the specified path that match the search pattern.
2856
/// </summary>
2957
/// <param name="path">The path to search for files.</param>
3058
/// <param name="searchPattern">The search pattern to match files.</param>
59+
/// <param name="recursive">Whether to search recursively in subdirectories.</param>
3160
/// <returns>An enumerable collection of file paths.</returns>
32-
public static IEnumerable<string> SafeEnumerateFiles(string path, string searchPattern)
61+
public static IEnumerable<string> SafeEnumerateFiles(string path, string searchPattern, bool recursive = true)
3362
{
3463
ConcurrentQueue<string> folders = new();
3564
folders.Enqueue(path);
@@ -55,14 +84,17 @@ public static IEnumerable<string> SafeEnumerateFiles(string path, string searchP
5584

5685
try
5786
{
58-
subDirs = Directory.GetDirectories(currentDir);
87+
if (recursive)
88+
{
89+
subDirs = Directory.GetDirectories(currentDir);
90+
}
5991
}
6092
catch (UnauthorizedAccessException) { continue; }
6193
catch (DirectoryNotFoundException) { continue; }
6294

63-
foreach (string str in subDirs)
95+
foreach (string dir in subDirs)
6496
{
65-
folders.Enqueue(str);
97+
folders.Enqueue(dir);
6698
}
6799
}
68100
}

0 commit comments

Comments
 (0)