コード例 #1
0
        public void FrameworkReducer_ReduceToHighest()
        {
            // both frameworks are equivalent
            var fw1 = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.Windows, FrameworkConstants.EmptyVersion);
            var fw2 = FrameworkConstants.CommonFrameworks.Win8;

            var packageFrameworks = new List <NuGetFramework>()
            {
                fw1,
                fw2
            };

            FrameworkReducer reducer = new FrameworkReducer();

            // the non-zero version should win in both cases
            var upwards   = reducer.ReduceUpwards(packageFrameworks).Single();
            var downwards = reducer.ReduceUpwards(packageFrameworks).Single();

            Assert.Equal(fw2, upwards);
            Assert.Equal(fw2, downwards);
        }
コード例 #2
0
        public void FrameworkReducer_ReduceUpPCL()
        {
            FrameworkReducer reducer = new FrameworkReducer();

            var framework1 = NuGetFramework.Parse("portable-net45+win8");
            var framework2 = NuGetFramework.Parse("portable-net451+win81");

            var all = new NuGetFramework[] { framework1, framework2 };

            var result = reducer.ReduceUpwards(all);

            Assert.Equal(framework2, result.Single());
        }
コード例 #3
0
        public void FrameworkReducer_ReduceUpEqual()
        {
            FrameworkReducer reducer = new FrameworkReducer();

            var framework1 = NuGetFramework.Parse("net40");
            var framework2 = NuGetFramework.Parse("net40");

            var all = new NuGetFramework[] { framework1, framework2 };

            var result = reducer.ReduceUpwards(all);

            Assert.Equal(framework2, result.Single());
        }
コード例 #4
0
        public void FrameworkReducer_ReduceUpEquivalent()
        {
            FrameworkReducer reducer = new FrameworkReducer();

            var framework1 = NuGetFramework.Parse("net40");
            var framework2 = NuGetFramework.Parse("net40-client");

            var all = new NuGetFramework[] { framework1, framework2 };

            var result = reducer.ReduceUpwards(all).ToArray();

            Assert.Equal(2, result.Length);
            Assert.Equal(framework1, result.First());
            Assert.Equal(framework2, result.Last());
        }
コード例 #5
0
        public void FrameworkReducer_ReduceUpwardsBasic()
        {
            FrameworkReducer reducer = new FrameworkReducer();

            var net35  = NuGetFramework.Parse("net35");
            var net40  = NuGetFramework.Parse("net40");
            var net45  = NuGetFramework.Parse("net45");
            var net451 = NuGetFramework.Parse("net451");
            var net453 = NuGetFramework.Parse("net453");

            var all = new NuGetFramework[] { net35, net40, net45, net451, net453 };

            var result = reducer.ReduceUpwards(all);

            Assert.Equal(net453, result.Single());
        }
コード例 #6
0
        public void FrameworkReducer_ReduceUpwardsNonSingle()
        {
            FrameworkReducer reducer = new FrameworkReducer();

            var net35  = NuGetFramework.Parse("net35");
            var net40  = NuGetFramework.Parse("net40");
            var net45  = NuGetFramework.Parse("net45");
            var net451 = NuGetFramework.Parse("net451");
            var net453 = NuGetFramework.Parse("net453");
            var wp8    = NuGetFramework.Parse("wp8");
            var wp81   = NuGetFramework.Parse("wp81");

            var all = new NuGetFramework[] { net35, net40, net45, net451, net453, wp8, wp81 };

            var result = reducer.ReduceUpwards(all);

            Assert.Equal(net453, result.First());
            Assert.Equal(wp81, result.Skip(1).First());
        }
