示例#1
0
        // We require our constructor to be private so we can
        // enforce this being an instance (via Instance() above)
        private RegistryManager(string path, KSP ksp)
        {
            this.ksp = ksp;

            this.path = Path.Combine(path, "registry.json");
            lockfilePath = Path.Combine(path, "registry.locked");

            // Create a lock for this registry, so we cannot touch it again.
            if (!GetLock())
            {
                throw new RegistryInUseKraken(lockfilePath);
            }

            LoadOrCreate();

            // We don't cause an inconsistency error to stop the registry from being loaded,
            // because then the user can't do anything to correct it. However we're
            // sure as hell going to complain if we spot one!
            try
            {
                registry.CheckSanity();
            }
            catch (InconsistentKraken kraken)
            {
                log.ErrorFormat("Loaded registry with inconsistencies:\r\n\r\n{0}", kraken.InconsistenciesPretty);
            }
        }
示例#2
0
 // Constructor
 private ModuleInstaller(KSP ksp, IUser user)
 {
     User = user;
     this.ksp = ksp;
     registry_manager = RegistryManager.Instance(ksp);
     log.DebugFormat("Creating ModuleInstaller for {0}", ksp.GameDir());
 }
示例#3
0
文件: KSP.cs 项目: zicrog/CKAN
        public void Valid_MissingVersionData_False()
        {
            // Arrange
            string       gamedir  = TestData.NewTempDir();
            string       ckandir  = Path.Combine(gamedir, "CKAN");
            string       buildid  = Path.Combine(gamedir, "buildID.txt");
            string       readme   = Path.Combine(gamedir, "readme.txt");
            string       jsonpath = Path.Combine(ckandir, "compatible_ksp_versions.json");
            const string compatible_ksp_versions_json = @"{
                ""VersionOfKspWhenWritten"": ""1.4.3"",
                ""CompatibleKspVersions"":   [""1.4""]
            }";

            // Generate a valid game dir except for missing buildID.txt and readme.txt
            CKAN.Utilities.CopyDirectory(TestData.good_ksp_dir(), gamedir, true);
            File.Delete(buildid);
            File.Delete(readme);

            // Save GameDir/CKAN/compatible_ksp_versions.json
            Directory.CreateDirectory(ckandir);
            File.WriteAllText(jsonpath, compatible_ksp_versions_json);

            // Act
            CKAN.KSP my_ksp = new CKAN.KSP(gamedir, "missing-ver-test", nullUser);

            // Assert
            Assert.IsFalse(my_ksp.Valid);
        }
示例#4
0
文件: KSP.cs 项目: zicrog/CKAN
        public void Constructor_NullMainCompatVer_NoCrash()
        {
            // Arrange
            string       gamedir  = TestData.NewTempDir();
            string       ckandir  = Path.Combine(gamedir, "CKAN");
            string       buildid  = Path.Combine(gamedir, "buildID.txt");
            string       readme   = Path.Combine(gamedir, "readme.txt");
            string       jsonpath = Path.Combine(ckandir, "compatible_ksp_versions.json");
            const string compatible_ksp_versions_json = @"{
                ""VersionOfKspWhenWritten"": null,
                ""CompatibleKspVersions"":   [""1.4""]
            }";

            // Generate a valid game dir except for missing buildID.txt and readme.txt
            CKAN.Utilities.CopyDirectory(TestData.good_ksp_dir(), gamedir, true);
            File.Delete(buildid);
            File.Delete(readme);

            // Save GameDir/CKAN/compatible_ksp_versions.json
            Directory.CreateDirectory(ckandir);
            File.WriteAllText(jsonpath, compatible_ksp_versions_json);

            // Act & Assert
            Assert.DoesNotThrow(() =>
            {
                CKAN.KSP my_ksp = new CKAN.KSP(gamedir, "null-compat-ver-test", nullUser);
            });
        }
示例#5
0
文件: KSP.cs 项目: zicrog/CKAN
 public void Setup()
 {
     ksp_dir  = TestData.NewTempDir();
     nullUser = new NullUser();
     CKAN.Utilities.CopyDirectory(TestData.good_ksp_dir(), ksp_dir, true);
     ksp = new CKAN.KSP(ksp_dir, "test", nullUser);
 }
示例#6
0
        public void FakeInstance_ValidArgumentsWithDLCs_ManagerHasValidInstance()
        {
            string     name      = "testname";
            KspVersion mhVersion = KspVersion.Parse("1.1.0");
            KspVersion bgVersion = KspVersion.Parse("1.0.0");
            string     tempdir   = TestData.NewTempDir();
            KspVersion version   = KspVersion.Parse("1.7.1");

            Dictionary <CKAN.DLC.IDlcDetector, KspVersion> dlcs = new Dictionary <CKAN.DLC.IDlcDetector, KspVersion>()
            {
                { new CKAN.DLC.MakingHistoryDlcDetector(), mhVersion },
                { new CKAN.DLC.BreakingGroundDlcDetector(), bgVersion }
            };

            manager.FakeInstance(name, tempdir, version, dlcs);
            CKAN.KSP newKSP = new CKAN.KSP(tempdir, name, new NullUser());
            CKAN.DLC.MakingHistoryDlcDetector  mhDetector = new CKAN.DLC.MakingHistoryDlcDetector();
            CKAN.DLC.BreakingGroundDlcDetector bgDetector = new CKAN.DLC.BreakingGroundDlcDetector();

            Assert.IsTrue(manager.HasInstance(name));
            Assert.IsTrue(mhDetector.IsInstalled(newKSP, out string _, out UnmanagedModuleVersion detectedMhVersion));
            Assert.IsTrue(bgDetector.IsInstalled(newKSP, out string _, out UnmanagedModuleVersion detectedBgVersion));
            Assert.IsTrue(detectedMhVersion == new UnmanagedModuleVersion(mhVersion.ToString()));
            Assert.IsTrue(detectedBgVersion == new UnmanagedModuleVersion(bgVersion.ToString()));

            // Tidy up.
            CKAN.RegistryManager.Instance(newKSP).ReleaseLock();
            System.IO.Directory.Delete(tempdir, true);
        }
示例#7
0
 // Constructor
 private ModuleInstaller(KSP ksp, IUser user)
 {
     User             = user;
     this.ksp         = ksp;
     registry_manager = RegistryManager.Instance(ksp);
     log.DebugFormat("Creating ModuleInstaller for {0}", ksp.GameDir());
 }
