VerifyCommand.cs 4.7 KB
Newer Older
J
Jared Parsons 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RepoUtil
{
    /// <summary>
    /// This utility is used to verify the repo is in a consistent state with respect to NuGet references. 
    /// </summary>
J
Jared Parsons 已提交
15
    internal sealed class VerifyCommand : ICommand
J
Jared Parsons 已提交
16 17
    {
        private readonly string _sourcesPath;
J
Jared Parsons 已提交
18
        private readonly RepoConfig _repoConfig;
J
Jared Parsons 已提交
19

J
Jared Parsons 已提交
20
        internal VerifyCommand(RepoConfig repoConfig, string sourcesPath)
J
Jared Parsons 已提交
21
        {
J
Jared Parsons 已提交
22
            _repoConfig = repoConfig;
J
Jared Parsons 已提交
23 24 25
            _sourcesPath = sourcesPath;
        }

J
Jared Parsons 已提交
26
        public bool Run(TextWriter writer, string[] args)
J
Jared Parsons 已提交
27
        {
28
            RepoData repoData;
29
            return
30
                VerifyProjectJsonContents(writer, out repoData) &&
J
Jared Parsons 已提交
31
                VerifyRepoConfig(writer) &&
32
                VerifyGeneratedFiles(writer, repoData);
J
Jared Parsons 已提交
33 34
        }

J
Jared Parsons 已提交
35 36 37 38
        /// <summary>
        /// Verify the packages listed in project.json are well formed.  Packages should all either have the same version or 
        /// be explicitly fixed in the config file.
        /// </summary>
39
        private bool VerifyProjectJsonContents(TextWriter writer, out RepoData repoData)
J
Jared Parsons 已提交
40
        {
J
Jared Parsons 已提交
41
            writer.WriteLine($"Verifying project.json contents");
J
Jared Parsons 已提交
42

43 44 45 46 47 48 49 50 51 52
            List<NuGetPackageConflict> conflicts;
            repoData = RepoData.Create(_repoConfig, _sourcesPath, out conflicts);
            if (conflicts?.Count > 0)
            { 
                foreach (var conflict in conflicts)
                {
                    writer.WriteLine($"Error! Package {conflict.PackageName} has different versions:");
                    writer.WriteLine($"\t{conflict.Original.FileName} at {conflict.Original.NuGetPackage.Version}");
                    writer.WriteLine($"\t{conflict.Conflict.FileName} at {conflict.Conflict.NuGetPackage.Version}");
                    writer.WriteLine($"The versions must be the same or one must be explicitly listed as fixed in RepoData.json");
J
Jared Parsons 已提交
53
                }
54 55

                return false;
J
Jared Parsons 已提交
56 57
            }

58
            return true;
J
Jared Parsons 已提交
59
        }
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

        /// <summary>
        /// Verify that all of the data contained in the repo configuration is valid.  In particular that it hasn't gotten
        /// stale and referring to invalid packages.
        /// </summary>
        /// <param name="writer"></param>
        private bool VerifyRepoConfig(TextWriter writer)
        {
            writer.WriteLine($"Verifying RepoData.json");
            var packages = ProjectJsonUtil
                .GetProjectJsonFiles(_sourcesPath)
                .SelectMany(x => ProjectJsonUtil.GetDependencies(x));
            var set = new HashSet<NuGetPackage>(packages);
            var allGood = true;

            foreach (var package in _repoConfig.FixedPackages)
            {
                if (!set.Contains(package))
                {
                    writer.WriteLine($"Error: Fixed package {package.Name} - {package.Version} is not used anywhere");
                    allGood = false;
                }
            }

            return allGood;
        }
J
Jared Parsons 已提交
86

87
        private bool VerifyGeneratedFiles(TextWriter writer, RepoData repoData)
J
Jared Parsons 已提交
88 89 90 91 92 93
        {
            var allGood = true;
            writer.WriteLine($"Verifying generated files");
            if (_repoConfig.MSBuildGenerateData.HasValue)
            {
                var data = _repoConfig.MSBuildGenerateData.Value;
94
                var packages = GenerateUtil.GetFilteredPackages(data, repoData);
95 96

                // Need to verify the contents of the generated file are correct.
J
Jared Parsons 已提交
97 98 99 100 101 102 103 104 105
                var fileName = new FileName(_sourcesPath, data.RelativeFileName);
                var actualContent = File.ReadAllText(fileName.FullPath, GenerateUtil.Encoding);
                var expectedContent = GenerateUtil.GenerateMSBuildContent(packages);
                if (actualContent != expectedContent)
                {
                    writer.WriteLine($"{fileName.RelativePath} does not have the expected contents");
                    allGood = false;
                }

106 107 108 109 110 111 112 113 114 115 116 117 118
                if (!allGood)
                {
                    writer.WriteLine($@"Generated contents out of date. Run ""RepoUtil.change"" to correct");
                    return false;
                }

                // Verify none of the regex entries are stale.
                var staleRegexList = GenerateUtil.GetStaleRegex(data, repoData);
                foreach (var regex in staleRegexList)
                {
                    writer.WriteLine($"Regex {regex} matches no packages");
                    allGood = false;
                }
J
Jared Parsons 已提交
119 120
            }

121
            return allGood;
J
Jared Parsons 已提交
122
        }
J
Jared Parsons 已提交
123 124
    }
}