public static void NormalizeGitDirectory(string gitDirectory, Arguments arguments, string branch = null) { using (var repo = new Repository(gitDirectory)) { var remote = EnsureOnlyOneRemoteIsDefined(repo); AddMissingRefSpecs(repo, remote); Logger.WriteInfo(string.Format("Fetching from remote '{0}' using the following refspecs: {1}.", remote.Name, string.Join(", ", remote.FetchRefSpecs.Select(r => r.Specification)))); var fetchOptions = BuildFetchOptions(arguments.Username, arguments.Password); repo.Network.Fetch(remote, fetchOptions); CreateMissingLocalBranchesFromRemoteTrackingOnes(repo, remote.Name); if (!repo.Info.IsHeadDetached) { Logger.WriteInfo(string.Format("HEAD points at branch '{0}'.", repo.Refs.Head.TargetIdentifier)); return; } Logger.WriteInfo(string.Format("HEAD is detached and points at commit '{0}'.", repo.Refs.Head.TargetIdentifier)); if (branch != null) { Logger.WriteInfo(string.Format("Checking out local branch 'refs/heads/{0}'.", branch)); repo.Checkout("refs/heads/" + branch); } else { CreateFakeBranchPointingAtThePullRequestTip(repo); } } }
public static bool TryGetVersion(string directory, out SemanticVersion versionAndBranch) { var gitDirectory = GitDirFinder.TreeWalkForGitDir(directory); if (string.IsNullOrEmpty(gitDirectory)) { var message = "No .git directory found in provided solution path. This means the assembly may not be versioned correctly. " + "To fix this warning either clone the repository using git or remove the `GitVersion.Fody` nuget package. " + "To temporarily work around this issue add a AssemblyInfo.cs with an appropriate `AssemblyVersionAttribute`." + "If it is detected that this build is occurring on a CI server an error may be thrown."; Logger.WriteWarning(message); versionAndBranch = null; return false; } var arguments = new Arguments(); foreach (var buildServer in BuildServerList.GetApplicableBuildServers(arguments)) { Logger.WriteInfo(string.Format("Executing PerformPreProcessingSteps for '{0}'.", buildServer.GetType().Name)); buildServer.PerformPreProcessingSteps(gitDirectory); } versionAndBranch = VersionCache.GetVersion(gitDirectory); return true; }
static void CreateFakeBranchPointingAtThePullRequestTip(Repository repo, Arguments arguments) { var remote = repo.Network.Remotes.Single(); var remoteTips = string.IsNullOrEmpty(arguments.Username) ? GetRemoteTipsForAnonymousUser(repo, remote) : GetRemoteTipsUsingUsernamePasswordCredentials(repo, remote, arguments.Username, arguments.Password); var headTipSha = repo.Head.Tip.Sha; var refs = remoteTips.Where(r => r.TargetIdentifier == headTipSha).ToList(); if (refs.Count == 0) { var message = string.Format("Couldn't find any remote tips from remote '{0}' pointing at the commit '{1}'.", remote.Url, headTipSha); throw new WarningException(message); } if (refs.Count > 1) { var names = string.Join(", ", refs.Select(r => r.CanonicalName)); var message = string.Format("Found more than one remote tip from remote '{0}' pointing at the commit '{1}'. Unable to determine which one to use ({2}).", remote.Url, headTipSha, names); throw new WarningException(message); } var canonicalName = refs[0].CanonicalName; Logger.WriteInfo(string.Format("Found remote tip '{0}' pointing at the commit '{1}'.", canonicalName, headTipSha)); if (!canonicalName.StartsWith("refs/pull/")) { var message = string.Format("Remote tip '{0}' from remote '{1}' doesn't look like a valid pull request.", canonicalName, remote.Url); throw new WarningException(message); } var fakeBranchName = canonicalName.Replace("refs/pull/", "refs/heads/pull/"); Logger.WriteInfo(string.Format("Creating fake local branch '{0}'.", fakeBranchName)); repo.Refs.Add(fakeBranchName, new ObjectId(headTipSha)); Logger.WriteInfo(string.Format("Checking local branch '{0}' out.", fakeBranchName)); repo.Checkout(fakeBranchName); }
public ContinuaCi(Arguments arguments) { this.arguments = arguments; }
public GitPreparer(Arguments arguments) { this.arguments = arguments; }
public Arguments ParseArguments(string[] commandLineArguments) { if (commandLineArguments.Length == 0) { return(new Arguments { TargetPath = System.Environment.CurrentDirectory, }); } var firstArgument = commandLineArguments.First(); if (firstArgument.IsHelp()) { return(new Arguments { IsHelp = true, }); } if (firstArgument.IsInit()) { return(new Arguments { TargetPath = System.Environment.CurrentDirectory, Init = true, }); } var arguments = new Arguments(); AddAuthentication(arguments); var switchesAndValues = CollectSwitchesAndValuesFromArguments(commandLineArguments, out var firstArgumentIsSwitch); for (var i = 0; i < switchesAndValues.AllKeys.Length; i++) { var name = switchesAndValues.AllKeys[i]; var values = switchesAndValues.GetValues(name); var value = values?.FirstOrDefault(); if (name.IsSwitch("version")) { EnsureArgumentValueCount(values); arguments.IsVersion = true; continue; } if (name.IsSwitch("l")) { EnsureArgumentValueCount(values); arguments.LogFilePath = value; continue; } if (name.IsSwitch("config")) { EnsureArgumentValueCount(values); arguments.ConfigFile = value; continue; } if (name.IsSwitch("targetpath")) { EnsureArgumentValueCount(values); arguments.TargetPath = value; continue; } if (name.IsSwitch("dynamicRepoLocation")) { EnsureArgumentValueCount(values); arguments.DynamicRepositoryLocation = value; continue; } if (name.IsSwitch("url")) { EnsureArgumentValueCount(values); arguments.TargetUrl = value; continue; } if (name.IsSwitch("b")) { EnsureArgumentValueCount(values); arguments.TargetBranch = value; continue; } if (name.IsSwitch("u")) { EnsureArgumentValueCount(values); if (arguments.Authentication == null) { arguments.Authentication = new Authentication(); } arguments.Authentication.Username = value; continue; } if (name.IsSwitch("p")) { EnsureArgumentValueCount(values); if (arguments.Authentication == null) { arguments.Authentication = new Authentication(); } arguments.Authentication.Password = value; continue; } if (name.IsSwitch("c")) { EnsureArgumentValueCount(values); arguments.CommitId = value; continue; } if (name.IsSwitch("exec")) { EnsureArgumentValueCount(values); arguments.Exec = value; continue; } if (name.IsSwitch("execargs")) { EnsureArgumentValueCount(values); arguments.ExecArgs = value; continue; } if (name.IsSwitch("proj")) { EnsureArgumentValueCount(values); arguments.Proj = value; continue; } if (name.IsSwitch("projargs")) { EnsureArgumentValueCount(values); arguments.ProjArgs = value; continue; } if (name.IsSwitch("diag")) { if (value == null || value.IsTrue()) { arguments.Diag = true; } continue; } if (name.IsSwitch("updateAssemblyInfo")) { if (value.IsTrue()) { arguments.UpdateAssemblyInfo = true; } else if (value.IsFalse()) { arguments.UpdateAssemblyInfo = false; } else if (values != null && values.Length > 1) { arguments.UpdateAssemblyInfo = true; foreach (var v in values) { arguments.AddAssemblyInfoFileName(v); } } else if (!value.IsSwitchArgument()) { arguments.UpdateAssemblyInfo = true; arguments.AddAssemblyInfoFileName(value); } else { arguments.UpdateAssemblyInfo = true; } if (arguments.UpdateAssemblyInfoFileName.Count > 1 && arguments.EnsureAssemblyInfo) { throw new WarningException("Can't specify multiple assembly info files when using -ensureassemblyinfo switch, either use a single assembly info file or do not specify -ensureassemblyinfo and create assembly info files manually"); } continue; } if (name.IsSwitch("assemblyversionformat")) { throw new WarningException("assemblyversionformat switch removed, use AssemblyVersioningScheme configuration value instead"); } if (name.IsSwitch("v") || name.IsSwitch("showvariable")) { 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 (name.IsSwitch("showConfig")) { if (value.IsTrue()) { arguments.ShowConfig = true; } else if (value.IsFalse()) { arguments.UpdateAssemblyInfo = false; } else { arguments.ShowConfig = true; } continue; } if (name.IsSwitch("output")) { if (!Enum.TryParse(value, true, out OutputType outputType)) { throw new WarningException($"Value '{value}' cannot be parsed as output type, please use 'json' or 'buildserver'"); } arguments.Output = outputType; continue; } if (name.IsSwitch("nofetch")) { arguments.NoFetch = true; continue; } if (name.IsSwitch("nonormalize")) { arguments.NoNormalize = true; continue; } if (name.IsSwitch("ensureassemblyinfo")) { if (value.IsTrue()) { arguments.EnsureAssemblyInfo = true; } else if (value.IsFalse()) { arguments.EnsureAssemblyInfo = false; } else { arguments.EnsureAssemblyInfo = true; } if (arguments.UpdateAssemblyInfoFileName.Count > 1 && arguments.EnsureAssemblyInfo) { throw new WarningException("Can't specify multiple assembly info files when using /ensureassemblyinfo switch, either use a single assembly info file or do not specify /ensureassemblyinfo and create assembly info files manually"); } continue; } if (name.IsSwitch("overrideconfig")) { var keyValueOptions = (value ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (keyValueOptions.Length == 0) { continue; } arguments.HasOverrideConfig = true; arguments.OverrideConfig = new Config(); if (keyValueOptions.Length > 1) { throw new WarningException("Can't specify multiple /overrideconfig options: currently supported only 'tag-prefix' option"); } // key=value foreach (var keyValueOption in keyValueOptions) { var keyAndValue = keyValueOption.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (keyAndValue.Length != 2) { throw new WarningException($"Could not parse /overrideconfig option: {keyValueOption}. Ensure it is in format 'key=value'"); } var optionKey = keyAndValue[0].ToLowerInvariant(); arguments.OverrideConfig.TagPrefix = optionKey switch { "tag-prefix" => keyAndValue[1], _ => throw new WarningException($"Could not parse /overrideconfig option: {optionKey}. Currently supported only 'tag-prefix' option") }; } continue; } if (name.IsSwitch("nocache")) { arguments.NoCache = true; continue; } if (name.IsSwitch("verbosity")) { // first try the old version if (Enum.TryParse(value, true, out LogLevel logLevel)) { arguments.Verbosity = LogExtensions.GetVerbosityForLevel(logLevel); } else if (!Enum.TryParse(value, true, out arguments.Verbosity)) { throw new WarningException($"Could not parse Verbosity value '{value}'"); } continue; } if (name.IsSwitch("updatewixversionfile")) { arguments.UpdateWixVersionFile = true; continue; } var couldNotParseMessage = $"Could not parse command line parameter '{name}'."; // If we've reached through all argument switches without a match, we can relatively safely assume that the first argument isn't a switch, but the target path. if (i == 0) { if (name.StartsWith("/")) { if (Path.DirectorySeparatorChar == '/' && name.IsValidPath()) { arguments.TargetPath = name; continue; } } else if (!name.IsSwitchArgument()) { arguments.TargetPath = name; continue; } couldNotParseMessage += " If it is the target path, make sure it exists."; } throw new WarningException(couldNotParseMessage); } if (arguments.TargetPath == null) { // If the first argument is a switch, it should already have been consumed in the above loop, // or else a WarningException should have been thrown and we wouldn't end up here. arguments.TargetPath = firstArgumentIsSwitch ? System.Environment.CurrentDirectory : firstArgument; } return(arguments); }
public AssemblyInfoFileUpdate(Arguments args, string workingDirectory, VersionVariables variables, IFileSystem fileSystem) { if (!args.UpdateAssemblyInfo) { return; } if (args.Output != OutputType.Json) { Logger.WriteInfo("Updating assembly info files"); } var assemblyInfoFiles = GetAssemblyInfoFiles(workingDirectory, args, fileSystem).ToList(); Logger.WriteInfo($"Found {assemblyInfoFiles.Count} files"); var assemblyVersion = variables.AssemblySemVer; var assemblyVersionRegex = new Regex(@"AssemblyVersion(Attribute)?\s*\(\s*""[^""]*""\s*\)"); var assemblyVersionString = !string.IsNullOrWhiteSpace(assemblyVersion) ? $"AssemblyVersion(\"{assemblyVersion}\")" : null; var assemblyInfoVersion = variables.InformationalVersion; var assemblyInfoVersionRegex = new Regex(@"AssemblyInformationalVersion(Attribute)?\s*\(\s*""[^""]*""\s*\)"); var assemblyInfoVersionString = $"AssemblyInformationalVersion(\"{assemblyInfoVersion}\")"; var assemblyFileVersion = variables.AssemblySemFileVer; var assemblyFileVersionRegex = new Regex(@"AssemblyFileVersion(Attribute)?\s*\(\s*""[^""]*""\s*\)"); var assemblyFileVersionString = !string.IsNullOrWhiteSpace(assemblyFileVersion) ? $"AssemblyFileVersion(\"{assemblyFileVersion}\")" : null; foreach (var assemblyInfoFile in assemblyInfoFiles) { var backupAssemblyInfo = assemblyInfoFile.FullName + ".bak"; var localAssemblyInfo = assemblyInfoFile.FullName; fileSystem.Copy(assemblyInfoFile.FullName, backupAssemblyInfo, true); restoreBackupTasks.Add(() => { if (fileSystem.Exists(localAssemblyInfo)) { fileSystem.Delete(localAssemblyInfo); } fileSystem.Move(backupAssemblyInfo, localAssemblyInfo); }); cleanupBackupTasks.Add(() => fileSystem.Delete(backupAssemblyInfo)); var originalFileContents = fileSystem.ReadAllText(assemblyInfoFile.FullName); var fileContents = originalFileContents; var appendedAttributes = false; if (!string.IsNullOrWhiteSpace(assemblyVersion)) { fileContents = ReplaceOrAppend(assemblyVersionRegex, fileContents, assemblyVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } if (!string.IsNullOrWhiteSpace(assemblyFileVersion)) { fileContents = ReplaceOrAppend(assemblyFileVersionRegex, fileContents, assemblyFileVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } fileContents = ReplaceOrAppend(assemblyInfoVersionRegex, fileContents, assemblyInfoVersionString, assemblyInfoFile.Extension, ref appendedAttributes); if (appendedAttributes) { // If we appended any attributes, put a new line after them fileContents += Environment.NewLine; } if (originalFileContents != fileContents) { fileSystem.WriteAllText(assemblyInfoFile.FullName, fileContents); } } }
static int VerifyArgumentsAndRun() { Arguments arguments = null; 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); } catch (WarningException exception) { var error = string.Format("An error occurred:\r\n{0}", exception.Message); Logger.WriteWarning(error); 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; } return 0; }
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); }
public Arguments ParseArguments(string[] commandLineArguments) { if (commandLineArguments.Length == 0) { var args = new Arguments { TargetPath = System.Environment.CurrentDirectory, }; args.Output.Add(OutputType.Json); AddAuthentication(args); return(args); } var firstArgument = commandLineArguments.First(); if (firstArgument.IsInit()) { return(new Arguments { TargetPath = System.Environment.CurrentDirectory, Init = true, }); } if (firstArgument.IsHelp()) { return(new Arguments { IsHelp = true, }); } if (firstArgument.IsSwitch("version")) { return(new Arguments { IsVersion = true, }); } var arguments = new Arguments(); AddAuthentication(arguments); var switchesAndValues = CollectSwitchesAndValuesFromArguments(commandLineArguments, out var firstArgumentIsSwitch); for (var i = 0; i < switchesAndValues.AllKeys.Length; i++) { ParseSwitchArguments(arguments, switchesAndValues, i); } if (arguments.Output.Count == 0) { arguments.Output.Add(OutputType.Json); } if (arguments.Output.Contains(OutputType.File) && arguments.OutputFile == null) { arguments.OutputFile = defaultOutputFileName; } // If the first argument is a switch, it should already have been consumed in the above loop, // or else a WarningException should have been thrown and we wouldn't end up here. arguments.TargetPath ??= firstArgumentIsSwitch ? System.Environment.CurrentDirectory : firstArgument; arguments.TargetPath = arguments.TargetPath.TrimEnd('/', '\\'); if (!arguments.EnsureAssemblyInfo) { arguments.UpdateAssemblyInfoFileName = ResolveFiles(arguments.TargetPath, arguments.UpdateAssemblyInfoFileName).ToHashSet(); } arguments.NoFetch = arguments.NoFetch || buildAgent != null && buildAgent.PreventFetch(); return(arguments); }
private static bool ParseSwitches(Arguments arguments, string name, string[] values, string value) { if (name.IsSwitch("l")) { EnsureArgumentValueCount(values); arguments.LogFilePath = value; return(true); } if (ParseConfigArguments(arguments, name, values, value)) { return(true); } if (ParseRemoteArguments(arguments, name, values, value)) { return(true); } if (ParseExecArguments(arguments, name, values, value)) { return(true); } if (name.IsSwitch("updateprojectfiles")) { ParseUpdateProjectInfo(arguments, value, values); return(true); } if (name.IsSwitch("updateAssemblyInfo")) { ParseUpdateAssemblyInfo(arguments, value, values); return(true); } if (name.IsSwitch("ensureassemblyinfo")) { ParseEnsureAssemblyInfo(arguments, value); return(true); } if (name.IsSwitch("v") || name.IsSwitch("showvariable")) { ParseShowVariable(arguments, value, name); return(true); } if (name.IsSwitch("output")) { ParseOutput(arguments, values); return(true); } if (name.IsSwitch("outputfile")) { EnsureArgumentValueCount(values); arguments.OutputFile = value; return(true); } if (name.IsSwitch("nofetch")) { arguments.NoFetch = true; return(true); } if (name.IsSwitch("nonormalize")) { arguments.NoNormalize = true; return(true); } if (name.IsSwitch("nocache")) { arguments.NoCache = true; return(true); } if (name.IsSwitch("verbosity")) { ParseVerbosity(arguments, value); return(true); } if (name.IsSwitch("updatewixversionfile")) { arguments.UpdateWixVersionFile = true; return(true); } return(false); }
public static void Run(Arguments arguments, IFileSystem fileSystem, IEnvironment environment) { Logger.WriteInfo($"Running on {(runningOnUnix ? "Unix" : "Windows")}."); var noFetch = arguments.NoFetch; var authentication = arguments.Authentication; var targetPath = arguments.TargetPath; var targetUrl = arguments.TargetUrl; var dynamicRepositoryLocation = arguments.DynamicRepositoryLocation; var targetBranch = arguments.TargetBranch; var commitId = arguments.CommitId; var overrideConfig = arguments.HasOverrideConfig ? arguments.OverrideConfig : null; var noCache = arguments.NoCache; var noNormalize = arguments.NoNormalize; var executeCore = new ExecuteCore(fileSystem, environment, arguments.ConfigFileLocator); var variables = executeCore.ExecuteGitVersion(targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId, overrideConfig, noCache, noNormalize); switch (arguments.Output) { case OutputType.BuildServer: { BuildServerList.Init(environment); foreach (var buildServer in BuildServerList.GetApplicableBuildServers()) { buildServer.WriteIntegration(Console.WriteLine, variables); } break; } case OutputType.Json: switch (arguments.ShowVariable) { case null: Console.WriteLine(JsonOutputFormatter.ToJson(variables)); break; default: if (!variables.TryGetValue(arguments.ShowVariable, out var part)) { throw new WarningException($"'{arguments.ShowVariable}' variable does not exist"); } Console.WriteLine(part); break; } break; default: throw new ArgumentOutOfRangeException(); } if (arguments.UpdateWixVersionFile) { using (var wixVersionFileUpdater = new WixVersionFileUpdater(targetPath, variables, fileSystem)) { wixVersionFileUpdater.Update(); } } using (var assemblyInfoUpdater = new AssemblyInfoFileUpdater(arguments.UpdateAssemblyInfoFileName, targetPath, variables, fileSystem, arguments.EnsureAssemblyInfo)) { if (arguments.UpdateAssemblyInfo) { assemblyInfoUpdater.Update(); } var execRun = RunExecCommandIfNeeded(arguments, targetPath, variables); var msbuildRun = RunMsBuildIfNeeded(arguments, targetPath, variables); if (!execRun && !msbuildRun) { assemblyInfoUpdater.CommitChanges(); //TODO Put warning back //if (!context.CurrentBuildServer.IsRunningInBuildAgent()) //{ // Console.WriteLine("WARNING: Not running in build server and /ProjectFile or /Exec arguments not passed"); // Console.WriteLine(); // Console.WriteLine("Run GitVersion.exe /? for help"); //} } } }