| File: RestoreCommand\OriginalCaseGlobalPackageFolder.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Commands\NuGet.Commands.csproj (NuGet.Commands) |
// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. #nullable disable using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using NuGet.Common; using NuGet.DependencyResolver; using NuGet.LibraryModel; using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.ProjectModel; using NuGet.Repositories; namespace NuGet.Commands { using LocalPackageArchiveDownloader = NuGet.Protocol.LocalPackageArchiveDownloader; public class OriginalCaseGlobalPackageFolder { private readonly List<NuGetv3LocalRepository> _localRepositories; private readonly RestoreRequest _request; private readonly ToolPathResolver _toolPathResolver; private readonly VersionFolderPathResolver _pathResolver; public Guid ParentId { get; } public OriginalCaseGlobalPackageFolder(RestoreRequest request) : this(request, Guid.Empty) { } public OriginalCaseGlobalPackageFolder(RestoreRequest request, Guid parentId) { if (request == null) { throw new ArgumentNullException(nameof(request)); } _request = request; ParentId = parentId; _localRepositories = new List<NuGetv3LocalRepository>(); _localRepositories.Add(request.DependencyProviders.GlobalPackages); _localRepositories.AddRange(request.DependencyProviders.FallbackPackageFolders); _pathResolver = new VersionFolderPathResolver( _request.PackagesDirectory, _request.IsLowercasePackagesDirectory); _toolPathResolver = new ToolPathResolver( _request.PackagesDirectory, _request.IsLowercasePackagesDirectory); } public async Task CopyPackagesToOriginalCaseAsync(IEnumerable<RestoreTargetGraph> graphs, CancellationToken token) { // Keep track of the packages we've already converted to original case. var converted = new HashSet<PackageIdentity>(); var originalCaseContext = GetPathContext(); var versionFolderPathResolver = new VersionFolderPathResolver(_request.PackagesDirectory, _request.IsLowercasePackagesDirectory); // Iterate over every package node. foreach (var graph in graphs) { var packages = graph .Flattened .Select(graphItem => graphItem.Data.Match) .Where(remoteMatch => remoteMatch.Library.Type == LibraryType.Package); foreach (var remoteMatch in packages) { var identity = GetPackageIdentity(remoteMatch); var hashPath = _pathResolver.GetNupkgMetadataPath(identity.Id, identity.Version); // No need to re-install the same package identity more than once or if it is // already installed. if (!converted.Add(identity) || File.Exists(hashPath)) { continue; } var localPackageSourceInfo = GetLocalPackageSourceInfo(remoteMatch); var packageIdentity = new PackageIdentity(remoteMatch.Library.Name, remoteMatch.Library.Version); IPackageDownloader packageDependency = null; if (string.IsNullOrEmpty(localPackageSourceInfo?.Package.ZipPath)) { packageDependency = await remoteMatch.Provider.GetPackageDownloaderAsync( packageIdentity, _request.CacheContext, _request.Log, token); } else { packageDependency = new LocalPackageArchiveDownloader( localPackageSourceInfo.Repository.RepositoryRoot, localPackageSourceInfo.Package.ZipPath, packageIdentity, _request.Log); } // Install the package. using (packageDependency) { var result = await PackageExtractor.InstallFromSourceAsync( identity, packageDependency, versionFolderPathResolver, originalCaseContext, token, ParentId); if (result) { _request.Log.LogInformation(string.Format( CultureInfo.CurrentCulture, Strings.Log_ConvertedPackageToOriginalCase, identity)); } } } } } public void ConvertLockFileToOriginalCase(LockFile lockFile) { for (var i = 0; i < lockFile.Libraries.Count; i++) { var library = lockFile.Libraries[i]; // If the library is a package, convert its path to original case. if (library.Type == LibraryType.Package) { var path = _pathResolver.GetPackageDirectory(library.Name, library.Version); var forwardSlashPath = PathUtility.GetPathWithForwardSlashes(path); if (forwardSlashPath != library.Path) { // Update the path to the original case. lockFile.Libraries[i] = library with { Path = forwardSlashPath }; } } } } private PackageExtractionContext GetPathContext() { return new PackageExtractionContext( _request.PackageSaveMode, _request.XmlDocFileSaveMode, _request.ClientPolicyContext, _request.Log) { SignedPackageVerifier = _request.SignedPackageVerifier }; } private static PackageIdentity GetPackageIdentity(RemoteMatch remoteMatch) { return new PackageIdentity( remoteMatch.Library.Name, remoteMatch.Library.Version); } private LocalPackageSourceInfo GetLocalPackageSourceInfo(RemoteMatch remoteMatch) { var library = remoteMatch.Library; // Try to get the package from the local repositories first. var localPackage = NuGetv3LocalRepositoryUtility.GetPackage( _localRepositories, library.Name, library.Version); if (localPackage != null && File.Exists(localPackage.Package.ZipPath)) { return localPackage; } return null; } } }