示例#8
0
 public FakeWin32Registry(CKAN.KSP instance, string autostart = "test")
 {
     Instances = new List <Tuple <string, string> >
     {
         new Tuple <string, string>("test", instance.GameDir())
     };
     AutoStartInstance = autostart;
 }
示例#9
0
文件: KSPManager.cs 项目: pjf/CKAN
        /// <summary>
        /// Adds a KSP instance to registry.
        /// Returns the resulting KSP object.
        /// </summary>
        public KSP AddInstance(string name, string path)
        {
            var ksp = new KSP(path, User);

            GetInstances().Add(name, ksp);
            PopulateRegistryWithInstances();
            return(ksp);
        }
示例#10
0
        private void DeSerialisationFixes(StreamingContext context)
        {
            // Our context is our KSP install.
            KSP ksp = (KSP)context.Context;

            registry_version = LATEST_REGISTRY_VERSION;
            factorioAuthData = ksp?.tryGetFactorioAuthData();
        }
示例#11
0
 /// <summary>
 /// Renames an instance in the registry and saves.
 /// </summary>
 public void RenameInstance(string from, string to)
 {
     // TODO: What should we do if our target name already exists?
     KSP ksp = instances[from];
     instances.Remove(from);
     ksp.Name = to;
     instances.Add(to, ksp);
     Configuration.SetRegistryToInstances(instances);
 }
示例#12
0
        /// <summary>
        ///     Register the supplied module as having been installed, thereby keeping
        ///     track of its metadata and files.
        /// </summary>
        public void RegisterModule(Module mod, IEnumerable <string> absolute_files, KSP ksp)
        {
            SealionTransaction();

            // But we also want to keep track of all its files.
            // We start by checking to see if any files are owned by another mod,
            // if so, we abort with a list of errors.

            var inconsistencies = new List <string>();

            // We always work with relative files, so let's get some!
            IEnumerable <string> relative_files = absolute_files.Select(x => ksp.ToRelativeGameDir(x));

            foreach (string file in relative_files)
            {
                // For now, it's always cool if a module wants to register a directory.
                // We have to flip back to absolute paths to actually test this.
                if (Directory.Exists(ksp.ToAbsoluteGameDir(file)))
                {
                    continue;
                }

                if (this.installed_files.ContainsKey(file))
                {
                    // Woah! Registering an already owned file? Not cool!
                    // (Although if it existed, we should have thrown a kraken well before this.)
                    string owner = this.installed_files[file];
                    inconsistencies.Add(
                        string.Format("{0} wishes to install {1}, but this file is registered to {2}",
                                      mod.identifier, file, owner
                                      ));
                }
            }

            if (inconsistencies.Count > 0)
            {
                throw new InconsistentKraken(inconsistencies);
            }

            // If everything is fine, then we copy our files across. By not doing this
            // in the loop above, we make sure we don't have a half-registered module
            // when we throw our exceptinon.

            // This *will* result in us overwriting who owns a directory, and that's cool,
            // directories aren't really owned like files are. However because each mod maintains
            // its own list of files, we'll remove directories when the last mod using them
            // is uninstalled.
            foreach (string file in relative_files)
            {
                this.installed_files[file] = mod.identifier;
            }

            // Finally, register our module proper.
            var installed = new InstalledModule(ksp, mod, relative_files);

            installed_modules.Add(mod.identifier, installed);
        }
示例#13
0
文件: Repo.cs 项目: starllv/CKAN
        /// <summary>
        /// Set a registry's available modules to the list from just one repo
        /// </summary>
        /// <param name="registry_manager">Manager of the regisry of interest</param>
        /// <param name="ksp">Game instance</param>
        /// <param name="user">Object for user interaction callbacks</param>
        /// <param name="repo">Repository to check</param>
        /// <returns>
        /// Number of modules found in repo
        /// </returns>
        public static bool Update(RegistryManager registry_manager, KSP ksp, IUser user, string repo = null)
        {
            if (repo == null)
            {
                return(Update(registry_manager, ksp, user, (Uri)null));
            }

            return(Update(registry_manager, ksp, user, new Uri(repo)));
        }
示例#14
0
文件: Repo.cs 项目: Rusk85/CKAN
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, string repo = null)
        {
            if (repo == null)
            {
                return Update(registry_manager, ksp, user, clear, (Uri)null);
            }

            return Update(registry_manager, ksp, user, clear, new Uri(repo));
        }
示例#15
0
        public static int Update(RegistryManager registry_manager, KSP ksp, IUser user, Boolean clear = true, string repo = null)
        {
            if (repo == null)
            {
                return(Update(registry_manager, ksp, user, clear, (Uri)null));
            }

            return(Update(registry_manager, ksp, user, clear, new Uri(repo)));
        }
示例#16
0
 public FakeWin32Registry(CKAN.KSP instance, string autostart)
     : this(
         new List <Tuple <string, string> >
 {
     new Tuple <string, string>("test", instance.GameDir())
 },
         autostart
         )
 {
 }
