File size: 2,788 Bytes
7b715bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Checks for the presence of NuGet packages with the version number declared
// in each project file beneath the given directory, reporting project files that
// should be built and released.

using System.Net;
using System.Xml.Linq;

if (args.Length != 1)
{
    Console.WriteLine("Argument: <parent-directory>");
    Console.WriteLine("(All project files below this directory, recursively, will be checked.");
    return 1;
}

bool errors = false;
var client = new HttpClient();

// Fetch everything in parallel.
var packages = Directory.GetFiles(args[0], "*.csproj", SearchOption.AllDirectories).Select(Fetch).ToList();

// We don't care what order we await the tasks in.
foreach (var package in packages)
{
    var response = await package.ResponseTask;
    switch (response.StatusCode)
    {
        case HttpStatusCode.OK:
            // Ignore
            break;
        case HttpStatusCode.NotFound:
            // We want to build/generate this
            Console.WriteLine(package.ProjectFile.Replace("\\", "/"));
            break;
        default:
            // Keep going to find all broken packages, but remember to fail eventually.
            Console.Error.WriteLine($"Package {package.Id} check failed with status code {response.StatusCode}");
            errors = true;
            break;
    }
}

return errors ? 1 : 0;

Package Fetch(string projectFile)
{
    var doc = XDocument.Load(projectFile);
    string id = Path.GetFileNameWithoutExtension(projectFile);
    var version = doc.Root.Element("PropertyGroup").Element("Version").Value;

    // A version of x.y.z.0 is packaged as just x.y.z
    var bits = version.Split('.');
    if (bits.Length == 4 && bits[3] == "0")
    {
        version = string.Join(".", bits.Take(3));
    }

    var url = new Uri($"https://globalcdn.nuget.org/packages/{id.ToLowerInvariant()}.{version}.nupkg");
    var request = new HttpRequestMessage
    {
        RequestUri = url,
        Method = HttpMethod.Head
    };
    var responseTask = client.SendAsync(request);
    return new Package(projectFile, id, version, responseTask);
}

record Package (string ProjectFile, string Id, string Version, Task<HttpResponseMessage> ResponseTask);