public static LockFileLibrary GetLibrary(this LockFile lockFile, LibraryDependency libraryDependency)
 {
     // lockFile.GetLibrary is case sensitive.  So if a package is referenced in one case but another package list it as a dependency as another case it will fail to look up the library.
     // https://github.com/NuGet/Home/issues/6500
     // In the event NuGet resolved with a warning of:
     //   NUGETRESTORE : warning : NU1603: Microsoft.Aether.Logging.CentralLoggingService depends on NEST (>= 1.9.0) but NEST 1.9.0 was not found. An approximate best match of NEST 1.9.1 was resolved.
     // Then the lookup for GetLibrary will fail because LockFile.Libraries will actually contain the version resolved to where libraryDependency contains the version specified.  In this case because lockFile.Libraries will only ever contain one version we will just take that version blindly.
     return(lockFile.GetLibrary(libraryDependency.Name, libraryDependency.LibraryRange.VersionRange.MinVersion) ??
            (lockFile.Libraries.FirstOrDefault(l => l.Name.Equals(libraryDependency.Name, StringComparison.OrdinalIgnoreCase) && l.Version.Equals(libraryDependency.LibraryRange.VersionRange.MinVersion)) ??
             lockFile.Libraries.FirstOrDefault(l => l.Name.Equals(libraryDependency.Name, StringComparison.OrdinalIgnoreCase))));
 }
        internal List <InstalledPackage> GetInstalledPackages()
        {
            var installedPackages = new List <InstalledPackage>();
            var targetLibraries   = GetSupportedTargetFrameworkLibraries().ToList();

            foreach (var targetLibrary in targetLibraries)
            {
                var packageFolder = GetFolderForLibrary(targetLibrary);
                var dependencies  = targetLibrary.Dependencies.Select(x => new PackageRequest {
                    Id = x.Id, VersionsRange = x.VersionRange.OriginalString
                });
                var library      = _lockFile.GetLibrary(targetLibrary.Name, targetLibrary.Version);
                var contentFiles = library.Files.Select(x => new ContentFile {
                    PhysicalPath = Path.Combine(packageFolder, PathUtility.GetPathWithDirectorySeparator(x)), InPackagePath = PathUtility.GetPathWithDirectorySeparator(x)
                }).ToList();
                installedPackages.Add(new InstalledPackage(library.Name, library.Version.Version.ToString(), dependencies, packageFolder, contentFiles));
            }

            var sortedPackages = SortInstalledPackagesByDependencies(targetLibraries, installedPackages);

            sortedPackages.Add(GetProjectAsInstalledPackage());
            return(sortedPackages);
        }
        public static IEnumerable <LockFileLibrary> ResolveDependencies(this LockFileTargetLibrary targetLibrary, LockFile lockFile, LockFileTarget lockFileTarget)
        {
            foreach (PackageDependency dependency in targetLibrary.Dependencies)
            {
                LockFileTargetLibrary dependencyTargetLibrary = lockFileTarget.GetTargetLibrary(dependency.Id);

                yield return(lockFile.GetLibrary(dependencyTargetLibrary.Name, dependencyTargetLibrary.Version));

                foreach (LockFileLibrary lockFileLibrary in dependencyTargetLibrary.ResolveDependencies(lockFile, lockFileTarget))
                {
                    yield return(lockFileLibrary);
                }
            }
        }
        /// <summary>
        /// Creates an MSBuild properties file that specifies the full closure of packages with locked versions.
        /// </summary>
        /// <returns>A <see cref="ProjectRootElement"/> object that can be saved.</returns>
        internal bool TryCreateProject(out ProjectRootElement project)
        {
            project = null;

            if (!File.Exists(ProjectAssetsFile))
            {
                Log.LogError($"NuGet assets file '{ProjectAssetsFile}' does not exist.");
                return(false);
            }

            // should item group be conditioned or items or metadata?  Perhaps item condition should be considered and compared as well as an item could be conditioned.  Consider the below scenarios.  Since we are only parsing the assets file we need to consider the project file entries.
            // <PackageReference Include="foo" Version="1.2.3" Condition="bar"/>
            // <PackageReference Include="foo">
            //    <version>1.2.3</version>
            //    <version Condition="bar">1.2.3</version>
            // </PackageReference>
            // What about dependencies of packages that are conditioned? they should be conditioned as well.

            HashSet <string> packagesToExclude = new HashSet <string>(PackagesToExclude?.Select(i => i.ItemSpec).Distinct() ?? Enumerable.Empty <string>(), StringComparer.OrdinalIgnoreCase);

            project = ProjectRootElement.Create();

            project.ToolsVersion = String.Empty;

            ProjectPropertyElement wasImportedPropertyElement = project.AddProperty("NuGetDeterministicPropsWasImported", "true");

            LockFile lockFile = LockFileUtilities.GetLockFile(ProjectAssetsFile, NullLogger.Instance);

            bool crossTargeting = lockFile.PackageSpec.TargetFrameworks.Count > 1;

            foreach (TargetFrameworkInformation targetFramework in lockFile.PackageSpec.TargetFrameworks)
            {
                HashSet <LockFileLibrary> addedLibraries = new HashSet <LockFileLibrary>();

                ProjectItemGroupElement itemGroupElement = project.AddItemGroup();

                if (crossTargeting)
                {
                    itemGroupElement.Condition = $" '$(TargetFramework)' == '{targetFramework.FrameworkName.GetShortFolderName()}' ";
                }

                LockFileTarget target = lockFile.GetTarget(targetFramework.FrameworkName, runtimeIdentifier: null);

                bool addedImplicitReference = false;

                foreach (LibraryDependency libraryDependency in targetFramework.Dependencies.Where(i => !packagesToExclude.Contains(i.Name)))
                {
                    if (libraryDependency.AutoReferenced)
                    {
                        if (ExcludeImplicitReferences)
                        {
                            continue;
                        }
                        addedImplicitReference = true;
                    }

                    LockFileLibrary library = lockFile.GetLibrary(libraryDependency);

                    if (library.Type.Equals("project", StringComparison.OrdinalIgnoreCase))
                    {
                        // if a csproj name matches a package id then nuget swaps in the csproj output instead of the package.  Because of this we should skip adding the package as a locked package because it provides no value.
                        continue;
                    }

                    if (addedLibraries.Contains(library))
                    {
                        continue;
                    }

                    addedLibraries.Add(library);

                    LockFileTargetLibrary targetLibrary = target.GetTargetLibrary(libraryDependency.Name);

                    itemGroupElement.AddItem("PackageReference", targetLibrary.Name, GetPackageReferenceItemMetadata(library, libraryDependency));

                    foreach (LockFileLibrary dependency in targetLibrary.ResolveDependencies(lockFile, target).Where(i => !addedLibraries.Contains(i) && !packagesToExclude.Contains(i.Name)))
                    {
                        addedLibraries.Add(dependency);

                        itemGroupElement.AddItem("PackageReference", dependency.Name, GetPackageReferenceItemMetadata(dependency));
                    }
                }

                if (addedImplicitReference)
                {
                    ProjectPropertyElement disableImplicitFrameworkReferencesPropertyElement = project.AddProperty("DisableImplicitFrameworkReferences", "true");

                    if (crossTargeting)
                    {
                        disableImplicitFrameworkReferencesPropertyElement.Condition = $" '$(TargetFramework)' == '{targetFramework.FrameworkName.GetShortFolderName()}' ";
                    }
                }
            }

            ProjectImportElement beforeImportElement = project.CreateImportElement("Before.$(MSBuildThisFile)");

            project.InsertAfterChild(beforeImportElement, wasImportedPropertyElement.Parent);
            beforeImportElement.Condition = $"Exists('{beforeImportElement.Project}')";

            ProjectImportElement afterImportElement = project.AddImport("After.$(MSBuildThisFile)");

            afterImportElement.Condition = $"Exists('{afterImportElement.Project}')";

            return(true);
        }