VerifyCommand.cs 4.9 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;
J
Jared Parsons 已提交
29
            if (VerifyProjectJsonContents(writer, out repoData) &&
J
Jared Parsons 已提交
30
                VerifyRepoConfig(writer) &&
J
Jared Parsons 已提交
31 32 33 34 35 36 37
                VerifyGeneratedFiles(writer, repoData))
            {
                return true;
            }

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

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

48 49 50 51 52 53 54 55 56 57
            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 已提交
58
                }
59 60

                return false;
J
Jared Parsons 已提交
61 62
            }

63
            return true;
J
Jared Parsons 已提交
64
        }
65 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
                .GetProjectJsonFiles(_sourcesPath)
                .SelectMany(x => ProjectJsonUtil.GetDependencies(x));
77
            var set = new HashSet<NuGetPackage>(packages, default(Constants.IgnoreGenerateNameComparer));
78 79
            var allGood = true;

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

            return allGood;
        }
J
Jared Parsons 已提交
91

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

                // Need to verify the contents of the generated file are correct.
J
Jared Parsons 已提交
102 103 104 105 106 107 108 109 110
                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;
                }

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

126
            return allGood;
J
Jared Parsons 已提交
127
        }
J
Jared Parsons 已提交
128 129
    }
}