Example #1
0
        public static void CreateSrcSrv(this Project project, SrcSrvContext srcSrvContext)
        {
            Argument.IsNotNull(() => project);
            Argument.IsNotNull(() => srcSrvContext);

            Argument.IsNotNullOrWhitespace("rawUrl", srcSrvContext.RawUrl);
            Argument.IsNotNullOrWhitespace("revision", srcSrvContext.Revision);

            var srcsrvFile = GetOutputSrcSrvFile(project);

            CreateSrcSrv(project, srcsrvFile, srcSrvContext);
        }
Example #2
0
        public static void CreateSrcSrv(this Project project, SrcSrvContext srcSrvContext)
        {
            Argument.IsNotNull(() => project);
            Argument.IsNotNull(() => srcSrvContext);

            Argument.IsNotNullOrWhitespace("rawUrl", srcSrvContext.RawUrl);
            Argument.IsNotNullOrWhitespace("revision", srcSrvContext.Revision);

            var srcsrvFile = GetOutputSrcSrvFile(project);

            CreateSrcSrv(project, srcsrvFile, srcSrvContext);
        }
Example #3
0
        private static void CreateSrcSrv(string srcsrvFile, SrcSrvContext srcSrvContext)
        {
            Argument.IsNotNull(() => srcSrvContext);
            Argument.IsNotNullOrWhitespace(() => srcSrvContext.RawUrl);
            Argument.IsNotNullOrWhitespace(() => srcSrvContext.Revision);
            Argument.IsNotNullOrWhitespace(() => srcsrvFile);

            if (srcSrvContext.VstsData.Count != 0)
            {
                File.WriteAllBytes(srcsrvFile, SrcSrv.CreateVsts(srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.VstsData));
            }
            else
            {
                File.WriteAllBytes(srcsrvFile, SrcSrv.Create(srcSrvContext.RawUrl, srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.DownloadWithPowershell));
            }
        }
Example #4
0
        private static void CreateSrcSrv(string srcsrvFile, SrcSrvContext srcSrvContext)
        {
            Argument.IsNotNull(nameof(srcSrvContext), srcSrvContext);
            Argument.IsNotNullOrWhitespace(nameof(srcSrvContext) + "." + nameof(srcSrvContext.RawUrl), srcSrvContext.RawUrl);
            Argument.IsNotNullOrWhitespace(nameof(srcSrvContext) + "." + nameof(srcSrvContext.Revision), srcSrvContext.Revision);
            Argument.IsNotNullOrWhitespace(nameof(srcsrvFile), srcsrvFile);

            if (srcSrvContext.VstsData.Count != 0)
            {
                Log.Debug("Writing VSTS specific bytes to srcsrv file because VstsData was not empty.");
                File.WriteAllBytes(srcsrvFile, SrcSrv.CreateVsts(srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.VstsData));
            }
            else
            {
                File.WriteAllBytes(srcsrvFile, SrcSrv.Create(srcSrvContext.RawUrl, srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.DownloadWithPowershell));
            }
        }
Example #5
0
        public static void CreateSrcSrv(this Project project, string srcsrvFile, SrcSrvContext srcSrvContext)
        {
            Argument.IsNotNull(() => project);
            Argument.IsNotNull(() => srcSrvContext);
            Argument.IsNotNullOrWhitespace("rawUrl", srcSrvContext.RawUrl);
            Argument.IsNotNullOrWhitespace("revision", srcSrvContext.Revision);
            Argument.IsNotNullOrWhitespace(() => srcsrvFile);

            if (srcSrvContext.VstsData.Count != 0)
            {
                File.WriteAllBytes(srcsrvFile, SrcSrv.CreateVsts(srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.VstsData));
            }
            else
            {
                File.WriteAllBytes(srcsrvFile, SrcSrv.Create(srcSrvContext.RawUrl, srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.DownloadWithPowershell));
            }
        }
