Exemple #1
0
    private static async Task <(LockFile, String, NuGetFramework)> RestoreAndFilterOutSDKPackages(
        this NuGetDeploymentConfiguration config,
        BoundRestoreCommandUser restorer,
        CancellationToken token,
        String restoreSDKPackageID,
        String restoreSDKPackageVersion
        )
    {
        var packageID = config.PackageID;
        var lockFile  = await restorer.RestoreIfNeeded(packageID, config.PackageVersion, token);

        // TODO better error messages
        var packagePath = restorer.ResolveFullPath(
            lockFile,
            lockFile.Libraries.FirstOrDefault(l => String.Equals(l.Name, packageID, StringComparison.OrdinalIgnoreCase))?.Path
            );
        var epAssemblyPath = NuGetUtility.GetAssemblyPathFromNuGetAssemblies(
            packageID,
            lockFile
            .Targets[0]
            .GetTargetLibrary(packageID)
            .RuntimeAssemblies
            .Select(ra => Path.GetFullPath(Path.Combine(packagePath, ra.Path)))
            .ToArray(),
            config.AssemblyPath
            );

        // We might be restoring .NETStandard package against .NETCoreApp framework, so find out the actual framework the package was built against.
        // So from path "/path/to/nuget/repo/package-id/package-version/lib/target-fw/package-id.dll" we want to extract the target-fw portion.
        // packagePath variable holds everything before the 'lib', so we just need to name of the folder 1 hierarchy level down from packagePath.
        var start            = GetNextSeparatorIndex(epAssemblyPath, packagePath.Length + 1) + 1;
        var end              = GetNextSeparatorIndex(epAssemblyPath, start);
        var packageFramework = NuGetFramework.ParseFolder(epAssemblyPath.Substring(start, end - start));

        //}
        //var targetFramework = restorer.ThisFramework;
        //sdkPackageID = NuGetUtility.GetSDKPackageID( targetFramework, config.ProcessSDKFrameworkPackageID ?? sdkPackageID );
        //sdkPackageVersion = NuGetUtility.GetSDKPackageVersion( targetFramework, sdkPackageID, config.ProcessSDKFrameworkPackageVersion ?? sdkPackageVersion );

        // Warning: The code below exploits the de facto behaviour that package named "System.XYZ" will contain assembly named "System.XYZ". Should sometime in the future this change, this code will then result in possibly wrong behaviour.
        // TODO I wonder if this assumption is needed anymore with .NET Standard and .NET Core 2+?

        var packageSDKPackageID = packageFramework.GetSDKPackageID(config.PackageSDKFrameworkPackageID);
        var sdkPackages         = new HashSet <String>(StringComparer.OrdinalIgnoreCase);

        if (!String.Equals(packageSDKPackageID, restoreSDKPackageID, StringComparison.OrdinalIgnoreCase))
        {
            // Typically when package is for .NET Standard and target framework is .NET Core
            var restoreLockFile = await restorer.RestoreIfNeeded(restoreSDKPackageID, restoreSDKPackageVersion, token);

            sdkPackages.UnionWith(restoreLockFile.Targets[0].GetAllDependencies(restoreSDKPackageID.Singleton())
                                  .SelectMany(lib => lib.Name.Singleton().Concat(lib.CompileTimeAssemblies.Select(cta => Path.GetFileNameWithoutExtension(cta.Path)).FilterUnderscores()))
                                  );
        }
        sdkPackages.UnionWith(lockFile.Targets[0].GetAllDependencies(packageSDKPackageID.Singleton()).Select(lib => lib.Name));


        var packageSDKPackageVersion = packageFramework.GetSDKPackageVersion(packageSDKPackageID, config.PackageSDKFrameworkPackageVersion);
        // In addition, check all compile assemblies from sdk package (e.g. Microsoft.NETCore.App )
        // Starting from 2.0.0, all assemblies from all dependent packages are marked as compile-assemblies stored in sdk package.
        var sdkPackageContainsAllPackagesAsAssemblies = config.PackageFrameworkIsPackageBased;

        Version.TryParse(packageSDKPackageVersion, out var sdkPkgVer);
        if (sdkPackageContainsAllPackagesAsAssemblies.IsTrue() ||
            (!sdkPackageContainsAllPackagesAsAssemblies.HasValue && packageFramework.IsPackageBased) // sdkPackageID == NuGetUtility.SDK_PACKAGE_NETCORE && sdkPkgVer != null && sdkPkgVer.Major >= 2 )
            )
        {
            var sdkPackageLibraries = lockFile.Targets[0].Libraries.Where(l => l.Name == packageSDKPackageID);

            if (sdkPkgVer != null)
            {
                sdkPackageLibraries = sdkPackageLibraries.Where(l => l.Version.Version >= sdkPkgVer);
            }

            var sdkPackageLibrary = sdkPackageLibraries.FirstOrDefault();

            if (sdkPackageLibrary == null && sdkPkgVer != null)
            {
                // We need to restore the correctly versioned SDK package
                sdkPackageLibrary = (await restorer.RestoreIfNeeded(packageSDKPackageID, packageSDKPackageVersion, token)).Targets[0].GetTargetLibrary(packageSDKPackageID);
            }

            if (sdkPackageLibrary != null)
            {
                sdkPackages.UnionWith(sdkPackageLibrary.CompileTimeAssemblies.Select(cta => Path.GetFileNameWithoutExtension(cta.Path)).FilterUnderscores());
            }
        }

        // Actually -> return LockFile, but modify it so that sdk packages are removed
        var targetLibs = lockFile.Targets[0].Libraries;

        for (var i = 0; i < targetLibs.Count;)
        {
            var curLib   = targetLibs[i];
            var contains = sdkPackages.Contains(curLib.Name);
            if (contains ||
                (
                    (curLib.RuntimeAssemblies.Count <= 0 || !curLib.RuntimeAssemblies.Select(ra => ra.Path).FilterUnderscores().Any()) &&
                    curLib.RuntimeTargets.Count <= 0 &&
                    curLib.ResourceAssemblies.Count <= 0 &&
                    curLib.NativeLibraries.Count <= 0
                )
                )
            {
                targetLibs.RemoveAt(i);
                if (!contains)
                {
                    sdkPackages.Add(curLib.Name);
                }
            }
            else
            {
                ++i;
            }
        }

        var libs = lockFile.Libraries;

        for (var i = 0; i < libs.Count;)
        {
            var curLib = libs[i];
            if (sdkPackages.Contains(curLib.Name))
            {
                libs.RemoveAt(i);
            }
            else
            {
                ++i;
            }
        }

        return(lockFile, epAssemblyPath, packageFramework);
    }