コード例 #1
0
ファイル: load_order.py プロジェクト: Skarfoze/wrye-bash
def refresh_lo(cached=False, cached_active=True):
    """Refresh cached_lord, reverting if locked to the saved one. If any of
    cached or cached_active are True, we will keep the cached values for
    those except if _game_handle.***_changed() respective methods return
    True. In the case of timestamp games, cached is effectively always False,
    as load_order_changed returns True - that's not slow, as getting the load
    order just involves getting mtime info from modInfos cache. This last one
    **must be up to date** for correct load order/active validation."""
    if _lords_pickle is None: __load_pickled_load_orders()  # once only
    if locked and _saved_load_orders:
        saved = _saved_load_orders[_current_list_index].lord  # type: LoadOrder
        lord, acti = _game_handle.set_load_order(  # make sure saved lo is valid
            list(saved.loadOrder),
            list(saved.activeOrdered),
            dry_run=True)
        fixed = LoadOrder(lord, acti)
        if fixed != saved:
            bolt.deprint(u'Saved load order is no longer valid: %s'
                         u'\nCorrected to %s' % (saved, fixed))
        saved = fixed
    else:
        saved = None
    if cached_lord is not __empty:
        lo = cached_lord.loadOrder if (
            cached and not _game_handle.load_order_changed()) else None
        active = cached_lord.activeOrdered if (
            cached_active and not _game_handle.active_changed()) else None
    else:
        active = lo = None
    _update_cache(lo, active)
    if locked and saved is not None:
        if cached_lord.loadOrder != saved.loadOrder:
            save_lo(saved.loadOrder, saved.activeOrdered)
            global warn_locked
            warn_locked = True
コード例 #2
0
ファイル: env.py プロジェクト: Skarfoze/wrye-bash
def shellDeletePass(node, parent=None):
    """Delete tmp dirs/files - ignore errors (but log them)."""
    if node.exists():
        try:
            shellDelete(node, parent=parent, confirm=False, recycle=False)
        except OSError:
            deprint(u"Error deleting %s:" % node, traceback=True)
コード例 #3
0
ファイル: load_order.py プロジェクト: Skarfoze/wrye-bash
def _update_cache(lord=None, acti_sorted=None, __index_move=0):
    """
    :type lord: tuple[bolt.Path] | list[bolt.Path]
    :type acti_sorted: tuple[bolt.Path] | list[bolt.Path]
    """
    global cached_lord
    try:
        fix_lo = games.FixInfo()
        lord, acti_sorted = _game_handle.get_load_order(
            lord, acti_sorted, fix_lo)
        fix_lo.lo_deprint()
        cached_lord = LoadOrder(lord, acti_sorted)
    except Exception:
        bolt.deprint(u'Error updating load_order cache')
        cached_lord = __empty
        raise
    finally:
        if cached_lord is not __empty:
            global _current_list_index
            if _current_list_index < 0 or (
                    not __index_move and cached_lord !=
                    _saved_load_orders[_current_list_index].lord):
                # either getting or setting, plant the new load order in
                _current_list_index += 1
                _new_entry()
            elif __index_move:  # attempted to undo/redo
                _current_list_index += __index_move
                target = _saved_load_orders[_current_list_index].lord
                if target != cached_lord:  # we partially redid/undid
                    # put it after (redo) or before (undo) the target
                    _current_list_index += int(math.copysign(1, __index_move))
                    # list[-1:-1] won't do what we want
                    _current_list_index = max(0, _current_list_index)
                    _new_entry()
コード例 #4
0
def compressionSettings(archive_path, blockSize, isSolid):
    archiveType = writeExts.get(archive_path.cext)
    if not archiveType:
        #--Always fall back to using the defaultExt
        archive_path = GPath(archive_path.sbody + defaultExt).tail
        archiveType = writeExts.get(archive_path.cext)
    if archive_path.cext in noSolidExts:  # zip
        solid = u''
    else:
        if isSolid:
            if blockSize:
                solid = u'-ms=on -ms=%dm' % blockSize
            else:
                solid = u'-ms=on'
        else:
            solid = u'-ms=off'
    userArgs = bass.inisettings['7zExtraCompressionArguments']
    if userArgs:
        if reSolid.search(userArgs):
            if not solid:  # zip, will blow if ms=XXX is passed in
                old = userArgs
                userArgs = reSolid.sub(u'', userArgs).strip()
                if old != userArgs:
                    deprint(archive_path.s +
                            u': 7zExtraCompressionArguments ini option "' +
                            old + u'" -> "' + userArgs + u'"')
            solid = userArgs
        else:
            solid += userArgs
    return archive_path, archiveType, solid
コード例 #5
0
def _import_bush_and_set_game(opts, bashIni):
    import bush
    bolt.deprint(u'Searching for game to manage:')
    ret = bush.detect_and_set_game(opts.oblivionPath, bashIni)
    if ret is not None:  # None == success
        if len(ret) == 0:
            msgtext = _(
                u"Wrye Bash could not find a game to manage. Please use "
                u"-o command line argument to specify the game path")
        else:
            msgtext = _(
                u"Wrye Bash could not determine which game to manage.  "
                u"The following games have been detected, please select "
                u"one to manage.")
            msgtext += u'\n\n'
            msgtext += _(
                u'To prevent this message in the future, use the -o command '
                u'line argument or the bash.ini to specify the game path')
        retCode = _wxSelectGame(ret, msgtext)
        if retCode is None:
            bolt.deprint(u"No games were found or Selected. Aborting.")
            return None
        # Add the game to the command line, so we use it if we restart
        bass.update_sys_argv(['--oblivionPath', bush.game_path(retCode).s])
        bush.detect_and_set_game(opts.oblivionPath, bashIni, retCode)
    # Force Python mode if CBash can't work with this game
    bolt.CBash = opts.mode if bush.game.esp.canCBash else 1  #1 = python mode...
    return bush.game
コード例 #6
0
ファイル: env.py プロジェクト: Skarfoze/wrye-bash
def _get_app_links(apps_dir):
    """Scan Mopy/Apps folder for shortcuts (.lnk files). Windows only !

    :param apps_dir: the absolute Path to Mopy/Apps folder
    :return: a dictionary of shortcut properties tuples keyed by the
    absolute Path of the Apps/.lnk shortcut
    """
    if win32client is None: return {}
    links = {}
    try:
        sh = win32client.Dispatch('WScript.Shell')
        for lnk in apps_dir.list():
            lnk = apps_dir.join(lnk)
            if lnk.cext == u'.lnk' and lnk.isfile():
                shortcut = sh.CreateShortCut(lnk.s)
                description = shortcut.Description
                if not description:
                    description = u' '.join((_(u'Launch'), lnk.sbody))
                links[lnk] = (
                    shortcut.TargetPath,
                    shortcut.IconLocation,
                    # shortcut.WorkingDirectory, shortcut.Arguments,
                    description)
    except:
        deprint(_(u"Error initializing links:"), traceback=True)
    return links
