diff --git a/src/CsProj/FileSystem/DotNetFileSystemProvider.cs b/src/CsProj/FileSystem/DotNetFileSystemProvider.cs index f76e4b3..bc2aeca 100644 --- a/src/CsProj/FileSystem/DotNetFileSystemProvider.cs +++ b/src/CsProj/FileSystem/DotNetFileSystemProvider.cs @@ -43,5 +43,15 @@ public string LoadContent(string filePath) { return File.ReadAllText(filePath); } + + /// + /// Write all text content to the given filepath + /// + /// + /// + public void WriteAllContent(string filePath, string data) + { + File.WriteAllText(filePath, data); + } } } \ No newline at end of file diff --git a/src/CsProj/FileSystem/IFileSystemProvider.cs b/src/CsProj/FileSystem/IFileSystemProvider.cs index 4ce9f7b..4a34d45 100644 --- a/src/CsProj/FileSystem/IFileSystemProvider.cs +++ b/src/CsProj/FileSystem/IFileSystemProvider.cs @@ -29,5 +29,13 @@ public interface IFileSystemProvider /// /// string LoadContent(string filePath); + + /// + /// Writes all the content to the given file as a strings + /// + /// + /// + /// + void WriteAllContent(string filePath, string data); } } \ No newline at end of file diff --git a/src/CsProj/ProjectFileVersionPatcher.cs b/src/CsProj/ProjectFileVersionPatcher.cs index 54d7986..e5446bb 100644 --- a/src/CsProj/ProjectFileVersionPatcher.cs +++ b/src/CsProj/ProjectFileVersionPatcher.cs @@ -1,14 +1,20 @@ using System; -using System.IO; using System.Linq; using System.Xml.Linq; +using Skarp.Version.Cli.CsProj.FileSystem; namespace Skarp.Version.Cli.CsProj { public class ProjectFileVersionPatcher { + private readonly IFileSystemProvider _fileSystem; private XDocument _doc; + public ProjectFileVersionPatcher(IFileSystemProvider fileSystem) + { + _fileSystem = fileSystem; + } + public virtual void Load(string xmlDocument) { _doc = XDocument.Parse(xmlDocument, LoadOptions.PreserveWhitespace); @@ -67,7 +73,7 @@ private void AddMissingElementToCsProj(string elementName, string value) if (node == null) { throw new ArgumentException( - "Given XML does not contain PackageVersion and cannot locate PropertyGroup to add it to - is this a valid csproj?"); + $"Given XML does not contain {elementName} and cannot locate existing PropertyGroup to add it to - is this a valid csproj file?"); } } @@ -82,7 +88,7 @@ private void AddMissingElementToCsProj(string elementName, string value) /// The path of the csproj to write to public virtual void Flush(string filePath) { - File.WriteAllText(filePath, _doc.ToString()); + _fileSystem.WriteAllContent(filePath, ToXmlString()); } /// diff --git a/src/Program.cs b/src/Program.cs index 01d9114..8866fdb 100755 --- a/src/Program.cs +++ b/src/Program.cs @@ -166,13 +166,14 @@ string preReleasePrefix private static void SetUpDependencies() { + var dotNetFileSystemProvider = new DotNetFileSystemProvider(); _cli = new VersionCli( new GitVcs(), new ProjectFileDetector( - new DotNetFileSystemProvider() + dotNetFileSystemProvider ), new ProjectFileParser(), - new ProjectFileVersionPatcher(), + new ProjectFileVersionPatcher(dotNetFileSystemProvider), new SemVerBumper() ); } diff --git a/src/VersionBump.cs b/src/VersionBump.cs index 6e0b5f1..8b5321b 100644 --- a/src/VersionBump.cs +++ b/src/VersionBump.cs @@ -5,6 +5,9 @@ namespace Skarp.Version.Cli /// public enum VersionBump { + // Not supplied or parsing error or something - we can't bump `unknown` + Unknown, + Major, Minor, diff --git a/src/Versioning/SemVer.cs b/src/Versioning/SemVer.cs index ce02103..be47316 100644 --- a/src/Versioning/SemVer.cs +++ b/src/Versioning/SemVer.cs @@ -36,16 +36,7 @@ public string ToSemVerVersionString() return sb.ToString(); } - - /// - /// Returns a simple version string including only major.minor.patch - /// - /// - public string ToSimpleVersionString() - { - return $"{Major}.{Minor}.{Patch}"; - } - + /// /// Create a new instance of a SemVer based off the version string /// diff --git a/src/Versioning/SemVerBumper.cs b/src/Versioning/SemVerBumper.cs index e52039a..690e105 100644 --- a/src/Versioning/SemVerBumper.cs +++ b/src/Versioning/SemVerBumper.cs @@ -67,7 +67,7 @@ public SemVer Bump( } default: { - throw new ArgumentOutOfRangeException($"VersionBump : {bump} not supported"); + throw new ArgumentOutOfRangeException(nameof(bump), $"VersionBump : {bump} not supported"); } } @@ -160,15 +160,15 @@ private void HandlePreMinorBump(SemVer newVersion, string preReleasePrefix) private void HandleMinorBump(SemVer newVersion) { - if (!newVersion.IsPreRelease) + if (newVersion.IsPreRelease) { - newVersion.Minor += 1; - newVersion.Patch = 0; + newVersion.PreRelease = string.Empty; + newVersion.BuildMeta = string.Empty; } else { - newVersion.PreRelease = string.Empty; - newVersion.BuildMeta = string.Empty; + newVersion.Minor += 1; + newVersion.Patch = 0; } } @@ -187,16 +187,16 @@ private void HandlePreMajorBump(SemVer newVersion, string preReleasePrefix) private void HandleMajorBump(SemVer newVersion) { - if (!newVersion.IsPreRelease) + if (newVersion.IsPreRelease) { - newVersion.Major += 1; - newVersion.Minor = 0; - newVersion.Patch = 0; + newVersion.PreRelease = string.Empty; + newVersion.BuildMeta = string.Empty; } else { - newVersion.PreRelease = string.Empty; - newVersion.BuildMeta = string.Empty; + newVersion.Major += 1; + newVersion.Minor = 0; + newVersion.Patch = 0; } } } diff --git a/test/CsProj/FileSystem/DotNetFileSystemProviderTests.cs b/test/CsProj/FileSystem/DotNetFileSystemProviderTests.cs new file mode 100644 index 0000000..a831a3d --- /dev/null +++ b/test/CsProj/FileSystem/DotNetFileSystemProviderTests.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; +using System.Linq; +using Skarp.Version.Cli.CsProj.FileSystem; +using Xunit; + +namespace Skarp.Version.Cli.Test.CsProj.FileSystem +{ + public class DotNetFileSystemProviderTests + { + private readonly DotNetFileSystemProvider _provider; + + public DotNetFileSystemProviderTests() + { + _provider = new DotNetFileSystemProvider(); + } + + [Fact] + public void List_works() + { + // List files in the current directory running from (the build output folder) + var files = _provider.List("./").ToList(); + + Assert.NotEmpty(files); + Assert.Contains("./dotnet-version.dll", files); + } + + [Theory] + [InlineData("./dotnet-version.dll", false)] + [InlineData("../../../dotnet-version-test.csproj", true)] + public void IsCsProjectFile_works(string path, bool isCsProj) + { + Assert.Equal(_provider.IsCsProjectFile(path), isCsProj); + } + + [Fact] + public void Cwd_works() + { + var cwd = _provider.Cwd(); + Assert.Contains($"netcoreapp", cwd); + } + + [Fact] + public void LoadAllContent_works() + { + var content = _provider.LoadContent("../../../dotnet-version-test.csproj"); + Assert.Contains("fb420acf-9e12-42b6-b724-1eee9cbf251e", content); + } + + [Fact] + public void WriteAllContent_works() + { + var path = "./test-file.txt"; + var content = "this is content"; + _provider.WriteAllContent(path, content); + + var loadedContent = File.ReadAllText(path); + + Assert.Equal(content, loadedContent); + } + } +} \ No newline at end of file diff --git a/test/CsProj/ProjectFileVersionPatcherTest.cs b/test/CsProj/ProjectFileVersionPatcherTest.cs index c4b55a6..3ddfa51 100644 --- a/test/CsProj/ProjectFileVersionPatcherTest.cs +++ b/test/CsProj/ProjectFileVersionPatcherTest.cs @@ -1,5 +1,7 @@ using System; +using FakeItEasy; using Skarp.Version.Cli.CsProj; +using Skarp.Version.Cli.CsProj.FileSystem; using Xunit; namespace Skarp.Version.Cli.Test.CsProj @@ -7,21 +9,23 @@ namespace Skarp.Version.Cli.Test.CsProj public class ProjectFileVersionPatcherTest { private static string _projectXml = - "" + - "" + - "netstandard1.6" + - "Unit.For.The.Win" + - "Unit.Testing.Library" + - "1.0.0" + - "1.0.0" + - "" + - ""; + "" + + "" + + "netstandard1.6" + + "Unit.For.The.Win" + + "Unit.Testing.Library" + + "1.0.0" + + "1.0.0" + + "" + + ""; private readonly ProjectFileVersionPatcher _patcher; + private readonly IFileSystemProvider _fileSystem; public ProjectFileVersionPatcherTest() { - _patcher = new ProjectFileVersionPatcher(); + _fileSystem = A.Fake(); + _patcher = new ProjectFileVersionPatcher(_fileSystem); } [Fact] @@ -31,6 +35,7 @@ public void Throws_when_load_not_called() Assert.IsAssignableFrom(ex); } + [Fact] public void CanPatchVersionOnWellFormedXml() { @@ -41,40 +46,86 @@ public void CanPatchVersionOnWellFormedXml() Assert.NotEqual(_projectXml, newXml); Assert.Contains("1.1.0-0", newXml); } - + [Fact] public void CanPatchWhenVersionIsMissing() { - var xml = - "" + - "" + - "netstandard1.6" + - "Unit.For.The.Win" + - "Unit.Testing.Library" + - "" + - ""; + var xml = + "" + + "" + + "netstandard1.6" + + "Unit.For.The.Win" + + "Unit.Testing.Library" + + "" + + ""; _patcher.Load(xml); _patcher.PatchVersionField("1.0.0", "2.0.0"); var newXml = _patcher.ToXmlString(); Assert.Contains("2.0.0", newXml); - } - + } + [Fact] public void PreservesWhiteSpaceWhilePatching() { - var xml = - "" + - "" + - "1.0.0" + - "" + - $"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}" + - ""; + var xml = + "" + + "" + + "1.0.0" + + "" + + $"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}" + + ""; _patcher.Load(xml); _patcher.PatchVersionField("1.0.0", "2.0.0"); var newXml = _patcher.ToXmlString(); - Assert.Contains($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}", newXml); + Assert.Contains($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}", + newXml); + } + + [Fact] + public void HandlesMissingVersionWhenTargetFrameworksField() + { + var xml = + "" + + "" + + "netstandard1.6;dotnet462" + + "" + + ""; + + _patcher.Load(xml); + _patcher.PatchVersionField("1.0.0", "2.0.0"); + var newXml = _patcher.ToXmlString(); + Assert.Contains("2.0.0", newXml); + } + + [Fact] + public void BailsWhenUnableToLocatePropertyGroup() + { + var xml = + "" + + ""; + + _patcher.Load(xml); + var ex = Record.Exception(() => _patcher.PatchVersionField("1.0.0", "2.0.0")); + + var aex = Assert.IsAssignableFrom(ex); + + Assert.Equal( + "Given XML does not contain Version and cannot locate existing PropertyGroup to add it to - is this a valid csproj file?", + aex.Message + ); + } + + [Fact] + public void Flush_calls_filesystem() + { + _patcher.Load(_projectXml); + + var thePath = "/some/path.txt"; + _patcher.Flush(thePath); + + A.CallTo(() => _fileSystem.WriteAllContent(thePath, A._)).MustHaveHappenedOnceExactly(); } } } \ No newline at end of file diff --git a/test/Versioning/SemVerBumperTests.cs b/test/Versioning/SemVerBumperTests.cs index 5da0def..f9e4684 100644 --- a/test/Versioning/SemVerBumperTests.cs +++ b/test/Versioning/SemVerBumperTests.cs @@ -1,3 +1,4 @@ +using System; using Skarp.Version.Cli.Versioning; using Xunit; @@ -51,10 +52,15 @@ string expectedBuildMeta [InlineData("4.1.3", VersionBump.PreMinor, "4.2.0-next.0")] [InlineData("2.1.0", VersionBump.Patch, "2.1.1")] [InlineData("2.1.0", VersionBump.PrePatch, "2.1.1-next.0")] - [InlineData("1.1.1-42", VersionBump.Patch, "1.1.1")] // snap out of pre-release mode - [InlineData("1.1.1-42+master", VersionBump.Patch, "1.1.1")] // snap out of pre-release mode - [InlineData("1.1.1-42", VersionBump.PreRelease, "1.1.1-next.43")] // increment prerelease number - [InlineData("1.1.1-next.42", VersionBump.PreRelease, "1.1.1-next.43")] // increment prerelease number + // snap out of pre-release mode + [InlineData("2.0.0-next.2", VersionBump.Major, "2.0.0")] + [InlineData("1.1.1-42", VersionBump.Patch, "1.1.1")] + [InlineData("1.1.1-42+master", VersionBump.Patch, "1.1.1")] + [InlineData("4.1.3-next.1", VersionBump.Minor, "4.1.3")] + + // increment prerelease number + [InlineData("1.1.1-42", VersionBump.PreRelease, "1.1.1-next.43")] + [InlineData("1.1.1-next.42", VersionBump.PreRelease, "1.1.1-next.43")] public void CanBumpAndSerializeStringVersion(string version, VersionBump bump, string expectedVersion) { var semver = _bumper.Bump(SemVer.FromString(version), bump); @@ -75,5 +81,46 @@ string prefix var semver = _bumper.Bump(SemVer.FromString(version), bump, preReleasePrefix: prefix); Assert.Equal(expectedVersion, semver.ToSemVerVersionString()); } + + [Fact] + public void Bails_when_bump_is_not_supported() + { + var ex = Record.Exception(() => _bumper.Bump(SemVer.FromString("1.0.0"), VersionBump.Unknown)); + var aex = Assert.IsAssignableFrom(ex); + Assert.Contains( + "VersionBump : Unknown not supported", + aex.Message + ); + } + + [Fact] + public void Bails_when_specific_version_empty() + { + var ex = Record.Exception(() => _bumper.Bump(SemVer.FromString("1.0.0"), VersionBump.Specific, "")); + Assert.IsAssignableFrom(ex); + } + + [Fact] + public void Complains_about_prerelease_bump_if_not_already_pre() + { + var semver = SemVer.FromString("2.0.0"); + var ex = Record.Exception((() => _bumper.Bump(semver, VersionBump.PreRelease))); + + var iex = Assert.IsAssignableFrom(ex); + Assert.Contains("Cannot Prerelease bump when not", iex.Message); + } + + [Theory] + [InlineData("1.0.0-alpha-1")] + [InlineData("1.0.0-alpha-notANumber")] + [InlineData("1.0.0-alpha.notANumber")] + public void Bails_when_prerelease_label_is_messy(string version) + { + var semver = SemVer.FromString(version); + + var ex = Record.Exception((() => _bumper.Bump(semver, VersionBump.PreRelease))); + var aex = Assert.IsAssignableFrom(ex); + Assert.Contains("`label.number`", aex.Message); + } } } \ No newline at end of file