/// <summary> /// Converts a NuGet package to a Unity package. /// </summary> private async Task ConvertNuGetPackageToUnity(PackageIdentity identity, NpmPackageInfo npmPackageInfo, NpmPackageVersion npmPackageVersion, IPackageSearchMetadata packageMeta, RegistryEntry packageEntry) { var unityPackageFileName = GetUnityPackageFileName(identity, npmPackageVersion); var unityPackageFilePath = Path.Combine(_rootPersistentFolder, unityPackageFileName); _logger.LogInformation($"Converting NuGet package {identity} to Unity `{unityPackageFileName}`"); var downloadResource = await _sourceRepository.GetResourceAsync <DownloadResource>(CancellationToken.None); var downloadResult = await downloadResource.GetDownloadResourceResultAsync( identity, new PackageDownloadContext(_sourceCacheContext), SettingsUtility.GetGlobalPackagesFolder(_settings), _logger, CancellationToken.None); var packageReader = downloadResult.PackageReader; // Update Repository metadata if necessary var repoMeta = packageReader.NuspecReader.GetRepositoryMetadata(); if (repoMeta != null && repoMeta.Url != null && repoMeta.Commit != null && repoMeta.Type != null) { npmPackageVersion.Repository = new NpmSourceRepository() { Revision = repoMeta.Commit, Type = repoMeta.Type, Url = repoMeta.Url, }; } else { npmPackageVersion.Repository = null; } try { var memStream = new MemoryStream(); using (var outStream = File.Create(unityPackageFilePath)) using (var gzoStream = new GZipOutputStream(outStream)) using (var tarArchive = new TarOutputStream(gzoStream, Encoding.UTF8)) { // Select the framework version that is the closest or equal to the latest configured framework version var versions = (await packageReader.GetLibItemsAsync(CancellationToken.None)).ToList(); var collectedItems = new Dictionary <FrameworkSpecificGroup, HashSet <RegistryTargetFramework> >(); foreach (var targetFramework in _targetFrameworks) { var item = versions.Where(x => x.TargetFramework.Framework == targetFramework.Framework.Framework && x.TargetFramework.Version <= targetFramework.Framework.Version).OrderByDescending(x => x.TargetFramework.Version) .FirstOrDefault(); if (item == null) { continue; } if (!collectedItems.TryGetValue(item, out var frameworksPerGroup)) { frameworksPerGroup = new HashSet <RegistryTargetFramework>(); collectedItems.Add(item, frameworksPerGroup); } frameworksPerGroup.Add(targetFramework); } if (!packageEntry.Analyzer && collectedItems.Count == 0) { throw new InvalidOperationException($"The package does not contain a compatible .NET assembly {string.Join(",", _targetFrameworks.Select(x => x.Name))}"); } var isPackageNetStandard21Assembly = DotNetHelper.IsNetStandard21Assembly(identity.Id); var hasMultiNetStandard = collectedItems.Count > 1; var hasOnlyNetStandard21 = collectedItems.Count == 1 && collectedItems.Values.First().All(x => x.Name == "netstandard2.1"); if (isPackageNetStandard21Assembly) { _logger.LogInformation($"Package {identity.Id} is a system package for netstandard2.1 and will be only used for netstandard 2.0"); } if (packageEntry.Analyzer) { var packageFiles = (await packageReader.GetPackageFilesAsync(PackageSaveMode.Files, CancellationToken.None)).ToList(); var analyzerFiles = packageFiles.Where(p => p.StartsWith("analyzers/dotnet/cs")).ToArray(); if (analyzerFiles.Length == 0) { analyzerFiles = packageFiles.Where(p => p.StartsWith("analyzers")).ToArray(); } var createdDirectoryList = new List <string>(); foreach (var analyzerFile in analyzerFiles) { var folderPrefix = $"{Path.GetDirectoryName(analyzerFile).Replace($"analyzers{Path.DirectorySeparatorChar}", string.Empty)}{Path.DirectorySeparatorChar}"; // Write folder meta if (!string.IsNullOrEmpty(folderPrefix)) { var directoryNameBuilder = new StringBuilder(); foreach (var directoryName in folderPrefix.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)) { directoryNameBuilder.Append(directoryName); directoryNameBuilder.Append(Path.DirectorySeparatorChar); var processedDirectoryName = directoryNameBuilder.ToString()[0..^ 1];
/// <summary> /// Converts a NuGet package to Unity package if not already /// </summary> private async Task ConvertNuGetToUnityPackageIfDoesNotExist(PackageIdentity identity, NpmPackageInfo npmPackageInfo, NpmPackageVersion npmPackageVersion, IPackageSearchMetadata packageMeta, bool forceUpdate, RegistryEntry packageEntry) { // If we need to force the update, we delete the previous package+sha1 files if (forceUpdate) { DeleteUnityPackage(identity, npmPackageVersion); } if (!IsUnityPackageValid(identity, npmPackageVersion) || !IsUnityPackageSha1Valid(identity, npmPackageVersion)) { await ConvertNuGetPackageToUnity(identity, npmPackageInfo, npmPackageVersion, packageMeta, packageEntry); } else { npmPackageVersion.Distribution.Shasum = ReadUnityPackageSha1(identity, npmPackageVersion); } }