/// <summary> /// Returns metadata info for given nupkg file. /// Note: Don't hold any object referenecs for ZipPackage data, since it might hold whole package in the memory. /// </summary> public IPackageMetadata GetPackageMetadataFromPath(string nupkgFilePath, Func<string, bool> shouldIncludeFunc) { if (string.IsNullOrEmpty(nupkgFilePath)) { return null; } if (!_fileSystem.FileExists(nupkgFilePath)) { return null; } // Note: don't use ZipPackage ctor that takes Stream, it stores package contents in memory and they // are not collected after even though we are not referencing any of ZipPackage objects. Instead use // ZipPackage(filePath) ctor. var package = _nugetHelper.OpenPackage(nupkgFilePath, (p) => { return new NuGet.ZipPackage(p); }); // check if package id should be excluded and exit early if (shouldIncludeFunc != null && !shouldIncludeFunc(package.Id)) { return null; } var packageFolder = Path.GetDirectoryName(nupkgFilePath) ?? string.Empty; // Note: If using this commented code to get package assemblies, it unpacks whole package into memory, // and then it is never garbage collected even though we don't keep any references to it. It is also // should not be cached since ctor that we use sets _enableCaching = false for ZipPackage. So it might // have some unmanaged objects that are not collected by some reason. // var allAssemblies = package.GetFiles() // .Where(x => ".dll".Equals(Path.GetExtension(x.EffectivePath), StringComparison.OrdinalIgnoreCase)) // .Select(x => x.Path.ToString()) // .ToList(); // we assume that nupkg file lives in the package dir and has lib, ref an dother package dirs in the same dir var allAssemblies = _fileSystem.DirectoryGetFiles(packageFolder, "*.dll", SearchOption.AllDirectories) .Select(x => x.Substring(packageFolder.Length + 1)) .ToList(); var packageTargetFrameworkNames = package.GetSupportedFrameworks().ToList() ?? Enumerable.Empty<FrameworkName>(); var tfmAssemblyGroups = new Dictionary<FrameworkName, IList<string>>(); // here we construct a list of the form { TFM }, { list of target assemblies } foreach (var tfm in packageTargetFrameworkNames) { var dnxResult = TfmPackageAssemblyMatcher.GetAssembliesForFramework(tfm, package, allAssemblies); if (dnxResult != null) { tfmAssemblyGroups.Add(new FrameworkName(tfm.Identifier, tfm.Version, tfm.Profile), dnxResult.ToList()); } } // now we need to convert it to the list of the form: { assembly }, { list of TFM } var assembliesMetadata = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); foreach (var kvp in tfmAssemblyGroups) { foreach (var assemblyPath in kvp.Value) { List<string> existingAssemblyTfms = null; if (assembliesMetadata.TryGetValue(assemblyPath, out existingAssemblyTfms)) { existingAssemblyTfms.Add(DnxVersionUtility.GetShortFrameworkName(kvp.Key)); } else { assembliesMetadata.Add(assemblyPath, new List<string> { DnxVersionUtility.GetShortFrameworkName(kvp.Key) }); } } } var selectedAssemblies = new List<AssemblyMetadata>(); foreach (var am in assembliesMetadata) { var fullPath = Path.Combine(packageFolder, am.Key); if (!_fileSystem.FileExists(fullPath)) { fullPath = Path.Combine(packageFolder, package.Id.ToString(), am.Key); if (!_fileSystem.FileExists(fullPath)) { continue; } } selectedAssemblies.Add(new AssemblyMetadata { FullPath = fullPath, TargetFrameworks = am.Value }); } var newPackageMetadata = new PackageMetadata { Id = package.Id.ToString(), Version = package.Version.ToString(), LocalPath = nupkgFilePath, TargetFrameworks = packageTargetFrameworkNames.Select(x => DnxVersionUtility.GetShortFrameworkName(x)).ToList(), Assemblies = selectedAssemblies }; return newPackageMetadata; }
/// <summary> /// Returns metadata info for given nupkg file. /// Note: Don't hold any object referenecs for ZipPackage data, since it might hold whole package in the memory. /// </summary> public IPackageMetadata GetPackageMetadataFromPath(string nupkgFilePath, Func <string, bool> shouldIncludeFunc) { if (string.IsNullOrEmpty(nupkgFilePath)) { return(null); } if (!_fileSystem.FileExists(nupkgFilePath)) { return(null); } // Note: don't use ZipPackage ctor that takes Stream, it stores package contents in memory and they // are not collected after even though we are not referencing any of ZipPackage objects. Instead use // ZipPackage(filePath) ctor. var package = _nugetHelper.OpenPackage(nupkgFilePath, (p) => { return(new NuGet.ZipPackage(p)); }); // check if package id should be excluded and exit early if (shouldIncludeFunc != null && !shouldIncludeFunc(package.Id)) { return(null); } var packageFolder = Path.GetDirectoryName(nupkgFilePath) ?? string.Empty; // Note: If using this commented code to get package assemblies, it unpacks whole package into memory, // and then it is never garbage collected even though we don't keep any references to it. It is also // should not be cached since ctor that we use sets _enableCaching = false for ZipPackage. So it might // have some unmanaged objects that are not collected by some reason. // var allAssemblies = package.GetFiles() // .Where(x => ".dll".Equals(Path.GetExtension(x.EffectivePath), StringComparison.OrdinalIgnoreCase)) // .Select(x => x.Path.ToString()) // .ToList(); // we assume that nupkg file lives in the package dir and has lib, ref an dother package dirs in the same dir var allAssemblies = _fileSystem.DirectoryGetFiles(packageFolder, "*.dll", SearchOption.AllDirectories) .Select(x => x.Substring(packageFolder.Length + 1)) .ToList(); var packageTargetFrameworkNames = package.GetSupportedFrameworks().ToList() ?? Enumerable.Empty <FrameworkName>(); var tfmAssemblyGroups = new Dictionary <FrameworkName, IList <string> >(); // here we construct a list of the form { TFM }, { list of target assemblies } foreach (var tfm in packageTargetFrameworkNames) { var dnxResult = TfmPackageAssemblyMatcher.GetAssembliesForFramework(tfm, package, allAssemblies); if (dnxResult != null) { tfmAssemblyGroups.Add(new FrameworkName(tfm.Identifier, tfm.Version, tfm.Profile), dnxResult.ToList()); } } // now we need to convert it to the list of the form: { assembly }, { list of TFM } var assembliesMetadata = new Dictionary <string, List <string> >(StringComparer.OrdinalIgnoreCase); foreach (var kvp in tfmAssemblyGroups) { foreach (var assemblyPath in kvp.Value) { List <string> existingAssemblyTfms = null; if (assembliesMetadata.TryGetValue(assemblyPath, out existingAssemblyTfms)) { existingAssemblyTfms.Add(DnxVersionUtility.GetShortFrameworkName(kvp.Key)); } else { assembliesMetadata.Add(assemblyPath, new List <string> { DnxVersionUtility.GetShortFrameworkName(kvp.Key) }); } } } var selectedAssemblies = new List <AssemblyMetadata>(); foreach (var am in assembliesMetadata) { var fullPath = Path.Combine(packageFolder, am.Key); if (!_fileSystem.FileExists(fullPath)) { fullPath = Path.Combine(packageFolder, package.Id.ToString(), am.Key); if (!_fileSystem.FileExists(fullPath)) { continue; } } selectedAssemblies.Add(new AssemblyMetadata { FullPath = fullPath, TargetFrameworks = am.Value }); } var newPackageMetadata = new PackageMetadata { Id = package.Id.ToString(), Version = package.Version.ToString(), LocalPath = nupkgFilePath, TargetFrameworks = packageTargetFrameworkNames.Select(x => DnxVersionUtility.GetShortFrameworkName(x)).ToList(), Assemblies = selectedAssemblies }; return(newPackageMetadata); }