Exemple #1
0
    def finish(self):
        database_cursor = self.database.cursor()

        # variants left in this list must now be deleted
        for row in self.existing_variants.values():
            variant_id = row[2]
            database_cursor.execute("DELETE FROM game_variant WHERE id = ?",
                                    (variant_id, ))

        # games left in this list must now be deleted
        for row in self.existing_games.values():
            game_id = row[2]
            database_cursor.execute("DELETE FROM game WHERE id = ?",
                                    (game_id, ))

        database_cursor.execute(
            "SELECT count(*) FROM game WHERE uuid IS NOT NULL "
            "AND (have IS NULL OR have != (SELECT coalesce(max(have), 0) "
            "FROM game_variant WHERE game_uuid = game.uuid))")
        update_rows = database_cursor.fetchone()[0]
        print(update_rows, "game entries need update for have field")
        if update_rows > 0:
            database_cursor.execute(
                "UPDATE game SET have = (SELECT coalesce(max(have), 0) FROM "
                "game_variant WHERE game_uuid = game.uuid) WHERE uuid IS NOT "
                "NULL AND (have IS NULL OR have != (SELECT coalesce(max("
                "have), 0) FROM game_variant WHERE game_uuid = game.uuid))")
        # FIXME: Remove this line?
        FileDatabase.get_instance().get_last_event_stamps()
        self.file_stamps["database_locker"] = LauncherSettings.get(
            Option.DATABASE_LOCKER)
        self.database.update_last_file_event_stamps(self.file_stamps)
Exemple #2
0
    def __init__(self, database):
        self.database = database
        database_cursor = self.database.cursor()

        database_cursor.execute(
            "SELECT uuid, update_stamp, have, id FROM game "
            "WHERE uuid IS NOT NULL")
        self.existing_games = {}
        for row in database_cursor:
            self.existing_games[row[0]] = row[1], row[2], row[3]
        database_cursor.execute(
            "SELECT uuid, update_stamp, have, id FROM game_variant")
        self.existing_variants = {}
        for row in database_cursor:
            self.existing_variants[row[0]] = row[1], row[2], row[3]

        self.file_stamps = FileDatabase.get_instance().get_last_event_stamps()
        cached_file_stamps = self.database.get_last_file_event_stamps()
        self.added_files = (self.file_stamps["last_file_insert"] !=
                            cached_file_stamps["last_file_insert"])
        self.deleted_files = (self.file_stamps["last_file_delete"] !=
                              cached_file_stamps["last_file_delete"])
        # print(LauncherSettings.get(Option.DATABASE_LOCKER),
        #         cached_file_stamps["database_locker"])
        # assert 0
        if (LauncherSettings.get(Option.DATABASE_LOCKER) !=
                cached_file_stamps["database_locker"]):
            # Assume that files could be deleted or removed...
            if LauncherSettings.get(Option.DATABASE_LOCKER) == "0":
                self.deleted_files = True
            else:
                self.added_files = True
Exemple #3
0
    def build_media_list(self, floppies=False, cds=False, hds=False):
        media_list = []
        added = set()
        for file_item in self.get_file_list():
            name = file_item["name"]
            url = file_item.get("url", "")

            if name.startswith("DH0/"):
                if hds:
                    # p = os.path.join(self.path, "HardDrive")
                    # p = "hd://game/" + self.uuid + "/DH0"
                    p = "file_list://DH0"
                    if p in added:
                        # already added
                        continue
                    added.add(p)
                    # FIXME: hack for now
                    sha1 = self.values.get("dh0_sha1", "")
                    media_list.append((p, sha1))
                else:
                    continue

            sha1 = file_item["sha1"]
            base, ext = os.path.splitext(name)
            ext = ext.lower()

            if hds:
                if ext not in [".zip"]:
                    continue
            elif cds:
                if ext not in [".cue", ".iso"]:
                    continue
                if "(Track" in base:
                    # probably part of a split multi-track cue
                    continue
            elif floppies:
                if ext not in [".adf", ".adz", ".dms", ".ipf"]:
                    continue

            path = ""
            found_sha1 = ""
            if sha1:
                print(sha1)
                file = FileDatabase.get_instance().find_file(sha1=sha1)
                if file:
                    found_sha1 = sha1
                    path = file["path"]
            if url and not path:
                path = url
                found_sha1 = sha1

            if path:
                media_list.append((path, found_sha1))
            else:
                pass
                # return False
                #  FIXME: handle it with a visible error message
                # raise Exception("could not find file " + repr(name))
        return media_list
