OSDN Git Service

AppliStation-all,アセンブリバージョンを1.4.6に
[applistation/AppliStation.git] / na-get-lib / NaGet.SubCommands / NaGetInstall2.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using NaGet.Packages;
5 using NaGet.Packages.Install;
6 using NaGet.SubCommands;
7 using NaGet.SubCommands.SubTask;
8 using NaGet.Tasks;
9 using NaGet.InteropServices;
10
11 namespace NaGet.SubCommands
12 {
13         /// <summary>
14         /// インストール処理
15         /// </summary>
16         public class NaGetInstall2 : NaGetTaskSet2
17         {
18                 private IList<Installation> installations;
19                 
20                 private DownloadScannerService scanner;
21                 
22                 private PackageListsManager pkgListMan;
23                 
24                 /// <summary>
25                 /// コンストラクタ
26                 /// </summary>
27                 /// <param name="pkgs">インストールするパッケージ</param>
28                 public NaGetInstall2(PackageListsManager pkgListMan, Package[] pkgs)
29                         : this(pkgListMan, Installation.ConvertInstallations(pkgs))
30                 {
31                 }
32                 
33                 /// <summary>
34                 /// コンストラクタ
35                 /// </summary>
36                 /// <param name="installations">インストール処理の配列</param>
37                 public NaGetInstall2(PackageListsManager pkgMan, IList<Installation> insts)
38                 {
39                         pkgListMan = pkgMan;
40                         installations = new ReadOnlyCollection<Installation>(insts);
41                         
42                         scanner = new DownloadScannerService();
43                         scanner.Init();
44                         
45                         initializeSubTasks();
46                 }
47                 
48                 private void initializeSubTasks()
49                 {
50                         // taskセットの初期化
51                         initSubTask();
52                         registSubTask("セキュリティプロトコル設定の確認",
53                                       new SecurityProtocolConfigSubTask());
54                         foreach (Installation inst in installations) {
55                                 VirusScanSubTask scanSTask = new VirusScanSubTask(scanner, inst.InstallerFile, inst.InstallerURL);
56                                 
57                                 if (! inst.Downloaded) {
58                                         DownloadSubTask dlSTask = new DownloadSubTask(inst.InstallerURL, inst.InstallerFile);
59                                         
60                                         dlSTask.EnableChangeFileName = true;
61                                         dlSTask.TaskEventRaised += delegate(object sender, TaskEventArgs e) {
62                                                 if (e.Type == TaskEventType.COMPLETED) {
63                                                         scanSTask.TargetFilePath = inst.InstallerFile = dlSTask.Filepath;
64                                                 }
65                                         };
66                                         
67                                         registSubTask(string.Format("ダウンロード: {0}", inst),
68                                                       dlSTask);
69                                 }
70                                 registSubTask(string.Format("ウイルススキャン: {0}", inst),
71                                               scanSTask);
72                         }
73                         registSubTask("インストーラーの検証",
74                                       new VerifyInstallerFileSubTask(installations));
75                         foreach (Installation inst in installations) {
76                                 bool isSilentInstall = (inst.Silent && inst.IsSupportsSilent);
77                                 string msg = string.Format("インストール: {0}{1}",
78                                                            inst.ToString(),
79                                                            (isSilentInstall)? " (サイレントインストール)" : string.Empty);
80                                 registSubTask(msg,
81                                               new FunctionalSubTask<Installation>(runInstall, inst));
82                         }
83                         registSubTask("インストール済みのソフトリスト更新",
84                                       new LocalUpdateSubTask(pkgListMan));
85                 }
86                 
87                 public override void Run()
88                 {
89                         NotifyStarted();
90                         RaiseTaskSetEvent(TaskEventType.STARTED, string.Empty);
91                         
92                         try {
93                                 while (hasMoreSubTask) {
94                                         bool canGoToNextSubTask = true;
95                                         
96                                         RaiseTaskSetEvent(TaskEventType.STARTED_SUBTASK, currentSubTaskName);
97                                         currentSubTask.Run();
98                                         RaiseTaskSetEvent(TaskEventType.COMPLETED_SUBTASK, currentSubTaskName);
99                                         
100                                         if (runCheckVerify() == false) {
101                                                 canGoToNextSubTask = false;
102                                                 initializeSubTasks();
103                                                 NotifyGoToSubTask(0); // 最初からやり直し。
104                                         }
105                                         if (cancelCalled) {
106                                                 throw new TaskCanceledException("cancel is called");
107                                         }
108                                         
109                                         if (canGoToNextSubTask) {
110                                                 NotifyGoToNextSubTask();
111                                         }
112                                 }
113                         } catch (TaskCanceledException) {
114                                 cancelCalled = true;
115                         } catch (Exception e) {
116                                 RaiseTaskSetEvent(TaskEventType.ERROR, e.Message);
117                         }
118                         
119                         if (cancelCalled) {
120                                 NotifyCancelled();
121                                 RaiseTaskSetEvent(TaskEventType.CANCELED, "キャンセルされました");
122                         } else {
123                                 NotifyCompleted();
124                                 RaiseTaskSetEvent(TaskEventType.COMPLETED, string.Empty);
125                         }
126                 }
127                 
128                 private bool runCheckVerify()
129                 {
130                         bool ret = true;
131                         
132                         if (currentSubTask is VerifyInstallerFileSubTask) {
133                                 VerifyInstallerFileSubTask verifySTask = currentSubTask as VerifyInstallerFileSubTask;
134                                 if (verifySTask.InvalidInstallers != null && verifySTask.InvalidInstallers.Count > 0) {
135                                         System.Text.StringBuilder invalidInstallerNames = new System.Text.StringBuilder();
136                                         foreach (Installation invalidInst in verifySTask.InvalidInstallers) {
137                                                 invalidInstallerNames.AppendFormat(" - {0}\n", invalidInst.ToString());
138                                         }
139                                         
140                                         string msg = string.Format("以下の{0}個のパッケージでファイルが壊れている可能性があります。\n{1}\n強制的にインストールを続行しますか?",
141                                                                    verifySTask.InvalidInstallers.Count, invalidInstallerNames.ToString());
142                                         NaGetTaskQueryResult result = NaGetTaskQueryResult.CANCEL;
143                                         
144                                         if (!cancelCalled) {
145                                                 result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE
146                                                                                 | NaGetTaskQueryResult.RETRY
147                                                                                 | NaGetTaskQueryResult.CANCEL);
148                                         }
149                                         
150                                         switch (result) {
151                                                 case NaGetTaskQueryResult.CONTINUE:
152                                                         RaiseTaskSetEvent(TaskEventType.WARNING, "ハッシュの非整合を無視してインストールを継続");
153                                                         ret = true;
154                                                         break;
155                                                 case NaGetTaskQueryResult.RETRY:
156                                                         RaiseTaskSetEvent(TaskEventType.INFO, "ダウンロード処理を再試行");
157                                                         
158                                                         foreach (Installation invalidInst in verifySTask.InvalidInstallers) {
159                                                                 invalidInst.RemoveDownloadedFile();
160                                                         }
161                                                         ret = false;
162                                                         break;
163                                                 case NaGetTaskQueryResult.CANCEL:
164                                                 case NaGetTaskQueryResult.CANCELED_AUTOMATICALLY:
165                                                 default:
166                                                         ret = false;
167                                                         throw new TaskCanceledException("処理の継続のキャンセルが選択されました");
168                                         }
169                                 }
170                         }
171                         
172                         return ret;
173                 }
174                 
175                 private void runInstall(Installation inst)
176                 {
177                         if (! inst.IsInstallablePackage()) {
178                                 string msg = string.Format("{0}はインストールすることができません", inst.ToString());
179                                 throw new ApplicationException(msg);
180                         }
181                         
182                         inst.ErrorDataReceived += this.ReceivedErrorData;
183                         inst.OutputDataReceived += this.ReceivedOutputData;
184                         int exitCode = inst.Install();
185                         if (exitCode != 0) {
186                                 RaiseTaskSetEvent(TaskEventType.WARNING, "インストールが正常に終えていない可能性があります。プロセスの終了コード:"+exitCode);
187                         }
188                         
189                         pkgListMan.WriteInstallationLog(inst);
190                 }
191                 
192                 public override bool Cancelable {
193                         get {
194                                 return !cancelCalled && Running && isDuringDownloading;
195                         }
196                 }
197                 
198                 private bool isDuringDownloading {
199                         get {
200                                 return Running && (currentSubTask is DownloadSubTask);
201                         }
202                 }
203         }
204 }