OSDN Git Service

7cf9cbe969fb84bf3f00c6aa86fdb8548045c437
[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.TaskEventRaised += delegate(object sender, TaskEventArgs e) {
58                                                 if (e.Type == TaskEventType.COMPLETED) {
59                                                         scanSTask.TargetFilePath = inst.InstallerFile;
60                                                 }
61                                         };
62                                         
63                                         registSubTask(string.Format("ダウンロード: {0}", inst),
64                                                       dlSTask);
65                                 }
66                                 registSubTask(string.Format("ウイルススキャン: {0}", inst),
67                                               scanSTask);
68                         }
69                         registSubTask("インストーラーの検証",
70                                       new VerifyInstallerFileSubTask(installations));
71                         foreach (Installation inst in installations) {
72                                 bool isSilentInstall = (inst.Silent && inst.IsSupportsSilent);
73                                 string msg = string.Format("インストール: {0}{1}",
74                                                            inst.ToString(),
75                                                            (isSilentInstall)? " (サイレントインストール)" : string.Empty);
76                                 registSubTask(msg,
77                                               new FunctionalSubTask(runInstall, inst));
78                         }
79                         registSubTask("インストール済みのソフトリスト更新",
80                                       new LocalUpdateSubTask(pkgListMan));
81                 }
82                 
83                 public override void Run()
84                 {
85                         NotifyStarted();
86                         RaiseTaskSetEvent(TaskEventType.STARTED, string.Empty);
87                         
88                         try {
89                                 while (hasMoreSubTask) {
90                                         bool canGoToNextSubTask = true;
91                                         
92                                         RaiseTaskSetEvent(TaskEventType.STARTED_SUBTASK, currentSubTaskName);
93                                         currentSubTask.Run();
94                                         RaiseTaskSetEvent(TaskEventType.COMPLETED_SUBTASK, currentSubTaskName);
95                                         
96                                         if (runCheckVerify() == false) {
97                                                 canGoToNextSubTask = false;
98                                                 initializeSubTasks();
99                                                 NotifyGoToSubTask(0); // 最初からやり直し。
100                                         }
101                                         if (cancelCalled) {
102                                                 throw new TaskCanceledException("cancel is called");
103                                         }
104                                         
105                                         if (canGoToNextSubTask) {
106                                                 NotifyGoToNextSubTask();
107                                         }
108                                 }
109                         } catch (TaskCanceledException) {
110                                 cancelCalled = true;
111                         } catch (Exception e) {
112                                 RaiseTaskSetEvent(TaskEventType.ERROR, e.Message);
113                         }
114                         
115                         if (cancelCalled) {
116                                 NotifyCancelled();
117                                 RaiseTaskSetEvent(TaskEventType.CANCELED, "キャンセルされました");
118                         } else {
119                                 NotifyCompleted();
120                                 RaiseTaskSetEvent(TaskEventType.COMPLETED, string.Empty);
121                         }
122                 }
123                 
124                 private bool runCheckVerify()
125                 {
126                         bool ret = true;
127                         
128                         if (currentSubTask is VerifyInstallerFileSubTask) {
129                                 VerifyInstallerFileSubTask verifySTask = currentSubTask as VerifyInstallerFileSubTask;
130                                 if (verifySTask.InvalidInstallers != null && verifySTask.InvalidInstallers.Count > 0) {
131                                         System.Text.StringBuilder invalidInstallerNames = new System.Text.StringBuilder();
132                                         foreach (Installation invalidInst in verifySTask.InvalidInstallers) {
133                                                 invalidInstallerNames.AppendFormat(" - {0}\n", invalidInst.ToString());
134                                         }
135                                         
136                                         string msg = string.Format("以下の{0}個のパッケージでファイルが壊れている可能性があります。\n{1}\n強制的にインストールを続行しますか?",
137                                                                    verifySTask.InvalidInstallers.Count, invalidInstallerNames.ToString());
138                                         NaGetTaskQueryResult result = NaGetTaskQueryResult.CANCEL;
139                                         
140                                         if (!cancelCalled) {
141                                                 result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE
142                                                                                 | NaGetTaskQueryResult.RETRY
143                                                                                 | NaGetTaskQueryResult.CANCEL);
144                                         }
145                                         
146                                         switch (result) {
147                                                 case NaGetTaskQueryResult.CONTINUE:
148                                                         RaiseTaskSetEvent(TaskEventType.WARNING, "ハッシュの非整合を無視してインストールを継続");
149                                                         ret = true;
150                                                         break;
151                                                 case NaGetTaskQueryResult.RETRY:
152                                                         RaiseTaskSetEvent(TaskEventType.INFO, "ダウンロード処理を再試行");
153                                                         
154                                                         foreach (Installation invalidInst in verifySTask.InvalidInstallers) {
155                                                                 invalidInst.RemoveDownloadedFile();
156                                                         }
157                                                         ret = false;
158                                                         break;
159                                                 case NaGetTaskQueryResult.CANCEL:
160                                                 case NaGetTaskQueryResult.CANCELED_AUTOMATICALLY:
161                                                 default:
162                                                         ret = false;
163                                                         throw new TaskCanceledException("処理の継続のキャンセルが選択されました");
164                                         }
165                                 }
166                         }
167                         
168                         return ret;
169                 }
170                 
171                 private void runInstall(object uninstObj)
172                 {
173                         Installation inst = (Installation) uninstObj;
174                         
175                         if (! inst.IsInstallablePackage()) {
176                                 string msg = string.Format("{0}はインストールすることができません", inst.ToString());
177                                 throw new ApplicationException(msg);
178                         }
179                         
180                         inst.ErrorDataReceived += this.ReceivedErrorData;
181                         inst.OutputDataReceived += this.ReceivedOutputData;
182                         int exitCode = inst.Install();
183                         if (exitCode != 0) {
184                                 RaiseTaskSetEvent(TaskEventType.WARNING, "インストールが正常に終えていない可能性があります。プロセスの終了コード:"+exitCode);
185                         }
186                         
187                         pkgListMan.WriteInstallationLog(inst);
188                 }
189                 
190                 public override bool Cancelable {
191                         get {
192                                 return !cancelCalled && Running && isDuringDownloading;
193                         }
194                 }
195                 
196                 private bool isDuringDownloading {
197                         get {
198                                 return Running && (currentSubTask is DownloadSubTask);
199                         }
200                 }
201         }
202 }