AssemblyVersioningScheme GetAssemblyVersioningScheme()
        {
            if (string.IsNullOrWhiteSpace(AssemblyVersioningScheme))
            {
                var gitDirectory = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);

                var configFilePath = Path.Combine(Directory.GetParent(gitDirectory).FullName, "GitVersionConfig.yaml");
                if (File.Exists(configFilePath))
                {
                    using (var reader = File.OpenText(configFilePath))
                    {
                        return(ConfigReader.Read(reader).AssemblyVersioningScheme);
                    }
                }
                return(global::AssemblyVersioningScheme.MajorMinorPatch);
            }

            AssemblyVersioningScheme versioningScheme;

            if (Enum.TryParse(AssemblyVersioningScheme, true, out versioningScheme))
            {
                return(versioningScheme);
            }

            throw new WarningException(string.Format("Unexpected assembly versioning scheme '{0}'.", AssemblyVersioningScheme));
        }
        public static bool TryGetVersion(string directory, out SemanticVersion versionAndBranch)
        {
            var gitDirectory = GitDirFinder.TreeWalkForGitDir(directory);

            if (string.IsNullOrEmpty(gitDirectory))
            {
                var message =
                    "No .git directory found in provided solution path. This means the assembly may not be versioned correctly. " +
                    "To fix this warning either clone the repository using git or remove the `GitVersion.Fody` nuget package. " +
                    "To temporarily work around this issue add a AssemblyInfo.cs with an appropriate `AssemblyVersionAttribute`." +
                    "If it is detected that this build is occurring on a CI server an error may be thrown.";
                Logger.WriteWarning(message);
                versionAndBranch = null;
                return(false);
            }

            var arguments = new Arguments();

            foreach (var buildServer in BuildServerList.GetApplicableBuildServers(arguments))
            {
                Logger.WriteInfo(string.Format("Executing PerformPreProcessingSteps for '{0}'.", buildServer.GetType().Name));
                buildServer.PerformPreProcessingSteps(gitDirectory);
            }
            versionAndBranch = VersionCache.GetVersion(gitDirectory);
            return(true);
        }
Exemple #3
0
        public void InnerExecute()
        {
            Tuple <CachedVersion, GitVersionContext> result;
            var gitDirectory  = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);
            var configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem);

            if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out result, configuration))
            {
                return;
            }

            var authentication = new Authentication();

            var cachedVersion            = result.Item1;
            var gitVersionContext        = result.Item2;
            var config                   = gitVersionContext.Configuration;
            var assemblyVersioningScheme = config.AssemblyVersioningScheme;
            var versioningMode           = config.VersioningMode;

            var variablesFor = VariableProvider.GetVariablesFor(
                cachedVersion.SemanticVersion, assemblyVersioningScheme, versioningMode,
                config.ContinuousDeploymentFallbackTag,
                gitVersionContext.IsCurrentCommitTagged);

            WriteIntegrationParameters(cachedVersion, BuildServerList.GetApplicableBuildServers(authentication), variablesFor);
        }
Exemple #4
0
        public void InnerExecute()
        {
            TempFileTracker.DeleteTempFiles();

            InvalidFileChecker.CheckForInvalidFiles(CompileFiles, ProjectFile);

            var gitDirectory = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);

            if (string.IsNullOrEmpty(gitDirectory))
            {
                return;
            }

            var configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem);

            if (!string.IsNullOrEmpty(AssemblyVersioningScheme))
            {
                AssemblyVersioningScheme versioningScheme;
                if (Enum.TryParse(AssemblyVersioningScheme, true, out versioningScheme))
                {
                    configuration.AssemblyVersioningScheme = versioningScheme;
                }
                else
                {
                    throw new WarningException(string.Format("Unexpected assembly versioning scheme '{0}'.", AssemblyVersioningScheme));
                }
            }

            // TODO This should be covered by tests
            // TODO would be good to not have to duplicate this in both msbuild tasks
            // Null is intentional. Empty string means the user has set the value to an empty string and wants to clear the tag
            if (DevelopBranchTag != null)
            {
                configuration.DevelopBranchTag = DevelopBranchTag;
            }

            if (ReleaseBranchTag != null)
            {
                configuration.ReleaseBranchTag = ReleaseBranchTag;
            }

            if (TagPrefix != null)
            {
                configuration.TagPrefix = TagPrefix;
            }

            if (NextVersion != null)
            {
                configuration.NextVersion = NextVersion;
            }

            CachedVersion semanticVersion;

            if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out semanticVersion, configuration))
            {
                return;
            }
            CreateTempAssemblyInfo(semanticVersion, configuration);
        }
