public static void DefaultPreReleasePhase(string phase, string expectedVersion, string path, Version actualVersion) { $"Given a git repository with a commit in '{path = GetScenarioDirectory($"default-pre-release-phase-{phase}")}'" .x(() => EnsureEmptyRepositoryAndCommit(path)); $"When the version is determined using the default pre-release phase '{phase}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, default, default, phase, new TestLogger()));
public static void NoCommits(string path, Version actualVersion) { $"Given an empty git repository in {path = MethodBase.GetCurrentMethod().GetTestDirectory()}" .x(() => EnsureEmptyRepository(path)); "When the version is determined using minimum major minor '1.2'" .x(() => actualVersion = Versioner.GetVersion(path, default, new MajorMinor(1, 2), default, default, default, default));
public static void RepoWithHistory(string name, string path) { $"Given a git repository in '{path = GetScenarioDirectory("versioning-repo-with-history-" + name)}' with a history of branches and/or tags" .x(async() => { await EnsureRepositoryWithACommit(path); foreach (var command in historicalCommands[name].Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) { var nameAndArgs = command.Split(" ", 2); await RunAsync(nameAndArgs[0], nameAndArgs[1], path); await Task.Delay(200); } }); "When the version is determined for every commit" .x(() => { var versionCounts = new Dictionary <string, int>(); using (var repo = new Repository(path)) { foreach (var commit in repo.Commits) { Commands.Checkout(repo, commit); var version = Versioner.GetVersion(path, default, default, default, default, default);
public static void NoCommits(string buildMetadata, string expectedVersion, string path, Version actualVersion) { $"Given an empty git repository in '{path = GetScenarioDirectory($"build-metadata-no-tag-{buildMetadata}")}'" .x(c => EnsureEmptyRepository(path).Using(c)); $"When the version is determined using build metadata '{buildMetadata}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, buildMetadata, default, new TestLogger()));
public static void NoCommits(string path, Repository repo, Version actualVersion) { $"Given an empty git repository in '{path = GetScenarioDirectory($"minimum-major-minor-not-tagged")}'" .x(c => repo = EnsureEmptyRepository(path).Using(c)); "When the version is determined using minimum major minor '1.2'" .x(() => actualVersion = Versioner.GetVersion(repo, default, new MajorMinor(1, 2), default, new TestLogger()));
public static void DefaultPreReleasePhase(string phase, string expectedVersion, string path, Version actualVersion) { $"Given a git repository with a commit in {path = MethodBase.GetCurrentMethod().GetTestDirectory(phase)}" .x(() => EnsureEmptyRepositoryAndCommit(path)); $"When the version is determined using the default pre-release phase '{phase}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, default, default, phase, default));
public static void NoCommits(string buildMetadata, string expectedVersion, string path, Version actualVersion) { $"Given an empty git repository in {path = MethodBase.GetCurrentMethod().GetTestDirectory(buildMetadata)}" .x(() => EnsureEmptyRepository(path)); $"When the version is determined using build metadata '{buildMetadata}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, buildMetadata, default, default, default));
public static async Task NoCommits(string buildMetadata, string expectedVersion) { // arrange var path = MethodBase.GetCurrentMethod().GetTestDirectory(buildMetadata); await EnsureEmptyRepository(path); // act var actualVersion = Versioner.GetVersion(path, "", MajorMinor.Zero, buildMetadata, default, "", NullLogger.Instance);
public static async Task NoCommits() { // arrange var path = MethodBase.GetCurrentMethod().GetTestDirectory(); await EnsureEmptyRepository(path); // act var actualVersion = Versioner.GetVersion(path, "", new MajorMinor(1, 2), "", default, "", NullLogger.Instance);
public static async Task DefaultPreReleasePhase(string phase, string expectedVersion) { // arrange var path = MethodBase.GetCurrentMethod().GetTestDirectory(phase); await EnsureEmptyRepositoryAndCommit(path); // act var actualVersion = Versioner.GetVersion(path, "", MajorMinor.Zero, "", default, phase, NullLogger.Instance);
public static void TagPrefix(string tag, string prefix, string expectedVersion, string path, Version actualVersion) { $"Given a git repository with a commit in '{path = GetScenarioDirectory($"tag-prefixes-{tag}")}'" .x(async() => await EnsureRepositoryWithACommit(path)); $"And the commit is tagged '{tag}'" .x(async() => await RunAsync("git", $"tag {tag}", path)); $"When the version is determined using the tag prefix '{prefix}'" .x(() => actualVersion = Versioner.GetVersion(path, default, prefix, default, default, default));
public static async Task TagPrefix(string tag, string prefix, string expectedVersion) { // act var path = MethodBase.GetCurrentMethod().GetTestDirectory((tag, prefix)); await EnsureEmptyRepositoryAndCommit(path); await Tag(path, tag); // act var actualVersion = Versioner.GetVersion(path, prefix, MajorMinor.Zero, "", default, "", NullLogger.Instance);
public static void CurrentTag(string tag, string buildMetadata, string expectedVersion, string path, Version actualVersion) { $"Given a git repository with a commit in '{path = GetScenarioDirectory($"build-metadata-current-tag-{tag}-{buildMetadata}")}'" .x(async() => await EnsureRepositoryWithACommit(path)); $"And the commit is tagged '{tag}'" .x(async() => await RunAsync("git", $"tag {tag}", path)); $"When the version is determined using build metadata '{buildMetadata}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, default, default, buildMetadata));
public static void TagPrefix(string tag, string prefix, string expectedVersion, string path, Repository repo, Version actualVersion) { $"Given a git repository with a commit in '{path = GetScenarioDirectory($"tag-prefixes-{tag}")}'" .x(c => repo = EnsureEmptyRepositoryAndCommit(path).Using(c)); $"And the commit is tagged '{tag}'" .x(() => repo.ApplyTag(tag)); $"When the version is determined using the tag prefix '{prefix}'" .x(() => actualVersion = Versioner.GetVersion(path, prefix, default, default, new TestLogger()));
public static void TagPrefix(string tag, string prefix, string expectedVersion, string path, Version actualVersion) { $"Given a git repository with a commit in {path = MethodBase.GetCurrentMethod().GetTestDirectory(tag)}" .x(() => EnsureEmptyRepositoryAndCommit(path)); $"And the commit is tagged '{tag}'" .x(() => Tag(path, tag)); $"When the version is determined using the tag prefix '{prefix}'" .x(() => actualVersion = Versioner.GetVersion(path, prefix, default, default, default, default, default));
public static async Task RepoWithHistory(int minMajor, int minMinor) { // arrange var minMajorMinor = new MajorMinor(minMajor, minMinor); var historicalCommands = @" git commit --allow-empty -m '.' git tag not-a-version git checkout -b foo git commit --allow-empty -m '.' git tag 1.0.0-foo.1 git checkout main git merge foo --no-edit --no-ff git checkout -b bar git commit --allow-empty -m '.' git checkout main git checkout -b baz git commit --allow-empty -m '.' git checkout main git merge bar baz --no-edit --no-ff --strategy=octopus "; var path = MethodBase.GetCurrentMethod().GetTestDirectory(minMajorMinor); await EnsureEmptyRepository(path); foreach (var item in historicalCommands .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select((command, index) => new { Command = command, Index = $"{index}" })) { if (item.Command.StartsWith("git commit", StringComparison.Ordinal)) { // Sometimes git seems to treat bar and baz as a single branch if the commits are empty. // This probably occurs during the octopus merge. // So let's add a file before each commit to ensure that doesn't happen. await File.WriteAllTextAsync(Path.Combine(path, item.Index), item.Index); _ = await ReadAsync("git", $"add {item.Index}", path); // if not enough delay is given between commits, // the order of parallel commits on different branches seems to be non-deterministic await Task.Delay(1100); } var nameAndArgs = item.Command.Split(" ", 2); _ = await ReadAsync(nameAndArgs[0], nameAndArgs[1], path); } var log = new TestLogger(); // act _ = Versioner.GetVersion(path, "", minMajorMinor, "", default, "", log);
public static void RtmVersionIncrement(string tag, VersionPart autoIncrement, string expectedVersion, string path, Repository repo, Version actualVersion) { $"Given a git repository with a commit in '{path = GetScenarioDirectory($"rtm-auto-increment-{tag}")}'" .x(c => repo = EnsureEmptyRepositoryAndCommit(path).Using(c)); $"And the commit is tagged '{tag}'" .x(() => repo.ApplyTag(tag)); $"And another commit" .x(() => Commit(path)); $"When the version is determined using auto-increment '{autoIncrement}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, default, autoIncrement, default, new TestLogger()));
public static void RtmVersionIncrement(string tag, VersionPart autoIncrement, string expectedVersion, string path, Version actualVersion) { $"Given a git repository with a commit in {path = MethodBase.GetCurrentMethod().GetTestDirectory(autoIncrement)}" .x(() => EnsureEmptyRepositoryAndCommit(path)); $"And the commit is tagged '{tag}'" .x(() => Tag(path, tag)); "And another commit" .x(() => Commit(path)); $"When the version is determined using auto-increment '{autoIncrement}'" .x(() => actualVersion = Versioner.GetVersion(path, default, default, default, autoIncrement, default, default));
public static void Subdirectory(string path, Version version) { $"Given a git repository with a commit in '{path = GetScenarioDirectory("msbuild-integration-subdirectory")}'" .x(async() => await EnsureRepositoryWithACommit(path)); "And the commit is tagged 2.0.0" .x(async() => await RunAsync("git", "tag 2.0.0", path)); "And the repository has a subdirectory" .x(() => EnsureEmptyDirectory(path = Path.Combine(path, "subdirectory"))); "When the version is determined using the subdirectory" .x(() => version = Versioner.GetVersion(path, default, default, default, default, default));
public static async Task RtmVersionIncrement(string tag, VersionPart autoIncrement, string expectedVersion) { // arrange var path = MethodBase.GetCurrentMethod().GetTestDirectory((tag, autoIncrement)); await EnsureEmptyRepositoryAndCommit(path); await Tag(path, tag); await Commit(path); // act var actualVersion = Versioner.GetVersion(path, "", MajorMinor.Zero, "", autoIncrement, "", NullLogger.Instance); // assert Assert.Equal(expectedVersion, actualVersion.ToString()); }
static int Main(string[] args) { var app = new CommandLineApplication(); app.HelpOption(); var buildMetadata = app.Option("-b|--build-metadata <BUILD_METADATA>", "The build metadata to append to the version.", CommandOptionType.SingleValue); var majorMinor = app.Option("-m|--major-minor <MAJOR.MINOR>", "The MAJOR.MINOR version range. E.g. '2.0'.", CommandOptionType.SingleValue); var path = app.Option("-p|--path <PATH>", "The path of the repository.", CommandOptionType.SingleValue); var tagPrefix = app.Option("-t|--tag-prefix <TAG_PREFIX>", "The tag prefix.", CommandOptionType.SingleValue); var verbose = app.Option("-v|--verbose", "Enable verbose logging.", CommandOptionType.NoValue); app.OnExecute(() => { var major = 0; var minor = 0; var majorMinorValue = majorMinor.Value(); if (!string.IsNullOrEmpty(majorMinorValue)) { var numbers = majorMinorValue.Split('.'); if (numbers.Length > 2) { Console.Out.WriteLine($"MinVer: error MINVER0004 : More than one dot in MAJOR.MINOR range '{majorMinorValue}'."); return(2); } if (!int.TryParse(numbers[0], out major)) { Console.Out.WriteLine($"MinVer: error MINVER0005 : Invalid MAJOR '{numbers[0]}' in MAJOR.MINOR range '{majorMinorValue}'."); return(2); } if (numbers.Length > 1 && !int.TryParse(numbers[1], out minor)) { Console.Out.WriteLine($"MinVer: error MINVER0006 : Invalid MINOR '{numbers[1]}' in MAJOR.MINOR range '{majorMinorValue}'."); return(2); } } Console.Out.WriteLine(Versioner.GetVersion(path.Value() ?? ".", verbose.HasValue(), tagPrefix.Value(), major, minor, buildMetadata.Value())); return(0); }); return(app.Execute(args)); }
public static void RepoWithHistory(string name, string path) { $"Given a git repository with a history of branches and/or tags in {path = MethodBase.GetCurrentMethod().GetTestDirectory(name)}" .x(async() => { await EnsureEmptyRepositoryAndCommit(path); foreach (var command in historicalCommands[name].Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) { var nameAndArgs = command.Split(" ", 2); await Cli.Wrap(nameAndArgs[0]).WithArguments(nameAndArgs[1]).WithWorkingDirectory(path).ExecuteAsync(); await Task.Delay(200); } }); "When the version is determined for every commit" .x(async() => { var versionCounts = new Dictionary <string, int>(); foreach (var sha in await GetCommitShas(path)) { await Checkout(path, sha); var version = Versioner.GetVersion(path, default, default, default, default, default, default);
private static int Main(string[] args) { using var app = new CommandLineApplication { Name = "minver", FullName = $"MinVer CLI {informationalVersion}", }; app.HelpOption(); var workDirArg = app.Argument("workingDirectory", "Working directory (optional)"); var autoIncrementOption = app.Option("-a|--auto-increment <VERSION_PART>", VersionPartExtensions.ValidValues, CommandOptionType.SingleValue); var buildMetaOption = app.Option("-b|--build-metadata <BUILD_METADATA>", "", CommandOptionType.SingleValue); var defaultPreReleasePhaseOption = app.Option("-d|--default-pre-release-phase <PHASE>", "alpha (default), preview, etc.", CommandOptionType.SingleValue); var ignoreHeightOption = app.Option <bool>("-i|--ignore-height", "Use the latest tag (or root commit) as-is, without adding height", CommandOptionType.NoValue); var minMajorMinorOption = app.Option("-m|--minimum-major-minor <MINIMUM_MAJOR_MINOR>", MajorMinor.ValidValues, CommandOptionType.SingleValue); var tagPrefixOption = app.Option("-t|--tag-prefix <TAG_PREFIX>", "", CommandOptionType.SingleValue); var verbosityOption = app.Option("-v|--verbosity <VERBOSITY>", VerbosityMap.ValidValues, CommandOptionType.SingleValue); #if MINVER var versionOverrideOption = app.Option("-o|--version-override <VERSION>", "", CommandOptionType.SingleValue); #endif app.OnExecute(() => { var workDir = workDirArg.Value ?? "."; if (!Directory.Exists(workDir)) { Logger.ErrorWorkDirDoesNotExist(workDir); return(2); } if (!Options.TryParse( autoIncrementOption.Value(), buildMetaOption.Value(), defaultPreReleasePhaseOption.Value(), ignoreHeightOption.HasValue() ? true : null, minMajorMinorOption.Value(), tagPrefixOption.Value(), verbosityOption.Value(), #if MINVER versionOverrideOption.Value(), #endif out var options)) { return(2); } #if MINVER_CLI if (!Options.TryParseEnvVars(out var envOptions)) { return(2); } options = options.Mask(envOptions); #endif var log = new Logger(options.Verbosity ?? default); _ = log.IsDebugEnabled && log.Debug($"MinVer {informationalVersion}."); if (options.VersionOverride != null) { _ = log.IsInfoEnabled && log.Info($"Using version override {options.VersionOverride}."); Console.Out.WriteLine(options.VersionOverride); return(0); } var version = Versioner.GetVersion(workDir, options.TagPrefix ?? "", options.MinMajorMinor ?? MajorMinor.Zero, options.BuildMeta ?? "", options.AutoIncrement ?? default, options.DefaultPreReleasePhase ?? "", log, options.IgnoreHeight ?? false); Console.Out.WriteLine(version); return(0); }); return(app.Execute(args)); }
public static async Task RepoWithHistory() { // arrange var historicalCommands = @" git commit --allow-empty -m '.' git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 0.0.0-alpha.1 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 0.0.0 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 0.1.0-beta.1 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 0.1.0 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 1.0.0-alpha.1 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 1.0.0-rc.1 git tag 1.0.0 git checkout -b foo git commit --allow-empty -m '.' git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 1.0.1-alpha.1 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 1.0.1 git commit --allow-empty -m '.' git checkout main git commit --allow-empty -m '.' git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 1.1.0-alpha.1 git commit --allow-empty -m '.' git merge foo --no-edit git commit --allow-empty -m '.' git tag 1.1.0-beta.2 git tag 1.1.0-beta.10 git commit --allow-empty -m '.' git commit --allow-empty -m '.' git tag 1.1.0-rc.1 git tag 1.1.0 -a -m '.' "; var path = MethodBase.GetCurrentMethod().GetTestDirectory(); await EnsureEmptyRepositoryAndCommit(path); foreach (var command in historicalCommands.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) { var nameAndArgs = command.Split(" ", 2); _ = await ReadAsync(nameAndArgs[0], nameAndArgs[1], path); await Task.Delay(200); } var log = new TestLogger(); // act var versionCounts = new Dictionary <string, int>(); foreach (var sha in await GetCommitShas(path)) { await Checkout(path, sha); var version = Versioner.GetVersion(path, "", MajorMinor.Zero, "", default, "", log);