示例#17
0
        /// <summary>
        /// Create a new fake KSP instance
        /// </summary>
        /// <param name="new_name">The name for the new instance.</param>
        /// <param name="new_path">The loaction of the new instance.</param>
        /// <param name="version">The version of the new instance. Should have a build number.</param>
        /// <param name="dlcVersion">The version of the DLC. Null if DLC should be faked.</param>
        public void FakeInstance(string new_name, string new_path, KspVersion version, string dlcVersion = null)
        {
            if (!version.InBuildMap())
            {
                throw new IncorrectKSPVersionKraken(String.Format("The specified KSP version is not a known version: {0}", version.ToString()));
            }
            if (Directory.Exists(new_path) && (Directory.GetFiles(new_path).Length != 0 || Directory.GetDirectories(new_path).Length != 0))
            {
                throw new BadInstallLocationKraken("The specified folder already exists and is not empty.");
            }

            try
            {
                log.DebugFormat("Creating folder structure and text files at {0} for KSP version {1}", Path.GetFullPath(new_path), version.ToString());

                // Create a KSP root directory, containing a GameData folder, a buildID.txt/buildID64.txt and a readme.txt
                Directory.CreateDirectory(new_path);
                Directory.CreateDirectory(Path.Combine(new_path, "GameData"));
                Directory.CreateDirectory(Path.Combine(new_path, "Ships"));
                Directory.CreateDirectory(Path.Combine(new_path, "Ships", "VAB"));
                Directory.CreateDirectory(Path.Combine(new_path, "Ships", "SPH"));
                Directory.CreateDirectory(Path.Combine(new_path, "Ships", "@thumbs"));
                Directory.CreateDirectory(Path.Combine(new_path, "Ships", "@thumbs", "VAB"));
                Directory.CreateDirectory(Path.Combine(new_path, "Ships", "@thumbs", "SPH"));

                // Don't write the buildID.txts if we have no build, otherwise it would be -1.
                if (version.IsBuildDefined)
                {
                    File.WriteAllText(Path.Combine(new_path, "buildID.txt"), String.Format("build id = {0}", version.Build));
                    File.WriteAllText(Path.Combine(new_path, "buildID64.txt"), String.Format("build id = {0}", version.Build));
                }

                // Create the readme.txt WITHOUT build number.
                File.WriteAllText(Path.Combine(new_path, "readme.txt"), String.Format("Version {0}", new KspVersion(version.Major, version.Minor, version.Patch).ToString()));

                // If a installed DLC should be simulated, we create the needed folder structure and the readme.txt
                if (!String.IsNullOrEmpty(dlcVersion) && version.CompareTo(new KspVersion(1, 4, 0)) >= 0)
                {
                    Directory.CreateDirectory(Path.Combine(new_path, "GameData", "SquadExpansion", "MakingHistory"));
                    File.WriteAllText(
                        Path.Combine(new_path, "GameData", "SquadExpansion", "MakingHistory", "readme.txt"),
                        String.Format("Version {0}", dlcVersion));
                }

                // Add the new instance to the registry
                KSP new_instance = new KSP(new_path, new_name, User);
                AddInstance(new_instance);
            }
            // Thrown by AddInstance() if created instance is not valid.
            // Thrown f.e. if a write operation didn't complete for unknown reasons.
            catch (NotKSPDirKraken kraken)
            {
                throw kraken;
            }
        }
示例#18
0
文件: Registry.cs 项目: javisar/CKAN
        /// <summary>
        /// Registers the given DLL as having been installed. This provides some support
        /// for pre-CKAN modules.
        ///
        /// Does nothing if the DLL is already part of an installed module.
        /// </summary>
        public void RegisterDll(KSP ksp, string absolute_path)
        {
            SealionTransaction();

            string relative_path = ksp.ToRelativeGameDir(absolute_path);

            string owner;

            if (installed_files.TryGetValue(relative_path, out owner))
            {
                log.InfoFormat(
                    "Not registering {0}, it belongs to {1}",
                    relative_path,
                    owner
                    );
                return;
            }

            // http://xkcd.com/208/
            // This regex works great for things like GameData/Foo/Foo-1.2.dll
#if (!ONI)
            Match match = Regex.Match(
                relative_path, @"
                    ^GameData/            # DLLs only live in GameData
                    (?:.*/)?              # Intermediate paths (ending with /)
                    (?<modname>[^.]+)     # Our DLL name, up until the first dot.
                    .*\.dll$              # Everything else, ending in dll
                ",
                RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace
                );
#else
            Match match = Regex.Match(
                relative_path, @"" +
                @"^" + GameConfig.Constants.ModsDir + @"/            # DLLs only live in GameData
                    (?:.*/)?              # Intermediate paths (ending with /)
                    (?<modname>[^.]+)     # Our DLL name, up until the first dot.
                    .*\.dll$              # Everything else, ending in dll
                ",
                RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace
                );
#endif

            string modName = match.Groups["modname"].Value;

            if (modName.Length == 0)
            {
                log.WarnFormat("Attempted to index {0} which is not a DLL", relative_path);
                return;
            }

            log.InfoFormat("Registering {0} from {1}", modName, relative_path);

            // We're fine if we overwrite an existing key.
            installed_dlls[modName] = relative_path;
        }
示例#19
0
 private static string FindDownloadsPath(KSP gameInst)
 {
     foreach (string p in downloadPaths)
     {
         if (!string.IsNullOrEmpty(p) && Directory.Exists(p))
         {
             return(p);
         }
     }
     return(gameInst.GameDir());
 }
示例#20
0
        /// <summary>
        /// Sets the current instance.
        /// Throws an InvalidKSPInstanceKraken if not found.
        /// </summary>
        public void SetCurrentInstance(string name)
        {
            // TODO: Should we disallow this if _CurrentInstance is already set?

            if (!GetInstances().ContainsKey(name))
            {
                throw new InvalidKSPInstanceKraken(name);
            }

            _CurrentInstance = GetInstances()[name];
        }
示例#21
0
        /// <summary>
        /// Returns an instance of the registry manager for the KSP install.
        /// The file `registry.json` is assumed.
        /// </summary>
        public static RegistryManager Instance(KSP ksp)
        {
            string directory = ksp.CkanDir();
            if (!singleton.ContainsKey(directory))
            {
                log.DebugFormat("Preparing to load registry at {0}", directory);
                singleton[directory] = new RegistryManager(directory, ksp);
            }

            return singleton[directory];
        }
示例#22
0
        /// <summary>
        /// Returns an instance of the registry manager for the KSP install.
        /// The file `registry.json` is assumed.
        /// </summary>
        public static RegistryManager Instance(KSP ksp)
        {
            string directory = ksp.CkanDir();
            if (!registryCache.ContainsKey(directory))
            {
                log.DebugFormat("Preparing to load registry at {0}", directory);
                registryCache[directory] = new RegistryManager(directory, ksp);
            }

            return registryCache[directory];
        }
示例#23
0
        /// <summary>
        /// Returns the prefered KSP instance, or null if none can be found.
        ///
        /// This works by checking to see if we're in a KSP dir first, then the
        /// registry for an autostart instance, then will try to auto-populate
        /// by scanning for the game.
        ///
        /// This *will not* touch the registry if we find a portable install.
        ///
        /// This *will* run KSP instance autodetection if the registry is empty.
        ///
        /// This *will* set the current instance, or throw an exception if it's already set.
        ///
        /// Returns null if we have multiple instances, but none of them are preferred.
        /// </summary>

        public KSP GetPreferredInstance()
        {
            if (_CurrentInstance != null)
            {
                // TODO: Throw a better exception
                throw new KSPManagerKraken("Tried to set KSP instance twice!");
            }

            _CurrentInstance = _GetPreferredInstance();
            return(_CurrentInstance);
        }
示例#24
0
 public void SetCurrentInstanceByPath(string path)
 {
     KSP ksp = new KSP(path, "custom", User);
     if (ksp.Valid)
     {
         CurrentInstance = ksp;
     }
     else
     {
         throw new NotKSPDirKraken(ksp.GameDir());
     }
 }