Exemple #5
0
        public void SetUp()
        {
            var assemblyLocation  = System.Reflection.Assembly.GetExecutingAssembly().Location;
            var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);

            string repositoryDirectory = GitDirFinder.TreeWalkForGitDir(assemblyDirectory);

            repo = new Repository(repositoryDirectory);
        }
        public override bool Execute()
        {
            try
            {
                CachedVersion versionAndBranch;
                var           gitDirectory  = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);
                var           configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem);

                // TODO This should be covered by tests
                // Null is intentional. Empty string means the user has set the value to an empty string and wants to clear the tag
                if (DevelopBranchTag != null)
                {
                    configuration.DevelopBranchTag = DevelopBranchTag;
                }

                if (ReleaseBranchTag != null)
                {
                    configuration.ReleaseBranchTag = ReleaseBranchTag;
                }

                if (TagPrefix != null)
                {
                    configuration.TagPrefix = TagPrefix;
                }

                if (NextVersion != null)
                {
                    configuration.NextVersion = NextVersion;
                }

                if (VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out versionAndBranch, configuration))
                {
                    var thisType  = typeof(GetVersion);
                    var variables = VariableProvider.GetVariablesFor(versionAndBranch.SemanticVersion, configuration);
                    foreach (var variable in variables)
                    {
                        thisType.GetProperty(variable.Key).SetValue(this, variable.Value, null);
                    }
                }
                return(true);
            }
            catch (WarningException errorException)
            {
                logger.LogWarning(errorException.Message);
                return(true);
            }
            catch (Exception exception)
            {
                logger.LogError("Error occurred: " + exception);
                return(false);
            }
            finally
            {
                Logger.Reset();
            }
        }
Exemple #7
0
        public void InnerExecute()
        {
            CachedVersion semanticVersion;
            var           gitDirectory  = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);
            var           configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem);

            if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out semanticVersion, configuration))
            {
                return;
            }

            var authentication = new Authentication();

            WriteIntegrationParameters(semanticVersion, BuildServerList.GetApplicableBuildServers(authentication));
        }
Exemple #8
0
        public string GetShaHashOfCurrentBranch(Context context, TemporaryFilesContext temporaryFilesContext)
        {
            Argument.IsNotNull(() => context);

            string commitSha           = null;
            var    repositoryDirectory = context.SolutionDirectory;

            if (_repositoryPreparer.IsPreparationRequired(context))
            {
                Log.Info("No local repository is found in '{0}', creating a temporary one", repositoryDirectory);

                repositoryDirectory = _repositoryPreparer.Prepare(context, temporaryFilesContext);
            }

            repositoryDirectory = GitDirFinder.TreeWalkForGitDir(repositoryDirectory);

            using (var repository = new Repository(repositoryDirectory))
            {
                if (string.IsNullOrEmpty(context.ShaHash))
                {
                    Log.Info("No sha hash is available on the context, retrieving latest commit of current branch");

                    var lastCommit = repository.Commits.First();
                    commitSha = lastCommit.Sha;
                }
                else
                {
                    Log.Info("Checking if commit with sha hash '{0}' exists on the repository", context.ShaHash);

                    var commit = repository.Commits.FirstOrDefault(c => string.Equals(c.Sha, context.ShaHash, StringComparison.OrdinalIgnoreCase));
                    if (commit != null)
                    {
                        commitSha = commit.Sha;
                    }
                }
            }

            if (commitSha == null)
            {
                throw Log.ErrorAndCreateException <GitLinkException>("Cannot find commit '{0}' in repo.", context.ShaHash);
            }

            return(commitSha);
        }