コード例 #7
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
 def _fix_load_order(self, lord, fix_lo):
     super(TimestampGame, self)._fix_load_order(lord, fix_lo)
     if fix_lo is not None and fix_lo.lo_added:
         # should not occur, except if undoing
         bolt.deprint(u'Incomplete load order passed in to set_load_order. '
                      u'Missing: ' + u', '.join(x.s
                                                for x in fix_lo.lo_added))
         lord[:] = self.__calculate_mtime_order(mods=lord)
コード例 #8
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
    def _fix_load_order(self, lord, fix_lo):
        """Fix inconsistencies between given loadorder and actually installed
        mod files as well as impossible load orders. We need a refreshed
        bosh.modInfos reflecting the contents of Data/.

        Called in get_load_order() to fix a newly fetched LO and in
        set_load_order() to check if a load order passed in is valid. Needs
        rethinking as save load and active should be an atomic operation -
        leads to hacks (like the _selected parameter).
        :type lord: list[bolt.Path]
        """
        if fix_lo is None: fix_lo = FixInfo()  # discard fix info
        old_lord = lord[:]
        # game's master might be out of place (if using timestamps for load
        # ordering or a manually edited loadorder.txt) so move it up
        master_name = self.master_path
        master_dex = 0
        try:
            master_dex = lord.index(master_name)
        except ValueError:
            if not master_name in self.mod_infos:
                raise exception.BoltError(u'%s is missing or corrupted' %
                                          master_name)
            fix_lo.lo_added = {master_name}
        if master_dex > 0:
            bolt.deprint(u'%s has index %d (must be 0)' %
                         (master_name, master_dex))
            lord.remove(master_name)
            lord.insert(0, master_name)
            fix_lo.lo_reordered = True
        # below do not apply to timestamp method (on getting it)
        loadorder_set = set(lord)
        mods_set = set(self.mod_infos.keys())
        fix_lo.lo_removed = loadorder_set - mods_set  # may remove corrupted mods
        # present in text file, we are supposed to take care of that
        fix_lo.lo_added |= mods_set - loadorder_set
        # Remove non existent plugins from load order
        lord[:] = [x for x in lord if x not in fix_lo.lo_removed]
        # See if any esm files are loaded below an esp and reorder as necessary
        ol = lord[:]
        lord.sort(key=lambda m: not self.in_master_block(self.mod_infos[m]))
        fix_lo.lo_reordered |= ol != lord
        # Append new plugins to load order
        index_first_esp = self._index_of_first_esp(lord)
        for mod in fix_lo.lo_added:
            if self.in_master_block(self.mod_infos[mod]):
                if not mod == master_name:
                    lord.insert(index_first_esp, mod)
                else:
                    lord.insert(0, master_name)
                    bolt.deprint(u'%s inserted to Load order' % master_name)
                index_first_esp += 1
            else:
                lord.append(mod)
        # end textfile get
        fix_lo.lo_duplicates = self._check_for_duplicates(lord)
        fix_lo.lo_reordered |= self._order_fixed(lord)
        if fix_lo.lo_reordered: fix_lo.lo_reordered = old_lord, lord
コード例 #9
0
ファイル: env.py プロジェクト: Skarfoze/wrye-bash
def __get_error_info():
    try:
        sErrorInfo = u'\n'.join(u'  %s: %s' % (key, envDefs[key])
                                for key in sorted(envDefs))
    except UnicodeDecodeError:
        deprint(u'Error decoding _os.environ', traceback=True)
        sErrorInfo = u'\n'.join(u'  %s: %s' % (key, decode(envDefs[key]))
                                for key in sorted(envDefs))
    return sErrorInfo
コード例 #10
0
 def SetActivePlugins(self,plugins):
     plugins = [_enc(x) for x in plugins]
     num = len(plugins)
     plugins = list_of_strings(plugins)
     try:
         _Clo_set_active_plugins(self._DB, plugins, num)
     except LibloError as ex: # plugins.txt not written !
         deprint(u'lo_set_active_plugins failed:', traceback=True)
         raise BoltError(ex.msg), None, sys.exc_info()[2]
コード例 #11
0
 def SetLoadOrder(self, plugins):
     plugins = [_enc(x) for x in plugins]
     num = len(plugins)
     plugins = list_of_strings(plugins)
     try:
         _Clo_set_load_order(self._DB, plugins, num)
     except LibloError as ex: # must notify the user that lo was not set
         deprint(u'lo_set_load_order failed:', traceback=True)
         raise BoltError(ex.msg), None, sys.exc_info()[2]
コード例 #12
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
 def _fetch_active_plugins(self):
     acti, _lo = self._parse_plugins_txt()
     if self.master_path in acti:
         acti.remove(self.master_path)
         self._write_plugins_txt(acti, acti)
         bolt.deprint(u'Removed %s from %s' %
                      (self.master_path, self.plugins_txt_path))
     acti.insert(0, self.master_path)
     return acti
コード例 #13
0
 def restore_ini(self):
     if self._timestamped_old is self.__unset:
         return  # we did not move bash.ini
     if self._timestamped_old is not None:
         bolt.deprint(u'Restoring bash.ini')
         GPath(self._timestamped_old).copyTo(u'bash.ini')
     elif self._bash_ini_path:
         # remove bash.ini as it is the one from the backup
         bolt.GPath(u'bash.ini').remove()
コード例 #14
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
 def parse_ccc_file(cls):
     _ccc_path = bass.dirs['app'].join(cls._ccc_filename)
     try:
         with open(_ccc_path.s, 'r') as ins:
             lines = map(bolt.GPath, map(str.strip, ins.readlines()))
             cls.must_be_active_if_present += tuple(lines)
     except (OSError, IOError) as e:
         if e.errno != errno.ENOENT:
             bolt.deprint(u'Failed to open %s' % _ccc_path, traceback=True)
コード例 #15
0
 def GetActivePlugins(self):
     plugins = c_char_p_p()
     num = c_size_t()
     try:
         _Clo_get_active_plugins(self._DB, byref(plugins), byref(num))
     except LibloError as err:
         if err.code != LIBLO_WARN_INVALID_LIST: raise
         deprint(u'lo_get_active_plugins WARN_INVALID_LIST:',
                 traceback=True)
     return map(GPath, plugins[:num.value])
コード例 #16
0
 def backup_settings(self, balt_):
     deprint(u'')
     deprint(_(u'BACKUP BASH SETTINGS: ') + self._backup_dest_file.s)
     temp_settings_backup_dir = bolt.Path.tempDir()
     try:
         self._backup_settings(temp_settings_backup_dir)
         self._backup_success(balt_)
     finally:
         if temp_settings_backup_dir:
             temp_settings_backup_dir.rmtree(safety=u'WryeBash_')
