Пример #1
0
        /// <summary>
        /// Create a library for a project.
        /// </summary>
        public static LockFileTargetLibrary CreateLockFileTargetProject(
            GraphItem <RemoteResolveResult> graphItem,
            LibraryIdentity library,
            LibraryIncludeFlags dependencyType,
            RestoreTargetGraph targetGraph,
            ProjectStyle rootProjectStyle)
        {
            var localMatch = (LocalMatch)graphItem.Data.Match;

            // Target framework information is optional and may not exist for csproj projects
            // that do not have a project.json file.
            string projectFramework = null;
            object frameworkInfoObject;

            if (localMatch.LocalLibrary.Items.TryGetValue(
                    KnownLibraryProperties.TargetFrameworkInformation,
                    out frameworkInfoObject))
            {
                // Retrieve the resolved framework name, if this is null it means that the
                // project is incompatible. This is marked as Unsupported.
                var targetFrameworkInformation = (TargetFrameworkInformation)frameworkInfoObject;
                projectFramework = targetFrameworkInformation.FrameworkName?.DotNetFrameworkName
                                   ?? NuGetFramework.UnsupportedFramework.DotNetFrameworkName;
            }

            // Create the target entry
            var projectLib = new LockFileTargetLibrary()
            {
                Name      = library.Name,
                Version   = library.Version,
                Type      = LibraryType.Project,
                Framework = projectFramework,

                // Find all dependencies which would be in the nuspec
                // Include dependencies with no constraints, or package/project/external
                // Exclude suppressed dependencies, the top level project is not written
                // as a target so the node depth does not matter.
                Dependencies = graphItem.Data.Dependencies
                               .Where(
                    d => (d.LibraryRange.TypeConstraintAllowsAnyOf(
                              LibraryDependencyTarget.PackageProjectExternal)) &&
                    d.SuppressParent != LibraryIncludeFlags.All)
                               .Select(d => GetDependencyVersionRange(d))
                               .ToList()
            };

            if (rootProjectStyle == ProjectStyle.PackageReference)
            {
                // Add files under asset groups
                object filesObject;
                object msbuildPath;
                if (localMatch.LocalLibrary.Items.TryGetValue(KnownLibraryProperties.MSBuildProjectPath, out msbuildPath))
                {
                    var files      = new List <ProjectRestoreMetadataFile>();
                    var fileLookup = new Dictionary <string, ProjectRestoreMetadataFile>(StringComparer.OrdinalIgnoreCase);

                    // Find the project path, this is provided by the resolver
                    var msbuildFilePathInfo = new FileInfo((string)msbuildPath);

                    // Ensure a trailing slash for the relative path helper.
                    var projectDir = PathUtility.EnsureTrailingSlash(msbuildFilePathInfo.Directory.FullName);

                    // Read files from the project if they were provided.
                    if (localMatch.LocalLibrary.Items.TryGetValue(KnownLibraryProperties.ProjectRestoreMetadataFiles, out filesObject))
                    {
                        files.AddRange((List <ProjectRestoreMetadataFile>)filesObject);
                    }

                    var targetFrameworkShortName = targetGraph.Framework.GetShortFolderName();
                    var libAnyPath = $"lib/{targetFrameworkShortName}/any.dll";

                    if (files.Count == 0)
                    {
                        // If the project did not provide a list of assets, add in default ones.
                        // These are used to detect transitive vs non-transitive project references.
                        var absolutePath = Path.Combine(projectDir, "bin", "placeholder", $"{localMatch.Library.Name}.dll");

                        files.Add(new ProjectRestoreMetadataFile(libAnyPath, absolutePath));
                    }

                    // Process and de-dupe files
                    for (var i = 0; i < files.Count; i++)
                    {
                        var path = files[i].PackagePath;

                        // LIBANY avoid compatibility checks and will always be used.
                        if (LIBANY.Equals(path, StringComparison.Ordinal))
                        {
                            path = libAnyPath;
                        }

                        if (!fileLookup.ContainsKey(path))
                        {
                            fileLookup.Add(path, files[i]);
                        }
                    }

                    var contentItems = new ContentItemCollection();
                    contentItems.Load(fileLookup.Keys);

                    // Create an ordered list of selection criteria. Each will be applied, if the result is empty
                    // fallback frameworks from "imports" will be tried.
                    // These are only used for framework/RID combinations where content model handles everything.
                    var orderedCriteria = CreateCriteria(targetGraph, targetGraph.Framework);

                    // Compile
                    // ref takes precedence over lib
                    var compileGroup = GetLockFileItems(
                        orderedCriteria,
                        contentItems,
                        targetGraph.Conventions.Patterns.CompileRefAssemblies,
                        targetGraph.Conventions.Patterns.CompileLibAssemblies);

                    projectLib.CompileTimeAssemblies.AddRange(
                        ConvertToProjectPaths(fileLookup, projectDir, compileGroup));

                    // Runtime
                    var runtimeGroup = GetLockFileItems(
                        orderedCriteria,
                        contentItems,
                        targetGraph.Conventions.Patterns.RuntimeAssemblies);

                    projectLib.RuntimeAssemblies.AddRange(
                        ConvertToProjectPaths(fileLookup, projectDir, runtimeGroup));
                }
            }

            // Add frameworkAssemblies for projects
            object frameworkAssembliesObject;

            if (localMatch.LocalLibrary.Items.TryGetValue(
                    KnownLibraryProperties.FrameworkAssemblies,
                    out frameworkAssembliesObject))
            {
                projectLib.FrameworkAssemblies.AddRange((List <string>)frameworkAssembliesObject);
            }

            // Exclude items
            ExcludeItems(projectLib, dependencyType);

            return(projectLib);
        }
        /// <summary>
        /// Convert MSBuild items to a DependencyGraphSpec.
        /// </summary>
        public static DependencyGraphSpec GetDependencySpec(IEnumerable <IMSBuildItem> items)
        {
            if (items == null)
            {
                throw new ArgumentNullException(nameof(items));
            }

            // Unique names created by the MSBuild restore target are project paths, these
            // can be different on case-insensitive file systems for the same project file.
            // To workaround this unique names should be compared based on the OS.
            var uniqueNameComparer = PathUtility.GetStringComparerBasedOnOS();

            var graphSpec         = new DependencyGraphSpec();
            var itemsById         = new Dictionary <string, List <IMSBuildItem> >(uniqueNameComparer);
            var restoreSpecs      = new HashSet <string>(uniqueNameComparer);
            var validForRestore   = new HashSet <string>(uniqueNameComparer);
            var projectPathLookup = new Dictionary <string, string>(uniqueNameComparer);
            var toolItems         = new List <IMSBuildItem>();

            // Sort items and add restore specs
            foreach (var item in items)
            {
                var projectUniqueName = item.GetProperty("ProjectUniqueName");

                if (item.IsType("restorespec"))
                {
                    restoreSpecs.Add(projectUniqueName);
                }
                else if (!string.IsNullOrEmpty(projectUniqueName))
                {
                    List <IMSBuildItem> idItems;
                    if (!itemsById.TryGetValue(projectUniqueName, out idItems))
                    {
                        idItems = new List <IMSBuildItem>(1);
                        itemsById.Add(projectUniqueName, idItems);
                    }

                    idItems.Add(item);
                }
            }

            // Add projects
            var validProjectSpecs = itemsById.Values.Select(GetPackageSpec).Where(e => e != null);

            foreach (var spec in validProjectSpecs)
            {
                // Keep track of all project path casings
                var uniqueName = spec.RestoreMetadata.ProjectUniqueName;
                if (uniqueName != null && !projectPathLookup.ContainsKey(uniqueName))
                {
                    projectPathLookup.Add(uniqueName, uniqueName);
                }

                var projectPath = spec.RestoreMetadata.ProjectPath;
                if (projectPath != null && !projectPathLookup.ContainsKey(projectPath))
                {
                    projectPathLookup.Add(projectPath, projectPath);
                }

                if (spec.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference ||
                    spec.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson ||
                    spec.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetCliTool ||
                    spec.RestoreMetadata.ProjectStyle == ProjectStyle.Standalone ||
                    spec.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetToolReference)
                {
                    validForRestore.Add(spec.RestoreMetadata.ProjectUniqueName);
                }

                graphSpec.AddProject(spec);
            }

            // Fix project reference casings to match the original project on case insensitive file systems.
            NormalizePathCasings(projectPathLookup, graphSpec);

            // Remove references to projects that could not be read by restore.
            RemoveMissingProjects(graphSpec);

            // Add valid projects to restore section
            foreach (var projectUniqueName in restoreSpecs.Intersect(validForRestore))
            {
                graphSpec.AddRestore(projectUniqueName);
            }

            return(graphSpec);
        }
        public LockFile CreateLockFile(LockFile previousLockFile,
                                       PackageSpec project,
                                       IEnumerable <RestoreTargetGraph> targetGraphs,
                                       IReadOnlyList <NuGetv3LocalRepository> localRepositories,
                                       RemoteWalkContext context,
                                       LockFileBuilderCache lockFileBuilderCache)
        {
            var lockFile = new LockFile()
            {
                Version = _lockFileVersion
            };

            var previousLibraries = previousLockFile?.Libraries.ToDictionary(l => Tuple.Create(l.Name, l.Version));

            if (project.RestoreMetadata?.ProjectStyle == ProjectStyle.PackageReference ||
                project.RestoreMetadata?.ProjectStyle == ProjectStyle.DotnetToolReference)
            {
                AddProjectFileDependenciesForPackageReference(project, lockFile, targetGraphs);
            }
            else
            {
                AddProjectFileDependenciesForSpec(project, lockFile);
            }

            // Record all libraries used
            var libraryItems = targetGraphs
                               .SelectMany(g => g.Flattened)                                   // All GraphItem<RemoteResolveResult> resolved in the graph.
                               .Distinct(GraphItemKeyComparer <RemoteResolveResult> .Instance) // Distinct list of GraphItems. Two items are equal only if the itmes' Keys are equal.
                               .OrderBy(x => x.Data.Match.Library);

            foreach (var item in libraryItems)
            {
                var library = item.Data.Match.Library;

                if (project.Name.Equals(library.Name, StringComparison.OrdinalIgnoreCase))
                {
                    // Do not include the project itself as a library.
                    continue;
                }

                if (library.Type == LibraryType.Project || library.Type == LibraryType.ExternalProject)
                {
                    // Project
                    var localMatch = (LocalMatch)item.Data.Match;

                    var projectLib = new LockFileLibrary()
                    {
                        Name    = library.Name,
                        Version = library.Version,
                        Type    = LibraryType.Project,
                    };

                    // Set the relative path if a path exists
                    // For projects without project.json this will be empty
                    if (!string.IsNullOrEmpty(localMatch.LocalLibrary.Path))
                    {
                        projectLib.Path = PathUtility.GetRelativePath(
                            project.FilePath,
                            localMatch.LocalLibrary.Path,
                            '/');
                    }

                    // The msbuild project path if it exists
                    object msbuildPath;
                    if (localMatch.LocalLibrary.Items.TryGetValue(KnownLibraryProperties.MSBuildProjectPath, out msbuildPath))
                    {
                        var msbuildRelativePath = PathUtility.GetRelativePath(
                            project.FilePath,
                            (string)msbuildPath,
                            '/');

                        projectLib.MSBuildProject = msbuildRelativePath;
                    }

                    lockFile.Libraries.Add(projectLib);
                }
                else if (library.Type == LibraryType.Package)
                {
                    // Packages
                    var packageInfo = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, library.Name, library.Version);

                    // Add the library if it was resolved, unresolved packages are not added to the assets file.
                    if (packageInfo != null)
                    {
                        var package  = packageInfo.Package;
                        var resolver = packageInfo.Repository.PathResolver;

                        var             sha512          = package.Sha512;
                        var             path            = PathUtility.GetPathWithForwardSlashes(resolver.GetPackageDirectory(package.Id, package.Version));
                        LockFileLibrary lockFileLib     = null;
                        LockFileLibrary previousLibrary = null;

                        if (previousLibraries?.TryGetValue(Tuple.Create(package.Id, package.Version), out previousLibrary) == true)
                        {
                            // Check that the previous library is still valid
                            if (previousLibrary != null &&
                                StringComparer.Ordinal.Equals(path, previousLibrary.Path) &&
                                StringComparer.Ordinal.Equals(sha512, previousLibrary.Sha512))
                            {
                                // We mutate this previous library so we must take a clone of it. This is
                                // important because later, when deciding whether the lock file has changed,
                                // we compare the new lock file to the previous (in-memory) lock file.
                                lockFileLib = previousLibrary.Clone();
                            }
                        }

                        // Create a new lock file library if one doesn't exist already.
                        if (lockFileLib == null)
                        {
                            lockFileLib = CreateLockFileLibrary(package, sha512, path);
                        }

                        // Create a new lock file library
                        lockFile.Libraries.Add(lockFileLib);
                    }
                }
            }

            Dictionary <Tuple <string, NuGetVersion>, LockFileLibrary> libraries = EnsureUniqueLockFileLibraries(lockFile);

            var librariesWithWarnings = new HashSet <LibraryIdentity>();

            var rootProjectStyle = project.RestoreMetadata?.ProjectStyle ?? ProjectStyle.Unknown;

            // Add the targets
            foreach (var targetGraph in targetGraphs
                     .OrderBy(graph => graph.Framework.ToString(), StringComparer.Ordinal)
                     .ThenBy(graph => graph.RuntimeIdentifier, StringComparer.Ordinal))
            {
                var target = new LockFileTarget
                {
                    TargetFramework   = targetGraph.Framework,
                    RuntimeIdentifier = targetGraph.RuntimeIdentifier
                };

                var flattenedFlags = IncludeFlagUtils.FlattenDependencyTypes(_includeFlagGraphs, project, targetGraph);

                // Check if warnings should be displayed for the current framework.
                var tfi = project.GetTargetFramework(targetGraph.Framework);

                bool warnForImportsOnGraph = tfi.Warn &&
                                             (target.TargetFramework is FallbackFramework ||
                                              target.TargetFramework is AssetTargetFallbackFramework);

                foreach (var graphItem in targetGraph.Flattened.OrderBy(x => x.Key))
                {
                    var library = graphItem.Key;

                    // include flags
                    LibraryIncludeFlags includeFlags;
                    if (!flattenedFlags.TryGetValue(library.Name, out includeFlags))
                    {
                        includeFlags = ~LibraryIncludeFlags.ContentFiles;
                    }

                    if (library.Type == LibraryType.Project || library.Type == LibraryType.ExternalProject)
                    {
                        if (project.Name.Equals(library.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            // Do not include the project itself as a library.
                            continue;
                        }

                        var projectLib = LockFileUtils.CreateLockFileTargetProject(
                            graphItem,
                            library,
                            includeFlags,
                            targetGraph,
                            rootProjectStyle);

                        target.Libraries.Add(projectLib);
                    }
                    else if (library.Type == LibraryType.Package)
                    {
                        var packageInfo = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, library.Name, library.Version);

                        if (packageInfo == null)
                        {
                            continue;
                        }

                        var package           = packageInfo.Package;
                        var libraryDependency = tfi.Dependencies.FirstOrDefault(e => e.Name.Equals(library.Name, StringComparison.OrdinalIgnoreCase));

                        var targetLibrary = LockFileUtils.CreateLockFileTargetLibrary(
                            libraryDependency?.Aliases,
                            libraries[Tuple.Create(library.Name, library.Version)],
                            package,
                            targetGraph,
                            dependencyType: includeFlags,
                            targetFrameworkOverride: null,
                            dependencies: graphItem.Data.Dependencies,
                            cache: lockFileBuilderCache);

                        target.Libraries.Add(targetLibrary);

                        // Log warnings if the target library used the fallback framework
                        if (warnForImportsOnGraph && !librariesWithWarnings.Contains(library))
                        {
                            var nonFallbackFramework = new NuGetFramework(target.TargetFramework);

                            var targetLibraryWithoutFallback = LockFileUtils.CreateLockFileTargetLibrary(
                                libraryDependency?.Aliases,
                                libraries[Tuple.Create(library.Name, library.Version)],
                                package,
                                targetGraph,
                                targetFrameworkOverride: nonFallbackFramework,
                                dependencyType: includeFlags,
                                dependencies: graphItem.Data.Dependencies,
                                cache: lockFileBuilderCache);

                            if (!targetLibrary.Equals(targetLibraryWithoutFallback))
                            {
                                var libraryName = DiagnosticUtility.FormatIdentity(library);

                                var message = string.Format(CultureInfo.CurrentCulture,
                                                            Strings.Log_ImportsFallbackWarning,
                                                            libraryName,
                                                            GetFallbackFrameworkString(target.TargetFramework),
                                                            nonFallbackFramework);

                                var logMessage = RestoreLogMessage.CreateWarning(
                                    NuGetLogCode.NU1701,
                                    message,
                                    library.Name,
                                    targetGraph.TargetGraphName);

                                _logger.Log(logMessage);

                                // only log the warning once per library
                                librariesWithWarnings.Add(library);
                            }
                        }
                    }
                }

                EnsureUniqueLockFileTargetLibraries(target);
                lockFile.Targets.Add(target);
            }

            PopulatePackageFolders(localRepositories.Select(repo => repo.RepositoryRoot).Distinct(), lockFile);

            AddCentralTransitiveDependencyGroupsForPackageReference(project, lockFile, targetGraphs);

            // Add the original package spec to the lock file.
            lockFile.PackageSpec = project;

            return(lockFile);
        }
        public static void Log(ILogger logger, IReadOnlyList <RestoreSummary> restoreSummaries, bool logErrors = false)
        {
            if (restoreSummaries.Count == 0)
            {
                return;
            }

            var noOpCount   = 0;
            var feedsUsed   = new HashSet <string>();
            var configFiles = new HashSet <string>();
            var installed   = new Dictionary <string, int>(restoreSummaries.Count, PathUtility.GetStringComparerBasedOnOS());

            foreach (RestoreSummary restoreSummary in restoreSummaries)
            {
                if (restoreSummary.NoOpRestore)
                {
                    noOpCount++;
                }

                foreach (var feed in restoreSummary.FeedsUsed)
                {
                    feedsUsed.Add(feed);
                }

                foreach (var configFile in restoreSummary.ConfigFiles)
                {
                    configFiles.Add(configFile);
                }

                if (!string.IsNullOrEmpty(restoreSummary.InputPath))
                {
                    if (installed.ContainsKey(restoreSummary.InputPath))
                    {
                        installed[restoreSummary.InputPath] += restoreSummary.InstallCount;
                    }
                    else
                    {
                        installed[restoreSummary.InputPath] = restoreSummary.InstallCount;
                    }
                }
            }

            // This should only be true by nuget exe since it does not have msbuild logger
            if (logErrors)
            {
                // Display the errors summary
                foreach (var restoreSummary in restoreSummaries)
                {
                    // log errors
                    LogErrorsToConsole(
                        restoreSummary,
                        string.Format(CultureInfo.CurrentCulture, Strings.Log_ErrorSummary, restoreSummary.InputPath),
                        logger);
                }
            }

            // Display the information summary
            if (configFiles.Any())
            {
                logger.LogInformationSummary(string.Empty);
                logger.LogInformationSummary(Strings.Log_ConfigFileSummary);
                foreach (var configFile in configFiles)
                {
                    logger.LogInformationSummary($"    {configFile}");
                }
            }

            if (feedsUsed.Any())
            {
                logger.LogInformationSummary(string.Empty);
                logger.LogInformationSummary(Strings.Log_FeedsUsedSummary);
                foreach (var feedUsed in feedsUsed)
                {
                    logger.LogInformationSummary($"    {feedUsed}");
                }
            }

            if (installed.Any(i => i.Value > 0))
            {
                logger.LogInformationSummary(string.Empty);
                logger.LogInformationSummary(Strings.Log_InstalledSummary);
                foreach (var pair in installed.Where(i => i.Value > 0))
                {
                    logger.LogInformationSummary("    " + string.Format(
                                                     CultureInfo.CurrentCulture,
                                                     Strings.Log_InstalledSummaryCount,
                                                     pair.Value,
                                                     pair.Key));
                }
            }

            if (!RuntimeEnvironmentHelper.IsRunningInVisualStudio)
            {
                if (noOpCount == restoreSummaries.Count)
                {
                    logger.LogMinimal(Strings.Log_AllProjectsUpToDate);
                }
                else if (noOpCount > 0)
                {
                    logger.LogMinimal(string.Format(CultureInfo.CurrentCulture, Strings.Log_ProjectUpToDateSummary, noOpCount, restoreSummaries.Count));
                }
            }
        }
        public LockFile CreateLockFile(
            LockFile previousLockFile,
            PackageSpec project,
            IEnumerable <RestoreTargetGraph> targetGraphs,
            IReadOnlyList <NuGetv3LocalRepository> localRepositories,
            RemoteWalkContext context)
        {
            var lockFile = new LockFile();

            lockFile.Version = _lockFileVersion;

            var previousLibraries = previousLockFile?.Libraries.ToDictionary(l => Tuple.Create(l.Name, l.Version));

            if (project.RestoreMetadata?.ProjectStyle == ProjectStyle.PackageReference)
            {
                AddProjectFileDependenciesForNETCore(project, lockFile, targetGraphs);
            }
            else
            {
                AddProjectFileDependenciesForSpec(project, lockFile);
            }

            // Record all libraries used
            foreach (var item in targetGraphs.SelectMany(g => g.Flattened).Distinct()
                     .OrderBy(x => x.Data.Match.Library))
            {
                var library = item.Data.Match.Library;

                if (project.Name.Equals(library.Name, StringComparison.OrdinalIgnoreCase))
                {
                    // Do not include the project itself as a library.
                    continue;
                }

                if (library.Type == LibraryType.Project || library.Type == LibraryType.ExternalProject)
                {
                    // Project
                    LocalMatch localMatch = (LocalMatch)item.Data.Match;

                    var projectLib = new LockFileLibrary()
                    {
                        Name    = library.Name,
                        Version = library.Version,
                        Type    = LibraryType.Project,
                    };

                    // Set the relative path if a path exists
                    // For projects without project.json this will be empty
                    if (!string.IsNullOrEmpty(localMatch.LocalLibrary.Path))
                    {
                        projectLib.Path = PathUtility.GetRelativePath(
                            project.FilePath,
                            localMatch.LocalLibrary.Path,
                            '/');
                    }

                    // The msbuild project path if it exists
                    object msbuildPath;
                    if (localMatch.LocalLibrary.Items.TryGetValue(KnownLibraryProperties.MSBuildProjectPath, out msbuildPath))
                    {
                        var msbuildRelativePath = PathUtility.GetRelativePath(
                            project.FilePath,
                            (string)msbuildPath,
                            '/');

                        projectLib.MSBuildProject = msbuildRelativePath;
                    }

                    lockFile.Libraries.Add(projectLib);
                }
                else if (library.Type == LibraryType.Package)
                {
                    // Packages
                    var packageInfo = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, library.Name, library.Version);

                    if (packageInfo == null)
                    {
                        continue;
                    }

                    var package  = packageInfo.Package;
                    var resolver = packageInfo.Repository.PathResolver;

                    LockFileLibrary previousLibrary = null;
                    if (previousLibraries?.TryGetValue(Tuple.Create(package.Id, package.Version), out previousLibrary) == true)
                    {
                        // We mutate this previous library so we must take a clone of it. This is
                        // important because later, when deciding whether the lock file has changed,
                        // we compare the new lock file to the previous (in-memory) lock file.
                        previousLibrary = previousLibrary.Clone();
                    }

                    var sha512 = File.ReadAllText(resolver.GetHashPath(package.Id, package.Version));
                    var path   = PathUtility.GetPathWithForwardSlashes(
                        resolver.GetPackageDirectory(package.Id, package.Version));

                    var lockFileLib = previousLibrary;

                    // If we have the same library in the lock file already, use that.
                    if (previousLibrary == null ||
                        previousLibrary.Sha512 != sha512 ||
                        previousLibrary.Path != path)
                    {
                        lockFileLib = CreateLockFileLibrary(
                            package,
                            sha512,
                            path);
                    }
                    else if (Path.DirectorySeparatorChar != LockFile.DirectorySeparatorChar)
                    {
                        // Fix slashes for content model patterns
                        lockFileLib.Files = lockFileLib.Files
                                            .Select(p => p.Replace(Path.DirectorySeparatorChar, LockFile.DirectorySeparatorChar))
                                            .ToList();
                    }

                    lockFile.Libraries.Add(lockFileLib);

                    var packageIdentity = new PackageIdentity(lockFileLib.Name, lockFileLib.Version);
                    context.PackageFileCache.TryAdd(packageIdentity, lockFileLib.Files);
                }
            }

            var libraries = lockFile.Libraries.ToDictionary(lib => Tuple.Create(lib.Name, lib.Version));

            var warnForImports        = project.TargetFrameworks.Any(framework => framework.Warn);
            var librariesWithWarnings = new HashSet <LibraryIdentity>();

            var rootProjectStyle = project.RestoreMetadata?.ProjectStyle ?? ProjectStyle.Unknown;

            // Add the targets
            foreach (var targetGraph in targetGraphs
                     .OrderBy(graph => graph.Framework.ToString(), StringComparer.Ordinal)
                     .ThenBy(graph => graph.RuntimeIdentifier, StringComparer.Ordinal))
            {
                var target = new LockFileTarget();
                target.TargetFramework   = targetGraph.Framework;
                target.RuntimeIdentifier = targetGraph.RuntimeIdentifier;

                var flattenedFlags = IncludeFlagUtils.FlattenDependencyTypes(_includeFlagGraphs, project, targetGraph);

                var fallbackFramework     = target.TargetFramework as FallbackFramework;
                var warnForImportsOnGraph = warnForImports && fallbackFramework != null;

                foreach (var graphItem in targetGraph.Flattened.OrderBy(x => x.Key))
                {
                    var library = graphItem.Key;

                    // include flags
                    LibraryIncludeFlags includeFlags;
                    if (!flattenedFlags.TryGetValue(library.Name, out includeFlags))
                    {
                        includeFlags = ~LibraryIncludeFlags.ContentFiles;
                    }

                    if (library.Type == LibraryType.Project || library.Type == LibraryType.ExternalProject)
                    {
                        if (project.Name.Equals(library.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            // Do not include the project itself as a library.
                            continue;
                        }

                        var projectLib = LockFileUtils.CreateLockFileTargetProject(
                            graphItem,
                            library,
                            includeFlags,
                            targetGraph,
                            rootProjectStyle);

                        target.Libraries.Add(projectLib);
                        continue;
                    }
                    else if (library.Type == LibraryType.Package)
                    {
                        var packageInfo = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, library.Name, library.Version);

                        if (packageInfo == null)
                        {
                            continue;
                        }

                        var package = packageInfo.Package;

                        var targetLibrary = LockFileUtils.CreateLockFileTargetLibrary(
                            libraries[Tuple.Create(library.Name, library.Version)],
                            package,
                            targetGraph,
                            dependencyType: includeFlags,
                            targetFrameworkOverride: null,
                            dependencies: graphItem.Data.Dependencies);

                        target.Libraries.Add(targetLibrary);

                        // Log warnings if the target library used the fallback framework
                        if (warnForImportsOnGraph && !librariesWithWarnings.Contains(library))
                        {
                            var nonFallbackFramework = new NuGetFramework(fallbackFramework);

                            var targetLibraryWithoutFallback = LockFileUtils.CreateLockFileTargetLibrary(
                                libraries[Tuple.Create(library.Name, library.Version)],
                                package,
                                targetGraph,
                                targetFrameworkOverride: nonFallbackFramework,
                                dependencyType: includeFlags,
                                dependencies: graphItem.Data.Dependencies);

                            if (!targetLibrary.Equals(targetLibraryWithoutFallback))
                            {
                                var libraryName = $"{library.Name} {library.Version}";
                                _logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Strings.Log_ImportsFallbackWarning, libraryName, String.Join(", ", fallbackFramework.Fallback), nonFallbackFramework));

                                // only log the warning once per library
                                librariesWithWarnings.Add(library);
                            }
                        }
                    }
                }

                lockFile.Targets.Add(target);
            }

            PopulatePackageFolders(localRepositories.Select(repo => repo.RepositoryRoot).Distinct(), lockFile);

            // Add the original package spec to the lock file.
            lockFile.PackageSpec = project;

            return(lockFile);
        }
