def __init__(self, settings_file, fsName): self._backup_dest_file = settings_file # absolute path to dest 7z file self.files = {} for (bash_dir, tmpdir), setting_files in \ _init_settings_files(fsName).iteritems(): if not setting_files: # we have to backup everything in there setting_files = bash_dir.list() tmp_dir = GPath(tmpdir) for name in setting_files: fpath = bash_dir.join(name) if fpath.exists(): self.files[tmp_dir.join(name)] = fpath # backup save profile settings savedir = GPath(u'My Games').join(fsName) profiles = [u''] + initialization.getLocalSaveDirs() for profile in profiles: pluginsTxt = (u'Saves', profile, u'plugins.txt') loadorderTxt = (u'Saves', profile, u'loadorder.txt') for txt in (pluginsTxt, loadorderTxt): tpath = savedir.join(*txt) fpath = dirs['saveBase'].join(*txt) if fpath.exists(): self.files[tpath] = fpath table = (u'Saves', profile, u'Bash', u'Table.dat') tpath = savedir.join(*table) fpath = dirs['saveBase'].join(*table) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def getJava(): """Locate javaw.exe to launch jars from Bash.""" if _os.name == 'posix': import subprocess java_bin_path = '' try: java_bin_path = subprocess.check_output('command -v java', shell=True).rstrip('\n') except subprocess.CalledProcessError: pass # what happens when java doesn't exist? return GPath(java_bin_path) try: java_home = GPath(_os.environ['JAVA_HOME']) java = java_home.join('bin', u'javaw.exe') if java.exists(): return java except KeyError: # no JAVA_HOME pass win = GPath(_os.environ['SYSTEMROOT']) # Default location: Windows\System32\javaw.exe java = win.join(u'system32', u'javaw.exe') if not java.exists(): # 1st possibility: # - Bash is running as 32-bit # - The only Java installed is 64-bit # Because Bash is 32-bit, Windows\System32 redirects to # Windows\SysWOW64. So look in the ACTUAL System32 folder # by using Windows\SysNative java = win.join(u'sysnative', u'javaw.exe') if not java.exists(): # 2nd possibility # - Bash is running as 64-bit # - The only Java installed is 32-bit # So javaw.exe would actually be in Windows\SysWOW64 java = win.join(u'syswow64', u'javaw.exe') return java
def renameArchives(root=r"C:\Program Files\Bethesda Softworks\Fallout 3\Downloads"): """Renames TesSource archive files to sort a little better. E.g., change 12345-2.23-My Wicked Mod-TESSource.zip to My Wicked Mod 2.23.zip.""" reTesSource = re.compile(r"^\d{4}-(\d[^-]*)-(.+)-TESSource.(zip|rar|7z|ace|exe)$", re.I) reTesSourceNV = re.compile(r"^\d{4}-(.+)-TESSource.(zip|rar|7z|ace|exe)$", re.I) reTesSource3 = re.compile(r"^(.+)-\d+-TESSource.(zip|rar|7z|ace|exe|esp)$", re.I) reBracketNum = re.compile(r"\[1\]") for (dirPath, dirNames, fileNames) in os.walk(root): dirPath = GPath(dirPath) for name in fileNames: path = dirPath.join(name) maTesSource = reTesSource.match(name.s) maTesSource3 = reTesSource3.match(name.s) maTesSourceNV = reTesSourceNV.match(name.s) if maTesSource: newName = "%s %s.%s" % maTesSource.group(2, 1, 3) elif maTesSourceNV: newName = "%s.%s" % maTesSourceNV.group(1, 2) elif maTesSource3: newName = "%s.%s" % maTesSource3.group(1, 2) else: newName = name newName = reBracketNum.sub("", newName) if newName != name: newPath = os.path.join(dirPath, newName) print newName.s path.moveTo(newPath)
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()
def get_registry_path(subkey, entry, exe): """Check registry for a path to a program.""" if not winreg: return None for hkey in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER): for wow6432 in (u'', u'Wow6432Node\\'): try: key = winreg.OpenKey(hkey, u'Software\\%s%s' % (wow6432, subkey)) value = winreg.QueryValueEx(key, entry) except OSError: continue if value[1] != winreg.REG_SZ: continue installPath = GPath(value[0]) if not installPath.exists(): continue exePath = installPath.join(exe) if not exePath.exists(): continue return installPath return None
def _restore_settings(self, fsName): deprint(u'') deprint(_(u'RESTORE BASH SETTINGS: ') + self._settings_file.s) # backup previous Bash ini if it exists old_bash_ini = dirs['mopy'].join(u'bash.ini') self._timestamped_old = u''.join( [old_bash_ini.root.s, u'(', bolt.timestamp(), u').ini']) try: old_bash_ini.moveTo(self._timestamped_old) deprint(u'Existing bash.ini moved to %s' % self._timestamped_old) except StateError: # does not exist self._timestamped_old = None # restore all the settings files restore_paths = _init_settings_files(fsName).keys() for dest_dir, back_path in restore_paths: full_back_path = self._extract_dir.join(back_path) for name in full_back_path.list(): if full_back_path.join(name).isfile(): deprint( GPath(back_path).join(name).s + u' --> ' + dest_dir.join(name).s) full_back_path.join(name).copyTo(dest_dir.join(name)) # restore savegame profile settings back_path = GPath(u'My Games').join(fsName, u'Saves') saves_dir = dirs['saveBase'].join(u'Saves') full_back_path = self._extract_dir.join(back_path) if full_back_path.exists(): for root_dir, folders, files_ in full_back_path.walk( True, None, True): root_dir = GPath(u'.' + root_dir.s) for name in files_: deprint( back_path.join(root_dir, name).s + u' --> ' + saves_dir.join(root_dir, name).s) full_back_path.join(root_dir, name).copyTo( saves_dir.join(root_dir, name))
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
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()
def __init__(self, parent=None, path=None, quit=False, backup_images=None): BaseBackupSettings.__init__(self,parent,path,quit) game = bush.game.name for path, name, tmpdir in ( (dirs['mopy'], u'bash.ini', game+u'\\Mopy'), (dirs['mods'].join(u'Bash'), u'Table', game+u'\\Data\\Bash'), (dirs['mods'].join(u'Docs'), u'Bash Readme Template', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'Bashed Lists', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_sand_small.css', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_teal.css', game+u'\\Data\\Docs'), (dirs['modsBash'], u'Table', game+u' Mods\\Bash Mod Data'), (dirs['modsBash'].join(u'INI Data'),u'Table', game+u' Mods\\Bash Mod Data\\INI Data'), (dirs['bainData'], u'Converters', game+u' Mods\\Bash Installers\\Bash'), (dirs['bainData'], u'Installers', game+u' Mods\\Bash Installers\\Bash'), (dirs['userApp'], u'Profiles', u'LocalAppData\\'+game), (dirs['userApp'], u'bash config', u'LocalAppData\\'+game), (dirs['saveBase'], u'BashProfiles', u'My Games\\'+game), (dirs['saveBase'], u'BashSettings', u'My Games\\'+game), (dirs['saveBase'], u'Messages', u'My Games\\'+game), (dirs['saveBase'], u'ModeBase', u'My Games\\'+game), (dirs['saveBase'], u'People', u'My Games\\'+game), ): tmpdir = GPath(tmpdir) for ext in (u'',u'.dat',u'.pkl',u'.html',u'.txt'): # hack so the above file list can be shorter, could include rogue files but not very likely tpath = tmpdir.join(name+ext) fpath = path.join(name+ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup #end for #end for #backup all files in Mopy\Data, Data\Bash Patches\ and Data\INI Tweaks for path, tmpdir in ( (dirs['l10n'], game+u'\\Mopy\\bash\\l10n'), (dirs['mods'].join(u'Bash Patches'),game+u'\\Data\\Bash Patches'), (dirs['mods'].join(u'INI Tweaks'), game+u'\\Data\\INI Tweaks'), ): tmpdir = GPath(tmpdir) for name in path.list(): if path.join(name).isfile(): self.files[tmpdir.join(name)] = path.join(name) #backup image files if told to if backup_images == 1: #changed images only tmpdir = GPath(game+u'\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): fullname = path.join(name) if fullname.isfile(): changed = True for ver_list in bolt.images_list: if name.s in bolt.images_list[ver_list] and bolt.images_list[ver_list][name.s] == fullname.size: changed = False if changed and not name.s.lower() == u'thumbs.db': self.files[tmpdir.join(name)] = fullname elif backup_images == 2: #all images tmpdir = GPath(game+u'\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): if path.join(name).isfile() and not name.s.lower() == u'thumbs.db': self.files[tmpdir.join(name)] = path.join(name) #backup save profile settings savedir = GPath(u'My Games\\'+game) profiles = [u''] + [x for x in dirs['saveBase'].join(u'Saves').list() if dirs['saveBase'].join(u'Saves',x).isdir() and x != u'bash'] for profile in profiles: tpath = savedir.join(u'Saves',profile,u'plugins.txt') fpath = dirs['saveBase'].join(u'Saves',profile,u'plugins.txt') if fpath.exists(): self.files[tpath] = fpath for ext in (u'.dat',u'.pkl'): tpath = savedir.join(u'Saves',profile,u'Bash',u'Table'+ext) fpath = dirs['saveBase'].join(u'Saves',profile,u'Bash',u'Table'+ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def __init__(self, parent=None, path=None, quit=False, backup_images=None): BaseBackupSettings.__init__(self,parent,path,quit) game, dirs = bush.game.fsName, bosh.dirs for path, name, tmpdir in ( (dirs['mopy'], u'bash.ini', game+u'\\Mopy'), (dirs['mods'].join(u'Bash'), u'Table', game+u'\\Data\\Bash'), (dirs['mods'].join(u'Docs'), u'Bash Readme Template', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'Bashed Lists', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_sand_small.css', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_teal.css', game+u'\\Data\\Docs'), (dirs['modsBash'], u'Table', game+u' Mods\\Bash Mod Data'), (dirs['modsBash'].join(u'INI Data'),u'Table', game+u' Mods\\Bash Mod Data\\INI Data'), (dirs['bainData'], u'Converters', game+u' Mods\\Bash Installers\\Bash'), (dirs['bainData'], u'Installers', game+u' Mods\\Bash Installers\\Bash'), (dirs['userApp'], u'Profiles', u'LocalAppData\\'+game), (dirs['userApp'], u'bash config', u'LocalAppData\\'+game), (dirs['saveBase'], u'BashProfiles', u'My Games\\'+game), (dirs['saveBase'], u'BashSettings', u'My Games\\'+game), (dirs['saveBase'], u'Messages', u'My Games\\'+game), (dirs['saveBase'], u'ModeBase', u'My Games\\'+game), (dirs['saveBase'], u'People', u'My Games\\'+game), ): tmpdir = GPath(tmpdir) for ext in (u'',u'.dat',u'.pkl',u'.html',u'.txt'): # hack so the above file list can be shorter, could include rogue files but not very likely tpath = tmpdir.join(name+ext) fpath = path.join(name+ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup #backup all files in Mopy\Data, Data\Bash Patches\ and Data\INI Tweaks for path, tmpdir in ( (dirs['l10n'], game+u'\\Mopy\\bash\\l10n'), (dirs['mods'].join(u'Bash Patches'),game+u'\\Data\\Bash Patches'), (dirs['mods'].join(u'INI Tweaks'), game+u'\\Data\\INI Tweaks'), ): tmpdir = GPath(tmpdir) for name in path.list(): if path.join(name).isfile(): self.files[tmpdir.join(name)] = path.join(name) #backup image files if told to def _isChanged(abs_path, rel_path): for ver_list in images_list.values(): if ver_list.get(rel_path.s, -1) == abs_path.size: return False return True if backup_images: # 1 is changed images only, 2 is all images onlyChanged = backup_images == 1 tmpdir = GPath(game+u'\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): fullname = path.join(name) if fullname.isfile() and not name.s.lower() == u'thumbs.db' \ and (not onlyChanged or _isChanged(fullname, name)): self.files[tmpdir.join(name)] = fullname #backup save profile settings savedir = GPath(u'My Games\\'+game) profiles = [u''] + bosh.SaveInfos.getLocalSaveDirs() for profile in profiles: pluginsTxt = (u'Saves', profile, u'plugins.txt') loadorderTxt = (u'Saves', profile, u'loadorder.txt') for txt in (pluginsTxt, loadorderTxt): tpath = savedir.join(*txt) fpath = dirs['saveBase'].join(*txt) if fpath.exists(): self.files[tpath] = fpath for ext in (u'.dat', u'.pkl'): table = (u'Saves', profile, u'Bash', u'Table' + ext) tpath = savedir.join(*table) fpath = dirs['saveBase'].join(*table) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def exit(): try: os.close(lockfd) os.remove(pidpath.s) except OSError as e: print e # Cleanup temp installers directory import tempfile tempDir = GPath(tempfile.tempdir) for file in tempDir.list(): if file.cs.startswith(u'wryebash_'): file = tempDir.join(file) try: if file.isdir(): file.rmtree(safety=file.stail) else: file.remove() except: pass if basherImported: from basher import appRestart from basher import uacRestart if appRestart: if not hasattr(sys, 'frozen'): exePath = GPath(sys.executable) sys.argv = [exePath.stail] + sys.argv if u'--restarting' not in sys.argv: sys.argv += [u'--restarting'] #--Assume if we're restarting that they don't want to be # prompted again about UAC if u'--no-uac' not in sys.argv: sys.argv += [u'--no-uac'] def updateArgv(args): if isinstance(args, (list, tuple)): if len(args) > 0 and isinstance(args[0], (list, tuple)): for arg in args: updateArgv(arg) else: found = 0 for i in xrange(len(sys.argv)): if not found and sys.argv[i] == args[0]: found = 1 elif found: if found < len(args): sys.argv[i] = args[found] found += 1 else: break else: sys.argv.extend(args) updateArgv(appRestart) try: if uacRestart: if not hasattr(sys, 'frozen'): sys.argv = sys.argv[1:] import win32api if hasattr(sys, 'frozen'): win32api.ShellExecute( 0, 'runas', sys.argv[0], u' '.join('"%s"' % x for x in sys.argv[1:]), None, True) else: args = u' '.join([u'%s', u'"%s"'][u' ' in x] % x for x in sys.argv) win32api.ShellExecute(0, 'runas', exePath.s, args, None, True) return else: import subprocess if hasattr(sys, 'frozen'): subprocess.Popen(sys.argv, close_fds=bolt.close_fds) else: subprocess.Popen( sys.argv, executable=exePath.s, close_fds=bolt.close_fds ) #close_fds is needed for the one instance checker except Exception as error: print error print u'Error Attempting to Restart Wrye Bash!' print u'cmd line: %s %s' % (exePath.s, sys.argv) print raise
def _detectGames(cli_path=u'', bash_ini_=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'': test_path = GPath(cli_path) if not test_path.isabs(): test_path = Path.getcwd().join(test_path) installPaths['cmd'] = ( test_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 ini_game_path = get_ini_option(bash_ini_, u'sOblivionPath') if ini_game_path and not ini_game_path == u'.': test_path = GPath(ini_game_path.strip()) if not test_path.isabs(): test_path = Path.getcwd().join(test_path) installPaths['ini'] = ( test_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 test_path = Path.getcwd() if test_path.cs[-4:] == u'mopy': test_path = GPath(test_path.s[:-5]) if not test_path.isabs(): test_path = Path.getcwd().join(test_path) installPaths['upMopy'] = ( test_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 test_path, foundMsg, errorMsg in installPaths.itervalues(): for name, info in _allGames.items(): if test_path.join(*info.game_detect_file).exists(): # Must be this game deprint(foundMsg % {'gamename': name}, test_path) foundGames_[name] = test_path return foundGames_, name # no game exe in this install path - print error message deprint(errorMsg % {'path': test_path.s}) # no game found in installPaths - foundGames are the ones from the registry return foundGames_, None
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
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
def __init__(self, parent=None, path=None, quit=False, backup_images=None): BaseBackupSettings.__init__(self, parent, path, quit) for path, name, tmpdir in ( (dirs['mopy'], 'Bash.ini', 'Fallout New Vegas\\Mopy'), (dirs['mods'].join('Bash'), 'Table', 'Fallout New Vegas\\Data\\Bash'), (dirs['mods'].join('Docs'), 'Bash Readme Template', 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('Docs'), 'Bashed Lists', 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('Docs'), 'wtxt_sand_small.css', 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('Docs'), 'wtxt_teal.css', 'Fallout New Vegas\\Data\\Docs'), (dirs['modsBash'], 'Table', 'Fallout New Vegas Mods\\Bash Mod Data'), (dirs['modsBash'].join('INI Data'), 'Table', 'Fallout New Vegas Mods\\Bash Mod Data\\INI Data'), (dirs['installers'].join('Bash'), 'Converters', 'Fallout New Vegas Mods\\Bash Installers\\Bash'), (dirs['installers'].join('Bash'), 'Installers', 'Fallout New Vegas Mods\\Bash Installers\\Bash'), (dirs['userApp'], 'Profiles', 'LocalAppData\\FalloutNV'), (dirs['userApp'], 'bash config', 'LocalAppData\\FalloutNV'), (dirs['saveBase'], 'BashProfiles', 'My Games\\FalloutNV'), (dirs['saveBase'], 'BashSettings', 'My Games\\FalloutNV'), (dirs['saveBase'], 'Messages', 'My Games\\FalloutNV'), (dirs['saveBase'], 'ModeBase', 'My Games\\FalloutNV'), (dirs['saveBase'], 'People', 'My Games\\FalloutNV'), ): tmpdir = GPath(tmpdir) for ext in ( '', '.dat', '.pkl', '.html', '.txt' ): # hack so the above file list can be shorter, could include rogue files but not very likely tpath = tmpdir.join(name + ext) fpath = path.join(name + ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup #end for #end for #backup all files in Mopy\Data, Data\Bash Patches and Data\INI Tweaks for path, tmpdir in ( (dirs['l10n'], 'Fallout New Vegas\\Mopy\\bash\\l10n'), (dirs['mods'].join('Bash Patches'), 'Fallout New Vegas\\Data\\Bash Patches'), (dirs['mods'].join('INI Tweaks'), 'Fallout New Vegas\\Data\\INI Tweaks'), ): tmpdir = GPath(tmpdir) for name in path.list(): if path.join(name).isfile(): self.files[tmpdir.join(name)] = path.join(name) #backup image files if told to if backup_images == 1: #changed images only tmpdir = GPath('Fallout New Vegas\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): fullname = path.join(name) if fullname.isfile(): changed = True for ver_list in bolt.images_list: if name.s in bolt.images_list[ ver_list] and bolt.images_list[ver_list][ name.s] == fullname.size: changed = False if changed and not name.s.lower() == 'thumbs.db': self.files[tmpdir.join(name)] = fullname elif backup_images == 2: #all images tmpdir = GPath('Fallout New Vegas\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): if path.join( name).isfile() and not name.s.lower() == 'thumbs.db': self.files[tmpdir.join(name)] = path.join(name) #backup save profile settings savedir = GPath('My Games\\FalloutNV') profiles = [''] + [ x for x in dirs['saveBase'].join('Saves').list() if dirs['saveBase']. join('Saves', x).isdir() and str(x).lower() != 'bash' ] for profile in profiles: tpath = savedir.join('Saves', profile, 'plugins.txt') fpath = dirs['saveBase'].join('Saves', profile, 'plugins.txt') if fpath.exists(): self.files[tpath] = fpath for ext in ('.dat', '.pkl'): tpath = savedir.join('Saves', profile, 'Bash', 'Table' + ext) fpath = dirs['saveBase'].join('Saves', profile, 'Bash', 'Table' + ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def Apply(self): if self.ErrorConflict(): self.WarnFailed() return elif not self.PromptMismatch(): raise BackupCancelled() return deprint('') deprint('RESTORE BASH SETTINGS: ' + self.dir.join(self.archive).s) # reinitialize bosh.dirs using the backup copy of bash.ini if it exists tmpBash = self.tmp.join('Fallout New Vegas\\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.falloutPath) # restore all the settings files restore_paths = ( (dirs['mopy'], 'Fallout New Vegas\\Mopy'), (dirs['mods'].join('Bash'), 'Fallout New Vegas\\Data\\Bash'), (dirs['mods'].join('Bash Patches'), 'Fallout New Vegas\\Data\\Bash Patches'), (dirs['mods'].join('Docs'), 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('INI Tweaks'), 'Fallout New Vegas\\Data\\INI Tweaks'), (dirs['modsBash'], 'Fallout New Vegas Mods\\Bash Mod Data'), (dirs['modsBash'].join('INI Data'), 'Fallout New Vegas Mods\\Bash Mod Data\\INI Data'), (dirs['installers'].join('Bash'), 'Fallout New Vegas Mods\\Bash Installers\\Bash'), (dirs['userApp'], 'LocalAppData\\FalloutNV'), (dirs['saveBase'], 'My Games\\FalloutNV'), ) if 14 >= self.verApp: # restore from old data paths restore_paths += ((dirs['l10n'], 'Fallout New Vegas\\Data'), ) if self.restore_images: restore_paths += ((dirs['images'], 'Fallout New Vegas\\Mopy\\images'), ) else: restore_paths += ((dirs['l10n'], 'Fallout New Vegas\\bash\\l10n'), ) if self.restore_images: restore_paths += ((dirs['images'], 'Fallout New Vegas\\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 + ' --> ' + fpath.join(name).s) path.join(name).copyTo(fpath.join(name)) #restore savegame profile settings tpath = GPath('My Games\\FalloutNV\\Saves') fpath = dirs['saveBase'].join('Saves') path = self.tmp.join(tpath) if path.exists(): for root, folders, files in path.walk(True, None, True): root = GPath('.' + root.s) for name in files: deprint( tpath.join(root, name).s + ' --> ' + 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()
def exit(): try: os.close(lockfd) os.remove(pidpath.s) except OSError as e: print e # Cleanup temp installers directory import tempfile tempDir = GPath(tempfile.tempdir) for file in tempDir.list(): if file.cs.startswith(u'wryebash_'): file = tempDir.join(file) try: if file.isdir(): file.rmtree(safety=file.stail) else: file.remove() except: pass if basherImported: from basher import appRestart from basher import uacRestart if appRestart: if not hasattr(sys,'frozen'): exePath = GPath(sys.executable) sys.argv = [exePath.stail] + sys.argv if u'--restarting' not in sys.argv: sys.argv += [u'--restarting'] #--Assume if we're restarting that they don't want to be # prompted again about UAC if u'--no-uac' not in sys.argv: sys.argv += [u'--no-uac'] def updateArgv(args): if isinstance(args,(list,tuple)): if len(args) > 0 and isinstance(args[0],(list,tuple)): for arg in args: updateArgv(arg) else: found = 0 for i in xrange(len(sys.argv)): if not found and sys.argv[i] == args[0]: found = 1 elif found: if found < len(args): sys.argv[i] = args[found] found += 1 else: break else: sys.argv.extend(args) updateArgv(appRestart) try: if uacRestart: if not hasattr(sys,'frozen'): sys.argv = sys.argv[1:] import win32api if hasattr(sys,'frozen'): win32api.ShellExecute(0,'runas',sys.argv[0],u' '.join('"%s"' % x for x in sys.argv[1:]),None,True) else: args = u' '.join([u'%s',u'"%s"'][u' ' in x] % x for x in sys.argv) win32api.ShellExecute(0,'runas',exePath.s,args,None,True) return else: import subprocess if hasattr(sys,'frozen'): subprocess.Popen(sys.argv,close_fds=bolt.close_fds) else: subprocess.Popen(sys.argv, executable=exePath.s, close_fds=bolt.close_fds) #close_fds is needed for the one instance checker except Exception as error: print error print u'Error Attempting to Restart Wrye Bash!' print u'cmd line: %s %s' %(exePath.s, sys.argv) print raise