CanonPath, SourcePath: Change operator + to /

This is less confusing and makes it more similar to std::filesystem::path.
This commit is contained in:
Eelco Dolstra 2024-02-05 15:13:11 +01:00
parent 6ec08b85f6
commit a6737b7e17
23 changed files with 48 additions and 47 deletions

View file

@ -2689,14 +2689,14 @@ SourcePath resolveExprPath(SourcePath path)
// Basic cycle/depth limit to avoid infinite loops.
if (++followCount >= maxFollow)
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
auto p = path.parent().resolveSymlinks() + path.baseName();
auto p = path.parent().resolveSymlinks() / path.baseName();
if (p.lstat().type != InputAccessor::tSymlink) break;
path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))};
}
/* If `path' refers to a directory, append `/default.nix'. */
if (path.resolveSymlinks().lstat().type == InputAccessor::tDirectory)
return path + "default.nix";
return path / "default.nix";
return path;
}

View file

@ -1816,7 +1816,7 @@ static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Va
// detailed node info quickly in this case we produce a thunk to
// query the file type lazily.
auto epath = state.allocValue();
epath->mkPath(path + name);
epath->mkPath(path / name);
if (!readFileType)
readFileType = &state.getBuiltin("readFileType");
attr.mkApp(readFileType, epath);

View file