示例#25
0
 /// <summary>
 /// Adds a KSP instance to registry.
 /// Returns the resulting KSP object.
 /// </summary>
 public KSP AddInstance(string name, KSP ksp_instance)
 {
     if (ksp_instance.Valid)
     {
         instances.Add(name, ksp_instance);
         Win32Registry.SetRegistryToInstances(instances, AutoStartInstance);
     }
     else
     {
         throw new NotKSPDirKraken(ksp_instance.GameDir());
     }
     return(ksp_instance);
 }
示例#26
0
 /// <summary>
 /// Adds a KSP instance to registry.
 /// Returns the resulting KSP object.
 /// </summary>
 public KSP AddInstance(string name, string path)
 {
     try
     {
         var ksp = new KSP(path, User);
         GetInstances().Add(name, ksp);
         PopulateRegistryWithInstances();
         return(ksp);
     }
     catch (NotKSPDirKraken e)
     {
         return(null);
     }
 }
示例#27
0
        public void CloneInstance_BadInstance_ThrowsNotKSPDirKraken()
        {
            string badName = "badInstance";
            string tempdir = TestData.NewTempDir();

            CKAN.KSP badKSP = new CKAN.KSP(TestData.bad_ksp_dirs().First(), "badDir", new NullUser());

            Assert.Throws <NotKSPDirKraken>(() =>
                                            manager.CloneInstance(badKSP, badName, tempdir));
            Assert.IsFalse(manager.HasInstance(badName));

            // Tidy up
            System.IO.Directory.Delete(tempdir, true);
        }
示例#28
0
 /// <summary>
 /// Adds a KSP instance to registry.
 /// Returns the resulting KSP object.
 /// </summary>
 public KSP AddInstance(KSP ksp_instance)
 {
     if (ksp_instance.Valid)
     {
         string name = ksp_instance.Name;
         instances.Add(name, ksp_instance);
         Configuration.SetRegistryToInstances(instances);
     }
     else
     {
         throw new NotKSPDirKraken(ksp_instance.GameDir());
     }
     return ksp_instance;
 }
示例#29
0
        /// <summary>
        /// Download the given mod. Returns the filename it was saved to.
        ///
        /// If no filename is provided, the standard_name() will be used.
        ///
        /// </summary>
        /// <param name="filename">Filename.</param>
        public string Download(CkanModule module, string filename = null)
        {
            // Generate a temporary file if none is provided.
            if (filename == null)
            {
                filename = module.StandardName();
            }

            Console.WriteLine("    * Downloading " + filename + "...");

            string fullPath = Path.Combine(KSP.DownloadCacheDir(), filename);

            log.DebugFormat("Downloading {0} to {1}", module.download, fullPath);

            WebClient agent = new WebClient();

            try {
                agent.DownloadFile(module.download, fullPath);
            }
            catch (Exception ex) {
                // Clean up our file, it's unlikely to be complete.
                // It's okay if this fails.
                try {
                    log.DebugFormat("Removing {0} after web error failure", fullPath);
                    File.Delete(fullPath);
                }
                catch {
                    // Apparently we need a catch, even if we do nothing.
                }

                if (ex is System.Net.WebException && Regex.IsMatch(ex.Message, "authentication or decryption has failed"))
                {
                    Console.WriteLine("\nOh no! Our download failed!\n");
                    Console.WriteLine("\t{0}\n", ex.Message);
                    Console.WriteLine("If you're on Linux, try running:\n");
                    Console.WriteLine("\tmozroots --import --ask-remove\n");
                    Console.WriteLine("on the command-line to update your certificate store, and try again.\n");

                    // TODO: Throw an exception that signals we need to exit, rather than
                    // stopping all other code from tidying up. (We do this for now, so
                    // we don't have ugly stack-traces on things we kinda expect.)
                    Environment.Exit(MainClass.EXIT_ERROR);
                }

                throw;
            }

            return(fullPath);
        }
示例#30
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 bool UpdateAllRepositories(RegistryManager registry_manager, KSP ksp, NetModuleCache cache, IUser user)
        {
            SortedDictionary <string, Repository> sortedRepositories = registry_manager.registry.Repositories;
            List <CkanModule> allAvail = new List <CkanModule>();

            foreach (KeyValuePair <string, Repository> repository in sortedRepositories)
            {
                log.InfoFormat("About to update {0}", repository.Value.name);
                SortedDictionary <string, int> downloadCounts;
                List <CkanModule> avail = UpdateRegistry(repository.Value.uri, ksp, user, out downloadCounts);
                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(false);
                }
                else
                {
                    log.InfoFormat("Updated {0}", repository.Value.name);
                    // Merge all the lists
                    allAvail.AddRange(avail);
                }
            }
            // Save allAvail to the registry if we found anything
            if (allAvail.Count > 0)
            {
                registry_manager.registry.SetAllAvailable(allAvail);
                // Save our changes.
                registry_manager.Save(enforce_consistency: false);

                ShowUserInconsistencies(registry_manager.registry, user);

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

                // Registry.Available is slow, just return success,
                // caller can check it if it's really needed
                return(true);
            }
            else
            {
                // Return failure
                return(false);
            }
        }
示例#31
0
        /// <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);
        }
示例#32
0
        /// <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;
        }
示例#33
0
 private void UpdateRepo(object sender, DoWorkEventArgs e)
 {
     try
     {
         KSP current_instance1 = CurrentInstance;
         Repo.Update(RegistryManager.Instance(CurrentInstance), current_instance1.Version(), (Uri)null);
     }
     catch (MissingCertificateKraken ex)
     {
         m_ErrorDialog.ShowErrorDialog(ex.ToString());
     }
     catch (Exception)
     {
         m_ErrorDialog.ShowErrorDialog("Failed to connect to repository");
     }
 }
示例#34
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();

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.Version()).Count);
        }
示例#35
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);
            }

            // Return how many we got!
            return(registry_manager.registry.Available(ksp.Version()).Count);
        }
示例#36
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;
        }
示例#37
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;
        }
示例#38
0
        private void AddNewButton_Click(object sender, EventArgs e)
        {
            if (m_BrowseKSPFolder.ShowDialog() == DialogResult.OK)
            {
                KSP instance;
                try
                {
                    instance = new KSP(m_BrowseKSPFolder.SelectedPath, GUI.user);
                }
                catch (NotKSPDirKraken){
                    GUI.user.displayError("Directory {0} is not valid KSP directory.", new object[] {m_BrowseKSPFolder.SelectedPath});
                    return;
                }

                string instanceName = manager.GetNextValidInstanceName("New instance");
                manager.AddInstance(instanceName, instance);
                UpdateInstancesList();
            }
        }