Exemple #9
0
        public override bool Execute()
        {
            try
            {
                Tuple <CachedVersion, GitVersionContext> versionAndBranch;
                var gitDirectory  = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);
                var configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem);

                if (VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out versionAndBranch, configuration))
                {
                    var thisType          = typeof(GetVersion);
                    var cachedVersion     = versionAndBranch.Item1;
                    var gitVersionContext = versionAndBranch.Item2;
                    var config            = gitVersionContext.Configuration;
                    var variables         = VariableProvider.GetVariablesFor(
                        cachedVersion.SemanticVersion, config.AssemblyVersioningScheme,
                        config.VersioningMode, config.ContinuousDeploymentFallbackTag,
                        gitVersionContext.IsCurrentCommitTagged);
                    foreach (var variable in variables)
                    {
                        thisType.GetProperty(variable.Key).SetValue(this, variable.Value, null);
                    }
                }
                return(true);
            }
            catch (WarningException errorException)
            {
                logger.LogWarning(errorException.Message);
                return(true);
            }
            catch (Exception exception)
            {
                logger.LogError("Error occurred: " + exception);
                return(false);
            }
            finally
            {
                Logger.Reset();
            }
        }
        public override bool Execute()
        {
            var gitFolder = GitDirFinder.TreeWalkForGitDir(ProjectFolder);

            if (string.IsNullOrEmpty(gitFolder))
            {
                if (TeamCity.IsRunningInBuildAgent()) //fail the build if we're on a TC build agent
                {
                    this.LogError("Failed to find .git directory on agent. Please make sure agent checkout mode is enabled for you VCS roots - http://confluence.jetbrains.com/display/TCD8/VCS+Checkout+Mode");
                    return(false);
                }

                var message = string.Format("No .git directory found in solution path '{0}'. This means the assembly may not be versioned correctly. To fix this warning either clone the repository using git or remove the `GitFlowVersion.Fody` nuget package. To temporarily work around this issue add a AssemblyInfo.cs with an appropriate `AssemblyVersionAttribute`.", ProjectFolder);
                this.LogWarning(message);

                return(true);
            }

            var versionAndBranch = VersionCache.GetVersion(gitFolder);

            WriteTeamCityParameters(versionAndBranch);
            var semanticVersion = versionAndBranch.Version;

            Version      = string.Format("{0}.{1}.{2}", semanticVersion.Major, semanticVersion.Minor, semanticVersion.Patch);
            FileVersion  = string.Format("{0}.{1}.{2}", semanticVersion.Major, semanticVersion.Minor, semanticVersion.Patch);
            InfoVersion  = versionAndBranch.ToLongString();
            NugetVersion = NugetVersionBuilder.GenerateNugetVersion(versionAndBranch);

            this.LogInfo(String.Format("Version number is {0} and InfoVersion is {1}", Version, InfoVersion));
            if (Files == null)
            {
                return(true);
            }
            var task = new UpdateAssemblyInfo(Files, Version, FileVersion);

            task.Execute();
            return(true);
        }
Exemple #11
0
        public void InnerExecute()
        {
            TempFileTracker.DeleteTempFiles();

            InvalidFileChecker.CheckForInvalidFiles(CompileFiles, ProjectFile);

            var gitDirectory = GitDirFinder.TreeWalkForGitDir(SolutionDirectory);

            if (string.IsNullOrEmpty(gitDirectory))
            {
                return;
            }

            var configuration = ConfigurationProvider.Provide(gitDirectory, fileSystem);

            Tuple <CachedVersion, GitVersionContext> semanticVersion;

            if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out semanticVersion, configuration))
            {
                return;
            }
            CreateTempAssemblyInfo(semanticVersion.Item1, semanticVersion.Item2.Configuration);
        }
