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); }
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); }
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); }
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(); } }
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)); }
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); }
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); }
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); }
public void From_WorkingDirectory_Parent() { var parentDirectory = Directory.GetParent(workDirectory).FullName; Assert.Null(GitDirFinder.TreeWalkForGitDir(parentDirectory)); }
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); }
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); }
public void From_GitDirectory() { Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForGitDir(gitDirectory)); }
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); }
public void From_RefsDirectory() { var refsDirectory = Path.Combine(gitDirectory, "refs"); Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForGitDir(refsDirectory)); }
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); }