示例#1
0
文件: Repo.cs 项目: Rusk85/CKAN
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = default_ckan_repo;
            }

            UpdateRegistry(repo, registry_manager.registry, ksp, user, clear);

            // Save our changes!
            registry_manager.Save();

            // Return how many we got!
            return registry_manager.registry.Available(ksp.Version()).Count;
        }
示例#2
0
文件: Repo.cs 项目: Rusk85/CKAN
        /// <summary>
        ///     Download and update the local CKAN meta-info.
        ///     Optionally takes a URL to the zipfile repo to download.
        ///     Returns the number of unique modules updated.
        /// </summary>
        public static int UpdateAllRepositories(RegistryManager registry_manager, KSP ksp, IUser user)
        {
            // If we handle multiple repositories, we will call ClearRegistry() ourselves...
            registry_manager.registry.ClearAvailable();
            // TODO this should already give us a pre-sorted list
            SortedDictionary<string, Repository> sortedRepositories = registry_manager.registry.Repositories;
            foreach (KeyValuePair<string, Repository> repository in sortedRepositories)
            {
                log.InfoFormat("About to update {0}", repository.Value.name);
                UpdateRegistry(repository.Value.uri, registry_manager.registry, ksp, user, false);
            }

            // Save our changes.
            registry_manager.Save();

            // Return how many we got!
            return registry_manager.registry.Available(ksp.Version()).Count;
        }
示例#3
0
        private static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = default_ckan_repo;
            }

            UpdateRegistry(repo, registry_manager.registry, ksp, user, clear);

            // Save our changes!
            registry_manager.Save(enforce_consistency: false);

            ShowUserInconsistencies(registry_manager.registry, user);

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.Version()).Count);
        }
示例#4
0
        /// <summary>
        ///     Download and update the local CKAN meta-info.
        ///     Optionally takes a URL to the zipfile repo to download.
        ///     Returns the number of unique modules updated.
        /// </summary>
        public static int UpdateAllRepositories(RegistryManager registry_manager, KSP ksp, IUser user)
        {
            // If we handle multiple repositories, we will call ClearRegistry() ourselves...
            registry_manager.registry.ClearAvailable();
            // TODO this should already give us a pre-sorted list
            SortedDictionary <string, Repository> sortedRepositories = registry_manager.registry.Repositories;

            foreach (KeyValuePair <string, Repository> repository in sortedRepositories)
            {
                log.InfoFormat("About to update {0}", repository.Value.name);
                UpdateRegistry(repository.Value.uri, registry_manager.registry, ksp, user, false);
            }

            // Save our changes.
            registry_manager.Save();

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.Version()).Count);
        }
示例#5
0
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = default_ckan_repo;
            }

            UpdateRegistry(repo, registry_manager.registry, ksp, user, clear);

            // Save our changes!
            registry_manager.Save();

            // maybe we can move some preexisting modules to installed (i.e. they now may have corresponding version available)
            ksp.ScanGameData();

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.Version()).Count);
        }
示例#6
0
        public static void ScanGameData()
        {
            RegistryManager registry_manager = RegistryManager.Instance();
            Registry        registry         = registry_manager.registry;

            // Forget that we've seen any DLLs, as we're going to refresh them all.
            registry.ClearDlls();

            // TODO: It would be great to optimise this to skip .git directories and the like.
            // Yes, I keep my GameData in git.

            string[] dllFiles = Directory.GetFiles(GameData(), "*.dll", SearchOption.AllDirectories);

            foreach (string file in dllFiles)
            {
                // register_dll does the heavy lifting of turning it into a modname
                registry.RegisterDll(file);
            }

            registry_manager.Save();
        }
示例#7
0
文件: Repo.cs 项目: fei090620/CKAN
        // Same as above, just with a Uri instead of string for the repo
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = CKAN.Repository.default_ckan_repo_uri;
            }

            List <CkanModule> newAvail = UpdateRegistry(repo, ksp, user);

            if (newAvail != null && newAvail.Count > 0)
            {
                registry_manager.registry.SetAllAvailable(newAvail);
                // Save our changes!
                registry_manager.Save(enforce_consistency: false);
            }

            ShowUserInconsistencies(registry_manager.registry, user);

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.VersionCriteria()).Count);
        }