コード例 #17
0
ファイル: bush.py プロジェクト: LORDofDOOM/wrye-bash
def __setGame(foundGames_, name, msg):
    """Set bush game globals - raise if they are already set."""
    global gamePath, game, foundGames
    if game is not None: raise BoltError(u'Trying to reset the game')
    foundGames = foundGames_
    gamePath = foundGames_[name]
    game = _allGames[name]
    deprint(msg % {'gamename': name}, gamePath)
    # Unload the other modules from the cache
    for i in _allGames.keys():
        if i != name: del _allGames[i]
    game.init()
コード例 #18
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
 def warn_lo(self):
     if not self.lo_changed(): return
     added = _pl(self.lo_added) or u'None'
     removed = _pl(self.lo_removed) or u'None'
     duplicates = (u'lo_duplicates(%s), ' % _pl(self.lo_duplicates)) \
         if self.lo_duplicates else u''
     reordered = u'(No)' if not self.lo_reordered else _pl(
         self.lo_reordered[0], u'from:\n', joint=u'\n') + _pl(
             self.lo_reordered[1], u'\nto:\n', joint=u'\n')
     msg = u'Fixed Load Order: added(%s), removed(%s), %sreordered %s' % (
         added, removed, duplicates, reordered)
     bolt.deprint(msg)
コード例 #19
0
ファイル: bass.py プロジェクト: FelesNoctis/wrye-bash-docedit
def rmTempDir():
    """Remove the current temporary directory, and set the current Temp Dir to
       None - meaning a new one will be generated on getTempDir()"""
    global _tempDir
    if _tempDir is None:
        return
    try:
        _tempDir.rmtree(safety=_tempDir.stail)
    except OSError:
        from bolt import deprint
        deprint(u'Failed to remove %s' % _tempDir, traceback=True)
    _tempDir = None
コード例 #20
0
def __fixActive(acti, lord):
    # filter plugins not present in modInfos - this will disable corrupted too!
    actiFiltered = [x for x in acti
                    if x in bosh.modInfos]  #preserve acti order
    _removed = set(acti) - set(actiFiltered)
    if _removed:  # take note as we may need to rewrite plugins txt
        msg = u'Those mods were present in plugins.txt but were not present ' \
              u'in Data/ directory or were corrupted: ' + _pl(_removed) + u'\n'
        bosh.modInfos.selectedBad = _removed
    else:
        msg = u''
    # again is below needed ? Apparently not with liblo 4 (acti is [Skyrim.esm,
    # Update.esm] on empty plugins.txt) - Keep it cause eventually (when liblo
    # is made to return actual contents of plugins.txt at all times) I may
    # need to correct this here
    addUpdateEsm = False
    if bush.game.fsName == 'Skyrim':
        skyrim = bolt.GPath(u'Skyrim.esm')
        if not skyrim in actiFiltered:
            actiFiltered.insert(0, skyrim)
            msg += u'Skyrim.esm not present in active mods' + u'\n'
        updateEsm = bolt.GPath(u'Update.esm')
        if updateEsm in lord and not updateEsm in actiFiltered:
            msg += (u'Update.esm not present in plugins.txt while present in '
                    u'Data folder') + u'\n'
            addUpdateEsm = True
    dexDict = {mod: index for index, mod in enumerate(lord)}
    # not needed for oblivion, for skyrim liblo will write plugins.txt in order
    # STILL restore for skyrim to warn on LO change
    if usingTxtFile():
        actiSorted = actiFiltered[:]
        actiSorted.sort(key=dexDict.__getitem__)  # all present in lord
        if actiFiltered != actiSorted:  # were mods in an order that disagrees with lord ?
            msg += (u'Plugins.txt order of plugins (%s) differs from current '
                    u'load order (%s)') % (_pl(actiFiltered), _pl(actiSorted))
    else:
        actiSorted = sorted(actiFiltered, key=dexDict.__getitem__)
    if addUpdateEsm:  # insert after the last master (as does liblo)
        actiSorted.insert(_indexFirstEsp(actiSorted), updateEsm)
    # check if we have more than 256 active mods
    if len(actiSorted) > 255:
        msg += u'Plugins.txt contains more than 255 plugins - the following ' \
               u'plugins will be deactivated: '
        bosh.modInfos.selectedExtra = actiSorted[255:]
        msg += _pl(bosh.modInfos.selectedExtra)
    acti[:] = actiSorted[:255]  # chop off extra
    if msg:
        ##: Notify user - maybe backup previous plugin txt ?
        bolt.deprint(u'Invalid Plugin txt corrected' + u'\n' + msg)
        SetActivePlugins(acti, lord, _fixed=True)
        return True  # changes, saved
    return False  # no changes, not saved
コード例 #21
0
ファイル: bush.py プロジェクト: Skarfoze/wrye-bash
def __setGame(name, msg):
    """Set bush game globals - raise if they are already set."""
    global game, game_mod
    if game is not None: raise BoltError(u'Trying to reset the game')
    gamePath = foundGames[name]
    game = _allGames[name](gamePath)
    game_mod = _allModules[name]
    deprint(msg % {'gamename': name}, gamePath)
    # Unload the other modules from the cache
    for i in _allGames.keys():
        if i != name:
            del _allGames[i]
            del _allModules[i]  # the keys should be the same
    game.init()
コード例 #22
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
def _parse_plugins_txt_(path, mod_infos, _star):
    """Parse loadorder.txt and plugins.txt files with or without stars.

    Return two lists which are identical except when _star is True, whereupon
    the second list is the load order while the first the active plugins. In
    all other cases use the first list, which is either the list of active
    mods (when parsing plugins.txt) or the load order (when parsing
    loadorder.txt)
    :type path: bolt.Path
    :type mod_infos: bosh.ModInfos
    :type _star: bool
    :rtype: (list[bolt.Path], list[bolt.Path])
    """
    with path.open('r') as ins:
        #--Load Files
        active, modnames = [], []
        for line in ins:
            # Oblivion/Skyrim saves the plugins.txt file in cp1252 format
            # It wont accept filenames in any other encoding
            modname = _re_plugins_txt_comment.sub('', line).strip()
            if not modname: continue
            # use raw strings below
            is_active = not _star or modname.startswith('*')
            if _star and is_active: modname = modname[1:]
            try:
                test = bolt.decode(modname, encoding='cp1252')
            except UnicodeError:
                bolt.deprint(u'%r failed to properly decode' % modname)
                continue
            if bolt.GPath(test) not in mod_infos:
                # The automatic encoding detector could have returned
                # an encoding it actually wasn't.  Luckily, we
                # have a way to double check: modInfos.data
                for encoding in bolt.encodingOrder:
                    try:
                        test2 = unicode(modname, encoding)
                        if bolt.GPath(test2) not in mod_infos:
                            continue
                        modname = bolt.GPath(test2)
                        break
                    except UnicodeError:
                        pass
                else:
                    modname = bolt.GPath(test)
            else:
                modname = bolt.GPath(test)
            modnames.append(modname)
            if is_active: active.append(modname)
    return active, modnames