示例#39
0
        /// <summary>
        /// Creates a copy of the provided argument, or a known-good KSP install if passed null.
        /// Use .KSP to access the KSP object itself.
        /// </summary>
        public DisposableKSP(string directory_to_clone = null, string registry_file = null)
        {
            directory_to_clone = directory_to_clone ?? good_ksp;
            disposable_dir = TestData.NewTempDir();
            TestData.CopyDirectory(directory_to_clone, disposable_dir);

            // If we've been given a registry file, then copy it into position before
            // creating our KSP object.

            if (registry_file != null)
            {
                string registry_dir = Path.Combine(disposable_dir, "CKAN");
                string registry_path = Path.Combine(registry_dir, "registry.json");
                Directory.CreateDirectory(registry_dir);
                File.Copy(registry_file, registry_path, true);
            }

            KSP = new KSP(disposable_dir, NullUser.User);
        }
示例#40
0
        // We require our constructor to be private so we can
        // enforce this being an instance (via Instance() above)
        private RegistryManager(string path, KSP ksp)
        {
            this.ksp = ksp;

            this.path = Path.Combine(path, "registry.json");
            LoadOrCreate();

            // We don't cause an inconsistency error to stop the registry from being loaded,
            // because then the user can't do anything to correct it. However we're
            // sure as hell going to complain if we spot one!
            try
            {
                registry.CheckSanity();
            }
            catch (InconsistentKraken kraken)
            {
                log.ErrorFormat("Loaded registry with inconsistencies:\n\n{0}", kraken.InconsistenciesPretty);
            }
        }
示例#41
0
        /// <summary>
        /// Creates a copy of the provided argument, or a known-good KSP install if passed null.
        /// Use .KSP to access the KSP object itself.
        /// </summary>
        public DisposableKSP(string directoryToClone = null, string registryFile = null)
        {
            directoryToClone = directoryToClone ?? _goodKsp;
            _disposableDir = TestData.NewTempDir();
            TestData.CopyDirectory(directoryToClone, _disposableDir);

            // If we've been given a registry file, then copy it into position before
            // creating our KSP object.

            if (registryFile != null)
            {
                var registryDir = Path.Combine(_disposableDir, "CKAN");
                var registryPath = Path.Combine(registryDir, "registry.json");
                Directory.CreateDirectory(registryDir);
                File.Copy(registryFile, registryPath, true);
            }

            KSP = new KSP(_disposableDir, NullUser.User);
            Logging.Initialize();
        }
示例#42
0
        private void AddNewButton_Click(object sender, EventArgs e)
        {
            if (_instanceDialog.ShowDialog() != DialogResult.OK) return;
            if (!File.Exists(_instanceDialog.FileName)) return;

            KSP instance;
            var path = Path.GetDirectoryName(_instanceDialog.FileName);
            try
            {
                instance = new KSP(path, GUI.user);
            }
            catch (NotKSPDirKraken)
            {
                GUI.user.displayError("Directory {0} is not valid KSP directory.", new object[] { path });
                return;
            }

            var instanceName = Path.GetFileName(path);
            instanceName = _manager.GetNextValidInstanceName(instanceName);
            _manager.AddInstance(instanceName, instance);
            UpdateInstancesList();
        }
示例#43
0
        /// <summary>
        /// Deregister a module, which must already have its files removed, thereby
        /// forgetting abouts its metadata and files.
        ///
        /// Throws an InconsistentKraken if not all files have been removed.
        /// </summary>
        public void DeregisterModule(KSP ksp, string module)
        {
            SealionTransaction();

            var inconsistencies = new List<string>();

            var absolute_files = installed_modules[module].Files.Select(ksp.ToAbsoluteGameDir);
            // Note, this checks to see if a *file* exists; it doesn't
            // trigger on directories, which we allow to still be present
            // (they may be shared by multiple mods.

            foreach (var absolute_file in absolute_files.Where(File.Exists))
            {
                inconsistencies.Add(string.Format(
                    "{0} is registered to {1} but has not been removed!",
                    absolute_file, module));
            }

            if (inconsistencies.Count > 0)
            {
                // Uh oh, what mess have we got ourselves into now, Inconsistency Kraken?
                throw new InconsistentKraken(inconsistencies);
            }

            // Okay, all the files are gone. Let's clear our metadata.
            foreach (string rel_file in installed_modules[module].Files)
            {
                installed_files.Remove(rel_file);
            }

            // Bye bye, module, it's been nice having you visit.
            installed_modules.Remove(module);
        }
