mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-25 15:26:17 +02:00
CanonPath, SourcePath: Change operator + to /
This is less confusing and makes it more similar to std::filesystem::path.
This commit is contained in:
parent
6ec08b85f6
commit
a6737b7e17
23 changed files with 48 additions and 47 deletions
|
@ -2689,14 +2689,14 @@ SourcePath resolveExprPath(SourcePath path)
|
||||||
// Basic cycle/depth limit to avoid infinite loops.
|
// Basic cycle/depth limit to avoid infinite loops.
|
||||||
if (++followCount >= maxFollow)
|
if (++followCount >= maxFollow)
|
||||||
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
|
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;
|
if (p.lstat().type != InputAccessor::tSymlink) break;
|
||||||
path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))};
|
path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If `path' refers to a directory, append `/default.nix'. */
|
/* If `path' refers to a directory, append `/default.nix'. */
|
||||||
if (path.resolveSymlinks().lstat().type == InputAccessor::tDirectory)
|
if (path.resolveSymlinks().lstat().type == InputAccessor::tDirectory)
|
||||||
return path + "default.nix";
|
return path / "default.nix";
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// detailed node info quickly in this case we produce a thunk to
|
||||||
// query the file type lazily.
|
// query the file type lazily.
|
||||||
auto epath = state.allocValue();
|
auto epath = state.allocValue();
|
||||||
epath->mkPath(path + name);
|
epath->mkPath(path / name);
|
||||||
if (!readFileType)
|
if (!readFileType)
|
||||||
readFileType = &state.getBuiltin("readFileType");
|
readFileType = &state.getBuiltin("readFileType");
|
||||||
attr.mkApp(readFileType, epath);
|
attr.mkApp(readFileType, epath);
|
||||||
|
|
|
@ -5,26 +5,26 @@ namespace nix {
|
||||||
std::string FilteringInputAccessor::readFile(const CanonPath & path)
|
std::string FilteringInputAccessor::readFile(const CanonPath & path)
|
||||||
{
|
{
|
||||||
checkAccess(path);
|
checkAccess(path);
|
||||||
return next->readFile(prefix + path);
|
return next->readFile(prefix / path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FilteringInputAccessor::pathExists(const CanonPath & 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)
|
std::optional<InputAccessor::Stat> FilteringInputAccessor::maybeLstat(const CanonPath & path)
|
||||||
{
|
{
|
||||||
checkAccess(path);
|
checkAccess(path);
|
||||||
return next->maybeLstat(prefix + path);
|
return next->maybeLstat(prefix / path);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath & path)
|
InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath & path)
|
||||||
{
|
{
|
||||||
checkAccess(path);
|
checkAccess(path);
|
||||||
DirEntries entries;
|
DirEntries entries;
|
||||||
for (auto & entry : next->readDirectory(prefix + path)) {
|
for (auto & entry : next->readDirectory(prefix / path)) {
|
||||||
if (isAllowed(path + entry.first))
|
if (isAllowed(path / entry.first))
|
||||||
entries.insert(std::move(entry));
|
entries.insert(std::move(entry));
|
||||||
}
|
}
|
||||||
return entries;
|
return entries;
|
||||||
|
@ -33,12 +33,12 @@ InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath
|
||||||
std::string FilteringInputAccessor::readLink(const CanonPath & path)
|
std::string FilteringInputAccessor::readLink(const CanonPath & path)
|
||||||
{
|
{
|
||||||
checkAccess(path);
|
checkAccess(path);
|
||||||
return next->readLink(prefix + path);
|
return next->readLink(prefix / path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FilteringInputAccessor::showPath(const CanonPath & path)
|
std::string FilteringInputAccessor::showPath(const CanonPath & path)
|
||||||
{
|
{
|
||||||
return next->showPath(prefix + path);
|
return next->showPath(prefix / path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilteringInputAccessor::checkAccess(const CanonPath & path)
|
void FilteringInputAccessor::checkAccess(const CanonPath & path)
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct FSInputAccessor : InputAccessor, PosixSourceAccessor
|
||||||
|
|
||||||
CanonPath makeAbsPath(const CanonPath & path)
|
CanonPath makeAbsPath(const CanonPath & path)
|
||||||
{
|
{
|
||||||
return root + path;
|
return root / path;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<CanonPath> getPhysicalPath(const CanonPath & path) override
|
std::optional<CanonPath> getPhysicalPath(const CanonPath & path) override
|
||||||
|
|
|
@ -295,7 +295,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||||
throw Error("getting working directory status: %s", git_error_last()->message);
|
throw Error("getting working directory status: %s", git_error_last()->message);
|
||||||
|
|
||||||
/* Get submodule info. */
|
/* Get submodule info. */
|
||||||
auto modulesFile = path + ".gitmodules";
|
auto modulesFile = path / ".gitmodules";
|
||||||
if (pathExists(modulesFile.abs()))
|
if (pathExists(modulesFile.abs()))
|
||||||
info.submodules = parseSubmodules(modulesFile);
|
info.submodules = parseSubmodules(modulesFile);
|
||||||
|
|
||||||
|
|
|
@ -319,7 +319,7 @@ struct GitInputScheme : InputScheme
|
||||||
if (!repoInfo.isLocal)
|
if (!repoInfo.isLocal)
|
||||||
throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string());
|
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 {
|
auto result = runProgram(RunOptions {
|
||||||
.program = "git",
|
.program = "git",
|
||||||
|
@ -680,7 +680,7 @@ struct GitInputScheme : InputScheme
|
||||||
std::map<CanonPath, nix::ref<InputAccessor>> mounts;
|
std::map<CanonPath, nix::ref<InputAccessor>> mounts;
|
||||||
|
|
||||||
for (auto & submodule : repoInfo.workdirInfo.submodules) {
|
for (auto & submodule : repoInfo.workdirInfo.submodules) {
|
||||||
auto submodulePath = CanonPath(repoInfo.url) + submodule.path;
|
auto submodulePath = CanonPath(repoInfo.url) / submodule.path;
|
||||||
fetchers::Attrs attrs;
|
fetchers::Attrs attrs;
|
||||||
attrs.insert_or_assign("type", "git");
|
attrs.insert_or_assign("type", "git");
|
||||||
attrs.insert_or_assign("url", submodulePath.abs());
|
attrs.insert_or_assign("url", submodulePath.abs());
|
||||||
|
|
|
@ -141,7 +141,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
if (!isLocal)
|
if (!isLocal)
|
||||||
throw Error("cannot commit '%s' to Mercurial repository '%s' because it's not a working tree", path, input.to_string());
|
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);
|
writeFile(absPath.abs(), contents);
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ struct PathInputScheme : InputScheme
|
||||||
std::string_view contents,
|
std::string_view contents,
|
||||||
std::optional<std::string> commitMsg) const override
|
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
|
CanonPath getAbsPath(const Input & input) const
|
||||||
|
|
|
@ -235,14 +235,14 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
||||||
std::regex regex2("^[0-9a-f]{38}\\.debug$");
|
std::regex regex2("^[0-9a-f]{38}\\.debug$");
|
||||||
|
|
||||||
for (auto & [s1, _type] : narAccessor->readDirectory(buildIdDir)) {
|
for (auto & [s1, _type] : narAccessor->readDirectory(buildIdDir)) {
|
||||||
auto dir = buildIdDir + s1;
|
auto dir = buildIdDir / s1;
|
||||||
|
|
||||||
if (narAccessor->lstat(dir).type != SourceAccessor::tDirectory
|
if (narAccessor->lstat(dir).type != SourceAccessor::tDirectory
|
||||||
|| !std::regex_match(s1, regex1))
|
|| !std::regex_match(s1, regex1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (auto & [s2, _type] : narAccessor->readDirectory(dir)) {
|
for (auto & [s2, _type] : narAccessor->readDirectory(dir)) {
|
||||||
auto debugPath = dir + s2;
|
auto debugPath = dir / s2;
|
||||||
|
|
||||||
if (narAccessor->lstat(debugPath).type != SourceAccessor::tRegular
|
if (narAccessor->lstat(debugPath).type != SourceAccessor::tRegular
|
||||||
|| !std::regex_match(s2, regex2))
|
|| !std::regex_match(s2, regex2))
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct LocalStoreAccessor : PosixSourceAccessor
|
||||||
auto [storePath, rest] = store->toStorePath(path.abs());
|
auto [storePath, rest] = store->toStorePath(path.abs());
|
||||||
if (requireValidPath && !store->isValidPath(storePath))
|
if (requireValidPath && !store->isValidPath(storePath))
|
||||||
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(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
|
std::optional<Stat> maybeLstat(const CanonPath & path) override
|
||||||
|
|
|
@ -277,7 +277,7 @@ json listNar(ref<SourceAccessor> accessor, const CanonPath & path, bool recurse)
|
||||||
json &res2 = obj["entries"];
|
json &res2 = obj["entries"];
|
||||||
for (const auto & [name, type] : accessor->readDirectory(path)) {
|
for (const auto & [name, type] : accessor->readDirectory(path)) {
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
res2[name] = listNar(accessor, path + name, true);
|
res2[name] = listNar(accessor, path / name, true);
|
||||||
} else
|
} else
|
||||||
res2[name] = json::object();
|
res2[name] = json::object();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,20 +77,20 @@ void SourceAccessor::dumpPath(
|
||||||
std::string name(i.first);
|
std::string name(i.first);
|
||||||
size_t pos = i.first.find(caseHackSuffix);
|
size_t pos = i.first.find(caseHackSuffix);
|
||||||
if (pos != std::string::npos) {
|
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);
|
name.erase(pos);
|
||||||
}
|
}
|
||||||
if (!unhacked.emplace(name, i.first).second)
|
if (!unhacked.emplace(name, i.first).second)
|
||||||
throw Error("file name collision in between '%s' and '%s'",
|
throw Error("file name collision in between '%s' and '%s'",
|
||||||
(path + unhacked[name]),
|
(path / unhacked[name]),
|
||||||
(path + i.first));
|
(path / i.first));
|
||||||
} else
|
} else
|
||||||
unhacked.emplace(i.first, i.first);
|
unhacked.emplace(i.first, i.first);
|
||||||
|
|
||||||
for (auto & i : unhacked)
|
for (auto & i : unhacked)
|
||||||
if (filter((path + i.first).abs())) {
|
if (filter((path / i.first).abs())) {
|
||||||
sink << "entry" << "(" << "name" << i.first << "node";
|
sink << "entry" << "(" << "name" << i.first << "node";
|
||||||
dump(path + i.second);
|
dump(path / i.second);
|
||||||
sink << ")";
|
sink << ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ void CanonPath::extend(const CanonPath & x)
|
||||||
path += x.abs();
|
path += x.abs();
|
||||||
}
|
}
|
||||||
|
|
||||||
CanonPath CanonPath::operator + (const CanonPath & x) const
|
CanonPath CanonPath::operator / (const CanonPath & x) const
|
||||||
{
|
{
|
||||||
auto res = *this;
|
auto res = *this;
|
||||||
res.extend(x);
|
res.extend(x);
|
||||||
|
@ -78,7 +78,7 @@ void CanonPath::push(std::string_view c)
|
||||||
path += c;
|
path += c;
|
||||||
}
|
}
|
||||||
|
|
||||||
CanonPath CanonPath::operator + (std::string_view c) const
|
CanonPath CanonPath::operator / (std::string_view c) const
|
||||||
{
|
{
|
||||||
auto res = *this;
|
auto res = *this;
|
||||||
res.push(c);
|
res.push(c);
|
||||||
|
|
|
@ -190,14 +190,14 @@ public:
|
||||||
/**
|
/**
|
||||||
* Concatenate two paths.
|
* 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.
|
* Add a path component to this one. It must not contain any slashes.
|
||||||
*/
|
*/
|
||||||
void push(std::string_view c);
|
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
|
* Check whether access to this path is allowed, which is the case
|
||||||
|
|
|
@ -34,7 +34,7 @@ void copyRecursive(
|
||||||
sink.createDirectory(to);
|
sink.createDirectory(to);
|
||||||
for (auto & [name, _] : accessor.readDirectory(from)) {
|
for (auto & [name, _] : accessor.readDirectory(from)) {
|
||||||
copyRecursive(
|
copyRecursive(
|
||||||
accessor, from + name,
|
accessor, from / name,
|
||||||
sink, to + "/" + name);
|
sink, to + "/" + name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ Mode dump(
|
||||||
{
|
{
|
||||||
Tree entries;
|
Tree entries;
|
||||||
for (auto & [name, _] : accessor.readDirectory(path)) {
|
for (auto & [name, _] : accessor.readDirectory(path)) {
|
||||||
auto child = path + name;
|
auto child = path / name;
|
||||||
if (!filter(child.abs())) continue;
|
if (!filter(child.abs())) continue;
|
||||||
|
|
||||||
auto entry = hook(child);
|
auto entry = hook(child);
|
||||||
|
|
|
@ -41,11 +41,11 @@ std::optional<CanonPath> SourcePath::getPhysicalPath() const
|
||||||
std::string SourcePath::to_string() const
|
std::string SourcePath::to_string() const
|
||||||
{ return accessor->showPath(path); }
|
{ return accessor->showPath(path); }
|
||||||
|
|
||||||
SourcePath SourcePath::operator+(const CanonPath & x) const
|
SourcePath SourcePath::operator / (const CanonPath & x) const
|
||||||
{ return {accessor, path + x}; }
|
{ return {accessor, path / x}; }
|
||||||
|
|
||||||
SourcePath SourcePath::operator+(std::string_view c) const
|
SourcePath SourcePath::operator / (std::string_view c) const
|
||||||
{ return {accessor, path + c}; }
|
{ return {accessor, path / c}; }
|
||||||
|
|
||||||
bool SourcePath::operator==(const SourcePath & x) const
|
bool SourcePath::operator==(const SourcePath & x) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -89,14 +89,15 @@ struct SourcePath
|
||||||
/**
|
/**
|
||||||
* Append a `CanonPath` to this path.
|
* 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
|
* Append a single component `c` to this path. `c` must not
|
||||||
* contain a slash. A slash is implicitly added between this path
|
* contain a slash. A slash is implicitly added between this path
|
||||||
* and `c`.
|
* 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;
|
bool operator!=(const SourcePath & x) const;
|
||||||
bool operator<(const SourcePath & x) const;
|
bool operator<(const SourcePath & x) const;
|
||||||
|
|
|
@ -97,7 +97,7 @@ static bool isNixExpr(const SourcePath & path, struct InputAccessor::Stat & st)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
st.type == InputAccessor::tRegular
|
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). */
|
are implemented using profiles). */
|
||||||
if (i == "manifest.nix") continue;
|
if (i == "manifest.nix") continue;
|
||||||
|
|
||||||
auto path2 = (path + i).resolveSymlinks();
|
auto path2 = (path / i).resolveSymlinks();
|
||||||
|
|
||||||
InputAccessor::Stat st;
|
InputAccessor::Stat st;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct MixLs : virtual Args, MixJSON
|
||||||
if (st.type == SourceAccessor::Type::tDirectory && !showDirectory) {
|
if (st.type == SourceAccessor::Type::tDirectory && !showDirectory) {
|
||||||
auto names = accessor->readDirectory(curPath);
|
auto names = accessor->readDirectory(curPath);
|
||||||
for (auto & [name, type] : names)
|
for (auto & [name, type] : names)
|
||||||
showFile(curPath + name, relPath + "/" + name);
|
showFile(curPath / name, relPath + "/" + name);
|
||||||
} else
|
} else
|
||||||
showFile(curPath, relPath);
|
showFile(curPath, relPath);
|
||||||
};
|
};
|
||||||
|
|
|
@ -124,7 +124,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
||||||
if (true)
|
if (true)
|
||||||
pathAdditions.push_back(store->printStorePath(path) + "/bin");
|
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) {
|
if (auto st = accessor->maybeLstat(propPath); st && st->type == SourceAccessor::tRegular) {
|
||||||
for (auto & p : tokenizeString<Paths>(accessor->readFile(propPath)))
|
for (auto & p : tokenizeString<Paths>(accessor->readFile(propPath)))
|
||||||
todo.push(store->parseStorePath(p));
|
todo.push(store->parseStorePath(p));
|
||||||
|
|
|
@ -225,7 +225,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
if (st->type == SourceAccessor::Type::tDirectory) {
|
if (st->type == SourceAccessor::Type::tDirectory) {
|
||||||
auto names = accessor->readDirectory(p);
|
auto names = accessor->readDirectory(p);
|
||||||
for (auto & [name, type] : names)
|
for (auto & [name, type] : names)
|
||||||
visitPath(p + name);
|
visitPath(p / name);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (st->type == SourceAccessor::Type::tRegular) {
|
else if (st->type == SourceAccessor::Type::tRegular) {
|
||||||
|
|
|
@ -80,29 +80,29 @@ namespace nix {
|
||||||
{
|
{
|
||||||
CanonPath p1("a//foo/bar//");
|
CanonPath p1("a//foo/bar//");
|
||||||
CanonPath p2("xyzzy/bla");
|
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 p1("/");
|
||||||
CanonPath p2("/a/b");
|
CanonPath p2("/a/b");
|
||||||
ASSERT_EQ((p1 + p2).abs(), "/a/b");
|
ASSERT_EQ((p1 / p2).abs(), "/a/b");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
CanonPath p1("/a/b");
|
CanonPath p1("/a/b");
|
||||||
CanonPath p2("/");
|
CanonPath p2("/");
|
||||||
ASSERT_EQ((p1 + p2).abs(), "/a/b");
|
ASSERT_EQ((p1 / p2).abs(), "/a/b");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
CanonPath p("/foo/bar");
|
CanonPath p("/foo/bar");
|
||||||
ASSERT_EQ((p + "x").abs(), "/foo/bar/x");
|
ASSERT_EQ((p / "x").abs(), "/foo/bar/x");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
CanonPath p("/");
|
CanonPath p("/");
|
||||||
ASSERT_EQ((p + "foo" + "bar").abs(), "/foo/bar");
|
ASSERT_EQ((p / "foo" / "bar").abs(), "/foo/bar");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue