// TODO: add HasLocalInstalledPackage() ? // ReSharper disable once CyclomaticComplexity public static IEnumerable <InstalledPackage> GetLocalInstalledPackages( string packagesConfigFile = null, bool includeDependencies = false) { packagesConfigFile = packagesConfigFile ?? GetBuildPackagesConfigFile(); ControlFlow.Assert(!IncludesDependencies(packagesConfigFile) || includeDependencies, $"!IncludesDependencies({packagesConfigFile}) || includeDependencies"); var packagesDirectory = GetPackagesDirectory(packagesConfigFile); var packageIds = XmlTasks.XmlPeek( packagesConfigFile, IsLegacyFile(packagesConfigFile) ? ".//package/@id" : ".//*[local-name() = 'PackageReference']/@Include"); var installedPackages = new HashSet <InstalledPackage>(InstalledPackage.Comparer.Instance); foreach (var packageId in packageIds) { // TODO: use xml namespaces // TODO: version as tag var version = XmlTasks.XmlPeekSingle( packagesConfigFile, IsLegacyFile(packagesConfigFile) ? $".//package[@id='{packageId}']/@version" : $".//*[local-name() = 'PackageReference'][@Include='{packageId}']/@Version") .NotNull("version != null"); var packageData = GetGlobalInstalledPackage(packageId, version, packagesDirectory); if (packageData == null) { continue; } installedPackages.Add(packageData); yield return(packageData); } if (includeDependencies) { var packagesToCheck = new Queue <InstalledPackage>(installedPackages); while (packagesToCheck.Any()) { var packageToCheck = packagesToCheck.Dequeue(); foreach (var dependentPackage in GetDependentPackages(packageToCheck, packagesDirectory)) { if (installedPackages.Contains(dependentPackage)) { continue; } installedPackages.Add(dependentPackage); packagesToCheck.Enqueue(dependentPackage); yield return(dependentPackage); } } } }
private static string GetPackagesDirectory([CanBeNull] string packagesConfigFile) { string TryGetFromEnvironmentVariable() => EnvironmentInfo.GetVariable <string>("NUGET_PACKAGES"); string TryGetGlobalDirectoryFromConfig() => GetConfigFiles(packagesConfigFile) .Select(x => new { File = x, Setting = XmlTasks.XmlPeekSingle(x, ".//add[@key='globalPackagesFolder']/@value") }) .Where(x => x.Setting != null) .Select(x => Path.IsPathRooted(x.Setting) ? x.Setting : Path.Combine(Path.GetDirectoryName(x.File).NotNull(), x.Setting)) .FirstOrDefault(); string TryGetDefaultGlobalDirectory() => packagesConfigFile == null || !IsLegacyFile(packagesConfigFile) ? Path.Combine( EnvironmentInfo.SpecialFolder(SpecialFolders.UserProfile) .NotNull("EnvironmentInfo.SpecialFolder(SpecialFolders.UserProfile) != null"), ".nuget", "packages") : null; string TryGetLocalDirectory() => packagesConfigFile != null ? new FileInfo(packagesConfigFile).Directory.NotNull() .DescendantsAndSelf(x => x.Parent) .Where(x => x.GetFiles("*.sln").Any()) .Select(x => Path.Combine(x.FullName, "packages")) .FirstOrDefault(Directory.Exists) : null; var packagesDirectory = TryGetFromEnvironmentVariable() ?? TryGetGlobalDirectoryFromConfig() ?? TryGetDefaultGlobalDirectory() ?? TryGetLocalDirectory(); return(packagesDirectory != null && Directory.Exists(packagesDirectory) ? packagesDirectory : null); }