private void UpdateFromFolderLayout(PackageIndex index, string path, bool filter = false) { var version = NuGetVersion.Parse(Path.GetFileName(path)); var id = Path.GetFileName(Path.GetDirectoryName(path)); if (filter && !ShouldInclude(id)) { return; } string refFolder = Path.Combine(path, "ref"); if (!Directory.Exists(refFolder)) { refFolder = Path.Combine(path, "lib"); } IEnumerable <Version> assemblyVersions = null; if (Directory.Exists(refFolder)) { assemblyVersions = Directory.EnumerateFiles(refFolder, "*.dll", SearchOption.AllDirectories) .Select(f => VersionUtility.GetAssemblyVersion(f)); } UpdateFromValues(index, id, version, assemblyVersions); }
public void MergeInboxFromLayout(NuGetFramework framework, string layoutDirectory, bool addPackages = true) { foreach (var file in Directory.EnumerateFiles(layoutDirectory, "*.dll", SearchOption.AllDirectories)) { var assemblyName = Path.GetFileNameWithoutExtension(file); var assemblyVersion = VersionUtility.GetAssemblyVersion(file); TryAddInbox(assemblyName, framework, assemblyVersion, addPackages); } }
public void HarvestFilesFromPackage() { string pathToPackage = Path.Combine(PackagesFolder, PackageId, PackageVersion); if (!Directory.Exists(pathToPackage)) { Log.LogError($"Cannot harvest from package {PackageId}/{PackageVersion} because {pathToPackage} does not exist."); return; } var harvestedFiles = new List <ITaskItem>(); foreach (var extension in includedExtensions) { foreach (var packageFile in Directory.EnumerateFiles(pathToPackage, $"*{extension}", SearchOption.AllDirectories)) { string packagePath = packageFile.Substring(pathToPackage.Length + 1).Replace('\\', '/'); if (ShouldExclude(packagePath)) { Log.LogMessage($"Preferring live build of package path {packagePath} over the asset from last stable package."); continue; } else { Log.LogMessage($"Including {packagePath} from last stable package {PackageId}/{PackageVersion}."); } var item = new TaskItem(packageFile); var targetPath = Path.GetDirectoryName(packagePath).Replace('\\', '/'); item.SetMetadata("TargetPath", targetPath); item.SetMetadata("TargetFramework", GetTargetFrameworkFromPackagePath(targetPath)); item.SetMetadata("HarvestDependencies", "true"); item.SetMetadata("IsReferenceAsset", IsReferencePackagePath(targetPath).ToString()); var assemblyVersion = VersionUtility.GetAssemblyVersion(packageFile); if (assemblyVersion != null) { item.SetMetadata("AssemblyVersion", assemblyVersion.ToString()); } harvestedFiles.Add(item); } } Files = harvestedFiles.ToArray(); }
private void UpdateFromFolderLayout(PackageIndex index, string path, bool filter = false) { var version = NuGetVersion.Parse(Path.GetFileName(path)); var id = Path.GetFileName(Path.GetDirectoryName(path)); if (filter && !ShouldInclude(id)) { return; } var dlls = Directory.EnumerateFiles(path, "*.dll", SearchOption.AllDirectories); var assemblyVersions = dlls.Select(f => VersionUtility.GetAssemblyVersion(f)); var dllNames = dlls.Select(f => Path.GetFileNameWithoutExtension(f)).Distinct(); UpdateFromValues(index, id, version, assemblyVersions, dllNames); }
private void UpdateFromPackage(PackageIndex index, string packagePath, bool filter = false) { string id; NuGetVersion version; IEnumerable <Version> assemblyVersions; using (var reader = new PackageArchiveReader(packagePath)) { var identity = reader.GetIdentity(); id = identity.Id; version = identity.Version; if (filter && !ShouldInclude(id)) { return; } var refFiles = reader.GetFiles("ref").Where(r => !NuGetAssetResolver.IsPlaceholder(r)); if (!refFiles.Any()) { refFiles = reader.GetFiles("lib"); } assemblyVersions = refFiles.Select(refFile => { using (var refStream = reader.GetStream(refFile)) using (var memStream = new MemoryStream()) { refStream.CopyTo(memStream); memStream.Seek(0, SeekOrigin.Begin); return(VersionUtility.GetAssemblyVersion(memStream)); } }).ToArray(); } UpdateFromValues(index, id, version, assemblyVersions); }
private void UpdateFromPackage(PackageIndex index, string packagePath, bool filter = false) { string id; NuGetVersion version; IEnumerable <Version> assemblyVersions; IEnumerable <string> dllNames; using (var reader = new PackageArchiveReader(packagePath)) { var identity = reader.GetIdentity(); id = identity.Id; version = identity.Version; if (filter && !ShouldInclude(id)) { return; } var dlls = reader.GetFiles().Where(f => Path.GetExtension(f).Equals(".dll", StringComparison.OrdinalIgnoreCase)); assemblyVersions = dlls.Select(refFile => { using (var refStream = reader.GetStream(refFile)) using (var memStream = new MemoryStream()) { refStream.CopyTo(memStream); memStream.Seek(0, SeekOrigin.Begin); return(VersionUtility.GetAssemblyVersion(memStream)); } }).ToArray(); dllNames = dlls.Select(f => Path.GetFileNameWithoutExtension(f)).Distinct().ToArray(); } UpdateFromValues(index, id, version, assemblyVersions, dllNames); }
private void HarvestSupportedFrameworks() { List <ITaskItem> supportedFrameworks = new List <ITaskItem>(); AggregateNuGetAssetResolver resolver = new AggregateNuGetAssetResolver(RuntimeFile); string packagePath = Path.Combine(PackagesFolder, PackageId, PackageVersion); // add the primary package resolver.AddPackageItems(PackageId, GetPackageItems(packagePath)); if (RuntimePackages != null) { // add any split runtime packages foreach (var runtimePackage in RuntimePackages) { var runtimePackageId = runtimePackage.ItemSpec; var runtimePackageVersion = runtimePackage.GetMetadata("Version"); resolver.AddPackageItems(runtimePackageId, GetPackageItems(PackagesFolder, runtimePackageId, runtimePackageVersion)); } } // create a resolver that can be used to determine the API version for inbox assemblies // since inbox assemblies are represented with placeholders we can remove the placeholders // and use the netstandard reference assembly to determine the API version var filesWithoutPlaceholders = GetPackageItems(packagePath) .Where(f => !NuGetAssetResolver.IsPlaceholder(f)); NuGetAssetResolver resolverWithoutPlaceholders = new NuGetAssetResolver(RuntimeFile, filesWithoutPlaceholders); string package = $"{PackageId}/{PackageVersion}"; foreach (var framework in Frameworks) { var runtimeIds = framework.GetMetadata("RuntimeIDs")?.Split(';'); NuGetFramework fx; try { fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec); } catch (Exception ex) { Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}"); continue; } if (fx.Equals(NuGetFramework.UnsupportedFramework)) { Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework."); continue; } var compileAssets = resolver.ResolveCompileAssets(fx, PackageId); bool hasCompileAsset, hasCompilePlaceHolder; NuGetAssetResolver.ExamineAssets(Log, "Compile", package, fx.ToString(), compileAssets, out hasCompileAsset, out hasCompilePlaceHolder); // start by making sure it has some asset available for compile var isSupported = hasCompileAsset || hasCompilePlaceHolder; if (!isSupported) { Log.LogMessage(LogImportance.Low, $"Skipping {fx} because it is not supported."); continue; } foreach (var runtimeId in runtimeIds) { string target = String.IsNullOrEmpty(runtimeId) ? fx.ToString() : $"{fx}/{runtimeId}"; var runtimeAssets = resolver.ResolveRuntimeAssets(fx, runtimeId); bool hasRuntimeAsset, hasRuntimePlaceHolder; NuGetAssetResolver.ExamineAssets(Log, "Runtime", package, target, runtimeAssets, out hasRuntimeAsset, out hasRuntimePlaceHolder); isSupported &= hasCompileAsset == hasRuntimeAsset; isSupported &= hasCompilePlaceHolder == hasRuntimePlaceHolder; if (!isSupported) { Log.LogMessage(LogImportance.Low, $"Skipping {fx} because it is not supported on {target}."); break; } } if (isSupported) { var supportedFramework = new TaskItem(framework.ItemSpec); supportedFramework.SetMetadata("HarvestedFromPackage", package); // set version // first try the resolved compile asset for this package var refAssm = compileAssets.FirstOrDefault(r => !NuGetAssetResolver.IsPlaceholder(r))?.Substring(PackageId.Length + 1); if (refAssm == null) { // if we didn't have a compile asset it means this framework is supported inbox with a placeholder // resolve the assets without placeholders to pick up the netstandard reference assembly. compileAssets = resolverWithoutPlaceholders.ResolveCompileAssets(fx); refAssm = compileAssets.FirstOrDefault(r => !NuGetAssetResolver.IsPlaceholder(r)); } string version = "unknown"; if (refAssm != null) { version = VersionUtility.GetAssemblyVersion(Path.Combine(packagePath, refAssm))?.ToString() ?? version; } supportedFramework.SetMetadata("Version", version); Log.LogMessage($"Validating version {version} for {supportedFramework.ItemSpec} because it was supported by {PackageId}/{PackageVersion}."); supportedFrameworks.Add(supportedFramework); } } SupportedFrameworks = supportedFrameworks.ToArray(); }
public void HarvestFilesFromPackage() { string pathToPackage = Path.Combine(PackagesFolder, PackageId, PackageVersion); if (!Directory.Exists(pathToPackage)) { Log.LogError($"Cannot harvest from package {PackageId}/{PackageVersion} because {pathToPackage} does not exist."); return; } var livePackageFiles = Files.NullAsEmpty() .Where(f => IsIncludedExtension(f.GetMetadata("Extension"))) .Select(f => new PackageItem(f)) .ToDictionary(p => p.TargetPath, StringComparer.OrdinalIgnoreCase); var harvestedFiles = new List <ITaskItem>(); var removeFiles = new List <ITaskItem>(); // make sure we preserve refs that match desktop assemblies var liveDesktopDlls = livePackageFiles.Values.Where(pi => pi.IsDll && pi.TargetFramework?.Framework == FrameworkConstants.FrameworkIdentifiers.Net); var desktopRefVersions = liveDesktopDlls.Where(d => d.IsRef && d.Version != null).Select(d => d.Version); var desktopLibVersions = liveDesktopDlls.Where(d => !d.IsRef && d.Version != null).Select(d => d.Version); // find destkop assemblies with no matching lib. var preserveRefVersion = new HashSet <Version>(desktopLibVersions); preserveRefVersion.ExceptWith(desktopRefVersions); foreach (var extension in s_includedExtensions) { foreach (var packageFile in Directory.EnumerateFiles(pathToPackage, $"*{extension}", SearchOption.AllDirectories)) { string packagePath = packageFile.Substring(pathToPackage.Length + 1).Replace('\\', '/'); // determine if we should include this file from the harvested package // exclude if its specifically set for exclusion if (ShouldExclude(packagePath)) { Log.LogMessage(LogImportance.Low, $"Excluding package path {packagePath}."); continue; } var assemblyVersion = extension == s_dll?VersionUtility.GetAssemblyVersion(packageFile) : null; PackageItem liveFile = null; // determine if the harvested file clashes with a live built file // we'll prefer the harvested reference assembly so long as it's the same API // version and not required to match implementation 1:1 as is the case for desktop if (livePackageFiles.TryGetValue(packagePath, out liveFile)) { // Not a dll, not a ref, or not a versioned assembly: prefer live built file. if (extension != s_dll || !liveFile.IsRef || assemblyVersion == null || liveFile.Version == null) { Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {packagePath} over the asset from last stable package."); continue; } // preserve desktop references to ensure bindingRedirects will work. if (liveFile.TargetFramework.Framework == FrameworkConstants.FrameworkIdentifiers.Net) { Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {packagePath} over the asset from last stable package for desktop framework."); continue; } // as above but handle the case where a netstandard ref may be used for a desktop impl. if (preserveRefVersion.Contains(liveFile.Version)) { Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {packagePath} over the asset from last stable package for desktop framework."); continue; } // preserve references with a different major.minor version if (assemblyVersion.Major != liveFile.Version.Major || assemblyVersion.Minor != liveFile.Version.Minor) { Log.LogMessage(LogImportance.Low, $"Preferring live build of reference {packagePath} over the asset from last stable package since the live build is a different API version."); continue; } // preserve references that specifically set the preserve metadata. bool preserve = false; bool.TryParse(liveFile.OriginalItem.GetMetadata("Preserve"), out preserve); if (preserve) { Log.LogMessage(LogImportance.Low, $"Preferring live build of reference {packagePath} over the asset from last stable package since Preserve was set to true."); continue; } // replace the live file with the harvested one, removing both the live file and PDB from the // file list. Log.LogMessage($"Using reference {packagePath} from last stable package {PackageId}/{PackageVersion} rather than the built reference {liveFile.SourcePath} since it is the same API version. Set <Preserve>true</Preserve> on {liveFile.SourceProject} if you'd like to avoid this.."); removeFiles.Add(liveFile.OriginalItem); PackageItem livePdbFile; if (livePackageFiles.TryGetValue(Path.ChangeExtension(packagePath, ".pdb"), out livePdbFile)) { removeFiles.Add(livePdbFile.OriginalItem); } } else { Log.LogMessage(LogImportance.Low, $"Including {packagePath} from last stable package {PackageId}/{PackageVersion}."); } var item = new TaskItem(packageFile); if (liveFile?.OriginalItem != null) { // preserve all the meta-data from the live file that was replaced. liveFile.OriginalItem.CopyMetadataTo(item); } else { var targetPath = Path.GetDirectoryName(packagePath).Replace('\\', '/'); item.SetMetadata("TargetPath", targetPath); string targetFramework = GetTargetFrameworkFromPackagePath(targetPath); item.SetMetadata("TargetFramework", targetFramework); // only harvest for non-portable frameworks, matches logic in packaging.targets. bool harvestDependencies = !targetFramework.StartsWith("portable-"); item.SetMetadata("HarvestDependencies", harvestDependencies.ToString()); item.SetMetadata("IsReferenceAsset", IsReferencePackagePath(targetPath).ToString()); } if (assemblyVersion != null) { // overwrite whatever metadata may have been copied from the live file. item.SetMetadata("AssemblyVersion", assemblyVersion.ToString()); } harvestedFiles.Add(item); } } HarvestedFiles = harvestedFiles.ToArray(); if (Files != null) { UpdatedFiles = Files.Except(removeFiles).ToArray(); } }
public void HarvestFilesFromPackage() { string pathToPackage = _packageFolders[PackageId]; var livePackageItems = Files.NullAsEmpty() .Where(f => IsIncludedExtension(f.GetMetadata("Extension"))) .Select(f => new PackageItem(f)); var livePackageFiles = new Dictionary <string, PackageItem>(StringComparer.OrdinalIgnoreCase); foreach (var livePackageItem in livePackageItems) { PackageItem existingitem; if (livePackageFiles.TryGetValue(livePackageItem.TargetPath, out existingitem)) { Log.LogError($"Package contains two files with same targetpath: {livePackageItem.TargetPath}, items:{livePackageItem.SourcePath}, {existingitem.SourcePath}."); } else { livePackageFiles.Add(livePackageItem.TargetPath, livePackageItem); } } var harvestedFiles = new List <ITaskItem>(); var removeFiles = new List <ITaskItem>(); // make sure we preserve refs that match desktop assemblies var liveDesktopDlls = livePackageFiles.Values.Where(pi => pi.IsDll && pi.TargetFramework?.Framework == FrameworkConstants.FrameworkIdentifiers.Net); var desktopRefVersions = liveDesktopDlls.Where(d => d.IsRef && d.Version != null).Select(d => d.Version); var desktopLibVersions = liveDesktopDlls.Where(d => !d.IsRef && d.Version != null).Select(d => d.Version); // find desktop assemblies with no matching lib. var preserveRefVersion = new HashSet <Version>(desktopLibVersions); preserveRefVersion.ExceptWith(desktopRefVersions); foreach (var extension in s_includedExtensions) { foreach (var packageFile in Directory.EnumerateFiles(pathToPackage, $"*{extension}", SearchOption.AllDirectories)) { string harvestPackagePath = packageFile.Substring(pathToPackage.Length + 1).Replace('\\', '/'); // determine if we should include this file from the harvested package // exclude if its specifically set for exclusion if (ShouldExclude(harvestPackagePath)) { Log.LogMessage(LogImportance.Low, $"Excluding package path {harvestPackagePath} because it is specifically excluded."); continue; } ITaskItem includeItem = null; if (!IncludeAllPaths && !ShouldInclude(harvestPackagePath, out includeItem)) { Log.LogMessage(LogImportance.Low, $"Excluding package path {harvestPackagePath} because it is not included in {nameof(PathsToInclude)}."); continue; } // allow for the harvested item to be moved var remappedTargetPath = includeItem?.GetMetadata("TargetPath"); if (!String.IsNullOrEmpty(remappedTargetPath)) { harvestPackagePath = remappedTargetPath + '/' + Path.GetFileName(packageFile); } List <string> targetPaths = new List <string>() { harvestPackagePath }; var additionalTargetPaths = includeItem?.GetMetadata("AdditionalTargetPath"); if (!String.IsNullOrEmpty(additionalTargetPaths)) { foreach (var additionalTargetPath in additionalTargetPaths.Split(';')) { if (!String.IsNullOrEmpty(additionalTargetPath)) { targetPaths.Add(additionalTargetPath + '/' + Path.GetFileName(packageFile)); } } } var assemblyVersion = extension == s_dll?VersionUtility.GetAssemblyVersion(packageFile) : null; PackageItem liveFile = null; foreach (var livePackagePath in targetPaths) { // determine if the harvested file clashes with a live built file // we'll prefer the harvested reference assembly so long as it's the same API // version and not required to match implementation 1:1 as is the case for desktop if (livePackageFiles.TryGetValue(livePackagePath, out liveFile)) { // Not a dll, or not a versioned assembly: prefer live built file. if (extension != s_dll || assemblyVersion == null || liveFile.Version == null) { // we don't consider this an error even for explicitly included files Log.LogMessage(LogImportance.Low, $"Preferring live build of package path {livePackagePath} over the asset from last stable package because the file is not versioned."); continue; } // not a ref if (!liveFile.IsRef) { LogSkipIncludedFile(livePackagePath, " because it is a newer implementation."); continue; } // preserve desktop references to ensure bindingRedirects will work. if (liveFile.TargetFramework.Framework == FrameworkConstants.FrameworkIdentifiers.Net) { LogSkipIncludedFile(livePackagePath, " because it is desktop reference."); continue; } // as above but handle the case where a netstandard ref may be used for a desktop impl. if (preserveRefVersion.Contains(liveFile.Version)) { LogSkipIncludedFile(livePackagePath, " because it will be applicable for desktop projects."); continue; } // preserve references with a different major.minor version if (assemblyVersion.Major != liveFile.Version.Major || assemblyVersion.Minor != liveFile.Version.Minor) { LogSkipIncludedFile(livePackagePath, $" because it is a different API version ( {liveFile.Version.Major}.{liveFile.Version.Minor} vs {assemblyVersion.Major}.{assemblyVersion.Minor}."); continue; } // preserve references that specifically set the preserve metadata. bool preserve = false; bool.TryParse(liveFile.OriginalItem.GetMetadata("Preserve"), out preserve); if (preserve) { LogSkipIncludedFile(livePackagePath, " because it set metadata Preserve=true."); continue; } // replace the live file with the harvested one, removing both the live file and PDB from the // file list. Log.LogMessage($"Using reference {livePackagePath} from last stable package {PackageId}/{PackageVersion} rather than the built reference {liveFile.SourcePath} since it is the same API version. Set <Preserve>true</Preserve> on {liveFile.SourceProject} if you'd like to avoid this.."); removeFiles.Add(liveFile.OriginalItem); PackageItem livePdbFile; if (livePackageFiles.TryGetValue(Path.ChangeExtension(livePackagePath, ".pdb"), out livePdbFile)) { removeFiles.Add(livePdbFile.OriginalItem); } } else { Log.LogMessage(LogImportance.Low, $"Including {livePackagePath} from last stable package {PackageId}/{PackageVersion}."); } var item = new TaskItem(packageFile); if (liveFile?.OriginalItem != null) { // preserve all the meta-data from the live file that was replaced. liveFile.OriginalItem.CopyMetadataTo(item); } else { if (includeItem != null) { includeItem.CopyMetadataTo(item); } var targetPath = Path.GetDirectoryName(livePackagePath).Replace('\\', '/'); item.SetMetadata("TargetPath", targetPath); string targetFramework = GetTargetFrameworkFromPackagePath(targetPath); item.SetMetadata("TargetFramework", targetFramework); // only harvest for non-portable frameworks, matches logic in packaging.targets. bool harvestDependencies = !targetFramework.StartsWith("portable-"); item.SetMetadata("HarvestDependencies", harvestDependencies.ToString()); item.SetMetadata("IsReferenceAsset", IsReferencePackagePath(targetPath).ToString()); } if (assemblyVersion != null) { // overwrite whatever metadata may have been copied from the live file. item.SetMetadata("AssemblyVersion", assemblyVersion.ToString()); } item.SetMetadata("HarvestedFrom", $"{PackageId}/{PackageVersion}/{harvestPackagePath}"); harvestedFiles.Add(item); } } } HarvestedFiles = harvestedFiles.ToArray(); if (_pathsNotIncluded != null) { foreach (var pathNotIncluded in _pathsNotIncluded) { Log.LogError($"Path '{pathNotIncluded}' was specified in {nameof(PathsToInclude)} but was not found in the package {PackageId}/{PackageVersion}."); } } if (Files != null) { UpdatedFiles = Files.Except(removeFiles).ToArray(); } }