Exemple #4
0
 def run(self):
     self.defragment(FileDatabase.get_instance(), "Files.sqlite")
     self.stop_check()
     self.defragment(LockerDatabase.instance(), "Locker.sqlite")
     self.stop_check()
     self.defragment(fsgs.get_game_database(), "Amiga.sqlite")
     self.stop_check()
     self.defragment(Database.get_instance(), "Database.sqlite")
    def kickstart_startup_scan(cls):
        if cls._kickstart_scanned:
            return
        cls._kickstart_scanned = True

        print("kickstart_startup_scan")
        kickstarts_dir = FSGSDirectories.get_kickstarts_dir()
        if LauncherSettings.get("kickstarts_dir_mtime"
                                ) == cls.get_dir_mtime_str(kickstarts_dir):
            print("... mtime not changed")
        else:
            file_database = FileDatabase.get_instance()
            print("... database.find_local_roms")
            local_roms = file_database.find_local_roms()
            print("... walk kickstarts_dir")
            for dir_path, dir_names, file_names in os.walk(kickstarts_dir):
                for file_name in file_names:
                    if not file_name.lower().endswith(
                            ".rom") and not file_name.lower().endswith(".bin"):
                        continue
                    path = Paths.join(dir_path, file_name)
                    if path in local_roms:
                        local_roms[path] = None
                        # already exists in database
                        continue
                    print("[startup] adding kickstart", path)
                    ROMManager.add_rom_to_database(path, file_database)
            print(local_roms)
            for path, file_id in local_roms.items():
                if file_id is not None:
                    print("[startup] removing kickstart", path)
                    file_database.delete_file(id=file_id)
            print("... commit")
            file_database.commit()
            LauncherSettings.set("kickstarts_dir_mtime",
                                 cls.get_dir_mtime_str(kickstarts_dir))

        amiga = Amiga.get_model_config("A500")
        for sha1 in amiga["kickstarts"]:
            if fsgs.file.find_by_sha1(sha1=sha1):
                break
        else:
            file_database = FileDatabase.get_instance()
            cls.amiga_forever_kickstart_scan()
            file_database.commit()
Exemple #6
0
 def update_file_database_timestamps(self):
     # This isn't very elegant, but in order to force the game scanner to
     # refresh the game list based on files, we update the stamps in the
     # file database. Also, since we haven't keep track of additions /
     # deletions, we set both stamps for now...
     file_database = FileDatabase.instance()
     file_database.last_file_insert = time.time()
     file_database.last_file_delete = time.time()
     file_database.update_last_event_stamps()
     file_database.commit()
 def scan_dir_for_kickstarts(scan_dir):
     file_database = FileDatabase.get_instance()
     for dir_path, dir_names, file_names in os.walk(scan_dir):
         for file_name in file_names:
             if not file_name.endswith(".rom"):
                 continue
             path = Paths.join(dir_path, file_name)
             if file_database.find_file(path=path):
                 continue
             print("[startup] adding kickstart", path)
             ROMManager.add_rom_to_database(path, file_database)
 def check_sha1(cls, sha1):
     # FIXME: check_sha1 should check with PluginManager directly?
     database = FileDatabase.instance()
     result = database.check_sha1(sha1)
     if not result and is_locker_enabled():
         database = LockerDatabase.instance()
         result = database.check_sha1(sha1)
         # print("check sha1", sha1, "in locker database - result", result)
     # if not result:
     #     result = self.context.get_game_database().find_file_by_sha1(sha1)
     return result