コード例 #7
0
        public static void Generate(string outDir, Nuspec spec)
        {
            if (Directory.Exists(outDir))
            {
                Directory.Delete(outDir, true);
            }
            Directory.CreateDirectory(outDir);

            /*
             * This approach creates a lib/<framework> as necessary, depending on the target framework of each assembly.
             * An issue will arise when referencing such nuget package via SlnX, because as per today there only one
             * targetFramework can be selected on each <package ... /> element.
             * Another potential issue is caused by NuGet.exe (see https://docs.microsoft.com/en-us/nuget/reference/nuspec#dependencies-element).
             * For each lib/<framework> there should be a
             *  <group targetFramework="<framework>"> in the <dependencies> element.
             * This code creates such a structure, but due to the nature of the Slnx nuget packages handling
             * it cannot know weather a file (DLL) in a specific framwork does reference one of the listed packages.
             * It fact, it is well possible that this code would generate invalid dependencies.
             * e.g.
             *   <group targetFramework="net45"> ---> Caused by a project present in the SlnX (no reference to NUinit here)
             *      <dependency id = "NUnit" version="3.13.1" /> ---> Caused by another project in the SlnX
             *   <group>
             * For this reason, the code will now check for the "highest" compatible framwork, and create the package for that one only
             *
             * var dependencies = new StringBuilder();
             * foreach (var frameworkItems in spec.Files)
             * {
             *  var frameworkDir = Path.Combine(outDir, "lib", frameworkItems.Key);
             *  Directory.CreateDirectory(frameworkDir);
             *  foreach(var f in frameworkItems.Value)
             *  {
             *      File.Copy(f, Path.Combine(frameworkDir, Path.GetFileName(f)), true);
             *  }
             *
             *  if (string.IsNullOrEmpty(frameworkItems.Key))
             *  {
             *      dependencies.Append(_dependencyGroupOpening);
             *  }
             *  else
             *  {
             *      dependencies.AppendFormat(_dependencyGroupFrameworkTemplate, frameworkItems.Key);
             *  }
             *  dependencies.AppendLine();
             *  foreach (var d in spec.Dependecies)
             *  {
             *      dependencies.AppendFormat(string.Format(_dependencyTemplate, d.Id, d.Version));
             *      dependencies.AppendLine();
             *  }
             *  dependencies.Append(_dependencyGroupClosing);
             *  dependencies.AppendLine();
             * }
             */

            var frameworkReducer = new FrameworkReducer();
            var highestFramework = frameworkReducer.ReduceUpwards(spec.Elements.Select(x => NuGetFramework.Parse(x.Key))).ToList();

            if (highestFramework.Count != 1)
            {
                var required = string.Join(Environment.NewLine, highestFramework);
                throw new Exception($"For the required package {spec.Id} multiple .NET frameworks would be necessary. This is probably caused by a mixture of '.NET Framework' and '.NET Core' based projects.\nThis is not supported.\nRequired frameworks: {required}");
            }
            var highestFrameworkName = highestFramework.Single().GetShortFolderName();

            var packageVersion = spec.Version;

            if (packageVersion == null)
            {
                if (!spec.Elements.ContainsKey(highestFrameworkName))
                {
                    throw new Exception($"The .NET version of the required package {spec.Id} has been resolved to {highestFrameworkName}. No file has been found under that framework.");
                }
                var assemblies = spec.Elements[highestFrameworkName].Where(x => File.Exists(x) && (x.ToLower().EndsWith(".dll") || x.ToLower().EndsWith(".exe")));
                if (assemblies.Count() == 0)
                {
                    throw new Exception("Error while loading the nuget information. No DLL found from which automatically retrieve the version information.");
                }

                var assemblyPath = assemblies.First();
                if (File.Exists(assemblyPath))
                {
                    var assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
                    packageVersion = assemblyName.Version.ToString(3);
                }
                else
                {
                    throw new Exception(string.Format("Unable to automatically retrieve the package version. Assembly {0} not found", assemblyPath));
                }
            }

            foreach (var frameworkItems in spec.Elements)
            {
                var frameworkDir = Path.Combine(outDir, "lib", highestFrameworkName);
                Directory.CreateDirectory(frameworkDir);
                foreach (var f in frameworkItems.Value)
                {
                    FileAttributes attr = File.GetAttributes(f);
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                    {
                        CopyDirectory(f, Path.Combine(frameworkDir, Path.GetFileName(f)));
                    }
                    else
                    {
                        File.Copy(f, Path.Combine(frameworkDir, Path.GetFileName(f)), true);
                    }
                }
            }
            var dependencies = new StringBuilder();

            if (string.IsNullOrEmpty(highestFrameworkName))
            {
                dependencies.Append(_dependencyGroupOpening);
            }
            else
            {
                dependencies.AppendFormat(_dependencyGroupFrameworkTemplate, highestFrameworkName);
            }
            dependencies.AppendLine();
            foreach (var d in spec.Dependecies)
            {
                dependencies.AppendFormat(string.Format(_dependencyTemplate, d.Id, d.VersionRange.OriginalString));
                dependencies.AppendLine();
            }
            dependencies.Append(_dependencyGroupClosing);
            dependencies.AppendLine();


            string customElements = null;

            if (spec.AdditionalElements != null)
            {
                var lines = spec.AdditionalElements.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                customElements = string.Join($"{Environment.NewLine}    ", lines);
            }
            var content = string.Format(_nuspecTemplate, spec.Id, packageVersion, customElements, dependencies);

            Utilities.WriteAllText(Path.Combine(outDir, spec.FileName), content);
        }
