public PackageInProject?Read( string?id, string?version, PackagePath path, IEnumerable <string>?projectReferences) { if (path == null) { return(null); } if (string.IsNullOrWhiteSpace(id)) { _logger.Normal($"Skipping package with no id specified in file '{path.FullName}'."); return(null); } if (string.IsNullOrWhiteSpace(version)) { _logger.Normal($"Skipping package '{id}' with no version specified in file '{path.FullName}'."); return(null); } var packageVersionRange = PackageVersionRange.Parse(id, version); if (packageVersionRange == null) { _logger.Normal($"Skipping package '{id}' with version '{version}' that could not be parsed in file '{path.FullName}'."); return(null); } var pip = new PackageInProject(packageVersionRange, path, projectReferences); var singleVersion = pip.Identity; if (singleVersion == null) { _logger.Normal($"Skipping package '{id}' with version range '{version}' that is not a single version in file '{path.FullName}'."); return(null); } return(pip); }
private static async Task UninstallDependencies(NugetStore store, NugetPackage package) { foreach (var dependency in package.Dependencies) { string dependencyId = dependency.Item1; string dependencyIdPrefix = dependencyId.Split('.').First(); PackageVersionRange dependencyVersionRange = dependency.Item2; // Dependency must be from Stride/Xenko and package version must match exactly if (((dependencyIdPrefix == "Stride") || (dependencyIdPrefix == "Xenko")) && (dependencyVersionRange.Contains(package.Version))) { NugetPackage dependencyPackage = store.FindLocalPackage(dependencyId, package.Version); if (dependencyPackage != null) { await store.UninstallPackage(dependencyPackage, null); await UninstallDependencies(store, dependencyPackage); } } } }
public void TwoRowsHaveOutput() { var package1 = PackageVersionRange.Parse("foo.bar", "1.2.3"); var package2 = PackageVersionRange.Parse("fish", "2.3.4"); var rows = new List <PackageUpdateSet> { PackageUpdates.UpdateSetFor(package1, PackageUpdates.MakePackageForV110(package1)), PackageUpdates.UpdateSetFor(package2, PackageUpdates.MakePackageForV110(package2)) }; var output = ReportToString(rows); Assert.That(output, Is.Not.Null); Assert.That(output, Is.Not.Empty); var lines = output.Split(Environment.NewLine); Assert.That(lines.Length, Is.EqualTo(3)); Assert.That(lines[1], Does.Contain("foo.bar,")); Assert.That(lines[2], Does.Contain("fish,")); }
public PackageInProject Read( string id, string version, PackagePath path, IEnumerable <string> projectReferences) { if (string.IsNullOrWhiteSpace(id)) { _logger.Normal($"Skipping package with no id specified in file '{path.FullName}'."); return(null); } if (string.IsNullOrWhiteSpace(version)) { // TODO this is very spammy when using MSBuild Directory.build.props or .targets files for versioning NuGets. Should find a better way for this. _logger.Detailed($"Skipping package '{id}' with no version specified in file '{path.FullName}'."); return(null); } var packageVersionRange = PackageVersionRange.Parse(id, version); if (packageVersionRange == null) { _logger.Normal($"Skipping package '{id}' with version '{version}' that could not be parsed in file '{path.FullName}'."); return(null); } var pip = new PackageInProject(packageVersionRange, path, projectReferences); var singleVersion = pip.Identity; if (singleVersion == null) { _logger.Normal($"Skipping package '{id}' with version range '{version}' that is not a single version in file '{path.FullName}'."); return(null); } return(pip); }
/// <inheritdoc/> public override bool UpgradeAfterAssetsLoaded(PackageLoadParameters loadParameters, PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, PackageVersionRange dependencyVersionBeforeUpdate) { if (dependencyVersionBeforeUpdate.MinVersion < new PackageVersion("1.3.0-alpha02")) { // Add everything as root assets (since we don't know what the project was doing in the code before) foreach (var assetItem in dependentPackage.Assets) { if (!AssetRegistry.IsAssetTypeAlwaysMarkAsRoot(assetItem.Asset.GetType())) { dependentPackage.RootAssets.Add(new AssetReference(assetItem.Id, assetItem.Location)); } } } if (dependencyVersionBeforeUpdate.MinVersion < new PackageVersion("1.6.0-beta")) { // Mark all assets dirty to force a resave foreach (var assetItem in dependentPackage.Assets) { if (!(assetItem.Asset is SourceCodeAsset)) { assetItem.IsDirty = true; } } } return(true); }
/// <summary> /// Find the installed package <paramref name="packageId"/> using the version <paramref name="versionRange"/> if not null, otherwise the <paramref name="constraintProvider"/> if specified. /// If no constraints are specified, the first found entry, whatever it means for NuGet, is used. /// </summary> /// <param name="packageId">Name of the package.</param> /// <param name="versionRange">The version range.</param> /// <param name="constraintProvider">The package constraint provider.</param> /// <param name="allowPrereleaseVersions">if set to <c>true</c> [allow prelease version].</param> /// <param name="allowUnlisted">if set to <c>true</c> [allow unlisted].</param> /// <returns>A Package matching the search criterion or null if not found.</returns> /// <exception cref="System.ArgumentNullException">packageIdentity</exception> /// <returns></returns> public NugetPackage FindLocalPackage(string packageId, PackageVersion version = null, ConstraintProvider constraintProvider = null, bool allowPrereleaseVersions = true, bool allowUnlisted = false) { var versionRange = new PackageVersionRange(version); return(FindLocalPackage(packageId, versionRange, constraintProvider, allowPrereleaseVersions, allowUnlisted)); }
private async Task PreLoadPackageDependencies(ILogger log, SolutionProject project, PackageLoadParameters loadParameters) { if (log == null) { throw new ArgumentNullException(nameof(log)); } if (project == null) { throw new ArgumentNullException(nameof(project)); } if (loadParameters == null) { throw new ArgumentNullException(nameof(loadParameters)); } bool packageDependencyErrors = false; var package = project.Package; // TODO: Remove and recheck Dependencies Ready if some secondary packages are removed? if (package.State >= PackageState.DependenciesReady) { return; } log.Verbose($"Process dependencies for {project.Name}..."); var packageReferences = new Dictionary <string, PackageVersionRange>(); // Check if there is any package upgrade to do var pendingPackageUpgrades = new List <PendingPackageUpgrade>(); pendingPackageUpgradesPerPackage.Add(package, pendingPackageUpgrades); // Load some informations about the project try { var msProject = VSProjectHelper.LoadProject(project.FullPath, loadParameters.BuildConfiguration, extraProperties: new Dictionary <string, string> { { "SkipInvalidConfigurations", "true" } }); try { var packageVersion = msProject.GetPropertyValue("PackageVersion"); if (!string.IsNullOrEmpty(packageVersion)) { package.Meta.Version = new PackageVersion(packageVersion); } project.TargetPath = msProject.GetPropertyValue("TargetPath"); package.Meta.Name = (msProject.GetProperty("PackageId") ?? msProject.GetProperty("AssemblyName"))?.EvaluatedValue ?? package.Meta.Name; var outputType = msProject.GetPropertyValue("OutputType"); project.Type = outputType.ToLowerInvariant() == "winexe" || outputType.ToLowerInvariant() == "exe" || outputType.ToLowerInvariant() == "appcontainerexe" || // UWP msProject.GetPropertyValue("AndroidApplication").ToLowerInvariant() == "true" // Android ? ProjectType.Executable : ProjectType.Library; // Note: Platform might be incorrect if Stride is not restored yet (it won't include Stride targets) // Also, if already set, don't try to query it again if (project.Type == ProjectType.Executable && project.Platform == PlatformType.Shared) { project.Platform = VSProjectHelper.GetPlatformTypeFromProject(msProject) ?? PlatformType.Shared; } foreach (var packageReference in msProject.GetItems("PackageReference").ToList()) { if (packageReference.HasMetadata("Version") && PackageVersionRange.TryParse(packageReference.GetMetadataValue("Version"), out var packageRange)) { packageReferences[packageReference.EvaluatedInclude] = packageRange; } } // Need to go recursively foreach (var projectReference in msProject.GetItems("ProjectReference").ToList()) { var projectFile = new UFile(Path.Combine(Path.GetDirectoryName(project.FullPath), projectReference.EvaluatedInclude)); if (File.Exists(projectFile)) { var referencedProject = Projects.OfType <SolutionProject>().FirstOrDefault(x => x.FullPath == new UFile(projectFile)); if (referencedProject != null) { await PreLoadPackageDependencies(log, referencedProject, loadParameters); // Get package upgrader from dependency (a project might depend on another project rather than referencing Stride directly) // A better system would be to evaluate nuget flattened dependencies WITHOUT doing the actual restore (dry-run). // However I am not sure it's easy/possible to do it (using API) without doing a full restore/download, which we don't want to do // with old version (it might be uninstalled already and we want to avoid re-downloading it again) if (pendingPackageUpgradesPerPackage.TryGetValue(referencedProject.Package, out var dependencyPackageUpgraders)) { foreach (var dependencyPackageUpgrader in dependencyPackageUpgraders) { // Make sure this upgrader is not already added if (!pendingPackageUpgrades.Any(x => x.DependencyPackage == dependencyPackageUpgrader.DependencyPackage)) { // Note: it's important to clone because once upgraded, each instance will have its Dependency.Version tested/updated pendingPackageUpgrades.Add(dependencyPackageUpgrader.Clone()); } } } } } } } finally { msProject.ProjectCollection.UnloadAllProjects(); msProject.ProjectCollection.Dispose(); } } catch (Exception ex) { log.Error($"Unexpected exception while loading project [{project.FullPath.ToWindowsPath()}]", ex); } foreach (var packageReference in packageReferences) { var dependencyName = packageReference.Key; var dependencyVersion = packageReference.Value; var packageUpgrader = AssetRegistry.GetPackageUpgrader(dependencyName); if (packageUpgrader != null) { // Check if this upgrader has already been added due to another package reference if (pendingPackageUpgrades.Any(pendingPackageUpgrade => pendingPackageUpgrade.PackageUpgrader == packageUpgrader)) { continue; } // Check if upgrade is necessary if (dependencyVersion.MinVersion >= packageUpgrader.Attribute.UpdatedVersionRange.MinVersion) { continue; } // Check if upgrade is allowed if (dependencyVersion.MinVersion < packageUpgrader.Attribute.PackageMinimumVersion) { // Throw an exception, because the package update is not allowed and can't be done throw new InvalidOperationException($"Upgrading project [{project.Name}] to use [{dependencyName}] from version [{dependencyVersion}] to [{packageUpgrader.Attribute.UpdatedVersionRange.MinVersion}] is not supported (supported only from version [{packageUpgrader.Attribute.PackageMinimumVersion}]"); } log.Info($"Upgrading project [{project.Name}] to use [{dependencyName}] from version [{dependencyVersion}] to [{packageUpgrader.Attribute.UpdatedVersionRange.MinVersion}] will be required"); pendingPackageUpgrades.Add(new PendingPackageUpgrade(packageUpgrader, new PackageDependency(dependencyName, dependencyVersion), null)); } } if (pendingPackageUpgrades.Count > 0) { var upgradeAllowed = packageUpgradeAllowed != false ? PackageUpgradeRequestedAnswer.Upgrade : PackageUpgradeRequestedAnswer.DoNotUpgrade; // Need upgrades, let's ask user confirmation if (loadParameters.PackageUpgradeRequested != null && !packageUpgradeAllowed.HasValue) { upgradeAllowed = loadParameters.PackageUpgradeRequested(package, pendingPackageUpgrades); if (upgradeAllowed == PackageUpgradeRequestedAnswer.UpgradeAll) { packageUpgradeAllowed = true; } if (upgradeAllowed == PackageUpgradeRequestedAnswer.DoNotUpgradeAny) { packageUpgradeAllowed = false; } } if (!PackageLoadParameters.ShouldUpgrade(upgradeAllowed)) { log.Error($"Necessary package migration for [{package.Meta.Name}] has not been allowed"); return; } // Perform pre assembly load upgrade foreach (var pendingPackageUpgrade in pendingPackageUpgrades) { var expectedVersion = pendingPackageUpgrade.PackageUpgrader.Attribute.UpdatedVersionRange.MinVersion.ToString(); // Update NuGet references try { var projectFile = project.FullPath; var msbuildProject = VSProjectHelper.LoadProject(projectFile.ToWindowsPath()); var isProjectDirty = false; foreach (var packageReference in msbuildProject.GetItems("PackageReference").ToList()) { if (packageReference.EvaluatedInclude == pendingPackageUpgrade.Dependency.Name && packageReference.GetMetadataValue("Version") != expectedVersion) { packageReference.SetMetadataValue("Version", expectedVersion); isProjectDirty = true; } } if (isProjectDirty) { msbuildProject.Save(); } msbuildProject.ProjectCollection.UnloadAllProjects(); msbuildProject.ProjectCollection.Dispose(); } catch (Exception e) { log.Warning($"Unable to load project [{project.FullPath.GetFileName()}]", e); } var packageUpgrader = pendingPackageUpgrade.PackageUpgrader; var dependencyPackage = pendingPackageUpgrade.DependencyPackage; if (!packageUpgrader.UpgradeBeforeAssembliesLoaded(loadParameters, package.Session, log, package, pendingPackageUpgrade.Dependency, dependencyPackage)) { log.Error($"Error while upgrading package [{package.Meta.Name}] for [{dependencyPackage.Meta.Name}] from version [{pendingPackageUpgrade.Dependency.Version}] to [{dependencyPackage.Meta.Version}]"); return; } } } // Now that our references are upgraded, let's do a real nuget restore (download files) log.Verbose($"Restore NuGet packages for {project.Name}..."); if (loadParameters.AutoCompileProjects) { await VSProjectHelper.RestoreNugetPackages(log, project.FullPath); } // If platform was unknown (due to missing nuget packages during first pass), check it again if (project.Type == ProjectType.Executable && project.Platform == PlatformType.Shared) { try { var msProject = VSProjectHelper.LoadProject(project.FullPath, extraProperties: new Dictionary <string, string> { { "SkipInvalidConfigurations", "true" } }); try { project.Platform = VSProjectHelper.GetPlatformTypeFromProject(msProject) ?? PlatformType.Shared; } finally { msProject.ProjectCollection.UnloadAllProjects(); msProject.ProjectCollection.Dispose(); } } catch (Exception ex) { log.Error($"Unexpected exception while loading project [{project.FullPath.ToWindowsPath()}]", ex); } } UpdateDependencies(project, true, true); // 1. Load store package foreach (var projectDependency in project.FlattenedDependencies) { var loadedPackage = packages.Find(projectDependency); if (loadedPackage == null) { string file = null; switch (projectDependency.Type) { case DependencyType.Project: if (Path.GetExtension(projectDependency.MSBuildProject).ToLowerInvariant() == ".csproj") { file = UPath.Combine(project.FullPath.GetFullDirectory(), (UFile)projectDependency.MSBuildProject); } break; case DependencyType.Package: file = PackageStore.Instance.GetPackageFileName(projectDependency.Name, new PackageVersionRange(projectDependency.Version), constraintProvider); break; } if (file != null && File.Exists(file)) { // Load package var loadedProject = LoadProject(log, file, loadParameters); loadedProject.Package.Meta.Name = projectDependency.Name; loadedProject.Package.Meta.Version = projectDependency.Version; Projects.Add(loadedProject); loadedPackage = loadedProject.Package; } } if (loadedPackage != null) { projectDependency.Package = loadedPackage; } } // 2. Load local packages /*foreach (var packageReference in package.LocalDependencies) * { * // Check that the package was not already loaded, otherwise return the same instance * if (Packages.ContainsById(packageReference.Id)) * { * continue; * } * * // Expand the string of the location * var newLocation = packageReference.Location; * * var subPackageFilePath = package.RootDirectory != null ? UPath.Combine(package.RootDirectory, newLocation) : newLocation; * * // Recursive load * var loadedPackage = PreLoadPackage(log, subPackageFilePath.FullPath, false, loadedPackages, loadParameters); * * if (loadedPackage == null || loadedPackage.State < PackageState.DependenciesReady) * packageDependencyErrors = true; * }*/ // 3. Update package state if (!packageDependencyErrors) { package.State = PackageState.DependenciesReady; } }
public PackageUpgraderAttribute(string packageName, string packageMinimumVersion, string packageUpdatedVersionRange) { PackageName = packageName; PackageMinimumVersion = new PackageVersion(packageMinimumVersion); PackageVersionRange.TryParse(packageUpdatedVersionRange, out this.updatedVersionRange); }
/// <summary> /// Initializes a new instance of the <see cref="PackageDependency"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="version">The version.</param> public PackageDependency(string name, PackageVersionRange version) { Name = name; Version = version; }
/// <summary> /// Add constraint <paramref name="range"/> to package ID <paramref name="packageId"/>. /// </summary> /// <param name="packageId">Package on which constraint <paramref name="range"/> will be applied.</param> /// <param name="range">Range of constraint.</param> public void AddConstraint(string packageId, PackageVersionRange range) { constraints[packageId] = range; }
/// <summary> /// Performs the second step of package migration, after assets have been loaded. /// </summary> /// <param name="session">The session.</param> /// <param name="log">The log.</param> /// <param name="dependentPackage">The source package.</param> /// <param name="dependency">The dependency.</param> /// <param name="dependencyPackage">The dependency package.</param> /// <param name="dependencyVersionBeforeUpdate">The version before the update.</param> /// <returns></returns> public virtual bool UpgradeAfterAssetsLoaded(PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, PackageVersionRange dependencyVersionBeforeUpdate) { return(true); }
/// <summary> /// Find the installed package <paramref name="packageId"/> using the version <paramref name="versionRange"/> if not null, otherwise the <paramref name="constraintProvider"/> if specified. /// If no constraints are specified, the first found entry, whatever it means for NuGet, is used. /// </summary> /// <param name="packageId">Name of the package.</param> /// <param name="versionRange">The version range.</param> /// <param name="constraintProvider">The package constraint provider.</param> /// <param name="allowPrereleaseVersions">if set to <c>true</c> [allow prelease version].</param> /// <param name="allowUnlisted">if set to <c>true</c> [allow unlisted].</param> /// <returns>A Package matching the search criterion or null if not found.</returns> /// <exception cref="System.ArgumentNullException">packageId</exception> /// <returns></returns> public NugetPackage FindLocalPackage(string packageId, PackageVersionRange versionRange = null, ConstraintProvider constraintProvider = null, bool allowPrereleaseVersions = true, bool allowUnlisted = false) { var package = manager.LocalRepository.FindPackage(packageId, versionRange?.ToVersionSpec(), constraintProvider?.Provider(), allowPrereleaseVersions, allowUnlisted); return(package != null ? new NugetPackage(package) : null); }