using System; using System.Collections.Generic; using System.Collections.ObjectModel; using NaGet.Packages; using NaGet.Packages.Install; using NaGet.SubCommands; using NaGet.SubCommands.SubTask; using NaGet.Tasks; using NaGet.InteropServices; namespace NaGet.SubCommands { /// /// キャッシュへのインストーラファイルのダウンロード処理 /// public class NaGetDownloadToCache2 : NaGetTaskSet2 { private IList installations; private DownloadScannerService scanner; /// /// コンストラクタ /// /// インストールするパッケージ public NaGetDownloadToCache2(PackageListsManager pkgListMan, Package[] pkgs) : this(pkgListMan, Installation.ConvertInstallations(pkgs)) { } /// /// コンストラクタ /// /// インストール処理の配列 public NaGetDownloadToCache2(PackageListsManager pkgMan, IList insts) { installations = new ReadOnlyCollection(insts); scanner = new DownloadScannerService(); scanner.Init(); // taskセットの初期化 initSubTask(); foreach (Installation inst in installations) { DownloadSubTask dlSTask = new DownloadSubTask(inst.InstallerURL, inst.InstallerFile); VirusScanSubTask scanSTask = new VirusScanSubTask(scanner, inst.InstallerFile, inst.InstallerURL); dlSTask.EnableChangeFileName = true; dlSTask.TaskEventRaised += delegate(object sender, TaskEventArgs e) { if (e.Type == TaskEventType.COMPLETED) { scanSTask.TargetFilePath = inst.InstallerFile = dlSTask.Filepath; } }; registSubTask(string.Format("ダウンロード: {0}", inst), dlSTask); registSubTask(string.Format("ウイルススキャン: {0}", inst), scanSTask); } registSubTask("インストーラーの検証", new VerifyInstallerFileSubTask(insts)); registSubTask("インストール済みのソフトリスト更新", new LocalUpdateSubTask(pkgMan)); } public override void Run() { NotifyStarted(); RaiseTaskSetEvent(TaskEventType.STARTED, string.Empty); try { while (hasMoreSubTask) { bool canGoToNextSubTask = true; RaiseTaskSetEvent(TaskEventType.STARTED_SUBTASK, currentSubTaskName); currentSubTask.Run(); RaiseTaskSetEvent(TaskEventType.COMPLETED_SUBTASK, currentSubTaskName); if (runCheckVerify() == false) { canGoToNextSubTask = false; NotifyGoToSubTask(0); // 最初からやり直し。 } if (cancelCalled) { throw new TaskCanceledException("cancel is called"); } if (canGoToNextSubTask) { NotifyGoToNextSubTask(); } } } catch (TaskCanceledException) { cancelCalled = true; } catch (Exception e) { RaiseTaskSetEvent(TaskEventType.ERROR, e.Message); } if (cancelCalled) { NotifyCancelled(); RaiseTaskSetEvent(TaskEventType.CANCELED, "キャンセルされました"); } else { NotifyCompleted(); RaiseTaskSetEvent(TaskEventType.COMPLETED, string.Empty); } } private bool runCheckVerify() { bool ret = true; if (currentSubTask is VerifyInstallerFileSubTask) { VerifyInstallerFileSubTask verifySTask = currentSubTask as VerifyInstallerFileSubTask; if (verifySTask.InvalidInstallers != null && verifySTask.InvalidInstallers.Count > 0) { System.Text.StringBuilder invalidInstallerNames = new System.Text.StringBuilder(); foreach (Installation invalidInst in verifySTask.InvalidInstallers) { invalidInstallerNames.AppendFormat(" - {0}\n", invalidInst.ToString()); } string msg = string.Format("以下の{0}個のパッケージでファイルが壊れている可能性があります。\n{1}\nダウンロードし直しますか?", verifySTask.InvalidInstallers.Count, invalidInstallerNames.ToString()); NaGetTaskQueryResult result = NaGetTaskQueryResult.CANCEL; if (!cancelCalled) { result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE | NaGetTaskQueryResult.CANCEL); } switch (result) { case NaGetTaskQueryResult.CONTINUE: RaiseTaskSetEvent(TaskEventType.INFO, "ダウンロード処理を再試行"); foreach (Installation invalidInst in verifySTask.InvalidInstallers) { invalidInst.RemoveDownloadedFile(); } ret = false; break; case NaGetTaskQueryResult.CANCEL: case NaGetTaskQueryResult.CANCELED_AUTOMATICALLY: default: ret = false; throw new TaskCanceledException("処理の継続のキャンセルが選択されました"); } } } return ret; } public override bool Cancelable { get { return !cancelCalled && Running && isDuringDownloading; } } private bool isDuringDownloading { get { return Running && (currentSubTask is DownloadSubTask); } } } }