Exemple #1
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);
        }
Exemple #2
0
        private static bool LinkProject(Context context, Project project, string shaHash)
        {
            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());

                var projectPdbFile    = Path.GetFullPath(project.GetOutputPdbFile());
                var projectStcSrvFile = Path.GetFullPath(project.GetOutputSrcSrvFile());
                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);
                }

                Log.Info("Verifying pdb file");

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

                var rawUrl = string.Format("{0}/{{0}}/%var2%", context.Provider.RawGitUrl);
                var paths  = new Dictionary <string, string>();
                foreach (var compilable in compilables)
                {
                    var relativePathForUrl = compilable.Replace(context.SolutionDirectory, string.Empty).Replace("\\", "/");
                    while (relativePathForUrl.StartsWith("/"))
                    {
                        relativePathForUrl = relativePathForUrl.Substring(1, relativePathForUrl.Length - 1);
                    }

                    paths.Add(compilable, relativePathForUrl);
                }

                project.CreateSrcSrv(rawUrl, shaHash, paths);

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

                PdbStrHelper.Execute(projectPdbFile, projectStcSrvFile);
            }
            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);
        }
Exemple #3
0
        public static int Link(Context context)
        {
            int?exitCode = null;

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            context.ValidateContext();

            if (!string.IsNullOrEmpty(context.LogFile))
            {
                var fileLogListener = new FileLogListener(context.LogFile, 25 * 1024);
                fileLogListener.IsDebugEnabled = context.IsDebug;

                fileLogListener.IgnoreCatelLogging = true;
                LogManager.AddListener(fileLogListener);
            }

            if (!PdbStrHelper.IsPdbStrAvailable())
            {
                Log.Error("PdbStr is not found on the computer, please install 'Debugging Tools for Windows'");
                return(-1);
            }

            try
            {
                var      projects = new List <Project>();
                string[] solutionFiles;
                if (string.IsNullOrEmpty(context.SolutionFile))
                {
                    solutionFiles = Directory.GetFiles(context.SolutionDirectory, "*.sln", SearchOption.AllDirectories);
                }
                else
                {
                    var pathToSolutionFile = Path.Combine(context.SolutionDirectory, context.SolutionFile);
                    if (!File.Exists(pathToSolutionFile))
                    {
                        Log.Error("Could not find solution file: " + pathToSolutionFile);
                        return(-1);
                    }

                    solutionFiles = new[] { pathToSolutionFile };
                }

                foreach (var solutionFile in solutionFiles)
                {
                    var solutionProjects = ProjectHelper.GetProjects(solutionFile, context.ConfigurationName, context.PlatformName);
                    projects.AddRange(solutionProjects);
                }

                var provider = context.Provider;
                if (provider == null)
                {
                    Log.ErrorAndThrowException <GitLinkException>("Cannot find a matching provider for '{0}'", context.TargetUrl);
                }

                Log.Info("Using provider '{0}'", provider.GetType().Name);

                var shaHash = context.Provider.GetShaHashOfCurrentBranch(context);

                Log.Info("Using commit sha '{0}' as version stamp", shaHash);

                var projectCount   = projects.Count();
                var failedProjects = new List <Project>();
                Log.Info("Found '{0}' project(s)", projectCount);
                Log.Info(string.Empty);

                foreach (var project in projects)
                {
                    try
                    {
                        if (project.ShouldBeIgnored(context.IgnoredProjects))
                        {
                            Log.Info("Ignoring '{0}'", project.GetProjectName());
                            Log.Info(string.Empty);
                            continue;
                        }

                        if (context.IsDebug)
                        {
                            project.DumpProperties();
                        }

                        if (!LinkProject(context, project, shaHash))
                        {
                            failedProjects.Add(project);
                        }
                    }
                    catch (Exception)
                    {
                        failedProjects.Add(project);
                    }
                }

                Log.Info("All projects are done. {0} of {1} succeeded", projectCount - failedProjects.Count, projectCount);

                if (failedProjects.Count > 0)
                {
                    Log.Info(string.Empty);
                    Log.Info("The following projects have failed:");
                    Log.Indent();

                    foreach (var failedProject in failedProjects)
                    {
                        Log.Info("* {0}", context.GetRelativePath(failedProject.GetProjectName()));
                    }

                    Log.Unindent();
                }

                exitCode = (failedProjects.Count == 0) ? 0 : -1;
            }
            catch (GitLinkException ex)
            {
                Log.Error(ex, "An error occurred");
            }
            catch (Exception ex)
            {
                Log.Error(ex, "An unexpected error occurred");
            }

            stopWatch.Stop();

            Log.Info(string.Empty);
            Log.Info("Completed in '{0}'", stopWatch.Elapsed);

            return(exitCode ?? -1);
        }
Exemple #4
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
                {
                    string someSourceFile = sourceFiles.FirstOrDefault();
                    if (someSourceFile == null)
                    {
                        Log.Error("No source files were found in the PDB.");
                        return(false);
                    }

                    repositoryDirectory = GitDirFinder.TreeWalkForGitDir(Path.GetDirectoryName(someSourceFile));
                    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));
                    }

                    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)
                        {
                            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);
        }