Skip to content

Commit f4d8360

Browse files
authoredDec 2, 2020
Feature/create cli (#3)
* Add list command * #1 : Add list command * #1 : Add project reader * #2 : Add version update commands * #2 : Add version tests * #2 : Add set command * #2 : Add set tests * Update and rename dotnet-core.yml to build.yml * Update build.yml
1 parent dfcaf6e commit f4d8360

29 files changed

+1252
-9
lines changed
 

‎.github/workflows/dotnet-core.yml ‎.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: .NET Core
1+
name: Build
22

33
on:
44
push:
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup .NET Core
1717
uses: actions/setup-dotnet@v1
1818
with:
19-
dotnet-version: 3.1.301
19+
dotnet-version: 5.0.x
2020
- name: Install dependencies
2121
run: dotnet restore
2222
- name: Build

‎README.md

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,40 @@
11
# UpdateVersion
2-
Update-Version is a developper tool to update the Visual Studio project versions.
2+
3+
Update-Version is a developper tool to update the .Net project versions.
4+
5+
## Installing UpdateVersion
6+
7+
Install UpdateVersion via the following command:
8+
9+
```text
10+
$ dotnet tool install -g Monbsoft.UpdateVersion
11+
```
12+
13+
## How To Use
14+
15+
Run `UpdateVersion --help` for information about usage.
16+
17+
```text
18+
UpdateVersion:
19+
Developper tool to update the Visual Studio project versions.
20+
21+
Usage:
22+
UpdateVersion [options] [command]
23+
24+
Options:
25+
-?, -h, --help Show help and usage information
26+
--version Show version information
27+
28+
Commands:
29+
list Lists all project versions
30+
```
31+
32+
## Usage
33+
34+
### Major version update
35+
36+
Update major versions via the following command:
37+
38+
```text
39+
$ UpdateVersion major
40+
```

‎UpdateVersion.sln

+12-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 16
44
VisualStudioVersion = 16.0.30717.126
55
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Monbsoft.UpdateVersion", "src\Monbsoft.UpdateVersion\Monbsoft.UpdateVersion.csproj", "{DA8669FD-210C-4BB4-A2FA-97B244BBFBEB}"
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Monbsoft.UpdateVersion", "src\Monbsoft.UpdateVersion\Monbsoft.UpdateVersion.csproj", "{DA8669FD-210C-4BB4-A2FA-97B244BBFBEB}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Monbsoft.UpdateVersion.Tests", "test\Monbsoft.UpdateVersion.Tests\Monbsoft.UpdateVersion.Tests.csproj", "{A5FC3208-92F2-4B43-A863-A5C4D30EBFE0}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8E10E03A-B534-4A14-965C-D82BD93D05B3}"
711
EndProject
812
Global
913
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,10 +19,17 @@ Global
1519
{DA8669FD-210C-4BB4-A2FA-97B244BBFBEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
1620
{DA8669FD-210C-4BB4-A2FA-97B244BBFBEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
1721
{DA8669FD-210C-4BB4-A2FA-97B244BBFBEB}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{A5FC3208-92F2-4B43-A863-A5C4D30EBFE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{A5FC3208-92F2-4B43-A863-A5C4D30EBFE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{A5FC3208-92F2-4B43-A863-A5C4D30EBFE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{A5FC3208-92F2-4B43-A863-A5C4D30EBFE0}.Release|Any CPU.Build.0 = Release|Any CPU
1826
EndGlobalSection
1927
GlobalSection(SolutionProperties) = preSolution
2028
HideSolutionNode = FALSE
2129
EndGlobalSection
30+
GlobalSection(NestedProjects) = preSolution
31+
{A5FC3208-92F2-4B43-A863-A5C4D30EBFE0} = {8E10E03A-B534-4A14-965C-D82BD93D05B3}
32+
EndGlobalSection
2233
GlobalSection(ExtensibilityGlobals) = postSolution
2334
SolutionGuid = {0B857B9C-B6E3-4386-834E-656B9476EB16}
2435
EndGlobalSection
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.CommandLine;
5+
using System.CommandLine.Invocation;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
11+
namespace Monbsoft.UpdateVersion.Commands
12+
{
13+
public class BuildCommand : VersionCommandBase
14+
{
15+
public static Command Create()
16+
{
17+
var command = new Command("build", "Increment build version number");
18+
19+
command.Handler = CommandHandler.Create<VersionCommandArguments>(args =>
20+
{
21+
var context = new CommandContext(args.Console, args.Verbosity)
22+
{
23+
Directory = Directory.GetCurrentDirectory()
24+
};
25+
var command = new PatchCommand();
26+
command.Execute(context);
27+
});
28+
29+
return command;
30+
}
31+
32+
public void Execute(CommandContext context)
33+
{
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using Monbsoft.UpdateVersion.Models;
3+
using System.CommandLine;
4+
using System.CommandLine.Invocation;
5+
using System.IO;
6+
7+
namespace Monbsoft.UpdateVersion.Commands
8+
{
9+
public class ListCommand
10+
{
11+
public static Command Create()
12+
{
13+
var command = new Command("list", "Lists all project versions");
14+
15+
command.Handler = CommandHandler.Create<ListCommandArguments>(args =>
16+
{
17+
var context = new CommandContext(args.Console, args.Verbosity)
18+
{
19+
Directory = Directory.GetCurrentDirectory()
20+
};
21+
var command = new ListCommand();
22+
command.Execute(context);
23+
});
24+
25+
return command;
26+
}
27+
28+
public void Execute(CommandContext context)
29+
{
30+
var reader = new ProjectStore();
31+
var finder = new ProjectFinder(context.Directory);
32+
var projectFiles = finder.FindProjects();
33+
34+
foreach (var projectFile in projectFiles)
35+
{
36+
var project = reader.Read(projectFile);
37+
context.WriteInfo($"\t{project.Name} -> {project.Version}");
38+
}
39+
}
40+
41+
private class ListCommandArguments
42+
{
43+
public IConsole Console { get; set; } = default;
44+
public FileInfo Path { get; set; } = default;
45+
public Verbosity Verbosity { get; set; } = Verbosity.Info;
46+
}
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using System.CommandLine;
3+
using System.CommandLine.Invocation;
4+
using System.IO;
5+
6+
namespace Monbsoft.UpdateVersion.Commands
7+
{
8+
public class MajorCommand : VersionCommandBase
9+
{
10+
public static Command Create()
11+
{
12+
var command = new Command("major", "Increments major version number");
13+
14+
command.Handler = CommandHandler.Create<VersionCommandArguments>(args =>
15+
{
16+
var context = new CommandContext(args.Console, args.Verbosity)
17+
{
18+
Directory = Directory.GetCurrentDirectory()
19+
};
20+
var command = new MajorCommand();
21+
command.Execute(context);
22+
});
23+
24+
return command;
25+
}
26+
27+
public void Execute(CommandContext context)
28+
{
29+
int count = Update(context, (oldVersion) =>
30+
{
31+
return oldVersion.Change(major: oldVersion.Major + 1, 0, 0);
32+
});
33+
context.WriteInfo($"{count} major versions are updated.");
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using System.CommandLine;
3+
using System.CommandLine.Invocation;
4+
using System.IO;
5+
6+
namespace Monbsoft.UpdateVersion.Commands
7+
{
8+
public class MinorCommand : VersionCommandBase
9+
{
10+
public static Command Create()
11+
{
12+
var command = new Command("minor", "Increments minor version number");
13+
14+
command.Handler = CommandHandler.Create<VersionCommandArguments>(args =>
15+
{
16+
var context = new CommandContext(args.Console, args.Verbosity)
17+
{
18+
Directory = Directory.GetCurrentDirectory()
19+
};
20+
var command = new MinorCommand();
21+
command.Execute(context);
22+
});
23+
24+
return command;
25+
}
26+
27+
public void Execute(CommandContext context)
28+
{
29+
int count = Update(context, (oldVersion) =>
30+
{
31+
return oldVersion.Change(minor: oldVersion.Minor + 1, patch: 0);
32+
});
33+
context.WriteInfo($"{count} minor versions are updated.");
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using System.CommandLine;
3+
using System.CommandLine.Invocation;
4+
using System.IO;
5+
6+
namespace Monbsoft.UpdateVersion.Commands
7+
{
8+
public class PatchCommand : VersionCommandBase
9+
{
10+
public static Command Create()
11+
{
12+
var command = new Command("patch", "Increments patch version number");
13+
14+
command.Handler = CommandHandler.Create<VersionCommandArguments>(args =>
15+
{
16+
var context = new CommandContext(args.Console, args.Verbosity)
17+
{
18+
Directory = Directory.GetCurrentDirectory()
19+
};
20+
var command = new PatchCommand();
21+
command.Execute(context);
22+
});
23+
24+
return command;
25+
}
26+
27+
public void Execute(CommandContext context)
28+
{
29+
int count = Update(context, (oldVersion) =>
30+
{
31+
return oldVersion.Change(patch: oldVersion.Patch + 1);
32+
});
33+
context.WriteInfo($"{count} patch versions are updated.");
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using Monbsoft.UpdateVersion.Models;
3+
using Semver;
4+
using System;
5+
using System.CommandLine;
6+
using System.CommandLine.Invocation;
7+
using System.IO;
8+
9+
namespace Monbsoft.UpdateVersion.Commands
10+
{
11+
public class SetCommand : VersionCommandBase
12+
{
13+
public static Command Create()
14+
{
15+
var command = new Command("set", "Sets the version of the projects.");
16+
17+
var versionArg = new Argument("vesion");
18+
versionArg.Description = "Version of the projects";
19+
command.AddArgument(versionArg);
20+
21+
command.Handler = CommandHandler.Create<SetCommandArguments>(args =>
22+
{
23+
var context = new CommandContext(args.Console, args.Verbosity)
24+
{
25+
Directory = Directory.GetCurrentDirectory()
26+
};
27+
var command = new SetCommand();
28+
command.Execute(context, args.Version);
29+
});
30+
31+
return command;
32+
}
33+
34+
public void Execute(CommandContext context, string version)
35+
{
36+
var newVersion = SemVersion.Parse(version);
37+
int count = Update(context, (oldVersion) =>
38+
{
39+
return newVersion;
40+
});
41+
context.WriteInfo($"{count} versions are updated.");
42+
}
43+
44+
public class SetCommandArguments
45+
{
46+
public IConsole Console { get; set; } = default;
47+
public Verbosity Verbosity { get; set; } = Verbosity.Info;
48+
public string Version { get; set; }
49+
}
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using Monbsoft.UpdateVersion.Models;
3+
using Semver;
4+
using System;
5+
using System.CommandLine;
6+
7+
namespace Monbsoft.UpdateVersion.Commands
8+
{
9+
public class VersionCommandArguments
10+
{
11+
public IConsole Console { get; set; } = default;
12+
public Verbosity Verbosity { get; set; } = Verbosity.Info;
13+
}
14+
15+
public abstract class VersionCommandBase
16+
{
17+
private ProjectStore _store;
18+
19+
public VersionCommandBase()
20+
{
21+
_store = new ProjectStore();
22+
}
23+
24+
protected int Update(CommandContext context, Func<SemVersion, SemVersion> changeVersion)
25+
{
26+
var finder = new ProjectFinder(context.Directory);
27+
var projectFiles = finder.FindProjects();
28+
foreach (var projectFile in projectFiles)
29+
{
30+
var project = _store.Read(projectFile);
31+
UpdateProject(project, changeVersion);
32+
_store.Save(project);
33+
}
34+
return projectFiles.Count;
35+
}
36+
37+
protected void UpdateProject(Project project, Func<SemVersion, SemVersion> changeVersion)
38+
{
39+
var oldVersion = SemVersion.Parse(project.Version);
40+
var newVersion = changeVersion(oldVersion);
41+
project.Version = newVersion.ToString();
42+
}
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Monbsoft.UpdateVersion.Models;
2+
using System;
3+
using System.CommandLine;
4+
using System.CommandLine.IO;
5+
6+
namespace Monbsoft.UpdateVersion.Core
7+
{
8+
public class CommandContext
9+
{
10+
public CommandContext(IConsole console, Verbosity verbosity)
11+
{
12+
if (console == null)
13+
{
14+
throw new ArgumentNullException(nameof(console));
15+
}
16+
Console = console;
17+
Verbosity = verbosity;
18+
}
19+
20+
public IConsole Console { get; set; }
21+
public string Directory { get; set; }
22+
public Verbosity Verbosity { get; set; }
23+
24+
public void WriteLine(Verbosity verbosity, string message)
25+
{
26+
if (Verbosity >= verbosity)
27+
{
28+
Console.Out.WriteLine(message);
29+
}
30+
}
31+
32+
public void WriteDebug(string message)
33+
{
34+
WriteLine(Verbosity.Debug, message);
35+
}
36+
37+
public void WriteInfo(string message)
38+
{
39+
WriteLine(Verbosity.Info, message);
40+
}
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using Microsoft.Extensions.FileProviders;
2+
using Microsoft.Extensions.FileProviders.Physical;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Linq;
6+
7+
namespace Monbsoft.UpdateVersion.Core
8+
{
9+
public class ProjectFinder
10+
{
11+
private static readonly string ProjectFormat = "*.csproj";
12+
private static readonly string SolutionFormat = "*.sln";
13+
private readonly DirectoryInfo _currentFolder;
14+
15+
public ProjectFinder(string folderPath)
16+
{
17+
_currentFolder = new DirectoryInfo(folderPath);
18+
if(!_currentFolder.Exists)
19+
{
20+
throw new DirectoryNotFoundException(_currentFolder.Name);
21+
}
22+
}
23+
24+
public List<IFileInfo> FindProjects()
25+
{
26+
List<IFileInfo> projectFiles = new List<IFileInfo>();
27+
// try project files in current folder
28+
if (TryProjectFiles(true, out projectFiles))
29+
{
30+
return projectFiles;
31+
}
32+
// try
33+
if (ExistsSolutionFile())
34+
{
35+
TryProjectFiles(false, out projectFiles);
36+
}
37+
else
38+
{
39+
throw new FileNotFoundException("No project or solution file is found.");
40+
}
41+
42+
return projectFiles;
43+
}
44+
private bool ExistsSolutionFile()
45+
{
46+
var files = _currentFolder.GetFiles(SolutionFormat);
47+
48+
if (files.Length > 1)
49+
{
50+
throw new FileNotFoundException("More solution files are found.");
51+
}
52+
if (files.Length == 0)
53+
{
54+
return false;
55+
}
56+
57+
return true;
58+
}
59+
60+
private bool TryProjectFiles(bool inCurrentFolder, out List<IFileInfo> projectFiles)
61+
{
62+
var files = _currentFolder.GetFiles();
63+
SearchOption searchOption = SearchOption.AllDirectories;
64+
65+
if(inCurrentFolder)
66+
{
67+
searchOption = SearchOption.TopDirectoryOnly;
68+
}
69+
70+
if (!files.Any())
71+
{
72+
projectFiles = default;
73+
return false;
74+
}
75+
projectFiles = _currentFolder.EnumerateFiles(ProjectFormat, searchOption)
76+
.Select(file => new PhysicalFileInfo(file)).ToList<IFileInfo>();
77+
return projectFiles.Any();
78+
}
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using Microsoft.Extensions.FileProviders;
2+
using Monbsoft.UpdateVersion.Models;
3+
using Semver;
4+
using System;
5+
using System.Linq;
6+
using System.Xml;
7+
using System.Xml.Linq;
8+
using System.Xml.XPath;
9+
10+
namespace Monbsoft.UpdateVersion.Core
11+
{
12+
public class ProjectStore
13+
{
14+
public Project Read(IFileInfo projectFile)
15+
{
16+
if (projectFile == null)
17+
{
18+
throw new ArgumentNullException(nameof(projectFile));
19+
}
20+
var project = new Project(projectFile);
21+
22+
var projectDocument = ReadProject(projectFile);
23+
var versionElement = ReadVersionElement(projectDocument);
24+
25+
if (versionElement != null)
26+
{
27+
project.Version = versionElement.Value;
28+
}
29+
30+
if (!SemVersion.TryParse(project.Version, out var version))
31+
{
32+
version = new SemVersion(0, 1, 0);
33+
project.Version = version.ToString();
34+
}
35+
return project;
36+
}
37+
38+
public void Save(Project project)
39+
{
40+
var projectDocument = ReadProject(project.File);
41+
var versionElement = ReadVersionElement(projectDocument);
42+
43+
SemVersion parsedVersion = SemVersion.Parse(project.Version);
44+
45+
if (versionElement != null)
46+
{
47+
versionElement.Value = parsedVersion.ToString();
48+
}
49+
else
50+
{
51+
// Find the first non-conditional PropertyGroup
52+
var propertyGroup = projectDocument.Root.DescendantNodes()
53+
.FirstOrDefault(node => node is XElement el
54+
&& el.Name == "PropertyGroup"
55+
&& el.Attributes().All(attr =>
56+
attr.Name != "Condition")) as XElement;
57+
// No valid property group, create a new one
58+
if (propertyGroup == null)
59+
{
60+
propertyGroup = new XElement("PropertyGroup");
61+
projectDocument.Root.AddFirst(propertyGroup);
62+
}
63+
propertyGroup.Add(new XElement("Version", parsedVersion.ToString()));
64+
}
65+
66+
var settings = new XmlWriterSettings
67+
{
68+
OmitXmlDeclaration = true,
69+
};
70+
71+
using var xw = XmlWriter.Create(project.FullName, settings);
72+
projectDocument.Save(xw);
73+
}
74+
75+
/// <summary>
76+
/// Reads the xml version element if it exists.
77+
/// </summary>
78+
/// <param name="projectDocument"></param>
79+
/// <returns></returns>
80+
private XElement ReadVersionElement(XDocument projectDocument)
81+
{
82+
return projectDocument.XPathSelectElements("//Version").FirstOrDefault();
83+
}
84+
85+
/// <summary>
86+
/// Reads the project file as XML
87+
/// </summary>
88+
/// <param name="fileInfo"></param>
89+
/// <returns></returns>
90+
private XDocument ReadProject(IFileInfo fileInfo)
91+
{
92+
return XDocument.Load(fileInfo.PhysicalPath, LoadOptions.PreserveWhitespace);
93+
}
94+
}
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Microsoft.Extensions.FileProviders;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.Xml.Linq;
8+
using System.Xml.XPath;
9+
10+
namespace Monbsoft.UpdateVersion.Models
11+
{
12+
public class Project
13+
{
14+
public Project(IFileInfo file)
15+
{
16+
File = file ?? throw new ArgumentNullException(nameof(file));
17+
}
18+
19+
public IFileInfo File { get; }
20+
21+
public string FullName => File.PhysicalPath;
22+
23+
public string Name => File.Name;
24+
25+
public string Version { get; set; }
26+
27+
public override string ToString()
28+
{
29+
return Name;
30+
}
31+
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Monbsoft.UpdateVersion.Models
8+
{
9+
public enum Verbosity
10+
{
11+
Quiet,
12+
Info,
13+
Debug,
14+
Warn
15+
}
16+
}

‎src/Monbsoft.UpdateVersion/Monbsoft.UpdateVersion.csproj

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>net5.0</TargetFramework>
6+
<RootNamespace>Monbsoft.UpdateVersion</RootNamespace>
7+
<AssemblyName>update-version</AssemblyName>
8+
<Version>0.1.0</Version>
9+
<PackageId>Monbsoft.UpdateVersion</PackageId>
10+
<IsPackable>true</IsPackable>
11+
<PackAsTool>true</PackAsTool>
12+
<ToolCommandName>updateVersion</ToolCommandName>
613
</PropertyGroup>
714

815
<ItemGroup>
16+
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0" />
17+
<PackageReference Include="semver" Version="2.0.6" />
918
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20371.2" />
1019
</ItemGroup>
1120

‎src/Monbsoft.UpdateVersion/Program.cs

+40-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,48 @@
1-
using System;
1+
using Monbsoft.UpdateVersion.Commands;
2+
using System;
3+
using System.CommandLine;
4+
using System.CommandLine.Builder;
5+
using System.CommandLine.Help;
6+
using System.CommandLine.Invocation;
7+
using System.CommandLine.IO;
8+
using System.CommandLine.Parsing;
9+
using System.Threading.Tasks;
210

311
namespace Monbsoft.UpdateVersion
412
{
513
class Program
6-
{
7-
static void Main(string[] args)
14+
{
15+
public static Task<int> Main(string[] args)
816
{
9-
Console.WriteLine("Hello World!");
17+
var command = new RootCommand()
18+
{
19+
Description = "Developper tool to update the Visual Studio project versions."
20+
};
21+
command.AddCommand(ListCommand.Create());
22+
command.AddCommand(MajorCommand.Create());
23+
command.AddCommand(MinorCommand.Create());
24+
command.AddCommand(PatchCommand.Create());
25+
//command.AddCommand(BuildCommand.Create());
26+
command.AddCommand(SetCommand.Create());
27+
28+
29+
var builder = new CommandLineBuilder(command)
30+
.UseHelp()
31+
.UseDefaults()
32+
.UseVersionOption()
33+
.CancelOnProcessTermination()
34+
.UseExceptionHandler();
35+
36+
var parser = builder.Build();
37+
return parser.InvokeAsync(args);
38+
}
39+
40+
private static void HandleException(Exception ex, InvocationContext context)
41+
{
42+
context.Console.Error.WriteLine();
43+
context.Console.Error.WriteLine(ex.Message);
44+
45+
context.ResultCode = 1;
1046
}
1147
}
1248
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using Monbsoft.UpdateVersion.Commands;
2+
using Monbsoft.UpdateVersion.Core;
3+
using Monbsoft.UpdateVersion.Models;
4+
using Monbsoft.UpdateVersion.Tests.Utilities;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using Xunit;
11+
12+
namespace Monbsoft.UpdateVersion.Tests
13+
{
14+
public class BuildTests
15+
{
16+
private TestConsole _console;
17+
18+
public BuildTests()
19+
{
20+
_console = new TestConsole();
21+
}
22+
23+
//[Fact]
24+
//public void ChangeBuildVersionTest()
25+
//{
26+
// using (var fs = new DisposableFileSystem())
27+
// {
28+
// fs.CreateFile("MySolution.sln");
29+
// fs.CreateFolder("src/Services");
30+
// fs.CreateFile("src/Services/project1.csproj", ProjectHelper.BuildVersion("3.63.4"));
31+
// var store = new ProjectStore();
32+
// var command = new BuildCommand();
33+
// var context = new CommandContext(_console, Verbosity.Info);
34+
// context.Directory = fs.RootPath;
35+
36+
// command.Execute(context);
37+
// var project = store.Read(PathHelper.GetFile(fs, "src/Services/project1.csproj"));
38+
39+
// Assert.Equal("3.63.4+1", project.Version);
40+
41+
// }
42+
//}
43+
44+
//[Fact]
45+
//public void ChangeExistingBuildVersionTest()
46+
//{
47+
// using (var fs = new DisposableFileSystem())
48+
// {
49+
// fs.CreateFile("MySolution.sln");
50+
// fs.CreateFolder("src/Services");
51+
// fs.CreateFile("src/Services/project1.csproj", ProjectHelper.BuildVersion("5.0.8"));
52+
// var store = new ProjectStore();
53+
// var command = new BuildCommand();
54+
// var context = new CommandContext(_console, Verbosity.Info);
55+
// context.Directory = fs.RootPath;
56+
57+
// command.Execute(context);
58+
// var project = store.Read(PathHelper.GetFile(fs, "src/Services/project1.csproj"));
59+
60+
// Assert.Equal("5.0.8+15", project.Version);
61+
62+
// }
63+
//}
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using Monbsoft.UpdateVersion.Core;
2+
using Monbsoft.UpdateVersion.Tests.Utilities;
3+
using System.IO;
4+
using System.Linq;
5+
using Xunit;
6+
7+
namespace Monbsoft.UpdateVersion.Tests
8+
{
9+
public class FileFinderTests
10+
{
11+
[Fact]
12+
public void FindWithSolutionFile()
13+
{
14+
using(var fs = new DisposableFileSystem())
15+
{
16+
fs.CreateFile("MySolution.sln")
17+
.CreateFolder("src/project")
18+
.CreateFile("src/project/proj1.csproj");
19+
var finder = new ProjectFinder(fs.RootPath);
20+
21+
22+
var projectFiles = finder.FindProjects();
23+
var project = projectFiles.First();
24+
25+
26+
Assert.Single(projectFiles);
27+
Assert.Equal("proj1.csproj", project.Name);
28+
}
29+
}
30+
31+
[Fact]
32+
public void FindWithProjectFiles()
33+
{
34+
using(var fs = new DisposableFileSystem())
35+
{
36+
fs.CreateFile("project1.csproj")
37+
.CreateFile("project2.csproj");
38+
var finder = new ProjectFinder(fs.RootPath);
39+
40+
var projects = finder.FindProjects();
41+
42+
Assert.Equal("project1.csproj", projects[0].Name);
43+
Assert.Equal("project2.csproj", projects[1].Name);
44+
45+
}
46+
}
47+
48+
[Fact]
49+
public void FindWithNoProjectOrSolution()
50+
{
51+
using(var fs = new DisposableFileSystem())
52+
{
53+
fs.CreateFolder("src/project1")
54+
.CreateFile("src/project1/project1.csproj");
55+
var finder = new ProjectFinder(fs.RootPath);
56+
57+
Assert.Throws<FileNotFoundException>(() => finder.FindProjects());
58+
59+
}
60+
}
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Monbsoft.UpdateVersion.Commands;
2+
using Monbsoft.UpdateVersion.Core;
3+
using Monbsoft.UpdateVersion.Models;
4+
using Monbsoft.UpdateVersion.Tests.Utilities;
5+
using Xunit;
6+
7+
namespace Monbsoft.UpdateVersion.Tests
8+
{
9+
public class MajorTests
10+
{
11+
private TestConsole _console;
12+
13+
public MajorTests()
14+
{
15+
_console = new TestConsole();
16+
}
17+
18+
[Fact]
19+
public void ChangeMajorVersionTest()
20+
{
21+
using(var fs = new DisposableFileSystem())
22+
{
23+
fs.CreateFile("MySolution.sln");
24+
fs.CreateFolder("src/Services");
25+
fs.CreateFile("src/Services/project1.csproj", ProjectHelper.BuildVersion("1.5.1"));
26+
var store = new ProjectStore();
27+
var command = new MajorCommand();
28+
var context = new CommandContext(_console, Verbosity.Info);
29+
context.Directory = fs.RootPath;
30+
31+
command.Execute(context);
32+
var project = store.Read(PathHelper.GetFile(fs, "src/Services/project1.csproj"));
33+
34+
Assert.Equal("2.0.0", project.Version);
35+
36+
}
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Monbsoft.UpdateVersion.Commands;
2+
using Monbsoft.UpdateVersion.Core;
3+
using Monbsoft.UpdateVersion.Models;
4+
using Monbsoft.UpdateVersion.Tests.Utilities;
5+
using Xunit;
6+
7+
namespace Monbsoft.UpdateVersion.Tests
8+
{
9+
public class PatchTests
10+
{
11+
private TestConsole _console;
12+
13+
public PatchTests()
14+
{
15+
_console = new TestConsole();
16+
}
17+
18+
[Fact]
19+
public void ChangePatchVersionTest()
20+
{
21+
using (var fs = new DisposableFileSystem())
22+
{
23+
fs.CreateFile("MySolution.sln");
24+
fs.CreateFolder("src/Services");
25+
fs.CreateFile("src/Services/project1.csproj", ProjectHelper.BuildVersion("1.5.1"));
26+
var store = new ProjectStore();
27+
var command = new PatchCommand();
28+
var context = new CommandContext(_console, Verbosity.Info);
29+
context.Directory = fs.RootPath;
30+
31+
command.Execute(context);
32+
var project = store.Read(PathHelper.GetFile(fs, "src/Services/project1.csproj"));
33+
34+
Assert.Equal("1.5.2", project.Version);
35+
36+
}
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
11+
<PackageReference Include="xunit" Version="2.4.1" />
12+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
13+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
14+
<PrivateAssets>all</PrivateAssets>
15+
</PackageReference>
16+
<PackageReference Include="coverlet.collector" Version="1.3.0">
17+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
18+
<PrivateAssets>all</PrivateAssets>
19+
</PackageReference>
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\..\src\Monbsoft.UpdateVersion\Monbsoft.UpdateVersion.csproj" />
24+
</ItemGroup>
25+
26+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Monbsoft.UpdateVersion.Commands;
2+
using Monbsoft.UpdateVersion.Core;
3+
using Monbsoft.UpdateVersion.Models;
4+
using Monbsoft.UpdateVersion.Tests.Utilities;
5+
using Xunit;
6+
7+
namespace Monbsoft.UpdateVersion.Tests
8+
{
9+
public class MinorTests
10+
{
11+
private TestConsole _console;
12+
13+
public MinorTests()
14+
{
15+
_console = new TestConsole();
16+
}
17+
18+
[Fact]
19+
public void ChangeMinorVersionTest()
20+
{
21+
using (var fs = new DisposableFileSystem())
22+
{
23+
fs.CreateFile("MySolution.sln");
24+
fs.CreateFolder("src/Services");
25+
fs.CreateFile("src/Services/project1.csproj", ProjectHelper.BuildVersion("1.5.1"));
26+
var store = new ProjectStore();
27+
var command = new MinorCommand();
28+
var context = new CommandContext(_console, Verbosity.Info);
29+
context.Directory = fs.RootPath;
30+
31+
command.Execute(context);
32+
var project = store.Read(PathHelper.GetFile(fs, "src/Services/project1.csproj"));
33+
34+
Assert.Equal("1.6.0", project.Version);
35+
36+
}
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using Microsoft.Extensions.FileProviders;
2+
using Microsoft.Extensions.FileProviders.Physical;
3+
using Monbsoft.UpdateVersion.Core;
4+
using Monbsoft.UpdateVersion.Tests.Utilities;
5+
using System;
6+
using System.IO;
7+
using Xunit;
8+
9+
namespace Monbsoft.UpdateVersion.Tests
10+
{
11+
public class ProjectStoreTests
12+
{
13+
14+
[Fact]
15+
public void ReadNoVersionTest()
16+
{
17+
string projectFile = "project2.csproj";
18+
using (var fs = new DisposableFileSystem())
19+
{
20+
fs.CreateFile(projectFile, ProjectHelper.BuildVersion(string.Empty));
21+
var store = new ProjectStore();
22+
23+
var project = store.Read(CreateFileInfo(fs, projectFile));
24+
25+
Assert.Equal("0.1.0", project.Version);
26+
}
27+
}
28+
29+
[Fact]
30+
public void ReadProjectTest()
31+
{
32+
string projectFile = "project1.csproj";
33+
using (var fs = new DisposableFileSystem())
34+
{
35+
fs.CreateFile(projectFile, ProjectHelper.BuildVersion("0.5"));
36+
var store = new ProjectStore();
37+
38+
var project = store.Read(CreateFileInfo(fs, projectFile));
39+
40+
Assert.Equal("0.5", project.Version);
41+
}
42+
}
43+
44+
[Fact]
45+
public void ReadProjectWithPatchTest()
46+
{
47+
string projectFile = "MyProject.csproj";
48+
using (var fs = new DisposableFileSystem())
49+
{
50+
fs.CreateFile(projectFile, ProjectHelper.BuildVersion("1.3.5"));
51+
var store = new ProjectStore();
52+
53+
var project = store.Read(CreateFileInfo(fs, projectFile));
54+
55+
Assert.Equal("1.3.5", project.Version);
56+
}
57+
}
58+
59+
[Fact]
60+
public void UpdateProjectTest()
61+
{
62+
string projectFile = "MyProject.csproj";
63+
64+
using (var fs = new DisposableFileSystem())
65+
{
66+
fs.CreateFile(projectFile, ProjectHelper.BuildVersion("1.4.0"));
67+
var store = new ProjectStore();
68+
var project = store.Read(CreateFileInfo(fs, projectFile));
69+
project.Version = "2.0";
70+
71+
store.Save(project);
72+
var newProject = store.Read(CreateFileInfo(fs, projectFile));
73+
74+
Assert.Equal("2.0", project.Version);
75+
}
76+
}
77+
78+
[Fact]
79+
public void UpdateProjectWithBadVersionTest()
80+
{
81+
string projectFile = "MyProject.csproj";
82+
83+
using (var fs = new DisposableFileSystem())
84+
{
85+
fs.CreateFile(projectFile, ProjectHelper.BuildVersion("1.4.0"));
86+
var store = new ProjectStore();
87+
var project = store.Read(CreateFileInfo(fs, projectFile));
88+
project.Version = "${BuildVersion}";
89+
90+
Assert.Throws<ArgumentException>("version", () => store.Save(project));
91+
}
92+
}
93+
94+
private static IFileInfo CreateFileInfo(DisposableFileSystem fs, string filename)
95+
{
96+
return new PhysicalFileInfo(new FileInfo(Path.Combine(fs.RootPath, filename)));
97+
}
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using Monbsoft.UpdateVersion.Commands;
2+
using Monbsoft.UpdateVersion.Core;
3+
using Monbsoft.UpdateVersion.Models;
4+
using Monbsoft.UpdateVersion.Tests.Utilities;
5+
using Xunit;
6+
7+
namespace Monbsoft.UpdateVersion.Tests
8+
{
9+
public class SetTests
10+
{
11+
private TestConsole _console;
12+
13+
public SetTests()
14+
{
15+
_console = new TestConsole();
16+
}
17+
18+
[Fact]
19+
public void ChangeVersionTest()
20+
{
21+
using (var fs = new DisposableFileSystem())
22+
{
23+
fs.CreateFile("MySolution.sln");
24+
fs.CreateFolder("src/Services");
25+
fs.CreateFile("src/Services/project1.csproj", ProjectHelper.BuildVersion("1.5.1"));
26+
var store = new ProjectStore();
27+
var command = new SetCommand();
28+
var context = new CommandContext(_console, Verbosity.Info);
29+
context.Directory = fs.RootPath;
30+
31+
command.Execute(context, "3.0.1");
32+
var project = store.Read(PathHelper.GetFile(fs, "src/Services/project1.csproj"));
33+
34+
Assert.Equal("3.0.1", project.Version);
35+
36+
}
37+
}
38+
39+
[Fact]
40+
public void ChangeVersionsTest()
41+
{
42+
using (var fs = new DisposableFileSystem())
43+
{
44+
fs.CreateFile("MySolution.sln")
45+
.CreateFolder("src/Services/project1")
46+
.CreateFile("src/Services/project1/project1.csproj", ProjectHelper.BuildVersion("1.5.1"))
47+
.CreateFolder("src/Services/project2")
48+
.CreateFile("src/Services/project2/project2.csproj", ProjectHelper.BuildVersion("2.1.0"));
49+
var store = new ProjectStore();
50+
var command = new SetCommand();
51+
var context = new CommandContext(_console, Verbosity.Info);
52+
context.Directory = fs.RootPath;
53+
54+
command.Execute(context, "4.0.12");
55+
var project1 = store.Read(PathHelper.GetFile(fs, "src/Services/project1/project1.csproj"));
56+
var project2 = store.Read(PathHelper.GetFile(fs, "src/Services/project2/project2.csproj"));
57+
58+
Assert.Equal("4.0.12", project1.Version);
59+
Assert.Equal("4.0.12", project2.Version);
60+
61+
}
62+
}
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Text;
5+
6+
namespace Monbsoft.UpdateVersion.Tests.Utilities
7+
{
8+
public class DisposableFileSystem : IDisposable
9+
{
10+
private bool _disposed;
11+
12+
public DisposableFileSystem()
13+
{
14+
_disposed = false;
15+
RootPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
16+
Directory.CreateDirectory(RootPath);
17+
DirectoryInfo = new DirectoryInfo(RootPath);
18+
}
19+
20+
public DirectoryInfo DirectoryInfo { get; set; }
21+
public string RootPath { get; }
22+
23+
public DisposableFileSystem CreateFile(string path)
24+
{
25+
File.WriteAllText(Path.Combine(RootPath, path), GetDefaultContent());
26+
return this;
27+
}
28+
public DisposableFileSystem CreateFile(string path, string content)
29+
{
30+
File.WriteAllText(Path.Combine(RootPath, path), content);
31+
return this;
32+
}
33+
public DisposableFileSystem CreateFolder(string path)
34+
{
35+
Directory.CreateDirectory(Path.Combine(RootPath, path));
36+
return this;
37+
}
38+
public void Dispose()
39+
{
40+
Dispose(true);
41+
GC.SuppressFinalize(this);
42+
}
43+
44+
protected virtual void Dispose(bool disposing)
45+
{
46+
if (_disposed)
47+
{
48+
return;
49+
}
50+
if (disposing)
51+
{
52+
try
53+
{
54+
Directory.Delete(RootPath, true);
55+
}
56+
catch
57+
{
58+
59+
}
60+
}
61+
_disposed = true;
62+
}
63+
64+
private string GetDefaultContent()
65+
{
66+
return @"<Project Sdk=""Microsoft.NET.Sdk"">
67+
</Project>";
68+
}
69+
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.Extensions.FileProviders;
2+
using Microsoft.Extensions.FileProviders.Physical;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace Monbsoft.UpdateVersion.Tests.Utilities
11+
{
12+
public static class PathHelper
13+
{
14+
public static IFileInfo GetFile(DisposableFileSystem fs, string filename)
15+
{
16+
var fileInfo = new FileInfo(Path.Combine(fs.RootPath, filename));
17+
return new PhysicalFileInfo(fileInfo);
18+
}
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Monbsoft.UpdateVersion.Tests.Utilities
8+
{
9+
public static class ProjectHelper
10+
{
11+
private const string ProjectTemplate = @"<Project Sdk=""Microsoft.NET.Sdk"">
12+
<PropertyGroup>
13+
<OutputType>Exe</OutputType>
14+
<TargetFrameworks>net5.0</TargetFrameworks>
15+
{0}
16+
</PropertyGroup>
17+
<ItemGroup>
18+
<Compile Include=""**\*.cs"" Exclude=""Excluded.cs;$(DefaultItemExcludes)"" />
19+
</ItemGroup>
20+
</Project>";
21+
22+
public static string BuildVersion(string version)
23+
{
24+
return string.Format(ProjectTemplate, $"<Version>{version}</Version>");
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System.CommandLine;
2+
using System.CommandLine.IO;
3+
using System.IO;
4+
using System.Text;
5+
6+
namespace Monbsoft.UpdateVersion.Tests.Utilities
7+
{
8+
public class TestConsole : IConsole
9+
{
10+
public TestConsole()
11+
{
12+
Out = new StandardStreamWriter();
13+
Error = new StandardStreamWriter();
14+
}
15+
16+
public IStandardStreamWriter Error { get; protected set; }
17+
18+
public IStandardStreamWriter Out { get; protected set; }
19+
20+
public bool IsOutputRedirected { get; protected set; }
21+
22+
public bool IsErrorRedirected { get; protected set; }
23+
24+
public bool IsInputRedirected { get; protected set; }
25+
26+
internal class StandardStreamWriter : TextWriter, IStandardStreamWriter
27+
{
28+
private readonly StringBuilder _stringBuilder = new StringBuilder();
29+
30+
public override void Write(char value)
31+
{
32+
_stringBuilder.Append(value);
33+
}
34+
35+
public override void Write(string? value)
36+
{
37+
_stringBuilder.Append(value);
38+
}
39+
40+
public override Encoding Encoding { get; } = Encoding.Unicode;
41+
42+
public override string ToString() => _stringBuilder.ToString();
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)
Please sign in to comment.