Delete hasPrefix and hasSuffix from the codebase

These now have equivalents in the standard lib in C++20. This change was
performed with a custom clang-tidy check which I will submit later.
Executed like so:

ninja -C build && run-clang-tidy -checks='-*,nix-*' -load=build/libnix-clang-tidy.so -p .. -fix ../tests | tee -a clang-tidy-result

Change-Id: I62679e315ff9e7ce72a40b91b79c3e9fc01b27e9
This commit is contained in:
Jade Lovelace 2024-03-17 19:14:18 -07:00
parent 706cee5c49
commit 61e21b2557
44 changed files with 91 additions and 147 deletions

View file

@ -172,7 +172,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s)
return state.rootPath(CanonPath(state.store->toRealPath(storePath))); return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
} }
else if (hasPrefix(s, "flake:")) { else if (s.starts_with("flake:")) {
experimentalFeatureSettings.require(Xp::Flakes); experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false); auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false);
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first.storePath; auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first.storePath;

View file

@ -159,7 +159,7 @@ void MixFlakeOptions::completeFlakeInput(std::string_view prefix)
auto flakeRef = parseFlakeRefWithFragment(expandTilde(flakeRefS), absPath(".")).first; auto flakeRef = parseFlakeRefWithFragment(expandTilde(flakeRefS), absPath(".")).first;
auto flake = flake::getFlake(*evalState, flakeRef, true); auto flake = flake::getFlake(*evalState, flakeRef, true);
for (auto & input : flake.inputs) for (auto & input : flake.inputs)
if (hasPrefix(input.first, prefix)) if (input.first.starts_with(prefix))
completions->add(input.first); completions->add(input.first);
} }
} }
@ -320,7 +320,7 @@ void completeFlakeRefWithFragment(
auto attrPath = parseAttrPath(*evalState, attrPathS); auto attrPath = parseAttrPath(*evalState, attrPathS);
std::string lastAttr; std::string lastAttr;
if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) { if (!attrPath.empty() && !attrPathS.ends_with(".")) {
lastAttr = evalState->symbols[attrPath.back()]; lastAttr = evalState->symbols[attrPath.back()];
attrPath.pop_back(); attrPath.pop_back();
} }
@ -329,7 +329,7 @@ void completeFlakeRefWithFragment(
if (!attr) continue; if (!attr) continue;
for (auto & attr2 : (*attr)->getAttrs()) { for (auto & attr2 : (*attr)->getAttrs()) {
if (hasPrefix(evalState->symbols[attr2], lastAttr)) { if (std::string_view(evalState->symbols[attr2]).starts_with(lastAttr)) {
auto attrPath2 = (*attr)->getAttrPath(attr2); auto attrPath2 = (*attr)->getAttrPath(attr2);
/* Strip the attrpath prefix. */ /* Strip the attrpath prefix. */
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
@ -367,12 +367,12 @@ void completeFlakeRef(ref<Store> store, std::string_view prefix)
for (auto & registry : fetchers::getRegistries(store)) { for (auto & registry : fetchers::getRegistries(store)) {
for (auto & entry : registry->entries) { for (auto & entry : registry->entries) {
auto from = entry.from.to_string(); auto from = entry.from.to_string();
if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) { if (!prefix.starts_with("flake:") && from.starts_with("flake:")) {
std::string from2(from, 6); std::string from2(from, 6);
if (hasPrefix(from2, prefix)) if (from2.starts_with(prefix))
completions->add(from2); completions->add(from2);
} else { } else {
if (hasPrefix(from, prefix)) if (from.starts_with(prefix))
completions->add(from); completions->add(from);
} }
} }

View file

@ -272,7 +272,7 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
auto dir = std::string(cur, 0, slash); auto dir = std::string(cur, 0, slash);
auto prefix2 = std::string(cur, slash + 1); auto prefix2 = std::string(cur, slash + 1);
for (auto & entry : readDirectory(dir == "" ? "/" : dir)) { for (auto & entry : readDirectory(dir == "" ? "/" : dir)) {
if (entry.name[0] != '.' && hasPrefix(entry.name, prefix2)) if (entry.name[0] != '.' && entry.name.starts_with(prefix2))
completions.insert(prev + dir + "/" + entry.name); completions.insert(prev + dir + "/" + entry.name);
} }
} catch (Error &) { } catch (Error &) {

View file

@ -29,7 +29,7 @@ static Strings parseNixPath(const std::string & s)
if (*p == ':') { if (*p == ':') {
auto prefix = std::string(start2, s.end()); auto prefix = std::string(start2, s.end());
if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) { if (EvalSettings::isPseudoUrl(prefix) || prefix.starts_with("flake:")) {
++p; ++p;
while (p != s.end() && *p != ':') ++p; while (p != s.end() && *p != ':') ++p;
} }
@ -82,7 +82,7 @@ bool EvalSettings::isPseudoUrl(std::string_view s)
std::string EvalSettings::resolvePseudoUrl(std::string_view url) std::string EvalSettings::resolvePseudoUrl(std::string_view url)
{ {
if (hasPrefix(url, "channel:")) if (url.starts_with("channel:"))
return "https://nixos.org/channels/" + std::string(url.substr(8)) + "/nixexprs.tar.xz"; return "https://nixos.org/channels/" + std::string(url.substr(8)) + "/nixexprs.tar.xz";
else else
return std::string(url); return std::string(url);

View file

@ -484,7 +484,7 @@ SourcePath EvalState::checkSourcePath(const SourcePath & path_)
*/ */
Path abspath = canonPath(path_.path.abs()); Path abspath = canonPath(path_.path.abs());
if (hasPrefix(abspath, corepkgsPrefix)) return CanonPath(abspath); if (abspath.starts_with(corepkgsPrefix)) return CanonPath(abspath);
for (auto & i : *allowedPaths) { for (auto & i : *allowedPaths) {
if (isDirOrInDir(abspath, i)) { if (isDirOrInDir(abspath, i)) {
@ -527,18 +527,18 @@ void EvalState::checkURI(const std::string & uri)
if (uri == prefix || if (uri == prefix ||
(uri.size() > prefix.size() (uri.size() > prefix.size()
&& prefix.size() > 0 && prefix.size() > 0
&& hasPrefix(uri, prefix) && uri.starts_with(prefix)
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/'))) && (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
return; return;
/* If the URI is a path, then check it against allowedPaths as /* If the URI is a path, then check it against allowedPaths as
well. */ well. */
if (hasPrefix(uri, "/")) { if (uri.starts_with("/")) {
checkSourcePath(CanonPath(uri)); checkSourcePath(CanonPath(uri));
return; return;
} }
if (hasPrefix(uri, "file://")) { if (uri.starts_with("file://")) {
checkSourcePath(CanonPath(std::string(uri, 7))); checkSourcePath(CanonPath(std::string(uri, 7)));
return; return;
} }
@ -642,7 +642,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
} }
auto envName = symbols.create(primOp.name); auto envName = symbols.create(primOp.name);
if (hasPrefix(primOp.name, "__")) if (primOp.name.starts_with("__"))
primOp.name = primOp.name.substr(2); primOp.name = primOp.name.substr(2);
Value * v = allocValue(); Value * v = allocValue();
@ -719,7 +719,7 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
// for the top level, don't print the double underscore ones; // for the top level, don't print the double underscore ones;
// they are in builtins. // they are in builtins.
for (auto & i : se.vars) for (auto & i : se.vars)
if (!hasPrefix(st[i.first], "__")) if (!std::string_view(st[i.first]).starts_with("__"))
std::cout << st[i.first] << " "; std::cout << st[i.first] << " ";
std::cout << ANSI_NORMAL; std::cout << ANSI_NORMAL;
std::cout << std::endl; std::cout << std::endl;
@ -2790,7 +2790,7 @@ SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_
if (pathExists(res)) return CanonPath(canonPath(res)); if (pathExists(res)) return CanonPath(canonPath(res));
} }
if (hasPrefix(path, "nix/")) if (path.starts_with("nix/"))
return CanonPath(concatStrings(corepkgsPrefix, path.substr(4))); return CanonPath(concatStrings(corepkgsPrefix, path.substr(4)));
error<ThrownError>( error<ThrownError>(
@ -2823,7 +2823,7 @@ std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Pa
} }
} }
else if (hasPrefix(value, "flake:")) { else if (value.starts_with("flake:")) {
experimentalFeatureSettings.require(Xp::Flakes); experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false); auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false);
debug("fetching flake search path element '%s''", value); debug("fetching flake search path element '%s''", value);

View file

@ -35,7 +35,7 @@ void ConfigFile::apply()
for (auto & [name, value] : settings) { for (auto & [name, value] : settings) {
auto baseName = hasPrefix(name, "extra-") ? std::string(name, 6) : name; auto baseName = name.starts_with("extra-") ? std::string(name, 6) : name;
// FIXME: Move into libutil/config.cc. // FIXME: Move into libutil/config.cc.
std::string valueS; std::string valueS;

View file

@ -186,7 +186,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
} }
} else { } else {
if (!hasPrefix(path, "/")) if (!path.starts_with("/"))
throw BadURL("flake reference '%s' is not an absolute path", url); throw BadURL("flake reference '%s' is not an absolute path", url);
auto query = decodeQuery(match[2]); auto query = decodeQuery(match[2]);
path = canonPath(path + "/" + getOr(query, "dir", "")); path = canonPath(path + "/" + getOr(query, "dir", ""));

View file

@ -223,7 +223,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
Path actualPath(absPath(workdir)); Path actualPath(absPath(workdir));
PathFilter filter = [&](const Path & p) -> bool { PathFilter filter = [&](const Path & p) -> bool {
assert(hasPrefix(p, actualPath)); assert(p.starts_with(actualPath));
std::string file(p, actualPath.size() + 1); std::string file(p, actualPath.size() + 1);
auto st = lstat(p); auto st = lstat(p);
@ -231,7 +231,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
auto prefix = file + "/"; auto prefix = file + "/";
auto i = files.lower_bound(prefix); auto i = files.lower_bound(prefix);
return i != files.end() && hasPrefix(*i, prefix); return i != files.end() && (*i).starts_with(prefix);
} }
return files.count(file); return files.count(file);
@ -267,7 +267,7 @@ struct GitInputScheme : InputScheme
url.scheme != "git+file") return {}; url.scheme != "git+file") return {};
auto url2(url); auto url2(url);
if (hasPrefix(url2.scheme, "git+")) url2.scheme = std::string(url2.scheme, 4); if (url2.scheme.starts_with("git+")) url2.scheme = std::string(url2.scheme, 4);
url2.query.clear(); url2.query.clear();
Attrs attrs; Attrs attrs;

View file

@ -181,7 +181,7 @@ struct MercurialInputScheme : InputScheme
Path actualPath(absPath(actualUrl)); Path actualPath(absPath(actualUrl));
PathFilter filter = [&](const Path & p) -> bool { PathFilter filter = [&](const Path & p) -> bool {
assert(hasPrefix(p, actualPath)); assert(p.starts_with(actualPath));
std::string file(p, actualPath.size() + 1); std::string file(p, actualPath.size() + 1);
auto st = lstat(p); auto st = lstat(p);
@ -189,7 +189,7 @@ struct MercurialInputScheme : InputScheme
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
auto prefix = file + "/"; auto prefix = file + "/";
auto i = files.lower_bound(prefix); auto i = files.lower_bound(prefix);
return i != files.end() && hasPrefix(*i, prefix); return i != files.end() && (*i).starts_with(prefix);
} }
return files.count(file); return files.count(file);

View file

@ -157,7 +157,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
return std::make_shared<Registry>(Registry::Global); // empty registry return std::make_shared<Registry>(Registry::Global); // empty registry
} }
if (!hasPrefix(path, "/")) { if (!path.starts_with("/")) {
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath; auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json"); store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");

View file

@ -188,10 +188,10 @@ struct CurlInputScheme : InputScheme
const bool hasTarballExtension(std::string_view path) const const bool hasTarballExtension(std::string_view path) const
{ {
return hasSuffix(path, ".zip") || hasSuffix(path, ".tar") return path.ends_with(".zip") || path.ends_with(".tar")
|| hasSuffix(path, ".tgz") || hasSuffix(path, ".tar.gz") || path.ends_with(".tgz") || path.ends_with(".tar.gz")
|| hasSuffix(path, ".tar.xz") || hasSuffix(path, ".tar.bz2") || path.ends_with(".tar.xz") || path.ends_with(".tar.bz2")
|| hasSuffix(path, ".tar.zst"); || path.ends_with(".tar.zst");
} }
virtual bool isValidURL(const ParsedURL & url, bool requireTree) const = 0; virtual bool isValidURL(const ParsedURL & url, bool requireTree) const = 0;

View file

@ -47,7 +47,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
std::map<std::string, Config::SettingInfo> settings; std::map<std::string, Config::SettingInfo> settings;
globalConfig.getSettings(settings); globalConfig.getSettings(settings);
for (auto & s : settings) for (auto & s : settings)
if (hasPrefix(s.first, prefix)) if (s.first.starts_with(prefix))
completions->add(s.first, fmt("Set the `%s` setting.", s.first)); completions->add(s.first, fmt("Set the `%s` setting.", s.first));
} }
} }

View file

@ -188,7 +188,7 @@ public:
if (type == actBuild) { if (type == actBuild) {
std::string name(storePathToName(getS(fields, 0))); std::string name(storePathToName(getS(fields, 0)));
if (hasSuffix(name, ".drv")) if (name.ends_with(".drv"))
name = name.substr(0, name.size() - 4); name = name.substr(0, name.size() - 4);
i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name); i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name);
auto machineName = getS(fields, 1); auto machineName = getS(fields, 1);
@ -207,7 +207,7 @@ public:
auto name = storePathToName(getS(fields, 0)); auto name = storePathToName(getS(fields, 0));
auto sub = getS(fields, 1); auto sub = getS(fields, 1);
i->s = fmt( i->s = fmt(
hasPrefix(sub, "local") sub.starts_with("local")
? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s" ? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s"
: "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s", : "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s",
name, sub); name, sub);
@ -215,7 +215,7 @@ public:
if (type == actPostBuildHook) { if (type == actPostBuildHook) {
auto name = storePathToName(getS(fields, 0)); auto name = storePathToName(getS(fields, 0));
if (hasSuffix(name, ".drv")) if (name.ends_with(".drv"))
name = name.substr(0, name.size() - 4); name = name.substr(0, name.size() - 4);
i->s = fmt("post-build " ANSI_BOLD "%s" ANSI_NORMAL, name); i->s = fmt("post-build " ANSI_BOLD "%s" ANSI_NORMAL, name);
i->name = DrvName(name).name; i->name = DrvName(name).name;

View file

@ -596,7 +596,7 @@ void LocalDerivationGoal::startBuilder()
else else
pathsInChroot[i.substr(0, p)] = {i.substr(p + 1), optional}; pathsInChroot[i.substr(0, p)] = {i.substr(p + 1), optional};
} }
if (hasPrefix(worker.store.storeDir, tmpDirInSandbox)) if (worker.store.storeDir.starts_with(tmpDirInSandbox))
{ {
throw Error("`sandbox-build-dir` must not contain the storeDir"); throw Error("`sandbox-build-dir` must not contain the storeDir");
} }

View file

@ -53,13 +53,13 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
* Python package brings its own * Python package brings its own
* `$out/lib/pythonX.Y/site-packages/easy-install.pth'.) * `$out/lib/pythonX.Y/site-packages/easy-install.pth'.)
*/ */
if (hasSuffix(srcFile, "/propagated-build-inputs") || if (srcFile.ends_with("/propagated-build-inputs") ||
hasSuffix(srcFile, "/nix-support") || srcFile.ends_with("/nix-support") ||
hasSuffix(srcFile, "/perllocal.pod") || srcFile.ends_with("/perllocal.pod") ||
hasSuffix(srcFile, "/info/dir") || srcFile.ends_with("/info/dir") ||
hasSuffix(srcFile, "/log") || srcFile.ends_with("/log") ||
hasSuffix(srcFile, "/manifest.nix") || srcFile.ends_with("/manifest.nix") ||
hasSuffix(srcFile, "/manifest.json")) srcFile.ends_with("/manifest.json"))
continue; continue;
else if (S_ISDIR(srcSt.st_mode)) { else if (S_ISDIR(srcSt.st_mode)) {

View file

@ -41,7 +41,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
request.decompress = false; request.decompress = false;
auto decompressor = makeDecompressionSink( auto decompressor = makeDecompressionSink(
unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink); unpack && mainUrl.ends_with(".xz") ? "xz" : "none", sink);
fileTransfer->download(std::move(request), *decompressor); fileTransfer->download(std::move(request), *decompressor);
decompressor->finish(); decompressor->finish();
}); });
@ -62,7 +62,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
if (getAttr("outputHashMode") == "flat") if (getAttr("outputHashMode") == "flat")
for (auto hashedMirror : settings.hashedMirrors.get()) for (auto hashedMirror : settings.hashedMirrors.get())
try { try {
if (!hasSuffix(hashedMirror, "/")) hashedMirror += '/'; if (!hashedMirror.ends_with("/")) hashedMirror += '/';
std::optional<HashType> ht = parseHashTypeOpt(getAttr("outputHashAlgo")); std::optional<HashType> ht = parseHashTypeOpt(getAttr("outputHashAlgo"));
Hash h = newHashAllowEmpty(getAttr("outputHash"), ht); Hash h = newHashAllowEmpty(getAttr("outputHash"), ht);
fetch(hashedMirror + printHashType(h.type) + "/" + h.to_string(Base16, false)); fetch(hashedMirror + printHashType(h.type) + "/" + h.to_string(Base16, false));

View file

@ -221,7 +221,7 @@ struct ClientSettings
for (auto & s : ss) for (auto & s : ss)
if (trusted.count(s)) if (trusted.count(s))
subs.push_back(s); subs.push_back(s);
else if (!hasSuffix(s, "/") && trusted.count(s + "/")) else if (!s.ends_with("/") && trusted.count(s + "/"))
subs.push_back(s + "/"); subs.push_back(s + "/");
else else
warn("ignoring untrusted substituter '%s', you are not a trusted user.\n" warn("ignoring untrusted substituter '%s', you are not a trusted user.\n"

View file

@ -658,7 +658,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
// FIXME: remove // FIXME: remove
bool isDerivation(std::string_view fileName) bool isDerivation(std::string_view fileName)
{ {
return hasSuffix(fileName, drvExtension); return fileName.ends_with(drvExtension);
} }
@ -927,7 +927,7 @@ std::string_view BasicDerivation::nameFromPath(const StorePath & drvPath)
{ {
auto nameWithSuffix = drvPath.name(); auto nameWithSuffix = drvPath.name();
constexpr std::string_view extension = ".drv"; constexpr std::string_view extension = ".drv";
assert(hasSuffix(nameWithSuffix, extension)); assert(nameWithSuffix.ends_with(extension));
nameWithSuffix.remove_suffix(extension.size()); nameWithSuffix.remove_suffix(extension.size());
return nameWithSuffix; return nameWithSuffix;
} }

View file

@ -670,8 +670,8 @@ struct curlFileTransfer : public FileTransfer
void enqueueItem(std::shared_ptr<TransferItem> item) void enqueueItem(std::shared_ptr<TransferItem> item)
{ {
if (item->request.data if (item->request.data
&& !hasPrefix(item->request.uri, "http://") && !item->request.uri.starts_with("http://")
&& !hasPrefix(item->request.uri, "https://")) && !item->request.uri.starts_with("https://"))
throw nix::Error("uploading to '%s' is not supported", item->request.uri); throw nix::Error("uploading to '%s' is not supported", item->request.uri);
{ {
@ -703,7 +703,7 @@ struct curlFileTransfer : public FileTransfer
Callback<FileTransferResult> callback) override Callback<FileTransferResult> callback) override
{ {
/* Ugly hack to support s3:// URIs. */ /* Ugly hack to support s3:// URIs. */
if (hasPrefix(request.uri, "s3://")) { if (request.uri.starts_with("s3://")) {
// FIXME: do this on a worker thread // FIXME: do this on a worker thread
try { try {
#if ENABLE_S3 #if ENABLE_S3

View file

@ -241,7 +241,7 @@ bool Settings::isWSL1()
uname(&utsbuf); uname(&utsbuf);
// WSL1 uses -Microsoft suffix // WSL1 uses -Microsoft suffix
// WSL2 uses -microsoft-standard suffix // WSL2 uses -microsoft-standard suffix
return hasSuffix(utsbuf.release, "-Microsoft"); return std::string_view(utsbuf.release).ends_with("-Microsoft");
} }
Path Settings::getDefaultSSLCertFile() Path Settings::getDefaultSSLCertFile()
@ -415,7 +415,7 @@ void initLibStore() {
sshd). This breaks build users because they don't have access sshd). This breaks build users because they don't have access
to the TMPDIR, in particular in nix-store --serve. */ to the TMPDIR, in particular in nix-store --serve. */
#if __APPLE__ #if __APPLE__
if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/")) if (getEnv("TMPDIR").value_or("/tmp").starts_with("/var/folders/"))
unsetenv("TMPDIR"); unsetenv("TMPDIR");
#endif #endif

View file

@ -145,7 +145,7 @@ protected:
FileTransferRequest makeRequest(const std::string & path) FileTransferRequest makeRequest(const std::string & path)
{ {
return FileTransferRequest( return FileTransferRequest(
hasPrefix(path, "https://") || hasPrefix(path, "http://") || hasPrefix(path, "file://") path.starts_with("https://") || path.starts_with("http://") || path.starts_with("file://")
? path ? path
: cacheUri + "/" + path); : cacheUri + "/" + path);

View file

@ -85,7 +85,7 @@ protected:
for (auto & entry : readDirectory(binaryCacheDir)) { for (auto & entry : readDirectory(binaryCacheDir)) {
if (entry.name.size() != 40 || if (entry.name.size() != 40 ||
!hasSuffix(entry.name, ".narinfo")) !entry.name.ends_with(".narinfo"))
continue; continue;
paths.insert(parseStorePath( paths.insert(parseStorePath(
storeDir + "/" + entry.name.substr(0, entry.name.size() - 8) storeDir + "/" + entry.name.substr(0, entry.name.size() - 8)

View file

@ -24,10 +24,10 @@ Machine::Machine(decltype(storeUri) storeUri,
|| storeUri == "auto" || storeUri == "auto"
|| storeUri == "daemon" || storeUri == "daemon"
|| storeUri == "local" || storeUri == "local"
|| hasPrefix(storeUri, "auto?") || storeUri.starts_with("auto?")
|| hasPrefix(storeUri, "daemon?") || storeUri.starts_with("daemon?")
|| hasPrefix(storeUri, "local?") || storeUri.starts_with("local?")
|| hasPrefix(storeUri, "?") || storeUri.starts_with("?")
? storeUri ? storeUri
: "ssh://" + storeUri), : "ssh://" + storeUri),
systemTypes(systemTypes), systemTypes(systemTypes),
@ -67,12 +67,12 @@ bool Machine::mandatoryMet(const std::set<std::string> & features) const
ref<Store> Machine::openStore() const ref<Store> Machine::openStore() const
{ {
Store::Params storeParams; Store::Params storeParams;
if (hasPrefix(storeUri, "ssh://")) { if (storeUri.starts_with("ssh://")) {
storeParams["max-connections"] = "1"; storeParams["max-connections"] = "1";
storeParams["log-fd"] = "4"; storeParams["log-fd"] = "4";
} }
if (hasPrefix(storeUri, "ssh://") || hasPrefix(storeUri, "ssh-ng://")) { if (storeUri.starts_with("ssh://") || storeUri.starts_with("ssh-ng://")) {
if (sshKey != "") if (sshKey != "")
storeParams["ssh-key"] = sshKey; storeParams["ssh-key"] = sshKey;
if (sshPublicHostKey != "") if (sshPublicHostKey != "")

View file

@ -42,7 +42,7 @@ StorePath::StorePath(const Hash & hash, std::string_view _name)
bool StorePath::isDerivation() const bool StorePath::isDerivation() const
{ {
return hasSuffix(name(), drvExtension); return name().ends_with(drvExtension);
} }
StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x"); StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x");

View file

@ -448,11 +448,11 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
return std::make_shared<std::stringstream>(std::move(compressed)); return std::make_shared<std::stringstream>(std::move(compressed));
}; };
if (narinfoCompression != "" && hasSuffix(path, ".narinfo")) if (narinfoCompression != "" && path.ends_with(".narinfo"))
uploadFile(path, compress(narinfoCompression), mimeType, narinfoCompression); uploadFile(path, compress(narinfoCompression), mimeType, narinfoCompression);
else if (lsCompression != "" && hasSuffix(path, ".ls")) else if (lsCompression != "" && path.ends_with(".ls"))
uploadFile(path, compress(lsCompression), mimeType, lsCompression); uploadFile(path, compress(lsCompression), mimeType, lsCompression);
else if (logCompression != "" && hasPrefix(path, "log/")) else if (logCompression != "" && path.starts_with("log/"))
uploadFile(path, compress(logCompression), mimeType, logCompression); uploadFile(path, compress(logCompression), mimeType, logCompression);
else else
uploadFile(path, istream, mimeType, ""); uploadFile(path, istream, mimeType, "");
@ -499,7 +499,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
for (auto object : contents) { for (auto object : contents) {
auto & key = object.GetKey(); auto & key = object.GetKey();
if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue; if (key.size() != 40 || !key.ends_with(".narinfo")) continue;
paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName)); paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName));
} }

View file

@ -12,7 +12,7 @@ SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, cons
, compress(compress) , compress(compress)
, logFD(logFD) , logFD(logFD)
{ {
if (host == "" || hasPrefix(host, "-")) if (host == "" || host.starts_with("-"))
throw Error("invalid SSH host name '%s'", host); throw Error("invalid SSH host name '%s'", host);
auto state(state_.lock()); auto state(state_.lock());

View file

@ -162,7 +162,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
if (auto prefix = needsCompletion(*pos)) { if (auto prefix = needsCompletion(*pos)) {
for (auto & [name, flag] : longFlags) { for (auto & [name, flag] : longFlags) {
if (!hiddenCategories.count(flag->category) if (!hiddenCategories.count(flag->category)
&& hasPrefix(name, std::string(*prefix, 2))) && name.starts_with(std::string(*prefix, 2)))
{ {
if (auto & f = flag->experimentalFeature) if (auto & f = flag->experimentalFeature)
flagExperimentalFeatures.insert(*f); flagExperimentalFeatures.insert(*f);
@ -274,7 +274,7 @@ nlohmann::json Args::toJSON()
static void hashTypeCompleter(size_t index, std::string_view prefix) static void hashTypeCompleter(size_t index, std::string_view prefix)
{ {
for (auto & type : hashTypes) for (auto & type : hashTypes)
if (hasPrefix(type, prefix)) if (type.starts_with(prefix))
completions->add(type); completions->add(type);
} }
@ -370,7 +370,7 @@ MultiCommand::MultiCommand(const Commands & commands_)
}}, }},
.completer = {[&](size_t, std::string_view prefix) { .completer = {[&](size_t, std::string_view prefix) {
for (auto & [name, command] : commands) for (auto & [name, command] : commands)
if (hasPrefix(name, prefix)) if (name.starts_with(prefix))
completions->add(name); completions->add(name);
}} }}
}); });

View file

@ -41,7 +41,7 @@ std::map<std::string, std::string> getCgroups(const Path & cgroupFile)
if (!std::regex_match(line, match, regex)) if (!std::regex_match(line, match, regex))
throw Error("invalid line '%s' in '%s'", line, cgroupFile); throw Error("invalid line '%s' in '%s'", line, cgroupFile);
std::string name = hasPrefix(std::string(match[2]), "name=") ? std::string(match[2], 5) : match[2]; std::string name = std::string(match[2]).starts_with("name=") ? std::string(match[2], 5) : match[2];
cgroups.insert_or_assign(name, match[3]); cgroups.insert_or_assign(name, match[3]);
} }
@ -117,13 +117,13 @@ static CgroupStats destroyCgroup(const Path & cgroup, bool returnStats)
if (pathExists(cpustatPath)) { if (pathExists(cpustatPath)) {
for (auto & line : tokenizeString<std::vector<std::string>>(readFile(cpustatPath), "\n")) { for (auto & line : tokenizeString<std::vector<std::string>>(readFile(cpustatPath), "\n")) {
std::string_view userPrefix = "user_usec "; std::string_view userPrefix = "user_usec ";
if (hasPrefix(line, userPrefix)) { if (line.starts_with(userPrefix)) {
auto n = string2Int<uint64_t>(line.substr(userPrefix.size())); auto n = string2Int<uint64_t>(line.substr(userPrefix.size()));
if (n) stats.cpuUser = std::chrono::microseconds(*n); if (n) stats.cpuUser = std::chrono::microseconds(*n);
} }
std::string_view systemPrefix = "system_usec "; std::string_view systemPrefix = "system_usec ";
if (hasPrefix(line, systemPrefix)) { if (line.starts_with(systemPrefix)) {
auto n = string2Int<uint64_t>(line.substr(systemPrefix.size())); auto n = string2Int<uint64_t>(line.substr(systemPrefix.size()));
if (n) stats.cpuSystem = std::chrono::microseconds(*n); if (n) stats.cpuSystem = std::chrono::microseconds(*n);
} }

View file

@ -18,7 +18,7 @@ bool Config::set(const std::string & name, const std::string & value)
bool append = false; bool append = false;
auto i = _settings.find(name); auto i = _settings.find(name);
if (i == _settings.end()) { if (i == _settings.end()) {
if (hasPrefix(name, "extra-")) { if (name.starts_with("extra-")) {
i = _settings.find(std::string(name, 6)); i = _settings.find(std::string(name, 6));
if (i == _settings.end() || !i->second.setting->isAppendable()) if (i == _settings.end() || !i->second.setting->isAppendable())
return false; return false;

View file

@ -266,7 +266,7 @@ static Logger::Fields getFields(nlohmann::json & json)
std::optional<nlohmann::json> parseJSONMessage(const std::string & msg) std::optional<nlohmann::json> parseJSONMessage(const std::string & msg)
{ {
if (!hasPrefix(msg, "@nix ")) return std::nullopt; if (!msg.starts_with("@nix ")) return std::nullopt;
try { try {
return nlohmann::json::parse(std::string(msg, 5)); return nlohmann::json::parse(std::string(msg, 5));
} catch (std::exception & e) { } catch (std::exception & e) {

View file

@ -83,7 +83,7 @@ SourcePath SourcePath::resolveSymlinks(SymlinkResolution mode) const
throw Error("infinite symlink recursion in path '%s'", path); throw Error("infinite symlink recursion in path '%s'", path);
auto target = res.readLink(); auto target = res.readLink();
res.path.pop(); res.path.pop();
if (hasPrefix(target, "/")) if (target.starts_with("/"))
res.path = CanonPath::root; res.path = CanonPath::root;
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/")); todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
} }

View file

@ -27,7 +27,7 @@ static inline std::optional<std::string_view> splitPrefixTo(std::string_view & s
} }
static inline bool splitPrefix(std::string_view & string, std::string_view prefix) { static inline bool splitPrefix(std::string_view & string, std::string_view prefix) {
bool res = hasPrefix(string, prefix); bool res = string.starts_with(prefix);
if (res) if (res)
string.remove_prefix(prefix.length()); string.remove_prefix(prefix.length());
return res; return res;

View file

@ -1449,19 +1449,6 @@ bool statusOk(int status)
} }
bool hasPrefix(std::string_view s, std::string_view prefix)
{
return s.compare(0, prefix.size(), prefix) == 0;
}
bool hasSuffix(std::string_view s, std::string_view suffix)
{
return s.size() >= suffix.size()
&& s.substr(s.size() - suffix.size()) == suffix;
}
std::string toLower(const std::string & s) std::string toLower(const std::string & s)
{ {
std::string r(s); std::string r(s);

View file

@ -665,19 +665,6 @@ T readLittleEndian(unsigned char * p)
return x; return x;
} }
/**
* @return true iff `s` starts with `prefix`.
*/
bool hasPrefix(std::string_view s, std::string_view prefix);
/**
* @return true iff `s` ends in `suffix`.
*/
bool hasSuffix(std::string_view s, std::string_view suffix);
/** /**
* Convert a string to lower case. * Convert a string to lower case.
*/ */

View file

@ -305,7 +305,7 @@ static void main_nix_build(int argc, char * * argv)
absolute = canonPath(absPath(i), true); absolute = canonPath(absPath(i), true);
} catch (Error & e) {}; } catch (Error & e) {};
auto [path, outputNames] = parsePathWithOutputs(absolute); auto [path, outputNames] = parsePathWithOutputs(absolute);
if (evalStore->isStorePath(path) && hasSuffix(path, ".drv")) if (evalStore->isStorePath(path) && path.ends_with(".drv"))
drvs.push_back(DrvInfo(*state, evalStore, absolute)); drvs.push_back(DrvInfo(*state, evalStore, absolute));
else else
/* If we're in a #! script, interpret filenames /* If we're in a #! script, interpret filenames

View file

@ -200,7 +200,7 @@ static int main_nix_channel(int argc, char ** argv)
} else if (*arg == "--rollback") { } else if (*arg == "--rollback") {
cmd = cRollback; cmd = cRollback;
} else { } else {
if (hasPrefix(*arg, "-")) if ((*arg).starts_with("-"))
throw UsageError("unsupported argument '%s'", *arg); throw UsageError("unsupported argument '%s'", *arg);
args.push_back(std::move(*arg)); args.push_back(std::move(*arg));
} }

View file

@ -125,13 +125,13 @@ static void getAllExprs(EvalState & state,
continue; // ignore dangling symlinks in ~/.nix-defexpr continue; // ignore dangling symlinks in ~/.nix-defexpr
} }
if (isNixExpr(path2, st) && (st.type != InputAccessor::tRegular || hasSuffix(path2.baseName(), ".nix"))) { if (isNixExpr(path2, st) && (st.type != InputAccessor::tRegular || path2.baseName().ends_with(".nix"))) {
/* Strip off the `.nix' filename suffix (if applicable), /* Strip off the `.nix' filename suffix (if applicable),
otherwise the attribute cannot be selected with the otherwise the attribute cannot be selected with the
`-A' option. Useful if you want to stick a Nix `-A' option. Useful if you want to stick a Nix
expression directly in ~/.nix-defexpr. */ expression directly in ~/.nix-defexpr. */
std::string attrName = i; std::string attrName = i;
if (hasSuffix(attrName, ".nix")) if (attrName.ends_with(".nix"))
attrName = std::string(attrName, 0, attrName.size() - 4); attrName = std::string(attrName, 0, attrName.size() - 4);
if (!seen.insert(attrName).second) { if (!seen.insert(attrName).second) {
std::string suggestionMessage = ""; std::string suggestionMessage = "";
@ -241,7 +241,7 @@ std::set<std::string> searchByPrefix(const DrvInfos & allElems, std::string_view
std::set<std::string> result; std::set<std::string> result;
for (const auto & drvInfo : allElems) { for (const auto & drvInfo : allElems) {
const auto drvName = DrvName { drvInfo.queryName() }; const auto drvName = DrvName { drvInfo.queryName() };
if (hasPrefix(drvName.name, prefix)) { if (drvName.name.starts_with(prefix)) {
result.emplace(drvName.name); result.emplace(drvName.name);
if (result.size() >= maxResults) { if (result.size() >= maxResults) {

View file

@ -448,7 +448,7 @@ struct Common : InstallableCommand, MixProfile
StorePath getShellOutPath(ref<Store> store, ref<Installable> installable) StorePath getShellOutPath(ref<Store> store, ref<Installable> installable)
{ {
auto path = installable->getStorePath(); auto path = installable->getStorePath();
if (path && hasSuffix(path->to_string(), "-env")) if (path && path->to_string().ends_with("-env"))
return *path; return *path;
else { else {
auto drvs = Installable::toDerivations(store, {installable}); auto drvs = Installable::toDerivations(store, {installable});

View file

@ -101,7 +101,7 @@ struct CmdDoctor : StoreCommand
try { try {
Path userEnv = canonPath(profileDir, true); Path userEnv = canonPath(profileDir, true);
if (store->isStorePath(userEnv) && hasSuffix(userEnv, "user-environment")) { if (store->isStorePath(userEnv) && userEnv.ends_with("user-environment")) {
while (profileDir.find("/profiles/") == std::string::npos && isLink(profileDir)) while (profileDir.find("/profiles/") == std::string::npos && isLink(profileDir))
profileDir = absPath(readLink(profileDir), dirOf(profileDir)); profileDir = absPath(readLink(profileDir), dirOf(profileDir));

View file

@ -334,7 +334,7 @@ struct CmdFlakeCheck : FlakeCommand
return return
name == expected name == expected
|| name == "_" || name == "_"
|| (hasPrefix(name, "_") && name.substr(1) == expected); || (name.starts_with("_") && name.substr(1) == expected);
}; };
auto checkSystemName = [&](const std::string & system, const PosIdx pos) { auto checkSystemName = [&](const std::string & system, const PosIdx pos) {

View file

@ -42,7 +42,7 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url)
throw Error("mirror URL '%s' did not expand to anything", url); throw Error("mirror URL '%s' did not expand to anything", url);
std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror")); std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror"));
return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1); return mirror + (mirror.ends_with("/") ? "" : "/") + s.substr(p + 1);
} }
std::tuple<StorePath, Hash> prefetchFile( std::tuple<StorePath, Hash> prefetchFile(

View file

@ -115,7 +115,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
printInfo("found Nix in '%s'", where); printInfo("found Nix in '%s'", where);
if (hasPrefix(where, "/run/current-system")) if (where.starts_with("/run/current-system"))
throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'"); throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'");
Path profileDir = dirOf(where); Path profileDir = dirOf(where);
@ -129,7 +129,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
Path userEnv = canonPath(profileDir, true); Path userEnv = canonPath(profileDir, true);
if (baseNameOf(where) != "bin" || if (baseNameOf(where) != "bin" ||
!hasSuffix(userEnv, "user-environment")) !userEnv.ends_with("user-environment"))
throw Error("directory '%s' does not appear to be part of a Nix profile", where); throw Error("directory '%s' does not appear to be part of a Nix profile", where);
if (!store->isValidPath(store->parseStorePath(userEnv))) if (!store->isValidPath(store->parseStorePath(userEnv)))

View file

@ -105,7 +105,7 @@ bool isSymlink(const Path & path)
Path resolveSymlink(const Path & path) Path resolveSymlink(const Path & path)
{ {
auto target = readLink(path); auto target = readLink(path);
return hasPrefix(target, "/") return target.starts_with("/")
? target ? target
: concatStrings(dirOf(path), "/", target); : concatStrings(dirOf(path), "/", target);
} }
@ -125,7 +125,7 @@ std::set<std::string> resolveTree(const Path & path, PathSet & deps)
std::set<std::string> getPath(const Path & path) std::set<std::string> getPath(const Path & path)
{ {
if (hasPrefix(path, "/dev")) return {}; if (path.starts_with("/dev")) return {};
Path cacheFile = resolveCacheFile(path); Path cacheFile = resolveCacheFile(path);
if (pathExists(cacheFile)) if (pathExists(cacheFile))

View file

@ -234,36 +234,6 @@ namespace nix {
ASSERT_EQ(concatStringsSep(",", strings), "this"); ASSERT_EQ(concatStringsSep(",", strings), "this");
} }
/* ----------------------------------------------------------------------------
* hasPrefix
* --------------------------------------------------------------------------*/
TEST(hasPrefix, emptyStringHasNoPrefix) {
ASSERT_FALSE(hasPrefix("", "foo"));
}
TEST(hasPrefix, emptyStringIsAlwaysPrefix) {
ASSERT_TRUE(hasPrefix("foo", ""));
ASSERT_TRUE(hasPrefix("jshjkfhsadf", ""));
}
TEST(hasPrefix, trivialCase) {
ASSERT_TRUE(hasPrefix("foobar", "foo"));
}
/* ----------------------------------------------------------------------------
* hasSuffix
* --------------------------------------------------------------------------*/
TEST(hasSuffix, emptyStringHasNoSuffix) {
ASSERT_FALSE(hasSuffix("", "foo"));
}
TEST(hasSuffix, trivialCase) {
ASSERT_TRUE(hasSuffix("foo", "foo"));
ASSERT_TRUE(hasSuffix("foobar", "bar"));
}
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* base64Encode * base64Encode
* --------------------------------------------------------------------------*/ * --------------------------------------------------------------------------*/