コード例 #23
0
ファイル: load_order.py プロジェクト: LORDofDOOM/wrye-bash
def __fixActive(acti, lord):
    # filter plugins not present in modInfos - this will disable corrupted too!
    actiFiltered = [x for x in acti if x in bosh.modInfos] #preserve acti order
    _removed = set(acti) - set(actiFiltered)
    if _removed: # take note as we may need to rewrite plugins txt
        msg = u'Those mods were present in plugins.txt but were not present ' \
              u'in Data/ directory or were corrupted: ' + _pl(_removed) + u'\n'
        bosh.modInfos.selectedBad = _removed
    else: msg = u''
    # again is below needed ? Apparently not with liblo 4 (acti is [Skyrim.esm,
    # Update.esm] on empty plugins.txt) - Keep it cause eventually (when liblo
    # is made to return actual contents of plugins.txt at all times) I may
    # need to correct this here
    addUpdateEsm = False
    if bush.game.fsName == 'Skyrim':
        skyrim = bolt.GPath(u'Skyrim.esm')
        if not skyrim in actiFiltered:
            actiFiltered.insert(0, skyrim)
            msg += u'Skyrim.esm not present in active mods' + u'\n'
        updateEsm = bolt.GPath(u'Update.esm')
        if updateEsm in lord and not updateEsm in actiFiltered:
            msg += (u'Update.esm not present in plugins.txt while present in '
                    u'Data folder') + u'\n'
            addUpdateEsm = True
    dexDict = {mod:index for index, mod in enumerate(lord)}
    # not needed for oblivion, for skyrim liblo will write plugins.txt in order
    # STILL restore for skyrim to warn on LO change
    if usingTxtFile():
        actiSorted = actiFiltered[:]
        actiSorted.sort(key=dexDict.__getitem__) # all present in lord
        if actiFiltered != actiSorted: # were mods in an order that disagrees with lord ?
            msg += (u'Plugins.txt order of plugins (%s) differs from current '
                   u'load order (%s)') % (_pl(actiFiltered), _pl(actiSorted))
    else: actiSorted = sorted(actiFiltered, key=dexDict.__getitem__)
    if addUpdateEsm: # insert after the last master (as does liblo)
        actiSorted.insert(_indexFirstEsp(actiSorted), updateEsm)
    # check if we have more than 256 active mods
    if len(actiSorted) > 255:
        msg += u'Plugins.txt contains more than 255 plugins - the following ' \
               u'plugins will be deactivated: '
        bosh.modInfos.selectedExtra = actiSorted[255:]
        msg += _pl(bosh.modInfos.selectedExtra)
    acti[:] = actiSorted[:255] # chop off extra
    if msg:
        ##: Notify user - maybe backup previous plugin txt ?
        bolt.deprint(u'Invalid Plugin txt corrected' + u'\n' + msg)
        SetActivePlugins(acti, lord, _fixed=True)
        return True # changes, saved
    return False # no changes, not saved
コード例 #24
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
def __write_plugins(out, lord, active, _star):
    def asterisk(active_set=frozenset(active)):
        return '*' if _star and (mod in active_set) else ''

    for mod in (_star and lord) or active:
        # Ok, this seems to work for Oblivion, but not Skyrim
        # Skyrim seems to refuse to have any non-cp1252 named file in
        # plugins.txt.  Even activating through the SkyrimLauncher
        # doesn't work.
        try:
            out.write(asterisk() + bolt.encode(mod.s, firstEncoding='cp1252'))
            out.write('\r\n')
        except UnicodeEncodeError:
            bolt.deprint(mod.s + u' failed to properly encode and was not '
                         u'included in plugins.txt')
コード例 #25
0
def _updateCache(lord=None, actiSorted=None):
    global _current_lo
    try:
        if lord is None:
            lord = _getLoFromLiblo()
            _setLoTxtModTime()
        # got a valid load order - now to active...
        if actiSorted is None:
            actiSorted = _getActiveFromLiblo(lord)
            _setPluginsTxtModTime()
        _current_lo = LoadOrder(lord, actiSorted)
    except Exception:
        bolt.deprint('Error updating load_order cache from liblo')
        _current_lo = __empty
        raise
コード例 #26
0
def assure_single_instance(instance):
    """Ascertain that only one instance of Wrye Bash is running.

    If this is the second instance running, then display an error message and
    exit. 'instance' must stay alive for the whole execution of the program.
    See: https://wxpython.org/Phoenix/docs/html/wx.SingleInstanceChecker.html

    :type instance: wx.SingleInstanceChecker"""
    if instance.IsAnotherRunning():
        bolt.deprint(u'Only one instance of Wrye Bash can run. Exiting.')
        msg = _(u'Only one instance of Wrye Bash can run.')
        _app = _wx.App(False)
        with _wx.MessageDialog(None, msg, _(u'Wrye Bash'), _wx.OK) as dialog:
            dialog.ShowModal()
        sys.exit(1)
コード例 #27
0
ファイル: load_order.py プロジェクト: LORDofDOOM/wrye-bash
def _updateCache(lord=None, actiSorted=None):
    global _current_lo
    try:
        if lord is None:
            lord = _getLoFromLiblo()
            _setLoTxtModTime()
        # got a valid load order - now to active...
        if actiSorted is None:
            actiSorted = _getActiveFromLiblo(lord)
            _setPluginsTxtModTime()
        _current_lo = LoadOrder(lord, actiSorted)
    except Exception:
        bolt.deprint('Error updating load_order cache from liblo')
        _current_lo = __empty
        raise
コード例 #28
0
 def _backup_settings(self, temp_dir):
     # copy all files to ~tmp backup dir
     for tpath, fpath in self.files.iteritems():
         deprint(tpath.s + u' <-- ' + fpath.s)
         fpath.copyTo(temp_dir.join(tpath))
     # dump the version info and file listing
     with temp_dir.join(u'backup.dat').open('wb') as out:
         # Bash version the settings were saved with, if this is newer
         # than the installed settings version, do not allow restore
         cPickle.dump(bass.settings['bash.version'], out, -1)
         # app version, if this doesn't match the installed settings
         # version, warn the user on restore
         cPickle.dump(AppVersion, out, -1)
     # create the backup archive in 7z format WITH solid compression
     # may raise StateError
     backup_dir, dest7z = self._backup_dest_file.head, self._backup_dest_file.tail
     command = archives.compressCommand(dest7z, backup_dir, temp_dir)
     archives.compress7z(command, backup_dir, dest7z, temp_dir)
     bass.settings['bash.backupPath'] = backup_dir
