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);
        }
Ejemplo n.º 2
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        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,"));
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        /// <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);
        }
Ejemplo n.º 6
0
        /// <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));
        }
Ejemplo n.º 7
0
        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;
            }
        }
Ejemplo n.º 8
0
 public PackageUpgraderAttribute(string packageName, string packageMinimumVersion, string packageUpdatedVersionRange)
 {
     PackageName           = packageName;
     PackageMinimumVersion = new PackageVersion(packageMinimumVersion);
     PackageVersionRange.TryParse(packageUpdatedVersionRange, out this.updatedVersionRange);
 }
Ejemplo n.º 9
0
 /// <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;
 }
Ejemplo n.º 10
0
 /// <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;
 }
Ejemplo n.º 11
0
 /// <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);
 }
Ejemplo n.º 12
0
        /// <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);
        }