示例#8
0
        /// <summary>
        ///     Download and update the local CKAN meta-info.
        ///     Optionally takes a URL to the zipfile repo to download.
        ///     Returns the number of unique modules updated.
        /// </summary>
        public static int UpdateAllRepositories(RegistryManager registry_manager, KSP ksp, IUser user)
        {
            // If we handle multiple repositories, we will call ClearRegistry() ourselves...
            registry_manager.registry.ClearAvailable();
            // TODO this should already give us a pre-sorted list
            SortedDictionary <string, Repository> sortedRepositories = registry_manager.registry.Repositories;

            foreach (KeyValuePair <string, Repository> repository in sortedRepositories)
            {
                log.InfoFormat("About to update {0}", repository.Value.name);
                UpdateRegistry(repository.Value.uri, registry_manager.registry, ksp, user, false);
            }

            // Save our changes
            // we're not sure where it's called from (and whether InconsistentKraken will be handled), and it shouldn't change consistency, so let's not check for it.
            registry_manager.Save(false);

            // maybe we can move some preexisting modules to installed (i.e. they now may have corresponding version available)
            ksp.ScanGameData();

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.Version()).Count);
        }
示例#9
0
        /// <summary>
        ///     Installs all modules given a list of identifiers as a transaction. Resolves dependencies.
        ///     This *will* save the registry at the end of operation.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// Propagates a CancelledActionKraken if the user cancelled the install.
        /// </summary>
        //
        // TODO: Break this up into smaller pieces! It's huge!
        public void InstallList(
            List <string> modules,
            RelationshipResolverOptions options,
            NetAsyncDownloader downloader = null
            )
        {
            onReportProgress = onReportProgress ?? ((message, progress) => { });

            var resolver = new RelationshipResolver(modules, options, registry_manager.registry);
            List <CkanModule> modsToInstall = resolver.ModList();
            List <CkanModule> downloads     = new List <CkanModule> ();

            // TODO: All this user-stuff should be happening in another method!
            // We should just be installing mods as a transaction.

            User.WriteLine("About to install...\n");

            foreach (CkanModule module in modsToInstall)
            {
                if (!ksp.Cache.IsCachedZip(module.download))
                {
                    User.WriteLine(" * {0}", module);
                    downloads.Add(module);
                }
                else
                {
                    User.WriteLine(" * {0} (cached)", module);
                }
            }

            bool ok = User.YesNo("\nContinue?", FrontEndType.CommandLine);

            if (!ok)
            {
                throw new CancelledActionKraken("User declined install list");
            }

            User.WriteLine(""); // Just to look tidy.

            if (downloads.Count > 0)
            {
                if (downloader == null)
                {
                    downloader = new NetAsyncDownloader();
                }

                downloader.DownloadModules(ksp.Cache, downloads, onReportProgress);
            }

            // We're about to install all our mods; so begin our transaction.
            var txoptions = new TransactionOptions();

            txoptions.Timeout = TransactionManager.MaximumTimeout;

            using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required, txoptions))
            {
                for (int i = 0; i < modsToInstall.Count; i++)
                {
                    int percentComplete = (i * 100) / modsToInstall.Count;

                    onReportProgress(String.Format("Installing mod \"{0}\"", modsToInstall[i]),
                                     percentComplete);

                    Install(modsToInstall[i]);
                }

                onReportProgress("Updating registry", 70);

                registry_manager.Save();

                onReportProgress("Commiting filesystem changes", 80);

                transaction.Complete();
            }

            // We can scan GameData as a separate transaction. Installing the mods
            // leaves everything consistent, and this is just gravy. (And ScanGameData
            // acts as a Tx, anyway, so we don't need to provide our own.)

            onReportProgress("Rescanning GameData", 90);

            ksp.ScanGameData();

            onReportProgress("Done!", 100);
        }
