diff --git a/ModernRonin.ProjectRenamer.Tests/CommonExtensionsTests.cs b/ModernRonin.ProjectRenamer.Tests/CommonExtensionsTests.cs index e7b1ef2..faaf63e 100644 --- a/ModernRonin.ProjectRenamer.Tests/CommonExtensionsTests.cs +++ b/ModernRonin.ProjectRenamer.Tests/CommonExtensionsTests.cs @@ -40,6 +40,15 @@ public void IsDirectorySeparator_returns_true_for_linux_separator() => public void IsDirectorySeparator_returns_true_for_windows_separator() => '\\'.IsDirectorySeparator().Should().BeTrue(); + [Test] + public void + On_Windows_EnsurePlatformDirectorySeparators_replaces_forward_slashes_with_backward_slashes() + { + @"alpha/bravo\charlie/delta".EnsurePlatformDirectorySeparators() + .Should() + .Be(@"alpha\bravo\charlie\delta"); + } + [Test] public void Repeat_returns_the_string_repeated_the_passed_number_of_times() => "alpha".Repeat(3).Should().Be("alphaalphaalpha"); diff --git a/ModernRonin.ProjectRenamer.Tests/DotnetTests.cs b/ModernRonin.ProjectRenamer.Tests/DotnetTests.cs new file mode 100644 index 0000000..2c2abf9 --- /dev/null +++ b/ModernRonin.ProjectRenamer.Tests/DotnetTests.cs @@ -0,0 +1,31 @@ +using AutofacContrib.NSubstitute; +using NSubstitute; +using NUnit.Framework; + +namespace ModernRonin.ProjectRenamer.Tests +{ + [TestFixture] + public class DotnetTests + { + [SetUp] + public void Setup() + { + _dependencies = new AutoSubstitute(); + _underTest = _dependencies.Resolve(); + } + + AutoSubstitute _dependencies; + Dotnet _underTest; + + IExecutor Executor => _dependencies.Resolve(); + + [Test(Description = "fix for https://github.com/ModernRonin/ProjectRenamer/issues/24")] + public void AddToSolution_replaces_forward_slashes_with_backward_slashes_in_solutionFolder() + { + _underTest.AddToSolution("c:/myproject/myproject.csproj", "Features/.shared"); + + Executor.Received() + .Tool("dotnet", @"sln add -s ""Features\.shared"" ""c:/myproject/myproject.csproj"""); + } + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer.Tests/RenamerModuleTests.cs b/ModernRonin.ProjectRenamer.Tests/RenamerModuleTests.cs new file mode 100644 index 0000000..a08b330 --- /dev/null +++ b/ModernRonin.ProjectRenamer.Tests/RenamerModuleTests.cs @@ -0,0 +1,35 @@ +using System; +using Autofac; +using FluentAssertions; +using NUnit.Framework; + +namespace ModernRonin.ProjectRenamer.Tests +{ + [TestFixture] + public class RenamerModuleTests + { + [SetUp] + public void Setup() + { + var builder = new ContainerBuilder(); + builder.RegisterModule(); + _container = builder.Build(); + } + + IContainer _container; + + [Test] + public void Application_factory_can_be_resolved() + { + var factory = _container.Resolve>(); + factory.Should().NotBeNull(); + factory(new Configuration(), string.Empty).Should().NotBeNull(); + } + + [Test] + public void IConfigurationSetup_can_be_resolved() + { + _container.Resolve().Should().NotBeNull(); + } + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/Application.cs b/ModernRonin.ProjectRenamer/Application.cs index c4262e6..9afdf9f 100644 --- a/ModernRonin.ProjectRenamer/Application.cs +++ b/ModernRonin.ProjectRenamer/Application.cs @@ -10,7 +10,10 @@ namespace ModernRonin.ProjectRenamer public class Application { readonly Configuration _configuration; - readonly IExecutor _executor; + readonly IDotnet _dotnet; + readonly IErrorHandler _errors; + readonly IFilesystem _filesystem; + readonly IGit _git; readonly IInput _input; readonly ILogger _logger; readonly IRuntime _runtime; @@ -18,26 +21,31 @@ public class Application public Application(Configuration configuration, string solutionPath, - IExecutor executor, IRuntime runtime, ILogger logger, - IInput input) + IInput input, + IGit git, + IErrorHandler errors, + IDotnet dotnet, + IFilesystem filesystem) { _configuration = configuration; _solutionPath = solutionPath; - _executor = executor; _runtime = runtime; _logger = logger; _input = input; + _git = git; + _errors = errors; + _dotnet = dotnet; + _filesystem = filesystem; } public void Run() { - EnsureGitIsClean(); + _git.EnsureIsClean(); var (wasFound, oldProjectPath, solutionFolderPath) = findProject(); - if (!wasFound) - _executor.Error($"{_configuration.OldProjectName} cannot be found in the solution"); + if (!wasFound) _errors.Handle($"{_configuration.OldProjectName} cannot be found in the solution"); var oldDir = Path.GetDirectoryName(oldProjectPath); var newBase = _configuration.NewProjectName.Any(CommonExtensions.IsDirectorySeparator) @@ -46,8 +54,8 @@ public void Run() var newDir = _configuration.NewProjectName.ToAbsolutePath(newBase); var newFileName = Path.GetFileName(_configuration.NewProjectName); var newProjectPath = Path.Combine(newDir, $"{newFileName}{Constants.ProjectFileExtension}"); - var isPaketUsed = Directory.Exists(".paket"); - var gitVersion = _executor.GitRead("--version"); + var isPaketUsed = _filesystem.DoesDirectoryExist(".paket"); + var gitVersion = _git.GetVersion(); if (!_configuration.DontReviewSettings) { var lines = new[] @@ -78,32 +86,22 @@ public void Run() addNewReferences(); addToSolution(); updatePaket(); - stageAllChanges(); + _git.StageAllChanges(); build(); commit(); void addNewReferences() { - dependents.ForEach(p => addReference(p, newProjectPath)); - dependencies.ForEach(d => addReference(newProjectPath, d)); - - void addReference(string project, string reference) => - projectReferenceCommand("add", project, reference); + dependents.ForEach(p => _dotnet.AddReference(p, newProjectPath)); + dependencies.ForEach(d => _dotnet.AddReference(newProjectPath, d)); } void removeOldReferences() { - dependents.ForEach(p => removeReference(p, oldProjectPath)); - dependencies.ForEach(d => removeReference(oldProjectPath, d)); - - void removeReference(string project, string reference) => - projectReferenceCommand("remove", project, reference); + dependents.ForEach(p => _dotnet.RemoveReference(p, oldProjectPath)); + dependencies.ForEach(d => _dotnet.RemoveReference(oldProjectPath, d)); } - void projectReferenceCommand(string command, string project, string reference) => - _executor.DotNet( - $"{command} {project.EscapeForShell()} reference {reference.EscapeForShell()}"); - (string[] dependents, string[] dependencies) analyzeReferences() { _logger.Info( @@ -122,10 +120,8 @@ bool hasReferenceToOldProject(string p) => IEnumerable getReferencedProjects(string project) { + var relativeReferences = _dotnet.GetReferencedProjects(project); var baseDirectory = Path.GetFullPath(Path.GetDirectoryName(project)); - var relativeReferences = _executor.DotNetRead($"list {project.EscapeForShell()} reference") - .Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries) - .Skip(2); return relativeReferences.Select(r => r.ToAbsolutePath(baseDirectory)); } @@ -139,9 +135,7 @@ void commit() var msg = wasMove ? $"Moved {oldProjectPath.ToRelativePath(CurrentDirectoryAbsolute)} to {newProjectPath.ToRelativePath(CurrentDirectoryAbsolute)}" : $"Renamed {_configuration.OldProjectName} to {_configuration.NewProjectName}"; - var arguments = $"commit -m \"{msg}\""; - _executor.Git(arguments, - () => { _logger.Error($"'git {arguments}' failed"); }); + _git.Commit(msg); } } @@ -149,24 +143,22 @@ void build() { if (_configuration.DoRunBuild) { - _executor.DotNet("build", () => + _dotnet.BuildSolution(() => { if (_input.AskUser( "dotnet build returned an error or warning - do you want to rollback all changes?") ) { - _executor.RollbackGit(); + _git.RollbackAllChanges(); _runtime.Abort(); } }); } } - void stageAllChanges() => _executor.Git("add ."); - void updatePaket() { - if (isPaketUsed && !_configuration.DontRunPaketInstall) _executor.DotNet("paket install"); + if (isPaketUsed && !_configuration.DontRunPaketInstall) _dotnet.PaketInstall(); } void updatePaketReference() @@ -193,24 +185,19 @@ bool isPaketReference(string line) void gitMove() { - Directory.CreateDirectory(Path.GetDirectoryName(newDir)); - _executor.Git($"mv {oldDir} {newDir}"); + _filesystem.EnsureDirectoryExists(Path.GetDirectoryName(newDir)); + _git.Move(oldDir, newDir); var oldPath = Path.GetFileName(oldProjectPath).ToAbsolutePath(newDir); - if (oldPath != newProjectPath) _executor.Git($"mv {oldPath} {newProjectPath}"); + if (oldPath != newProjectPath) _git.Move(oldPath, newProjectPath); } void addToSolution() { - var solutionFolderArgument = string.IsNullOrWhiteSpace(solutionFolderPath) - ? string.Empty - : $"-s \"{solutionFolderPath}\""; - solutionCommand($"add {solutionFolderArgument}", newProjectPath); + if (string.IsNullOrWhiteSpace(solutionFolderPath)) _dotnet.AddToSolution(newProjectPath); + else _dotnet.AddToSolution(newProjectPath, solutionFolderPath); } - void removeFromSolution() => solutionCommand("remove", oldProjectPath); - - void solutionCommand(string command, string projectPath) => - _executor.DotNet($"sln {command} {projectPath.EscapeForShell()}"); + void removeFromSolution() => _dotnet.RemoveFromSolution(oldProjectPath); (bool wasFound, string projectPath, string solutionFolder) findProject() { @@ -244,26 +231,10 @@ string[] allProjects() return all.Except(excluded).ToArray(); - string[] filesIn(string directory) => - Directory - .EnumerateFiles(directory, $"*{Constants.ProjectFileExtension}", - SearchOption.AllDirectories) - .ToArray(); + string[] filesIn(string directory) => _filesystem.FindProjectFiles(directory, true); } } - void EnsureGitIsClean() - { - run("update-index -q --refresh"); - run("diff-index --quiet --cached HEAD --"); - run("diff-files --quiet"); - run("ls-files --exclude-standard --others"); - - void run(string arguments) => - _executor.Git(arguments, - () => _executor.Error("git does not seem to be clean, check git status")); - } - - static string CurrentDirectoryAbsolute => Path.GetFullPath(Directory.GetCurrentDirectory()); + string CurrentDirectoryAbsolute => Path.GetFullPath(_filesystem.CurrentDirectory); } } \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/CommonExtensions.cs b/ModernRonin.ProjectRenamer/CommonExtensions.cs index 24a0ad9..8381007 100644 --- a/ModernRonin.ProjectRenamer/CommonExtensions.cs +++ b/ModernRonin.ProjectRenamer/CommonExtensions.cs @@ -8,6 +8,9 @@ public static class CommonExtensions { public static string AsText(this bool self) => self ? "yes" : "no"; + public static string EnsurePlatformDirectorySeparators(this string self) => + self.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + public static string EscapeForShell(this string self) => $"\"{self}\""; public static bool IsDirectorySeparator(this char self) => diff --git a/ModernRonin.ProjectRenamer/ConfigurationSetup.cs b/ModernRonin.ProjectRenamer/ConfigurationSetup.cs index 1fe216a..19d6ed6 100644 --- a/ModernRonin.ProjectRenamer/ConfigurationSetup.cs +++ b/ModernRonin.ProjectRenamer/ConfigurationSetup.cs @@ -10,22 +10,26 @@ namespace ModernRonin.ProjectRenamer public class ConfigurationSetup : IConfigurationSetup { readonly ILogger _console; - readonly IExecutor _executor; + readonly IErrorHandler _errors; + readonly IFilesystem _filesystem; readonly IRuntime _runtime; - public ConfigurationSetup(IExecutor executor, ILogger console, IRuntime runtime) + public ConfigurationSetup(ILogger console, + IRuntime runtime, + IErrorHandler errors, + IFilesystem filesystem) { - _executor = executor; _console = console; _runtime = runtime; + _errors = errors; + _filesystem = filesystem; } public (Configuration configuration, string solutionPath) Get(string[] commandLineArguments) { - var solutionFiles = - Directory.EnumerateFiles(".", "*.sln", SearchOption.TopDirectoryOnly).ToArray(); + var solutionFiles = _filesystem.FindSolutionFiles(".", false); if (1 != solutionFiles.Length) - _executor.Error("Needs to be run from a directory with exactly one *.sln file in it."); + _errors.Handle("Needs to be run from a directory with exactly one *.sln file in it."); var solutionPath = Path.GetFullPath(solutionFiles.First()); switch (ParseCommandLine(commandLineArguments)) { @@ -36,7 +40,7 @@ public ConfigurationSetup(IExecutor executor, ILogger console, IRuntime runtime) case (var helpOverview, Configuration configuration): if (configuration.OldProjectName.Any(CommonExtensions.IsDirectorySeparator)) { - _executor.Error( + _errors.Handle( $"Do not specify paths for input/'old' project names, please.{Environment.NewLine}{Environment.NewLine}{helpOverview}"); } @@ -45,7 +49,7 @@ public ConfigurationSetup(IExecutor executor, ILogger console, IRuntime runtime) return (configuration, solutionPath); default: - _executor.Error( + _errors.Handle( "Something went seriously wrong. Please create an issue at https://github.com/ModernRonin/ProjectRenamer with as much detail as possible."); break; } diff --git a/ModernRonin.ProjectRenamer/Constants.cs b/ModernRonin.ProjectRenamer/Constants.cs index eed3b95..cf546ee 100644 --- a/ModernRonin.ProjectRenamer/Constants.cs +++ b/ModernRonin.ProjectRenamer/Constants.cs @@ -3,5 +3,6 @@ public static class Constants { public const string ProjectFileExtension = ".csproj"; + public const string SolutionFileExtension = ".sln"; } } \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/Dotnet.cs b/ModernRonin.ProjectRenamer/Dotnet.cs new file mode 100644 index 0000000..aa86e35 --- /dev/null +++ b/ModernRonin.ProjectRenamer/Dotnet.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ModernRonin.ProjectRenamer +{ + public class Dotnet : IDotnet + { + const string ToolDotnet = "dotnet"; + readonly IErrorHandler _errors; + readonly IExecutor _executor; + + public Dotnet(IExecutor executor, IErrorHandler errors) + { + _executor = executor; + _errors = errors; + } + + public void AddReference(string project, string reference) => + ProjectReferenceCommand("add", project, reference); + + public void AddToSolution(string pathToProject, string solutionFolder) => + SolutionCommand($"add -s {solutionFolder.EnsurePlatformDirectorySeparators().EscapeForShell()}", + pathToProject); + + public void AddToSolution(string pathToProject) => SolutionCommand("add", pathToProject); + + public void BuildSolution(Action onNonZeroExitCode) => Run("build", onNonZeroExitCode); + + public IEnumerable GetReferencedProjects(string project) => + Read($"list {project.EscapeForShell()} reference") + .Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries) + .Skip(2); + + public void PaketInstall() => Run("paket install"); + public void RemoveFromSolution(string pathToProject) => SolutionCommand("remove", pathToProject); + + public void RemoveReference(string project, string reference) => + ProjectReferenceCommand("remove", project, reference); + + void ProjectReferenceCommand(string command, string project, string reference) => + Run($"{command} {project.EscapeForShell()} reference {reference.EscapeForShell()}"); + + string Read(string arguments) => + _executor.ToolRead(ToolDotnet, arguments, () => _errors.Handle(ToolDotnet, arguments)); + + void Run(string arguments) => _executor.Tool(ToolDotnet, arguments); + + void Run(string arguments, Action onNonZeroExitCode) => + _executor.Tool(ToolDotnet, arguments, onNonZeroExitCode); + + void SolutionCommand(string command, string projectPath) => + Run($"sln {command} {projectPath.EscapeForShell()}"); + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/ErrorHandler.cs b/ModernRonin.ProjectRenamer/ErrorHandler.cs new file mode 100644 index 0000000..cefa6a1 --- /dev/null +++ b/ModernRonin.ProjectRenamer/ErrorHandler.cs @@ -0,0 +1,39 @@ +using System; + +namespace ModernRonin.ProjectRenamer +{ + public class ErrorHandler : IErrorHandler + { + readonly Lazy _git; + readonly ILogger _logger; + readonly IRuntime _runtime; + + public ErrorHandler(ILogger logger, Lazy git, IRuntime runtime) + { + _logger = logger; + _git = git; + _runtime = runtime; + } + + public void Handle(string msg) => Handle(msg, false); + + public void Handle(string tool, string arguments) + { + Handle($"call '{tool} {arguments}' failed - aborting", true); + } + + public void HandleAndReset(string msg) => Handle(msg, true); + + void Handle(string msg, bool doResetGit) + { + _logger.Error(msg); + if (doResetGit) + { + _logger.Error("...running git reset to undo any changes..."); + _git.Value.RollbackAllChanges(); + } + + _runtime.Abort(); + } + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/Executor.cs b/ModernRonin.ProjectRenamer/Executor.cs index eea3589..ac73692 100644 --- a/ModernRonin.ProjectRenamer/Executor.cs +++ b/ModernRonin.ProjectRenamer/Executor.cs @@ -4,62 +4,25 @@ namespace ModernRonin.ProjectRenamer { public class Executor : IExecutor { - const string ToolDotnet = "dotnet"; - const string ToolGit = "git"; - readonly ILogger _logger; + readonly IErrorHandler _errors; readonly IRuntime _runtime; - public Executor(IRuntime runtime, ILogger logger) + public Executor(IRuntime runtime, IErrorHandler errors) { _runtime = runtime; - _logger = logger; + _errors = errors; } - public void DotNet(string arguments) => Tool(ToolDotnet, arguments); - - public void DotNet(string arguments, Action onNonZeroExitCode) => - Tool(ToolDotnet, arguments, onNonZeroExitCode); - - public string DotNetRead(string arguments) => - ToolRead(ToolDotnet, arguments, () => StandardErrorHandler(ToolDotnet, arguments)); - - public void Error(string msg, bool doResetGit = false) - { - _logger.Error(msg); - if (doResetGit) - { - _logger.Error("...running git reset to undo any changes..."); - RollbackGit(); - } - - _runtime.Abort(); - } - - public void Git(string arguments) => Tool(ToolGit, arguments); - - public void Git(string arguments, Action onNonZeroExitCode) => - Tool(ToolGit, arguments, onNonZeroExitCode); - - public string GitRead(string arguments) => - ToolRead(ToolGit, arguments, () => StandardErrorHandler(ToolGit, arguments)); - - public void RollbackGit() => Git("reset --hard HEAD", () => { }); - - void StandardErrorHandler(string tool, string arguments) - { - Error($"call '{tool} {arguments}' failed - aborting", true); - } - - void Tool(string tool, string arguments, Action onNonZeroExitCode) + public void Tool(string tool, string arguments, Action onNonZeroExitCode) { _runtime.DoWithTool(tool, arguments, onNonZeroExitCode, psi => psi.RedirectStandardOutput = false, _ => { }); } - void Tool(string tool, string arguments) => - Tool(tool, arguments, () => StandardErrorHandler(tool, arguments)); + public void Tool(string tool, string arguments) => + Tool(tool, arguments, () => _errors.Handle(tool, arguments)); - string ToolRead(string tool, string arguments, Action onNonZeroExitCode) + public string ToolRead(string tool, string arguments, Action onNonZeroExitCode) { var result = string.Empty; _runtime.DoWithTool(tool, arguments, onNonZeroExitCode, psi => psi.RedirectStandardOutput = true, diff --git a/ModernRonin.ProjectRenamer/Filesystem.cs b/ModernRonin.ProjectRenamer/Filesystem.cs new file mode 100644 index 0000000..c4f1bf8 --- /dev/null +++ b/ModernRonin.ProjectRenamer/Filesystem.cs @@ -0,0 +1,24 @@ +using System.IO; +using System.Linq; + +namespace ModernRonin.ProjectRenamer +{ + public class Filesystem : IFilesystem + { + public string CurrentDirectory => Directory.GetCurrentDirectory(); + public bool DoesDirectoryExist(string directory) => Directory.Exists(directory); + public void EnsureDirectoryExists(string directory) => Directory.CreateDirectory(directory); + + public string[] FindProjectFiles(string directory, bool doRecurse) => + Directory + .EnumerateFiles(directory, $"*{Constants.ProjectFileExtension}", SearchOption(doRecurse)) + .ToArray(); + + public string[] FindSolutionFiles(string directory, bool doRecurse) => + Directory.EnumerateFiles(".", $"*{Constants.SolutionFileExtension}", SearchOption(doRecurse)) + .ToArray(); + + static SearchOption SearchOption(bool doRecurse) => + doRecurse ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly; + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/Git.cs b/ModernRonin.ProjectRenamer/Git.cs new file mode 100644 index 0000000..23c17f4 --- /dev/null +++ b/ModernRonin.ProjectRenamer/Git.cs @@ -0,0 +1,53 @@ +using System; + +namespace ModernRonin.ProjectRenamer +{ + public class Git : IGit + { + const string ToolGit = "git"; + + readonly IErrorHandler _errors; + readonly IExecutor _executor; + readonly ILogger _logger; + + public Git(IExecutor executor, ILogger logger, IErrorHandler errors) + { + _executor = executor; + _logger = logger; + _errors = errors; + } + + public void Commit(string msg) + { + var arguments = $"commit -m \"{msg}\""; + Run(arguments, + () => _logger.Error($"'git {arguments}' failed")); + } + + public void EnsureIsClean() + { + run("update-index -q --refresh"); + run("diff-index --quiet --cached HEAD --"); + run("diff-files --quiet"); + run("ls-files --exclude-standard --others"); + + void run(string arguments) => + Run(arguments, + () => _errors.Handle("git does not seem to be clean, check git status")); + } + + public string GetVersion() => Read("--version"); + + public void Move(string oldPath, string newPath) => Run($"mv {oldPath} {newPath}"); + public void RollbackAllChanges() => Run("reset --hard HEAD", () => { }); + public void StageAllChanges() => Run("add ."); + + string Read(string arguments) => + _executor.ToolRead(ToolGit, arguments, () => _errors.Handle(ToolGit, arguments)); + + void Run(string arguments) => _executor.Tool(ToolGit, arguments); + + void Run(string arguments, Action onNonZeroExitCode) => + _executor.Tool(ToolGit, arguments, onNonZeroExitCode); + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/IDotnet.cs b/ModernRonin.ProjectRenamer/IDotnet.cs new file mode 100644 index 0000000..dc1ece3 --- /dev/null +++ b/ModernRonin.ProjectRenamer/IDotnet.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace ModernRonin.ProjectRenamer +{ + public interface IDotnet + { + void AddReference(string project, string reference); + void AddToSolution(string pathToProject, string solutionFolder); + void AddToSolution(string pathToProject); + void BuildSolution(Action onNonZeroExitCode); + IEnumerable GetReferencedProjects(string project); + void PaketInstall(); + void RemoveFromSolution(string pathToProject); + void RemoveReference(string project, string reference); + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/IErrorHandler.cs b/ModernRonin.ProjectRenamer/IErrorHandler.cs new file mode 100644 index 0000000..d0589c6 --- /dev/null +++ b/ModernRonin.ProjectRenamer/IErrorHandler.cs @@ -0,0 +1,9 @@ +namespace ModernRonin.ProjectRenamer +{ + public interface IErrorHandler + { + void Handle(string msg); + void Handle(string tool, string arguments); + void HandleAndReset(string msg); + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/IExecutor.cs b/ModernRonin.ProjectRenamer/IExecutor.cs index d5db880..51f056e 100644 --- a/ModernRonin.ProjectRenamer/IExecutor.cs +++ b/ModernRonin.ProjectRenamer/IExecutor.cs @@ -4,13 +4,8 @@ namespace ModernRonin.ProjectRenamer { public interface IExecutor { - void DotNet(string arguments); - void DotNet(string arguments, Action onNonZeroExitCode); - string DotNetRead(string arguments); - void Error(string msg, bool doResetGit = false); - void Git(string arguments); - void Git(string arguments, Action onNonZeroExitCode); - string GitRead(string arguments); - void RollbackGit(); + void Tool(string tool, string arguments, Action onNonZeroExitCode); + void Tool(string tool, string arguments); + string ToolRead(string tool, string arguments, Action onNonZeroExitCode); } } \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/IFilesystem.cs b/ModernRonin.ProjectRenamer/IFilesystem.cs new file mode 100644 index 0000000..f1d9445 --- /dev/null +++ b/ModernRonin.ProjectRenamer/IFilesystem.cs @@ -0,0 +1,11 @@ +namespace ModernRonin.ProjectRenamer +{ + public interface IFilesystem + { + string CurrentDirectory { get; } + bool DoesDirectoryExist(string directory); + void EnsureDirectoryExists(string directory); + string[] FindProjectFiles(string directory, bool doRecurse); + string[] FindSolutionFiles(string directory, bool doRecurse); + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/IGit.cs b/ModernRonin.ProjectRenamer/IGit.cs new file mode 100644 index 0000000..58d2f0c --- /dev/null +++ b/ModernRonin.ProjectRenamer/IGit.cs @@ -0,0 +1,12 @@ +namespace ModernRonin.ProjectRenamer +{ + public interface IGit + { + void Commit(string msg); + void EnsureIsClean(); + string GetVersion(); + void Move(string oldPath, string newPath); + void RollbackAllChanges(); + void StageAllChanges(); + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/Program.cs b/ModernRonin.ProjectRenamer/Program.cs index 717c243..05990f1 100644 --- a/ModernRonin.ProjectRenamer/Program.cs +++ b/ModernRonin.ProjectRenamer/Program.cs @@ -19,13 +19,7 @@ static void Main(string[] args) static IContainer WireUp() { var builder = new ContainerBuilder(); - - builder.RegisterType().AsImplementedInterfaces(); - builder.RegisterType().AsImplementedInterfaces(); - builder.RegisterType().AsImplementedInterfaces(); - builder.RegisterType().AsImplementedInterfaces(); - builder.RegisterType().AsSelf(); - + builder.RegisterModule(); return builder.Build(); } } diff --git a/ModernRonin.ProjectRenamer/Properties/launchSettings.json b/ModernRonin.ProjectRenamer/Properties/launchSettings.json index 7b78760..f28315b 100644 --- a/ModernRonin.ProjectRenamer/Properties/launchSettings.json +++ b/ModernRonin.ProjectRenamer/Properties/launchSettings.json @@ -20,6 +20,11 @@ "commandLineArgs": "LibraryInSubFolder ProjectInSubFolder --no-commit --no-paket", "workingDirectory": "C:\\Projects\\Github\\ProjectRenamerTestBed" }, + "rename library, in nested solution folder starting with ., no commit": { + "commandName": "Project", + "commandLineArgs": "LibraryInNestedSolutionFolderWithLeadingPeriod Changed --no-commit --no-paket", + "workingDirectory": "C:\\Projects\\Github\\ProjectRenamerTestBed" + }, "move root library to subfolder, no paket": { "commandName": "Project", "commandLineArgs": "LibraryInRoot subfolder/LibraryInRoot --no-paket", diff --git a/ModernRonin.ProjectRenamer/RenamerModule.cs b/ModernRonin.ProjectRenamer/RenamerModule.cs new file mode 100644 index 0000000..c60e9fc --- /dev/null +++ b/ModernRonin.ProjectRenamer/RenamerModule.cs @@ -0,0 +1,20 @@ +using Autofac; + +namespace ModernRonin.ProjectRenamer +{ + public class RenamerModule : Module + { + protected override void Load(ContainerBuilder builder) + { + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsImplementedInterfaces(); + builder.RegisterType().AsSelf(); + } + } +} \ No newline at end of file diff --git a/ModernRonin.ProjectRenamer/release.history b/ModernRonin.ProjectRenamer/release.history index 260ff1d..96b3e1f 100644 --- a/ModernRonin.ProjectRenamer/release.history +++ b/ModernRonin.ProjectRenamer/release.history @@ -1,7 +1,9 @@  - 2.1.2 + 2.1.3 +2.1.3: +* bugfix: fixed a bug concerning nested solution folders; thanks to @Mike-E-angelo for reporting the bug 2.1.2: * bugfix: fixed another whitespace related scenario; thanks to @sejohnson-at-griffis for reporting the bug 2.1.1: diff --git a/README.md b/README.md index 4ab58bb..2da036f 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,9 @@ dotnet tool update --global ModernRonin.ProjectRenamer When I publish a new version, I always post at [my blog](https://modernronin.github.io/) under the [renameproject tag](https://modernronin.github.io/tags/renameproject/), aside from updating this readme here. ### Release History +2.1.3: +* bugfix: fixed a bug concerning nested solution folders; thanks to @Mike-E-angelo for reporting the bug + 2.1.2: * bugfix: fixed another whitespace related scenario; thanks to [@sejohnson-at-griffis](https://github.com/sejohnson-at-griffis) for reporting the bug