private void ContentsDownloadButton_Click(object sender, EventArgs e) { if (ModList.SelectedRows.Count == 0) { return; } DataGridViewRow selectedItem = ModList.SelectedRows[0]; if (selectedItem == null) { return; } var module = ((GUIMod)selectedItem.Tag).ToCkanModule(); if (module == null) { return; } ResetProgress(); ShowWaitDialog(false); ModuleInstaller.GetInstance(CurrentInstance, GUI.user).CachedOrDownload(module); HideWaitDialog(true); UpdateModContentsTree(module); RecreateDialogs(); }
private void _UpdateModContentsTree(CkanModule module, bool force = false) { ContentsPreviewTree.BackColor = SystemColors.Window; ContentsPreviewTree.LineColor = SystemColors.WindowText; if (Equals(module, currentModContentsModule) && !force) { return; } else { currentModContentsModule = module; } if (module.IsMetapackage) { NotCachedLabel.Text = Properties.Resources.ModInfoNoDownload; ContentsPreviewTree.Enabled = false; ContentsDownloadButton.Enabled = false; ContentsOpenButton.Enabled = false; ContentsPreviewTree.Nodes.Clear(); } else { ContentsPreviewTree.Enabled = true; ContentsPreviewTree.Nodes.Clear(); ContentsPreviewTree.Nodes.Add(module.name); if (!Main.Instance.Manager.Cache.IsMaybeCachedZip(module)) { NotCachedLabel.Text = Properties.Resources.ModInfoNotCached; ContentsDownloadButton.Enabled = true; ContentsOpenButton.Enabled = false; ContentsPreviewTree.Enabled = false; } else { NotCachedLabel.Text = Properties.Resources.ModInfoCached; ContentsDownloadButton.Enabled = false; ContentsOpenButton.Enabled = true; ContentsPreviewTree.Enabled = true; // Get all the data; can put this in bg if slow var contents = ModuleInstaller.GetInstance( manager.CurrentInstance, Main.Instance.Manager.Cache, Main.Instance.currentUser) .GetModuleContentsList(module)?.ToList(); // Update UI; must be in fg if (contents != null) { foreach (string item in contents) { ContentsPreviewTree.Nodes[0].Nodes.Add( item.Replace('/', Path.DirectorySeparatorChar)); } ContentsPreviewTree.Nodes[0].ExpandAll(); } } } }
public void SetUp() { _testModule = TestData.DogeCoinFlag_101_module(); _nullUser = new NullUser(); _manager = new KSPManager(_nullUser); _instance = new DisposableKSP(); _registryManager = CKAN.RegistryManager.Instance(_instance.KSP); _registry = _registryManager.registry; _installer = CKAN.ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _nullUser); _gameDataDir = _instance.KSP.GameData(); _registry.AddAvailable(_testModule); var testModFile = TestData.DogeCoinFlagZip(); _manager.Cache.Store(_testModule, testModFile); _installer.InstallList( new List <string>() { _testModule.identifier }, new RelationshipResolverOptions(), _registryManager ); }
public void SetUp() { _testModule = TestData.DogeCoinFlag_101_module(); _instance = new DisposableKSP(); _nullUser = new NullUser(); _config = new FakeConfiguration(_instance.KSP, _instance.KSP.Name); _manager = new GameInstanceManager(_nullUser, _config); _registryManager = CKAN.RegistryManager.Instance(_instance.KSP); _registry = _registryManager.registry; _installer = CKAN.ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _nullUser); _gameDir = _instance.KSP.GameDir(); _gameDataDir = _instance.KSP.game.PrimaryModDirectory(_instance.KSP); _registry.AddAvailable(_testModule); var testModFile = TestData.DogeCoinFlagZip(); _manager.Cache.Store(_testModule, testModFile); HashSet <string> possibleConfigOnlyDirs = null; _installer.InstallList( new List <string>() { _testModule.identifier }, new RelationshipResolverOptions(), _registryManager, ref possibleConfigOnlyDirs ); }
public void TestSimple() { var modules = _registry.available_modules .Select((mod) => new GUIMod(mod.Value.Latest(), _registry, _instance.KSP.VersionCriteria())) .ToList(); // varargs method signature means we must call .ToArray() _listGui.Rows.AddRange(_modList.ConstructModList(modules).ToArray()); // the header row adds one to the count Assert.AreEqual(modules.Count + 1, _listGui.Rows.Count); // sort by a text column, this is the fuse-lighting _listGui.Sort(_listGui.Columns[6], ListSortDirection.Descending); // mark the mod for install, after completion we will get an exception var otherModule = modules.First((mod) => mod.Identifier.Contains("kOS")); otherModule.IsInstallChecked = true; Assert.IsTrue(otherModule.IsInstallChecked); Assert.IsFalse(otherModule.IsInstalled); Assert.DoesNotThrow(() => { // perform the install of the "other" module - now we need to sort ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _manager.User).InstallList( _modList.ComputeUserChangeSet(null).Select(change => change.Mod.ToCkanModule()).ToList(), new RelationshipResolverOptions(), new NetAsyncModulesDownloader(_manager.User, _manager.Cache) ); // trying to refresh the GUI state will throw a NullReferenceException _listGui.Refresh(); }); }
// Uninstalls a module, if it exists. static int Remove(RemoveOptions options) { ModuleInstaller installer = new ModuleInstaller(); installer.Uninstall(options.Modname); return(EXIT_OK); }
/// <summary> /// Initiate the GUI installer flow for one specific module /// </summary> /// <param name="registry">Reference to the registry</param> /// <param name="module">Module to install</param> public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule module) { RelationshipResolverOptions install_ops = RelationshipResolver.DefaultOpts(); install_ops.with_recommends = false; try { var initialChangeSet = new HashSet <ModChange>(); // Install the selected mod initialChangeSet.Add(new ModChange( new GUIMod(module, registry, CurrentInstance.VersionCriteria()), GUIModChangeType.Install, null )); InstalledModule installed = registry.InstalledModule(module.identifier); if (installed != null) { // Already installed, remove it first initialChangeSet.Add(new ModChange( new GUIMod(installed.Module, registry, CurrentInstance.VersionCriteria()), GUIModChangeType.Remove, null )); } List <ModChange> fullChangeSet = new List <ModChange>( await mainModList.ComputeChangeSetFromModList( registry, initialChangeSet, ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user), CurrentInstance.VersionCriteria() ) ); if (fullChangeSet != null && fullChangeSet.Count > 0) { // Resolve the provides relationships in the dependencies installWorker.RunWorkerAsync( new KeyValuePair <List <ModChange>, RelationshipResolverOptions>( fullChangeSet, install_ops ) ); } } catch { // If we failed, do the clean-up normally done by PostInstallMods. HideWaitDialog(false); menuStrip1.Enabled = true; } finally { changeSet = null; } }
private bool installable(ModuleInstaller installer, CkanModule module, IRegistryQuerier registry) { return(module.IsCompatibleKSP(Main.Instance.CurrentInstance.VersionCriteria()) && installer.CanInstall( RelationshipResolver.DependsOnlyOpts(), new List <CkanModule>() { module }, registry)); }
/// <summary> /// Resolve differences between installed and available metadata for given ModuleInstaller /// </summary> /// <param name="metadataChanges">List of modules that changed</param> /// <param name="user">Object for user interaction callbacks</param> /// <param name="ksp">Game instance</param> private static void HandleModuleChanges(List <CkanModule> metadataChanges, IUser user, KSP ksp, NetModuleCache cache, RegistryManager registry_manager) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < metadataChanges.Count; i++) { CkanModule module = metadataChanges[i]; sb.AppendLine(string.Format("- {0} {1}", module.identifier, module.version)); } if (user.RaiseYesNoDialog(string.Format(@"The following mods have had their metadata changed since last update: {0} You should reinstall them in order to preserve consistency with the repository. Do you wish to reinstall now?", sb))) { ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, cache, new NullUser()); // New upstream metadata may break the consistency of already installed modules // e.g. if user installs modules A and B and then later up A is made to conflict with B // This is perfectly normal and shouldn't produce an error, therefore we skip enforcing // consistency. However, we will show the user any inconsistencies later on. // Use the identifiers so we use the overload that actually resolves relationships // Do each changed module one at a time so a failure of one doesn't cause all the others to fail foreach (string changedIdentifier in metadataChanges.Select(i => i.identifier)) { try { HashSet <string> possibleConfigOnlyDirs = null; installer.Upgrade( new[] { changedIdentifier }, new NetAsyncModulesDownloader(new NullUser(), cache), ref possibleConfigOnlyDirs, registry_manager, enforceConsistency: false ); } // Thrown when a dependency couldn't be satisfied catch (ModuleNotFoundKraken) { log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier); user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier); } // Thrown when a conflicts relationship is violated catch (InconsistentKraken) { log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier); user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier); } } } }
private bool InstallList(ModuleResolution modules, RelationshipResolverOptions options) { if (toInstall.Any()) { // actual magic happens here, we run the installer with our mod list var module_installer = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user); module_installer.onReportModInstalled = OnModInstalled; return(WasSuccessful(() => module_installer.InstallList(modules, options))); } return(true); }
private void _UpdateModContentsTree(bool force = false) { ContentsPreviewTree.BackColor = SystemColors.Window; ContentsPreviewTree.LineColor = SystemColors.WindowText; GUIMod guiMod = SelectedModule; if (!guiMod.IsCKAN) { return; } CkanModule module = guiMod.ToCkanModule(); if (Equals(module, currentModContentsModule) && !force) { return; } else { currentModContentsModule = module; } if (!guiMod.IsCached) { NotCachedLabel.Text = Properties.Resources.ModInfoNotCached; ContentsDownloadButton.Enabled = true; ContentsOpenButton.Enabled = false; ContentsPreviewTree.Enabled = false; } else { NotCachedLabel.Text = Properties.Resources.ModInfoCached; ContentsDownloadButton.Enabled = false; ContentsOpenButton.Enabled = true; ContentsPreviewTree.Enabled = true; } ContentsPreviewTree.Nodes.Clear(); ContentsPreviewTree.Nodes.Add(module.name); IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, Main.Instance.Manager.Cache, Main.Instance.currentUser).GetModuleContentsList(module); if (contents == null) { return; } foreach (string item in contents) { ContentsPreviewTree.Nodes[0].Nodes.Add(item.Replace('/', Path.DirectorySeparatorChar)); } ContentsPreviewTree.Nodes[0].ExpandAll(); }
private bool InstallList(HashSet <string> toInstall, RelationshipResolverOptions options, IDownloader downloader) { if (toInstall.Any()) { // actual magic happens here, we run the installer with our mod list var module_installer = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user); module_installer.onReportModInstalled = OnModInstalled; return(WasSuccessful( () => module_installer.InstallList(toInstall.ToList(), options, downloader))); } return(true); }
private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable <ModChange> full_change_set = null; Dictionary <GUIMod, string> new_conflicts = null; bool too_many_provides_thrown = false; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user); full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria()); } catch (InconsistentKraken k) { // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling. AddStatusMessage(k.ShortDescription); user_change_set = mainModList.ComputeUserChangeSet(); new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria()); full_change_set = null; } catch (TooManyModsProvideKraken) { // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it. // We can just rerun it as the ModInfoTabControl has been removed. too_many_provides_thrown = true; } catch (DependencyNotSatisfiedKraken k) { GUI.user.RaiseError( "{0} depends on {1}, which is not compatible with the currently installed version of KSP", k.parent, k.module ); // Uncheck the box MarkModForInstall(k.parent.identifier, true); } if (too_many_provides_thrown) { await UpdateChangeSetAndConflicts(registry); new_conflicts = Conflicts; full_change_set = ChangeSet; } last_mod_to_have_install_toggled.Clear(); Conflicts = new_conflicts; ChangeSet = full_change_set; }
private void _UpdateModContentsTree(bool force = false) { GUIMod guiMod = SelectedModule; if (!guiMod.IsCKAN) { return; } CkanModule module = guiMod.ToCkanModule(); if (Equals(module, current_mod_contents_module) && !force) { return; } else { current_mod_contents_module = module; } if (!guiMod.IsCached) { NotCachedLabel.Text = Properties.Resources.MainModInfoNotCached; ContentsDownloadButton.Enabled = true; ContentsOpenButton.Enabled = false; ContentsPreviewTree.Enabled = false; } else { NotCachedLabel.Text = Properties.Resources.MainModInfoCached; ContentsDownloadButton.Enabled = false; ContentsOpenButton.Enabled = true; ContentsPreviewTree.Enabled = true; } ContentsPreviewTree.Nodes.Clear(); ContentsPreviewTree.Nodes.Add(module.name); IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, Main.Instance.Manager.Cache, GUI.user).GetModuleContentsList(module); if (contents == null) { return; } foreach (string item in contents) { ContentsPreviewTree.Nodes[0].Nodes.Add(item); } ContentsPreviewTree.Nodes[0].ExpandAll(); }
/// <summary> /// Initiate the GUI installer flow for one specific module /// </summary> /// <param name="registry">Reference to the registry</param> /// <param name="module">Module to install</param> public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule module) { RelationshipResolverOptions install_ops = RelationshipResolver.DefaultOpts(); install_ops.with_recommends = false; try { // Resolve the provides relationships in the dependencies List <ModChange> fullChangeSet = new List <ModChange>( await mainModList.ComputeChangeSetFromModList( registry, new HashSet <ModChange>() { new ModChange( new GUIMod( module, registry, CurrentInstance.VersionCriteria() ), GUIModChangeType.Install, null ) }, ModuleInstaller.GetInstance(CurrentInstance, GUI.user), CurrentInstance.VersionCriteria() ) ); if (fullChangeSet != null && fullChangeSet.Count > 0) { installWorker.RunWorkerAsync( new KeyValuePair <List <ModChange>, RelationshipResolverOptions>( fullChangeSet, install_ops ) ); } } catch { // If we failed, do the clean-up normally done by PostInstallMods. HideWaitDialog(false); menuStrip1.Enabled = true; } finally { changeSet = null; } }
/// <summary> /// Gets the ModuleInstaller instance associated with the passed KSP instance. Creates a new ModuleInstaller instance if none exists. /// </summary> /// <returns>The ModuleInstaller instance.</returns> /// <param name="ksp_instance">Current KSP instance.</param> /// <param name="user">IUser implementation.</param> public static ModuleInstaller GetInstance(KSP ksp_instance, IUser user) { ModuleInstaller instance; // Check in the list of instances if we have already created a ModuleInstaller instance for this KSP instance. if (!instances.TryGetValue(ksp_instance.GameDir().ToLower(), out instance)) { // Create a new instance and insert it in the static list. instance = new ModuleInstaller(ksp_instance, user); instances.Add(ksp_instance.GameDir().ToLower(), instance); } return instance; }
private bool allowInstall(CkanModule module) { GameInstance currentInstance = Main.Instance.Manager.CurrentInstance; IRegistryQuerier registry = RegistryManager.Instance(currentInstance).registry; var installer = new ModuleInstaller( currentInstance, Main.Instance.Manager.Cache, Main.Instance.currentUser); return(installable(installer, module, registry) || Main.Instance.YesNoDialog( string.Format(Properties.Resources.AllModVersionsInstallPrompt, module.ToString()), Properties.Resources.AllModVersionsInstallYes, Properties.Resources.AllModVersionsInstallNo)); }
/// <summary> /// Gets the ModuleInstaller instance associated with the passed KSP instance. Creates a new ModuleInstaller instance if none exists. /// </summary> /// <returns>The ModuleInstaller instance.</returns> /// <param name="ksp_instance">Current KSP instance.</param> /// <param name="user">IUser implementation.</param> public static ModuleInstaller GetInstance(KSP ksp_instance, IUser user) { ModuleInstaller instance; // Check in the list of instances if we have already created a ModuleInstaller instance for this KSP instance. if (!instances.TryGetValue(ksp_instance.GameDir().ToLower(), out instance)) { // Create a new instance and insert it in the static list. instance = new ModuleInstaller(ksp_instance, user); instances.Add(ksp_instance.GameDir().ToLower(), instance); } return(instance); }
public void Up() { _instance = new DisposableKSP(); _registryManager = RegistryManager.Instance(_instance.KSP); _registry = Registry.Empty(); _config = new FakeConfiguration(_instance.KSP, _instance.KSP.Name); _manager = new GameInstanceManager( new NullUser(), _config ); // this module contains a ksp_version of "any" which repros our issue _anyVersionModule = TestData.DogeCoinFlag_101_module(); // install it and set it as pre-installed _manager.Cache.Store(TestData.DogeCoinFlag_101_module(), TestData.DogeCoinFlagZip()); _registry.RegisterModule(_anyVersionModule, new string[] { }, _instance.KSP, false); _registry.AddAvailable(_anyVersionModule); HashSet <string> possibleConfigOnlyDirs = null; ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _manager.User).InstallList( new List <CkanModule> { { _anyVersionModule } }, new RelationshipResolverOptions(), _registryManager, ref possibleConfigOnlyDirs, new NetAsyncModulesDownloader(_manager.User, _manager.Cache) ); // this module is not for "any" version, to provide another to sort against _registry.AddAvailable(TestData.kOS_014_module()); // test object _modList = new ModList(null); _listGui = new DataGridView(); // todo: refactor the column header code to allow mocking of the GUI without creating columns _listGui.Columns.Add(new DataGridViewCheckBoxColumn()); _listGui.Columns.Add(new DataGridViewCheckBoxColumn()); _listGui.Columns.Add(new DataGridViewCheckBoxColumn()); _listGui.Columns.Add(new DataGridViewCheckBoxColumn()); for (int i = 0; i < 10; i++) { _listGui.Columns.Add(i.ToString(), "Column" + i); } }
private void _UpdateModContentsTree(bool force = false) { GUIMod guiMod = GetSelectedModule(); if (!guiMod.IsCKAN) { return; } CfanModule module = guiMod.ToCkanModule(); if (Equals(module, current_mod_contents_module) && !force) { return; } else { current_mod_contents_module = module; } if (!guiMod.IsCached) { NotCachedLabel.Text = "This mod is not in the cache, click 'Download' to preview contents"; ContentsDownloadButton.Enabled = true; ContentsPreviewTree.Enabled = false; } else { NotCachedLabel.Text = "Module is cached, preview available"; ContentsDownloadButton.Enabled = false; ContentsPreviewTree.Enabled = true; } ContentsPreviewTree.Nodes.Clear(); ContentsPreviewTree.Nodes.Add(module.title); IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user).GetModuleContentsList(module); if (contents == null) { return; } foreach (string item in contents) { ContentsPreviewTree.Nodes[0].Nodes.Add(item); } ContentsPreviewTree.Nodes[0].ExpandAll(); }
private void ContentsDownloadButton_Click(object sender, EventArgs e) { var module = GetSelectedModule(); if (module == null) { return; } ResetProgress(); ShowWaitDialog(false); ModuleInstaller.GetInstance(CurrentInstance, GUI.user).CachedOrDownload(module); HideWaitDialog(true); UpdateModContentsTree(module); RecreateDialogs(); }
public async Task TooManyProvidesCallsHandlers() { using (var tidy = new DisposableKSP()) { var manager = new KSPManager(new NullUser()); var registry = Registry.Empty(); var generator = new RandomModuleGenerator(new Random(0451)); var provide_ident = "provide"; var ksp_version = tidy.KSP.Version(); var mod = generator.GeneratorRandomModule(depends: new List <RelationshipDescriptor> { new ModuleRelationshipDescriptor { name = provide_ident } }, ksp_version: ksp_version); var moda = generator.GeneratorRandomModule(provides: new List <string> { provide_ident } , ksp_version: ksp_version); var modb = generator.GeneratorRandomModule(provides: new List <string> { provide_ident } , ksp_version: ksp_version); var choice_of_provide = modb; registry.AddAvailable(mod); registry.AddAvailable(moda); registry.AddAvailable(modb); var installer = ModuleInstaller.GetInstance(tidy.KSP, manager.Cache, null); var main_mod_list = new MainModList(null, async kraken => await Task.FromResult(choice_of_provide)); var a = new HashSet <ModChange> { new ModChange(new GUIMod(mod, registry, new KspVersionCriteria(ksp_version)), GUIModChangeType.Install, null) }; var mod_list = await main_mod_list.ComputeChangeSetFromModList(registry, a, installer, new KspVersionCriteria (ksp_version)); CollectionAssert.AreEquivalent( new[] { new ModChange(new GUIMod(mod, registry, new KspVersionCriteria(ksp_version)), GUIModChangeType.Install, null), new ModChange(new GUIMod(modb, registry, new KspVersionCriteria(ksp_version)), GUIModChangeType.Install, null) }, mod_list); manager.Dispose(); } }
private void _UpdateModContentsTree() { var module = (CkanModule)ModInfoTabControl.Tag; if (module == current_mod_contents_module) { return; } else { current_mod_contents_module = module; } if (!manager.CurrentInstance.Cache.IsCachedZip(module.download)) { NotCachedLabel.Text = "This mod is not in the cache, click 'Download' to preview contents"; ContentsDownloadButton.Enabled = true; ContentsPreviewTree.Enabled = false; } else { NotCachedLabel.Text = "Module is cached, preview available"; ContentsDownloadButton.Enabled = false; ContentsPreviewTree.Enabled = true; } ContentsPreviewTree.Nodes.Clear(); ContentsPreviewTree.Nodes.Add(module.name); IEnumerable <string> contents = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user).GetModuleContentsList(module); if (contents == null) { return; } foreach (string item in contents) { ContentsPreviewTree.Nodes[0].Nodes.Add(item); } ContentsPreviewTree.Nodes[0].ExpandAll(); }
private void ImportModules() { // Prompt the user to select one or more ZIP files OpenFileDialog dlg = new OpenFileDialog() { Title = "Import Mods", AddExtension = true, CheckFileExists = true, CheckPathExists = true, InitialDirectory = FindDownloadsPath(CurrentInstance), DefaultExt = "zip", Filter = "Mods (*.zip)|*.zip", Multiselect = true }; if (dlg.ShowDialog() == DialogResult.OK && dlg.FileNames.Length > 0) { // Set up GUI to respond to IUser calls... GUIUser.DisplayYesNo old_YesNoDialog = currentUser.displayYesNo; currentUser.displayYesNo = YesNoDialog; tabController.RenameTab("WaitTabPage", "Status log"); tabController.ShowTab("WaitTabPage"); tabController.SetTabLock(true); try { ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser).ImportFiles( GetFiles(dlg.FileNames), currentUser, (CkanModule mod) => MarkModForInstall(mod.identifier, false) ); } finally { // Put GUI back the way we found it currentUser.displayYesNo = old_YesNoDialog; tabController.SetTabLock(false); tabController.HideTab("WaitTabPage"); } } }
static int Install(InstallOptions options) { // If we have a zipfile, use it. if (options.ZipFile != null) { // Aha! We've been called as ckan -f somefile.zip somefile.ckan if (options.Files.Count > 1) { Console.WriteLine("Only a single CKAN file can be provided when installing from zip"); return(EXIT_BADOPT); } // TODO: Support installing from CKAN file embedded in zip. string zipFilename = options.ZipFile; string ckanFilename = options.Files[0]; Console.WriteLine("Installing " + ckanFilename + " from " + zipFilename); CkanModule module = CkanModule.from_file(ckanFilename); ModuleInstaller installer = new ModuleInstaller(); installer.Install(module, zipFilename); return(EXIT_OK); } // Regular invocation, walk through all CKAN files on the cmdline foreach (string filename in options.Files) { CkanModule module = CkanModule.from_file(filename); ModuleInstaller installer = new ModuleInstaller(); installer.Install(module); } Console.WriteLine("\nDone!\n"); return(EXIT_OK); }
private void ImportModules() { // Prompt the user to select one or more ZIP files OpenFileDialog dlg = new OpenFileDialog() { Title = Properties.Resources.MainImportTitle, AddExtension = true, CheckFileExists = true, CheckPathExists = true, InitialDirectory = FindDownloadsPath(CurrentInstance), DefaultExt = "zip", Filter = Properties.Resources.MainImportFilter, Multiselect = true }; if (dlg.ShowDialog() == DialogResult.OK && dlg.FileNames.Length > 0) { // Show WaitTabPage (status page) and lock it. tabController.RenameTab("WaitTabPage", Properties.Resources.MainImportWaitTitle); tabController.ShowTab("WaitTabPage"); tabController.SetTabLock(true); try { ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser).ImportFiles( GetFiles(dlg.FileNames), currentUser, (CkanModule mod) => ManageMods.MarkModForInstall(mod.identifier, false), RegistryManager.Instance(CurrentInstance).registry ); } finally { // Put GUI back the way we found it tabController.SetTabLock(false); tabController.HideTab("WaitTabPage"); } } }
private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable <ModChange> full_change_set = null; Dictionary <GUIMod, string> new_conflicts = null; bool too_many_provides_thrown = false; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user); full_change_set = await mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria()); } catch (InconsistentKraken) { //Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling. user_change_set = mainModList.ComputeUserChangeSet(); new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria()); full_change_set = null; } catch (TooManyModsProvideKraken) { //Can be thrown by ComputeChangeSetFromModList if the user cancels out of it. //We can just rerun it as the ModInfoTabControl has been removed. too_many_provides_thrown = true; } if (too_many_provides_thrown) { await UpdateChangeSetAndConflicts(registry); new_conflicts = Conflicts; full_change_set = ChangeSet; } last_mod_to_have_install_toggled.Clear(); Conflicts = new_conflicts; ChangeSet = full_change_set; }
private void AuditRecommendations(IRegistryQuerier registry, GameVersionCriteria versionCriteria) { var installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser); if (installer.FindRecommendations( registry.InstalledModules.Select(im => im.Module).ToHashSet(), new HashSet <CkanModule>(), registry as Registry, out Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations, out Dictionary <CkanModule, List <string> > suggestions, out Dictionary <CkanModule, HashSet <string> > supporters )) { tabController.ShowTab("ChooseRecommendedModsTabPage", 3); ChooseRecommendedMods.LoadRecommendations( registry, new HashSet <CkanModule>(), new HashSet <CkanModule>(), versionCriteria, Manager.Cache, recommendations, suggestions, supporters); var result = ChooseRecommendedMods.Wait(); tabController.HideTab("ChooseRecommendedModsTabPage"); if (result != null && result.Any()) { installWorker.RunWorkerAsync( new KeyValuePair <List <ModChange>, RelationshipResolverOptions>( result.Select(mod => new ModChange( mod, GUIModChangeType.Install, null )).ToList(), RelationshipResolver.DependsOnlyOpts() ) ); } } else { currentUser.RaiseError(Properties.Resources.MainRecommendationsNoneFound); } }
public void InstallList_IdentifierEqualsVersionSyntax_InstallsModule() { using (DisposableKSP ksp = new DisposableKSP()) { // Arrange var config = new FakeConfiguration(ksp.KSP, ksp.KSP.Name); GameInstanceManager manager = new GameInstanceManager( new NullUser(), config ) { CurrentInstance = ksp.KSP }; var registry = CKAN.RegistryManager.Instance(ksp.KSP).registry; var inst = new CKAN.ModuleInstaller(ksp.KSP, manager.Cache, nullUser); const string mod_file_name = "DogeCoinFlag/Flags/dogecoin.png"; string mod_file_path = Path.Combine(ksp.KSP.game.PrimaryModDirectory(ksp.KSP), mod_file_name); CkanModule mod = TestData.DogeCoinFlag_101_module(); registry.AddAvailable(mod); manager.Cache.Store(mod, TestData.DogeCoinFlagZip()); List <string> modules = new List <string>() { $"{mod.identifier}={mod.version}" }; // Act HashSet <string> possibleConfigOnlyDirs = null; inst.InstallList(modules, new RelationshipResolverOptions(), CKAN.RegistryManager.Instance(manager.CurrentInstance), ref possibleConfigOnlyDirs); // Assert Assert.IsTrue(File.Exists(mod_file_path)); manager.Dispose(); config.Dispose(); } }
private void UpdateChangeSetAndConflicts(Registry registry) { IEnumerable <KeyValuePair <CkanModule, GUIModChangeType> > full_change_set; Dictionary <Module, string> conflicts; var user_change_set = mainModList.ComputeUserChangeSet(); try { var module_installer = ModuleInstaller.GetInstance(CurrentInstance, GUI.user); full_change_set = MainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.Version()); conflicts = null; } catch (InconsistentKraken) { conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.Version()); full_change_set = null; } Conflicts = conflicts; ChangeSet = full_change_set; }
// this probably needs to be refactored private void InstallMods(object sender, DoWorkEventArgs e) { installCanceled = false; ClearLog(); var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument; IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry; ModuleInstaller installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user); // Avoid accumulating multiple event handlers installer.onReportModInstalled -= OnModInstalled; installer.onReportModInstalled += OnModInstalled; // setup progress callback // this will be the final list of mods we want to install HashSet <CkanModule> toInstall = new HashSet <CkanModule>(); var toUninstall = new HashSet <string>(); var toUpgrade = new HashSet <string>(); // First compose sets of what the user wants installed, upgraded, and removed. foreach (ModChange change in opts.Key) { switch (change.ChangeType) { case GUIModChangeType.Remove: toUninstall.Add(change.Mod.Identifier); break; case GUIModChangeType.Update: toUpgrade.Add(change.Mod.Identifier); break; case GUIModChangeType.Install: toInstall.Add(change.Mod.ToModule()); break; case GUIModChangeType.Replace: ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), CurrentInstance.VersionCriteria()); if (repl != null) { toUninstall.Add(repl.ToReplace.identifier); toInstall.Add(repl.ReplaceWith); } break; } } // Prompt for recommendations and suggestions, if any var recRows = getRecSugRows( opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install) .Select(ch => ch.Mod.ToModule()), registry, toInstall ); if (recRows.Any()) { ShowRecSugDialog(recRows, toInstall); } tabController.HideTab("ChooseRecommendedModsTabPage"); if (installCanceled) { tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } // Now let's make all our changes. tabController.RenameTab("WaitTabPage", "Status log"); ShowWaitDialog(); tabController.SetTabLock(true); IDownloader downloader = new NetAsyncModulesDownloader(GUI.user); cancelCallback = () => { downloader.CancelDownload(); installCanceled = true; }; // checks if all actions were successfull bool processSuccessful = false; bool resolvedAllProvidedMods = false; // uninstall/installs/upgrades until every list is empty // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done while (!resolvedAllProvidedMods) { try { e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); if (toUninstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.UninstallList(toUninstall, false, toInstall.Select(m => m.identifier)); processSuccessful = true; } } if (toUpgrade.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.Upgrade(toUpgrade, downloader); processSuccessful = true; } } if (toInstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.InstallList(toInstall, opts.Value, downloader, false); processSuccessful = true; } } e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key); if (installCanceled) { return; } resolvedAllProvidedMods = true; } catch (TooManyModsProvideKraken k) { // Prompt user to choose which mod to use CkanModule chosen = TooManyModsProvideCore(k).Result; // Close the selection prompt Util.Invoke(this, () => { tabController.ShowTab("WaitTabPage"); tabController.HideTab("ChooseProvidedModsTabPage"); }); if (chosen != null) { // User picked a mod, queue it up for installation toInstall.Add(chosen); // DON'T return so we can loop around and try the above InstallList call again } else { // User cancelled, get out tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } } catch (DependencyNotSatisfiedKraken ex) { GUI.user.RaiseMessage( "{0} requires {1} but it is not listed in the index, or not available for your version of KSP.", ex.parent, ex.module); return; } catch (ModuleNotFoundKraken ex) { GUI.user.RaiseMessage( "Module {0} required but it is not listed in the index, or not available for your version of KSP.", ex.module); return; } catch (BadMetadataKraken ex) { GUI.user.RaiseMessage("Bad metadata detected for module {0}: {1}", ex.module, ex.Message); return; } catch (FileExistsKraken ex) { if (ex.owningModule != null) { GUI.user.RaiseMessage( "\r\nOh no! We tried to overwrite a file owned by another mod!\r\n" + "Please try a `ckan update` and try again.\r\n\r\n" + "If this problem re-occurs, then it maybe a packaging bug.\r\n" + "Please report it at:\r\n\r\n" + "https://github.com/KSP-CKAN/NetKAN/issues/new\r\n\r\n" + "Please including the following information in your report:\r\n\r\n" + "File : {0}\r\n" + "Installing Mod : {1}\r\n" + "Owning Mod : {2}\r\n" + "CKAN Version : {3}\r\n", ex.filename, ex.installingModule, ex.owningModule, Meta.GetVersion() ); } else { GUI.user.RaiseMessage( "\r\n\r\nOh no!\r\n\r\n" + "It looks like you're trying to install a mod which is already installed,\r\n" + "or which conflicts with another mod which is already installed.\r\n\r\n" + "As a safety feature, the CKAN will *never* overwrite or alter a file\r\n" + "that it did not install itself.\r\n\r\n" + "If you wish to install {0} via the CKAN,\r\n" + "then please manually uninstall the mod which owns:\r\n\r\n" + "{1}\r\n\r\n" + "and try again.\r\n", ex.installingModule, ex.filename ); } GUI.user.RaiseMessage("Your GameData has been returned to its original state.\r\n"); return; } catch (InconsistentKraken ex) { // The prettiest Kraken formats itself for us. GUI.user.RaiseMessage(ex.InconsistenciesPretty); return; } catch (CancelledActionKraken) { return; } catch (MissingCertificateKraken kraken) { // Another very pretty kraken. GUI.user.RaiseMessage(kraken.ToString()); return; } catch (DownloadThrottledKraken kraken) { string msg = kraken.ToString(); GUI.user.RaiseMessage(msg); if (YesNoDialog($"{msg}\r\n\r\nOpen settings now?", "Open Settings", "No")) { // Launch the URL describing this host's throttling practices, if any if (kraken.infoUrl != null) { Process.Start(new ProcessStartInfo() { UseShellExecute = true, FileName = kraken.infoUrl.ToString() }); } // Now pretend they clicked the menu option for the settings Enabled = false; settingsDialog.ShowDialog(); Enabled = true; } return; } catch (ModuleDownloadErrorsKraken kraken) { GUI.user.RaiseMessage(kraken.ToString()); GUI.user.RaiseError(kraken.ToString()); return; } catch (DirectoryNotFoundKraken kraken) { GUI.user.RaiseMessage("\r\n{0}", kraken.Message); return; } catch (DllNotFoundException) { if (GUI.user.RaiseYesNoDialog("libcurl installation not found. Open wiki page for help?")) { Process.Start(new ProcessStartInfo() { UseShellExecute = true, FileName = "https://github.com/KSP-CKAN/CKAN/wiki/libcurl" }); } throw; } } }
/// <summary> /// This function returns a changeset based on the selections of the user. /// Currently returns null if a conflict is detected. /// </summary> /// <param name="registry"></param> /// <param name="changeSet"></param> /// <param name="installer">A module installer for the current KSP install</param> /// <param name="version">The version of the current KSP install</param> public async Task<IEnumerable<KeyValuePair<GUIMod, GUIModChangeType>>> ComputeChangeSetFromModList( Registry registry, HashSet<KeyValuePair<GUIMod, GUIModChangeType>> changeSet, ModuleInstaller installer, KSPVersion version) { var modules_to_install = new HashSet<CkanModule>(); var modules_to_remove = new HashSet<Module>(); var options = new RelationshipResolverOptions { without_toomanyprovides_kraken = false, with_recommends = false }; foreach (var change in changeSet) { switch (change.Value) { case GUIModChangeType.None: break; case GUIModChangeType.Install: modules_to_install.Add(change.Key.ToCkanModule()); break; case GUIModChangeType.Remove: modules_to_remove.Add(change.Key); break; case GUIModChangeType.Update: break; default: throw new ArgumentOutOfRangeException(); } } var installed_modules = registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod); bool handled_all_to_many_provides = false; while (!handled_all_to_many_provides) { //Can't await in catch clause - doesn't seem to work in mono. Hence this flag TooManyModsProvideKraken kraken; try { new RelationshipResolver(modules_to_install.ToList(), options, registry, version); handled_all_to_many_provides = true; continue; } catch (TooManyModsProvideKraken k) { kraken = k; } catch (ModuleNotFoundKraken k) { //We shouldn't need this. However the relationship provider will throw TMPs with incompatible mods. user.RaiseError("Module {0} has not been found. This may be because it is not compatible " + "with the currently installed version of KSP", k.module); return null; } //Shouldn't get here unless there is a kraken. var mod = await too_many_provides(kraken); if (mod != null) { modules_to_install.Add(mod); } else { //TODO Is could be a new type of Kraken. throw kraken; } } foreach (var dependency in modules_to_remove. Select(mod => installer.FindReverseDependencies(mod.identifier)). SelectMany(reverse_dependencies => reverse_dependencies)) { //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed Module module_by_version = registry.GetModuleByVersion(installed_modules[dependency].identifier, installed_modules[dependency].version) ?? registry.InstalledModule(dependency).Module; changeSet.Add( new KeyValuePair<GUIMod, GUIModChangeType>( new GUIMod(module_by_version, registry, version), GUIModChangeType.Remove)); } //May throw InconsistentKraken var resolver = new RelationshipResolver(options, registry, version); resolver.RemoveModsFromInstalledList( changeSet.Where(change => change.Value.Equals(GUIModChangeType.Remove)).Select(m => m.Key.ToModule())); resolver.AddModulesToInstall(modules_to_install.ToList()); changeSet.UnionWith( resolver.ModList() .Select( mod => new KeyValuePair<GUIMod, GUIModChangeType>(new GUIMod(mod, registry, version), GUIModChangeType.Install))); return changeSet; }