init
This commit is contained in:
240
Program.cs
Normal file
240
Program.cs
Normal file
@ -0,0 +1,240 @@
|
||||
using NuGet.Configuration;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Protocol;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using NuGet.Resolver;
|
||||
using NuGet.Versioning;
|
||||
using NuGet.Common;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task<int> Main(string[] args)
|
||||
{
|
||||
if (args.Length == 0 || args.Contains("--help") || args.Contains("-h"))
|
||||
{
|
||||
Console.WriteLine("Утилита для скачивания NuGet пакетов с зависимостями");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Использование:");
|
||||
Console.WriteLine(" dotnet run -- --package-id <ID> [опции]");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Опции:");
|
||||
Console.WriteLine(" --package-id <ID> ID пакета для скачивания (обязательный)");
|
||||
Console.WriteLine(" --version <VERSION> Версия пакета (по умолчанию последняя стабильная)");
|
||||
Console.WriteLine(" --framework <FRAME> Целевой framework (по умолчанию netstandard2.0)");
|
||||
Console.WriteLine(" --output-dir <DIR> Папка для сохранения пакетов (по умолчанию ./nuget-packages)");
|
||||
Console.WriteLine(" --source <URL> Источник NuGet (по умолчанию https://api.nuget.org/v3/index.json)");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Примеры:");
|
||||
Console.WriteLine(" dotnet run -- --package-id Npgsql --framework netstandard2.0");
|
||||
Console.WriteLine(" dotnet run -- --package-id Npgsql --version 7.0.6 --output-dir ./my-packages");
|
||||
return 0;
|
||||
}
|
||||
|
||||
string? packageId = null;
|
||||
string? version = null;
|
||||
string framework = "netstandard2.0";
|
||||
string outputDir = "./nuget-packages";
|
||||
string source = "https://api.nuget.org/v3/index.json";
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
switch (args[i])
|
||||
{
|
||||
case "--package-id":
|
||||
if (i + 1 < args.Length) packageId = args[++i];
|
||||
break;
|
||||
case "--version":
|
||||
if (i + 1 < args.Length) version = args[++i];
|
||||
break;
|
||||
case "--framework":
|
||||
if (i + 1 < args.Length) framework = args[++i];
|
||||
break;
|
||||
case "--output-dir":
|
||||
if (i + 1 < args.Length) outputDir = args[++i];
|
||||
break;
|
||||
case "--source":
|
||||
if (i + 1 < args.Length) source = args[++i];
|
||||
break;
|
||||
case "--help":
|
||||
case "-h":
|
||||
Console.WriteLine("Использование: dotnet run -- --package-id <ID> [опции]");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Опции:");
|
||||
Console.WriteLine(" --package-id <ID> ID пакета для скачивания (обязательный)");
|
||||
Console.WriteLine(" --version <VERSION> Версия пакета (по умолчанию последняя стабильная)");
|
||||
Console.WriteLine(" --framework <FRAME> Целевой framework (по умолчанию netstandard2.0)");
|
||||
Console.WriteLine(" --output-dir <DIR> Папка для сохранения пакетов (по умолчанию ./nuget-packages)");
|
||||
Console.WriteLine(" --source <URL> Источник NuGet (по умолчанию https://api.nuget.org/v3/index.json)");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Примеры:");
|
||||
Console.WriteLine(" dotnet run -- --package-id Npgsql --framework netstandard2.0");
|
||||
Console.WriteLine(" dotnet run -- --package-id Npgsql --version 7.0.6 --output-dir ./my-packages");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(packageId))
|
||||
{
|
||||
Console.WriteLine("Ошибка: --package-id обязателен");
|
||||
return 1;
|
||||
}
|
||||
|
||||
await DownloadPackageWithDependencies(packageId, version, framework, outputDir, source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static async Task DownloadPackageWithDependencies(string packageId, string? version, string framework, string outputDir, string source)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"Скачивание пакета {packageId} с зависимостями...");
|
||||
Console.WriteLine($"Framework: {framework}");
|
||||
Console.WriteLine($"Источник: {source}");
|
||||
Console.WriteLine($"Папка назначения: {outputDir}");
|
||||
|
||||
// Создаем папку назначения
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
// Настраиваем источник пакетов
|
||||
var settings = Settings.LoadDefaultSettings(null);
|
||||
var sourceRepository = Repository.Factory.GetCoreV3(source);
|
||||
var resource = await sourceRepository.GetResourceAsync<FindPackageByIdResource>();
|
||||
|
||||
// Определяем версию пакета
|
||||
NuGetVersion packageVersion;
|
||||
if (string.IsNullOrEmpty(version))
|
||||
{
|
||||
var versions = await resource.GetAllVersionsAsync(packageId, new SourceCacheContext(), NullLogger.Instance, CancellationToken.None);
|
||||
packageVersion = versions.Where(v => !v.IsPrerelease).Max() ?? throw new InvalidOperationException($"Не найдена стабильная версия для пакета {packageId}");
|
||||
Console.WriteLine($"Выбрана версия: {packageVersion}");
|
||||
}
|
||||
else
|
||||
{
|
||||
packageVersion = NuGetVersion.Parse(version);
|
||||
}
|
||||
|
||||
// Создаем framework
|
||||
var nugetFramework = NuGetFramework.Parse(framework);
|
||||
|
||||
// Собираем все зависимости
|
||||
var packagesToDownload = new HashSet<PackageIdentity>();
|
||||
var processedPackages = new HashSet<string>();
|
||||
|
||||
await CollectDependencies(packageId, packageVersion, nugetFramework, packagesToDownload, processedPackages, sourceRepository);
|
||||
|
||||
Console.WriteLine($"Найдено пакетов для скачивания: {packagesToDownload.Count}");
|
||||
foreach (var package in packagesToDownload)
|
||||
{
|
||||
Console.WriteLine($" - {package.Id} {package.Version}");
|
||||
}
|
||||
|
||||
// Скачиваем все пакеты
|
||||
var cacheContext = new SourceCacheContext();
|
||||
var downloadResource = await sourceRepository.GetResourceAsync<DownloadResource>();
|
||||
|
||||
foreach (var package in packagesToDownload)
|
||||
{
|
||||
await DownloadPackage(package, downloadResource, cacheContext, outputDir);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Все пакеты успешно скачаны в папку: {outputDir}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Ошибка: {ex.Message}");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static async Task CollectDependencies(string packageId, NuGetVersion version, NuGetFramework framework,
|
||||
HashSet<PackageIdentity> packagesToDownload, HashSet<string> processedPackages, SourceRepository sourceRepository)
|
||||
{
|
||||
var packageIdentity = new PackageIdentity(packageId, version);
|
||||
var packageKey = $"{packageId}.{version}";
|
||||
|
||||
if (processedPackages.Contains(packageKey))
|
||||
return;
|
||||
|
||||
processedPackages.Add(packageKey);
|
||||
packagesToDownload.Add(packageIdentity);
|
||||
|
||||
try
|
||||
{
|
||||
// Получаем зависимости через PackageReader
|
||||
var downloadResource = await sourceRepository.GetResourceAsync<DownloadResource>();
|
||||
var cacheContext = new SourceCacheContext();
|
||||
var downloadResult = await downloadResource.GetDownloadResourceResultAsync(
|
||||
packageIdentity,
|
||||
new PackageDownloadContext(cacheContext),
|
||||
Path.GetTempPath(),
|
||||
NullLogger.Instance,
|
||||
CancellationToken.None);
|
||||
|
||||
if (downloadResult.Status == DownloadResourceResultStatus.Available)
|
||||
{
|
||||
using var packageReader = new PackageArchiveReader(downloadResult.PackageStream);
|
||||
var nuspecReader = packageReader.NuspecReader;
|
||||
var dependencyGroups = nuspecReader.GetDependencyGroups();
|
||||
|
||||
// Находим подходящую группу зависимостей для нашего framework
|
||||
var dependencyGroup = dependencyGroups
|
||||
.FirstOrDefault(dg => dg.TargetFramework == null || dg.TargetFramework == framework);
|
||||
|
||||
if (dependencyGroup != null)
|
||||
{
|
||||
Console.WriteLine($" Найдено зависимостей для {packageId}: {dependencyGroup.Packages.Count()}");
|
||||
foreach (var dependency in dependencyGroup.Packages)
|
||||
{
|
||||
// Получаем версию зависимости
|
||||
var dependencyVersion = dependency.VersionRange?.MinVersion ?? dependency.VersionRange?.MaxVersion;
|
||||
if (dependencyVersion != null)
|
||||
{
|
||||
Console.WriteLine($" Зависимость: {dependency.Id} {dependencyVersion}");
|
||||
await CollectDependencies(dependency.Id, dependencyVersion, framework, packagesToDownload, processedPackages, sourceRepository);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" Нет зависимостей для {packageId} в framework {framework}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Предупреждение: Не удалось получить зависимости для {packageId} {version}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task DownloadPackage(PackageIdentity packageIdentity, DownloadResource downloadResource,
|
||||
SourceCacheContext cacheContext, string outputDir)
|
||||
{
|
||||
Console.WriteLine($"Скачивание пакета: {packageIdentity.Id} {packageIdentity.Version}");
|
||||
|
||||
var downloadResult = await downloadResource.GetDownloadResourceResultAsync(
|
||||
packageIdentity,
|
||||
new PackageDownloadContext(cacheContext),
|
||||
Path.GetTempPath(),
|
||||
NullLogger.Instance,
|
||||
CancellationToken.None);
|
||||
|
||||
if (downloadResult.Status == DownloadResourceResultStatus.Available)
|
||||
{
|
||||
var packagePath = Path.Combine(outputDir, $"{packageIdentity.Id}.{packageIdentity.Version}.nupkg");
|
||||
|
||||
using (var packageStream = downloadResult.PackageStream)
|
||||
using (var fileStream = File.Create(packagePath))
|
||||
{
|
||||
await packageStream.CopyToAsync(fileStream);
|
||||
}
|
||||
|
||||
Console.WriteLine($" ✓ Скачан: {packagePath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" ✗ Ошибка скачивания: {packageIdentity.Id} {packageIdentity.Version}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user