コード例 #29
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
 def _fetch_load_order(self, cached_load_order, cached_active):
     """Read data from plugins.txt file. If plugins.txt does not exist
     create it. Discards information read if cached is passed in."""
     exists = self.plugins_txt_path.exists()
     active, lo = self._parse_modfile(
         self.plugins_txt_path)  # empty if not exists
     lo, active = (lo if cached_load_order is None else cached_load_order,
                   active if cached_active is None else cached_active)
     to_drop = []
     for rem in self.remove_from_plugins_txt:
         if rem in active or rem in lo:
             to_drop.append(rem)
     lo, active = self._readd_in_lists(lo, active)
     if not exists or to_drop:
         msg = u'Created %s' if not exists else (
             u'Removed ' + u' ,'.join(map(unicode, to_drop)) + u' from %s')
         self._persist_load_order(lo, active)
         bolt.deprint(msg % self.plugins_txt_path)
     return lo, active
コード例 #30
0
ファイル: barb.py プロジェクト: Mewfii/Wrye-Flash-FalloutNV
    def Apply(self):
        if not self.PromptFile(): return

        deprint('')
        deprint('BACKUP BASH SETTINGS: ' + self.dir.join(self.archive).s)

        # copy all files to ~tmp backup dir
        for tpath, fpath in self.files.iteritems():
            deprint(tpath.s + ' <-- ' + fpath.s)
            fpath.copyTo(self.tmp.join(tpath))
        #end for

        # dump the version info and file listing
        out = self.tmp.join('backup.dat').open('wb')
        cPickle.dump(
            self.verDat, out, -1
        )  #data version, if this doesn't match the installed data version, do not allow restore
        cPickle.dump(
            self.verApp, out, -1
        )  #app version, if this doesn't match the installer app version, warn the user on restore
        out.close()

        # create the backup archive
        try:
            pack7z(self.dir.join(self.archive), self.tmp)
        except StateError, e:
            raise
            return
コード例 #31
0
ファイル: env.py プロジェクト: Skarfoze/wrye-bash
def _get_default_app_icon(idex, target):
    # Use the default icon for that file type
    if winreg is None:
        return u'not\\a\\path', idex
    try:
        if target.isdir():
            global __folderIcon
            if not __folderIcon:
                # Special handling of the Folder icon
                folderkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, u'Folder')
                iconkey = winreg.OpenKey(folderkey, u'DefaultIcon')
                filedata = winreg.EnumValue(iconkey, 0)
                # filedata == ('', u'%SystemRoot%\\System32\\shell32.dll,3', 2)
                filedata = filedata[1]
                __folderIcon = filedata
            else:
                filedata = __folderIcon
        else:
            file_association = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT,
                                                 target.cext)
            pathKey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT,
                                     u'%s\\DefaultIcon' % file_association)
            filedata = winreg.EnumValue(pathKey, 0)[1]
            winreg.CloseKey(pathKey)
        if _os.path.isabs(filedata) and _os.path.isfile(filedata):
            icon = filedata
        else:
            icon, idex = filedata.split(u',')
            icon = _os.path.expandvars(icon)
        if not _os.path.isabs(icon):
            # Get the correct path to the dll
            for dir_ in _os.environ['PATH'].split(u';'):
                test = _os.path.join(dir_, icon)
                if _os.path.exists(test):
                    icon = test
                    break
    except:  # TODO(ut) comment the code above - what exception can I get here?
        deprint(_(u'Error finding icon for %s:') % target.s, traceback=True)
        icon = u'not\\a\\path'
    return icon, idex
コード例 #32
0
ファイル: bush.py プロジェクト: Skarfoze/wrye-bash
def _supportedGames(useCache=True):
    """Set games supported by Bash and return their paths from the registry."""
    if useCache and _allGames: return _registryGames.copy()
    # rebuilt cache
    _allGames.clear()
    _registryGames.clear()
    _fsName_display.clear()
    _display_fsName.clear()
    import pkgutil
    # Detect the known games
    for importer, modname, ispkg in pkgutil.iter_modules(game_init.__path__):
        if not ispkg: continue  # game support modules are packages
        # Equivalent of "from game import <modname>"
        try:
            module = __import__('game', globals(), locals(), [modname], -1)
            submod = getattr(module, modname)
            game_type = submod.GAME_TYPE
            _allModules[game_type.fsName] = submod
            _allGames[game_type.fsName] = game_type
            _fsName_display[game_type.fsName] = game_type.displayName
            #--Get this game's install path
            game_path = get_registry_game_path(game_type)
        except (ImportError, AttributeError):
            deprint(u'Error in game support module:', modname, traceback=True)
            continue
        if game_path: _registryGames[game_type.fsName] = game_path
        del module
    # unload some modules, _supportedGames is meant to run once
    del pkgutil
    _display_fsName.update({v: k for k, v in _fsName_display.iteritems()})
    deprint(u'Detected the following supported games via Windows Registry:')
    for foundName in _registryGames:
        deprint(u' %s:' % foundName, _registryGames[foundName])
    return _registryGames.copy()
コード例 #33
0
ファイル: games.py プロジェクト: Skarfoze/wrye-bash
 def _fixed_order_plugins(self):
     """Return the semi fixed plugins after pinning them in correct order by
     timestamping them."""
     # get existing
     add = [self.master_path]
     add.extend(x for x in self.must_be_active_if_present
                if x in self.mod_infos)
     # rewrite mtimes
     master_mtime = self.mod_infos[self.master_path].mtime
     update = bolt.GPath(u'Update.esm')
     for dlc in add[1:]:
         if dlc == update:
             master_mtime = self.mod_infos[update].mtime
         else:
             master_mtime += self.__dlc_spacing
             dlc_mtime = self.mod_infos[dlc].mtime
             if dlc_mtime != master_mtime:
                 self.mod_infos[dlc].setmtime(master_mtime)
                 bolt.deprint(u'Restamped %s  from %s to %s' %
                              (dlc, bolt.formatDate(dlc_mtime),
                               bolt.formatDate(master_mtime)))
     return add
コード例 #34
0
ファイル: bush.py プロジェクト: LORDofDOOM/wrye-bash
def setGame(gameName, workingDir=u'', bashIni=None):
    foundGames_, name = _detectGames(workingDir, bashIni)
    gameName = gameName.lower()
    #--See if the specified game is one that was found
    if gameName in foundGames_:
        # The game specified was found
        __setGame(foundGames_, gameName,
                 u'Specified game "%(gamename)s" was found:')
        return None
    #--Specified game not found, or game was not specified,
    #  so use the game found via workingDir or the cwd
    else:
        if gameName == u'':
            deprint(u'No preferred game specified.')
        else:
            deprint(u'Specified game "%s" was not found.' % gameName)
        if name in foundGames_:
            # Game specified was not found, or no game was specified
            # try the game returned by detectGames()
            __setGame(foundGames_, name, u' Using %(gamename)s game:')
            return None
    # No match found return the list of possible games
    return foundGames_.keys() # may be empty if nothing is found in registry
