public void GetLastStablePackagesFromIndex() { var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); List <ITaskItem> lastStablePackages = new List <ITaskItem>(); foreach (var latestPackage in LatestPackages) { var packageId = latestPackage.ItemSpec; var versionString = latestPackage.GetMetadata("Version"); NuGetVersion nuGetVersion = null; if (versionString == null || !NuGetVersion.TryParse(versionString, out nuGetVersion)) { Log.LogMessage($"Could not parse version {versionString} for LatestPackage {packageId}, will use latest stable."); } var latestVersion = nuGetVersion?.Version; PackageInfo info; if (index.Packages.TryGetValue(packageId, out info)) { var candidateVersions = (latestVersion == null) ? info.StableVersions : info.StableVersions.Where(sv => VersionUtility.As4PartVersion(sv) < latestVersion); if (candidateVersions.Any()) { lastStablePackages.Add(CreateItem(latestPackage, candidateVersions.Max())); } } } LastStablePackages = lastStablePackages.ToArray(); }
public override bool Execute() { if (References == null || References.Length == 0) { return(true); } if (PackageIndexes == null && PackageIndexes.Length == 0) { Log.LogError("PackageIndexes argument must be specified"); return(false); } var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); Dictionary <string, ITaskItem> packageReferences = new Dictionary <string, ITaskItem>(); Dictionary <string, ITaskItem> assemblyReferences = new Dictionary <string, ITaskItem>(); bool referencesMscorlib = false; NuGetFramework targetFx = NuGetFramework.Parse(TargetFramework); foreach (var reference in References) { string referenceName = reference.ItemSpec; referencesMscorlib |= referenceName.Equals("mscorlib"); string referenceVersion = reference.GetMetadata("Version"); reference.SetMetadata("TargetFramework", TargetFramework); if (!string.IsNullOrEmpty(TargetFramework) && index.IsInbox(referenceName, targetFx, referenceVersion)) { AddReference(assemblyReferences, reference); } else { AddReference(packageReferences, reference); } } if (referencesMscorlib) { // only add framework references for mscorlib-based assemblies. FrameworkReferences = assemblyReferences.Values.ToArray(); } if (packageReferences.Count == 0) { var emptyItem = new TaskItem("_._"); emptyItem.SetMetadata("TargetFramework", TargetFramework); packageReferences.Add(emptyItem.ItemSpec, emptyItem); } PackageReferences = packageReferences.Values.ToArray(); return(true); }
public override bool Execute() { if (null == OriginalPackages || OriginalPackages.Length == 0) { Log.LogError($"{nameof(OriginalPackages)} argument must be specified"); return(false); } if (String.IsNullOrEmpty(PreReleaseSuffix)) { Log.LogError($"{nameof(PreReleaseSuffix)} argument must be specified"); return(false); } if (PackageIndexes != null && PackageIndexes.Length > 0) { _index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); } else { LoadStablePackages(); } List <ITaskItem> updatedPackages = new List <ITaskItem>(); foreach (var originalPackage in OriginalPackages) { string packageId = originalPackage.ItemSpec; if (packageId == "_._") { updatedPackages.Add(originalPackage); continue; } TaskItem updatedPackage = new TaskItem(originalPackage); Version packageVersion = ParseAs3PartVersion(originalPackage.GetMetadata("Version")); if (!IsStable(packageId, packageVersion)) { // pre-release, set with suffix updatedPackage.SetMetadata("Version", packageVersion.ToString() + GetSuffix(packageId)); } else { // stable, just set the 3 part version without suffix updatedPackage.SetMetadata("Version", packageVersion.ToString()); } updatedPackages.Add(updatedPackage); } UpdatedPackages = updatedPackages.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { if (PackageIndexes == null && PackageIndexes.Length == 0) { Log.LogError("PackageIndexes argument must be specified"); return(false); } index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); List <ITaskItem> promotedDependencies = new List <ITaskItem>(); var dependencies = Dependencies.Select(d => new Dependency(d)).ToArray(); var refSets = dependencies.Where(d => d.Id != "_._").Where(d => d.IsReference).GroupBy(d => NuGetFramework.Parse(d.TargetFramework)).ToDictionary(g => g.Key, g => g.ToArray()); var refFxs = refSets.Keys.ToArray(); Log.LogMessage(LogImportance.Low, $"Ref frameworks {string.Join(";", refFxs.Select(f => f.ToString()))}"); var libSets = dependencies.Where(d => !d.IsReference).GroupBy(d => NuGetFramework.Parse(d.TargetFramework)).ToDictionary(g => g.Key, g => g.ToArray()); var libFxs = libSets.Keys.ToArray(); Log.LogMessage(LogImportance.Low, $"Lib frameworks {string.Join(";", libFxs.Select(f => f.ToString()))}"); if (libFxs.Length > 0) { foreach (var refFx in refFxs) { // find best lib (if any) var nearestLibFx = FrameworkUtilities.GetNearest(refFx, libFxs); if (nearestLibFx != null && !nearestLibFx.Equals(refFx)) { promotedDependencies.AddRange(CopyDependencies(libSets[nearestLibFx], refFx)); } } } if (refFxs.Length > 0) { foreach (var libFx in libFxs) { // find best lib (if any) var nearestRefFx = FrameworkUtilities.GetNearest(libFx, refFxs); if (nearestRefFx != null && !nearestRefFx.Equals(libFx)) { promotedDependencies.AddRange(CopyDependencies(refSets[nearestRefFx], libFx)); } } } PromotedDependencies = promotedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { if (!Apply) { UpdatedDependencies = OriginalDependencies; return(true); } var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); List <ITaskItem> updatedDependencies = new List <ITaskItem>(); var suppressMetaPackages = new HashSet <string>(SuppressMetaPackages.NullAsEmpty(), StringComparer.OrdinalIgnoreCase); // We cannot add a dependency to a meta-package from a package that itself is part of the meta-package otherwise we create a cycle var metaPackageThisPackageIsIn = index.MetaPackages.GetMetaPackageId(PackageId); if (metaPackageThisPackageIsIn != null) { suppressMetaPackages.Add(metaPackageThisPackageIsIn); } // keep track of meta-package dependencies to add by framework so that we only add them once per framework. Dictionary <string, HashSet <NuGetFramework> > metaPackagesToAdd = new Dictionary <string, HashSet <NuGetFramework> >(); foreach (var originalDependency in OriginalDependencies) { var metaPackage = index.MetaPackages.GetMetaPackageId(originalDependency.ItemSpec); if (metaPackage != null && !suppressMetaPackages.Contains(metaPackage)) { // convert to meta-package dependency var tfm = originalDependency.GetMetadata("TargetFramework"); var fx = NuGetFramework.Parse(tfm); HashSet <NuGetFramework> metaPackageFrameworks; if (!metaPackagesToAdd.TryGetValue(metaPackage, out metaPackageFrameworks)) { metaPackagesToAdd[metaPackage] = metaPackageFrameworks = new HashSet <NuGetFramework>(); } metaPackageFrameworks.Add(fx); } else { updatedDependencies.Add(originalDependency); } } updatedDependencies.AddRange(metaPackagesToAdd.SelectMany(pair => pair.Value.Select(tfm => CreateDependency(pair.Key, tfm)))); UpdatedDependencies = updatedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { IDictionary <string, string> modulesToPackages; if (PackageIndexes != null && PackageIndexes.Length > 0) { var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); modulesToPackages = index.ModulesToPackages; } else { modulesToPackages = new Dictionary <string, string>(); foreach (var modulePackage in ModulePackages.NullAsEmpty()) { modulesToPackages.Add(modulePackage.ItemSpec, modulePackage.GetMetadata("Package")); } } List <ITaskItem> packagesReferenced = new List <ITaskItem>(); foreach (var moduleReferenced in ModulesReferenced) { string moduleName = moduleReferenced.ItemSpec; string packageId; if (modulesToPackages.TryGetValue(moduleName, out packageId)) { var packageReferenced = new TaskItem(packageId); packageReferenced.SetMetadata("NativeLibrary", moduleName); moduleReferenced.CopyMetadataTo(packageReferenced); packagesReferenced.Add(packageReferenced); } } PackagesReferenced = packagesReferenced.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { if (PackageIndexes == null && PackageIndexes.Length == 0) { Log.LogError("PackageIndexes argument must be specified"); return(false); } if (String.IsNullOrEmpty(AssemblyName)) { Log.LogError("AssemblyName argument must be specified"); return(false); } Log.LogMessage(LogImportance.Low, "Determining inbox frameworks for {0}, {1}", AssemblyName, AssemblyVersion); var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); InboxFrameworks = index.GetInboxFrameworks(AssemblyName, AssemblyVersion).Select(fx => fx.GetShortFolderName()).ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); List <ITaskItem> updatedDependencies = new List <ITaskItem>(); // keep track of meta-package dependencies to add by framework so that we only add them once per framework. Dictionary <string, HashSet <NuGetFramework> > metaPackagesToAdd = new Dictionary <string, HashSet <NuGetFramework> >(); foreach (var originalDependency in OriginalDependencies) { var metaPackage = index.MetaPackages.GetMetaPackageId(originalDependency.ItemSpec); if (metaPackage != null) { // convert to meta-package dependency var tfm = originalDependency.GetMetadata("TargetFramework"); var fx = NuGetFramework.Parse(tfm); HashSet <NuGetFramework> metaPackageFrameworks; if (!metaPackagesToAdd.TryGetValue(metaPackage, out metaPackageFrameworks)) { metaPackagesToAdd[metaPackage] = metaPackageFrameworks = new HashSet <NuGetFramework>(); } metaPackageFrameworks.Add(fx); } else { updatedDependencies.Add(originalDependency); } } updatedDependencies.AddRange(metaPackagesToAdd.SelectMany(pair => pair.Value.Select(tfm => CreateDependency(pair.Key, tfm)))); UpdatedDependencies = updatedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { Func <string, bool> isKnownPackage; if (PackageIndexes != null && PackageIndexes.Length > 0) { var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); isKnownPackage = packageId => index.Packages.ContainsKey(packageId); } else { var baseLinePackageIds = new HashSet <string>(BaseLinePackages.NullAsEmpty().Select(b => b.ItemSpec)); isKnownPackage = packageId => baseLinePackageIds.Contains(packageId); } FilteredDependencies = OriginalDependencies.Where( dependency => !dependency.ItemSpec.StartsWith("System.Private") || // only apply filtering to System.Private dependencies isKnownPackage(dependency.ItemSpec) ).ToArray(); return(!Log.HasLoggedErrors); }
public void GetBaseLinedDependenciesFromIndex() { var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); List <ITaskItem> baseLinedDependencies = new List <ITaskItem>(); foreach (var dependency in OriginalDependencies) { Version assemblyVersion = null, packageVersion = null, baseLineVersion = null; string packageId = dependency.ItemSpec; Version.TryParse(dependency.GetMetadata("Version"), out packageVersion); Version.TryParse(dependency.GetMetadata("AssemblyVersion"), out assemblyVersion); // if we have an assembly version see if we have a better package version if (assemblyVersion != null) { packageVersion = index.GetPackageVersionForAssemblyVersion(packageId, assemblyVersion); } if (Apply && index.TryGetBaseLineVersion(packageId, out baseLineVersion) && (packageVersion == null || baseLineVersion > packageVersion)) { packageVersion = baseLineVersion; } if (packageVersion != assemblyVersion) { dependency.SetMetadata("Version", packageVersion.ToString()); } baseLinedDependencies.Add(dependency); } BaseLinedDependencies = baseLinedDependencies.ToArray(); }
public override bool Execute() { if (!Apply) { UpdatedDependencies = OriginalDependencies; return(true); } var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); List <ITaskItem> updatedDependencies = new List <ITaskItem>(); var suppressMetaPackages = new Dictionary <string, HashSet <string> >(); if (SuppressMetaPackages != null) { foreach (ITaskItem metapackage in SuppressMetaPackages) { if (!suppressMetaPackages.TryGetValue(metapackage.ItemSpec, out var value)) { value = new HashSet <string>(); suppressMetaPackages.Add(metapackage.ItemSpec, value); } var tfmSpecificSupression = metapackage.GetMetadata("TargetFramework"); if (string.IsNullOrEmpty(tfmSpecificSupression)) { // If the supression doesn't specify a TargetFramework, then it applies to all. value.Add("All"); } else { var fx = NuGetFramework.Parse(tfmSpecificSupression); value.Add(fx.DotNetFrameworkName); } } } // We cannot add a dependency to a meta-package from a package that itself is part of the meta-package otherwise we create a cycle var metaPackageThisPackageIsIn = index.MetaPackages.GetMetaPackageId(PackageId); if (metaPackageThisPackageIsIn != null) { suppressMetaPackages.Add(metaPackageThisPackageIsIn, new HashSet <string> { "All" }); } // keep track of meta-package dependencies to add by framework so that we only add them once per framework. Dictionary <string, HashSet <NuGetFramework> > metaPackagesToAdd = new Dictionary <string, HashSet <NuGetFramework> >(); foreach (var originalDependency in OriginalDependencies) { var metaPackage = index.MetaPackages.GetMetaPackageId(originalDependency.ItemSpec); // convert to meta-package dependency var tfm = originalDependency.GetMetadata("TargetFramework"); var fx = NuGetFramework.Parse(tfm); if (metaPackage != null && !ShouldSuppressMetapackage(suppressMetaPackages, metaPackage, fx)) { HashSet <NuGetFramework> metaPackageFrameworks; if (!metaPackagesToAdd.TryGetValue(metaPackage, out metaPackageFrameworks)) { metaPackagesToAdd[metaPackage] = metaPackageFrameworks = new HashSet <NuGetFramework>(); } metaPackageFrameworks.Add(fx); } else { updatedDependencies.Add(originalDependency); } } updatedDependencies.AddRange(metaPackagesToAdd.SelectMany(pair => pair.Value.Select(tfm => CreateDependency(pair.Key, tfm)))); UpdatedDependencies = updatedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
private void LoadSupport() { _frameworks = new Dictionary <NuGetFramework, ValidationFramework>(); // determine which TxM:RIDs should be considered for support based on Frameworks item foreach (var framework in Frameworks) { 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; } string runtimeIdList = framework.GetMetadata("RuntimeIDs"); if (_frameworks.ContainsKey(fx)) { Log.LogError($"Framework {fx} has been listed in Frameworks more than once."); continue; } _frameworks[fx] = new ValidationFramework(fx); if (!String.IsNullOrWhiteSpace(runtimeIdList)) { _frameworks[fx].RuntimeIds = runtimeIdList.Split(';'); } } // keep a list of explicitly listed supported frameworks so that we can check for conflicts. HashSet <NuGetFramework> explicitlySupportedFrameworks = new HashSet <NuGetFramework>(NuGetFramework.Comparer); // determine what version should be supported based on SupportedFramework items foreach (var supportedFramework in SupportedFrameworks) { NuGetFramework fx; string fxString = supportedFramework.ItemSpec; bool isExclusiveVersion = fxString.Length > 1 && fxString[0] == '[' && fxString[fxString.Length - 1] == ']'; if (isExclusiveVersion) { fxString = fxString.Substring(1, fxString.Length - 2); } try { fx = FrameworkUtilities.ParseNormalized(fxString); } catch (Exception ex) { Log.LogError($"Could not parse TargetFramework {fxString} as a SupportedFramework. {ex}"); continue; } if (fx.Equals(NuGetFramework.UnsupportedFramework)) { Log.LogError($"Did not recognize TargetFramework {fxString} as a SupportedFramework."); continue; } Version supportedVersion; string version = supportedFramework.GetMetadata("Version"); try { supportedVersion = Version.Parse(version); } catch (Exception ex) { Log.LogError($"Could not parse Version {version} on SupportedFramework item {supportedFramework.ItemSpec}. {ex}"); continue; } ValidationFramework validationFramework = null; if (!_frameworks.TryGetValue(fx, out validationFramework)) { Log.LogError($"SupportedFramework {fx} was specified but is not part of the Framework list to use for validation."); continue; } if (explicitlySupportedFrameworks.Contains(fx)) { if (supportedVersion <= validationFramework.SupportedVersion) { // if we've already picked up a higher/equal version, prefer it continue; } } else { explicitlySupportedFrameworks.Add(fx); } validationFramework.SupportedVersion = supportedVersion; if (!isExclusiveVersion) { // find all frameworks of higher version, sorted by version ascending IEnumerable <ValidationFramework> higherFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == fx.Framework && vf.Framework.Version > fx.Version).OrderBy(vf => vf.Framework.Version); // netcore50 is the last `netcore` framework, after that we use `uap` if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetCore) { var uapFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == FrameworkConstants.FrameworkIdentifiers.UAP).OrderBy(vf => vf.Framework.Version); higherFrameworks = higherFrameworks.Concat(uapFrameworks); } foreach (var higherFramework in higherFrameworks) { if (higherFramework.SupportedVersion != null && higherFramework.SupportedVersion > supportedVersion) { // found an higher framework version a higher API version, stop applying this supported version break; } higherFramework.SupportedVersion = supportedVersion; } } } // determine which Frameworks should support inbox _index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); foreach (var inboxPair in _index.GetInboxVersions(ContractName).NullAsEmpty()) { var fx = inboxPair.Key; var inboxVersion = inboxPair.Value; if (inboxVersion != null) { ValidationFramework validationFramework = null; if (_frameworks.TryGetValue(fx, out validationFramework)) { Version supportedVersion = validationFramework.SupportedVersion; if (supportedVersion != null && (supportedVersion.Major > inboxVersion.Major || (supportedVersion.Major == inboxVersion.Major && supportedVersion.Minor > inboxVersion.Minor))) { // Higher major.minor Log.LogMessage(LogImportance.Low, $"Framework {fx} supported {ContractName} as inbox but the current supported version {supportedVersion} is higher in major.minor than inbox version {inboxVersion}. Assuming out of box."); continue; } else if (supportedVersion != null && supportedVersion < inboxVersion && inboxVersion != VersionUtility.MaxVersion) { // Lower version Log.LogError($"Framework {fx} supports {ContractName} as inbox but the current supported version {supportedVersion} is lower than the inbox version {inboxVersion}"); } // equal major.minor, build.revision difference is permitted, prefer the version listed by ContractSupport item } if (validationFramework == null) { // we may not be explicitly validating for this framework so add it to validate inbox assets. _frameworks[fx] = validationFramework = new ValidationFramework(fx) { SupportedVersion = inboxVersion }; } validationFramework.IsInbox = true; } } // for every framework we know about, also infer it's netstandard version to ensure it can // be targeted by PCL. Even if a package only supports a single framework we still // want to include a portable reference assembly. This allows 3rd parties to add // their own implementation via a lineup/runtime.json. // only consider frameworks that support the contract at a specific version var inferFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null && fx.SupportedVersion != VersionUtility.MaxVersion).ToArray(); var genVersionSuppression = GetSuppressionValues(Suppression.PermitPortableVersionMismatch) ?? new HashSet <string>(); var inferNETStandardSuppression = GetSuppressionValues(Suppression.SuppressNETStandardInference) ?? new HashSet <string>(); Dictionary <NuGetFramework, ValidationFramework> generationsToValidate = new Dictionary <NuGetFramework, ValidationFramework>(); foreach (var inferFramework in inferFrameworks) { var inferFrameworkMoniker = inferFramework.Framework.ToString(); if (inferNETStandardSuppression.Contains(inferFrameworkMoniker)) { continue; } NuGetFramework generation = new NuGetFramework(_generationIdentifier, Generations.DetermineGenerationForFramework(inferFramework.Framework, UseNetPlatform)); Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {inferFramework.SupportedVersion} since it is supported by {inferFrameworkMoniker}"); ValidationFramework existingGeneration = null; if (generationsToValidate.TryGetValue(generation, out existingGeneration)) { // the netstandard version should be the minimum version supported by all platforms that support that netstandard version. if (inferFramework.SupportedVersion < existingGeneration.SupportedVersion) { Log.LogMessage($"Framework {inferFramework.Framework} supports {ContractName} at {inferFramework.SupportedVersion} which is lower than {existingGeneration.SupportedVersion} supported by generation {generation.GetShortFolderName()}. Lowering the version supported by {generation.GetShortFolderName()}."); existingGeneration.SupportedVersion = inferFramework.SupportedVersion; } } else { generationsToValidate.Add(generation, new ValidationFramework(generation) { SupportedVersion = inferFramework.SupportedVersion }); } } foreach (var generation in generationsToValidate) { _frameworks.Add(generation.Key, generation.Value); } }
/* Given a set of available frameworks ("InboxOnTargetFrameworks"), and a list of desired frameworks, * reduce the set of frameworks to the minimum set of frameworks which is compatible (preferring inbox frameworks. */ public override bool Execute() { if (null == Dependencies) { Log.LogError("Dependencies argument must be specified"); return(false); } if (PackageIndexes == null && PackageIndexes.Length == 0) { Log.LogError("PackageIndexes argument must be specified"); return(false); } var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); // Retrieve the list of dependency group TFM's var dependencyGroups = Dependencies .Select(dependencyItem => new TaskItemPackageDependency(dependencyItem)) .GroupBy(dependency => dependency.TargetFramework) .Select(dependencyGrouping => new TaskItemPackageDependencyGroup(dependencyGrouping.Key, dependencyGrouping)) .ToArray(); // Prepare a resolver for evaluating if candidate frameworks are actually supported by the package PackageItem[] packageItems = Files.Select(f => new PackageItem(f)).ToArray(); var packagePaths = packageItems.Select(pi => pi.TargetPath); NuGetAssetResolver resolver = new NuGetAssetResolver(null, packagePaths); // Determine all inbox frameworks which are supported by this package var supportedInboxFrameworks = index.GetAlllInboxFrameworks().Where(fx => IsSupported(fx, resolver)); var newDependencyGroups = new Queue <TaskItemPackageDependencyGroup>(); // For each inbox framework determine its best compatible dependency group and create an explicit group, trimming out any inbox dependencies foreach (var supportedInboxFramework in supportedInboxFrameworks) { var nearestDependencyGroup = dependencyGroups.GetNearest(supportedInboxFramework); // We found a compatible dependency group that is not the same as this framework if (nearestDependencyGroup != null && nearestDependencyGroup.TargetFramework != supportedInboxFramework) { // remove all dependencies which are inbox on supportedInboxFramework var filteredDependencies = nearestDependencyGroup.Packages.Where(d => !index.IsInbox(d.Id, supportedInboxFramework, d.AssemblyVersion)).ToArray(); newDependencyGroups.Enqueue(new TaskItemPackageDependencyGroup(supportedInboxFramework, filteredDependencies)); } } // Remove any redundant groups from the added set (EG: net45 and net46 with the same set of dependencies) int groupsToCheck = newDependencyGroups.Count; for (int i = 0; i < groupsToCheck; i++) { // to determine if this is a redundant group, we dequeue so that it won't be considered in the following check for nearest group. var group = newDependencyGroups.Dequeue(); // of the remaining groups, find the most compatible one var nearestGroup = newDependencyGroups.Concat(dependencyGroups).GetNearest(group.TargetFramework); // either we found no compatible group, // or the closest compatible group has different dependencies, // or the closest compatible group is portable and this is not (Portable profiles have different framework precedence, https://github.com/NuGet/Home/issues/6483), // keep it in the set of additions if (nearestGroup == null || !group.Packages.SetEquals(nearestGroup.Packages) || FrameworkUtilities.IsPortableMoniker(group.TargetFramework) != FrameworkUtilities.IsPortableMoniker(nearestGroup.TargetFramework)) { // not redundant, keep it in the queue newDependencyGroups.Enqueue(group); } } // Build the items representing added dependency groups. List <ITaskItem> trimmedDependencies = new List <ITaskItem>(); foreach (var newDependencyGroup in newDependencyGroups) { if (newDependencyGroup.Packages.Count == 0) { // no dependencies (all inbox), use a placeholder dependency. var item = new TaskItem(PlaceHolderDependency); item.SetMetadata("TargetFramework", newDependencyGroup.TargetFramework.GetShortFolderName()); trimmedDependencies.Add(item); } else { foreach (var dependency in newDependencyGroup.Packages) { var item = new TaskItem(dependency.Item); // emit CopiedFromTargetFramework to aide in debugging. item.SetMetadata("CopiedFromTargetFramework", item.GetMetadata("TargetFramework")); item.SetMetadata("TargetFramework", newDependencyGroup.TargetFramework.GetShortFolderName()); trimmedDependencies.Add(item); } } } TrimmedDependencies = trimmedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
private void LoadFrameworks() { _frameworks = new Dictionary <NuGetFramework, string[]>(NuGetFramework.Comparer); // load the specified frameworks 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; } _frameworks.Add(fx, runtimeIds); } // inspect any TFMs explicitly targeted var fileFrameworks = _targetPathToPackageItem.Values.Select(f => f.TargetFramework).Distinct(NuGetFramework.Comparer).Where(f => f != null); foreach (var fileFramework in fileFrameworks) { if (!_frameworks.ContainsKey(fileFramework)) { _frameworks.Add(fileFramework, s_noRids); } } // inspect any TFMs inbox var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); var inboxFrameworks = index.GetInboxFrameworks(PackageId).NullAsEmpty(); foreach (var inboxFramework in inboxFrameworks) { if (!_frameworks.ContainsKey(inboxFramework)) { _frameworks.Add(inboxFramework, s_noRids); } } // inspect for derived TFMs var expander = new FrameworkExpander(); foreach (var framework in _frameworks.Keys.ToArray()) { var derivedFxs = expander.Expand(framework); foreach (var derivedFx in derivedFxs) { if (derivedFx.IsDesktop() && derivedFx.HasProfile) { // skip desktop profiles continue; } if (derivedFx.Version.Major == 0 && derivedFx.Version.Minor == 0) { // skip unversioned frameworks continue; } if (s_ignoredFrameworks.Contains(derivedFx.Framework)) { continue; } if (!_frameworks.ContainsKey(derivedFx)) { _frameworks.Add(derivedFx, s_noRids); } } } }
/* Given a set of available frameworks ("InboxOnTargetFrameworks"), and a list of desired frameworks, * reduce the set of frameworks to the minimum set of frameworks which is compatible (preferring inbox frameworks. */ public override bool Execute() { if (null == Dependencies) { Log.LogError("Dependencies argument must be specified"); return(false); } if (PackageIndexes == null && PackageIndexes.Length == 0) { Log.LogError("PackageIndexes argument must be specified"); return(false); } var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); // Retrieve the list of generation dependency group TFM's var dependencyGroups = Dependencies.GroupBy(d => d.GetMetadata("TargetFramework")).Select(dg => new { Framework = NuGetFramework.Parse(dg.Key), Dependencies = dg.ToArray() }); List <ITaskItem> addedDependencies = new List <ITaskItem>(); // Exclude any non-portable frameworks that already have specific dependency groups. var frameworksToExclude = dependencyGroups.Select(dg => dg.Framework).Where(fx => !FrameworkUtilities.IsGenerationMoniker(fx)); // Prepare a resolver for evaluating if candidate frameworks are actually supported by the package PackageItem[] packageItems = Files.Select(f => new PackageItem(f)).ToArray(); var packagePaths = packageItems.Select(pi => pi.TargetPath); var targetFrameworksWithPlaceHolders = packageItems.Where(pi => NuGetAssetResolver.IsPlaceholder(pi.TargetPath)).Select(pi => pi.TargetFramework); NuGetAssetResolver resolver = new NuGetAssetResolver(null, packagePaths); foreach (var portableDependencyGroup in dependencyGroups.Where(dg => FrameworkUtilities.IsGenerationMoniker(dg.Framework))) { // Determine inbox frameworks for this generation that don't already have explicit groups HashSet <NuGetFramework> inboxFrameworksList = new HashSet <NuGetFramework>( index.GetAlllInboxFrameworks() .Where(fx => Generations.DetermineGenerationForFramework(fx, UseNetPlatform) >= portableDependencyGroup.Framework.Version && !frameworksToExclude.Any(exFx => exFx.Framework == fx.Framework && exFx.Profile == fx.Profile && exFx.Version <= fx.Version))); // Check for assets which have a ref, but not a lib asset. If we have any of these, then they are actually not supported frameworks // and we should not include them. inboxFrameworksList.RemoveWhere(inboxFx => !IsSupported(inboxFx, resolver)); // Only add the lowest version for a particular inbox framework. EG if both net45 and net46 are supported by this generation, // only add net45 inboxFrameworksList.RemoveWhere(fx => inboxFrameworksList.Any(otherFx => (otherFx.Framework.Equals(fx.Framework)) && (otherFx.Version < fx.Version))); // Create dependency items for each inbox framework. foreach (var framework in inboxFrameworksList) { bool addedDependencyToFramework = false; foreach (ITaskItem dependency in portableDependencyGroup.Dependencies) { string version = GetVersion(dependency); if (!index.IsInbox(dependency.ItemSpec, framework, version)) { addedDependencyToFramework = true; AddDependency(addedDependencies, new TaskItem(dependency), framework, portableDependencyGroup.Framework); } } if (!addedDependencyToFramework) { AddDependency(addedDependencies, new TaskItem("_._"), framework, portableDependencyGroup.Framework); } } } // Collapse frameworks // For any dependency with a targetframework, if there is another target framework which is compatible and older, remove this dependency. // Get all Dependencies which are not in a portable dependency group so that we can collapse the frameworks. If we include // the portable frameworks, then we'll end up collapsing to those. List <NuGetFramework> allDependencyGroups = new List <NuGetFramework>(); allDependencyGroups.AddRange(Dependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) && !FrameworkUtilities.IsGenerationMoniker(a) && !FrameworkUtilities.IsPortableMoniker(a))); allDependencyGroups.AddRange(addedDependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) && !FrameworkUtilities.IsGenerationMoniker(a) && !FrameworkUtilities.IsPortableMoniker(a))); List <NuGetFramework> collapsedDependencyGroups = FrameworkUtilities.ReduceDownwards(allDependencyGroups).ToList <NuGetFramework>(); // Get the list of dependency groups that we collapsed down so that we can add them back if they contained different dependencies than what is present in the collapsed group. /* TODO: Look into NuGet's sorting algorithm, they may have a bug (fixed in this line). They were not including version in the sort. * See ReduceCore in https://github.com/NuGet/NuGet.Client/blob/23ea68b91a439fcfd7f94bcd01bcdee2e8adae92/src/NuGet.Core/NuGet.Frameworks/FrameworkReducer.cs */ IEnumerable <NuGetFramework> removedDependencyGroups = allDependencyGroups.Where(d => !collapsedDependencyGroups.Contains(d))?.OrderBy(f => f.Framework, StringComparer.OrdinalIgnoreCase).ThenBy(f => f.Version); foreach (NuGetFramework removedDependencyGroup in removedDependencyGroups) { // always recalculate collapsedDependencyGroups in case we added an item in a previous iteration. Dependency groups are sorted, so this should be additive and we shouldn't need to restart the collapse / add back cycle var nearest = FrameworkUtilities.GetNearest(removedDependencyGroup, collapsedDependencyGroups.ToArray()); // gather the dependencies for this dependency group and the calculated "nearest" dependency group var nearestDependencies = addedDependencies.Where(d => nearest.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString()); var currentDependencies = addedDependencies.Where(d => removedDependencyGroup.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString()); // The nearest dependency group's dependencies are different than this dependency group's dependencies if (nearestDependencies.Count() != currentDependencies.Count()) { // ignore if dependency is a placeholder if (currentDependencies.Count() > 0) { if (!NuGetAssetResolver.IsPlaceholder(currentDependencies.First().ToString())) { collapsedDependencyGroups.Add(removedDependencyGroup); } } else { collapsedDependencyGroups.Add(removedDependencyGroup); } } // identical dependency count between current and nearest, and the count is > 0 else if (nearestDependencies.Count() > 0) { if (!currentDependencies.SequenceEqual(nearestDependencies, new DependencyITaskItemComparer())) { collapsedDependencyGroups.Add(removedDependencyGroup); } } } List <ITaskItem> collapsedDependencies = new List <ITaskItem>(); foreach (ITaskItem dependency in addedDependencies) { if (collapsedDependencyGroups.Contains(NuGetFramework.Parse(dependency.GetMetadata("TargetFramework")))) { collapsedDependencies.Add(dependency); } } TrimmedDependencies = collapsedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { string indexFilePath = PackageIndexFile.GetMetadata("FullPath"); PackageIndex index = File.Exists(indexFilePath) ? index = PackageIndex.Load(indexFilePath) : new PackageIndex(); if (PackageIds != null && PackageIds.Any()) { _packageIdsToInclude = new HashSet <string>(PackageIds.Select(i => i.ItemSpec), StringComparer.OrdinalIgnoreCase); } foreach (var package in Packages.NullAsEmpty().Select(f => f.GetMetadata("FullPath"))) { Log.LogMessage($"Updating from {package}."); UpdateFromPackage(index, package); } foreach (var packageFolder in PackageFolders.NullAsEmpty().Select(f => f.GetMetadata("FullPath"))) { var nupkgs = Directory.EnumerateFiles(packageFolder, "*.nupkg", SearchOption.TopDirectoryOnly); if (nupkgs.Any()) { foreach (var nupkg in nupkgs) { Log.LogMessage($"Updating from {nupkg}."); UpdateFromPackage(index, nupkg, true); } } else { var nuspecFolders = Directory.EnumerateFiles(packageFolder, "*.nuspec", SearchOption.AllDirectories) .Select(nuspec => Path.GetDirectoryName(nuspec)); foreach (var nuspecFolder in nuspecFolders) { Log.LogMessage($"Updating from {nuspecFolder}."); UpdateFromFolderLayout(index, nuspecFolder, true); } } } if (BaselinePackages != null) { foreach (var baselinePackage in BaselinePackages) { var info = GetOrCreatePackageInfo(index, baselinePackage.ItemSpec); var version = baselinePackage.GetMetadata("Version"); info.BaselineVersion = Version.Parse(version); } } if (StablePackages != null) { foreach (var stablePackage in StablePackages) { var info = GetOrCreatePackageInfo(index, stablePackage.ItemSpec); var version = stablePackage.GetMetadata("Version"); info.StableVersions.Add(Version.Parse(version)); } } if (ModuleToPackages != null) { foreach (var moduleToPackage in ModuleToPackages) { var package = moduleToPackage.GetMetadata("Package"); index.ModulesToPackages[moduleToPackage.ItemSpec] = package; } } if (!String.IsNullOrEmpty(PreRelease)) { index.PreRelease = PreRelease; } index.Save(indexFilePath); return(!Log.HasLoggedErrors); }
private void ValidateIndex() { if (SkipIndexCheck) { return; } if (PackageIndexes == null || PackageIndexes.Length == 0) { return; } var index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); PackageInfo info; if (!index.Packages.TryGetValue(PackageId, out info)) { Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an entry for package {PackageId}. Please run /t:UpdatePackageIndex on this project to commit an update."); return; } var allDlls = _report.Targets.Values.SelectMany(t => t.CompileAssets.NullAsEmpty().Concat(t.RuntimeAssets.NullAsEmpty())); var allAssemblies = allDlls.Where(f => f.Version != null); var assemblyVersions = new HashSet <Version>(allAssemblies.Select(f => VersionUtility.As4PartVersion(f.Version))); var thisPackageVersion = VersionUtility.As3PartVersion(NuGetVersion.Parse(PackageVersion).Version); foreach (var fileVersion in assemblyVersions) { Version packageVersion; // determine if we're missing a mapping for this package if (!info.AssemblyVersionInPackageVersion.TryGetValue(fileVersion, out packageVersion)) { Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an assembly version entry for {fileVersion} for package {PackageId}. Please run /t:UpdatePackageIndex on this project to commit an update."); } else { // determine if we have a mapping for an unstable package and that unstable package is not this one if (!info.StableVersions.Contains(packageVersion) && packageVersion != thisPackageVersion) { Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} indicates that assembly version {fileVersion} is contained in non-stable package version {packageVersion} which differs from this package version {thisPackageVersion}."); } } } var orphanedAssemblyVersions = info.AssemblyVersionInPackageVersion .Where(pair => pair.Value == thisPackageVersion && !assemblyVersions.Contains(pair.Key)) .Select(pair => pair.Key); if (orphanedAssemblyVersions.Any()) { Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is has an assembly version entry(s) for {String.Join(", ", orphanedAssemblyVersions)} which are no longer in package {PackageId}. Please run /t:UpdatePackageIndex on this project to commit an update."); } // if no assemblies are present in this package nor were ever present if (assemblyVersions.Count == 0 && info.AssemblyVersionInPackageVersion.Count == 0) { // if in the native module map if (index.ModulesToPackages.Values.Any(p => p.Equals(PackageId))) { // ensure the baseline is set if (info.BaselineVersion != thisPackageVersion) { Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing an baseline entry(s) for native module {PackageId}. Please run /t:UpdatePackageIndex on this project to commit an update."); } } else { // not in the native module map, see if any of the modules in this package are present // (with a different package, as would be the case for runtime-specific packages) var moduleNames = allDlls.Select(d => Path.GetFileNameWithoutExtension(d.LocalPath)); var missingModuleNames = moduleNames.Where(m => !index.ModulesToPackages.ContainsKey(m)); if (missingModuleNames.Any()) { Log.LogError($"PackageIndex from {String.Join(", ", PackageIndexes.Select(i => i.ItemSpec))} is missing ModulesToPackages entry(s) for {String.Join(", ", missingModuleNames)} to package {PackageId}. Please add a an entry for the appropriate package."); } } } }
private void LoadIndex() { _index = PackageIndex.Load(PackageIndexes.Select(pi => pi.GetMetadata("FullPath"))); }
public override bool Execute() { string indexFilePath = PackageIndexFile.GetMetadata("FullPath"); PackageIndex index = File.Exists(indexFilePath) ? index = PackageIndex.Load(indexFilePath) : new PackageIndex(); if (PackageIds != null && PackageIds.Any()) { _packageIdsToInclude = new HashSet <string>(PackageIds.Select(i => i.ItemSpec), StringComparer.OrdinalIgnoreCase); } foreach (var package in Packages.NullAsEmpty().Select(f => f.GetMetadata("FullPath"))) { Log.LogMessage($"Updating from {package}."); UpdateFromPackage(index, package); } foreach (var packageFolder in PackageFolders.NullAsEmpty().Select(f => f.GetMetadata("FullPath"))) { var nupkgs = Directory.EnumerateFiles(packageFolder, "*.nupkg", SearchOption.TopDirectoryOnly); if (nupkgs.Any()) { foreach (var nupkg in nupkgs) { Log.LogMessage($"Updating from {nupkg}."); UpdateFromPackage(index, nupkg, true); } } else { var nuspecFolders = Directory.EnumerateFiles(packageFolder, "*.nuspec", SearchOption.AllDirectories) .Select(nuspec => Path.GetDirectoryName(nuspec)); foreach (var nuspecFolder in nuspecFolders) { Log.LogMessage($"Updating from {nuspecFolder}."); UpdateFromFolderLayout(index, nuspecFolder, true); } } } if (BaselinePackages != null) { foreach (var baselinePackage in BaselinePackages) { var info = GetOrCreatePackageInfo(index, baselinePackage.ItemSpec); var version = baselinePackage.GetMetadata("Version"); info.BaselineVersion = Version.Parse(version); } } if (StablePackages != null) { foreach (var stablePackage in StablePackages) { var info = GetOrCreatePackageInfo(index, stablePackage.ItemSpec); var version = stablePackage.GetMetadata("Version"); info.StableVersions.Add(Version.Parse(version)); } } if (ModuleToPackages != null) { foreach (var moduleToPackage in ModuleToPackages) { var package = moduleToPackage.GetMetadata("Package"); index.ModulesToPackages[moduleToPackage.ItemSpec] = package; } } if (InboxFrameworkListFolder != null) { index.MergeFrameworkLists(InboxFrameworkListFolder.GetMetadata("FullPath")); } if (InboxFrameworkLayoutFolders != null) { foreach (var inboxFrameworkLayoutFolder in InboxFrameworkLayoutFolders) { var layoutDirectory = inboxFrameworkLayoutFolder.GetMetadata("FullPath"); var targetFramework = NuGetFramework.Parse(inboxFrameworkLayoutFolder.GetMetadata("TargetFramework")); index.MergeInboxFromLayout(targetFramework, layoutDirectory); } } if (SetBaselineVersionsToLatestStableVersion) { foreach (var packageInfo in index.Packages.Values) { var maxVersion = packageInfo.StableVersions.Max(); packageInfo.BaselineVersion = maxVersion; } } if (UpdateStablePackageInfo && Packages == null && PackageFolders == null) { // Given we will query the web for every package, we should run in parallel to try to optimize the performance. Parallel.ForEach(index.Packages, (package) => { IEnumerable <Version> stablePackageVersions = NuGetUtility.GetAllVersionsForPackageId(package.Key, includePrerelease: false, includeUnlisted: false, Log, CancellationToken.None); package.Value.StableVersions.Clear(); package.Value.StableVersions.AddRange(stablePackageVersions); }); } if (!String.IsNullOrEmpty(PreRelease)) { index.PreRelease = PreRelease; } index.Save(indexFilePath); return(!Log.HasLoggedErrors); }