2 using System.Collections.Generic;
\r
3 using System.Reflection;
\r
5 namespace NaGet.Packages.Install
\r
8 /// 依存関係を解決したりするための便利メソッド群
\r
10 public sealed class DependeciesResolver
\r
12 private DependeciesResolver()
\r
17 /// 依存解決済みInstallation配列を生成する
\r
19 /// <param name="insts">元のインストールリスト</param>
\r
20 /// <param name="pkgListsMan">インストール確認などをおこなうパッケージリストのマネージャ</param>
\r
21 /// <param name="resolved">解決済みInstallation配列</param>
\r
22 /// <param name="dependencies">依存によって必要とされたInstallation配列。ない場合は空配列</param>
\r
23 public static void ResolveInstallations(Installation[] insts, PackageListsManager pkgListsMan, out Installation[] resolved, out Installation[] dependencies)
\r
25 List<Installation> depInsts;
\r
28 depInsts = CreateRequiresInstallations(insts, pkgListsMan, null);
\r
29 dependencies = depInsts.ToArray();
\r
32 depInsts.AddRange(insts);
\r
33 resolved = depInsts.ToArray();
\r
37 /// Requires依存による依存パッケージの検索をし、それを解決するためのインストールリストを返す
\r
39 /// <param name="insts">対象インストールリスト</param>
\r
40 /// <param name="pkgListsMan">現在インストールされているか否かの判断に使われるパッケージリスト</param>
\r
41 /// <param name="preferencial">優先して使用をするパッケージのリスト。<c>null</c>でもよい</param>
\r
42 /// <returns>Requires依存による依存</returns>
\r
43 public static List<Installation> CreateRequiresInstallations(Installation[] insts, PackageListsManager pkgListsMan, ICollection<Package> preferencial)
\r
45 List<Installation> reqInsts = new List<Installation>();
\r
47 foreach (Entry entry in DeleteDuplicatedEntries(CreateRequiresEntries(insts))) {
\r
48 List<InstalledPackage> instPkgs = NaGet.Utils.MergeList<InstalledPackage>(
\r
49 pkgListsMan.installedPkgList.GetPackagesForEntry(entry),
\r
50 pkgListsMan.systemInstalledPkgList.GetPackagesForEntry(entry)
\r
53 if (instPkgs.Count <= 0) {
\r
54 if (Array.Exists(insts, delegate(Installation inst) {
\r
55 return entry.Match(inst.InstalledPackage);
\r
59 VersionComparetor vc = new VersionComparetor();
\r
60 Package pkgToBeInstall = null;
\r
62 if (preferencial != null) {
\r
63 foreach (Package pkg in preferencial) {
\r
64 if (entry.Match(pkg)) {
\r
65 pkgToBeInstall = pkg;
\r
70 if (pkgToBeInstall == null) {
\r
71 foreach (Package pkg in pkgListsMan.availablePkgList.GetPackagesForEntry(entry)) {
\r
72 if ((pkgToBeInstall == null) || (vc.Compare(pkgToBeInstall.Version, pkg.Version) < 0)) {
\r
73 pkgToBeInstall = pkg;
\r
78 if (pkgToBeInstall != null) {
\r
79 reqInsts.Add(new Installation(pkgToBeInstall));
\r
89 /// 与えられたエントリのイテレータに対し、重複しているものを取り除いて返す
\r
91 /// <remarks>現段階の実装では、重複の判断は名前のみである</remarks>
\r
92 /// <param name="entries">エントリのイテレータ</param>
\r
93 /// <returns>重複しているものを取り除いたエントリのイテレータ</returns>
\r
94 private static IEnumerable<Entry> DeleteDuplicatedEntries(IEnumerable<Entry> entries)
\r
96 LinkedList<string> pkgNames = new LinkedList<string>();
\r
98 foreach (Entry entry in entries) {
\r
99 if (! pkgNames.Contains(entry.Name)) {
\r
101 yield return entry;
\r
102 pkgNames.AddFirst(entry.Name);
\r
108 /// Requires依存エントリのイテレータを返す
\r
110 /// <remarks>現段階の実装では再帰的な依存は検索しない</remarks>
\r
111 /// <param name="insts">対象のインストールリスト</param>
\r
112 /// <returns>依存エントリのイテレータ。重複に関して解決は行わない</returns>
\r
113 private static IEnumerable<Entry> CreateRequiresEntries(Installation[] insts)
\r
115 foreach (Installation inst in insts) {
\r
116 Entry[] deps = inst.InstalledPackage.Requires;
\r
117 if (deps == null) continue;
\r
118 foreach (Entry dep in deps) {
\r