示例#10
0
        /// <summary>
        ///     Installs all modules given a list of identifiers as a transaction. Resolves dependencies.
        ///     This *will* save the registry at the end of operation.
        ///
        /// Propagates a BadMetadataKraken if our install metadata is bad.
        /// Propagates a FileExistsKraken if we were going to overwrite a file.
        /// Propagates a CancelledActionKraken if the user cancelled the install.
        /// </summary>
        //
        // TODO: Break this up into smaller pieces! It's huge!
        public void InstallList(
            ICollection <CkanModule> modules,
            RelationshipResolverOptions options,
            IDownloader downloader = null
            )
        {
            var resolver = new RelationshipResolver(modules, options, registry_manager.registry, ksp.Version());
            List <CkanModule> modsToInstall = resolver.ModList();
            List <CkanModule> downloads     = new List <CkanModule> ();

            // TODO: All this user-stuff should be happening in another method!
            // We should just be installing mods as a transaction.

            User.RaiseMessage("About to install...\n");

            foreach (CkanModule module in modsToInstall)
            {
                if (!ksp.Cache.IsCachedZip(module.download))
                {
                    User.RaiseMessage(" * {0}", module);
                    downloads.Add(module);
                }
                else
                {
                    User.RaiseMessage(" * {0} (cached)", module);
                }
            }

            bool ok = User.RaiseYesNoDialog("\nContinue?");

            if (!ok)
            {
                throw new CancelledActionKraken("User declined install list");
            }

            User.RaiseMessage(String.Empty); // Just to look tidy.

            if (downloads.Count > 0)
            {
                if (downloader == null)
                {
                    downloader = new NetAsyncDownloader(User);
                }

                downloader.DownloadModules(ksp.Cache, downloads);
            }

            // We're about to install all our mods; so begin our transaction.
            using (TransactionScope transaction = CkanTransaction.CreateTransactionScope())
            {
                for (int i = 0; i < modsToInstall.Count; i++)
                {
                    int percent_complete = (i * 100) / modsToInstall.Count;

                    User.RaiseProgress(String.Format("Installing mod \"{0}\"", modsToInstall[i]),
                                       percent_complete);

                    Install(modsToInstall[i]);
                }

                User.RaiseProgress("Updating registry", 70);

                registry_manager.Save(!options.without_enforce_consistency);

                User.RaiseProgress("Commiting filesystem changes", 80);

                transaction.Complete();
            }

            // We can scan GameData as a separate transaction. Installing the mods
            // leaves everything consistent, and this is just gravy. (And ScanGameData
            // acts as a Tx, anyway, so we don't need to provide our own.)

            User.RaiseProgress("Rescanning GameData", 90);

            if (!options.without_enforce_consistency)
            {
                ksp.ScanGameData();
            }

            User.RaiseProgress("Done!\n", 100);
        }