示例#44
0
        /// <summary>
        /// Given a stanza and an open zipfile, returns all files that would be installed
        /// for this stanza.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadInstallLocationKraken if the install stanza targets an
        /// unknown install location (eg: not GameData, Ships, etc)
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception>
        internal static List<InstallableFile> FindInstallableFiles(ModuleInstallDescriptor stanza, ZipFile zipfile, KSP ksp)
        {
            string installDir;
            bool makeDirs;
            var files = new List<InstallableFile> ();

            // Normalize the path before doing everything else
            // TODO: This really should happen in the ModuleInstallDescriptor itself.
            stanza.install_to = KSPPathUtils.NormalizePath(stanza.install_to);

            // Convert our stanza to a standard `file` type. This is a no-op if it's
            // already the basic type.

            stanza = stanza.ConvertFindToFile(zipfile);

            if (stanza.install_to == "GameData" || stanza.install_to.StartsWith("GameData/"))
            {
                // The installation path can be either "GameData" or a sub-directory of "GameData"
                // but it cannot contain updirs
                if (stanza.install_to.Contains("/../") || stanza.install_to.EndsWith("/.."))
                    throw new BadInstallLocationKraken("Invalid installation path: " + stanza.install_to);

                string subDir = stanza.install_to.Substring("GameData".Length);    // remove "GameData"
                subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir;    // remove a "/" at the beginning, if present

                // Add the extracted subdirectory to the path of KSP's GameData
                installDir = ksp == null ? null : (KSPPathUtils.NormalizePath(ksp.GameData() + "/" + subDir));
                makeDirs = true;
            }
            else if (stanza.install_to.StartsWith("Ships"))
            {
                // Don't allow directory creation in ships directory
                makeDirs = false;

                switch (stanza.install_to)
                {
                    case "Ships":
                        installDir = ksp == null ? null : ksp.Ships();
                        break;
                    case "Ships/VAB":
                        installDir = ksp == null ? null : ksp.ShipsVab();
                        break;
                    case "Ships/SPH":
                        installDir = ksp == null ? null : ksp.ShipsSph();
                        break;
                    case "Ships/@thumbs":
                        installDir = ksp == null ? null : ksp.ShipsThumbs();
                        break;
                    case "Ships/@thumbs/VAB":
                        installDir = ksp == null ? null : ksp.ShipsThumbsVAB();
                        break;
                    case "Ships/@thumbs/SPH":
                        installDir = ksp == null ? null : ksp.ShipsThumbsSPH();
                        break;
                    default:
                        throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
                }
            }
            else switch (stanza.install_to)
            {
                case "Tutorial":
                    installDir = ksp == null ? null : ksp.Tutorial();
                    makeDirs = true;
                    break;

                case "Scenarios":
                    installDir = ksp == null ? null : ksp.Scenarios();
                    makeDirs = true;
                    break;

                case "GameRoot":
                    installDir = ksp == null ? null : ksp.GameDir();
                    makeDirs = false;
                    break;

                default:
                    throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
            }

            // O(N^2) solution, as we're walking the zipfile for each stanza.
            // Surely there's a better way, although this is fast enough we may not care.

            foreach (ZipEntry entry in zipfile)
            {
                // Skips things not prescribed by our install stanza.
                if (! stanza.IsWanted(entry.Name)) {
                    continue;
                }

                // Prepare our file info.
                InstallableFile file_info = new InstallableFile
                {
                    source = entry,
                    makedir = makeDirs,
                    destination = null
                };

                // If we have a place to install it, fill that in...
                if (installDir != null)
                {
                    // Get the full name of the file.
                    string outputName = entry.Name;

                    // Update our file info with the install location
                    file_info.destination = TransformOutputName(stanza.file, outputName, installDir);
                }

                files.Add(file_info);
            }

            // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93)
            if (files.Count == 0)
            {
                // We have null as the first argument here, because we don't know which module we're installing
                throw new BadMetadataKraken(null, String.Format("No files found in {0} to install!", stanza.file));
            }

            return files;
        }
示例#45
0
        /// <summary>
        /// Registers the given DLL as having been installed. This provides some support
        /// for pre-CKAN modules.
        ///
        /// Does nothing if the DLL is already part of an installed module.
        /// </summary>
        public void RegisterDll(KSP ksp, string absolute_path)
        {
            SealionTransaction();

            string relative_path = ksp.ToRelativeGameDir(absolute_path);

            string owner;
            if (installed_files.TryGetValue(relative_path, out owner))
            {
                log.InfoFormat(
                    "Not registering {0}, it belongs to {1}",
                    relative_path,
                    owner
                );
                return;
            }

            // http://xkcd.com/208/
            // This regex works great for things like GameData/Foo/Foo-1.2.dll
            Match match = Regex.Match(
                relative_path, @"
                    ^GameData/            # DLLs only live in GameData
                    (?:.*/)?              # Intermediate paths (ending with /)
                    (?<modname>[^.]+)     # Our DLL name, up until the first dot.
                    .*\.dll$              # Everything else, ending in dll
                ",
                RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace
            );

            string modName = match.Groups["modname"].Value;

            if (modName.Length == 0)
            {
                log.WarnFormat("Attempted to index {0} which is not a DLL", relative_path);
                return;
            }

            log.InfoFormat("Registering {0} from {1}", modName, relative_path);

            // We're fine if we overwrite an existing key.
            installed_dlls[modName] = relative_path;
        }
示例#46
0
 public void Dispose()
 {
     Directory.Delete(disposable_dir, true);
     KSP.Dispose();
     KSP = null; // In case .Dispose() was called manually.
 }
示例#47
0
 public InstalledModuleFile(string path, KSP ksp)
 {
     string absolute_path = ksp.ToAbsoluteGameDir(path);
     sha1_sum = Sha1Sum(absolute_path);
 }
示例#48
0
        /// <summary>
        /// Given a module and an open zipfile, return all the files that would be installed
        /// for this module.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        public static List<InstallableFile> FindInstallableFiles(CkanModule module, ZipFile zipfile, KSP ksp)
        {
            var files = new List<InstallableFile> ();

            try
            {
                // Use the provided stanzas, or use the default install stanza if they're absent.
                if (module.install != null && module.install.Length != 0)
                {
                    foreach (ModuleInstallDescriptor stanza in module.install)
                    {
                        files.AddRange(FindInstallableFiles(stanza, zipfile, ksp));
                    }
                }
                else
                {
                    ModuleInstallDescriptor default_stanza = ModuleInstallDescriptor.DefaultInstallStanza(module.identifier, zipfile);
                    files.AddRange(FindInstallableFiles(default_stanza, zipfile, ksp));
                }
            }
            catch (BadMetadataKraken kraken)
            {
                // Decorate our kraken with the current module, as the lower-level
                // methods won't know it.
                kraken.module = module;
                throw;
            }

            return files;
        }
示例#49
0
文件: KSP.cs 项目: CliftonMarien/CKAN
 public void Setup()
 {
     ksp_dir = TestData.NewTempDir();
     TestData.CopyDirectory(TestData.good_ksp_dir(), ksp_dir);
     ksp = new CKAN.KSP(ksp_dir,NullUser.User);
 }