Exemple #9
0
    def scan_fs_uae_files(self, database):
        cursor = database.cursor()
        cursor.execute("SELECT id, path FROM game WHERE path IS NOT NULL")
        config_path_ids = {}
        for row in cursor:
            config_path_ids[database.decode_path(row[1])] = row[0]

        file_database = FileDatabase.get_instance()

        # FIXME: This is not good enough, we want to support multiple
        # extensions when using OpenRetro Launcher at least.
        if Product.base_name == "FS-Fuse":
            extension = ".fs-fuse"
        else:
            extension = ".fs-uae"

        configurations = file_database.find_files(ext=extension)
        for c in configurations:
            if self.stop_check():
                break
            # name = os.path.basename(c["path"])
            # name = c["name"]
            # name = name[:-7]
            # search = name.lower()
            path = c["path"]
            name = os.path.basename(path)
            name, ext = os.path.splitext(name)
            sort_key = name.lower()
            # search = self.create_configuration_search(name)
            name = self.create_configuration_name(name)

            game_id = database.add_configuration(path=path,
                                                 name=name,
                                                 sort_key=sort_key)
            database.update_game_search_terms(game_id,
                                              self.create_search_terms(name))

            print(config_path_ids)
            try:
                del config_path_ids[path]
            except KeyError:
                pass

                # FIXME: try splitting name into name, variant pair, and
                # actually add game_variant for config files as well, where
                # possible

        for id in config_path_ids.values():
            database.delete_game(id=id)
 def find_by_sha1(cls, sha1):
     # FIXME: check_sha1 should check with PluginManager directly?
     database = FileDatabase.instance()
     result = database.find_file(sha1=sha1)["path"]
     if not result:
         path = Downloader.get_cache_path(sha1)
         if os.path.exists(path):
             result = path
     #    result = self.context.get_game_database().find_file_by_sha1(sha1)
     # print("find by sha1", sha1, "in file database - result", result)
     if not result and is_locker_enabled() and not offline_mode():
         database = LockerDatabase.instance()
         if database.check_sha1(sha1):
             result = "locker://" + sha1
         # print("find by sha1", sha1, "in locker database - result",
         # result)
     return result
    def scan(self):
        self.set_status(gettext("Scanning files"), gettext("Scanning files"))
        file_database = FileDatabase.get_instance()
        # database.clear()
        scan_dirs = self.get_scan_dirs()

        if self.purge_other_dirs:
            all_database_file_ids = file_database.get_file_ids()
        else:
            all_database_file_ids = None

        for dir_ in scan_dirs:
            if not os.path.exists(dir_):
                print("[FILES] Scanner: Directory does not exist:", dir_)
                continue
            # this is important to make sure the database is portable across
            # operating systems
            dir_ = Paths.get_real_case(dir_)

            self.database_file_ids = file_database.get_file_hierarchy_ids(dir_)
            if self.purge_other_dirs:
                all_database_file_ids.difference_update(self.database_file_ids)

            self.scan_dir(file_database, dir_)

            print("Remaining files:", self.database_file_ids)
            self.purge_file_ids(self.database_file_ids)

            self.set_status(gettext("Scanning files"),
                            gettext("Committing data..."))
            # update last_file_insert and last_file_delete
            file_database.update_last_event_stamps()
            print("[FILES] FileScanner.scan - committing data")
            file_database.commit()

        if self.purge_other_dirs:
            self.purge_file_ids(all_database_file_ids)

        if self.stop_check():
            file_database.rollback()
        else:
            self.set_status(gettext("Scanning files"),
                            gettext("Committing data..."))
            print("[FILES] FileScanner.scan - committing data")
            file_database.commit()
    def upload_check(self, prefix):
        self.progressed(
            gettext("Finding files eligible for OpenRetro Locker") +
            " ({:0.0%})".format((prefix / 16.0)))
        file_database = FileDatabase.instance()
        cursor = file_database.cursor()
        # FIXME: prefix
        p = "0123456789ABCDEF"[prefix]
        cursor.execute(
            "SELECT DISTINCT sha1 FROM file "
            "WHERE hex(sha1) LIKE ?",
            (p + "%", ),
        )
        string_io = StringIO()
        for row in cursor:
            string_io.write(row[0])
        # print(prefix, len(string_io.getvalue()))
        self.stop_check()

        retry_seconds = 1
        while True:
            try:
                result = self.client.post("/api/locker-upload-check",
                                          data=string_io.getvalue())
            except OGDClient.ForbiddenError:
                raise Task.Failure(
                    gettext("OpenRetro Locker is not enabled for your user. "
                            "It may be available only to a few select beta "
                            "users."))
            except OGDClient.NonRetryableHTTPError as e:
                raise e
            except Exception:
                traceback.print_exc()
                self.progressed(
                    gettext("Re-trying in {0} seconds...").format(
                        retry_seconds))
                for _ in range(retry_seconds):
                    self.stop_check()
                    time.sleep(1.0)
                retry_seconds = min(retry_seconds * 2, 60 * 10)
            else:
                return result
    def copy_roms(self, src, dst):
        count = 0
        if not os.path.isdir(src):
            self.log("{0} is not a directory".format(src))
            return count
        src_file = os.path.join(src, "rom.key")
        if os.path.exists(src_file):
            dst_file = os.path.join(dst, "rom.key")
            self.copy_file(src_file, dst_file)
        for file_name in os.listdir(src):
            name, ext = os.path.splitext(file_name)
            if ext not in [".rom"]:
                continue
            src_file = os.path.join(src, file_name)
            dst_file = os.path.join(dst, file_name)
            self.copy_file(src_file, dst_file)

            database = FileDatabase.get_instance()
            ROMManager.add_rom_to_database(dst_file, database, self.log)
            database.commit()
            count += 1
        return count
