public void Dispose() { Logger.WriteInfo(string.Format("Done writing {0}", WIX_VERSION_FILE)); }
static int VerifyArgumentsAndRun() { try { var fileSystem = new FileSystem(); Arguments arguments; 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); 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); return(1); } return(0); }
static int VerifyArgumentsAndRun() { Arguments arguments = null; try { var fileSystem = new FileSystem(); var argumentsWithoutExeName = GetArgumentsWithoutExeName(); try { arguments = ArgumentParser.ParseArguments(argumentsWithoutExeName); } catch (Exception exception) { Console.WriteLine("Failed to parse arguments: {0}", string.Join(" ", argumentsWithoutExeName)); if (!string.IsNullOrWhiteSpace(exception.Message)) { Console.WriteLine(); Console.WriteLine(exception.Message); Console.WriteLine(); } 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"); GitTools.LibGitExtensions.DumpGraph(arguments.TargetPath, Logger.WriteInfo, 100); } return(1); } return(0); }
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.MajorMinorPatch + ".0"; var assemblyFileVersionRegex = new Regex(@"AssemblyFileVersion(Attribute)?\s*\(\s*""[^""]*""\s*\)"); var assemblyFileVersionString = $"AssemblyFileVersion(\"{assemblyFileVersion}\")"; 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); } fileContents = ReplaceOrAppend(assemblyInfoVersionRegex, fileContents, assemblyInfoVersionString, assemblyInfoFile.Extension, ref appendedAttributes); fileContents = ReplaceOrAppend(assemblyFileVersionRegex, fileContents, assemblyFileVersionString, 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 (Exception exception) { Console.WriteLine("Failed to parse arguments: {0}", string.Join(" ", argumentsWithoutExeName)); if (!string.IsNullOrWhiteSpace(exception.Message)) { Console.WriteLine(); Console.WriteLine(exception.Message); Console.WriteLine(); } HelpWriter.Write(); return(1); } if (arguments.IsVersion) { var assembly = Assembly.GetExecutingAssembly(); VersionWriter.Write(assembly); return(0); } if (arguments.IsHelp) { HelpWriter.Write(); return(0); } if (arguments.Diag) { arguments.NoCache = true; arguments.Output = OutputType.BuildServer; } ConfigureLogging(arguments); if (arguments.Diag) { Logger.WriteInfo("Dumping commit graph: "); LibGitExtensions.DumpGraph(arguments.TargetPath, Logger.WriteInfo, 100); } if (!Directory.Exists(arguments.TargetPath)) { Logger.WriteWarning($"The working directory '{arguments.TargetPath}' does not exist."); } else { Logger.WriteInfo("Working directory: " + arguments.TargetPath); } VerifyConfiguration(arguments, fileSystem); if (arguments.Init) { ConfigurationProvider.Init(arguments.TargetPath, fileSystem, new ConsoleAdapter(), arguments.ConfigFileLocator); return(0); } if (arguments.ShowConfig) { Console.WriteLine(ConfigurationProvider.GetEffectiveConfigAsString(arguments.TargetPath, fileSystem, arguments.ConfigFileLocator)); return(0); } if (!string.IsNullOrEmpty(arguments.Proj) || !string.IsNullOrEmpty(arguments.Exec)) { arguments.Output = OutputType.BuildServer; } SpecifiedArgumentRunner.Run(arguments, fileSystem); } catch (WarningException exception) { var error = $"An error occurred:\r\n{exception.Message}"; Logger.WriteWarning(error); return(1); } catch (Exception exception) { var error = $"An unexpected error occurred:\r\n{exception}"; Logger.WriteError(error); if (arguments != null) { Logger.WriteInfo(string.Empty); Logger.WriteInfo("Attempting to show the current git graph (please include in issue): "); Logger.WriteInfo("Showing max of 100 commits"); try { LibGitExtensions.DumpGraph(arguments.TargetPath, Logger.WriteInfo, 100); } catch (Exception dumpGraphException) { Logger.WriteError("Couldn't dump the git graph due to the following error: " + dumpGraphException); } } return(1); } return(0); }
static void Main() { int?exitCode = null; try { Arguments arguments; var argumentsWithoutExeName = GetArgumentsWithoutExeName(); try { arguments = ArgumentParser.ParseArguments(argumentsWithoutExeName); } catch (Exception) { Console.WriteLine("Failed to parse arguments: {0}", string.Join(" ", argumentsWithoutExeName)); HelpWriter.Write(); return; } if (arguments.IsHelp) { HelpWriter.Write(); return; } if (!string.IsNullOrEmpty(arguments.Proj) || !string.IsNullOrEmpty(arguments.Exec)) { arguments.Output = OutputType.BuildServer; } ConfigureLogging(arguments); var gitPreparer = new GitPreparer(arguments); var gitDirectory = gitPreparer.Prepare(); if (string.IsNullOrEmpty(gitDirectory)) { Console.Error.WriteLine("Failed to prepare or find the .git directory in path '{0}'", arguments.TargetPath); Environment.Exit(1); } var workingDirectory = Directory.GetParent(gitDirectory).FullName; Logger.WriteInfo("Working directory: " + workingDirectory); var applicableBuildServers = GetApplicableBuildServers(arguments).ToList(); foreach (var buildServer in applicableBuildServers) { buildServer.PerformPreProcessingSteps(gitDirectory); } var semanticVersion = VersionCache.GetVersion(gitDirectory); if (arguments.Output == OutputType.BuildServer) { foreach (var buildServer in applicableBuildServers) { buildServer.WriteIntegration(semanticVersion, Console.WriteLine); } } var variables = VariableProvider.GetVariablesFor(semanticVersion); if (arguments.Output == OutputType.Json) { switch (arguments.VersionPart) { case null: Console.WriteLine(JsonOutputFormatter.ToJson(variables)); break; default: string part; if (!variables.TryGetValue(arguments.VersionPart, out part)) { throw new WarningException(string.Format("Could not extract '{0}' from the available parts.", arguments.VersionPart)); } Console.WriteLine(part); break; } } using (var assemblyInfoUpdate = new AssemblyInfoFileUpdate(arguments, workingDirectory, variables)) { var execRun = RunExecCommandIfNeeded(arguments, workingDirectory, variables); var msbuildRun = RunMsBuildIfNeeded(arguments, workingDirectory, variables); if (!execRun && !msbuildRun) { assemblyInfoUpdate.DoNotRestoreAssemblyInfo(); //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"); //} } } if (gitPreparer.IsDynamicGitRepository) { DeleteHelper.DeleteGitRepository(gitPreparer.DynamicGitRepositoryPath); } } catch (WarningException exception) { var error = string.Format("An error occurred:\r\n{0}", exception.Message); Logger.WriteWarning(error); exitCode = 1; } catch (Exception exception) { var error = string.Format("An unexpected error occurred:\r\n{0}", exception); Logger.WriteError(error); exitCode = 1; } if (Debugger.IsAttached) { Console.ReadKey(); } if (!exitCode.HasValue) { exitCode = 0; } Environment.Exit(exitCode.Value); }
public static Commit FindCommitBranchWasBranchedFrom([NotNull] this Branch branch, IRepository repository, params Branch[] excludedBranches) { const string missingTipFormat = "{0} has no tip. Please see http://example.com/docs for information on how to fix this."; if (branch == null) { throw new ArgumentNullException("branch"); } using (Logger.IndentLog("Finding branch source")) { if (branch.Tip == null) { Logger.WriteWarning(string.Format(missingTipFormat, branch.FriendlyName)); return(null); } var otherBranches = repository.Branches .Except(excludedBranches) .Where(b => IsSameBranch(branch, b)) .ToList(); var mergeBases = otherBranches.Select(otherBranch => { if (otherBranch.Tip == null) { Logger.WriteWarning(string.Format(missingTipFormat, otherBranch.FriendlyName)); return(null); } // Otherbranch tip is a forward merge var commitToFindCommonBase = otherBranch.Tip; if (otherBranch.Tip.Parents.Contains(branch.Tip)) { commitToFindCommonBase = otherBranch.Tip.Parents.First(); } var findMergeBase = repository.ObjectDatabase.FindMergeBase(branch.Tip, commitToFindCommonBase); if (findMergeBase != null) { using (Logger.IndentLog(string.Format("Found merge base of {0} against {1}", findMergeBase.Sha, otherBranch.FriendlyName))) { // We do not want to include merge base commits which got forward merged into the other branch bool mergeBaseWasFowardMerge; do { // Now make sure that the merge base is not a forward merge mergeBaseWasFowardMerge = otherBranch.Commits .SkipWhile(c => c != commitToFindCommonBase) .TakeWhile(c => c != findMergeBase) .Any(c => c.Parents.Contains(findMergeBase)); if (mergeBaseWasFowardMerge) { Logger.WriteInfo("Merge base was due to a forward merge, moving to next merge base"); var second = commitToFindCommonBase.Parents.First(); var mergeBase = repository.ObjectDatabase.FindMergeBase(branch.Tip, second); if (mergeBase == findMergeBase) { break; } findMergeBase = mergeBase; } } while (mergeBaseWasFowardMerge); } } return(new { mergeBaseCommit = findMergeBase, branch = otherBranch }); }).Where(b => b != null && b.mergeBaseCommit != null).OrderByDescending(b => b.mergeBaseCommit.Committer.When).ToList(); var firstOrDefault = mergeBases.FirstOrDefault(); if (firstOrDefault != null) { return(firstOrDefault.mergeBaseCommit); } return(null); } }
public void Update() { Logger.WriteInfo("Updating assembly info files"); var assemblyInfoFiles = GetAssemblyInfoFiles(workingDirectory, assemblyInfoFileNames, fileSystem, ensureAssemblyInfo).ToList(); Logger.WriteInfo($"Found {assemblyInfoFiles.Count} files"); var assemblyVersion = variables.AssemblySemVer; var assemblyVersionRegex = new Regex(@"AssemblyVersion(Attribute)?\s*\(.*\)\s*"); var assemblyVersionString = !string.IsNullOrWhiteSpace(assemblyVersion) ? $"AssemblyVersion(\"{assemblyVersion}\")" : null; var assemblyInfoVersion = variables.InformationalVersion; var assemblyInfoVersionRegex = new Regex(@"AssemblyInformationalVersion(Attribute)?\s*\(.*\)\s*"); var assemblyInfoVersionString = $"AssemblyInformationalVersion(\"{assemblyInfoVersion}\")"; var assemblyFileVersion = variables.AssemblySemFileVer; var assemblyFileVersionRegex = new Regex(@"AssemblyFileVersion(Attribute)?\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 = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(assemblyVersionRegex, fileContents, assemblyVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } if (!string.IsNullOrWhiteSpace(assemblyFileVersion)) { fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(assemblyFileVersionRegex, fileContents, assemblyFileVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(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); } } }
string GetGitInfoFromUrl() { var gitRootDirectory = Path.Combine(arguments.TargetPath, "_dynamicrepository"); var gitDirectory = Path.Combine(gitRootDirectory, ".git"); if (Directory.Exists(gitRootDirectory)) { Logger.WriteInfo(string.Format("Deleting existing .git folder from '{0}' to force new checkout from url", gitRootDirectory)); DeleteHelper.DeleteGitRepository(gitRootDirectory); } Credentials credentials = null; var authentication = arguments.Authentication; if (!string.IsNullOrWhiteSpace(authentication.Username) && !string.IsNullOrWhiteSpace(authentication.Password)) { Logger.WriteInfo(string.Format("Setting up credentials using name '{0}'", authentication.Username)); credentials = new UsernamePasswordCredentials { Username = authentication.Username, Password = authentication.Password }; } Logger.WriteInfo(string.Format("Retrieving git info from url '{0}'", arguments.TargetUrl)); Repository.Clone(arguments.TargetUrl, gitDirectory, new CloneOptions { IsBare = true, Checkout = false, CredentialsProvider = (url, usernameFromUrl, types) => credentials }); if (!string.IsNullOrWhiteSpace(arguments.TargetBranch)) { // Normalize (download branches) before using the branch GitHelper.NormalizeGitDirectory(gitDirectory, arguments.Authentication); using (var repository = new Repository(gitDirectory)) { Reference newHead = null; var localReference = GetLocalReference(repository, arguments.TargetBranch); if (localReference != null) { newHead = localReference; } if (newHead == null) { var remoteReference = GetRemoteReference(repository, arguments.TargetBranch, arguments.TargetUrl); if (remoteReference != null) { repository.Network.Fetch(arguments.TargetUrl, new[] { string.Format("{0}:{1}", remoteReference.CanonicalName, arguments.TargetBranch) }); newHead = repository.Refs[string.Format("refs/heads/{0}", arguments.TargetBranch)]; } } if (newHead != null) { Logger.WriteInfo(string.Format("Switching to branch '{0}'", arguments.TargetBranch)); repository.Refs.UpdateTarget(repository.Refs.Head, newHead); } repository.CheckoutFilesIfExist("NextVersion.txt"); } } DynamicGitRepositoryPath = gitDirectory; return(gitDirectory); }
static string CreateDynamicRepository(string targetPath, Authentication authentication, string repositoryUrl, string targetBranch, bool noFetch) { var gitDirectory = Path.Combine(targetPath, ".git"); if (Directory.Exists(targetPath)) { Logger.WriteInfo(string.Format("Git repository already exists at {0}", targetPath)); GitHelper.NormalizeGitDirectory(gitDirectory, authentication, noFetch); Logger.WriteInfo(string.Format("Updating branch '{0}'", targetBranch)); using (var repo = new Repository(targetPath)) { var targetGitBranch = repo.Branches[targetBranch]; var trackedBranch = targetGitBranch.TrackedBranch; if (trackedBranch == null) { throw new InvalidOperationException(string.Format("Expecting {0} to have a remote tracking branch", targetBranch)); } targetGitBranch.Checkout(); repo.Reset(ResetMode.Hard, trackedBranch.Tip); } return(gitDirectory); } Credentials credentials = null; if (!string.IsNullOrWhiteSpace(authentication.Username) && !string.IsNullOrWhiteSpace(authentication.Password)) { Logger.WriteInfo(string.Format("Setting up credentials using name '{0}'", authentication.Username)); credentials = new UsernamePasswordCredentials { Username = authentication.Username, Password = authentication.Password }; } Logger.WriteInfo(string.Format("Retrieving git info from url '{0}'", repositoryUrl)); Repository.Clone(repositoryUrl, gitDirectory, new CloneOptions { Checkout = false, CredentialsProvider = (url, usernameFromUrl, types) => credentials }); // Normalize (download branches) before using the branch GitHelper.NormalizeGitDirectory(gitDirectory, authentication, noFetch); using (var repository = new Repository(gitDirectory)) { if (string.IsNullOrWhiteSpace(targetBranch)) { targetBranch = repository.Head.Name; } Reference newHead = null; var localReference = GetLocalReference(repository, targetBranch); if (localReference != null) { newHead = localReference; } if (newHead == null) { var remoteReference = GetRemoteReference(repository, targetBranch, repositoryUrl); if (remoteReference != null) { repository.Network.Fetch(repositoryUrl, new[] { string.Format("{0}:{1}", remoteReference.CanonicalName, targetBranch) }); newHead = repository.Refs[string.Format("refs/heads/{0}", targetBranch)]; } } if (newHead != null) { Logger.WriteInfo(string.Format("Switching to branch '{0}'", targetBranch)); repository.Refs.UpdateTarget(repository.Refs.Head, newHead); } } return(gitDirectory); }
public static void NormalizeGitDirectory(string gitDirectory, Authentication authentication, bool noFetch, string currentBranch) { using (var repo = new Repository(gitDirectory)) { var remote = EnsureOnlyOneRemoteIsDefined(repo); AddMissingRefSpecs(repo, remote); //If noFetch is enabled, then GitVersion will assume that the git repository is normalized before execution, so that fetching from remotes is not required. if (noFetch) { Logger.WriteInfo("Skipping fetching, if GitVersion does not calculate your version as expected you might need to allow fetching or use dynamic repositories"); } else { 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(authentication.Username, authentication.Password); repo.Network.Fetch(remote, fetchOptions); } EnsureLocalBranchExistsForCurrentBranch(repo, currentBranch); CreateOrUpdateLocalBranchesFromRemoteTrackingOnes(repo, remote.Name); var headSha = repo.Refs.Head.TargetIdentifier; if (!repo.Info.IsHeadDetached) { Logger.WriteInfo(string.Format("HEAD points at branch '{0}'.", headSha)); return; } Logger.WriteInfo(string.Format("HEAD is detached and points at commit '{0}'.", headSha)); Logger.WriteInfo(string.Format("Local Refs:\r\n" + string.Join(Environment.NewLine, repo.Refs.FromGlob("*").Select(r => string.Format("{0} ({1})", r.CanonicalName, r.TargetIdentifier))))); // In order to decide whether a fake branch is required or not, first check to see if any local branches have the same commit SHA of the head SHA. // If they do, go ahead and checkout that branch // If no, go ahead and check out a new branch, using the known commit SHA as the pointer var localBranchesWhereCommitShaIsHead = repo.Branches.Where(b => !b.IsRemote && b.Tip.Sha == headSha).ToList(); var matchingCurrentBranch = !string.IsNullOrEmpty(currentBranch) ? localBranchesWhereCommitShaIsHead.SingleOrDefault(b => b.CanonicalName.Replace("/heads/", "/") == currentBranch.Replace("/heads/", "/")) : null; if (matchingCurrentBranch != null) { Logger.WriteInfo(string.Format("Checking out local branch '{0}'.", currentBranch)); repo.Checkout(matchingCurrentBranch); } else if (localBranchesWhereCommitShaIsHead.Count > 1) { var branchNames = localBranchesWhereCommitShaIsHead.Select(r => r.CanonicalName); var csvNames = string.Join(", ", branchNames); const string moveBranchMsg = "Move one of the branches along a commit to remove warning"; Logger.WriteWarning(string.Format("Found more than one local branch pointing at the commit '{0}' ({1}).", headSha, csvNames)); var master = localBranchesWhereCommitShaIsHead.SingleOrDefault(n => n.Name == "master"); if (master != null) { Logger.WriteWarning("Because one of the branches is 'master', will build master." + moveBranchMsg); repo.Checkout(master); } else { var branchesWithoutSeparators = localBranchesWhereCommitShaIsHead.Where(b => !b.Name.Contains('/') && !b.Name.Contains('-')).ToList(); if (branchesWithoutSeparators.Count == 1) { var branchWithoutSeparator = branchesWithoutSeparators[0]; Logger.WriteWarning(string.Format("Choosing {0} as it is the only branch without / or - in it. " + moveBranchMsg, branchWithoutSeparator.CanonicalName)); repo.Checkout(branchWithoutSeparator); } else { throw new WarningException("Failed to try and guess branch to use. " + moveBranchMsg); } } } else if (localBranchesWhereCommitShaIsHead.Count == 0) { Logger.WriteInfo(string.Format("No local branch pointing at the commit '{0}'. Fake branch needs to be created.", headSha)); CreateFakeBranchPointingAtThePullRequestTip(repo, authentication); } else { Logger.WriteInfo(string.Format("Checking out local branch 'refs/heads/{0}'.", localBranchesWhereCommitShaIsHead[0].Name)); repo.Checkout(repo.Branches[localBranchesWhereCommitShaIsHead[0].Name]); } } }
private static bool Log(LogLevel loglevel, Func <string> messagefunc, Exception exception, object[] formatparameters) { // Create the main message. Careful of string format errors. string message; if (messagefunc == null) { message = null; } else { if (formatparameters == null || formatparameters.Length == 0) { message = messagefunc(); } else { try { message = string.Format(messagefunc(), formatparameters); } catch (FormatException) { message = messagefunc(); Logger.WriteError(string.Format("LoggerWrapper.Log(): Incorrectly formatted string: message: '{0}'; formatparameters: {1}", message, string.Join(";", formatparameters))); } } } if (exception != null) { // Append the exception to the end of the message. message = string.IsNullOrEmpty(message) ? exception.ToString() : string.Format("{0}\n{1}", message, exception); } if (!string.IsNullOrEmpty(message)) { switch (loglevel) { case LogLevel.Trace: case LogLevel.Debug: Logger.WriteDebug(message); break; case LogLevel.Info: Logger.WriteInfo(message); break; case LogLevel.Warn: Logger.WriteWarning(message); break; case LogLevel.Error: case LogLevel.Fatal: Logger.WriteError(message); break; } } return(true); }
/// <summary> /// Normalisation of a git directory turns all remote branches into local branches, turns pull request refs into a real branch and a few other things. This is designed to be run *only on the build server* which checks out repositories in different ways. /// It is not recommended to run normalisation against a local repository /// </summary> public static void NormalizeGitDirectory(string gitDirectory, AuthenticationInfo authentication, bool noFetch, string currentBranch) { using (var repo = new Repository(gitDirectory)) { // Need to unsure the HEAD does not move, this is essentially a BugCheck var expectedSha = repo.Head.Tip.Sha; try { var remote = EnsureOnlyOneRemoteIsDefined(repo); AddMissingRefSpecs(repo, remote); //If noFetch is enabled, then GitVersion will assume that the git repository is normalized before execution, so that fetching from remotes is not required. if (noFetch) { Logger.WriteInfo("Skipping fetching, if GitVersion does not calculate your version as expected you might need to allow fetching or use dynamic repositories"); } else { Fetch(authentication, remote, repo); } EnsureLocalBranchExistsForCurrentBranch(repo, remote, currentBranch); CreateOrUpdateLocalBranchesFromRemoteTrackingOnes(repo, remote.Name); var headSha = repo.Refs.Head.TargetIdentifier; if (!repo.Info.IsHeadDetached) { Logger.WriteInfo(string.Format("HEAD points at branch '{0}'.", headSha)); return; } Logger.WriteInfo(string.Format("HEAD is detached and points at commit '{0}'.", headSha)); Logger.WriteInfo(string.Format("Local Refs:\r\n" + string.Join(Environment.NewLine, repo.Refs.FromGlob("*").Select(r => string.Format("{0} ({1})", r.CanonicalName, r.TargetIdentifier))))); // In order to decide whether a fake branch is required or not, first check to see if any local branches have the same commit SHA of the head SHA. // If they do, go ahead and checkout that branch // If no, go ahead and check out a new branch, using the known commit SHA as the pointer var localBranchesWhereCommitShaIsHead = repo.Branches.Where(b => !b.IsRemote && b.Tip.Sha == headSha).ToList(); var matchingCurrentBranch = !string.IsNullOrEmpty(currentBranch) ? localBranchesWhereCommitShaIsHead.SingleOrDefault(b => b.CanonicalName.Replace("/heads/", "/") == currentBranch.Replace("/heads/", "/")) : null; if (matchingCurrentBranch != null) { Logger.WriteInfo(string.Format("Checking out local branch '{0}'.", currentBranch)); Commands.Checkout(repo, matchingCurrentBranch); } else if (localBranchesWhereCommitShaIsHead.Count > 1) { var branchNames = localBranchesWhereCommitShaIsHead.Select(r => r.CanonicalName); var csvNames = string.Join(", ", branchNames); const string moveBranchMsg = "Move one of the branches along a commit to remove warning"; Logger.WriteWarning(string.Format("Found more than one local branch pointing at the commit '{0}' ({1}).", headSha, csvNames)); var master = localBranchesWhereCommitShaIsHead.SingleOrDefault(n => n.FriendlyName == "master"); if (master != null) { Logger.WriteWarning("Because one of the branches is 'master', will build master." + moveBranchMsg); Commands.Checkout(repo, master); } else { var branchesWithoutSeparators = localBranchesWhereCommitShaIsHead.Where(b => !b.FriendlyName.Contains('/') && !b.FriendlyName.Contains('-')).ToList(); if (branchesWithoutSeparators.Count == 1) { var branchWithoutSeparator = branchesWithoutSeparators[0]; Logger.WriteWarning(string.Format("Choosing {0} as it is the only branch without / or - in it. " + moveBranchMsg, branchWithoutSeparator.CanonicalName)); Commands.Checkout(repo, branchWithoutSeparator); } else { throw new WarningException("Failed to try and guess branch to use. " + moveBranchMsg); } } } else if (localBranchesWhereCommitShaIsHead.Count == 0) { Logger.WriteInfo(string.Format("No local branch pointing at the commit '{0}'. Fake branch needs to be created.", headSha)); CreateFakeBranchPointingAtThePullRequestTip(repo, authentication); } else { Logger.WriteInfo(string.Format("Checking out local branch 'refs/heads/{0}'.", localBranchesWhereCommitShaIsHead[0].FriendlyName)); Commands.Checkout(repo, repo.Branches[localBranchesWhereCommitShaIsHead[0].FriendlyName]); } } finally { if (repo.Head.Tip.Sha != expectedSha) { if (Environment.GetEnvironmentVariable("IGNORE_NORMALISATION_GIT_HEAD_MOVE") != "1") { // Whoa, HEAD has moved, it shouldn't have. We need to blow up because there is a bug in normalisation throw new BugException(string.Format(@"GitVersion has a bug, your HEAD has moved after repo normalisation. To disable this error set an environmental variable called IGNORE_NORMALISATION_GIT_HEAD_MOVE to 1 Please run `git {0}` and submit it along with your build log (with personal info removed) in a new issue at https://github.com/GitTools/GitVersion", CreateGitLogArgs(100))); } } } } }
public static void Fetch(AuthenticationInfo authentication, Remote remote, Repository repo) { Logger.WriteInfo(string.Format("Fetching from remote '{0}' using the following refspecs: {1}.", remote.Name, string.Join(", ", remote.FetchRefSpecs.Select(r => r.Specification)))); Commands.Fetch(repo, remote.Name, new string[0], authentication.ToFetchOptions(), null); }
static KeyValuePair <string, BranchConfig> InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair <string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config, IList <Branch> excludedInheritBranches) { using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) { var excludedBranches = new[] { currentBranch }; // Check if we are a merge commit. If so likely we are a pull request var parentCount = currentCommit.Parents.Count(); if (parentCount == 2) { var parents = currentCommit.Parents.ToArray(); var branch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[1]); if (branch != null) { excludedBranches = new[] { currentBranch, branch }; currentBranch = branch; } else { var possibleTargetBranches = repository.Branches.Where(b => !b.IsRemote && b.Tip == parents[0]).ToList(); if (possibleTargetBranches.Count() > 1) { currentBranch = possibleTargetBranches.FirstOrDefault(b => b.Name == "master") ?? possibleTargetBranches.First(); } else { currentBranch = possibleTargetBranches.FirstOrDefault() ?? currentBranch; } } Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.Name + " as base"); } if (excludedInheritBranches == null) { excludedInheritBranches = repository.Branches.Where(b => { var branchConfig = LookupBranchConfiguration(config, b); return(branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit); }).ToList(); } excludedBranches.ToList().ForEach(excludedInheritBranches.Add); var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray()); List <Branch> possibleParents; if (branchPoint == null) { possibleParents = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList(); } else { var branches = branchPoint.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList(); if (branches.Count > 1) { var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedInheritBranches).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else { possibleParents = branches; } } Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name))); if (possibleParents.Count == 1) { var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value; return(new KeyValuePair <string, BranchConfig>( keyValuePair.Key, new BranchConfig(branchConfiguration) { Increment = branchConfig.Increment, PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion })); } // If we fail to inherit it is probably because the branch has been merged and we can't do much. So we will fall back to develop's config // if develop exists and master if not string errorMessage; if (possibleParents.Count == 0) { errorMessage = "Failed to inherit Increment branch configuration, no branches found."; } else { errorMessage = "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.Name)); } var developBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.Name, "^develop", RegexOptions.IgnoreCase)); var branchName = developBranch != null ? developBranch.Name : "master"; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, repository.Branches[branchName]).Value; return(new KeyValuePair <string, BranchConfig>( keyValuePair.Key, new BranchConfig(branchConfiguration) { Increment = value.Increment, PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion })); } }
public void Dispose() { Logger.WriteInfo($"Done writing {WixVersionFile}"); }
static KeyValuePair <string, BranchConfig> InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair <string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config, IList <Branch> excludedInheritBranches) { using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) { var excludedBranches = new[] { currentBranch }; // Check if we are a merge commit. If so likely we are a pull request var parentCount = currentCommit.Parents.Count(); if (parentCount == 2) { excludedBranches = CalculateWhenMultipleParents(repository, currentCommit, ref currentBranch, excludedBranches); } if (excludedInheritBranches == null) { excludedInheritBranches = repository.Branches.Where(b => { var branchConfig = LookupBranchConfiguration(config, b); // NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master" // NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick return((branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit)); }).ToList(); } excludedBranches.ToList().ForEach(excludedInheritBranches.Add); var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList(); var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray()); List <Branch> possibleParents; if (branchPoint == null) { possibleParents = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true) // It fails to inherit Increment branch configuration if more than 1 parent; // therefore no point to get more than 2 parents .Take(2) .ToList(); } else { var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else { possibleParents = branches; } } Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName))); if (possibleParents.Count == 1) { var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value; return(new KeyValuePair <string, BranchConfig>( keyValuePair.Key, new BranchConfig(branchConfiguration) { Increment = branchConfig.Increment, PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion, // If we are inheriting from develop then we should behave like develop IsDevelop = branchConfig.IsDevelop })); } // If we fail to inherit it is probably because the branch has been merged and we can't do much. So we will fall back to develop's config // if develop exists and master if not string errorMessage; if (possibleParents.Count == 0) { errorMessage = "Failed to inherit Increment branch configuration, no branches found."; } else { errorMessage = "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName)); } var chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.FriendlyName, "^develop", RegexOptions.IgnoreCase) || Regex.IsMatch(b.FriendlyName, "master$", RegexOptions.IgnoreCase)); if (chosenBranch == null) { // TODO We should call the build server to generate this exception, each build server works differently // for fetch issues and we could give better warnings. throw new InvalidOperationException("Could not find a 'develop' or 'master' branch, neither locally nor remotely."); } var branchName = chosenBranch.FriendlyName; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch).Value; return(new KeyValuePair <string, BranchConfig>( keyValuePair.Key, new BranchConfig(branchConfiguration) { Increment = inheritingBranchConfig.Increment, PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion, // If we are inheriting from develop then we should behave like develop IsDevelop = inheritingBranchConfig.IsDevelop })); } }
static int Run() { try { Arguments arguments; var argumentsWithoutExeName = GetArgumentsWithoutExeName(); try { arguments = ArgumentParser.ParseArguments(argumentsWithoutExeName); } catch (Exception) { Console.WriteLine("Failed to parse arguments: {0}", string.Join(" ", argumentsWithoutExeName)); HelpWriter.Write(); return(1); } if (arguments.IsHelp) { HelpWriter.Write(); return(0); } if (!string.IsNullOrEmpty(arguments.Proj) || !string.IsNullOrEmpty(arguments.Exec)) { arguments.Output = OutputType.BuildServer; } ConfigureLogging(arguments); var gitPreparer = new GitPreparer(arguments); var gitDirectory = gitPreparer.Prepare(); if (string.IsNullOrEmpty(gitDirectory)) { Console.Error.WriteLine("Failed to prepare or find the .git directory in path '{0}'", arguments.TargetPath); return(1); } var fileSystem = new FileSystem(); if (arguments.Init) { ConfigurationProvider.WriteSample(gitDirectory, fileSystem); return(0); } var workingDirectory = Directory.GetParent(gitDirectory).FullName; Logger.WriteInfo("Working directory: " + workingDirectory); var applicableBuildServers = GetApplicableBuildServers(arguments.Authentication).ToList(); foreach (var buildServer in applicableBuildServers) { buildServer.PerformPreProcessingSteps(gitDirectory); } SemanticVersion semanticVersion; var versionFinder = new GitVersionFinder(); var configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem); using (var repo = RepositoryLoader.GetRepo(gitDirectory)) { var gitVersionContext = new GitVersionContext(repo, configuration); semanticVersion = versionFinder.FindVersion(gitVersionContext); } if (arguments.Output == OutputType.BuildServer) { foreach (var buildServer in applicableBuildServers) { buildServer.WriteIntegration(semanticVersion, Console.WriteLine); } } var variables = VariableProvider.GetVariablesFor(semanticVersion, configuration); if (arguments.Output == OutputType.Json) { switch (arguments.VersionPart) { case null: Console.WriteLine(JsonOutputFormatter.ToJson(variables)); break; default: string part; if (!variables.TryGetValue(arguments.VersionPart, out part)) { throw new WarningException(string.Format("Could not extract '{0}' from the available parts.", arguments.VersionPart)); } Console.WriteLine(part); break; } } if (!string.IsNullOrWhiteSpace(arguments.AssemblyVersionFormat) && !variables.ContainsKey(arguments.AssemblyVersionFormat)) { Console.WriteLine("Unrecognised AssemblyVersionFormat argument. Valid values for this argument are: {0}", string.Join(" ", variables.Keys.OrderBy(a => a))); HelpWriter.Write(); return(1); } using (var assemblyInfoUpdate = new AssemblyInfoFileUpdate(arguments, workingDirectory, variables, fileSystem)) { var execRun = RunExecCommandIfNeeded(arguments, workingDirectory, variables); var msbuildRun = RunMsBuildIfNeeded(arguments, workingDirectory, variables); if (!execRun && !msbuildRun) { assemblyInfoUpdate.DoNotRestoreAssemblyInfo(); //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"); //} } } if (gitPreparer.IsDynamicGitRepository) { DeleteHelper.DeleteGitRepository(gitPreparer.DynamicGitRepositoryPath); } } 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); return(1); } return(0); }
/// <summary> /// Find the merge base of the two branches, i.e. the best common ancestor of the two branches' tips. /// </summary> public Commit FindMergeBase(Branch branch, Branch otherBranch) { var key = Tuple.Create(branch, otherBranch); if (mergeBaseCache.ContainsKey(key)) { Logger.WriteDebug($"Cache hit for merge base between '{branch.FriendlyName}' and '{otherBranch.FriendlyName}'."); return(mergeBaseCache[key].MergeBase); } using (Logger.IndentLog($"Finding merge base between '{branch.FriendlyName}' and '{otherBranch.FriendlyName}'.")) { // Otherbranch tip is a forward merge var commitToFindCommonBase = otherBranch.Tip; var commit = branch.Tip; if (otherBranch.Tip.Parents.Contains(commit)) { commitToFindCommonBase = otherBranch.Tip.Parents.First(); } var findMergeBase = Repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase); if (findMergeBase != null) { Logger.WriteInfo($"Found merge base of {findMergeBase.Sha}"); // We do not want to include merge base commits which got forward merged into the other branch Commit forwardMerge; do { // Now make sure that the merge base is not a forward merge forwardMerge = Repository.Commits .QueryBy(new CommitFilter { IncludeReachableFrom = commitToFindCommonBase, ExcludeReachableFrom = findMergeBase }) .FirstOrDefault(c => c.Parents.Contains(findMergeBase)); if (forwardMerge != null) { // TODO Fix the logging up in this section var second = forwardMerge.Parents.First(); Logger.WriteDebug("Second " + second.Sha); var mergeBase = Repository.ObjectDatabase.FindMergeBase(commit, second); if (mergeBase == null) { Logger.WriteWarning("Could not find mergbase for " + commit); } else { Logger.WriteDebug("New Merge base " + mergeBase.Sha); } if (mergeBase == findMergeBase) { Logger.WriteDebug("Breaking"); break; } findMergeBase = mergeBase; commitToFindCommonBase = second; Logger.WriteInfo($"Merge base was due to a forward merge, next merge base is {findMergeBase}"); } } while (forwardMerge != null); } // Store in cache. mergeBaseCache.Add(key, new MergeBaseData(branch, otherBranch, Repository, findMergeBase)); Logger.WriteInfo($"Merge base of {branch.FriendlyName}' and '{otherBranch.FriendlyName} is {findMergeBase}"); return(findMergeBase); } }
static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch targetBranch, BranchConfig branchConfiguration, IList <Branch> excludedInheritBranches) { var repository = context.Repository; var config = context.FullConfiguration; using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) { var excludedBranches = new[] { targetBranch }; // Check if we are a merge commit. If so likely we are a pull request var parentCount = context.CurrentCommit.Parents.Count(); if (parentCount == 2) { excludedBranches = CalculateWhenMultipleParents(repository, context.CurrentCommit, ref targetBranch, excludedBranches); } if (excludedInheritBranches == null) { excludedInheritBranches = repository.Branches.Where(b => { var branchConfig = config.GetConfigForBranch(b.FriendlyName); return(branchConfig != null && branchConfig.Increment == IncrementStrategy.Inherit); }).ToList(); } // Add new excluded branches. foreach (var excludedBranch in excludedBranches.ExcludingBranches(excludedInheritBranches)) { excludedInheritBranches.Add(excludedBranch); } var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList(); var branchPoint = context.RepositoryMetadataProvider .FindCommitBranchWasBranchedFrom(targetBranch, excludedInheritBranches.ToArray()); List <Branch> possibleParents; if (branchPoint == BranchCommit.Empty) { possibleParents = context.RepositoryMetadataProvider.GetBranchesContainingCommit(context.CurrentCommit, branchesToEvaluate, true) // It fails to inherit Increment branch configuration if more than 1 parent; // therefore no point to get more than 2 parents .Take(2) .ToList(); } else { var branches = context.RepositoryMetadataProvider .GetBranchesContainingCommit(branchPoint.Commit, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { var currentTipBranches = context.RepositoryMetadataProvider .GetBranchesContainingCommit(context.CurrentCommit, branchesToEvaluate, true).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else { possibleParents = branches; } } Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName))); if (possibleParents.Count == 1) { var branchConfig = GetBranchConfiguration(context, possibleParents[0], excludedInheritBranches); return(new BranchConfig(branchConfiguration) { Increment = branchConfig.Increment, PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion, // If we are inheriting from develop then we should behave like develop TracksReleaseBranches = branchConfig.TracksReleaseBranches }); } // If we fail to inherit it is probably because the branch has been merged and we can't do much. So we will fall back to develop's config // if develop exists and master if not string errorMessage; if (possibleParents.Count == 0) { errorMessage = "Failed to inherit Increment branch configuration, no branches found."; } else { errorMessage = "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName)); } var developBranchRegex = config.Branches[ConfigurationProvider.DevelopBranchKey].Regex; var masterBranchRegex = config.Branches[ConfigurationProvider.MasterBranchKey].Regex; var chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.FriendlyName, developBranchRegex, RegexOptions.IgnoreCase) || Regex.IsMatch(b.FriendlyName, masterBranchRegex, RegexOptions.IgnoreCase)); if (chosenBranch == null) { // TODO We should call the build server to generate this exception, each build server works differently // for fetch issues and we could give better warnings. throw new InvalidOperationException("Could not find a 'develop' or 'master' branch, neither locally nor remotely."); } var branchName = chosenBranch.FriendlyName; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); // To prevent infinite loops, make sure that a new branch was chosen. if (targetBranch.IsSameBranch(chosenBranch)) { Logger.WriteWarning("Fallback branch wants to inherit Increment branch configuration from itself. Using patch increment instead."); return(new BranchConfig(branchConfiguration) { Increment = IncrementStrategy.Patch }); } var inheritingBranchConfig = GetBranchConfiguration(context, chosenBranch, excludedInheritBranches); return(new BranchConfig(branchConfiguration) { Increment = inheritingBranchConfig.Increment, PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion, // If we are inheriting from develop then we should behave like develop TracksReleaseBranches = inheritingBranchConfig.TracksReleaseBranches }); } }
public static void Run(Arguments arguments, IFileSystem fileSystem) { 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 executeCore = new ExecuteCore(fileSystem, arguments.ConfigFileLocator); var variables = executeCore.ExecuteGitVersion(targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId, overrideConfig, noCache); 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: if (!variables.TryGetValue(arguments.ShowVariable, out var part)) { throw new WarningException($"'{arguments.ShowVariable}' variable does not exist"); } Console.WriteLine(part); break; } } 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"); //} } } }
static KeyValuePair <string, BranchConfig> InheritBranchConfiguration( bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair <string, BranchConfig> keyValuePair, BranchConfig branchConfiguration, Config config) { Logger.WriteInfo("Attempting to inherit branch configuration from parent branch"); var excludedBranches = new [] { currentBranch }; // Check if we are a merge commit. If so likely we are a pull request var parentCount = currentCommit.Parents.Count(); if (parentCount == 2) { var parents = currentCommit.Parents.ToArray(); var branch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[1]); if (branch != null) { excludedBranches = new[] { currentBranch, branch }; currentBranch = branch; } else { currentBranch = repository.Branches.SingleOrDefault(b => !b.IsRemote && b.Tip == parents[0]) ?? currentBranch; } Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.Name + " as base"); } var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, onlyEvaluateTrackedBranches, excludedBranches); List <Branch> possibleParents; if (branchPoint.Sha == currentCommit.Sha) { possibleParents = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList(); } else { var branches = branchPoint.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList(); var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, true).Except(excludedBranches).ToList(); possibleParents = branches .Except(currentTipBranches) .ToList(); } Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.Name))); // If it comes down to master and something, master is always first so we pick other branch if (possibleParents.Count == 2 && possibleParents.Any(p => p.Name == "master")) { possibleParents.Remove(possibleParents.Single(p => p.Name == "master")); } if (possibleParents.Count == 1) { var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0]).Value; return(new KeyValuePair <string, BranchConfig>( keyValuePair.Key, new BranchConfig(branchConfiguration) { Increment = branchConfig.Increment, PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion })); } // If we fail to inherit it is probably because the branch has been merged and we can't do much. So we will fall back to develop's config // if develop exists and master if not string errorMessage; if (possibleParents.Count == 0) { errorMessage = "Failed to inherit Increment branch configuration, no branches found."; } else { errorMessage = "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.Name)); } var hasDevelop = repository.FindBranch("develop") != null; var branchName = hasDevelop ? "develop" : "master"; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); var value = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, repository.Branches[branchName]).Value; return(new KeyValuePair <string, BranchConfig>( keyValuePair.Key, new BranchConfig(branchConfiguration) { Increment = value.Increment, PreventIncrementOfMergedBranchVersion = value.PreventIncrementOfMergedBranchVersion })); }