Exemple #12
0
    public void From_WorkingDirectory_Parent()
    {
        var parentDirectory = Directory.GetParent(workDirectory).FullName;

        Assert.Null(GitDirFinder.TreeWalkForGitDir(parentDirectory));
    }
Exemple #13
0
        public static Context ParseArguments(List <string> commandLineArguments, IProviderManager providerManager)
        {
            var context = new Context(providerManager);

            if (commandLineArguments.Count == 0)
            {
                context.IsHelp = true;
                return(context);
            }

            var firstArgument = commandLineArguments.First();

            if (IsHelp(firstArgument))
            {
                context.IsHelp = true;
                return(context);
            }

            if (commandLineArguments.Count < 3 && commandLineArguments.Count != 1)
            {
                throw Log.ErrorAndCreateException <GitLinkException>("Invalid number of arguments");
            }

            context.SolutionDirectory = firstArgument;

            var namedArguments = commandLineArguments.Skip(1).ToList();

            for (var index = 0; index < namedArguments.Count; index++)
            {
                var name = namedArguments[index];

                // First check everything without values
                if (IsSwitch("debug", name))
                {
                    context.IsDebug = true;
                    continue;
                }

                if (IsSwitch("errorsaswarnings", name))
                {
                    context.ErrorsAsWarnings = true;
                    continue;
                }

                if (IsSwitch("skipverify", name))
                {
                    context.SkipVerify = true;
                    continue;
                }

                // After this point, all arguments should have a value
                index++;
                var valueInfo = GetValue(namedArguments, index);
                var value     = valueInfo.Key;
                index = index + (valueInfo.Value - 1);

                if (IsSwitch("l", name))
                {
                    context.LogFile = value;
                    continue;
                }

                if (IsSwitch("c", name))
                {
                    context.ConfigurationName = value;
                    continue;
                }

                if (IsSwitch("p", name))
                {
                    context.PlatformName = value;
                    continue;
                }

                if (IsSwitch("u", name))
                {
                    context.TargetUrl = value;
                    continue;
                }

                if (IsSwitch("b", name))
                {
                    context.TargetBranch = value;
                    continue;
                }

                if (IsSwitch("s", name))
                {
                    context.ShaHash = value;
                    continue;
                }

                if (IsSwitch("f", name))
                {
                    context.SolutionFile = value;
                    continue;
                }

                if (IsSwitch("d", name))
                {
                    context.PdbFilesDirectory = value;
                    continue;
                }

                if (IsSwitch("ignore", name))
                {
                    context.IgnoredProjects.AddRange(value.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()));
                    continue;
                }

                throw Log.ErrorAndCreateException <GitLinkException>("Could not parse command line parameter '{0}'.", name);
            }

            if (string.IsNullOrEmpty(context.TargetUrl))
            {
                Log.Info("No target url was specified, trying to determine the target url automatically");

                var gitDir = GitDirFinder.TreeWalkForGitDir(context.SolutionDirectory);
                if (gitDir != null)
                {
                    using (var repo = RepositoryLoader.GetRepo(gitDir))
                    {
                        var currentBranch = repo.Head;

                        if (string.IsNullOrEmpty(context.ShaHash))
                        {
                            context.ShaHash = currentBranch.Tip.Sha;
                        }

                        if (currentBranch.Remote == null || currentBranch.IsDetachedHead())
                        {
                            currentBranch = repo.GetBranchesContainingCommit(context.ShaHash).FirstOrDefault(b => b.Remote != null);
                        }

                        if (currentBranch != null && currentBranch.Remote != null)
                        {
                            var url = currentBranch.Remote.Url;
                            if (url.StartsWith("https://"))
                            {
                                context.TargetUrl = url.OptimizeUrl();

                                Log.Info("Automatically determine target url '{0}'", context.TargetUrl);
                            }
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(context.TargetUrl))
            {
                context.Provider = providerManager.GetProvider(context.TargetUrl);
            }

            return(context);
        }
Exemple #14
0
        private static int GenerateReleaseNotes(string[] args)
        {
            var modelBindingDefinition = Args.Configuration.Configure <GitReleaseNotesArguments>();

            if (args.Any(a => a == "/?" || a == "?" || a.Equals("/help", StringComparison.InvariantCultureIgnoreCase)))
            {
                var help = new HelpProvider().GenerateModelHelp(modelBindingDefinition);
                var f    = new ConsoleHelpFormatter();
                f.WriteHelp(help, Console.Out);

                return(0);
            }

            var arguments = modelBindingDefinition.CreateAndBind(args);

            if (!ArgumentVerifier.VerifyArguments(arguments))
            {
                return(1);
            }

            var workingDirectory = arguments.WorkingDirectory ?? Directory.GetCurrentDirectory();

            var gitDirectory = GitDirFinder.TreeWalkForGitDir(workingDirectory);

            if (string.IsNullOrEmpty(gitDirectory))
            {
                throw new Exception("Failed to find .git directory.");
            }

            Console.WriteLine("Git directory found at {0}", gitDirectory);

            var repositoryRoot = Directory.GetParent(gitDirectory).FullName;

            var gitRepo = new Repository(gitDirectory);

            CreateIssueTrackers(gitRepo, arguments);

            IIssueTracker issueTracker = null;

            if (arguments.IssueTracker == null)
            {
                var firstOrDefault = _issueTrackers.FirstOrDefault(i => i.Value.RemotePresentWhichMatches);
                if (firstOrDefault.Value != null)
                {
                    issueTracker = firstOrDefault.Value;
                }
            }
            if (issueTracker == null)
            {
                if (!_issueTrackers.ContainsKey(arguments.IssueTracker.Value))
                {
                    throw new Exception(string.Format("{0} is not a known issue tracker", arguments.IssueTracker.Value));
                }

                issueTracker = _issueTrackers[arguments.IssueTracker.Value];
            }
            if (!issueTracker.VerifyArgumentsAndWriteErrorsToConsole())
            {
                return(1);
            }

            var    fileSystem           = new FileSystem.FileSystem();
            var    releaseFileWriter    = new ReleaseFileWriter(fileSystem);
            string outputFile           = null;
            var    previousReleaseNotes = new SemanticReleaseNotes();

            if (!string.IsNullOrEmpty(arguments.OutputFile))
            {
                outputFile = Path.IsPathRooted(arguments.OutputFile)
                    ? arguments.OutputFile
                    : Path.Combine(repositoryRoot, arguments.OutputFile);
                previousReleaseNotes = new ReleaseNotesFileReader(fileSystem, repositoryRoot).ReadPreviousReleaseNotes(outputFile);
            }

            var          categories     = arguments.Categories == null ? Categories : Categories.Concat(arguments.Categories.Split(',')).ToArray();
            TaggedCommit tagToStartFrom = arguments.AllTags
                ? GitRepositoryInfoFinder.GetFirstCommit(gitRepo)
                : GitRepositoryInfoFinder.GetLastTaggedCommit(gitRepo) ?? GitRepositoryInfoFinder.GetFirstCommit(gitRepo);
            var currentReleaseInfo = GitRepositoryInfoFinder.GetCurrentReleaseInfo(gitRepo);

            if (!string.IsNullOrEmpty(arguments.Version))
            {
                currentReleaseInfo.Name = arguments.Version;
                currentReleaseInfo.When = DateTimeOffset.Now;
            }
            var releaseNotes = ReleaseNotesGenerator.GenerateReleaseNotes(
                gitRepo, issueTracker,
                previousReleaseNotes, categories,
                tagToStartFrom, currentReleaseInfo,
                issueTracker.DiffUrlFormat);

            var releaseNotesOutput = releaseNotes.ToString();

            releaseFileWriter.OutputReleaseNotesFile(releaseNotesOutput, outputFile);

            return(0);
        }
Exemple #15
0
 public void From_GitDirectory()
 {
     Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForGitDir(gitDirectory));
 }
Exemple #16
0
        public static bool Link(string pdbPath, LinkOptions options = default(LinkOptions))
        {
            Argument.IsNotNullOrEmpty(() => pdbPath);

            var    projectSrcSrvFile = pdbPath + ".srcsrv";
            string repositoryDirectory;
            IReadOnlyCollection <string>         sourceFiles;
            IReadOnlyDictionary <string, string> repoSourceFiles;

            using (var pdb = new PdbFile(pdbPath))
            {
                sourceFiles = pdb.GetFilesAndChecksums().Keys.ToList();

                if (options.GitWorkingDirectory != null)
                {
                    repositoryDirectory = Path.Combine(options.GitWorkingDirectory, ".git");
                }
                else
                {
                    repositoryDirectory = GitDirFinder.TreeWalkForGitDir(Path.GetDirectoryName(sourceFiles.First()));
                    if (repositoryDirectory == null)
                    {
                        Log.Error("No source files found that are tracked in a git repo.");
                        return(false);
                    }
                }

                string workingDirectory = Path.GetDirectoryName(repositoryDirectory);

                var repository = new Lazy <Repository>(() => new Repository(repositoryDirectory));
                try
                {
                    string commitId = options.CommitId ?? repository.Value.Head.Commits.FirstOrDefault()?.Sha;
                    if (commitId == null)
                    {
                        Log.Error("No commit is checked out to HEAD. Have you committed yet?");
                        return(false);
                    }

                    var providerManager = new Providers.ProviderManager();
                    Providers.IProvider provider;
                    if (options.GitRemoteUrl == null)
                    {
                        var candidateProviders = from remote in repository.Value.Network.Remotes
                                                 let p = providerManager.GetProvider(remote.Url)
                                                         where p != null
                                                         select p;
                        provider = candidateProviders.FirstOrDefault();
                    }
                    else
                    {
                        provider = providerManager.GetProvider(options.GitRemoteUrl.AbsoluteUri);
                    }

                    if (provider == null)
                    {
                        Log.Error("Unable to detect the remote git service.");
                        return(false);
                    }

                    try
                    {
                        Repository repo = repository.Value;
                        repoSourceFiles = sourceFiles.ToDictionary(e => e, e => GetNormalizedPath(e, repo));
                    }
                    catch (RepositoryNotFoundException)
                    {
                        // Normalize using file system since we can't find the git repo.
                        Log.Warning($"Unable to find git repo at \"{options.GitWorkingDirectory}\". Using file system to find canonical capitalization of file paths.");
                        repoSourceFiles = sourceFiles.ToDictionary(e => e, e => GetNormalizedPath(e, workingDirectory));
                    }

                    if (!options.SkipVerify)
                    {
                        Log.Debug("Verifying pdb file");

                        var missingFiles = pdb.FindMissingOrChangedSourceFiles();
                        foreach (var missingFile in missingFiles)
                        {
                            Log.Warning($"File \"{missingFile}\" missing or changed since the PDB was compiled.");
                        }
                    }

                    string rawUrl = provider.RawGitUrl;
                    if (rawUrl.Contains(RevisionPlaceholder) || rawUrl.Contains(FilenamePlaceholder))
                    {
                        if (!rawUrl.Contains(RevisionPlaceholder) || !rawUrl.Contains(FilenamePlaceholder))
                        {
                            Log.Error("Supplied custom URL pattern must contain both a revision and a filename placeholder.");
                            return(false);
                        }

                        rawUrl = rawUrl
                                 .Replace(RevisionPlaceholder, "{0}")
                                 .Replace(FilenamePlaceholder, "%var2%");
                    }
                    else
                    {
                        rawUrl = $"{rawUrl}/{{0}}/%var2%";
                    }

                    Log.Info($"Using {string.Format(rawUrl, commitId)} for source server URLs.");
                    var srcSrvContext = new SrcSrvContext
                    {
                        RawUrl = rawUrl,
                        DownloadWithPowershell = options.Method == LinkMethod.Powershell,
                        Revision = commitId,
                    };
                    foreach (var sourceFile in repoSourceFiles)
                    {
                        // Skip files that aren't tracked by source control.
                        if (sourceFile.Value != null)
                        {
                            srcSrvContext.Paths.Add(Tuple.Create(sourceFile.Key, sourceFile.Value.Replace('\\', '/')));
                        }
                    }

                    if (provider is Providers.VisualStudioTeamServicesProvider)
                    {
                        srcSrvContext.VstsData["TFS_COLLECTION"]   = provider.CompanyUrl;
                        srcSrvContext.VstsData["TFS_TEAM_PROJECT"] = provider.ProjectName;
                        srcSrvContext.VstsData["TFS_REPO"]         = provider.ProjectName;
                    }

                    CreateSrcSrv(projectSrcSrvFile, srcSrvContext);
                }
                catch (RepositoryNotFoundException)
                {
                    Log.Error($"Unable to find git repo at \"{options.GitWorkingDirectory}\".");
                    return(false);
                }
                finally
                {
                    if (repository.IsValueCreated)
                    {
                        repository.Value.Dispose();
                    }
                }
            }

            Log.Debug("Created source server link file, updating pdb file '{0}'", Catel.IO.Path.GetRelativePath(pdbPath, repositoryDirectory));
            PdbStrHelper.Execute(PdbStrExePath, pdbPath, projectSrcSrvFile);
            var indexedFilesCount = repoSourceFiles.Values.Count(v => v != null);

            Log.Info($"Remote git source information for {indexedFilesCount}/{sourceFiles.Count} files written to pdb: \"{pdbPath}\"");

            return(true);
        }
Exemple #17
0
    public void From_RefsDirectory()
    {
        var refsDirectory = Path.Combine(gitDirectory, "refs");

        Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForGitDir(refsDirectory));
    }