Exemple #14
0
    def run_config_or_game(cls):
        gscontext = FSGameSystemContext()
        config_path = None
        archive_path = None
        floppy_image_paths = []
        cdrom_image_paths = []
        config_uuid = None
        floppy_extensions = (".adf", ".ipf", ".dms", ".adz")
        cdrom_extensions = (".cue", ".iso")
        archive_extensions = (".zip", ".lha")

        # FIXME: replace argument "parsing" with use of argparse module
        # at some point

        last_arg = sys.argv[-1]
        file_ext = os.path.splitext(last_arg)[-1].lower()
        if file_ext == ".fs-uae":
            config_path = last_arg
        elif file_ext in archive_extensions:
            archive_path = last_arg
        # elif file_ext in floppy_extensions:
        #     floppy_image_paths = [last_arg]
        elif is_uuid(last_arg):
            config_uuid = last_arg.lower()
        for arg in sys.argv[1:]:
            if not arg.startswith("--"):
                _, ext = os.path.splitext(arg)
                if ext in floppy_extensions:
                    floppy_image_paths.append(arg)
                elif ext in cdrom_extensions:
                    cdrom_image_paths.append(arg)

        if config_path:
            print("[STARTUP] Config path given:", config_path)
            if not os.path.exists(config_path):
                print("[STARTUP] Config path does not exist", file=sys.stderr)
                return True
            LauncherConfig.load_file(config_path)
            gscontext.config.add_from_argv()
            return cls.run_config_directly(gscontext=gscontext)

        if archive_path:
            print("[STARTUP] Archive path given:", archive_path)
            if not os.path.exists(archive_path):
                print("[STARTUP] Archive path does not exist", file=sys.stderr)
                return True
            archive = Archive(os.path.realpath(archive_path))
            archive_name = os.path.basename(archive_path)
            # We want to exclude pure directory entries when checking for
            # archives with only floppies.
            arc_files = [
                x for x in archive.list_files() if not x.endswith("/")
            ]
            if all(
                    map(lambda f: f.lower().endswith(floppy_extensions),
                        arc_files)):
                print("[STARTUP] Archive contains floppy disk images only")
                floppy_image_paths = arc_files
            else:
                if cls.auto_detect_game:
                    # FIXME: Could also do this for floppy file archives.
                    archive_util = ArchiveUtil(archive_path)
                    archive_uuid = archive_util.create_variant_uuid()
                    print(
                        "[STARTUP] Try auto-detecting variant, uuid =",
                        archive_uuid,
                    )
                    if gscontext.load_game_variant(archive_uuid):
                        print("[STARTUP] Auto-detected variant", archive_uuid)
                        print("[STARTUP] Adding archive files to file index")
                        for archive_file in archive.list_files():
                            stream = archive.open(archive_file)
                            data = stream.read()
                            size = len(data)
                            sha1 = hashlib.sha1(data).hexdigest()
                            FileDatabase.add_static_file(archive_file,
                                                         size=size,
                                                         sha1=sha1)
                        gscontext.config.add_from_argv()
                        gscontext.config.set("__config_name", archive_name)
                        LauncherConfig.post_load_values(gscontext.config)
                        return cls.run_config_directly(gscontext=gscontext)

                values = whdload.generate_config_for_archive(archive_path)
                values["hard_drive_0"] = archive_path
                values.update(gscontext.config.config_from_argv())
                # archive_name, archive_ext = os.path.splitext(archive_name)
                values["__config_name"] = archive_name
                return cls.run_config_directly_with_values(values,
                                                           gscontext=gscontext)

        if floppy_image_paths:
            enum_paths = tuple(enumerate(floppy_image_paths))
            values = {}
            values.update(gscontext.config.config_from_argv())
            max_drives = int(values.get("floppy_drive_count", "4"))
            values.update({
                "floppy_drive_{0}".format(k): v
                for k, v in enum_paths[:max_drives]
            })
            values.update(
                {"floppy_image_{0}".format(k): v
                 for k, v in enum_paths[:20]})
            # FIXME: Generate a better config name for save dir?
            values["__config_name"] = "Default"
            return cls.run_config_directly_with_values(values,
                                                       gscontext=gscontext)

        if cdrom_image_paths:
            enum_paths = tuple(enumerate(cdrom_image_paths))
            values = {"amiga_model": "CD32"}
            values.update(gscontext.config.config_from_argv())
            max_drives = int(values.get("cdrom_drive_count", "1"))
            values.update({
                "cdrom_drive_{0}".format(k): v
                for k, v in enum_paths[:max_drives]
            })
            values.update(
                {"cdrom_image_{0}".format(k): v
                 for k, v in enum_paths[:20]})
            # FIXME: Generate a better config name for save dir?
            values["__config_name"] = "Default"
            return cls.run_config_directly_with_values(values,
                                                       gscontext=gscontext)

        if config_uuid:
            print("[STARTUP] Config uuid given:", config_uuid)
            variant_uuid = config_uuid
            # values = gscontext.game.set_from_variant_uuid(variant_uuid)
            if gscontext.load_game_variant(variant_uuid):
                print("[STARTUP] Loaded variant")
            else:
                print("[STARTUP] Could not load variant, try to load game")
                game_uuid = config_uuid
                variant_uuid = gscontext.find_preferred_game_variant(game_uuid)
                print("[STARTUP] Preferred variant:", variant_uuid)
                gscontext.load_game_variant(variant_uuid)
            gscontext.config.add_from_argv()
            LauncherConfig.post_load_values(gscontext.config)
            return cls.run_config_directly(gscontext=gscontext)