コード例 #35
0
ファイル: bush.py プロジェクト: LHBDev/wrye-bash
def setGame(gameName,workingDir=u''):
    global gamePath
    global game
    foundGames,allGames,name = detectGames(workingDir)
    gameName = gameName.lower()
    #--See if the specified game is one that was found
    if gameName in foundGames:
        # The game specified was found
        gamePath = foundGames[gameName]
        game = allGames[gameName]
        deprint(u'Specified game "%s" was found:' % gameName, gamePath)
        # Unload the other modules
        for i in allGames.keys():
            if i != gameName:
                del allGames[i]
        game.init()
        return False
    #--Specified game not found, or game was not specified,
    #  so use the game found via workingDir or the cwd
    else:
        if gameName == u'':
            deprint(u'No preferred game specified.')
        else:
            deprint(u'Specified game "%s" was not found.' % gameName)
        if name in foundGames:
            # Game specified was not found, or no game was specified
            # try the game based on Wrye Bash install location
            gamePath = foundGames[name]
            deprint(u' Using %s game:' % name, gamePath)
            game = allGames[name]
            # Unload the other modules
            for i in allGames.keys():
                if i != name:
                    del allGames[i]
            game.init()
            return False
    # No match found return the list of possible games
    # Unload all the modules
    del allGames
    return foundGames.keys()
コード例 #36
0
ファイル: bush.py プロジェクト: LORDofDOOM/wrye-bash
def _supportedGames(useCache=True):
    """Set games supported by Bash and return their paths from the registry."""
    if useCache and _allGames: return _registryGames.copy()
    # rebuilt cache
    _allGames.clear()
    _registryGames.clear()
    import pkgutil
    import game as _game
    # Detect the known games
    for importer,modname,ispkg in pkgutil.iter_modules(_game.__path__):
        if not ispkg: continue # game support modules are packages
        # Equivalent of "from game import <modname>"
        try:
            module = __import__('game',globals(),locals(),[modname],-1)
        except ImportError:
            deprint(u'Error in game support module:', modname, traceback=True)
            continue
        submod = getattr(module,modname)
        if not hasattr(submod,'fsName') or not hasattr(submod,'exe'): continue
        _allGames[submod.fsName.lower()] = submod
        #--Get this game's install path
        if not winreg:
            del module
            continue
        for hkey in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
            for wow6432 in (u'',u'Wow6432Node\\'):
                for (subkey,entry) in submod.regInstallKeys:
                    try:
                        key = winreg.OpenKey(hkey,
                            u'Software\\%s%s' % (wow6432,subkey))
                        value = winreg.QueryValueEx(key,entry)
                    except: continue
                    if value[1] != winreg.REG_SZ: continue
                    installPath = GPath(value[0])
                    if not installPath.exists(): continue
                    exePath = installPath.join(submod.exe)
                    if not exePath.exists(): continue
                    _registryGames[submod.fsName.lower()] = installPath
        del module
    # unload some modules, _supportedGames is meant to run once
    del pkgutil
    del _game
    deprint(u'Detected the following supported games via Windows Registry:')
    for foundName in _registryGames:
        deprint(u' %s:' % foundName, _registryGames[foundName])
    return _registryGames.copy()
コード例 #37
0
ファイル: barb.py プロジェクト: CobaltBlues/wrye-bash
    def Apply(self):
        if not self.PromptFile(): return

        deprint(u'')
        deprint(_(u'BACKUP BASH SETTINGS: ') + self.dir.join(self.archive).s)

        # copy all files to ~tmp backup dir
        for tpath,fpath in self.files.iteritems():
            deprint(tpath.s + u' <-- ' + fpath.s)
            fpath.copyTo(self.tmp.join(tpath))
        #end for

        # dump the version info and file listing
        with self.tmp.join(u'backup.dat').open('wb') as out:
            cPickle.dump(self.verDat, out, -1) #data version, if this doesn't match the installed data version, do not allow restore
            cPickle.dump(self.verApp, out, -1) #app version, if this doesn't match the installer app version, warn the user on restore

        # create the backup archive
        try:
            pack7z(self.dir.join(self.archive),self.tmp)
        except StateError, e:
            raise
コード例 #38
0
ファイル: barb.py プロジェクト: LORDofDOOM/wrye-bash
 def Apply(self):
     if not self.PromptFile(): return
     deprint(u'')
     deprint(_(u'BACKUP BASH SETTINGS: ') + self.dir.join(self.archive).s)
     with BusyCursor():
         # copy all files to ~tmp backup dir
         for tpath,fpath in self.files.iteritems():
             deprint(tpath.s + u' <-- ' + fpath.s)
             fpath.copyTo(self.tmp.join(tpath))
         # dump the version info and file listing
         with self.tmp.join(u'backup.dat').open('wb') as out:
             # data version, if this doesn't match the installed data
             # version, do not allow restore
             cPickle.dump(self.verDat, out, -1)
             # app version, if this doesn't match the installer app version,
             # warn the user on restore
             cPickle.dump(self.verApp, out, -1)
         # create the backup archive in 7z format WITH solid compression
         # may raise StateError
         command = bosh.compressCommand(self.archive, self.dir, self.tmp)
         bolt.compress7z(command, self.dir, self.archive, self.tmp)
         bosh.settings['bash.backupPath'] = self.dir
     self.InfoSuccess()
コード例 #39
0
ファイル: windows.py プロジェクト: LORDofDOOM/wrye-bash
#       GNU Lesser General Public License for more details.
#
#       You should have received a copy of the GNU Lesser General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.
#

from ctypes import *
from bolt import deprint
import subprocess

try:
    from ctypes.wintypes import MAX_PATH
except ValueError:
    deprint("ctypes.wintypes import failure", traceback=True)
    try:
        MAX_PATH = int(subprocess.check_output(['getconf', 'PATH_MAX', '/']))
    except (ValueError, subprocess.CalledProcessError, OSError):
        deprint('calling getconf failed - error:', traceback=True)
        MAX_PATH = 4096
try:
    import win32gui
except ImportError: # linux
    win32gui = None
    raise
from bass import winreg

BUTTONID_OFFSET                 = 1000

