private void LoadFiles() { _packageToPackageItems = new Dictionary<string, List<PackageItem>>(); foreach (var file in PackageAssets) { try { var packageItem = new PackageItem(file); if (String.IsNullOrWhiteSpace(packageItem.TargetPath)) { Log.LogError($"{packageItem.TargetPath} is missing TargetPath metadata"); } if (!_packageToPackageItems.ContainsKey(packageItem.Package)) { _packageToPackageItems[packageItem.Package] = new List<PackageItem>(); } _packageToPackageItems[packageItem.Package].Add(packageItem); } catch (Exception ex) { Log.LogError($"Could not parse File {file.ItemSpec}. {ex}"); // skip it. } } // build a map to translate back to source file from resolved asset // we use package-specific paths since we're resolving a set of packages. _targetPathToPackageItem = new Dictionary<string, PackageItem>(); foreach (var packageFiles in _packageToPackageItems) { foreach (PackageItem packageFile in packageFiles.Value) { string packageSpecificTargetPath = AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageFiles.Key, packageFile.TargetPath); if (_targetPathToPackageItem.ContainsKey(packageSpecificTargetPath)) { Log.LogError($"Files {_targetPathToPackageItem[packageSpecificTargetPath].SourcePath} and {packageFile.SourcePath} have the same TargetPath {packageSpecificTargetPath}."); } _targetPathToPackageItem[packageSpecificTargetPath] = packageFile; } } _resolver = new AggregateNuGetAssetResolver(RuntimeFile); foreach (string packageId in _packageToPackageItems.Keys) { _resolver.AddPackageItems(packageId, _packageToPackageItems[packageId].Select(f => f.TargetPath)); } }
private ITaskItem PackageItemAsResolvedAsset(PackageItem packageItem) { var item = new TaskItem(packageItem.OriginalItem); item.SetMetadata("Private", "false"); item.SetMetadata("FromPkgProj", "true"); item.SetMetadata("NuGetPackageId", packageItem.Package); item.SetMetadata("NuGetPackageVersion", packageItem.PackageVersion); return item; }
private static ITaskItem SetPackageMetadata(ITaskItem item, PackageItem packageItem) { item.SetMetadata("Private", "false"); item.SetMetadata("FromPkgProj", "true"); item.SetMetadata("NuGetPackageId", packageItem.Package); item.SetMetadata("NuGetPackageVersion", packageItem.PackageVersion); return item; }
private void LoadFiles() { _validateFiles = new Dictionary<string, List<PackageItem>>(); foreach (var file in Files) { try { var validateFile = new PackageItem(file); if (String.IsNullOrWhiteSpace(validateFile.TargetPath)) { Log.LogError($"{validateFile.TargetPath} is missing TargetPath metadata"); } if (IsDll(validateFile.SourcePath)) { if (validateFile.TargetFramework == null) { Log.LogError($"{validateFile.SourcePath} is missing TargetFramework metadata"); } else if (validateFile.TargetPath.IndexOf(validateFile.TargetFramework.GetShortFolderName(), StringComparison.OrdinalIgnoreCase) == -1) { Log.LogError($"{validateFile.SourcePath} specifies TargetFramework {validateFile.TargetFramework} but TargetPath {validateFile.TargetPath} is missing the {validateFile.TargetFramework.GetShortFolderName()} qualifier"); } } if (!_validateFiles.ContainsKey(validateFile.Package)) { _validateFiles[validateFile.Package] = new List<PackageItem>(); } _validateFiles[validateFile.Package].Add(validateFile); } catch (Exception ex) { Log.LogError($"Could not parse File {file.ItemSpec}. {ex}"); // skip it. } } // build a map to translate back to source file from resolved asset // we use package-specific paths since we're resolving a set of packages. _targetPathToPackageItem = new Dictionary<string, PackageItem>(); foreach (var packageFiles in _validateFiles) { foreach (PackageItem validateFile in packageFiles.Value) { string packageSpecificTargetPath = AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageFiles.Key, validateFile.TargetPath); if (_targetPathToPackageItem.ContainsKey(packageSpecificTargetPath)) { Log.LogError($"Files {_targetPathToPackageItem[packageSpecificTargetPath].SourcePath} and {validateFile.SourcePath} have the same TargetPath {packageSpecificTargetPath}."); } _targetPathToPackageItem[packageSpecificTargetPath] = validateFile; } } _resolver = new AggregateNuGetAssetResolver(RuntimeFile); foreach (string packageId in _validateFiles.Keys) { _resolver.AddPackageItems(packageId, _validateFiles[packageId].Select(f => f.TargetPath)); } }
private static ITaskItem PackageItemAsResolvedAsset(PackageItem packageItem) { return SetPackageMetadata(new TaskItem(packageItem.OriginalItem), packageItem); }
private static IEnumerable<ITaskItem> PackageItemAndSymbolsAsResolvedAsset(PackageItem packageItem) { yield return PackageItemAsResolvedAsset(packageItem); string pdbPath = Path.ChangeExtension(packageItem.SourcePath, ".pdb"); if (File.Exists(pdbPath)) { var pdbItem = new TaskItem(Path.ChangeExtension(packageItem.OriginalItem.ItemSpec, ".pdb")); packageItem.OriginalItem.CopyMetadataTo(pdbItem); SetPackageMetadata(pdbItem, packageItem); if (!String.IsNullOrEmpty(packageItem.TargetPath)) { pdbItem.SetMetadata("TargetPath", Path.ChangeExtension(packageItem.TargetPath, ".pdb")); } yield return pdbItem; } }
private static ITaskItem GetOOBItem(PackageItem oobItem, string targetPath, string targetFramework) { TaskItem item = new TaskItem(oobItem.OriginalItem); item.SetMetadata("TargetPath", targetPath); item.SetMetadata("TargetFramework", targetFramework); return item; }
public static BuildProject BuildProjectFromPackageItem(PackageItem packageItem) { if (packageItem.SourceProject == null) { return null; } return new BuildProject() { Project = packageItem.SourceProject, AdditionalProperties = packageItem.AdditionalProperties, UndefineProperties = packageItem.UndefineProperties }; }
private void LoadFiles() { var packageItems = new Dictionary<string, List<PackageItem>>(); foreach (var file in Files) { try { var packageItem = new PackageItem(file); if (!packageItem.TargetPath.StartsWith("runtimes") && !packageItem.IsDll && !packageItem.IsPlaceholder) { continue; } if (String.IsNullOrWhiteSpace(packageItem.TargetPath)) { Log.LogError($"{packageItem.TargetPath} is missing TargetPath metadata"); } string packageId = packageItem.Package ?? PackageId; if (!packageItems.ContainsKey(packageId)) { packageItems[packageId] = new List<PackageItem>(); } packageItems[packageId].Add(packageItem); } catch (Exception ex) { Log.LogError($"Could not parse File {file.ItemSpec}. {ex}"); // skip it. } } // build a map to translate back to source file from resolved asset // we use package-specific paths since we're resolving a set of packages. _targetPathToPackageItem = new Dictionary<string, PackageItem>(); _unusedTargetPaths = new HashSet<string>(); foreach (var packageSpecificItems in packageItems) { foreach (PackageItem packageItem in packageSpecificItems.Value) { string packageSpecificTargetPath = AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageSpecificItems.Key, packageItem.TargetPath); if (_targetPathToPackageItem.ContainsKey(packageSpecificTargetPath)) { Log.LogError($"Files {_targetPathToPackageItem[packageSpecificTargetPath].SourcePath} and {packageItem.SourcePath} have the same TargetPath {packageSpecificTargetPath}."); } _targetPathToPackageItem[packageSpecificTargetPath] = packageItem; _unusedTargetPaths.Add(packageSpecificTargetPath); } } _resolver = new AggregateNuGetAssetResolver(RuntimeFile); foreach (string packageId in packageItems.Keys) { _resolver.AddPackageItems(packageId, packageItems[packageId].Select(f => f.TargetPath)); } // 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 if (packageItems.Any() && packageItems.ContainsKey(PackageId)) { var filesWithoutPlaceholders = packageItems[PackageId] .Select(pf => pf.TargetPath) .Where(f => !NuGetAssetResolver.IsPlaceholder(f)); _resolverWithoutPlaceholders = new NuGetAssetResolver(RuntimeFile, filesWithoutPlaceholders); } }
private void LoadFiles() { var packageItems = new Dictionary <string, List <PackageItem> >(); foreach (var file in Files) { try { var packageItem = new PackageItem(file); if (!packageItem.TargetPath.StartsWith("runtimes") && !packageItem.IsDll && !packageItem.IsPlaceholder) { continue; } if (String.IsNullOrWhiteSpace(packageItem.TargetPath)) { Log.LogError($"{packageItem.TargetPath} is missing TargetPath metadata"); } string packageId = packageItem.Package ?? PackageId; if (!packageItems.ContainsKey(packageId)) { packageItems[packageId] = new List <PackageItem>(); } packageItems[packageId].Add(packageItem); } catch (Exception ex) { Log.LogError($"Could not parse File {file.ItemSpec}. {ex}"); // skip it. } } // build a map to translate back to source file from resolved asset // we use package-specific paths since we're resolving a set of packages. _targetPathToPackageItem = new Dictionary <string, PackageItem>(); _unusedTargetPaths = new HashSet <string>(); foreach (var packageSpecificItems in packageItems) { foreach (PackageItem packageItem in packageSpecificItems.Value) { string packageSpecificTargetPath = AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageSpecificItems.Key, packageItem.TargetPath); if (_targetPathToPackageItem.ContainsKey(packageSpecificTargetPath)) { Log.LogError($"Files {_targetPathToPackageItem[packageSpecificTargetPath].SourcePath} and {packageItem.SourcePath} have the same TargetPath {packageSpecificTargetPath}."); } _targetPathToPackageItem[packageSpecificTargetPath] = packageItem; _unusedTargetPaths.Add(packageSpecificTargetPath); } } _resolver = new AggregateNuGetAssetResolver(RuntimeFile); foreach (string packageId in packageItems.Keys) { _resolver.AddPackageItems(packageId, packageItems[packageId].Select(f => f.TargetPath)); } // 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 if (packageItems.Any() && packageItems.ContainsKey(PackageId)) { var filesWithoutPlaceholders = packageItems[PackageId] .Select(pf => pf.TargetPath) .Where(f => !NuGetAssetResolver.IsPlaceholder(f)); _resolverWithoutPlaceholders = new NuGetAssetResolver(RuntimeFile, filesWithoutPlaceholders); } }
private static ITaskItem PackageItemAsResolvedAsset(PackageItem packageItem) { return(SetPackageMetadata(new TaskItem(packageItem.OriginalItem), packageItem)); }
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 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 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 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(); } }
private void LoadFiles() { _validateFiles = new Dictionary <string, List <PackageItem> >(); foreach (var file in Files) { try { var validateFile = new PackageItem(file); if (String.IsNullOrWhiteSpace(validateFile.TargetPath)) { Log.LogError($"{validateFile.TargetPath} is missing TargetPath metadata"); } if (IsDll(validateFile.SourcePath)) { if (validateFile.TargetFramework == null) { Log.LogError($"{validateFile.SourcePath} is missing TargetFramework metadata"); } else if (validateFile.TargetPath.IndexOf(validateFile.TargetFramework.GetShortFolderName(), StringComparison.OrdinalIgnoreCase) == -1) { Log.LogError($"{validateFile.SourcePath} specifies TargetFramework {validateFile.TargetFramework} but TargetPath {validateFile.TargetPath} is missing the {validateFile.TargetFramework.GetShortFolderName()} qualifier"); } } if (!_validateFiles.ContainsKey(validateFile.Package)) { _validateFiles[validateFile.Package] = new List <PackageItem>(); } _validateFiles[validateFile.Package].Add(validateFile); } catch (Exception ex) { Log.LogError($"Could not parse File {file.ItemSpec}. {ex}"); // skip it. } } // build a map to translate back to source file from resolved asset // we use package-specific paths since we're resolving a set of packages. _targetPathToPackageItem = new Dictionary <string, PackageItem>(); foreach (var packageFiles in _validateFiles) { foreach (PackageItem validateFile in packageFiles.Value) { string packageSpecificTargetPath = AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageFiles.Key, validateFile.TargetPath); if (_targetPathToPackageItem.ContainsKey(packageSpecificTargetPath)) { Log.LogError($"Files {_targetPathToPackageItem[packageSpecificTargetPath].SourcePath} and {validateFile.SourcePath} have the same TargetPath {packageSpecificTargetPath}."); } _targetPathToPackageItem[packageSpecificTargetPath] = validateFile; } } _resolver = new AggregateNuGetAssetResolver(RuntimeFile); foreach (string packageId in _validateFiles.Keys) { _resolver.AddPackageItems(packageId, _validateFiles[packageId].Select(f => f.TargetPath)); } }