OSDN Git Service

na-get-lib,ひとまず依存関係解決関数群を作った。
authorttp <ttp@users.sourceforge.jp>
Sat, 6 Sep 2008 03:29:37 +0000 (03:29 +0000)
committerttp <ttp@users.sourceforge.jp>
Sat, 6 Sep 2008 03:29:37 +0000 (03:29 +0000)
git-svn-id: http://localhost/svn/AppliStation/trunk@963 34ed2c89-c49f-4a4b-abdb-c318350108cf

na-get-lib/NaGet.Packages.Install/DependeciesResolver.cs [new file with mode: 0644]
na-get-lib/NaGet.Packages/PackageList.cs
na-get-lib/NaGet.Packages/PackageListsManager.cs
na-get-lib/na-get-lib.csproj

diff --git a/na-get-lib/NaGet.Packages.Install/DependeciesResolver.cs b/na-get-lib/NaGet.Packages.Install/DependeciesResolver.cs
new file mode 100644 (file)
index 0000000..e41cb91
--- /dev/null
@@ -0,0 +1,118 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Reflection;\r
+\r
+namespace NaGet.Packages.Install\r
+{\r
+       /// <summary>\r
+       /// 依存関係を解決したりするための便利メソッド群\r
+       /// </summary>\r
+       public sealed class DependeciesResolver\r
+       {\r
+               private DependeciesResolver()\r
+               {\r
+               }\r
+               \r
+               public static void ResolveInstallations(Installation[] insts, PackageListsManager pkgListsMan, out Installation[] resolved, out Installation[] dependencies)\r
+               {\r
+                       List<Installation> depInsts;\r
+                       \r
+                       // 依存関係のインストールリスト\r
+                       depInsts = CreateRequiresInstallations(insts, pkgListsMan);\r
+                       dependencies = depInsts.ToArray();\r
+                       \r
+                       // 依存解決をしたインストールリスト\r
+                       depInsts.AddRange(insts);\r
+                       resolved = depInsts.ToArray();\r
+               }\r
+               \r
+               /// <summary>\r
+               /// Requires依存による依存パッケージの検索をし、それを解決するためのインストールリストを返す\r
+               /// </summary>\r
+               /// <param name="insts">対象インストールリスト</param>\r
+               /// <param name="pkgListsMan">現在インストールされているか否かの判断に使われるパッケージリスト</param>\r
+               /// <returns>Requires依存による依存</returns>\r
+               public static List<Installation> CreateRequiresInstallations(Installation[] insts, PackageListsManager pkgListsMan)\r
+               {\r
+                       List<Installation> reqInsts = new List<Installation>();\r
+                       \r
+                       foreach (Entry entry in CreateRequiresEntries(insts, pkgListsMan)) {\r
+                               reqInsts.Add(new Installation(pkgListsMan.AvailablePkgList.GetPackageForEntry(entry)));\r
+                       }\r
+                       \r
+                       return reqInsts;\r
+               }\r
+               \r
+               \r
+               /// <summary>\r
+               /// Requires依存による依存パッケージの検索をし、それをパッケージ参照エントリのイテレータで返す。\r
+               /// 返されるイテレータは、インストール済み及び重複のパッケージは取り除かれている。\r
+               /// </summary>\r
+               /// <param name="insts">対象インストールリスト</param>\r
+               /// <param name="pkgListsMan">現在インストールされているか否かの判断に使われるパッケージリスト</param>\r
+               /// <returns>Requires依存による依存</returns>\r
+               public static IEnumerable<Entry> CreateRequiresEntries(Installation[] insts, PackageListsManager pkgListsMan)\r
+               {\r
+                       foreach (Entry entry in DeleteDuplicatedEntries(CreateDependencyEntries(insts, "Requires"))) {\r
+                               if (!pkgListsMan.IsInstalledFor(entry)) {                       \r
+                                       if (Array.Exists(insts, delegate(Installation inst) {\r
+                                                       return inst.InstalledPackage.Name == entry.Name;\r
+                                                        })) {\r
+                                               continue;\r
+                                       } else {\r
+                                               yield return entry;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// 与えられたエントリのイテレータに対し、重複しているものを取り除いて返す\r
+               /// </summary>\r
+               /// <remarks>現段階の実装では、重複の判断は名前のみである</remarks>\r
+               /// <param name="entries">エントリのイテレータ</param>\r
+               /// <returns>重複しているものを取り除いたエントリのイテレータ</returns>\r
+               private static IEnumerable<Entry> DeleteDuplicatedEntries(IEnumerable<Entry> entries)\r
+               {\r
+                       List<string> pkgNames = new List<string>();\r
+                       \r
+                       foreach (Entry entry in entries) {\r
+                               if (pkgNames.IndexOf(entry.Name) < 0) {\r
+                                       // 新出ならば返す\r
+                                       yield return entry;\r
+                                       pkgNames.Add(entry.Name);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// 指定した依存エントリのイテレータを返す\r
+               /// </summary>\r
+               /// <remarks>現段階の実装では再帰的な依存は検索しない</remarks>\r
+               /// <param name="insts">対象のインストールリスト</param>\r
+               /// <param name="dependencyName">依存の種類名。<code>Package</code>クラスのフィールド名を入れる</param>\r
+               /// <returns>依存エントリのイテレータ。重複に関して解決は行わない</returns>\r
+               /// <exception cref="ArgumentException"><code>dependencyName</code>が不正であった場合</exception>\r
+               public static IEnumerable<Entry> CreateDependencyEntries(Installation[] insts, string dependencyName)\r
+               {\r
+                       FieldInfo depFInfo = null;\r
+                       \r
+                       try {\r
+                               depFInfo = typeof(Installation).GetField(dependencyName, BindingFlags.Public);\r
+                               if (depFInfo.FieldType != typeof(Installation[])) throw new ApplicationException("Field type does not Installation[].");\r
+                       } catch (Exception ex) {\r
+                               throw new ArgumentException("Not suitable dependencyName", "dependencyName", ex);\r
+                       }\r
+                       \r
+                       foreach (Installation inst in insts) {\r
+                               Entry[] deps = (Entry[]) depFInfo.GetValue(inst);\r
+                               if (deps == null) continue;\r
+                               foreach (Entry dep in deps) {\r
+                                       yield return dep;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               \r
+       }\r
+}\r
index ed5e921..6b9fdc5 100644 (file)
@@ -177,5 +177,16 @@ namespace NaGet.Packages
                        }\r
                        return null;\r
                }\r
+               \r
+               /// <summary>\r
+               /// パッケージ参照エントリが対応するパッケージを返す\r
+               /// </summary>\r
+               /// <remarks>現在の実装では、名前でしか存在確認をしていない。</remarks>\r
+               /// <param name="name">検索にかけるパッケージ参照エントリ</param>\r
+               public TPackage GetPackageForEntry(Entry entry)\r
+               {\r
+                       return GetPackageForName(entry.Name);\r
+                       // TODO 名前でしか存在確認をしていない。将来的にはバージョンなども考慮すべき\r
+               }\r
        }\r
 }\r
index b4f5806..4136544 100644 (file)
@@ -221,6 +221,18 @@ namespace NaGet.Packages
                        }\r
                }\r
                \r
+               /// <summary>\r
+               /// 与えられたパッケージ参照エントリに対応するパッケージはインストール済みか否かを返す\r
+               /// </summary>\r
+               /// <seealso cref="PackageList.GetPackageForEntry(Entry)" />\r
+               /// <param name="entry">パッケージ参照エントリ</param>\r
+               /// <returns>対応するパッケージがインストール済みならば<code>true</code></returns>\r
+               public bool IsInstalledFor(Entry entry)\r
+               {\r
+                       return (installedPkgList.GetPackageForEntry(entry) != null) ||\r
+                               (systemInstalledPkgList.GetPackageForEntry(entry) != null);\r
+               }\r
+               \r
                #endregion\r
                \r
                #region インストールログ関連\r
index 937f75d..f8aa21e 100644 (file)
@@ -57,6 +57,7 @@
     <Compile Include="NaGet.InteropServices\DllAccess.cs" />\r
     <Compile Include="NaGet.InteropServices\PEFileInfoUtils.cs" />\r
     <Compile Include="NaGet.InteropServices\ShellLink.cs" />\r
+    <Compile Include="NaGet.Packages.Install\DependeciesResolver.cs" />\r
     <Compile Include="NaGet.Packages.Install\InstallationLog.cs" />\r
     <Compile Include="NaGet.Packages\PackageListsManager.cs" />\r
     <Compile Include="NaGet.Packages\VersionComparetor.cs" />\r