/// <summary> /// Import a list of files into the download cache, with progress bar and /// interactive prompts for installation and deletion. /// </summary> /// <param name="files">Set of files to import</param> /// <param name="user">Object for user interaction</param> /// <param name="installMod">Function to call to mark a mod for installation</param> /// <param name="allowDelete">True to ask user whether to delete imported files, false to leave the files as is</param> public void ImportFiles(HashSet <FileInfo> files, IUser user, Action <string> installMod, bool allowDelete = true) { Registry registry = registry_manager.registry; HashSet <string> installable = new HashSet <string>(); List <FileInfo> deletable = new List <FileInfo>(); // Get the mapping of known hashes to modules Dictionary <string, List <CkanModule> > index = registry.GetSha1Index(); int i = 0; foreach (FileInfo f in files) { int percent = i * 100 / files.Count; user.RaiseProgress($"Importing {f.Name}... ({percent}%)", percent); // Calc SHA-1 sum string sha1 = NetModuleCache.GetFileHashSha1(f.FullName); // Find SHA-1 sum in registry (potentially multiple) if (index.ContainsKey(sha1)) { deletable.Add(f); List <CkanModule> matches = index[sha1]; foreach (CkanModule mod in matches) { if (mod.IsCompatibleKSP(ksp.VersionCriteria())) { installable.Add(mod.identifier); } if (Cache.IsMaybeCachedZip(mod)) { user.RaiseMessage("Already cached: {0}", f.Name); } else { user.RaiseMessage($"Importing {mod.identifier} {StripEpoch(mod.version)}..."); Cache.Store(mod, f.FullName); } } } else { user.RaiseMessage("Not found in index: {0}", f.Name); } ++i; } if (installable.Count > 0 && user.RaiseYesNoDialog($"Install {installable.Count} compatible imported mods in game instance {ksp.Name} ({ksp.GameDir()})?")) { // Install the imported mods foreach (string identifier in installable) { installMod(identifier); } } if (allowDelete && deletable.Count > 0 && user.RaiseYesNoDialog($"Import complete. Delete {deletable.Count} old files?")) { // Delete old files foreach (FileInfo f in deletable) { f.Delete(); } } }