diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libstore/globals.cc | 3 | ||||
-rw-r--r-- | src/libutil/config.cc | 14 | ||||
-rw-r--r-- | src/libutil/file-system.cc | 15 | ||||
-rw-r--r-- | src/libutil/file-system.hh | 10 |
4 files changed, 37 insertions, 5 deletions
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index ab461e739..29ec60105 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -131,8 +131,9 @@ void loadConfFile() globalConfig.resetOverridden(); auto files = settings.nixUserConfFiles; + auto home = getHome(); for (auto file = files.rbegin(); file != files.rend(); file++) { - applyConfigFile(ApplyConfigOptions{.path = *file}); + applyConfigFile(ApplyConfigOptions{.path = *file, .home = home}); } auto nixConfEnv = getEnv("NIX_CONFIG"); diff --git a/src/libutil/config.cc b/src/libutil/config.cc index 333deb388..778da1413 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -126,7 +126,7 @@ static void applyConfigInner(const std::string & contents, const ApplyConfigOpti if (!options.path) { throw UsageError("can only include configuration '%1%' from files", tokens[1]); } - auto pathToInclude = absPath(tokens[1], dirOf(*options.path)); + auto pathToInclude = absPath(tildePath(tokens[1], options.home), dirOf(*options.path)); if (pathExists(pathToInclude)) { auto includeOptions = ApplyConfigOptions { .path = pathToInclude, @@ -437,10 +437,16 @@ template class BaseSetting<DeprecatedFeatures>; static Path parsePath(const AbstractSetting & s, const std::string & str, const ApplyConfigOptions & options) { - if (str == "") + if (str == "") { throw UsageError("setting '%s' is a path and paths cannot be empty", s.name); - else - return canonPath(str); + } else { + auto tildeResolvedPath = tildePath(str, options.home); + if (options.path) { + return absPath(tildeResolvedPath, dirOf(*options.path)); + } else { + return canonPath(tildeResolvedPath); + } + } } template<> Path PathsSetting<Path>::parse(const std::string & str, const ApplyConfigOptions & options) const diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 631cf076b..234c73163 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -117,6 +117,21 @@ Path realPath(Path const & path) return ret; } +Path tildePath(Path const & path, const std::optional<Path> & home) +{ + if (path.starts_with("~/")) { + if (home) { + return *home + "/" + path.substr(2); + } else { + throw UsageError("`~` path not allowed: %1%", path); + } + } else if (path.starts_with('~')) { + throw UsageError("`~` paths must start with `~/`: %1%", path); + } else { + return path; + } +} + void chmodPath(const Path & path, mode_t mode) { if (chmod(path.c_str(), mode) == -1) diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index e49323e84..0a54d1a3b 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -63,6 +63,16 @@ Path canonPath(PathView path, bool resolveSymlinks = false); Path realPath(Path const & path); /** + * Resolve a tilde path like `~/puppy.nix` into an absolute path. + * + * If `home` is given, it's substituted for `~/` at the start of the input + * `path`. Otherwise, an error is thrown. + * + * If the path starts with `~` but not `~/`, an error is thrown. + */ +Path tildePath(Path const & path, const std::optional<Path> & home = std::nullopt); + +/** * Change the permissions of a path * Not called `chmod` as it shadows and could be confused with * `int chmod(char *, mode_t)`, which does not handle errors |