diff --git a/src/GitVersionExe.Tests/ArgumentParserTests.cs b/src/GitVersionExe.Tests/ArgumentParserTests.cs index 0169bd2f59..6edcc218a0 100644 --- a/src/GitVersionExe.Tests/ArgumentParserTests.cs +++ b/src/GitVersionExe.Tests/ArgumentParserTests.cs @@ -1,244 +1,72 @@ using System; using System.Collections.Generic; +using System.Linq; +using CommandLine; using GitVersion; +using GitVersion.Options; using NUnit.Framework; using Shouldly; [TestFixture] public class ArgumentParserTests { - [Test] - public void Empty_means_use_current_directory() - { - var arguments = ArgumentParser.ParseArguments(""); - arguments.TargetPath.ShouldBe(Environment.CurrentDirectory); - arguments.LogFilePath.ShouldBe(null); - arguments.IsHelp.ShouldBe(false); - } - - [Test] - public void Single_means_use_as_target_directory() - { - var arguments = ArgumentParser.ParseArguments("path"); - arguments.TargetPath.ShouldBe("path"); - arguments.LogFilePath.ShouldBe(null); - arguments.IsHelp.ShouldBe(false); - } - - [Test] - public void No_path_and_logfile_should_use_current_directory_TargetDirectory() - { - var arguments = ArgumentParser.ParseArguments("-l logFilePath"); - arguments.TargetPath.ShouldBe(Environment.CurrentDirectory); - arguments.LogFilePath.ShouldBe("logFilePath"); - arguments.IsHelp.ShouldBe(false); - } - - [Test] - public void h_means_IsHelp() + [TestCaseSource("AllVerbs")] + public void PrintVerbHelp(string verb) { - var arguments = ArgumentParser.ParseArguments("-h"); - Assert.IsNull(arguments.TargetPath); - Assert.IsNull(arguments.LogFilePath); - arguments.IsHelp.ShouldBe(true); + Parser.Default.ParseArguments(new[] {"help", verb}, AllOptionTypes().ToArray()); } - [Test] - public void exec() + IEnumerable AllVerbs() { - var arguments = ArgumentParser.ParseArguments("-exec rake"); - arguments.Exec.ShouldBe("rake"); + return AllOptionTypes() + .Select(t => (VerbAttribute) Attribute.GetCustomAttribute(t, typeof(VerbAttribute))) + .Where(a => a != null).Select(a => a.Name); } - [Test] - public void exec_with_args() + IEnumerable AllOptionTypes() { - var arguments = ArgumentParser.ParseArguments(new List - { - "-exec", - "rake", - "-execargs", - "clean build" - }); - arguments.Exec.ShouldBe("rake"); - arguments.ExecArgs.ShouldBe("clean build"); + yield return typeof(InspectOptions); + yield return typeof(InitOptions); + yield return typeof(InspectRemoteRepositoryOptions); + yield return typeof(InjectBuildServerOptions); + yield return typeof(InjectMsBuildOptions); + yield return typeof(InjectProcess); + yield return typeof(InjectAssemblyInfo); } [Test] - public void msbuild() + public void InputVariablesMustHaveCorrectDefaultValues() { - var arguments = ArgumentParser.ParseArguments("-proj msbuild.proj"); - arguments.Proj.ShouldBe("msbuild.proj"); - } + var iv = new InputVariables(); - [Test] - public void msbuild_with_args() - { - var arguments = ArgumentParser.ParseArguments(new List - { - "-proj", - "msbuild.proj", - "-projargs", - "/p:Configuration=Debug /p:Platform=AnyCPU" - }); - arguments.Proj.ShouldBe("msbuild.proj"); - arguments.ProjArgs.ShouldBe("/p:Configuration=Debug /p:Platform=AnyCPU"); - } + iv.TargetUrl.ShouldBe(null); - [Test] - public void execwith_targetdirectory() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -exec rake"); - arguments.TargetPath.ShouldBe("targetDirectoryPath"); - arguments.Exec.ShouldBe("rake"); - } + iv.DynamicRepositoryLocation.ShouldBe(null); - [Test] - public void TargetDirectory_and_LogFilePath_can_be_parsed() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -l logFilePath"); - arguments.TargetPath.ShouldBe("targetDirectoryPath"); - arguments.LogFilePath.ShouldBe("logFilePath"); - arguments.IsHelp.ShouldBe(false); - } + iv.Authentication.ShouldNotBe(null); - [Test] - public void Username_and_Password_can_be_parsed() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -u [username] -p [password]"); - arguments.TargetPath.ShouldBe("targetDirectoryPath"); - arguments.Authentication.Username.ShouldBe("[username]"); - arguments.Authentication.Password.ShouldBe("[password]"); - arguments.IsHelp.ShouldBe(false); - } + var defaultAuthentication = new Authentication(); + iv.Authentication.Username.ShouldBeSameAs(defaultAuthentication.Username); + iv.Authentication.Password.ShouldBeSameAs(defaultAuthentication.Password); - [Test] - public void Unknown_output_should_throw() - { - var exception = Assert.Throws(() => ArgumentParser.ParseArguments("targetDirectoryPath -output invalid_value")); - exception.Message.ShouldBe("Value 'invalid_value' cannot be parsed as output type, please use 'json' or 'buildserver'"); - } + iv.TargetUrl.ShouldBe(null); - [Test] - public void Output_defaults_to_json() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath"); - arguments.Output.ShouldBe(OutputType.Json); - } + iv.TargetBranch.ShouldBe(null); - [Test] - public void Output_json_can_be_parsed() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -output json"); - arguments.Output.ShouldBe(OutputType.Json); - } + iv.NoFetch.ShouldBe(true); - [Test] - public void Output_buildserver_can_be_parsed() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -output buildserver"); - arguments.Output.ShouldBe(OutputType.BuildServer); + iv.TargetPath.ShouldBe(Environment.CurrentDirectory); } + [Explicit] [Test] - public void MultipleArgsAndFlag() + public void PrintEntireHelp() { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -output buildserver -updateAssemblyInfo"); - arguments.Output.ShouldBe(OutputType.BuildServer); - } - - [Test] - public void Url_and_BranchName_can_be_parsed() - { - var arguments = ArgumentParser.ParseArguments("targetDirectoryPath -url http://github.com/Particular/GitVersion.git -b somebranch"); - arguments.TargetPath.ShouldBe("targetDirectoryPath"); - arguments.TargetUrl.ShouldBe("http://github.com/Particular/GitVersion.git"); - arguments.TargetBranch.ShouldBe("somebranch"); - arguments.IsHelp.ShouldBe(false); - } - - [Test] - public void Wrong_number_of_arguments_should_throw() - { - var exception = Assert.Throws(() => ArgumentParser.ParseArguments("targetDirectoryPath -l logFilePath extraArg")); - exception.Message.ShouldBe("Could not parse command line parameter 'extraArg'."); - } - - [Test] - public void Unknown_argument_should_throw() - { - var exception = Assert.Throws(() => ArgumentParser.ParseArguments("targetDirectoryPath -x logFilePath")); - exception.Message.ShouldBe("Could not parse command line parameter '-x'."); - } - - [TestCase("-updateAssemblyInfo true")] - [TestCase("-updateAssemblyInfo 1")] - [TestCase("-updateAssemblyInfo")] - [TestCase("-updateAssemblyInfo -proj foo.sln")] - public void update_assembly_info_true(string command) - { - var arguments = ArgumentParser.ParseArguments(command); - arguments.UpdateAssemblyInfo.ShouldBe(true); - } - - [TestCase("-updateAssemblyInfo false")] - [TestCase("-updateAssemblyInfo 0")] - public void update_assembly_info_false(string command) - { - var arguments = ArgumentParser.ParseArguments(command); - arguments.UpdateAssemblyInfo.ShouldBe(false); - } - - [Test] - public void update_assembly_info_with_filename() - { - var arguments = ArgumentParser.ParseArguments("-updateAssemblyInfo CommonAssemblyInfo.cs"); - arguments.UpdateAssemblyInfo.ShouldBe(true); - arguments.UpdateAssemblyInfoFileName.ShouldBe("CommonAssemblyInfo.cs"); - } - - [Test] - public void update_assembly_info_with_relative_filename() - { - var arguments = ArgumentParser.ParseArguments("-updateAssemblyInfo ..\\..\\CommonAssemblyInfo.cs"); - arguments.UpdateAssemblyInfo.ShouldBe(true); - arguments.UpdateAssemblyInfoFileName.ShouldBe("..\\..\\CommonAssemblyInfo.cs"); - } - - [Test] - public void dynamicRepoLocation() - { - var arguments = ArgumentParser.ParseArguments("-dynamicRepoLocation c:\\foo\\"); - arguments.DynamicRepositoryLocation.ShouldBe("c:\\foo\\"); - } - - [Test] - public void can_log_to_console() - { - var arguments = ArgumentParser.ParseArguments("-l console -proj foo.sln"); - arguments.LogFilePath.ShouldBe("console"); - } - - [Test] - public void nofetch_true_when_defined() - { - var arguments = ArgumentParser.ParseArguments("-nofetch"); - arguments.NoFetch = true; - } - - [Test] - public void other_arguments_can_be_parsed_before_nofetch() - { - var arguments = ArgumentParser.ParseArguments("targetpath -nofetch "); - arguments.TargetPath = "targetpath"; - arguments.NoFetch = true; + Parser.Default.ParseArguments(new[] {"help"}, AllOptionTypes().ToArray()); + foreach (var verb in AllVerbs()) + { + PrintVerbHelp(verb); + } } - [Test] - public void other_arguments_can_be_parsed_after_nofetch() - { - var arguments = ArgumentParser.ParseArguments("-nofetch -proj foo.sln"); - arguments.NoFetch = true; - arguments.Proj = "foo.sln"; - } } \ No newline at end of file diff --git a/src/GitVersionExe.Tests/GitVersionExe.Tests.csproj b/src/GitVersionExe.Tests/GitVersionExe.Tests.csproj index d54c851fd4..73aa80b33b 100644 --- a/src/GitVersionExe.Tests/GitVersionExe.Tests.csproj +++ b/src/GitVersionExe.Tests/GitVersionExe.Tests.csproj @@ -45,6 +45,10 @@ ..\packages\ApprovalUtilities.3.0.8\lib\net45\ApprovalUtilities.Net45.dll + + ..\packages\CommandLineParser.2.0.251-beta\lib\net45\CommandLine.dll + True + ..\packages\LibGit2Sharp.0.21.0.176\lib\net40\LibGit2Sharp.dll True diff --git a/src/GitVersionExe.Tests/packages.config b/src/GitVersionExe.Tests/packages.config index aa71fbaa59..32ee171c8d 100644 --- a/src/GitVersionExe.Tests/packages.config +++ b/src/GitVersionExe.Tests/packages.config @@ -2,6 +2,7 @@ + diff --git a/src/GitVersionExe/ArgumentParser.cs b/src/GitVersionExe/ArgumentParser.cs deleted file mode 100644 index 620f543570..0000000000 --- a/src/GitVersionExe/ArgumentParser.cs +++ /dev/null @@ -1,308 +0,0 @@ -namespace GitVersion -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Linq; - using System.Text.RegularExpressions; - - - public class ArgumentParser - { - public static Arguments ParseArguments(string commandLineArguments) - { - return ParseArguments(commandLineArguments.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList()); - } - - public static Arguments ParseArguments(List commandLineArguments) - { - if (commandLineArguments.Count == 0) - { - return new Arguments - { - TargetPath = Environment.CurrentDirectory - }; - } - - var firstArgument = commandLineArguments.First(); - if (IsHelp(firstArgument)) - { - return new Arguments - { - IsHelp = true - }; - } - if (IsInit(firstArgument)) - { - return new Arguments - { - TargetPath = Environment.CurrentDirectory, - Init = true - }; - } - - if (commandLineArguments.Count == 1 && !(commandLineArguments[0].StartsWith("-") || commandLineArguments[0].StartsWith("/"))) - { - return new Arguments - { - TargetPath = firstArgument - }; - } - - List namedArguments; - var arguments = new Arguments(); - if (firstArgument.StartsWith("-") || firstArgument.StartsWith("/")) - { - arguments.TargetPath = Environment.CurrentDirectory; - namedArguments = commandLineArguments; - } - else - { - arguments.TargetPath = firstArgument; - namedArguments = commandLineArguments.Skip(1).ToList(); - } - - var args = CollectSwitchesAndValuesFromArguments(namedArguments); - - foreach (var name in args.AllKeys) - { - var values = args.GetValues(name); - - string value = null; - - if (values != null) - { - //Currently, no arguments use more than one value, so having multiple values is an input error. - //In the future, this exception can be removed to support multiple values for a switch. - if (values.Length > 1) throw new WarningException(string.Format("Could not parse command line parameter '{0}'.", values[1])); - - value = values.FirstOrDefault(); - } - - if (IsSwitch("l", name)) - { - arguments.LogFilePath = value; - continue; - } - - if (IsSwitch("targetpath", name)) - { - arguments.TargetPath = value; - continue; - } - - if (IsSwitch("dynamicRepoLocation", name)) - { - arguments.DynamicRepositoryLocation = value; - continue; - } - - if (IsSwitch("url", name)) - { - arguments.TargetUrl = value; - continue; - } - - if (IsSwitch("b", name)) - { - arguments.TargetBranch = value; - continue; - } - - if (IsSwitch("u", name)) - { - arguments.Authentication.Username = value; - continue; - } - - if (IsSwitch("p", name)) - { - arguments.Authentication.Password = value; - continue; - } - - if (IsSwitch("c", name)) - { - arguments.CommitId = value; - continue; - } - - if (IsSwitch("exec", name)) - { - arguments.Exec = value; - continue; - } - - if (IsSwitch("execargs", name)) - { - arguments.ExecArgs = value; - continue; - } - - if (IsSwitch("proj", name)) - { - arguments.Proj = value; - continue; - } - - if (IsSwitch("projargs", name)) - { - arguments.ProjArgs = value; - continue; - } - - if (IsSwitch("updateAssemblyInfo", name)) - { - if (new[] { "1", "true" }.Contains(value, StringComparer.OrdinalIgnoreCase)) - { - arguments.UpdateAssemblyInfo = true; - } - else if (new[] { "0", "false" }.Contains(value, StringComparer.OrdinalIgnoreCase)) - { - arguments.UpdateAssemblyInfo = false; - } - else if (!IsSwitchArgument(value)) - { - arguments.UpdateAssemblyInfo = true; - arguments.UpdateAssemblyInfoFileName = value; - } - else - { - arguments.UpdateAssemblyInfo = true; - } - continue; - } - - if (IsSwitch("assemblyversionformat", name)) - { - throw new WarningException("assemblyversionformat switch removed, use AssemblyVersioningScheme configuration value instead"); - } - - if (IsSwitch("v", name) || IsSwitch("showvariable", name)) - { - string versionVariable = null; - - if (!string.IsNullOrWhiteSpace(value)) - { - versionVariable = VersionVariables.AvailableVariables.SingleOrDefault(av => av.Equals(value.Replace("'", ""), StringComparison.CurrentCultureIgnoreCase)); - } - - if (versionVariable == null) - { - var messageFormat = "{0} requires a valid version variable. Available variables are:\n{1}"; - var message = string.Format(messageFormat, name, String.Join(", ", VersionVariables.AvailableVariables.Select(x=>string.Concat("'", x, "'")))); - throw new WarningException(message); - } - - arguments.ShowVariable = versionVariable; - continue; - } - - if (IsSwitch("showConfig", name)) - { - if (new[] { "1", "true" }.Contains(value, StringComparer.OrdinalIgnoreCase)) - { - arguments.ShowConfig = true; - } - else if (new[] { "0", "false" }.Contains(value, StringComparer.OrdinalIgnoreCase)) - { - arguments.UpdateAssemblyInfo = false; - } - else - { - arguments.ShowConfig = true; - } - continue; - } - - if (IsSwitch("output", name)) - { - OutputType outputType; - if (!Enum.TryParse(value, true, out outputType)) - { - throw new WarningException(string.Format("Value '{0}' cannot be parsed as output type, please use 'json' or 'buildserver'", value)); - } - - arguments.Output = outputType; - continue; - } - - if (IsSwitch("nofetch", name)) - { - arguments.NoFetch = true; - continue; - } - - throw new WarningException(string.Format("Could not parse command line parameter '{0}'.", name)); - } - - return arguments; - } - - static NameValueCollection CollectSwitchesAndValuesFromArguments(List namedArguments) - { - var args = new NameValueCollection(); - - string currentKey = null; - for (var index = 0; index < namedArguments.Count; index = index + 1) - { - var arg = namedArguments[index]; - //If this is a switch, create new name/value entry for it, with a null value. - if (IsSwitchArgument(arg)) - { - currentKey = arg; - args.Add(currentKey, null); - } - //If this is a value (not a switch) - else - { - //And if the current switch does not have a value yet, set it's value to this argument. - if (String.IsNullOrEmpty(args[currentKey])) - { - args[currentKey] = arg; - } - //Otherwise add the value under the same switch. - else - { - args.Add(currentKey, arg); - } - } - } - return args; - } - - static bool IsSwitchArgument(string value) - { - return value != null && (value.StartsWith("-") || value.StartsWith("/")) - && !Regex.Match(value, @"/\w+:").Success; //Exclude msbuild & project parameters in form /blah:, which should be parsed as values, not switch names. - } - - static bool IsSwitch(string switchName, string value) - { - if (value.StartsWith("-")) - { - value = value.Remove(0, 1); - } - - if (value.StartsWith("/")) - { - value = value.Remove(0, 1); - } - - return (string.Equals(switchName, value, StringComparison.OrdinalIgnoreCase)); - } - - static bool IsInit(string singleArgument) - { - return singleArgument.Equals("init", StringComparison.OrdinalIgnoreCase); - } - - static bool IsHelp(string singleArgument) - { - return (singleArgument == "?") || - IsSwitch("h", singleArgument) || - IsSwitch("help", singleArgument) || - IsSwitch("?", singleArgument); - } - } -} \ No newline at end of file diff --git a/src/GitVersionExe/AssemblyInfo.cs b/src/GitVersionExe/AssemblyInfo.cs index 03d10be69b..30f6667c7d 100644 --- a/src/GitVersionExe/AssemblyInfo.cs +++ b/src/GitVersionExe/AssemblyInfo.cs @@ -8,3 +8,4 @@ [assembly: InternalsVisibleTo("GitVersionTask.Tests")] [assembly: InternalsVisibleTo("AcceptanceTests")] [assembly: InternalsVisibleTo("GitVersionExe.Tests")] +[assembly: AssemblyCopyrightAttribute("GitTools")] diff --git a/src/GitVersionExe/GitVersionExe.csproj b/src/GitVersionExe/GitVersionExe.csproj index 95f2060c55..a888b0ce43 100644 --- a/src/GitVersionExe/GitVersionExe.csproj +++ b/src/GitVersionExe/GitVersionExe.csproj @@ -39,6 +39,10 @@ bin\Release\GitVersion.xml + + ..\packages\CommandLineParser.2.0.251-beta\lib\net40\CommandLine.dll + True + ..\packages\JetBrainsAnnotations.Fody.1.0.4.0\Lib\JetBrains.Annotations.dll False @@ -57,13 +61,23 @@ - + + + + + + + + + + + @@ -101,6 +115,7 @@ GitVersionCore + diff --git a/src/GitVersionExe/Options/InitOptions.cs b/src/GitVersionExe/Options/InitOptions.cs new file mode 100644 index 0000000000..bfa2858363 --- /dev/null +++ b/src/GitVersionExe/Options/InitOptions.cs @@ -0,0 +1,14 @@ +namespace GitVersion.Options +{ + using CommandLine; + + [Verb("init", + HelpText = "Start configuration utility for gitversion.")] + class InitOptions : LoggingOptions + { + [Option('p', "path", + HelpText = "The path to inspect, defaults to current directory." + )] + public string Path { get; set; } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Options/InjectAssemblyInfo.cs b/src/GitVersionExe/Options/InjectAssemblyInfo.cs new file mode 100644 index 0000000000..52d8ecb0c7 --- /dev/null +++ b/src/GitVersionExe/Options/InjectAssemblyInfo.cs @@ -0,0 +1,30 @@ +namespace GitVersion.Options +{ + using System.Collections.Generic; + using CommandLine; + using CommandLine.Text; + + [Verb("inject-assembly-info", + HelpText = "Search for all assembly information files in the git repo and update them using GitVersion variables.")] + class InjectAssemblyInfo : LoggingOptions + { + [Option('f', "filename", + HelpText = "Assembly information filename", Default = "AssemblyInfo.cs")] + public string AssemblyInformationFileName { get; set; } + + [Option('p', "path", + HelpText = "The path to inspect, defaults to current directory." + )] + public string Path { get; set; } + + [Usage(ApplicationAlias = "GitVersion")] + public static IEnumerable Examples + { + get + { + yield return new Example("Search all AssemblyInfo.cs and update with GitVersion variable information", new InjectAssemblyInfo()); + } + } + + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Options/InjectBuildServerOptions.cs b/src/GitVersionExe/Options/InjectBuildServerOptions.cs new file mode 100644 index 0000000000..cd1954cb01 --- /dev/null +++ b/src/GitVersionExe/Options/InjectBuildServerOptions.cs @@ -0,0 +1,20 @@ +namespace GitVersion.Options +{ + using System.Collections.Generic; + using CommandLine; + using CommandLine.Text; + + [Verb("inject-buildserver", + HelpText = "Inject gitversion variables as environment variables in your build server job.")] + class InjectBuildServerOptions : LoggingOptions + { + [Usage(ApplicationAlias = "GitVersion")] + public static IEnumerable Examples + { + get + { + yield return new Example("Normal scenario, will detect build server automatically", new InjectBuildServerOptions()); + } + } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Options/InjectMsBuildOptions.cs b/src/GitVersionExe/Options/InjectMsBuildOptions.cs new file mode 100644 index 0000000000..21bf34b931 --- /dev/null +++ b/src/GitVersionExe/Options/InjectMsBuildOptions.cs @@ -0,0 +1,24 @@ +namespace GitVersion.Options +{ + using System.Collections.Generic; + using CommandLine; + using CommandLine.Text; + + [Verb("inject-msbuild", + HelpText = "Build an msbuild file, GitVersion variables will be injected as msbuild properties.")] + class InjectMsBuildOptions : LoggingOptions + { + [Option('f',"filename", HelpText = "MS build file to build.")] + public string BuildFileName { get; set; } + + [Usage(ApplicationAlias = "GitVersion")] + public static IEnumerable Examples + { + get + { + yield return new Example("Build msbuild file", new InjectMsBuildOptions { BuildFileName = "GitVersion.sln" }); + } + } + + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Options/InjectProcess.cs b/src/GitVersionExe/Options/InjectProcess.cs new file mode 100644 index 0000000000..82041c907e --- /dev/null +++ b/src/GitVersionExe/Options/InjectProcess.cs @@ -0,0 +1,34 @@ +namespace GitVersion.Options +{ + using System.Collections.Generic; + using CommandLine; + using CommandLine.Text; + + [Verb("inject-process", + HelpText = "Executes target executable injecting GitVersion variables as environmental variables.")] + class InjectProcess : LoggingOptions + { + [Option('e', "executable", HelpText = "Path to executable filename.", Required = true)] + public string ExecutableFileName { get; set; } + + [Option('a', "arguments")] + public string Arguments { get; set; } + + [Option('v', "variables", HelpText = "Variables to inject, defaults to all.")] + public IEnumerable Variables { get; set; } + + [Usage(ApplicationAlias = "GitVersion")] + public static IEnumerable Examples + { + get + { + yield return new Example("Inject all gitversion variables into MyApp", new InjectProcess { ExecutableFileName = "MyApp.exe" }); + yield return new Example("Inject only SemVer variable into MyApp", + new InjectProcess { ExecutableFileName = "MyApp.exe", Variables = new[] {"SemVer"}}); + yield return new Example("Start MyApp with --verbose and --short argument injecting all GitVersion variables", + new InjectProcess { ExecutableFileName = "MyApp.exe", Arguments = "--verbose --short" }); + } + } + + } +} diff --git a/src/GitVersionExe/Options/InspectOptions.cs b/src/GitVersionExe/Options/InspectOptions.cs new file mode 100644 index 0000000000..110584011f --- /dev/null +++ b/src/GitVersionExe/Options/InspectOptions.cs @@ -0,0 +1,38 @@ +namespace GitVersion.Options +{ + using System.Collections.Generic; + using CommandLine; + using CommandLine.Text; + + [Verb("inspect", + HelpText = "Inspect git repository and output deduced version information.")] + class InspectOptions : LoggingOptions + { + [Option('p', "path", + HelpText = "The path to inspect, defaults to current directory." + )] + public string Path { get; set; } + + [Option('f', "format", + HelpText = "The output format (Json, KeyValue or Values).", + Default = "Json" + )] + public string Output { get; set; } + + [Option('v', "variables")] + public IEnumerable Variables { get; set; } + + [Usage(ApplicationAlias = "GitVersion")] + public static IEnumerable Examples + { + get + { + yield return new Example("Inspect the current directory, output version variables in Json format", new InspectOptions()); + yield return new Example("Inspect different directory", new InspectOptions { Path = @"c:\foo\bar\" }); + yield return new Example("Show only some variables", new InspectOptions { Variables = new[] {"SemVer", "Major", "Minor"} }); + yield return new Example("Output in key=value format, each pair on a new line", new InspectOptions { Output = "KeyValue" }); + yield return new Example("Show only one variable's value", UnParserSettings.WithGroupSwitchesOnly(), new InspectOptions { Output = "Values", Variables = new[] {"SemVer"} }); + } + } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Options/InspectRemoteRepositoryOptions.cs b/src/GitVersionExe/Options/InspectRemoteRepositoryOptions.cs new file mode 100644 index 0000000000..1deb69758c --- /dev/null +++ b/src/GitVersionExe/Options/InspectRemoteRepositoryOptions.cs @@ -0,0 +1,56 @@ +namespace GitVersion.Options +{ + using System.Collections.Generic; + using CommandLine; + using CommandLine.Text; + + [Verb("inspect-remote", + HelpText = "Inspect a remote repository.")] + class InspectRemoteRepositoryOptions : LoggingOptions + { + [Option('f', "format", + HelpText = "The output format (Json, KeyValue or Values).", + Default = "Json" + )] + public string Output { get; set; } + + [Option('v', "variables")] + public IEnumerable Variables { get; set; } + + [Option("url", Required = true, + HelpText = "Url to remote git repository.")] + public string Url { get; set; } + + [Option('b', "branch", + HelpText = "Name of the branch on the remote repository.")] + string Branch { get; set; } + + [Option('u', "username", + HelpText = "Username in case authentication is required.")] + public string UserName { get; set; } + + [Option("password", + HelpText = "Password in case authentication is required.")] + public string Password { get; set; } + + [Option('c', "commit", + HelpText = "The commit id to check. If not specified, the latest available commit on the specified branch will be used.")] + public string CommitId { get; set; } + + [Option(HelpText = "Target directory to clone to.", Default = "%tmp%")] + public string DynamicRepositoryLocation { get; set; } + + [Usage(ApplicationAlias = "GitVersion")] + public static IEnumerable RemoteExamples + { + get + { + yield return new Example("Inspect GitVersion's remote repositsory ", + new InspectRemoteRepositoryOptions + { + Url = "https://github.com/GitTools/GitVersion.git" + }); + } + } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Options/LoggingOptions.cs b/src/GitVersionExe/Options/LoggingOptions.cs new file mode 100644 index 0000000000..92446d0bf5 --- /dev/null +++ b/src/GitVersionExe/Options/LoggingOptions.cs @@ -0,0 +1,15 @@ +namespace GitVersion.Options +{ + using CommandLine; + + class LoggingOptions + { + [Option( + HelpText = "Prints all system messages to standard output.")] + public bool Verbose { get; set; } + + [Option( + HelpText = "Specify log file for system messages.")] + public string Log { get; set; } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Program.cs b/src/GitVersionExe/Program.cs index d6a20c44a9..7fb41d9e01 100644 --- a/src/GitVersionExe/Program.cs +++ b/src/GitVersionExe/Program.cs @@ -6,7 +6,9 @@ namespace GitVersion using System.IO; using System.Linq; using System.Text; - using GitVersion.Helpers; + using CommandLine; + using GitVersion.Options; + using GitVersion.Runners; class Program { @@ -16,15 +18,14 @@ static void Main() { var exitCode = VerifyArgumentsAndRun(); - if (Debugger.IsAttached) + if (exitCode != 0) { - Console.ReadKey(); + Console.Write(log.ToString()); } - if (exitCode != 0) + if (Debugger.IsAttached) { - // Dump log to console if we fail to complete successfully - Console.Write(log.ToString()); + Console.ReadKey(); } Environment.Exit(exitCode); @@ -32,93 +33,57 @@ static void Main() static int VerifyArgumentsAndRun() { - Arguments arguments = null; + var args = GetArgumentsWithoutExeName(); try - { - var fileSystem = new FileSystem(); - - var argumentsWithoutExeName = GetArgumentsWithoutExeName(); - try - { - arguments = ArgumentParser.ParseArguments(argumentsWithoutExeName); - } - catch (WarningException ex) - { - Console.WriteLine("Failed to parse arguments: {0}", string.Join(" ", argumentsWithoutExeName)); - if (!string.IsNullOrWhiteSpace(ex.Message)) - { - Console.WriteLine(); - Console.WriteLine(ex.Message); - Console.WriteLine(); - } - - HelpWriter.Write(); - return 1; - } - catch (Exception) - { - Console.WriteLine("Failed to parse arguments: {0}", string.Join(" ", argumentsWithoutExeName)); - - HelpWriter.Write(); - return 1; - } - if (arguments.IsHelp) - { - HelpWriter.Write(); - return 0; - } - - ConfigureLogging(arguments); - if (arguments.Init) - { - ConfigurationProvider.Init(arguments.TargetPath, fileSystem, new ConsoleAdapter()); - return 0; - } - if (arguments.ShowConfig) - { - Console.WriteLine(ConfigurationProvider.GetEffectiveConfigAsString(arguments.TargetPath, fileSystem)); - return 0; - } - - if (!string.IsNullOrEmpty(arguments.Proj) || !string.IsNullOrEmpty(arguments.Exec)) - { - arguments.Output = OutputType.BuildServer; - } - - Logger.WriteInfo("Working directory: " + arguments.TargetPath); - - SpecifiedArgumentRunner.Run(arguments, fileSystem); + { + Parser.Default.ParseArguments(args) + .WithParsed(InspectRunner.Run) + .WithParsed(InitRunner.Run) + //.WithParsed(Runner.Run) + .WithParsed(InjectBuildServerRunner.Run) + //.WithParsed(Runner.Run) + //.WithParsed(Runner.Run) + //.WithParsed(Runner.Run) + .WithNotParsed(HandleParseErrors); + + return 0; } - catch (WarningException exception) + catch (Exception e) { - var error = string.Format("An error occurred:\r\n{0}", exception.Message); - Logger.WriteWarning(error); + Console.WriteLine(e); return 1; } - catch (Exception exception) - { - var error = string.Format("An unexpected error occurred:\r\n{0}", exception); - Logger.WriteError(error); + } - if (arguments != null) - { - Logger.WriteInfo(string.Empty); - Logger.WriteInfo("Here is the current git graph (please include in issue): "); - Logger.WriteInfo("Showing max of 100 commits"); - LibGitExtensions.DumpGraph(arguments.TargetPath, Logger.WriteInfo, 100); - } - return 1; - } + static void HandleParseErrors(IEnumerable commandLineErrors) + { + var message = commandLineErrors.Aggregate("Error parsing arguments ...", + (current, err) => current + ("\nFailed to parse - " + err)); + throw new WarningException(message); + } - return 0; + static string[] GetArgumentsWithoutExeName() + { + return Environment.GetCommandLineArgs() + .Skip(1) + .ToArray(); } + + // Logging stuf + static void ConfigureLogging(Arguments arguments) { var writeActions = new List> - { - s => log.AppendLine(s) - }; + { + s => log.AppendLine(s) + }; if (arguments.Output == OutputType.BuildServer || arguments.LogFilePath == "console" || arguments.Init) { @@ -132,7 +97,9 @@ static void ConfigureLogging(Arguments arguments) Directory.CreateDirectory(Path.GetDirectoryName(arguments.LogFilePath)); if (File.Exists(arguments.LogFilePath)) { - using (File.CreateText(arguments.LogFilePath)) { } + using (File.CreateText(arguments.LogFilePath)) + { + } } writeActions.Add(x => WriteLogEntry(arguments, x)); @@ -154,12 +121,5 @@ static void WriteLogEntry(Arguments arguments, string s) var contents = string.Format("{0}\t\t{1}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), s); File.AppendAllText(arguments.LogFilePath, contents); } - - static List GetArgumentsWithoutExeName() - { - return Environment.GetCommandLineArgs() - .Skip(1) - .ToList(); - } } } \ No newline at end of file diff --git a/src/GitVersionExe/Runners/InitRunner.cs b/src/GitVersionExe/Runners/InitRunner.cs new file mode 100644 index 0000000000..6e62517d18 --- /dev/null +++ b/src/GitVersionExe/Runners/InitRunner.cs @@ -0,0 +1,14 @@ +namespace GitVersion.Runners +{ + using GitVersion.Helpers; + using GitVersion.Options; + + class InitRunner + { + public static void Run(InitOptions opts) + { + var fs = new FileSystem(); + ConfigurationProvider.Init(opts.Path, fs, new ConsoleAdapter()); + } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Runners/InjectBuildServerRunner.cs b/src/GitVersionExe/Runners/InjectBuildServerRunner.cs new file mode 100644 index 0000000000..7c2fcaf7d0 --- /dev/null +++ b/src/GitVersionExe/Runners/InjectBuildServerRunner.cs @@ -0,0 +1,21 @@ +namespace GitVersion.Runners +{ + using System; + using GitVersion.Helpers; + using GitVersion.Options; + + class InjectBuildServerRunner + { + public static void Run(InjectBuildServerOptions opts) + { + var inputVariables = new InputVariables(); // TODO: how to map to input variables + var fs = new FileSystem(); + var variables = SpecifiedArgumentRunner.GetVariables(fs, inputVariables); + + foreach (var buildServer in BuildServerList.GetApplicableBuildServers()) + { + buildServer.WriteIntegration(Console.WriteLine, variables); + } + } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/Runners/InspectRunner.cs b/src/GitVersionExe/Runners/InspectRunner.cs new file mode 100644 index 0000000000..c8a27a7ba9 --- /dev/null +++ b/src/GitVersionExe/Runners/InspectRunner.cs @@ -0,0 +1,41 @@ +namespace GitVersion.Runners +{ + using System; + using System.Linq; + using GitVersion.Helpers; + using GitVersion.Options; + + class InspectRunner + { + public static void Run(InspectOptions opts) + { + var inputVariables = new InputVariables() + { + TargetPath = opts.Path, + }; + + var fs = new FileSystem(); + var allVariables = SpecifiedArgumentRunner.GetVariables(fs, inputVariables); + + // TODO: allow more variables + var showVariable = opts.Variables.First(); + + switch (showVariable) + { + case null: + // TODO: allow more output formatters + Console.WriteLine(JsonOutputFormatter.ToJson(allVariables)); + break; + + default: + string part; + if (!allVariables.TryGetValue(showVariable, out part)) + { + throw new WarningException(string.Format("'{0}' variable does not exist", showVariable)); + } + Console.WriteLine(part); + break; + } + } + } +} \ No newline at end of file diff --git a/src/GitVersionExe/SpecifiedArgumentRunner.cs b/src/GitVersionExe/SpecifiedArgumentRunner.cs index 30324e4aae..05d3d3eee1 100644 --- a/src/GitVersionExe/SpecifiedArgumentRunner.cs +++ b/src/GitVersionExe/SpecifiedArgumentRunner.cs @@ -5,10 +5,51 @@ namespace GitVersion using System.Linq; using GitVersion.Helpers; + public class InputVariables + { + public InputVariables() + { + Authentication = new Authentication(); + NoFetch = true; + } + + public string TargetUrl { get; set; } + public string DynamicRepositoryLocation { get; set; } + public Authentication Authentication { get; set; } + public string TargetBranch { get; set; } + public bool NoFetch { get; set; } + public string TargetPath { get; set; } + public string CommitId { get; set; } + } + class SpecifiedArgumentRunner { const string MsBuild = @"c:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe"; + public static VersionVariables GetVariables(IFileSystem fileSystem, InputVariables inputVariables) + { + return GetVariables(fileSystem, + inputVariables.TargetUrl, + inputVariables.DynamicRepositoryLocation, + inputVariables.Authentication, + inputVariables.TargetBranch, + inputVariables.NoFetch, + inputVariables.TargetPath, + inputVariables.CommitId); + } + + private static VersionVariables GetVariables(IFileSystem fileSystem, + string targetUrl, + string dynamicRepositoryLocation, + Authentication authentication, + string targetBranch, + bool noFetch, + string targetPath, + string commitId) + { + return ExecuteCore.ExecuteGitVersion(fileSystem, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId); + } + public static void Run(Arguments arguments, IFileSystem fileSystem) { var noFetch = arguments.NoFetch; @@ -19,34 +60,7 @@ public static void Run(Arguments arguments, IFileSystem fileSystem) var targetBranch = arguments.TargetBranch; var commitId = arguments.CommitId; - var variables = ExecuteCore.ExecuteGitVersion(fileSystem, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId); - - if (arguments.Output == OutputType.BuildServer) - { - foreach (var buildServer in BuildServerList.GetApplicableBuildServers()) - { - buildServer.WriteIntegration(Console.WriteLine, variables); - } - } - - if (arguments.Output == OutputType.Json) - { - switch (arguments.ShowVariable) - { - case null: - Console.WriteLine(JsonOutputFormatter.ToJson(variables)); - break; - - default: - string part; - if (!variables.TryGetValue(arguments.ShowVariable, out part)) - { - throw new WarningException(string.Format("'{0}' variable does not exist", arguments.ShowVariable)); - } - Console.WriteLine(part); - break; - } - } + var variables = GetVariables(fileSystem, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId); using (var assemblyInfoUpdate = new AssemblyInfoFileUpdate(arguments, targetPath, variables, fileSystem)) { diff --git a/src/GitVersionExe/packages.config b/src/GitVersionExe/packages.config index 7d5720e321..cd1cd28765 100644 --- a/src/GitVersionExe/packages.config +++ b/src/GitVersionExe/packages.config @@ -1,6 +1,7 @@  +