Exemple #15
0
    def save_config():
        print("SaveButton.save_config")
        config = get_config(self)
        database = Database.get_instance()

        name = LauncherSettings.get("config_name").strip()
        if not name:
            print("no config_name")
            # FIXME: notify user
            return

        file_name = name + get_extension_for_config(config)
        path = os.path.join(
            FSGSDirectories.get_configurations_dir(), file_name
        )
        with io.open(path, "w", encoding="UTF-8") as f:
            f.write("# FS-UAE configuration saved by FS-UAE Launcher\n")
            f.write(
                "# Last saved: {0}\n".format(
                    datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")
                )
            )
            f.write("\n[fs-uae]\n")
            keys = sorted(fsgs.config.values.keys())
            for key in keys:
                value = config.get(key)
                if key.startswith("__"):
                    continue
                if key in LauncherConfig.no_save_keys_set:
                    continue
                # elif key == "joystick_port_2_mode" and value == "nothing":
                #     continue
                # elif key == "joystick_port_3_mode" and value == "nothing":
                #     continue
                if value == LauncherConfig.default_config.get(key, ""):
                    continue
                if value:
                    f.write("{0} = {1}\n".format(key, value))

        # scanner = ConfigurationScanner()
        # search = ConfigurationScanner.create_configuration_search(name)
        # name = scanner.create_configuration_name(name)
        # print("adding", path)
        # # deleting the path from the database first in case it already exists
        # database.delete_configuration(path=path)
        # database.delete_file(path=path)
        # database.add_file(path=path)
        # database.add_configuration(
        #     path=path, uuid="", name=name, scan=0, search=search)

        file_database = FileDatabase.get_instance()
        scanner = ConfigurationScanner()
        print("[save config] adding config", path)
        file_database.delete_file(path=path)
        with open(path, "rb") as f:
            sha1 = hashlib.sha1(f.read()).hexdigest()
        file_database.add_file(path=path, sha1=sha1)

        game_id = database.add_configuration(
            path=path, name=scanner.create_configuration_name(name)
        )
        database.update_game_search_terms(
            game_id, scanner.create_search_terms(name)
        )

        database.commit()
        file_database.commit()

        LauncherSettings.set("__config_refresh", str(time.time()))
        # Settings.set("config_changed", "0")
        LauncherConfig.set("__changed", "0")
 def purge_file_ids(self, file_ids):
     self.set_status(gettext("Scanning files"),
                     gettext("Purging old entries..."))
     database = FileDatabase.get_instance()
     for file_id in file_ids:
         database.delete_file(id=file_id)
    def config_startup_scan(cls):
        if cls._config_scanned:
            return
        cls._config_scanned = True

        configs_dir = FSGSDirectories.get_configurations_dir()
        print("config_startup_scan", configs_dir)
        print(LauncherSettings.settings)

        settings_mtime = LauncherSettings.get("configurations_dir_mtime")
        dir_mtime = cls.get_dir_mtime_str(configs_dir)
        if settings_mtime == dir_mtime + "+" + str(Database.VERSION):
            print("... mtime not changed", settings_mtime, dir_mtime)
            return

        database = Database.get_instance()
        file_database = FileDatabase.get_instance()

        print("... database.find_local_configurations")
        local_configs = Database.get_instance().find_local_configurations()
        print("... walk configs_dir")
        for dir_path, dir_names, file_names in os.walk(configs_dir):
            for file_name in file_names:
                # if not file_name.endswith(".fs-uae"):
                #     continue
                # FIXME: Move extension list somewhere else
                if not file_name.endswith(
                        ".fs-uae") and not file_name.endswith(".fs-fuse"):
                    continue
                path = Paths.join(dir_path, file_name)
                if path in local_configs:
                    local_configs[path] = None
                    # already exists in database
                    continue
                name, ext = os.path.splitext(file_name)
                # search = ConfigurationScanner.create_configuration_search(
                # name)
                scanner = ConfigurationScanner()
                print("[startup] adding config", path)
                file_database.delete_file(path=path)
                with open(path, "rb") as f:
                    sha1 = hashlib.sha1(f.read()).hexdigest()
                file_database.add_file(path=path, sha1=sha1)

                game_id = database.add_configuration(
                    path=path, name=scanner.create_configuration_name(name))
                database.update_game_search_terms(
                    game_id, scanner.create_search_terms(name))

        for path, config_id in local_configs.items():
            if config_id is not None:
                print("[startup] removing configuration", path)
                database.delete_game(id=config_id)
                file_database.delete_file(path=path)
        print("... commit")
        database.commit()

        LauncherSettings.set(
            "configurations_dir_mtime",
            cls.get_dir_mtime_str(configs_dir) + "+" + str(Database.VERSION),
        )