--- /dev/null
+using System;
+using System.Collections.Generic;
+using NaGet.Packages.Install;
+using NaGet.Packages;
+using NaGet.Net;
+
+namespace NaGet.SubCommands
+{
+ public class NaGetDownloadToCache : NaGetTaskSet
+ {
+ private bool done = false;
+
+ private int currentTaskSetIndex = -1;
+
+ private PackageListsManager pkgListMan;
+
+ /// <summary>
+ /// ダウンロードに使うダウンローダオブジェクト
+ /// </summary>
+ public Downloader Downloader {
+ get {
+ if (downloader == null) {
+ downloader = new Downloader();
+ downloader.DownloadEventRaised += delegate(object sender, DownloadEventArgs e) {
+ if (e.Type == DownloadEventType.DOWNLOADING && e.TaskProgressPercent > 0) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.PING, string.Empty, GetProgressPercent(NaGetTaskSetEventType.PING, e.TaskProgressPercent));
+ }
+ };
+ }
+ return downloader;
+ }
+ }
+
+ private Downloader downloader;
+
+ private bool packageInstallerDownloaded = false;
+
+ public override bool Cancelable {
+ get { return ! done; }
+ }
+
+ /// <summary>
+ /// ダウンロードするパッケージ
+ /// </summary>
+ public Installation[] Installations;
+
+ /// <summary>
+ /// コンストラクタ
+ /// </summary>
+ /// <param name="pkgs">インストールするパッケージ</param>
+ public NaGetDownloadToCache(PackageListsManager pkgListMan, Package[] pkgs)
+ : this(pkgListMan, Installation.ConvertInstallations(pkgs))
+ {
+ }
+
+ /// <summary>
+ /// コンストラクタ
+ /// </summary>
+ /// <param name="installations">インストール処理の配列</param>
+ public NaGetDownloadToCache(PackageListsManager pkgMan, Installation[] installations)
+ {
+ pkgListMan = pkgMan;
+
+ Installations = installations;
+ initializeMainTaskSetNames();
+ }
+
+ private void initializeMainTaskSetNames()
+ {
+ List<string> taskSetNames = new List<string>();
+
+ for (int i =0; i < Installations.Length; i++) {
+ taskSetNames.Add(string.Format("取得: {0}", Installations[i].ToString()));
+ taskSetNames.Add(string.Format("ウイルススキャン: {0}", Installations[i].ToString()));
+ }
+ taskSetNames.Add("インストーラーの検証");
+ taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.ArchiveInstalledPackageListFile));
+ taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.SystemInstalledPackageListFile));
+
+ TaskSetNames = taskSetNames.ToArray();
+ }
+
+ public override void Run()
+ {
+ currentTaskSetIndex = 0;
+ RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED, "インストール処理開始");
+
+ {
+ // ハッシュ非適合なインストーラの表
+ List<Installation> invalidInstallers = null;
+
+ do {
+ currentTaskSetIndex = 0;
+ packageInstallerDownloaded = false;
+
+ runDownloadAndVirusCheckInstallers();
+ if (done) return; // もしrunDownloadInstallers()内でエラー終了していたなら終了
+
+ packageInstallerDownloaded = true;
+
+
+ RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+
+ // ハッシュの壊れているインストーラーを取得
+ invalidInstallers = runCheckHashForInstaller();
+
+ // ハッシュが壊れているときの対策
+ if (invalidInstallers.Count > 0) {
+ System.Text.StringBuilder invalidInstallerNames = new System.Text.StringBuilder();
+ foreach (Installation invalidInst in invalidInstallers) {
+ invalidInstallerNames.AppendFormat(" - {0}\n", invalidInst.ToString());
+ }
+
+ string msg = string.Format("以下の{0}個のパッケージでファイルが壊れている可能性があります。\n{1}\n強制的にインストールを続行しますか?",
+ invalidInstallers.Count, invalidInstallerNames.ToString());
+ NaGetTaskQueryResult result = NaGetTaskQueryResult.CANCEL;
+
+ if (!cancelCalled) {
+ result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE
+ | NaGetTaskQueryResult.RETRY
+ | NaGetTaskQueryResult.CANCEL);
+ }
+
+ switch (result) {
+ case NaGetTaskQueryResult.CONTINUE:
+ RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "ハッシュの非整合を無視してインストールを継続");
+ invalidInstallers.Clear(); // ハッシュ非適合パッケージを強制的に抹消
+ break;
+ case NaGetTaskQueryResult.RETRY:
+ RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロード処理を再試行");
+
+ foreach (Installation invalidInst in invalidInstallers) {
+ invalidInst.RemoveDownloadedFile();
+ }
+
+ break;
+ //case NaGetTaskQueryResult.CANCEL:
+ default:
+ RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");
+ done = true;
+ return;
+ }
+ }
+
+ // もしハッシュが不適合なソフトがあるならばダウンロード処理からやり直す
+ } while (invalidInstallers == null || invalidInstallers.Count > 0);
+ RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ currentTaskSetIndex ++;
+ }
+
+ runLocalUpdate();
+
+ done = true;
+
+ RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED, "終了", 100);
+ }
+
+
+ /// <summary>
+ /// 処理内容のダウンロード・ウイルススキャン部分のサブルーチン
+ /// </summary>
+ private void runDownloadAndVirusCheckInstallers()
+ {
+ using (DownloadScanner scanner = new DownloadScanner()) {
+ scanner.Init();
+ foreach (Installation inst in Installations) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+
+ if (! inst.Downloaded) {
+ try {
+ inst.Download(Downloader);
+ } catch (NaGetTaskCanceledException) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "インストーラーのダウンロード処理がキャンセルされました");
+ done = true;
+ return;
+ } catch (System.Net.WebException e) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, e.Message);
+ if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続されていません。");
+ } else {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続できませんでした。ネットワークが切断されているか、ファイアウォールによって遮断された可能性があります。");
+ }
+ done = true;
+ return;
+ } catch (Exception e) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, e.Message);
+ done = true;
+ return;
+ }
+ }
+
+ if (! inst.Downloaded) { // ダウンロードが完了せずに終わった=失敗=エラー
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, string.Format("{0}のインストーラーファイルを正常にダウンロードできませんでした", inst.ToString()));
+ done = true;
+ return;
+ }
+ RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ currentTaskSetIndex ++;
+
+ RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ if (! NaGet.Env.EnableScanInstallerFile) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ウイルススキャンを行わない設定のため、ダウンロードしたファイルはウイルススキャンされませんでした");
+ } else if (!scanner.HasScanner) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロードしたファイルはウイルススキャンされませんでした(ウイルススキャンソフトが検出できませんでした)");
+ } else {
+ try {
+ DownloadScannerResult result = inst.ScanInstallerFile(scanner);
+
+ switch (result) {
+ case DownloadScannerResult.ScannerNotFound:
+ RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロードしたファイルはウイルススキャンされませんでした(ウイルススキャンソフトが検出できませんでした)");
+ break;
+ case DownloadScannerResult.InfectedAndCleaned:
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR,
+ "インストーラーファイルからウイルス感染が検出されたため、削除されました。");
+ done = true;
+ return;
+ case DownloadScannerResult.InfectedButNotCleaned:
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR,
+ "インストーラーファイルからウイルス感染が検出されました。");
+ done = true;
+ break;
+ case DownloadScannerResult.ErrorNotFound:
+ throw new System.IO.FileNotFoundException(string.Empty);
+ //break;
+ }
+
+ } catch (System.Runtime.InteropServices.COMException ex) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING,
+ string.Format("{0} (E{1})", ex.Message, ex.ErrorCode));
+ } catch (System.IO.FileNotFoundException ex) {
+ if (ex.InnerException is System.Runtime.InteropServices.COMException) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING,
+ string.Format("{0} (E{1})", ex.InnerException.Message, ((System.Runtime.InteropServices.COMException) ex.InnerException).ErrorCode));
+ }
+ RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "インストーラーファイルがウイルススキャナーによって削除されました。");
+ done = true;
+ return;
+ }
+ }
+ RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ currentTaskSetIndex ++;
+
+ if (cancelCalled) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");
+ done = true;
+ return;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// ダウンロードしたパッケージが整合したか否かハッシュでチェック
+ /// </summary>
+ /// <returns>整合しなかったインストーラーのリスト</returns>
+ private List<Installation> runCheckHashForInstaller()
+ {
+ List<Installation> invalidInstallers = new List<Installation>();
+
+ int i = 0;
+ foreach (Installation inst in Installations) {
+ float percent = (CurrentTaskSetIndex+((float)i / Installations.Length))*100f/TaskSetNames.Length;
+
+ if (inst.GetRegisteredHashCount() > 0) {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString(), percent);
+
+ if (inst.IsInstallablePackage() && inst.VerifyHashValues() == false) {
+ invalidInstallers.Add(inst);
+ RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "検証: "+inst.ToString() + " 非整合", percent);
+ } else {
+ RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString() + " OK", percent);
+ }
+ }
+ i++;
+ }
+
+ return invalidInstallers;
+ }
+
+ private void runLocalUpdate()
+ {
+ // インストールトリストの更新
+ RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ pkgListMan.DetectInstalledPkgs();
+ pkgListMan.SaveInstalledPackageList();
+ RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ currentTaskSetIndex++;
+
+ // システムにインストールされているリストの更新
+ RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ pkgListMan.DetectSystemInstalledPkgs();
+ pkgListMan.SaveSystemInstalledPackageList();
+ RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
+ currentTaskSetIndex++;
+ }
+
+ public override bool Done {
+ get { return done; }
+ }
+
+ public override int CurrentTaskSetIndex {
+ get { return currentTaskSetIndex; }
+ }
+
+ private bool cancelCalled = false;
+
+ public override bool Cancel()
+ {
+ cancelCalled = true;
+ if (! packageInstallerDownloaded) {
+ return Downloader.Cancel();
+ } else return true;
+ }
+ }
+}