コード例 #8
0
        public async Task UninstallAsync(PackageIdentity package, IExtensibleProject project, IEnumerable <PackageReference> installedPackageReferences,
                                         CancellationToken cancellationToken = default)
        {
            List <string> failedEntries = null;
            ICollection <PackageIdentity> uninstalledPackages;

            var targetFramework = FrameworkParser.TryParseFrameworkName(project.Framework, _frameworkNameProvider);

#if NET5_0_OR_GREATER
            var reducer      = new FrameworkReducer();
            var mostSpecific = reducer.ReduceUpwards(project.SupportedPlatforms).FirstOrDefault();
            targetFramework = mostSpecific;
#endif

            var projectConfig         = _nuGetProjectConfigurationProvider.GetProjectConfig(project);
            var uninstallationContext = new UninstallationContext(false, false);

            _nugetLogger.LogInformation($"Uninstall package {package}, Target framework: {targetFramework}");

            if (projectConfig is null)
            {
                _nugetLogger.LogWarning($"Project {project.Name} doesn't implement any configuration for own packages");
            }

            using (var cacheContext = new SourceCacheContext()
            {
                NoCache = false,
                DirectDownload = false,
            })
            {
                var dependencyInfoResource = await project.AsSourceRepository(_sourceRepositoryProvider)
                                             .GetResourceAsync <DependencyInfoResource>(cancellationToken);

                var dependencyInfoResourceCollection = new DependencyInfoResourceCollection(dependencyInfoResource);

                var resolverContext = await ResolveDependenciesAsync(package, targetFramework, PackageIdentity.Comparer, dependencyInfoResourceCollection, cacheContext, project, true, cancellationToken);

                var packageReferences = installedPackageReferences.ToList();

                if (uninstallationContext.RemoveDependencies)
                {
                    uninstalledPackages = await GetPackagesCanBeUninstalledAsync(resolverContext.AvailablePackages, packageReferences.Select(x => x.PackageIdentity));
                }
                else
                {
                    uninstalledPackages = new List <PackageIdentity>()
                    {
                        package
                    };
                }
            }

            try
            {
                foreach (var removedPackage in uninstalledPackages)
                {
                    if (removedPackage.Version is null)
                    {
                        _nugetLogger.LogWarning($"Skip package {removedPackage.Id} uninstall. Check your package.config for references of this packages");
                        continue;
                    }

                    var folderProject = new FolderNuGetProject(project.ContentPath);

                    if (folderProject.PackageExists(removedPackage))
                    {
                        _directoryService.ForceDeleteDirectory(_fileService, folderProject.GetInstalledPath(removedPackage), out failedEntries);
                    }

                    if (projectConfig is null)
                    {
                        continue;
                    }

                    var result = await projectConfig.UninstallPackageAsync(removedPackage, _nuGetProjectContextProvider.GetProjectContext(FileConflictAction.PromptUser), cancellationToken);

                    if (!result)
                    {
                        _nugetLogger.LogError($"Saving package configuration failed in project {project} when installing package {package}");
                    }
                }
            }
            catch (IOException ex)
            {
                Log.Error(ex);
                _nugetLogger.LogError("Package files cannot be complete deleted by unexpected error (may be directory in use by another process?");
            }
            finally
            {
                LogHelper.LogUnclearedPaths(failedEntries, Log);
            }
        }
