using System; using System.Collections.Generic; using System.Reflection; namespace NaGet.Packages.Install { /// /// 依存関係を解決したりするための便利メソッド群 /// public sealed class DependeciesResolver { private DependeciesResolver() { } /// /// 依存解決済みInstallation配列を生成する /// /// 元のインストールリスト /// インストール確認などをおこなうパッケージリストのマネージャ /// 解決済みInstallation配列 /// 依存によって必要とされたInstallation配列。ない場合は空配列 public static void ResolveInstallations(Installation[] insts, PackageListsManager pkgListsMan, out Installation[] resolved, out Installation[] dependencies) { List depInsts; // 依存関係のインストールリスト depInsts = CreateRequiresInstallations(insts, pkgListsMan); dependencies = depInsts.ToArray(); // 依存解決をしたインストールリスト depInsts.AddRange(insts); resolved = depInsts.ToArray(); } /// /// Requires依存による依存パッケージの検索をし、それを解決するためのインストールリストを返す /// /// 対象インストールリスト /// 現在インストールされているか否かの判断に使われるパッケージリスト /// Requires依存による依存 public static List CreateRequiresInstallations(Installation[] insts, PackageListsManager pkgListsMan) { List reqInsts = new List(); foreach (Entry entry in DeleteDuplicatedEntries(CreateRequiresEntries(insts))) { if (!pkgListsMan.IsInstalledFor(entry)) { if (Array.Exists(insts, delegate(Installation inst) { return inst.InstalledPackage.Name == entry.Name; })) { continue; } else { Package pkg = pkgListsMan.AvailablePkgList.GetPackageForEntry(entry); reqInsts.Add(new Installation(pkg)); } } } return reqInsts; } /// /// 与えられたエントリのイテレータに対し、重複しているものを取り除いて返す /// /// 現段階の実装では、重複の判断は名前のみである /// エントリのイテレータ /// 重複しているものを取り除いたエントリのイテレータ private static IEnumerable DeleteDuplicatedEntries(IEnumerable entries) { LinkedList pkgNames = new LinkedList(); foreach (Entry entry in entries) { if (! pkgNames.Contains(entry.Name)) { // 新出ならば返す yield return entry; pkgNames.AddFirst(entry.Name); } } } /// /// Requires依存エントリのイテレータを返す /// /// 現段階の実装では再帰的な依存は検索しない /// 対象のインストールリスト /// 依存エントリのイテレータ。重複に関して解決は行わない private static IEnumerable CreateRequiresEntries(Installation[] insts) { foreach (Installation inst in insts) { Entry[] deps = inst.InstalledPackage.Requires; if (deps == null) continue; foreach (Entry dep in deps) { yield return dep; } } } } }