OSDN Git Service

na-get,NaGetInstall(Update)のDownloderを外部から書き込みできないように(これに伴うAppliStation-GUI,all-getの変...
[applistation/AppliStation.git] / na-get-lib / NaGet.SubCommands / NaGetInstall.cs
1 using System;\r
2 using NaGet.Packages.Install;\r
3 using NaGet.Packages;\r
4 using NaGet.Net;\r
5 \r
6 namespace NaGet.SubCommands\r
7 {\r
8         public class NaGetInstall : NaGetTaskSet\r
9         {\r
10                 private bool done = false;\r
11                 \r
12                 private int currentTaskSetIndex = -1;\r
13                 \r
14                 private PackageListsManager pkgListMan;\r
15                 \r
16                 /// <summary>\r
17                 /// ダウンロードに使うダウンローダオブジェクト\r
18                 /// </summary>\r
19                 public Downloader Downloader {\r
20                         get {\r
21                                 if (downloader == null) {\r
22                                         downloader = new Downloader();\r
23                                 }\r
24                                 return downloader;\r
25                         }\r
26                 }\r
27                 \r
28                 private Downloader downloader;\r
29                 \r
30                 private bool packageInstallerDownloaded = false;\r
31                 \r
32                 public override bool Cancelable {\r
33                         get { return ! done; }\r
34                 }\r
35                 \r
36                 /// <summary>\r
37                 /// インストールするパッケージ\r
38                 /// </summary>\r
39                 public Installation[] Installations;\r
40                 \r
41                 /// <summary>\r
42                 /// コンストラクタ\r
43                 /// </summary>\r
44                 /// <param name="pkgs">インストールするパッケージ</param>\r
45                 public NaGetInstall(PackageListsManager pkgListMan, Package[] pkgs)\r
46                         : this(pkgListMan, Installation.ConvertInstallations(pkgs))\r
47                 {\r
48                 }\r
49                 \r
50                 /// <summary>\r
51                 /// コンストラクタ\r
52                 /// </summary>\r
53                 /// <param name="installations">インストール処理の配列</param>\r
54                 public NaGetInstall(PackageListsManager pkgMan, Installation[] installations)\r
55                 {\r
56                         pkgListMan = pkgMan;\r
57                         \r
58                         Installations = installations;\r
59                         initializeMainTaskSetNames();\r
60                 }\r
61                 \r
62                 private void initializeMainTaskSetNames()\r
63                 {\r
64                         System.Collections.Generic.List<string> taskSetNames = new System.Collections.Generic.List<string>();\r
65                         \r
66                         for (int i =0; i < Installations.Length; i++) {\r
67                                 taskSetNames.Add(string.Format("取得: {0}", Installations[i].ToString()));\r
68                         }\r
69                         taskSetNames.Add("インストーラの検証");\r
70                         for (int i =0; i < Installations.Length; i++) {\r
71                                 taskSetNames.Add(string.Format("インストール: {0}", Installations[i].ToString()));\r
72                         }\r
73                         taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.ArchiveInstalledPackageListFile));\r
74                         taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.SystemInstalledPackageListFile));\r
75                         \r
76                         TaskSetNames = taskSetNames.ToArray();\r
77                 }\r
78                                 \r
79                 public override void Run()\r
80                 {\r
81                         currentTaskSetIndex = 0;\r
82                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED, "インストール処理開始");\r
83                         \r
84                         {\r
85                                 // ハッシュ非適合なインストーラの表\r
86                                 System.Collections.Generic.List<Installation> invalidInstallers = null;\r
87                                 \r
88                                 while (invalidInstallers == null || invalidInstallers.Count > 0) {\r
89                                         currentTaskSetIndex = 0;\r
90                                         packageInstallerDownloaded = false;\r
91                                         \r
92                                         runDownloadInstallers();\r
93                                         if (done) return; // もしrunDownloadInstallers()内でエラー終了していたなら終了\r
94                                         \r
95                                         packageInstallerDownloaded = true;\r
96                                         \r
97                                         // ハッシュの壊れているインストーラを取得\r
98                                         invalidInstallers = runCheckHashForInstaller();\r
99                                         \r
100                                         // ハッシュが壊れているときの対策\r
101                                         if (invalidInstallers.Count > 0) {\r
102                                                 string msg = string.Format("{0}個のパッケージでファイルが壊れている可能性があります\n強制的にインストールを続行しますか?",\r
103                                                                            invalidInstallers.Count);\r
104                                                 NaGetTaskQueryResult result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE\r
105                                                                                                      | NaGetTaskQueryResult.RETRY\r
106                                                                                                      | NaGetTaskQueryResult.CANCEL);\r
107                                                 \r
108                                                 switch (result) {\r
109                                                         case NaGetTaskQueryResult.CONTINUE:\r
110                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "ハッシュの非整合を無視してインストールを継続");\r
111                                                                 invalidInstallers.Clear(); // ハッシュ非適合パッケージを強制的に抹消\r
112                                                                 break;\r
113                                                         case NaGetTaskQueryResult.RETRY:\r
114                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロード処理を再試行");\r
115                                                                 \r
116                                                                 foreach (Installation invalidInst in invalidInstallers) {\r
117                                                                         invalidInst.RemoveDownloadedFile();\r
118                                                                 }\r
119                                                                 \r
120                                                                 break;\r
121                                                         //case NaGetTaskQueryResult.CANCEL:\r
122                                                         default:\r
123                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");\r
124                                                                 done = true;\r
125                                                                 return;\r
126                                                 }\r
127                                         }\r
128                                         currentTaskSetIndex ++;\r
129                                 }\r
130                         }\r
131                         \r
132                         foreach (Installation inst in Installations) {\r
133                                 string installTaskMsg = inst.ToString();\r
134                                 if (inst.Silent && (!inst.SupportsSilentOnly)) {\r
135                                         installTaskMsg += " (サイレントインストール)";\r
136                                 }\r
137                                 \r
138                                 RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, installTaskMsg);\r
139                                 \r
140                                 try {\r
141                                         \r
142                                         inst.ErrorDataReceived += this.ReceivedErrorData;\r
143                                         inst.OutputDataReceived += this.ReceivedOutputData;\r
144                                         int exitCode = inst.Install();\r
145                                         if (exitCode != 0) {\r
146                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "インストールが正常に終えていない可能性があります。インストーラの終了コード:"+exitCode);\r
147                                         }\r
148                                         \r
149                                         pkgListMan.WriteInstallationLog(inst);\r
150                                 } catch (Exception e) {\r
151                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, e.Message);\r
152                                         done = true;\r
153                                         return;\r
154                                 }\r
155                                 currentTaskSetIndex ++;\r
156                                 \r
157                                 RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, installTaskMsg);\r
158                                 \r
159                                 if (cancelCalled) {\r
160                                         RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");\r
161                                         done = true;\r
162                                         return;\r
163                                 }\r
164                         }\r
165                         pkgListMan.SaveSystemInstalledLogList(); // ログのコミット\r
166                         \r
167                         runLocalUpdate();\r
168                         \r
169                         done = true;\r
170                         \r
171                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED, "終了", 100);\r
172                 }\r
173                 \r
174                 \r
175                 /// <summary>\r
176                 /// 処理内容のダウンロード部分のサブルーチン\r
177                 /// </summary>\r
178                 private void runDownloadInstallers()\r
179                 {\r
180                         foreach (Installation inst in Installations) {\r
181                                 if (! inst.IsInstallablePackage()) {\r
182                                         string msg = string.Format("{0}はインストールすることができません", inst.ToString());\r
183                                         \r
184                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, msg);\r
185                                         done = true;\r
186                                         return;\r
187                                 }\r
188                                 \r
189                                 RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, inst.ToString());\r
190                                 \r
191                                 if (! inst.Downloaded) {\r
192                                         try {\r
193                                                 inst.Download(Downloader);\r
194                                         } catch (NaGetTaskCanceledException) {\r
195                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "インストーラのダウンロード処理がキャンセルされました");\r
196                                                 done = true;\r
197                                                 return;\r
198                                         } catch (System.Net.WebException e) {\r
199                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, e.Message);\r
200                                                 if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) {\r
201                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続されていません。");\r
202                                                 } else {\r
203                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続できませんでした。ネットワークが切断されているか、ファイアウォールによって遮断された可能性があります。");\r
204                                                 }\r
205                                                 done = true;\r
206                                                 return;\r
207                                         } catch (Exception e) {\r
208                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, e.Message);\r
209                                                 done = true;\r
210                                                 return;\r
211                                         }\r
212                                 }\r
213                                 currentTaskSetIndex ++;\r
214                                 \r
215                                 if (inst.Downloaded) { // 正常終了\r
216                                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, inst.ToString());\r
217                                 } else { // インストールが完了せずに終わった=失敗=エラー\r
218                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, string.Format("{0}のインストーラを正常にダウンロードできませんでした", inst.ToString()));\r
219                                 }\r
220                         }\r
221                 }\r
222                 \r
223                 /// <summary>\r
224                 /// ダウンロードしたパッケージが整合したか否かハッシュでチェック\r
225                 /// </summary>\r
226                 /// <returns>整合しなかったインストーラのリスト</returns>\r
227                 private System.Collections.Generic.List<Installation> runCheckHashForInstaller()\r
228                 {\r
229                         System.Collections.Generic.List<Installation> invalidInstallers = new System.Collections.Generic.List<Installation>();\r
230                         \r
231                         int i = 0;\r
232                         foreach (Installation inst in Installations) {\r
233                                 float percent = (CurrentTaskSetIndex+((float)i / Installations.Length))*100f/TaskSetNames.Length;\r
234                                 \r
235                                 if (inst.GetRegisteredHashCount() > 0) {\r
236                                         RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString(), percent);\r
237                                         \r
238                                         if (inst.IsInstallablePackage() && inst.VerifyHashValues() == false) {\r
239                                                 invalidInstallers.Add(inst);\r
240                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "検証: "+inst.ToString() + " 非整合", percent);\r
241                                         } else {\r
242                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString() + " OK", percent);\r
243                                         }\r
244                                 }\r
245                                 i++;\r
246                         }\r
247                         \r
248                         return invalidInstallers;\r
249                 }\r
250                 \r
251                 private void runLocalUpdate()\r
252                 {\r
253                         // インストールトリストの更新\r
254                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
255                         pkgListMan.DetectInstalledPkgs();\r
256                         pkgListMan.SaveInstalledPackageList();\r
257                         currentTaskSetIndex++;\r
258                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex-1]);\r
259                 \r
260                         // システムにインストールされているリストの更新\r
261                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
262                         pkgListMan.DetectSystemInstalledPkgs();\r
263                         pkgListMan.SaveSystemInstalledPackageList();\r
264                         currentTaskSetIndex++;\r
265                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex-1]);\r
266                 }\r
267                 \r
268                 public override bool Done {\r
269                         get { return done; }\r
270                 }\r
271                 \r
272                 public override int CurrentTaskSetIndex {\r
273                         get { return currentTaskSetIndex; }\r
274                 }\r
275                 \r
276                 private bool cancelCalled = false;\r
277                 \r
278                 public override bool Cancel()\r
279                 {\r
280                         cancelCalled = true;\r
281                         if (! packageInstallerDownloaded) {\r
282                                 return Downloader.Cancel();\r
283                         } else return true;\r
284                 }\r
285         }\r
286 }\r