Ejemplo n.º 1
0
 public void Dispose()
 {
     Logger.WriteInfo(string.Format("Done writing {0}", WIX_VERSION_FILE));
 }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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);
                }
            }
        }
Ejemplo n.º 5
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.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);
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
0
        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);
            }
        }
Ejemplo n.º 8
0
        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);
                }
            }
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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]);
                }
            }
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        /// <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)));
                        }
                    }
                }
            }
        }
Ejemplo n.º 14
0
 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
                }));
            }
        }
Ejemplo n.º 16
0
 public void Dispose()
 {
     Logger.WriteInfo($"Done writing {WixVersionFile}");
 }
Ejemplo n.º 17
0
        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
                }));
            }
        }
Ejemplo n.º 18
0
        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);
        }
Ejemplo n.º 19
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
            }));
        }