Exemple #18
0
        public static bool Link(string pdbPath, LinkOptions options = default(LinkOptions))
        {
            Argument.IsNotNullOrEmpty(() => pdbPath);

            var    projectSrcSrvFile   = pdbPath + ".srcsrv";
            string repositoryDirectory = null;
            IReadOnlyList <string> sourceFiles;
            IReadOnlyDictionary <string, string> repoSourceFiles;

            if (options.GitWorkingDirectory != null)
            {
                repositoryDirectory = Path.Combine(options.GitWorkingDirectory, ".git");
                if (!Directory.Exists(repositoryDirectory))
                {
                    Log.Error("Provided directory does not contain a git depot.");
                    return(false);
                }
            }

            if (PortablePdbHelper.IsPortablePdb(pdbPath))
            {
                Log.Warning("Portable PDB format is not compatible with GitLink. Please use SourceLink (https://github.com/ctaggart/SourceLink).");
                return(true);
            }

            if (options.IndexAllDepotFiles)
            {
                if (repositoryDirectory == null)
                {
                    repositoryDirectory = GitDirFinder.TreeWalkForGitDir(Path.GetDirectoryName(pdbPath));
                    if (repositoryDirectory == null)
                    {
                        Log.Error("Couldn't auto detect git repo. Please use -baseDir to manually set it.");
                        return(false);
                    }
                }

                sourceFiles = GetSourceFilesFromDepot(repositoryDirectory);
            }
            else
            {
                sourceFiles = GetSourceFilesFromPdb(pdbPath, !options.SkipVerify);

                string someSourceFile = sourceFiles.FirstOrDefault();
                if (someSourceFile == null)
                {
                    Log.Error("No source files were found in the PDB. If you're PDB is a native one you should use -a option.");
                    return(false);
                }

                if (repositoryDirectory == null)
                {
                    repositoryDirectory = GitDirFinder.TreeWalkForGitDir(Path.GetDirectoryName(sourceFiles.FirstOrDefault()));
                    if (repositoryDirectory == null)
                    {
                        Log.Error("No source files found that are tracked in a git repo.");
                        return(false);
                    }
                }
            }

            string workingDirectory = Path.GetDirectoryName(repositoryDirectory);

            var repository = new Lazy <Repository>(() => new Repository(repositoryDirectory));

            try
            {
                string commitId = options.CommitId ?? repository.Value.Head.Commits.FirstOrDefault()?.Sha;
                if (commitId == null)
                {
                    Log.Error("No commit is checked out to HEAD. Have you committed yet?");
                    return(false);
                }

                var providerManager = new Providers.ProviderManager();
                Providers.IProvider provider;
                if (options.GitRemoteUrl == null)
                {
                    var candidateProviders = from remote in repository.Value.Network.Remotes
                                             let p = providerManager.GetProvider(remote.Url)
                                                     where p != null
                                                     select p;
                    provider = candidateProviders.FirstOrDefault();
                }
                else
                {
                    provider = providerManager.GetProvider(options.GitRemoteUrl.AbsoluteUri);
                }

                if (provider == null)
                {
                    Log.Error("Unable to detect the remote git service.");
                    return(false);
                }

                try
                {
                    Repository repo = repository.Value;
                    repoSourceFiles = sourceFiles.ToDictionary(e => e, e => repo.GetNormalizedPath(e));
                }
                catch (RepositoryNotFoundException)
                {
                    // Normalize using file system since we can't find the git repo.
                    Log.Warning($"Unable to find git repo at \"{options.GitWorkingDirectory}\". Using file system to find canonical capitalization of file paths.");
                    repoSourceFiles = sourceFiles.ToDictionary(e => e, e => GetNormalizedPath(e, workingDirectory));
                }

                string rawUrl = provider.RawGitUrl;
                if (rawUrl.Contains(RevisionPlaceholder) || rawUrl.Contains(FilenamePlaceholder))
                {
                    if (!rawUrl.Contains(RevisionPlaceholder) || !rawUrl.Contains(FilenamePlaceholder))
                    {
                        Log.Error("Supplied custom URL pattern must contain both a revision and a filename placeholder.");
                        return(false);
                    }

                    rawUrl = rawUrl
                             .Replace(RevisionPlaceholder, "{0}")
                             .Replace(FilenamePlaceholder, "%var2%");
                }
                else
                {
                    rawUrl = $"{rawUrl}/{{0}}/%var2%";
                }

                Log.Info($"Using {string.Format(rawUrl, commitId)} for source server URLs.");
                var srcSrvContext = new SrcSrvContext
                {
                    RawUrl = rawUrl,
                    DownloadWithPowershell = options.Method == LinkMethod.Powershell,
                    Revision = commitId,
                };
                foreach (var sourceFile in repoSourceFiles)
                {
                    // Skip files that aren't tracked by source control.
                    if (sourceFile.Value != null)
                    {
                        string relativePathForUrl = ReplaceSlashes(provider, sourceFile.Value);
                        srcSrvContext.Paths.Add(Tuple.Create(sourceFile.Key, relativePathForUrl));
                    }
                }

                // When using the VisualStudioTeamServicesProvider, add extra infomration to dictionary with VSTS-specific data
                if (provider is Providers.VisualStudioTeamServicesProvider)
                {
                    srcSrvContext.VstsData["TFS_COLLECTION"]   = provider.CompanyUrl;
                    srcSrvContext.VstsData["TFS_TEAM_PROJECT"] = provider.ProjectName;
                    srcSrvContext.VstsData["TFS_REPO"]         = provider.ProjectUrl;
                }

                CreateSrcSrv(projectSrcSrvFile, srcSrvContext);
            }
            catch (RepositoryNotFoundException)
            {
                Log.Error($"Unable to find git repo at \"{options.GitWorkingDirectory}\".");
                return(false);
            }
            finally
            {
                if (repository.IsValueCreated)
                {
                    repository.Value.Dispose();
                }
            }

            Log.Debug("Created source server link file, updating pdb file \"{0}\"", Catel.IO.Path.GetRelativePath(pdbPath, repositoryDirectory));
            PdbStrHelper.Execute(PdbStrExePath, pdbPath, projectSrcSrvFile);
            var indexedFilesCount = repoSourceFiles.Values.Count(v => v != null);

            Log.Info($"Remote git source information for {indexedFilesCount}/{sourceFiles.Count} files written to pdb: \"{pdbPath}\"");

            return(true);
        }