コード例 #9
0
        public async Task <InstallerResult> InstallAsync(
            PackageIdentity package,
            IExtensibleProject project,
            IReadOnlyList <SourceRepository> repositories,
            bool ignoreMissingPackages          = false,
            CancellationToken cancellationToken = default)
        {
            try
            {
                // Step 1. Decide what framework version used on package resolving
                // Enforce platform-specific framework for .NET 5.0

                var targetFramework = FrameworkParser.TryParseFrameworkName(project.Framework, _frameworkNameProvider);
                var reducer         = new FrameworkReducer();

#if NET5_0_OR_GREATER
                var mostSpecific = reducer.ReduceUpwards(project.SupportedPlatforms).FirstOrDefault();
                targetFramework = mostSpecific;
#endif

                _nugetLogger.LogInformation($"Installing package {package}, Target framework: {targetFramework}");

                // Prepare to step 2. Add globals if cache enabled as available repository with highest priority.
                // Note: This part falls under responsibility of RepositoryContextService but the same logic used to determine what packages are found by IPackageLoaderService
                // To not break behavior for now add here
                if (!project.NoCache)
                {
                    var repositoryList = repositories.ToList();
                    repositoryList.Insert(0, new SourceRepository(new PackageSource(DefaultNuGetFolders.GetGlobalPackagesFolder(), ".nuget"), Repository.Provider.GetCoreV3()));
                    repositories = repositoryList;
                }

                // Step 2. Build list of dependencies and determine DependencyBehavior if some packages are misssed in current feed
                Resolver.PackageResolverContext resolverContext = null;

                using (var cacheContext = new SourceCacheContext())
                {
#pragma warning disable IDISP013 // Await in using.
                    var getDependencyResourcesTasks = repositories.Select(repo => repo.GetResourceAsync <DependencyInfoResource>());
#pragma warning restore IDISP013 // Await in using.

                    var dependencyResources = (await getDependencyResourcesTasks.WhenAllOrExceptionAsync()).Where(x => x.IsSuccess && x.Result is not null)
                                              .Select(x => x.Result).ToArray();

                    var dependencyInfoResources = new DependencyInfoResourceCollection(dependencyResources);

                    resolverContext = await ResolveDependenciesAsync(package, targetFramework, PackageIdentityComparer.Default, dependencyInfoResources, cacheContext, project, ignoreMissingPackages, cancellationToken);

                    if (resolverContext is null ||
                        !(resolverContext?.AvailablePackages?.Any() ?? false))
                    {
                        var errorMessage = $"Package {package} cannot be resolved with current settings (TFM: {targetFramework}) for chosen destination";
                        _nugetLogger.LogWarning(errorMessage);
                        return(new InstallerResult(errorMessage));
                    }

                    // Step 3. Try to check is main package can be downloaded from resource
                    var mainPackageInfo = resolverContext.AvailablePackages.FirstOrDefault(p => p.Id == package.Id);

                    _nugetLogger.LogInformation($"Downloading {package}...");
                    var mainDownloadedFiles = await DownloadPackageResourceAsync(mainPackageInfo, cacheContext, cancellationToken);

                    _nugetLogger.LogInformation($"{package} download completed");

                    if (!mainDownloadedFiles.IsAvailable())
                    {
                        // Downlod failed by some reasons (probably connection issue or package goes deleted before feed updated)
                        var errorMessage = $"Current source lists package {package} but attempts to download it have failed. The source in invalid or required packages were removed while the current operation was in progress";
                        _nugetLogger.LogError(errorMessage);
                        return(new InstallerResult(errorMessage));
                    }

                    // Step 4. Check is main package compatible with target Framework
                    var canBeInstalled = await CheckCanBeInstalledAsync(project, mainDownloadedFiles.PackageReader, targetFramework, cancellationToken);

                    if (!canBeInstalled)
                    {
                        throw new IncompatiblePackageException($"Package {package} incompatible with project target platform {targetFramework}");
                    }

                    // Step 5. Build install list using NuGet Resolver and select available resources.
                    // Track packages which already installed and make sure only one version of package exists
                    var resolver = new Resolver.PackageResolver();
                    var availablePackagesToInstall = await resolver.ResolveWithVersionOverrideAsync(resolverContext, project, DependencyBehavior.Highest,
                                                                                                    (project, conflict) => _fileSystemService.CreateDeleteme(conflict.PackageIdentity.Id, project.GetInstallPath(conflict.PackageIdentity)),
                                                                                                    cancellationToken);

                    // Step 6. Download everything except main package and extract all
                    availablePackagesToInstall.Remove(mainPackageInfo);
                    _nugetLogger.LogInformation($"Downloading package dependencies...");
                    var downloadResults = await DownloadPackagesResourcesAsync(availablePackagesToInstall, cacheContext, cancellationToken);

                    downloadResults[mainPackageInfo] = mainDownloadedFiles;
                    _nugetLogger.LogInformation($"{downloadResults.Count - 1} dependencies downloaded");
                    var extractionContext = GetExtractionContext();
                    await ExtractPackagesResourcesAsync(downloadResults, project, extractionContext, cancellationToken);
                    await CheckLibAndFrameworkItemsAsync(downloadResults, targetFramework, cancellationToken);

                    return(new InstallerResult(downloadResults));
                }
            }
            catch (NuGetResolverInputException ex)
            {
                throw new IncompatiblePackageException($"Package {package} or some of it dependencies are missed for current target framework", ex);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                throw;
            }
        }
コード例 #10
0
 public IEnumerable <NuGetFramework> GetHighest()
 {
     return(_frameworkReducer.ReduceUpwards(_nuGetFrameworks));
 }