diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index f920b5ce08..91828b2d3d 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -37,6 +37,7 @@
+
diff --git a/src/GitVersion.App.Tests/ArgumentParserTests.cs b/src/GitVersion.App.Tests/ArgumentParserTests.cs
index 42e7c36304..fa9a7cb165 100644
--- a/src/GitVersion.App.Tests/ArgumentParserTests.cs
+++ b/src/GitVersion.App.Tests/ArgumentParserTests.cs
@@ -220,7 +220,7 @@ public void WrongNumberOfArgumentsShouldThrow()
}
[TestCase("targetDirectoryPath -x logFilePath")]
- [TestCase("/invalid-argument")]
+ [TestCase("--invalid-argument")]
public void UnknownArgumentsShouldThrow(string arguments)
{
var exception = Assert.Throws(() => this.argumentParser.ParseArguments(arguments));
@@ -370,14 +370,14 @@ public void UpdateAssemblyInfoWithRelativeFilename()
[Test]
public void OverrideconfigWithNoOptions()
{
- var arguments = this.argumentParser.ParseArguments("/overrideconfig");
+ var arguments = this.argumentParser.ParseArguments("--override-config");
arguments.OverrideConfiguration.ShouldBeNull();
}
[TestCaseSource(nameof(OverrideconfigWithInvalidOptionTestData))]
public string OverrideconfigWithInvalidOption(string options)
{
- var exception = Assert.Throws(() => this.argumentParser.ParseArguments($"/overrideconfig {options}"));
+ var exception = Assert.Throws(() => this.argumentParser.ParseArguments($"--override-config {options}"));
exception.ShouldNotBeNull();
return exception.Message;
}
@@ -386,18 +386,18 @@ private static IEnumerable OverrideconfigWithInvalidOptionTestData
{
yield return new TestCaseData("tag-prefix=sample=asdf")
{
- ExpectedResult = "Could not parse /overrideconfig option: tag-prefix=sample=asdf. Ensure it is in format 'key=value'."
+ ExpectedResult = "Could not parse --override-config option: tag-prefix=sample=asdf. Ensure it is in format 'key=value'."
};
yield return new TestCaseData("unknown-option=25")
{
- ExpectedResult = "Could not parse /overrideconfig option: unknown-option=25. Unsupported 'key'."
+ ExpectedResult = "Could not parse --override-config option: unknown-option=25. Unsupported 'key'."
};
}
[TestCaseSource(nameof(OverrideConfigWithSingleOptionTestData))]
public void OverrideConfigWithSingleOptions(string options, IGitVersionConfiguration expected)
{
- var arguments = this.argumentParser.ParseArguments($"/overrideconfig {options}");
+ var arguments = this.argumentParser.ParseArguments($"--override-config {options}");
ConfigurationHelper configurationHelper = new(arguments.OverrideConfiguration);
configurationHelper.Configuration.ShouldBeEquivalentTo(expected);
@@ -551,7 +551,7 @@ public void OverrideConfigWithMultipleOptions(string options, IGitVersionConfigu
private static IEnumerable OverrideConfigWithMultipleOptionsTestData()
{
yield return new TestCaseData(
- "/overrideconfig tag-prefix=sample /overrideconfig assembly-versioning-scheme=MajorMinor",
+ "--override-config tag-prefix=sample --override-config assembly-versioning-scheme=MajorMinor",
new GitVersionConfiguration
{
TagPrefixPattern = "sample",
@@ -559,7 +559,7 @@ private static IEnumerable OverrideConfigWithMultipleOptionsTestDa
}
);
yield return new TestCaseData(
- "/overrideconfig tag-prefix=sample /overrideconfig assembly-versioning-format=\"{Major}.{Minor}.{Patch}.{env:CI_JOB_ID ?? 0}\"",
+ "--override-config tag-prefix=sample --override-config assembly-versioning-format=\"{Major}.{Minor}.{Patch}.{env:CI_JOB_ID ?? 0}\"",
new GitVersionConfiguration
{
TagPrefixPattern = "sample",
@@ -567,7 +567,7 @@ private static IEnumerable OverrideConfigWithMultipleOptionsTestDa
}
);
yield return new TestCaseData(
- "/overrideconfig tag-prefix=sample /overrideconfig assembly-versioning-format=\"{Major}.{Minor}.{Patch}.{env:CI_JOB_ID ?? 0}\" /overrideconfig update-build-number=true /overrideconfig assembly-versioning-scheme=MajorMinorPatchTag /overrideconfig mode=ContinuousDelivery /overrideconfig tag-pre-release-weight=4",
+ "--override-config tag-prefix=sample --override-config assembly-versioning-format=\"{Major}.{Minor}.{Patch}.{env:CI_JOB_ID ?? 0}\" --override-config update-build-number=true --override-config assembly-versioning-scheme=MajorMinorPatchTag --override-config mode=ContinuousDelivery --override-config tag-pre-release-weight=4",
new GitVersionConfiguration
{
TagPrefixPattern = "sample",
@@ -711,7 +711,7 @@ public void LogPathCanContainForwardSlash()
[Test]
public void BooleanArgumentHandling()
{
- var arguments = this.argumentParser.ParseArguments("/nofetch /updateassemblyinfo true");
+ var arguments = this.argumentParser.ParseArguments("--no-fetch --update-assembly-info true");
arguments.NoFetch.ShouldBe(true);
arguments.UpdateAssemblyInfo.ShouldBe(true);
}
diff --git a/src/GitVersion.App/ArgumentInterceptor.cs b/src/GitVersion.App/ArgumentInterceptor.cs
new file mode 100644
index 0000000000..b19888610a
--- /dev/null
+++ b/src/GitVersion.App/ArgumentInterceptor.cs
@@ -0,0 +1,232 @@
+using System.IO.Abstractions;
+using GitVersion.Agents;
+using GitVersion.Extensions;
+using GitVersion.FileSystemGlobbing;
+using GitVersion.Helpers;
+using GitVersion.Logging;
+using GitVersion.OutputVariables;
+using Spectre.Console.Cli;
+
+namespace GitVersion;
+
+///
+/// Interceptor to capture parsed arguments
+///
+internal class ArgumentInterceptor : ICommandInterceptor
+{
+ private readonly ParseResultStorage storage;
+ private readonly IEnvironment environment;
+ private readonly IFileSystem fileSystem;
+ private readonly ICurrentBuildAgent buildAgent;
+ private readonly IConsole console;
+ private readonly IGlobbingResolver globbingResolver;
+
+ public ArgumentInterceptor(ParseResultStorage storage, IEnvironment environment, IFileSystem fileSystem, ICurrentBuildAgent buildAgent, IConsole console, IGlobbingResolver globbingResolver)
+ {
+ this.storage = storage;
+ this.environment = environment;
+ this.fileSystem = fileSystem;
+ this.buildAgent = buildAgent;
+ this.console = console;
+ this.globbingResolver = globbingResolver;
+ }
+
+ public void Intercept(CommandContext context, CommandSettings settings)
+ {
+ if (settings is GitVersionSettings gitVersionSettings)
+ {
+ var arguments = ConvertToArguments(gitVersionSettings);
+ AddAuthentication(arguments);
+ ValidateAndProcessArguments(arguments);
+ this.storage.SetResult(arguments);
+ }
+ }
+
+ private void AddAuthentication(Arguments arguments)
+ {
+ var username = this.environment.GetEnvironmentVariable("GITVERSION_REMOTE_USERNAME");
+ if (!username.IsNullOrWhiteSpace())
+ {
+ arguments.Authentication.Username = username;
+ }
+
+ var password = this.environment.GetEnvironmentVariable("GITVERSION_REMOTE_PASSWORD");
+ if (!password.IsNullOrWhiteSpace())
+ {
+ arguments.Authentication.Password = password;
+ }
+ }
+
+ private void ValidateAndProcessArguments(Arguments arguments)
+ {
+ // Apply default output if none specified
+ if (arguments.Output.Count == 0)
+ {
+ arguments.Output.Add(OutputType.Json);
+ }
+
+ // Set default output file if file output is specified
+ if (arguments.Output.Contains(OutputType.File) && arguments.OutputFile == null)
+ {
+ arguments.OutputFile = "GitVersion.json";
+ }
+
+ // Apply build agent settings
+ arguments.NoFetch = arguments.NoFetch || this.buildAgent.PreventFetch();
+
+ // Validate configuration file
+ ValidateConfigurationFile(arguments);
+
+ // Process assembly info files
+ if (!arguments.EnsureAssemblyInfo)
+ {
+ arguments.UpdateAssemblyInfoFileName = ResolveFiles(arguments.TargetPath ?? SysEnv.CurrentDirectory, arguments.UpdateAssemblyInfoFileName).ToHashSet();
+ }
+ }
+
+ private void ValidateConfigurationFile(Arguments arguments)
+ {
+ if (arguments.ConfigurationFile.IsNullOrWhiteSpace()) return;
+
+ if (FileSystemHelper.Path.IsPathRooted(arguments.ConfigurationFile))
+ {
+ if (!this.fileSystem.File.Exists(arguments.ConfigurationFile))
+ throw new WarningException($"Could not find config file at '{arguments.ConfigurationFile}'");
+ arguments.ConfigurationFile = FileSystemHelper.Path.GetFullPath(arguments.ConfigurationFile);
+ }
+ else
+ {
+ var configFilePath = FileSystemHelper.Path.GetFullPath(FileSystemHelper.Path.Combine(arguments.TargetPath, arguments.ConfigurationFile));
+ if (!this.fileSystem.File.Exists(configFilePath))
+ throw new WarningException($"Could not find config file at '{configFilePath}'");
+ arguments.ConfigurationFile = configFilePath;
+ }
+ }
+
+ private IEnumerable ResolveFiles(string workingDirectory, ISet? assemblyInfoFiles)
+ {
+ if (assemblyInfoFiles == null || assemblyInfoFiles.Count == 0)
+ {
+ return [];
+ }
+
+ var stringList = new List();
+
+ foreach (var filePattern in assemblyInfoFiles)
+ {
+ if (FileSystemHelper.Path.IsPathRooted(filePattern))
+ {
+ stringList.Add(filePattern);
+ }
+ else
+ {
+ var searchRoot = FileSystemHelper.Path.GetFullPath(workingDirectory);
+ var matchingFiles = this.globbingResolver.Resolve(searchRoot, filePattern);
+ stringList.AddRange(matchingFiles);
+ }
+ }
+
+ return stringList;
+ }
+
+ private static Arguments ConvertToArguments(GitVersionSettings settings)
+ {
+ var arguments = new Arguments();
+
+ // Set target path - prioritize explicit targetpath option over positional argument
+ arguments.TargetPath = settings.TargetPathOption?.TrimEnd('/', '\\')
+ ?? settings.TargetPath?.TrimEnd('/', '\\')
+ ?? SysEnv.CurrentDirectory;
+
+ // Configuration options
+ arguments.ConfigurationFile = settings.ConfigurationFile;
+ arguments.ShowConfiguration = settings.ShowConfiguration;
+
+ // Handle override configuration
+ if (settings.OverrideConfiguration != null && settings.OverrideConfiguration.Any())
+ {
+ var parser = new OverrideConfigurationOptionParser();
+
+ foreach (var kvp in settings.OverrideConfiguration)
+ {
+ // Validate the key format - Spectre.Console.Cli should have already parsed key=value correctly
+ // but we still need to validate against supported properties
+ var keyValueOption = $"{kvp.Key}={kvp.Value}";
+
+ var optionKey = kvp.Key.ToLowerInvariant();
+ if (!OverrideConfigurationOptionParser.SupportedProperties.Contains(optionKey))
+ {
+ throw new WarningException($"Could not parse --override-config option: {keyValueOption}. Unsupported 'key'.");
+ }
+
+ parser.SetValue(optionKey, kvp.Value);
+ }
+
+ arguments.OverrideConfiguration = parser.GetOverrideConfiguration();
+ }
+ else
+ {
+ arguments.OverrideConfiguration = new Dictionary