示例#11
0
        /// <summary>
        /// Install our mod from the filename supplied.
        /// If no file is supplied, we will fetch() it first.
        /// </summary>

        public void Install(CkanModule module, string filename = null)
        {
            Console.WriteLine(module.identifier + ":\n");

            string version = registry_manager.registry.InstalledVersion(module.identifier);

            if (version != null)
            {
                // TODO: Check if we can upgrade!
                Console.WriteLine("    {0} {1} already installed, skipped", module.identifier, version);
                return;
            }

            // Check our dependencies.

            if (module.requires != null)
            {
                foreach (dynamic depends in module.requires)
                {
                    string name = depends.name;
                    string ver  = registry_manager.registry.InstalledVersion(name);
                    // TODO: Compare versions.

                    if (ver == null)
                    {
                        // Oh, it's not installed! Let's see if we can find it.

                        // TODO: A big store of all our known CKAN data, so we can go
                        // find our module.

                        // If we can't find it, cry and moan.
                        Console.WriteLine("Requirement {0} not found", depends.name);
                        throw new ModuleNotFoundException(name, depends.version);
                    }
                }
            }

            // Fetch our file if we don't already have it.
            if (filename == null)
            {
                filename = CachedOrDownload(module);
            }

            // We'll need our registry to record which files we've installed.
            Registry registry = registry_manager.registry;

            // And a list of files to record them to.
            Dictionary <string, InstalledModuleFile> module_files = new Dictionary <string, InstalledModuleFile> ();

            // Open our zip file for processing
            ZipFile zipfile = new ZipFile(File.OpenRead(filename));

            // Walk through our install instructions.
            foreach (dynamic stanza in module.install)
            {
                InstallComponent(stanza, zipfile, module_files);
            }

            // Register our files.
            registry.RegisterModule(new InstalledModule(module_files, module, DateTime.Now));

            // Handle bundled mods, if we have them.
            if (module.bundles != null)
            {
                foreach (dynamic stanza in module.bundles)
                {
                    BundledModule bundled = new BundledModule(stanza);

                    string ver = registry_manager.registry.InstalledVersion(bundled.identifier);

                    if (ver != null)
                    {
                        Console.WriteLine(
                            "{0} {1} already installed, skipping bundled version {2}",
                            bundled.identifier, ver, bundled.version
                            );
                        continue;
                    }

                    // Not installed, so let's get about installing it!
                    Dictionary <string, InstalledModuleFile> installed_files = new Dictionary <string, InstalledModuleFile> ();

                    InstallComponent(stanza, zipfile, installed_files);

                    registry.RegisterModule(new InstalledModule(installed_files, bundled, DateTime.Now));
                }
            }

            // Done! Save our registry changes!
            registry_manager.Save();

            return;
        }
示例#12
0
        /// <summary>
        /// Download and update the local CKAN meta-info.
        /// Optionally takes a URL to the zipfile repo to download.
        /// </summary>
        public static RepoUpdateResult UpdateAllRepositories(RegistryManager registry_manager, GameInstance ksp, NetModuleCache cache, IUser user)
        {
            SortedDictionary <string, Repository> sortedRepositories = registry_manager.registry.Repositories;

            user.RaiseProgress("Checking for updates", 0);
            if (sortedRepositories.Values.All(repo => !string.IsNullOrEmpty(repo.last_server_etag) && repo.last_server_etag == Net.CurrentETag(repo.uri)))
            {
                user.RaiseProgress("Already up to date", 100);
                user.RaiseMessage("No changes since last update");
                return(RepoUpdateResult.NoChanges);
            }
            List <CkanModule> allAvail = new List <CkanModule>();
            int index = 0;

            foreach (KeyValuePair <string, Repository> repository in sortedRepositories)
            {
                user.RaiseProgress($"Updating {repository.Value.name}",
                                   10 + 80 * index / sortedRepositories.Count);
                SortedDictionary <string, int> downloadCounts;
                string            newETag;
                List <CkanModule> avail = UpdateRegistry(repository.Value.uri, ksp, user, out downloadCounts, out newETag);
                registry_manager.registry.SetDownloadCounts(downloadCounts);
                if (avail == null)
                {
                    // Report failure if any repo fails, rather than losing half the list.
                    // UpdateRegistry will have alerted the user to specific errors already.
                    return(RepoUpdateResult.Failed);
                }
                else
                {
                    // Merge all the lists
                    allAvail.AddRange(avail);
                    repository.Value.last_server_etag = newETag;
                    user.RaiseMessage("Updated {0} ({1} modules)",
                                      repository.Value.name, avail.Count);
                }
                ++index;
            }
            // Save allAvail to the registry if we found anything
            if (allAvail.Count > 0)
            {
                user.RaiseProgress("Saving modules to registry", 90);
                using (var transaction = CkanTransaction.CreateTransactionScope())
                {
                    // Save our changes.
                    registry_manager.registry.SetAllAvailable(allAvail);
                    registry_manager.Save(enforce_consistency: false);
                    transaction.Complete();
                }

                ShowUserInconsistencies(registry_manager.registry, user);

                List <CkanModule> metadataChanges = GetChangedInstalledModules(registry_manager.registry);
                if (metadataChanges.Count > 0)
                {
                    HandleModuleChanges(metadataChanges, user, ksp, cache, registry_manager);
                }

                // Registry.CompatibleModules is slow, just return success,
                // caller can check it if it's really needed
                user.RaiseProgress("Registry saved", 100);
                user.RaiseMessage("Repositories updated");
                return(RepoUpdateResult.Updated);
            }
            else
            {
                // Return failure
                user.RaiseMessage("No modules found!");
                return(RepoUpdateResult.Failed);
            }
        }