#---Internal Flags. Leave these alone unless you know what you're doing---#
コード例 #40
0
ファイル: bush.py プロジェクト: LHBDev/wrye-bash
def detectGames(workingDir=u''):
    """Detect which supported games are intalled.
       - First, read the windows registry, checking for the install keys for the
         games.
       - Next, check for a valid game at "workingDir"
       - Finally, also look one directory up from the cwd."""
    #--First: Find all supported games via the registry
    import pkgutil
    import game as _game
    foundGames = {}
    allGames = {}
    # Detect the known games
    for importer,modname,ispkg in pkgutil.iter_modules(_game.__path__):
        # Equivalent of "from game import <modname>"
        try:
            module = __import__('game',globals(),locals(),[modname],-1)
        except:
            deprint(u'Error in game support file:', modname, traceback=True)
            continue
        submod = getattr(module,modname)
        if not hasattr(submod,'name') or not hasattr(submod,'exe'): continue
        allGames[submod.name.lower()] = submod
        #--Get this game's install path
        for hkey in (_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE):
            for wow6432 in (u'',u'Wow6432Node\\'):
                for (subkey,entry) in submod.regInstallKeys:
                    try:
                        key = _winreg.OpenKey(hkey,
                            u'Software\\%s%s' % (wow6432,subkey))
                        value = _winreg.QueryValueEx(key,entry)
                    except: continue
                    if value[1] != _winreg.REG_SZ: continue
                    installPath = GPath(value[0])
                    if not installPath.exists(): continue
                    exePath = installPath.join(submod.exe)
                    if not exePath.exists(): continue
                    foundGames[submod.name.lower()] = installPath
        del module
    # unload some modules
    del pkgutil
    del _game
    deprint(u'Detected the following supported games via Windows Registry:')
    for foundName in foundGames:
        deprint(u' %s:' % foundName, foundGames[foundName])
    #--Second: Detect what game is installed on directory up from Mopy
    path = Path.getcwd()
    if path.cs[-4:] == u'mopy':
        path = GPath(path.s[:-5])
    installPaths = [path]
    #--Third: Detect what game is installed at the specified "workingDir"
    if workingDir != u'':
        path = GPath(workingDir)
        if not path.isabs():
            path = Path.getcwd().join(path)
        installPaths.insert(0,path)
    deprint(u'Detecting games via relative path and the -o argument:')
    name = None
    for path in installPaths:
        _name = path.tail.cs
        if _name in allGames:
            # We have a config for that game
            deprint(u' %s:' % _name, path)
            foundGames[_name] = path
            name = _name
            break
        else:
            # Folder name wasn't found, try looking by exe name
            for file in path.list():
                for _name in allGames:
                    if allGames[_name].exe == file:
                        # Must be this game
                        deprint(u' %s:' % _name, path)
                        name = _name
                        foundGames[name] = path
                        break
                else:
                    continue
                break
            else:
                continue
            break
    return foundGames,allGames,name
コード例 #41
0
ファイル: barb.py プロジェクト: CobaltBlues/wrye-bash
    def Apply(self):
        if self.ErrorConflict():
            self.WarnFailed()
            return
        elif not self.PromptMismatch():
            raise BackupCancelled()

        deprint(u'')
        deprint(_(u'RESTORE BASH SETTINGS: ') + self.dir.join(self.archive).s)

        # reinitialize bosh.dirs using the backup copy of bash.ini if it exists
        game = bush.game.name
        tmpBash = self.tmp.join(game+u'\\Mopy\\bash.ini')
        opts, args = bash.opts, bash.extra

        bash.SetUserPath(tmpBash.s,opts.userPath)

        bashIni = bash.GetBashIni(tmpBash.s)
        bosh.initBosh(opts.personalPath,opts.localAppDataPath,opts.oblivionPath)

        # restore all the settings files
        restore_paths = (
                (dirs['mopy'],                      game+u'\\Mopy'),
                (dirs['mods'].join(u'Bash'),        game+u'\\Data\\Bash'),
                (dirs['mods'].join(u'Bash Patches'),game+u'\\Data\\Bash Patches'),
                (dirs['mods'].join(u'Docs'),        game+u'\\Data\\Docs'),
                (dirs['mods'].join(u'INI Tweaks'),  game+u'\\Data\\INI Tweaks'),
                (dirs['modsBash'],                  game+u' Mods\\Bash Mod Data'),
                (dirs['modsBash'].join(u'INI Data'),game+u' Mods\\Bash Mod Data\\INI Data'),
                (dirs['bainData'],                  game+u' Mods\\Bash Installers\\Bash'),
                (dirs['userApp'],                   u'LocalAppData\\'+game),
                (dirs['saveBase'],                  u'My Games\\'+game),
                )
        if 293 >= self.verApp:
            # restore from old data paths
            restore_paths += (
                (dirs['l10n'],                      game+u'\\Data'),)
            if self.restore_images:
                restore_paths += (
                    (dirs['images'],                game+u'\\Mopy\\images'),)
        else:
            restore_paths += (
                (dirs['l10n'],                      game+u'\\bash\\l10n'),)
            if self.restore_images:
                restore_paths += (
                    (dirs['images'],                game+u'\\Mopy\\bash\\images'),)
        for fpath, tpath in restore_paths:
            path = self.tmp.join(tpath)
            if path.exists():
                for name in path.list():
                    if path.join(name).isfile():
                        deprint(GPath(tpath).join(name).s + u' --> ' + fpath.join(name).s)
                        path.join(name).copyTo(fpath.join(name))

        #restore savegame profile settings
        tpath = GPath(u'My Games\\'+game+u'\\Saves')
        fpath = dirs['saveBase'].join(u'Saves')
        path = self.tmp.join(tpath)
        if path.exists():
            for root, folders, files in path.walk(True,None,True):
                root = GPath(u'.'+root.s)
                for name in files:
                    deprint(tpath.join(root,name).s + u' --> ' + fpath.join(root,name).s)
                    path.join(root,name).copyTo(fpath.join(root,name))

        # tell the user the restore is compete and warn about restart
        self.WarnRestart()
        if basher.bashFrame: # should always exist
            basher.bashFrame.Destroy()
