diff --git a/src/CLI.cs b/src/CLI.cs index a9c935c..0cb9e4b 100644 --- a/src/CLI.cs +++ b/src/CLI.cs @@ -30,19 +30,42 @@ private class Options public int Run(string[] args) { - Console.Out.WriteLine("https://github.com/timabell/sln-items-sync"); - Console.Out.WriteLine("https://www.nuget.org/packages/sln-items-sync"); - Console.Out.WriteLine("A-GPL v3 Licensed"); + Console.Error.WriteLine("https://github.com/timabell/sln-items-sync"); + Console.Error.WriteLine("https://www.nuget.org/packages/sln-items-sync"); + Console.Error.WriteLine("A-GPL v3 Licensed"); + Console.Error.WriteLine(); var parserResult = Parser.Default.ParseArguments(args); if (parserResult.Errors.Any()) { + WriteUsage(); return 1; } - parserResult - .WithParsed(opts => - _slnSync.SyncSlnFile(slnPath: opts.SlnPath, slnFolder: opts.SlnFolder, opts.Paths)); + try + { + parserResult + .WithParsed(opts => + _slnSync.SyncSlnFile(slnPath: opts.SlnPath, slnFolder: opts.SlnFolder, opts.Paths)); + } catch(InvalidSlnPathException ex) { + Console.Error.WriteLine(ex.Message); + return 2; + } catch(PathNotFoundException ex) { + Console.Error.WriteLine(ex.Message); + return 3; + } catch(EmptyPathListException) { + Console.Error.WriteLine("No paths supplied to sync with."); + Console.Error.WriteLine("Supply a list of folder/file arguments that you want to be sync'd into the target solution folder."); + Console.Error.WriteLine(); + WriteUsage(); + return 4; + } + Console.Out.WriteLine("Sync completed."); return 0; } + + private static void WriteUsage() + { + Console.Error.WriteLine("Usage: sln-items-sync --solution paths-to-sync ..."); + } } diff --git a/src/SlnSync.cs b/src/SlnSync.cs index de10b7d..dfba54f 100644 --- a/src/SlnSync.cs +++ b/src/SlnSync.cs @@ -1,3 +1,4 @@ +using System.Runtime.Serialization; using System.Text; using SlnEditor.Models; @@ -19,6 +20,14 @@ public SlnSync() : this(new DefaultGuidGenerator()) /// list of paths to recursively add/update SolutionItems virtual folders with public void SyncSlnFile(string slnPath, string slnFolder, IEnumerable paths) { + if (!File.Exists(slnPath) || !slnPath.EndsWith(".sln")) + { + throw new InvalidSlnPathException($"'{slnPath}' is not a sln file"); + } + if (!paths.Any()) + { + throw new EmptyPathListException(); + } var contents = File.ReadAllText(slnPath); var updatedSln = SyncSlnText(contents, slnFolder, paths); File.WriteAllText(slnPath, updatedSln, Encoding.UTF8); // explicit UTF-8 to get byte-order marker (which sln files seem to have) @@ -42,7 +51,7 @@ public string SyncSlnText(string contents, string slnFolder, IEnumerable } else { - throw new Exception($"path not found: '{path}'"); + throw new PathNotFoundException(path); } } @@ -111,3 +120,7 @@ private SolutionFolder FindOrCreateSolutionFolder(ICollection solution private static SolutionFolder? FindSolutionFolder(IEnumerable solutionProjects, string folderName) => solutionProjects.OfType().FirstOrDefault(project => project.Name == folderName); } + +public class PathNotFoundException(string path) : Exception($"Path '{path}' not found"); +public class InvalidSlnPathException(string s) : Exception(s); +public class EmptyPathListException() : Exception(); diff --git a/tests/IntegrationTests.cs b/tests/IntegrationTests.cs index e12f439..f9ccbf4 100644 --- a/tests/IntegrationTests.cs +++ b/tests/IntegrationTests.cs @@ -425,8 +425,13 @@ public void AddsBOM() EndGlobal "); + SetupFilesystem(new[] + { + "some-file.txt", + }); + // Act - _cli.Run(["-s", TargetSlnFile]); + _cli.Run(["-s", TargetSlnFile, "some-file.txt"]); File.ReadAllText(Path.Combine(_testFolder, TargetSlnFile));