示例#50
0
文件: Repo.cs 项目: Rusk85/CKAN
        /// <summary>
        /// Updates the supplied registry from the URL given.
        /// This does not *save* the registry. For that, you probably want Repo.Update
        /// </summary>
        internal static void UpdateRegistry(Uri repo, Registry registry, KSP ksp, IUser user, Boolean clear = true)
        {
            log.InfoFormat("Downloading {0}", repo);

            string repo_file = Net.Download(repo);

            // Clear our list of known modules.
            var old_available = registry.available_modules;
            if (clear)
            {
                registry.ClearAvailable();
            }

            // Check the filetype.
            FileType type = FileIdentifier.IdentifyFile(repo_file);

            switch (type)
            {
            case FileType.TarGz:
                UpdateRegistryFromTarGz (repo_file, registry);
                break;
            case FileType.Zip:
                UpdateRegistryFromZip (repo_file, registry);
                break;
            default:
                break;
            }

            List<CkanModule> metadataChanges = new List<CkanModule>();

            foreach (var identifierModulePair in old_available)
            {
                var identifier = identifierModulePair.Key;

                if (registry.IsInstalled(identifier))
                {
                    var installedVersion = registry.InstalledVersion(identifier);
                    if (!(registry.available_modules.ContainsKey(identifier)))
                    {
                        log.InfoFormat("UpdateRegistry, module {0}, version {1} not in repository ({2})", identifier, installedVersion, repo);
                        continue;
                    }

                    if (!registry.available_modules[identifier].module_version.ContainsKey(installedVersion))
                    {
                        continue;
                    }

                    // if the mod is installed and the metadata is different we have to reinstall it
                    var metadata = registry.available_modules[identifier].module_version[installedVersion];

                    if (!old_available.ContainsKey(identifier) ||
                        !old_available[identifier].module_version.ContainsKey(installedVersion))
                    {
                        continue;
                    }

                    var oldMetadata = old_available[identifier].module_version[installedVersion];

                    bool same = true;
                    if ((metadata.install == null) != (oldMetadata.install == null) ||
                        (metadata.install != null && metadata.install.Length != oldMetadata.install.Length))
                    {
                        same = false;
                    }
                    else
                    {
                        if(metadata.install != null)
                        for (int i = 0; i < metadata.install.Length; i++)
                        {
                            if (metadata.install[i].file != oldMetadata.install[i].file)
                            {
                                same = false;
                                break;
                            }

                            if (metadata.install[i].install_to != oldMetadata.install[i].install_to)
                            {
                                same = false;
                                break;
                            }

                            if ((metadata.install[i].filter == null) != (oldMetadata.install[i].filter == null))
                            {
                                same = false;
                                break;
                            }

                            if(metadata.install[i].filter != null)
                            if (!metadata.install[i].filter.SequenceEqual(oldMetadata.install[i].filter))
                            {
                                same = false;
                                break;
                            }

                            if ((metadata.install[i].filter_regexp == null) != (oldMetadata.install[i].filter_regexp == null))
                            {
                                same = false;
                                break;
                            }

                            if(metadata.install[i].filter_regexp != null)
                            if (!metadata.install[i].filter_regexp.SequenceEqual(oldMetadata.install[i].filter_regexp))
                            {
                                same = false;
                                break;
                            }
                        }
                    }

                    if (!same)
                    {
                        metadataChanges.Add(registry.available_modules[identifier].module_version[installedVersion]);
                    }
                }
            }

            if (metadataChanges.Any())
            {
                string mods = "";
                for (int i = 0; i < metadataChanges.Count; i++)
                {
                    mods += metadataChanges[i].identifier + " "
                        + metadataChanges[i].version.ToString() + ((i < metadataChanges.Count-1) ? ", " : "");
                }

                if(user.RaiseYesNoDialog(String.Format(
                    @"The following mods have had their metadata changed since last update - {0}.
            It is advisable that you reinstall them in order to preserve consistency with the repository. Do you wish to reinstall now?", mods)))
                {
                    ModuleInstaller installer = ModuleInstaller.GetInstance(ksp, new NullUser());
                    installer.Upgrade(metadataChanges, new NetAsyncDownloader(new NullUser()));
                }
            }

            // Remove our downloaded meta-data now we've processed it.
            // Seems weird to do this as part of a transaction, but Net.Download uses them, so let's be consistent.
            file_transaction.Delete(repo_file);
        }
示例#51
0
 /// <summary>
 /// Given a module and a path to a zipfile, returns all the files that would be installed
 /// from that zip for this module.
 ///
 /// This *will* throw an exception if the file does not exist.
 ///
 /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
 ///
 /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
 /// </summary>
 // TODO: Document which exception!
 public static List<InstallableFile> FindInstallableFiles(CkanModule module, string zip_filename, KSP ksp)
 {
     // `using` makes sure our zipfile gets closed when we exit this block.
     using (ZipFile zipfile = new ZipFile(zip_filename))
     {
         log.DebugFormat("Searching {0} using {1} as module", zip_filename, module);
         return FindInstallableFiles(module, zipfile, ksp);
     }
 }
示例#52
0
        public InstalledModule(KSP ksp, Module module, IEnumerable<string> relative_files)
        {
            install_time = DateTime.Now;
            source_module = module;
            installed_files = new Dictionary<string, InstalledModuleFile>();

            foreach (string file in relative_files)
            {
                if (Path.IsPathRooted(file))
                {
                    throw new PathErrorKraken(file, "InstalledModule *must* have relative paths");
                }

                // IMF needs a KSP object so it can compute the SHA1.
                installed_files[file] = new InstalledModuleFile(file, ksp);
            }
        }
示例#53
0
文件: Repo.cs 项目: KSP-CKAN/CKAN
        /// <summary>
        /// Updates the supplied registry from the URL given.
        /// This does not *save* the registry. For that, you probably want Repo.Update
        /// </summary>
        internal static void UpdateRegistry(Uri repo, Registry registry, KSP ksp, IUser user, Boolean clear = true)
        {
            // Use this opportunity to also update the build mappings... kind of hacky
            ServiceLocator.Container.Resolve<IKspBuildMap>().Refresh();

            log.InfoFormat("Downloading {0}", repo);

            string repo_file = String.Empty;
            try
            {
                repo_file = Net.Download(repo);
            }
            catch (System.Net.WebException)
            {
                user.RaiseMessage("Connection to {0} could not be established.", repo);
                return;
            }

            // Clear our list of known modules.
            if (clear)
            {
                registry.ClearAvailable();
            }

            // Check the filetype.
            FileType type = FileIdentifier.IdentifyFile(repo_file);

            switch (type)
            {
            case FileType.TarGz:
                UpdateRegistryFromTarGz (repo_file, registry);
                break;
            case FileType.Zip:
                UpdateRegistryFromZip (repo_file, registry);
                break;
            default:
                break;
            }

            List<CkanModule> metadataChanges = new List<CkanModule>();

            foreach (var installedModule in registry.InstalledModules)
            {
                var identifier = installedModule.identifier;

                var installedVersion = registry.InstalledVersion(identifier);
                if (!(registry.available_modules.ContainsKey(identifier)))
                {
                    log.InfoFormat("UpdateRegistry, module {0}, version {1} not in repository ({2})", identifier, installedVersion, repo);
                    continue;
                }

                if (!registry.available_modules[identifier].module_version.ContainsKey(installedVersion))
                {
                    continue;
                }

                // if the mod is installed and the metadata is different we have to reinstall it
                var metadata = registry.available_modules[identifier].module_version[installedVersion];

                var oldMetadata = registry.InstalledModule(identifier).Module;

                bool same = true;
                if ((metadata.install == null) != (oldMetadata.install == null) ||
                    (metadata.install != null && metadata.install.Length != oldMetadata.install.Length))
                {
                    same = false;
                }
                else
                {
                    if(metadata.install != null)
                    for (int i = 0; i < metadata.install.Length; i++)
                    {
                        if (metadata.install[i].file != oldMetadata.install[i].file)
                        {
                            same = false;
                            break;
                        }

                        if (metadata.install[i].install_to != oldMetadata.install[i].install_to)
                        {
                            same = false;
                            break;
                        }

                        if (metadata.install[i].@as != oldMetadata.install[i].@as)
                        {
                            same = false;
                            break;
                        }

                        if ((metadata.install[i].filter == null) != (oldMetadata.install[i].filter == null))
                        {
                            same = false;
                            break;
                        }

                        if(metadata.install[i].filter != null)
                        if (!metadata.install[i].filter.SequenceEqual(oldMetadata.install[i].filter))
                        {
                            same = false;
                            break;
                        }

                        if ((metadata.install[i].filter_regexp == null) != (oldMetadata.install[i].filter_regexp == null))
                        {
                            same = false;
                            break;
                        }

                        if(metadata.install[i].filter_regexp != null)
                        if (!metadata.install[i].filter_regexp.SequenceEqual(oldMetadata.install[i].filter_regexp))
                        {
                            same = false;
                            break;
                        }
                    }
                }

                if (!RelationshipsAreEquivalent(metadata.conflicts, oldMetadata.conflicts))
                    same = false;

                if (!RelationshipsAreEquivalent(metadata.depends, oldMetadata.depends))
                    same = false;

                if (!RelationshipsAreEquivalent(metadata.recommends, oldMetadata.recommends))
                    same = false;

                if (metadata.provides != oldMetadata.provides)
                {
                    if (metadata.provides == null || oldMetadata.provides == null)
                        same = false;
                    else if (!metadata.provides.OrderBy(i => i).SequenceEqual(oldMetadata.provides.OrderBy(i => i)))
                        same = false;
                }

                if (!same)
                {
                    metadataChanges.Add(registry.available_modules[identifier].module_version[installedVersion]);
                }
            }

            if (metadataChanges.Any())
            {
                var sb = new StringBuilder();

                for (var i = 0; i < metadataChanges.Count; i++)
                {
                    var 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, 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 (var changedIdentifier in metadataChanges.Select(i => i.identifier))
                    {
                        try
                        {
                            installer.Upgrade(
                                new[] { changedIdentifier },
                                new NetAsyncModulesDownloader(new NullUser()),
                                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);
                        }
                    }
                }
            }

            // Remove our downloaded meta-data now we've processed it.
            // Seems weird to do this as part of a transaction, but Net.Download uses them, so let's be consistent.
            file_transaction.Delete(repo_file);
        }
示例#54
0
        /// <summary>
        ///     Register the supplied module as having been installed, thereby keeping
        ///     track of its metadata and files.
        /// </summary>
        public void RegisterModule(Module mod, IEnumerable<string> absolute_files, KSP ksp)
        {
            SealionTransaction();

            // But we also want to keep track of all its files.
            // We start by checking to see if any files are owned by another mod,
            // if so, we abort with a list of errors.

            var inconsistencies = new List<string>();

            // We always work with relative files, so let's get some!
            IEnumerable<string> relative_files = absolute_files.Select(x => ksp.ToRelativeGameDir(x));

            // For now, it's always cool if a module wants to register a directory.
            // We have to flip back to absolute paths to actually test this.
            foreach (string file in relative_files.Where(file => !Directory.Exists(ksp.ToAbsoluteGameDir(file))))
            {
                string owner;
                if (installed_files.TryGetValue(file, out owner))
                {
                    // Woah! Registering an already owned file? Not cool!
                    // (Although if it existed, we should have thrown a kraken well before this.)
                    inconsistencies.Add(
                        string.Format("{0} wishes to install {1}, but this file is registered to {2}",
                            mod.identifier, file, owner
                            ));
                }
            }

            if (inconsistencies.Count > 0)
            {
                throw new InconsistentKraken(inconsistencies);
            }

            // If everything is fine, then we copy our files across. By not doing this
            // in the loop above, we make sure we don't have a half-registered module
            // when we throw our exceptinon.

            // This *will* result in us overwriting who owns a directory, and that's cool,
            // directories aren't really owned like files are. However because each mod maintains
            // its own list of files, we'll remove directories when the last mod using them
            // is uninstalled.
            foreach (string file in relative_files)
            {
                installed_files[file] = mod.identifier;
            }

            // Finally, register our module proper.
            var installed = new InstalledModule(ksp, mod, relative_files);
            installed_modules.Add(mod.identifier, installed);
        }
示例#55
0
        public void Dispose()
        {
            var registry = RegistryManager.Instance(KSP);
            if (registry != null)
            {
                registry.Dispose();
            }

            var i = 6;
            while (--i < 0)
            {
                try
                {
                    // Now that the lockfile is closed, we can remove the directory
                    Directory.Delete(_disposableDir, true);
                }
                catch (IOException)
                {
                    // We silently catch this exception because we expect failures
                }
                catch (Exception ex)
                {
                    throw new AssertionException(_failureMessage, ex);
                }
            }

            //proceed to dispose our wrapped KSP object
            KSP.Dispose();
            KSP = null;
        }
示例#56
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;
        }
示例#57
0
 public void SetCurrentInstanceByPath(string name)
 {
     // TODO: Should we disallow this if _CurrentInstance is already set?
     CurrentInstance = new KSP(name, User);
 }
示例#58
0
        /// <summary>
        /// Ensures all files for this module have relative paths.
        /// Called when upgrading registry versions. Should be a no-op
        /// if called on newer registries.</summary>
        public void Renormalise(KSP ksp)
        {
            var normalised_installed_files = new Dictionary<string, InstalledModuleFile>();

            foreach (KeyValuePair<string, InstalledModuleFile> tuple in installed_files)
            {
                string path = KSPPathUtils.NormalizePath(tuple.Key);

                if (Path.IsPathRooted(path))
                {
                    path = ksp.ToRelativeGameDir(path);
                }

                normalised_installed_files[path] = tuple.Value;
            }

            installed_files = normalised_installed_files;
        }
示例#59
0
 /// <summary>
 /// Adds a KSP instance to registry.
 /// Returns the resulting KSP object.
 /// </summary>
 public KSP AddInstance(string name, KSP ksp_instance)
 {
     instances.Add(name, ksp_instance);
     Win32Registry.SetRegistryToInstances(instances, AutoStartInstance);
     return ksp_instance;
 }