VerifyCommand.cs 5.0 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 18
        private readonly string _sourcesDirectory;
        private readonly string _generateDirectory;
J
Jared Parsons 已提交
19
        private readonly RepoConfig _repoConfig;
J
Jared Parsons 已提交
20

21
        internal VerifyCommand(RepoConfig repoConfig, string sourcesDir, string generateDir)
J
Jared Parsons 已提交
22
        {
J
Jared Parsons 已提交
23
            _repoConfig = repoConfig;
24 25
            _sourcesDirectory = sourcesDir;
            _generateDirectory = generateDir;
J
Jared Parsons 已提交
26 27
        }

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

            writer.WriteLine($"Error! RepoUtil verification failed.");
            return false;
J
Jared Parsons 已提交
40 41
        }

J
Jared Parsons 已提交
42 43 44 45
        /// <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>
46
        private bool VerifyProjectJsonContents(TextWriter writer, out RepoData repoData)
J
Jared Parsons 已提交
47
        {
J
Jared Parsons 已提交
48
            writer.WriteLine($"Verifying project.json contents");
J
Jared Parsons 已提交
49

50
            List<NuGetPackageConflict> conflicts;
51
            repoData = RepoData.Create(_repoConfig, _sourcesDirectory, out conflicts);
52 53 54 55 56 57 58 59
            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 已提交
60
                }
61 62

                return false;
J
Jared Parsons 已提交
63 64
            }

65
            return true;
J
Jared Parsons 已提交
66
        }
67 68 69 70 71 72 73 74 75 76

        /// <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
77
                .GetProjectJsonFiles(_sourcesDirectory)
78
                .SelectMany(x => ProjectJsonUtil.GetDependencies(x));
79
            var set = new HashSet<NuGetPackage>(packages, default(Constants.IgnoreGenerateNameComparer));
80 81
            var allGood = true;

82
            foreach (var fixedPackage in _repoConfig.FixedPackages)
83
            {
84
                if (!set.Contains(fixedPackage))
85
                {
86
                    writer.WriteLine($"Error: Fixed package {fixedPackage.Name} - {fixedPackage.Version} is not used anywhere");
87 88 89 90 91 92
                    allGood = false;
                }
            }

            return allGood;
        }
J
Jared Parsons 已提交
93

94
        private bool VerifyGeneratedFiles(TextWriter writer, RepoData repoData)
J
Jared Parsons 已提交
95 96 97 98 99 100
        {
            var allGood = true;
            writer.WriteLine($"Verifying generated files");
            if (_repoConfig.MSBuildGenerateData.HasValue)
            {
                var data = _repoConfig.MSBuildGenerateData.Value;
101
                var packages = GenerateUtil.GetFilteredPackages(data, repoData);
102 103

                // Need to verify the contents of the generated file are correct.
104
                var fileName = new FileName(_generateDirectory, data.RelativeFilePath);
J
Jared Parsons 已提交
105 106 107 108 109 110 111 112
                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;
                }

113 114 115 116 117 118 119 120 121 122 123 124 125
                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 已提交
126 127
            }

128
            return allGood;
J
Jared Parsons 已提交
129
        }
J
Jared Parsons 已提交
130 131
    }
}