Example #6
0
        private static bool LinkProject(Context context, Project project, string pdbStrFile, string shaHash, string pathPdbDirectory = null)
        {
            Argument.IsNotNull(() => context);
            Argument.IsNotNull(() => project);

            try
            {
                var projectName = project.GetProjectName();

                Log.Info("Handling project '{0}'", projectName);

                Log.Indent();

                var compilables = project.GetCompilableItems().Select(x => x.GetFullFileName()).ToList();

                var outputPdbFile  = project.GetOutputPdbFile();
                var projectPdbFile = pathPdbDirectory != null?Path.Combine(pathPdbDirectory, Path.GetFileName(outputPdbFile)) : Path.GetFullPath(outputPdbFile);

                var projectSrcSrvFile = projectPdbFile + ".srcsrv";

                var srcSrvContext = new SrcSrvContext
                {
                    Revision = shaHash,
                    RawUrl   = context.Provider.RawGitUrl,
                    DownloadWithPowershell = context.DownloadWithPowershell
                };

                if (!File.Exists(projectPdbFile))
                {
                    Log.Warning("No pdb file found for '{0}', is project built in '{1}' mode with pdb files enabled? Expected file is '{2}'", projectName, context.ConfigurationName, projectPdbFile);
                    return(false);
                }

                if (!context.SkipVerify)
                {
                    Log.Info("Verifying pdb file");

                    var missingFiles = project.VerifyPdbFiles(compilables, projectPdbFile);
                    foreach (var missingFile in missingFiles)
                    {
                        Log.Warning("Missing file '{0}' or checksum '{1}' did not match", missingFile.Key, missingFile.Value);
                    }
                }

                if (!srcSrvContext.RawUrl.Contains("%var2%") && !srcSrvContext.RawUrl.Contains("{0}"))
                {
                    srcSrvContext.RawUrl = string.Format("{0}/{{0}}/%var2%", srcSrvContext.RawUrl);
                }

                foreach (var compilable in compilables)
                {
                    var relativePathForUrl = ReplaceSlashes(context.Provider, compilable.Replace(context.SolutionDirectory, string.Empty));
                    while (relativePathForUrl.StartsWith("/"))
                    {
                        relativePathForUrl = relativePathForUrl.Substring(1, relativePathForUrl.Length - 1);
                    }

                    srcSrvContext.Paths.Add(new Tuple <string, string>(compilable, relativePathForUrl));
                }

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

                project.CreateSrcSrv(projectSrcSrvFile, srcSrvContext);

                Log.Debug("Created source server link file, updating pdb file '{0}'", context.GetRelativePath(projectPdbFile));

                PdbStrHelper.Execute(pdbStrFile, projectPdbFile, projectSrcSrvFile);
            }
            catch (Exception ex)
            {
                Log.Warning(ex, "An error occurred while processing project '{0}'", project.GetProjectName());
                throw;
            }
            finally
            {
                Log.Unindent();
                Log.Info(string.Empty);
            }

            return(true);
        }
Example #7
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);
        }
Example #8
0
        private static bool LinkProject(Context context, Project project, string pdbStrFile, string shaHash, string pathPdbDirectory = null)
        {
            Argument.IsNotNull(() => context);
            Argument.IsNotNull(() => project);

            try
            {
                var projectName = project.GetProjectName();

                Log.Info("Handling project '{0}'", projectName);

                Log.Indent();

                var compilables = project.GetCompilableItems().Select(x => x.GetFullFileName()).ToList();

                var outputPdbFile = project.GetOutputPdbFile();
                var projectPdbFile = pathPdbDirectory != null ? Path.Combine(pathPdbDirectory, Path.GetFileName(outputPdbFile)) : Path.GetFullPath(outputPdbFile);
                var projectSrcSrvFile = projectPdbFile + ".srcsrv";

                var srcSrvContext = new SrcSrvContext
                {
                    Revision = shaHash,
                    RawUrl = context.Provider.RawGitUrl,
                    DownloadWithPowershell = context.DownloadWithPowershell
                };

                if (!File.Exists(projectPdbFile))
                {
                    Log.Warning("No pdb file found for '{0}', is project built in '{1}' mode with pdb files enabled? Expected file is '{2}'", projectName, context.ConfigurationName, projectPdbFile);
                    return false;
                }

                if (!context.SkipVerify)
                {
                    Log.Info("Verifying pdb file");

                    var missingFiles = project.VerifyPdbFiles(compilables, projectPdbFile);
                    foreach (var missingFile in missingFiles)
                    {
                        Log.Warning("Missing file '{0}' or checksum '{1}' did not match", missingFile.Key, missingFile.Value);
                    }
                }

                if (!srcSrvContext.RawUrl.Contains("%var2%") && !srcSrvContext.RawUrl.Contains("{0}"))
                {
                    srcSrvContext.RawUrl = string.Format("{0}/{{0}}/%var2%", srcSrvContext.RawUrl);
                }

                foreach (var compilable in compilables)
                {
                    var relativePathForUrl = ReplaceSlashes(context.Provider, compilable.Replace(context.SolutionDirectory, string.Empty));
                    while (relativePathForUrl.StartsWith("/"))
                    {
                        relativePathForUrl = relativePathForUrl.Substring(1, relativePathForUrl.Length - 1);
                    }

                    srcSrvContext.Paths.Add(new Tuple<string, string>(compilable, relativePathForUrl));
                }

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

                project.CreateSrcSrv(projectSrcSrvFile, srcSrvContext);

                Log.Debug("Created source server link file, updating pdb file '{0}'", context.GetRelativePath(projectPdbFile));

                PdbStrHelper.Execute(pdbStrFile, projectPdbFile, projectSrcSrvFile);
            }
            catch (Exception ex)
            {
                Log.Warning(ex, "An error occurred while processing project '{0}'", project.GetProjectName());
                throw;
            }
            finally
            {
                Log.Unindent();
                Log.Info(string.Empty);
            }

            return true;
        }
Example #9
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);
        }