Пример #6
0
        public PackagesLockFile CreateNuGetLockFile(LockFile assetsFile)
        {
            var lockFile = new PackagesLockFile();

            var libraryLookup = assetsFile.Libraries.Where(e => e.Type == LibraryType.Package)
                                .ToDictionary(e => new PackageIdentity(e.Name, e.Version));

            foreach (var target in assetsFile.Targets)
            {
                var nuGettarget = new PackagesLockFileTarget()
                {
                    TargetFramework   = target.TargetFramework,
                    RuntimeIdentifier = target.RuntimeIdentifier
                };

                var framework = assetsFile.PackageSpec.TargetFrameworks.FirstOrDefault(
                    f => EqualityUtility.EqualsWithNullCheck(f.FrameworkName, target.TargetFramework));

                var libraries = target.Libraries;

                // check if this is RID-based graph then only add those libraries which differ from original TFM.
                if (!string.IsNullOrEmpty(target.RuntimeIdentifier))
                {
                    var onlyTFM = assetsFile.Targets.First(t => EqualityUtility.EqualsWithNullCheck(t.TargetFramework, target.TargetFramework));

                    libraries = target.Libraries.Where(lib => !onlyTFM.Libraries.Any(tfmLib => tfmLib.Equals(lib))).ToList();
                }

                foreach (var library in libraries.Where(e => e.Type == LibraryType.Package))
                {
                    var identity = new PackageIdentity(library.Name, library.Version);

                    var dependency = new LockFileDependency()
                    {
                        Id = library.Name,
                        ResolvedVersion = library.Version,
                        ContentHash     = libraryLookup[identity].Sha512,
                        Dependencies    = library.Dependencies
                    };

                    var framework_dep = framework?.Dependencies.FirstOrDefault(
                        dep => StringComparer.OrdinalIgnoreCase.Equals(dep.Name, library.Name));

                    if (framework_dep != null)
                    {
                        dependency.Type             = PackageDependencyType.Direct;
                        dependency.RequestedVersion = framework_dep.LibraryRange.VersionRange;
                    }
                    else
                    {
                        dependency.Type = PackageDependencyType.Transitive;
                    }

                    nuGettarget.Dependencies.Add(dependency);
                }

                var projectFullPaths = assetsFile.Libraries
                                       .Where(l => l.Type == LibraryType.Project || l.Type == LibraryType.ExternalProject)
                                       .ToDictionary(l => new PackageIdentity(l.Name, l.Version), l => l.MSBuildProject);

                foreach (var projectReference in libraries.Where(e => e.Type == LibraryType.Project || e.Type == LibraryType.ExternalProject))
                {
                    var projectIdentity = new PackageIdentity(projectReference.Name, projectReference.Version);
                    var projectFullPath = projectFullPaths[projectIdentity];
                    var id = PathUtility.GetStringComparerBasedOnOS().Equals(Path.GetFileNameWithoutExtension(projectFullPath), projectReference.Name)
                        ? projectReference.Name.ToLowerInvariant()
                        : projectReference.Name;

                    var dependency = new LockFileDependency()
                    {
                        Id           = id,
                        Dependencies = projectReference.Dependencies,
                        Type         = PackageDependencyType.Project
                    };

                    nuGettarget.Dependencies.Add(dependency);
                }

                nuGettarget.Dependencies = nuGettarget.Dependencies.OrderBy(d => d.Type).ToList();

                lockFile.Targets.Add(nuGettarget);
            }

            return(lockFile);
        }