Changeset - r25625:c14e95bbb24a
[Not reviewed]
master
0 3 0
Patric Stout - 3 years ago 2021-06-10 21:13:34
truebrain@openttd.org
Add: '-X' option to ignore global folders in the search path (#9341)

This is extreme useful for automated testing. Without this, OpenTTD
will always look in your personal-dir (like ~/.local/share/openttd
or %USER%\Documents\OpenTTD). For most users this is exactly what
we want, that there is a shared place for all their files.

However, for automated testing this is rather annoying, as your
local development files influence the automated test. As such,
'-X' counters this, and only gives the local folders. This is
especially useful in combination with '-x' and '-c'.
3 files changed with 33 insertions and 8 deletions:
0 comments (0 inline, 0 general)
src/fileio.cpp
Show inline comments
 
@@ -70,28 +70,40 @@ typedef std::map<std::string, std::strin
 
static TarLinkList _tar_linklist[NUM_SUBDIRS]; ///< List of directory links
 

	
 
/**
 
 * Checks whether the given search path is a valid search path
 
 * @param sp the search path to check
 
 * @return true if the search path is valid
 
 */
 
static bool IsValidSearchPath(Searchpath sp)
 
{
 
	return sp < _searchpaths.size() && !_searchpaths[sp].empty();
 
}
 

	
 
static void FillValidSearchPaths()
 
static void FillValidSearchPaths(bool only_local_path)
 
{
 
	_valid_searchpaths.clear();
 
	for (Searchpath sp = SP_FIRST_DIR; sp < NUM_SEARCHPATHS; sp++) {
 
		if (only_local_path) {
 
			switch (sp) {
 
				case SP_WORKING_DIR:      // Can be influence by "-c" option.
 
				case SP_BINARY_DIR:       // Most likely contains all the language files.
 
				case SP_AUTODOWNLOAD_DIR: // Otherwise we cannot download in-game content.
 
					break;
 

	
 
				default:
 
					continue;
 
			}
 
		}
 

	
 
		if (IsValidSearchPath(sp)) _valid_searchpaths.emplace_back(sp);
 
	}
 
}
 

	
 
/**
 
 * Check whether the given file exists
 
 * @param filename the file to try for existence.
 
 * @param subdir the subdirectory to look in
 
 * @return true if and only if the file can be opened
 
 */
 
bool FioCheckFileExists(const std::string &filename, Subdirectory subdir)
 
{
 
@@ -943,29 +955,30 @@ extern void CocoaSetApplicationBundleDir
 
	_searchpaths[SP_APPLICATION_BUNDLE_DIR].clear();
 
#endif
 
}
 
#endif /* defined(_WIN32) */
 

	
 
std::string _personal_dir;
 

	
 
/**
 
 * Acquire the base paths (personal dir and game data dir),
 
 * fill all other paths (save dir, autosave dir etc) and
 
 * make the save and scenario directories.
 
 * @param exe the path from the current path to the executable
 
 * @param only_local_path Whether we shouldn't fill searchpaths with global folders.
 
 */
 
void DeterminePaths(const char *exe)
 
void DeterminePaths(const char *exe, bool only_local_path)
 
{
 
	DetermineBasePaths(exe);
 
	FillValidSearchPaths();
 
	FillValidSearchPaths(only_local_path);
 

	
 
#ifdef USE_XDG
 
	std::string config_home;
 
	const std::string homedir = GetHomeDir();
 
	const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
 
	if (xdg_config_home != nullptr) {
 
		config_home = xdg_config_home;
 
		config_home += PATHSEP;
 
		config_home += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR;
 
	} else if (!homedir.empty()) {
 
		/* Defaults to ~/.config */
 
		config_home = homedir;
 
@@ -1014,50 +1027,58 @@ void DeterminePaths(const char *exe)
 

	
 
	_highscore_file = config_dir + "hs.dat";
 
	extern std::string _hotkeys_file;
 
	_hotkeys_file = config_dir + "hotkeys.cfg";
 
	extern std::string _windows_file;
 
	_windows_file = config_dir + "windows.cfg";
 

	
 
#ifdef USE_XDG
 
	if (config_dir == config_home) {
 
		/* We are using the XDG configuration home for the config file,
 
		 * then store the rest in the XDG data home folder. */
 
		_personal_dir = _searchpaths[SP_PERSONAL_DIR_XDG];
 
		if (only_local_path) {
 
			/* In case of XDG and we only want local paths and we detected that
 
			 * the user either manually indicated the XDG path or didn't use
 
			 * "-c" option, we change the working-dir to the XDG personal-dir,
 
			 * as this is most likely what the user is expecting. */
 
			_searchpaths[SP_WORKING_DIR] = _searchpaths[SP_PERSONAL_DIR_XDG];
 
		}
 
	} else
 
#endif
 
	{
 
		_personal_dir = config_dir;
 
	}
 

	
 
	/* Make the necessary folders */
 
	FioCreateDirectory(config_dir);
 
#if defined(WITH_PERSONAL_DIR)
 
	FioCreateDirectory(_personal_dir);
 
#endif
 

	
 
	DEBUG(misc, 3, "%s found as personal directory", _personal_dir.c_str());
 

	
 
	static const Subdirectory default_subdirs[] = {
 
		SAVE_DIR, AUTOSAVE_DIR, SCENARIO_DIR, HEIGHTMAP_DIR, BASESET_DIR, NEWGRF_DIR, AI_DIR, AI_LIBRARY_DIR, GAME_DIR, GAME_LIBRARY_DIR, SCREENSHOT_DIR
 
	};
 

	
 
	for (uint i = 0; i < lengthof(default_subdirs); i++) {
 
		FioCreateDirectory(_personal_dir + _subdirs[default_subdirs[i]]);
 
	}
 

	
 
	/* If we have network we make a directory for the autodownloading of content */
 
	_searchpaths[SP_AUTODOWNLOAD_DIR] = _personal_dir + "content_download" PATHSEP;
 
	DEBUG(misc, 4, "%s added as search path", _searchpaths[SP_AUTODOWNLOAD_DIR].c_str());
 
	FioCreateDirectory(_searchpaths[SP_AUTODOWNLOAD_DIR]);
 
	FillValidSearchPaths();
 
	FillValidSearchPaths(only_local_path);
 

	
 
	/* Create the directory for each of the types of content */
 
	const Subdirectory dirs[] = { SCENARIO_DIR, HEIGHTMAP_DIR, BASESET_DIR, NEWGRF_DIR, AI_DIR, AI_LIBRARY_DIR, GAME_DIR, GAME_LIBRARY_DIR };
 
	for (uint i = 0; i < lengthof(dirs); i++) {
 
		FioCreateDirectory(FioGetDirectory(SP_AUTODOWNLOAD_DIR, dirs[i]));
 
	}
 

	
 
	extern std::string _log_file;
 
	_log_file = _personal_dir + "openttd.log";
 
}
 

	
 
/**
src/fileio_func.h
Show inline comments
 
@@ -18,25 +18,25 @@
 
void FioFCloseFile(FILE *f);
 
FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr);
 
bool FioCheckFileExists(const std::string &filename, Subdirectory subdir);
 
std::string FioFindFullPath(Subdirectory subdir, const char *filename);
 
std::string FioGetDirectory(Searchpath sp, Subdirectory subdir);
 
std::string FioFindDirectory(Subdirectory subdir);
 
void FioCreateDirectory(const std::string &name);
 

	
 
const char *FiosGetScreenshotDir();
 

	
 
void SanitizeFilename(char *filename);
 
void AppendPathSeparator(std::string &buf);
 
void DeterminePaths(const char *exe);
 
void DeterminePaths(const char *exe, bool only_local_path);
 
std::unique_ptr<char[]> ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize);
 
bool FileExists(const std::string &filename);
 
bool ExtractTar(const std::string &tar_filename, Subdirectory subdir);
 

	
 
extern std::string _personal_dir; ///< custom directory for personal settings, saves, newgrf, etc.
 
extern std::vector<Searchpath> _valid_searchpaths;
 

	
 
/** Helper for scanning for files with a given name */
 
class FileScanner {
 
protected:
 
	Subdirectory subdir; ///< The current sub directory we are searching through
 
public:
src/openttd.cpp
Show inline comments
 
@@ -188,24 +188,25 @@ static void ShowHelp()
 
		"  -p password         = Password to join server\n"
 
		"  -P password         = Password to join company\n"
 
		"  -D [ip][:port]      = Start dedicated server\n"
 
		"  -l ip[:port]        = Redirect DEBUG()\n"
 
#if !defined(_WIN32)
 
		"  -f                  = Fork into the background (dedicated only)\n"
 
#endif
 
		"  -I graphics_set     = Force the graphics set (see below)\n"
 
		"  -S sounds_set       = Force the sounds set (see below)\n"
 
		"  -M music_set        = Force the music set (see below)\n"
 
		"  -c config_file      = Use 'config_file' instead of 'openttd.cfg'\n"
 
		"  -x                  = Never save configuration changes to disk\n"
 
		"  -X                  = Don't use global folders to search for files\n"
 
		"  -q savegame         = Write some information about the savegame and exit\n"
 
		"\n",
 
		lastof(buf)
 
	);
 

	
 
	/* List the graphics packs */
 
	p = BaseGraphics::GetSetsList(p, lastof(buf));
 

	
 
	/* List the sounds packs */
 
	p = BaseSounds::GetSetsList(p, lastof(buf));
 

	
 
	/* List the music packs */
 
@@ -497,48 +498,50 @@ static const OptionData _options[] = {
 
	 GETOPT_SHORT_VALUE('P'),
 
#if !defined(_WIN32)
 
	 GETOPT_SHORT_NOVAL('f'),
 
#endif
 
	 GETOPT_SHORT_VALUE('r'),
 
	 GETOPT_SHORT_VALUE('t'),
 
	GETOPT_SHORT_OPTVAL('d'),
 
	 GETOPT_SHORT_NOVAL('e'),
 
	GETOPT_SHORT_OPTVAL('g'),
 
	 GETOPT_SHORT_VALUE('G'),
 
	 GETOPT_SHORT_VALUE('c'),
 
	 GETOPT_SHORT_NOVAL('x'),
 
	 GETOPT_SHORT_NOVAL('X'),
 
	 GETOPT_SHORT_VALUE('q'),
 
	 GETOPT_SHORT_NOVAL('h'),
 
	GETOPT_END()
 
};
 

	
 
/**
 
 * Main entry point for this lovely game.
 
 * @param argc The number of arguments passed to this game.
 
 * @param argv The values of the arguments.
 
 * @return 0 when there is no error.
 
 */
 
int openttd_main(int argc, char *argv[])
 
{
 
	std::string musicdriver;
 
	std::string sounddriver;
 
	std::string videodriver;
 
	std::string blitter;
 
	std::string graphics_set;
 
	std::string sounds_set;
 
	std::string music_set;
 
	Dimension resolution = {0, 0};
 
	std::unique_ptr<AfterNewGRFScan> scanner(new AfterNewGRFScan());
 
	bool dedicated = false;
 
	char *debuglog_conn = nullptr;
 
	bool only_local_path = false;
 

	
 
	extern bool _dedicated_forks;
 
	_dedicated_forks = false;
 

	
 
	_game_mode = GM_MENU;
 
	_switch_mode = SM_MENU;
 

	
 
	GetOptData mgo(argc - 1, argv + 1, _options);
 
	int ret = 0;
 

	
 
	int i;
 
	while ((i = mgo.GetOpt()) != -1) {
 
@@ -599,25 +602,25 @@ int openttd_main(int argc, char *argv[])
 
				}
 

	
 
				break;
 
			}
 

	
 
			_switch_mode = SM_NEWGAME;
 
			/* Give a random map if no seed has been given */
 
			if (scanner->generation_seed == GENERATE_NEW_SEED) {
 
				scanner->generation_seed = InteractiveRandom();
 
			}
 
			break;
 
		case 'q': {
 
			DeterminePaths(argv[0]);
 
			DeterminePaths(argv[0], only_local_path);
 
			if (StrEmpty(mgo.opt)) {
 
				ret = 1;
 
				return ret;
 
			}
 

	
 
			char title[80];
 
			title[0] = '\0';
 
			FiosGetSavegameListCallback(SLO_LOAD, mgo.opt, strrchr(mgo.opt, '.'), title, lastof(title));
 

	
 
			_load_check_data.Clear();
 
			SaveOrLoadResult res = SaveOrLoad(mgo.opt, SLO_CHECK, DFT_GAME_FILE, SAVE_DIR, false);
 
			if (res != SL_OK || _load_check_data.HasErrors()) {
 
@@ -628,47 +631,48 @@ int openttd_main(int argc, char *argv[])
 
					GetString(buf, _load_check_data.error, lastof(buf));
 
					fprintf(stderr, "%s\n", buf);
 
				}
 
				return ret;
 
			}
 

	
 
			WriteSavegameInfo(title);
 
			return ret;
 
		}
 
		case 'G': scanner->generation_seed = strtoul(mgo.opt, nullptr, 10); break;
 
		case 'c': _config_file = mgo.opt; break;
 
		case 'x': scanner->save_config = false; break;
 
		case 'X': only_local_path = true; break;
 
		case 'h':
 
			i = -2; // Force printing of help.
 
			break;
 
		}
 
		if (i == -2) break;
 
	}
 

	
 
	if (i == -2 || mgo.numleft > 0) {
 
		/* Either the user typed '-h', they made an error, or they added unrecognized command line arguments.
 
		 * In all cases, print the help, and exit.
 
		 *
 
		 * The next two functions are needed to list the graphics sets. We can't do them earlier
 
		 * because then we cannot show it on the debug console as that hasn't been configured yet. */
 
		DeterminePaths(argv[0]);
 
		DeterminePaths(argv[0], only_local_path);
 
		TarScanner::DoScan(TarScanner::BASESET);
 
		BaseGraphics::FindSets();
 
		BaseSounds::FindSets();
 
		BaseMusic::FindSets();
 
		ShowHelp();
 
		return ret;
 
	}
 

	
 
	DeterminePaths(argv[0]);
 
	DeterminePaths(argv[0], only_local_path);
 
	TarScanner::DoScan(TarScanner::BASESET);
 

	
 
	if (dedicated) DEBUG(net, 3, "Starting dedicated server, version %s", _openttd_revision);
 
	if (_dedicated_forks && !dedicated) _dedicated_forks = false;
 

	
 
#if defined(UNIX)
 
	/* We must fork here, or we'll end up without some resources we need (like sockets) */
 
	if (_dedicated_forks) DedicatedFork();
 
#endif
 

	
 
	LoadFromConfig(true);
 

	
0 comments (0 inline, 0 general)