コード例 #42
0
ファイル: bush.py プロジェクト: LORDofDOOM/wrye-bash
def _detectGames(cli_path=u'',bashIni=None):
    """Detect which supported games are installed.

    - If Bash supports no games raise.
    - For each game supported by Bash check for a supported game executable
    in the following dirs, in decreasing precedence:
       - the path provided by the -o cli argument if any
       - the sOblivionPath Bash Ini entry if present
       - one directory up from Mopy
    If a game exe is found update the path to this game and return immediately.
    Return (foundGames, name)
      - foundGames: a dict from supported games to their paths (the path will
      default to the windows registry path to the game, if present)
      - name: the game found in the first installDir or None if no game was
      found - a 'suggestion' for a game to use (if no game is specified/found
      via -g argument).
    """
    #--Find all supported games and all games in the windows registry
    foundGames_ = _supportedGames() # sets _allGames if not set
    if not _allGames: # if allGames is empty something goes badly wrong
        raise BoltError(_(u'No game support modules found in Mopy/bash/game.'))
    # check in order of precedence the -o argument, the ini and our parent dir
    installPaths = collections.OrderedDict() #key->(path, found msg, error msg)
    #--First: path specified via the -o command line argument
    if cli_path != u'':
        path = GPath(cli_path)
        if not path.isabs():
            path = Path.getcwd().join(path)
        installPaths['cmd'] = (path,
            _(u'Set game mode to %(gamename)s specified via -o argument') +
              u': ',
            _(u'No known game in the path specified via -o argument: ' +
              u'%(path)s'))
    #--Second: check if sOblivionPath is specified in the ini
    if bashIni and bashIni.has_option(u'General', u'sOblivionPath') \
               and not bashIni.get(u'General', u'sOblivionPath') == u'.':
        path = GPath(bashIni.get(u'General', u'sOblivionPath').strip())
        if not path.isabs():
            path = Path.getcwd().join(path)
        installPaths['ini'] = (path,
            _(u'Set game mode to %(gamename)s based on sOblivionPath setting '
              u'in bash.ini') + u': ',
            _(u'No known game in the path specified in sOblivionPath ini '
              u'setting: %(path)s'))
    #--Third: Detect what game is installed one directory up from Mopy
    path = Path.getcwd()
    if path.cs[-4:] == u'mopy':
        path = GPath(path.s[:-5])
        if not path.isabs():
            path = Path.getcwd().join(path)
        installPaths['upMopy'] = (path,
            _(u'Set game mode to %(gamename)s found in parent directory of'
              u' Mopy') + u': ',
            _(u'No known game in parent directory of Mopy: %(path)s'))
    #--Detect
    deprint(u'Detecting games via the -o argument, bash.ini and relative path:')
    # iterate installPaths in insert order ('cmd', 'ini', 'upMopy')
    for path, foundMsg, errorMsg in installPaths.itervalues():
        for name, module in _allGames.items():
            if path.join(module.exe).exists():
                # Must be this game
                deprint(foundMsg % {'gamename':name}, path)
                foundGames_[name] = path
                return foundGames_, name
        # no game exe in this install path - print error message
        deprint(errorMsg % {'path': path.s})
    # no game found in installPaths - foundGames are the ones from the registry
    return foundGames_, None
コード例 #43
0
ファイル: load_order.py プロジェクト: LORDofDOOM/wrye-bash
    # Move the new plugins.txt and loadorder.txt here for use
    move = newPath.join(u'plugins.txt')
    if move.exists():
        move.copyTo(_plugins_txt_path)
        _plugins_txt_path.mtime = time.time() # copy will not change mtime, bad
    move = newPath.join(u'loadorder.txt')
    if move.exists():
        move.copyTo(_loadorder_txt_path)
        _loadorder_txt_path.mtime = time.time()#update mtime to trigger refresh

#----------------------------------------------------------------------REFACTOR
_liblo_handle, _liblo_error = _liblo.Init(bosh.dirs['compiled'].s)
# That didn't work - Wrye Bash isn't installed correctly
if not _liblo.liblo:
    raise bolt.BoltError(u'The libloadorder API could not be loaded.')
bolt.deprint(u'Using libloadorder API version:', _liblo.version)

_liblo_handle = _liblo_handle(bosh.dirs['app'].s, bush.game.fsName,
                              bosh.dirs['userApp'].s)
if bush.game.fsName == u'Oblivion' and bosh.dirs['mods'].join(
        u'Nehrim.esm').isfile():
    _liblo_handle.SetGameMaster(u'Nehrim.esm')

if bosh.dirs['saveBase'] == bosh.dirs['app']:
#--If using the game directory as rather than the appdata dir.
    _dir = bosh.dirs['app']
else:
    _dir = bosh.dirs['userApp']
_plugins_txt_path = _dir.join(u'plugins.txt')
_loadorder_txt_path = _dir.join(u'loadorder.txt')
mtimePlugins = 0
コード例 #44
0
ファイル: load_order.py プロジェクト: LORDofDOOM/wrye-bash
def __fixLoadOrder(lord, _selected=None):
    """HACK: Fix inconsistencies between given loadorder and actually installed
    mod files as well as impossible load orders - save the fixed order via
    liblo.

    Called in _getLoFromLiblo() to fix a newly fetched LO and in
    SaveLoadOrder() to check if a load order passed in is valid. Needs
    rethinking as save load and active should be an atomic operation -
    complicated by the fact that liblo does not support this. As a consequence
    a lot of hacks are needed (like the _selected parameter).
    """
    oldLord = lord[:] ### print
    # game's master might be out of place (if using timestamps for load
    # ordering or a manually edited loadorder.txt) so move it up
    masterName = bosh.modInfos.masterName
    masterDex = lord.index(masterName)
    if masterDex > 0:
        bolt.deprint(u'%s in %d position' % (masterName, masterDex))
        lord.remove(masterName)
        lord.insert(0, masterName)
        _reordered = True
    else: _reordered = False
    loadOrder = set(lord)
    modFiles = set(bosh.modInfos.keys())
    _removedFiles = loadOrder - modFiles # may remove corrupted mods returned
    # from liblo (text file), we are supposed to take care of that
    _addedFiles = modFiles - loadOrder
    # Remove non existent plugins from load order
    lord[:] = [x for x in lord if x not in _removedFiles]
    indexFirstEsp = _indexFirstEsp(lord)
    # Check to see if any esm files are loaded below an esp and reorder as necessary
    for mod in lord[indexFirstEsp:]: # SEEMS NOT NEEDED, liblo does this
        if mod in bosh.modInfos and bosh.modInfos[mod].isEsm():
            lord.remove(mod)
            lord.insert(indexFirstEsp, mod)
            indexFirstEsp += 1
            _reordered = True
    # Append new plugins to load order
    for mod in _addedFiles:
        if bosh.modInfos[mod].isEsm():
            lord.insert(indexFirstEsp, mod)
            indexFirstEsp += 1
        else: lord.append(mod)
    if _addedFiles and not usingTxtFile():
        lord = bosh.modInfos.calculateLO(mods=lord)
    # Save changes if necessary
    if _removedFiles or _addedFiles or _reordered:
        if _removedFiles or _reordered: # must fix the active too
            # If _selected is not None we come from SaveLoadOrder which needs
            # to save _selected too - so fix this list instead of
            # _current_lo.activeOrdered. If fixed and saved, empty it so we do
            # not resave it. If selected was empty to begin with we need extra
            # hacks (wasEmpty in SaveLoadOrder)
            if _selected is None:
                if _current_lo is not __empty: # else we are on first refresh
                    _selected = list(_current_lo.activeOrdered)
            if _selected is not None and __fixActive(_selected, lord):
                _selected[:] = [] # avoid resaving
        bolt.deprint(u'Fixed Load Order: added(%s), removed(%s), reordered(%s)'
             % (_pl(_addedFiles) or u'None', _pl(_removedFiles) or u'None',
             u'No' if not _reordered else _pl(oldLord, u'from:\n') +
                                          _pl(lord, u'\nto:\n')))
        SaveLoadOrder(lord, _fixed=True)
        return True # changes, saved
    return False # no changes, not saved