示例#13
0
        /// <summary>
        /// Clears the registry of DLL data, and refreshes it by scanning GameData.
        /// This operates as a transaction.
        /// This *saves* the registry upon completion.
        /// </summary>
        // TODO: This would likely be better in the Registry class itself.
        public void ScanGameData()
        {
            using (TransactionScope tx = CkanTransaction.CreateTransactionScope())
            {
                Registry.ClearPreexistingModules();

                var detectedModules = FactorioModDetector.findAllModsInDirectory(Path.Combine(gamedatadir, "mods"));
                foreach (var detectedModule in detectedModules)
                {
                    string      detectedModulePath = detectedModule.Key;
                    ModInfoJson detectedModInfo    = detectedModule.Value;
                    if (Registry.InstalledModules.Any(p => p.identifier == detectedModInfo.name))
                    {
                        continue;
                    }
                    AvailableModule availableModule;
                    if (Registry.available_modules.TryGetValue(detectedModInfo.name, out availableModule))
                    {
                        CfanModule availableCfan = availableModule.ByVersion(detectedModInfo.version);
                        if (availableCfan != null)
                        {
                            string expectedFilename = availableCfan.standardFileName + ".zip";
                            if (Path.GetFileName(detectedModulePath) == expectedFilename)
                            {
                                // yay, we can use this mod as installed (we will be able to update/remove it through cfan)
                                Registry.RegisterModule(availableCfan, new [] { detectedModulePath }, this);
                                continue;
                            }
                        }
                    }
                    // we only register that this module exists, but we won't be able to do anything with it
                    Registry.RegisterPreexistingModule(this, detectedModulePath, detectedModInfo);
                }

                try
                {
                    Registry.CheckSanity();
                }
                catch (InconsistentKraken e)
                {
                    User.RaiseError("Autodetected mods has unmet dependencies, they won't be managed by CFAN until you fix inconsitencies.\n{0}", e.InconsistenciesPretty);

                    var unmet = SanityChecker.FindUnmetDependencies(Registry.InstalledModules.Select(p => p.Module), Registry.InstalledPreexistingModules);
                    do
                    {
                        unmet
                        .Select(unmetDependencyKeyValue => unmetDependencyKeyValue.Value)
                        .SelectMany(p => p.Select(modWithUnmetDependencies => detectedModules.FirstOrDefault(detectedModule => detectedModule.Value.name == modWithUnmetDependencies.identifier)))
                        .Where(p => !p.Equals(default(KeyValuePair <string, ModInfoJson>)))
                        .ToList()
                        .ForEach(modWithUnmetDependencies =>
                        {
                            Registry.DeregisterModule(this, modWithUnmetDependencies.Value.name, true);
                            Registry.RegisterPreexistingModule(this, modWithUnmetDependencies.Key, modWithUnmetDependencies.Value);
                        });
                        unmet = SanityChecker.FindUnmetDependencies(Registry.InstalledModules.Select(p => p.Module), Registry.InstalledPreexistingModules);
                    } while (unmet.Any());
                }

                tx.Complete();
            }

            RegistryManager.Save();
        }
示例#14
0
文件: Repo.cs 项目: KSP-CKAN/CKAN
        private static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, Uri repo = null)
        {
            // Use our default repo, unless we've been told otherwise.
            if (repo == null)
            {
                repo = default_ckan_repo;
            }

            UpdateRegistry(repo, registry_manager.registry, ksp, user, clear);

            // Save our changes!
            registry_manager.Save(enforce_consistency: false);

            ShowUserInconsistencies(registry_manager.registry, user);

            // Return how many we got!
            return registry_manager.registry.Available(ksp.VersionCriteria()).Count;
        }