def newTempDir(): """Generate a new temporary directory name, set it as the current Temp Dir.""" global _tempDir from bolt import Path _tempDir = Path.tempDir() return _tempDir
def shellMakeDirs(dirs, parent=None): if not dirs: return dirs = [dirs] if not isinstance(dirs, (list, tuple, set)) else dirs #--Skip dirs that already exist dirs = [x for x in dirs if not x.exists()] #--Check for dirs that are impossible to create (the drive they are # supposed to be on doesn't exist def _filterUnixPaths(path): return _os.name != 'posix' and not path.s.startswith(u"\\")\ and not path.drive().exists() errorPaths = [d for d in dirs if _filterUnixPaths(d)] if errorPaths: raise NonExistentDriveError(errorPaths) #--Checks complete, start working tempDirs, fromDirs, toDirs = [], [], [] try: for folder in dirs: # Attempt creating the directory via normal methods, only fall back # to shellMove if UAC or something else stopped it try: folder.makedirs() except: # Failed, try the UAC workaround tmpDir = Path.tempDir() tempDirs.append(tmpDir) toMake = [] toMakeAppend = toMake.append while not folder.exists() and folder != folder.head: # Need to test against dir == dir.head to prevent # infinite recursion if the final bit doesn't exist toMakeAppend(folder.tail) folder = folder.head if not toMake: continue toMake.reverse() base = tmpDir.join(toMake[0]) toDir = folder.join(toMake[0]) tmpDir.join(*toMake).makedirs() fromDirs.append(base) toDirs.append(toDir) if fromDirs: # fromDirs will only get filled if folder.makedirs() failed shellMove(fromDirs, toDirs, parent=parent) finally: for tmpDir in tempDirs: tmpDir.rmtree(safety=tmpDir.stail)
def testUAC(gameDataPath): if _os.name != 'nt': # skip this when not in Windows return False print 'testing UAC' tmpDir = Path.tempDir() tempFile = tmpDir.join(u'_tempfile.tmp') dest = gameDataPath.join(u'_tempfile.tmp') with tempFile.open('wb'): pass # create the file try: # to move it into the Game/Data/ directory shellMove(tempFile, dest, silent=True) except AccessDeniedError: return True finally: shellDeletePass(tmpDir) shellDeletePass(dest) return False
def init_dirs_mopy_and_cd(is_standalone): # ensure we are in the correct directory so relative paths will work # properly if is_standalone: pathToProg = os.path.dirname(unicode(sys.executable, Path.sys_fs_enc)) else: pathToProg = os.path.dirname(unicode(sys.argv[0], Path.sys_fs_enc)) if pathToProg: os.chdir(pathToProg) dirs['mopy'] = Path.getcwd() dirs['bash'] = dirs['mopy'].join(u'bash') dirs['compiled'] = dirs['bash'].join(u'compiled') dirs['l10n'] = dirs['bash'].join(u'l10n') dirs['db'] = dirs['bash'].join(u'db') dirs['templates'] = dirs['mopy'].join(u'templates') dirs['images'] = dirs['bash'].join(u'images') global mopy_dirs_initialized mopy_dirs_initialized = True
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 initDirs(): """Init directories. Assume that settings has already been initialized.""" # --Bash Ini mashIni = None if not conf.settings['mwDir']: conf.settings['mopyDir'] = os.getcwd() parentDir = os.path.split(conf.settings['mopyDir'])[0] conf.settings['mwDir'] = parentDir else: parentDir = conf.settings['mwDir'] conf.settings['mopyDir'] = os.getcwd() if not GPath(Path(parentDir).join('Morrowind.exe').s).exists(): BrowseToMWDir() # These are now defined # conf.settings['mwDir'] will be a string where the EXE is located # conf.dirs['app'] will be a path to where the EXE is located # mwDirParent is intended to be the parent of Morrowind where Morrowind.exe # is located. For example G:\Games\steamapps\common\Morrowind contains the # Morrowind.exe so the parent is G:\Games\steamapps\common # This parent directory is used as the prefix for other directories # such as the installers if not conf.settings['mwDirParent']: conf.settings['mwDirParent'] = conf.settings['mwDir'].split( '\\Morrowind')[0] # Read the INI with UTF8 # TODO Look for a way to detect if it is UTF8 and when it is not read normally if GPath('mash.ini').exists(): mashIni = ConfigParser.SafeConfigParser() with codecs.open('mash.ini', 'r', encoding='utf-8') as f: mashIni.readfp(f) # --Installers if mashIni and mashIni.has_option('General', 'sInstallersDir'): conf.dirs['installers'] = GPath( mashIni.get('General', 'sInstallersDir').strip()) conf.settings['sInstallersDir'] = conf.dirs['installers'].s else: conf.settings['sInstallersDir'] = Path( conf.settings['mwDirParent']).join( _defaultDirectoryExtensions['mashInstallers']).s conf.dirs['installers'] = GPath(conf.settings['sInstallersDir']) # --Installers Data if mashIni and mashIni.has_option('General', 'sInstallersData'): conf.dirs['installersData'] = GPath( mashIni.get('General', 'sInstallersData').strip()) conf.settings['installersData'] = conf.dirs['installersData'].s else: conf.settings['installersData'] = Path( conf.settings['mwDirParent']).join( _defaultDirectoryExtensions['InstallersData']).s conf.dirs['installersData'] = GPath(conf.settings['installersData']) # --Morrowind if mashIni and mashIni.has_option('General', 'sMorrowindPath'): conf.dirs['app'] = GPath( mashIni.get('General', 'sMorrowindPath').strip()) conf.settings['mwDir'] = conf.dirs['app'].s conf.settings['mosh.modInfos.objectMaps'] = _defaultDirectoryExtensions[ 'objectMaps'] conf.settings['mosh.fileInfo.backupDir'] = _defaultDirectoryExtensions[ 'backupDir'] conf.settings['mosh.fileInfo.hiddenDir'] = _defaultDirectoryExtensions[ 'hiddenDir'] conf.settings['mosh.fileInfo.snapshotDir'] = _defaultDirectoryExtensions[ 'snapshotDir'] conf.settings[ 'mosh.InstallersData.officialLocalCSV'] = _defaultDirectoryExtensions[ 'officialLocalCSV'] if not conf.settings['mloxDir']: conf.settings['mloxDir'] = conf.settings['mwDir'] + '\\Mopy\\mlox' if GPath(conf.settings['mloxDir']).exists(): conf.dirs['mloxDir'] = GPath(conf.settings['mloxDir']) # Set System Directories # conf.dirs['app'] is where Morrowind.exe is located # conf.dirs['mods'] should resolve to folder relative to the EXE conf.dirs['app'] = GPath(conf.settings['mwDir']) conf.dirs['mods'] = conf.dirs['app'].join('Data Files') # Detect Windows and make installers folder if it doesn't exist if sys.platform.lower().startswith("win") == True: drv, pth = os.path.splitdrive(conf.dirs['installers'].s) if os.access(drv, os.R_OK): # -# Testing the directories # class Dummy: chk = None # def testDir(a, d, ds): # if d in dirs['installers'].s: # Dummy.chk = os.access(d, a) # os.path.walk(dirs['installers'].s, testDir, os.F_OK) # print "chk", Dummy.chk # -# # print "Installers directory found." conf.dirs['installers'].makedirs() drv, pth = os.path.splitdrive(conf.dirs['installersData'].s) if os.access(drv, os.R_OK): conf.dirs['installersData'].makedirs()
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