@ -5,26 +5,26 @@ namespace nix {
std::string FilteringInputAccessor::readFile(const CanonPath & path)
{
checkAccess(path);
return next->readFile(prefix + path);
return next->readFile(prefix / path);
}
bool FilteringInputAccessor::pathExists(const CanonPath & path)
{
return isAllowed(path) && next->pathExists(prefix + path);
return isAllowed(path) && next->pathExists(prefix / path);
}
std::optional<InputAccessor::Stat> FilteringInputAccessor::maybeLstat(const CanonPath & path)
{
checkAccess(path);
return next->maybeLstat(prefix + path);
return next->maybeLstat(prefix / path);
}
InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath & path)
{
checkAccess(path);
DirEntries entries;
for (auto & entry : next->readDirectory(prefix + path)) {
if (isAllowed(path + entry.first))
for (auto & entry : next->readDirectory(prefix / path)) {
if (isAllowed(path / entry.first))
entries.insert(std::move(entry));
}
return entries;
@ -33,12 +33,12 @@ InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath
std::string FilteringInputAccessor::readLink(const CanonPath & path)
{
checkAccess(path);
return next->readLink(prefix + path);
return next->readLink(prefix / path);
}
std::string FilteringInputAccessor::showPath(const CanonPath & path)
{
return next->showPath(prefix + path);
return next->showPath(prefix / path);
}
void FilteringInputAccessor::checkAccess(const CanonPath & path)

View file

@ -48,7 +48,7 @@ struct FSInputAccessor : InputAccessor, PosixSourceAccessor
CanonPath makeAbsPath(const CanonPath & path)
{
return root + path;
return root / path;
}
std::optional<CanonPath> getPhysicalPath(const CanonPath & path) override

View file

@ -295,7 +295,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
throw Error("getting working directory status: %s", git_error_last()->message);
/* Get submodule info. */
auto modulesFile = path + ".gitmodules";
auto modulesFile = path / ".gitmodules";
if (pathExists(modulesFile.abs()))
info.submodules = parseSubmodules(modulesFile);

View file

@ -319,7 +319,7 @@ struct GitInputScheme : InputScheme
if (!repoInfo.isLocal)
throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string());
writeFile((CanonPath(repoInfo.url) + path).abs(), contents);
writeFile((CanonPath(repoInfo.url) / path).abs(), contents);
auto result = runProgram(RunOptions {
.program = "git",
@ -680,7 +680,7 @@ struct GitInputScheme : InputScheme
std::map<CanonPath, nix::ref<InputAccessor>> mounts;
for (auto & submodule : repoInfo.workdirInfo.submodules) {
auto submodulePath = CanonPath(repoInfo.url) + submodule.path;
auto submodulePath = CanonPath(repoInfo.url) / submodule.path;
fetchers::Attrs attrs;
attrs.insert_or_assign("type", "git");
attrs.insert_or_assign("url", submodulePath.abs());

View file

@ -141,7 +141,7 @@ struct MercurialInputScheme : InputScheme
if (!isLocal)
throw Error("cannot commit '%s' to Mercurial repository '%s' because it's not a working tree", path, input.to_string());
auto absPath = CanonPath(repoPath) + path;
auto absPath = CanonPath(repoPath) / path;
writeFile(absPath.abs(), contents);

View file

@ -84,7 +84,7 @@ struct PathInputScheme : InputScheme
std::string_view contents,
std::optional<std::string> commitMsg) const override
{
writeFile((CanonPath(getAbsPath(input)) + path).abs(), contents);
writeFile((CanonPath(getAbsPath(input)) / path).abs(), contents);
}
CanonPath getAbsPath(const Input & input) const

View file

@ -235,14 +235,14 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
std::regex regex2("^[0-9a-f]{38}\\.debug$");
for (auto & [s1, _type] : narAccessor->readDirectory(buildIdDir)) {
auto dir = buildIdDir + s1;
auto dir = buildIdDir / s1;
if (narAccessor->lstat(dir).type != SourceAccessor::tDirectory
|| !std::regex_match(s1, regex1))
continue;
for (auto & [s2, _type] : narAccessor->readDirectory(dir)) {
auto debugPath = dir + s2;
auto debugPath = dir / s2;
if (narAccessor->lstat(debugPath).type != SourceAccessor::tRegular
|| !std::regex_match(s2, regex2))

View file

@ -28,7 +28,7 @@ struct LocalStoreAccessor : PosixSourceAccessor
auto [storePath, rest] = store->toStorePath(path.abs());
if (requireValidPath && !store->isValidPath(storePath))
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath));
return CanonPath(store->getRealStoreDir()) + storePath.to_string() + CanonPath(rest);
return CanonPath(store->getRealStoreDir()) / storePath.to_string() / CanonPath(rest);
}
std::optional<Stat> maybeLstat(const CanonPath & path) override

View file

@ -277,7 +277,7 @@ json listNar(ref<SourceAccessor> accessor, const CanonPath & path, bool recurse)
json &res2 = obj["entries"];
for (const auto & [name, type] : accessor->readDirectory(path)) {
if (recurse) {
res2[name] = listNar(accessor, path + name, true);
res2[name] = listNar(accessor, path / name, true);
} else
res2[name] = json::object();
}

View file

@ -77,20 +77,20 @@ void SourceAccessor::dumpPath(
std::string name(i.first);
size_t pos = i.first.find(caseHackSuffix);
if (pos != std::string::npos) {
debug("removing case hack suffix from '%s'", path + i.first);
debug("removing case hack suffix from '%s'", path / i.first);
name.erase(pos);
}
if (!unhacked.emplace(name, i.first).second)
throw Error("file name collision in between '%s' and '%s'",
(path + unhacked[name]),
(path + i.first));
(path / unhacked[name]),
(path / i.first));
} else
unhacked.emplace(i.first, i.first);
for (auto & i : unhacked)
if (filter((path + i.first).abs())) {
if (filter((path / i.first).abs())) {
sink << "entry" << "(" << "name" << i.first << "node";
dump(path + i.second);
dump(path / i.second);
sink << ")";
}
}

View file

@ -63,7 +63,7 @@ void CanonPath::extend(const CanonPath & x)
path += x.abs();
}
CanonPath CanonPath::operator + (const CanonPath & x) const
CanonPath CanonPath::operator / (const CanonPath & x) const
{
auto res = *this;
res.extend(x);
@ -78,7 +78,7 @@ void CanonPath::push(std::string_view c)
path += c;
}
CanonPath CanonPath::operator + (std::string_view c) const
CanonPath CanonPath::operator / (std::string_view c) const
{
auto res = *this;
res.push(c);

View file

@ -190,14 +190,14 @@ public:
/**
* Concatenate two paths.
*/
CanonPath operator + (const CanonPath & x) const;
CanonPath operator / (const CanonPath & x) const;
/**
* Add a path component to this one. It must not contain any slashes.
*/
void push(std::string_view c);
CanonPath operator + (std::string_view c) const;
CanonPath operator / (std::string_view c) const;
/**
* Check whether access to this path is allowed, which is the case

View file

@ -34,7 +34,7 @@ void copyRecursive(
sink.createDirectory(to);
for (auto & [name, _] : accessor.readDirectory(from)) {
copyRecursive(
accessor, from + name,
accessor, from / name,
sink, to + "/" + name);
break;
}

View file

@ -259,7 +259,7 @@ Mode dump(
{
Tree entries;
for (auto & [name, _] : accessor.readDirectory(path)) {
auto child = path + name;
auto child = path / name;
if (!filter(child.abs())) continue;
auto entry = hook(child);

View file

@ -41,11 +41,11 @@ std::optional<CanonPath> SourcePath::getPhysicalPath() const
std::string SourcePath::to_string() const
{ return accessor->showPath(path); }
SourcePath SourcePath::operator+(const CanonPath & x) const
{ return {accessor, path + x}; }
SourcePath SourcePath::operator / (const CanonPath & x) const
{ return {accessor, path / x}; }
SourcePath SourcePath::operator+(std::string_view c) const
{ return {accessor, path + c}; }
SourcePath SourcePath::operator / (std::string_view c) const
{ return {accessor, path / c}; }
bool SourcePath::operator==(const SourcePath & x) const
{

View file

@ -89,14 +89,15 @@ struct SourcePath
/**
* Append a `CanonPath` to this path.
*/
SourcePath operator + (const CanonPath & x) const;
SourcePath operator / (const CanonPath & x) const;
/**
* Append a single component `c` to this path. `c` must not
* contain a slash. A slash is implicitly added between this path
* and `c`.
*/
SourcePath operator+(std::string_view c) const;
SourcePath operator / (std::string_view c) const;
bool operator==(const SourcePath & x) const;
bool operator!=(const SourcePath & x) const;
bool operator<(const SourcePath & x) const;

View file

@ -97,7 +97,7 @@ static bool isNixExpr(const SourcePath & path, struct InputAccessor::Stat & st)
{
return
st.type == InputAccessor::tRegular
|| (st.type == InputAccessor::tDirectory && (path + "default.nix").resolveSymlinks().pathExists());
|| (st.type == InputAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists());
}
@ -116,7 +116,7 @@ static void getAllExprs(EvalState & state,
are implemented using profiles). */
if (i == "manifest.nix") continue;
auto path2 = (path + i).resolveSymlinks();
auto path2 = (path / i).resolveSymlinks();
InputAccessor::Stat st;
try {

View file

@ -72,7 +72,7 @@ struct MixLs : virtual Args, MixJSON
if (st.type == SourceAccessor::Type::tDirectory && !showDirectory) {
auto names = accessor->readDirectory(curPath);
for (auto & [name, type] : names)
showFile(curPath + name, relPath + "/" + name);
showFile(curPath / name, relPath + "/" + name);
} else
showFile(curPath, relPath);
};

View file

@ -124,7 +124,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
if (true)
pathAdditions.push_back(store->printStorePath(path) + "/bin");
auto propPath = CanonPath(store->printStorePath(path)) + "nix-support" + "propagated-user-env-packages";
auto propPath = CanonPath(store->printStorePath(path)) / "nix-support" / "propagated-user-env-packages";
if (auto st = accessor->maybeLstat(propPath); st && st->type == SourceAccessor::tRegular) {
for (auto & p : tokenizeString<Paths>(accessor->readFile(propPath)))
todo.push(store->parseStorePath(p));

View file

@ -225,7 +225,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
if (st->type == SourceAccessor::Type::tDirectory) {
auto names = accessor->readDirectory(p);
for (auto & [name, type] : names)
visitPath(p + name);
visitPath(p / name);
}
else if (st->type == SourceAccessor::Type::tRegular) {

View file

@ -80,29 +80,29 @@ namespace nix {
{
CanonPath p1("a//foo/bar//");
CanonPath p2("xyzzy/bla");
ASSERT_EQ((p1 + p2).abs(), "/a/foo/bar/xyzzy/bla");
ASSERT_EQ((p1 / p2).abs(), "/a/foo/bar/xyzzy/bla");
}
{
CanonPath p1("/");
CanonPath p2("/a/b");
ASSERT_EQ((p1 + p2).abs(), "/a/b");
ASSERT_EQ((p1 / p2).abs(), "/a/b");
}
{
CanonPath p1("/a/b");
CanonPath p2("/");
ASSERT_EQ((p1 + p2).abs(), "/a/b");
ASSERT_EQ((p1 / p2).abs(), "/a/b");
}
{
CanonPath p("/foo/bar");
ASSERT_EQ((p + "x").abs(), "/foo/bar/x");
ASSERT_EQ((p / "x").abs(), "/foo/bar/x");
}
{
CanonPath p("/");
ASSERT_EQ((p + "foo" + "bar").abs(), "/foo/bar");
ASSERT_EQ((p / "foo" / "bar").abs(), "/foo/bar");
}
}