OSDN Git Service

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