diff options
Diffstat (limited to 'third_party/nix/src/nix')
29 files changed, 0 insertions, 4288 deletions
diff --git a/third_party/nix/src/nix/add-to-store.cc b/third_party/nix/src/nix/add-to-store.cc deleted file mode 100644 index 53641f120e8f..000000000000 --- a/third_party/nix/src/nix/add-to-store.cc +++ /dev/null @@ -1,51 +0,0 @@ -#include "libmain/common-args.hh" -#include "libstore/store-api.hh" -#include "libutil/archive.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdAddToStore final : MixDryRun, StoreCommand { - Path path; - std::optional<std::string> namePart; - - CmdAddToStore() { - expectArg("path", &path); - - mkFlag() - .longName("name") - .shortName('n') - .description("name component of the store path") - .labels({"name"}) - .dest(&namePart); - } - - std::string name() override { return "add-to-store"; } - - std::string description() override { return "add a path to the Nix store"; } - - Examples examples() override { return {}; } - - void run(ref<Store> store) override { - if (!namePart) { - namePart = baseNameOf(path); - } - - StringSink sink; - dumpPath(path, sink); - - ValidPathInfo info; - info.narHash = hashString(htSHA256, *sink.s); - info.narSize = sink.s->size(); - info.path = store->makeFixedOutputPath(true, info.narHash, *namePart); - info.ca = makeFixedOutputCA(true, info.narHash); - - if (!dryRun) { - store->addToStore(info, sink.s); - } - - std::cout << fmt("%s\n", info.path); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdAddToStore>()); diff --git a/third_party/nix/src/nix/build.cc b/third_party/nix/src/nix/build.cc deleted file mode 100644 index 3fe74b7ffdba..000000000000 --- a/third_party/nix/src/nix/build.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdBuild final : MixDryRun, InstallablesCommand { - Path outLink = "result"; - - CmdBuild() { - mkFlag() - .longName("out-link") - .shortName('o') - .description("path of the symlink to the build result") - .labels({"path"}) - .dest(&outLink); - - mkFlag() - .longName("no-link") - .description("do not create a symlink to the build result") - .set(&outLink, Path("")); - } - - std::string name() override { return "build"; } - - std::string description() override { - return "build a derivation or fetch a store path"; - } - - Examples examples() override { - return { - Example{"To build and run GNU Hello from NixOS 17.03:", - "nix build -f channel:nixos-17.03 hello; ./result/bin/hello"}, - Example{"To build the build.x86_64-linux attribute from release.nix:", - "nix build -f release.nix build.x86_64-linux"}, - }; - } - - void run(ref<Store> store) override { - auto buildables = build(store, dryRun ? DryRun : Build, installables); - - if (dryRun) { - return; - } - - for (size_t i = 0; i < buildables.size(); ++i) { - auto& b(buildables[i]); - - if (!outLink.empty()) { - for (auto& output : b.outputs) { - if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) { - std::string symlink = outLink; - if (i != 0u) { - symlink += fmt("-%d", i); - } - if (output.first != "out") { - symlink += fmt("-%s", output.first); - } - store2->addPermRoot(output.second, absPath(symlink), true); - } - } - } - } - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdBuild>()); diff --git a/third_party/nix/src/nix/cat.cc b/third_party/nix/src/nix/cat.cc deleted file mode 100644 index 7788707eae56..000000000000 --- a/third_party/nix/src/nix/cat.cc +++ /dev/null @@ -1,56 +0,0 @@ -#include "libstore/fs-accessor.hh" -#include "libstore/nar-accessor.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct MixCat : virtual Args { - std::string path; - - void cat(const ref<FSAccessor>& accessor) { - auto st = accessor->stat(path); - if (st.type == FSAccessor::Type::tMissing) { - throw Error(format("path '%1%' does not exist") % path); - } - if (st.type != FSAccessor::Type::tRegular) { - throw Error(format("path '%1%' is not a regular file") % path); - } - - std::cout << accessor->readFile(path); - } -}; - -struct CmdCatStore final : StoreCommand, MixCat { - CmdCatStore() { expectArg("path", &path); } - - std::string name() override { return "cat-store"; } - - std::string description() override { - return "print the contents of a store file on stdout"; - } - - void run(ref<Store> store) override { cat(store->getFSAccessor()); } -}; - -struct CmdCatNar final : StoreCommand, MixCat { - Path narPath; - - CmdCatNar() { - expectArg("nar", &narPath); - expectArg("path", &path); - } - - std::string name() override { return "cat-nar"; } - - std::string description() override { - return "print the contents of a file inside a NAR file"; - } - - void run(ref<Store> store) override { - cat(makeNarAccessor(make_ref<std::string>(readFile(narPath)))); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdCatStore>()); -static nix::RegisterCommand r2(nix::make_ref<nix::CmdCatNar>()); diff --git a/third_party/nix/src/nix/command.cc b/third_party/nix/src/nix/command.cc deleted file mode 100644 index f7f183ab0ab7..000000000000 --- a/third_party/nix/src/nix/command.cc +++ /dev/null @@ -1,156 +0,0 @@ -#include "nix/command.hh" - -#include <utility> - -#include "libstore/derivations.hh" -#include "libstore/store-api.hh" - -namespace nix { - -Commands* RegisterCommand::commands = nullptr; - -void Command::printHelp(const std::string& programName, std::ostream& out) { - Args::printHelp(programName, out); - - auto exs = examples(); - if (!exs.empty()) { - out << "\n"; - out << "Examples:\n"; - for (auto& ex : exs) { - out << "\n" - << " " << ex.description << "\n" // FIXME: wrap - << " $ " << ex.command << "\n"; - } - } -} - -MultiCommand::MultiCommand(Commands _commands) - : commands(std::move(_commands)) { - expectedArgs.push_back(ExpectedArg{ - "command", 1, true, [=](std::vector<std::string> ss) { - assert(!command); - auto i = commands.find(ss[0]); - if (i == commands.end()) { - throw UsageError("'%s' is not a recognised command", ss[0]); - } - command = i->second; - }}); -} - -void MultiCommand::printHelp(const std::string& programName, - std::ostream& out) { - if (command) { - command->printHelp(programName + " " + command->name(), out); - return; - } - - out << "Usage: " << programName << " <COMMAND> <FLAGS>... <ARGS>...\n"; - - out << "\n"; - out << "Common flags:\n"; - printFlags(out); - - out << "\n"; - out << "Available commands:\n"; - - Table2 table; - for (auto& command : commands) { - auto descr = command.second->description(); - if (!descr.empty()) { - table.push_back(std::make_pair(command.second->name(), descr)); - } - } - printTable(out, table); - -#if 0 - out << "\n"; - out << "For full documentation, run 'man " << programName << "' or 'man " << programName << "-<COMMAND>'.\n"; -#endif -} - -bool MultiCommand::processFlag(Strings::iterator& pos, Strings::iterator end) { - if (Args::processFlag(pos, end)) { - return true; - } - if (command && command->processFlag(pos, end)) { - return true; - } - return false; -} - -bool MultiCommand::processArgs(const Strings& args, bool finish) { - if (command) { - return command->processArgs(args, finish); - } - return Args::processArgs(args, finish); -} - -StoreCommand::StoreCommand() = default; - -ref<Store> StoreCommand::getStore() { - if (!_store) { - _store = createStore(); - } - return ref<Store>(_store); -} - -ref<Store> StoreCommand::createStore() { return openStore(); } - -void StoreCommand::run() { run(getStore()); } - -StorePathsCommand::StorePathsCommand(bool recursive) : recursive(recursive) { - if (recursive) { - mkFlag() - .longName("no-recursive") - .description("apply operation to specified paths only") - .set(&this->recursive, false); - } else { - mkFlag() - .longName("recursive") - .shortName('r') - .description("apply operation to closure of the specified paths") - .set(&this->recursive, true); - } - - mkFlag(0, "all", "apply operation to the entire store", &all); -} - -void StorePathsCommand::run(ref<Store> store) { - Paths storePaths; - - if (all) { - if (!installables.empty() != 0u) { - throw UsageError("'--all' does not expect arguments"); - } - for (auto& p : store->queryAllValidPaths()) { - storePaths.push_back(p); - } - } - - else { - for (auto& p : toStorePaths(store, NoBuild, installables)) { - storePaths.push_back(p); - } - - if (recursive) { - PathSet closure; - store->computeFSClosure(PathSet(storePaths.begin(), storePaths.end()), - closure, false, false); - storePaths = Paths(closure.begin(), closure.end()); - } - } - - run(store, storePaths); -} - -void StorePathCommand::run(ref<Store> store) { - auto storePaths = toStorePaths(store, NoBuild, installables); - - if (storePaths.size() != 1) { - throw UsageError("this command requires exactly one store path"); - } - - run(store, *storePaths.begin()); -} - -} // namespace nix diff --git a/third_party/nix/src/nix/command.hh b/third_party/nix/src/nix/command.hh deleted file mode 100644 index 87e2fbe9d28d..000000000000 --- a/third_party/nix/src/nix/command.hh +++ /dev/null @@ -1,194 +0,0 @@ -#pragma once - -#include <memory> - -#include "libexpr/common-eval-args.hh" -#include "libutil/args.hh" - -namespace nix { - -extern std::string programPath; - -struct Value; -class Bindings; -class EvalState; - -/* A command is an argument parser that can be executed by calling its - run() method. */ -struct Command : virtual Args { - virtual std::string name() = 0; - virtual void prepare(){}; - virtual void run() = 0; - - struct Example { - std::string description; - std::string command; - }; - - typedef std::list<Example> Examples; - - virtual Examples examples() { return Examples(); } - - void printHelp(const std::string& programName, std::ostream& out) override; -}; - -class Store; - -/* A command that require a Nix store. */ -struct StoreCommand : virtual Command { - StoreCommand(); - void run() override; - ref<Store> getStore(); - virtual ref<Store> createStore(); - virtual void run(ref<Store>) = 0; - - private: - std::shared_ptr<Store> _store; -}; - -struct Buildable { - Path drvPath; // may be empty - std::map<std::string, Path> outputs; -}; - -using Buildables = std::vector<Buildable>; - -struct Installable { - virtual std::string what() = 0; - - virtual Buildables toBuildables() { - throw Error("argument '%s' cannot be built", what()); - } - - Buildable toBuildable(); - - virtual Value* toValue(EvalState& state) { - throw Error("argument '%s' cannot be evaluated", what()); - } -}; - -struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs { - Path file; - - SourceExprCommand(); - - /* Return a value representing the Nix expression from which we - are installing. This is either the file specified by ‘--file’, - or an attribute set constructed from $NIX_PATH, e.g. ‘{ nixpkgs - = import ...; bla = import ...; }’. */ - Value* getSourceExpr(EvalState& state); - - ref<EvalState> getEvalState(); - - private: - std::shared_ptr<EvalState> evalState; - std::shared_ptr<Value*> vSourceExpr; -}; - -enum RealiseMode { Build, NoBuild, DryRun }; - -/* A command that operates on a list of "installables", which can be - store paths, attribute paths, Nix expressions, etc. */ -struct InstallablesCommand : virtual Args, SourceExprCommand { - std::vector<std::shared_ptr<Installable>> installables; - - InstallablesCommand() { expectArgs("installables", &_installables); } - - void prepare() override; - - virtual bool useDefaultInstallables() { return true; } - - private: - std::vector<std::string> _installables; -}; - -struct InstallableCommand : virtual Args, SourceExprCommand { - std::shared_ptr<Installable> installable; - - InstallableCommand() { expectArg("installable", &_installable); } - - void prepare() override; - - private: - std::string _installable; -}; - -/* A command that operates on zero or more store paths. */ -struct StorePathsCommand : public InstallablesCommand { - private: - bool recursive = false; - bool all = false; - - public: - StorePathsCommand(bool recursive = false); - - using StoreCommand::run; - - virtual void run(ref<Store> store, Paths storePaths) = 0; - - void run(ref<Store> store) override; - - bool useDefaultInstallables() override { return !all; } -}; - -/* A command that operates on exactly one store path. */ -struct StorePathCommand : public InstallablesCommand { - using StoreCommand::run; - - virtual void run(ref<Store> store, const Path& storePath) = 0; - - void run(ref<Store> store) override; -}; - -using Commands = std::map<std::string, ref<Command>>; - -/* An argument parser that supports multiple subcommands, - i.e. ‘<command> <subcommand>’. */ -class MultiCommand : virtual Args { - public: - Commands commands; - - std::shared_ptr<Command> command; - - MultiCommand(Commands commands); - - void printHelp(const std::string& programName, std::ostream& out) override; - - bool processFlag(Strings::iterator& pos, Strings::iterator end) override; - - bool processArgs(const Strings& args, bool finish) override; -}; - -/* A helper class for registering commands globally. */ -struct RegisterCommand { - static Commands* commands; - - RegisterCommand(ref<Command> command) { - if (!commands) { - commands = new Commands; - } - commands->emplace(command->name(), command); - } -}; - -std::shared_ptr<Installable> parseInstallable(SourceExprCommand& cmd, - const ref<Store>& store, - const std::string& installable, - bool useDefaultInstallables); - -Buildables build(const ref<Store>& store, RealiseMode mode, - const std::vector<std::shared_ptr<Installable>>& installables); - -PathSet toStorePaths( - const ref<Store>& store, RealiseMode mode, - const std::vector<std::shared_ptr<Installable>>& installables); - -Path toStorePath(const ref<Store>& store, RealiseMode mode, - const std::shared_ptr<Installable>& installable); - -PathSet toDerivations( - const ref<Store>& store, - const std::vector<std::shared_ptr<Installable>>& installables, - bool useDeriver = false); - -} // namespace nix diff --git a/third_party/nix/src/nix/copy.cc b/third_party/nix/src/nix/copy.cc deleted file mode 100644 index 75c85698d11e..000000000000 --- a/third_party/nix/src/nix/copy.cc +++ /dev/null @@ -1,86 +0,0 @@ -#include <atomic> - -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "libutil/sync.hh" -#include "libutil/thread-pool.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdCopy final : StorePathsCommand { - std::string srcUri, dstUri; - - CheckSigsFlag checkSigs = CheckSigs; - - SubstituteFlag substitute = NoSubstitute; - - CmdCopy() : StorePathsCommand(true) { - mkFlag() - .longName("from") - .labels({"store-uri"}) - .description("URI of the source Nix store") - .dest(&srcUri); - mkFlag() - .longName("to") - .labels({"store-uri"}) - .description("URI of the destination Nix store") - .dest(&dstUri); - - mkFlag() - .longName("no-check-sigs") - .description("do not require that paths are signed by trusted keys") - .set(&checkSigs, NoCheckSigs); - - mkFlag() - .longName("substitute-on-destination") - .shortName('s') - .description( - "whether to try substitutes on the destination store (only " - "supported by SSH)") - .set(&substitute, Substitute); - } - - std::string name() override { return "copy"; } - - std::string description() override { return "copy paths between Nix stores"; } - - Examples examples() override { - return { - Example{"To copy Firefox from the local store to a binary cache in " - "file:///tmp/cache:", - "nix copy --to file:///tmp/cache $(type -p firefox)"}, - Example{"To copy the entire current NixOS system closure to another " - "machine via SSH:", - "nix copy --to ssh://server /run/current-system"}, - Example{"To copy a closure from another machine via SSH:", - "nix copy --from ssh://server " - "/nix/store/a6cnl93nk1wxnq84brbbwr6hxw9gp2w9-blender-2.79-rc2"}, -#ifdef ENABLE_S3 - Example{"To copy Hello to an S3 binary cache:", - "nix copy --to s3://my-bucket?region=eu-west-1 nixpkgs.hello"}, - Example{"To copy Hello to an S3-compatible binary cache:", - "nix copy --to " - "s3://my-bucket?region=eu-west-1&endpoint=example.com " - "nixpkgs.hello"}, -#endif - }; - } - - ref<Store> createStore() override { - return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri); - } - - void run(ref<Store> srcStore, Paths storePaths) override { - if (srcUri.empty() && dstUri.empty()) { - throw UsageError("you must pass '--from' and/or '--to'"); - } - - ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri); - - copyPaths(srcStore, dstStore, PathSet(storePaths.begin(), storePaths.end()), - NoRepair, checkSigs, substitute); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdCopy>()); diff --git a/third_party/nix/src/nix/doctor.cc b/third_party/nix/src/nix/doctor.cc deleted file mode 100644 index d0b4c2b58873..000000000000 --- a/third_party/nix/src/nix/doctor.cc +++ /dev/null @@ -1,142 +0,0 @@ -#include <absl/strings/match.h> -#include <absl/strings/str_cat.h> -#include <absl/strings/str_split.h> - -#include "libmain/shared.hh" -#include "libstore/serve-protocol.hh" -#include "libstore/store-api.hh" -#include "libstore/worker-protocol.hh" -#include "nix/command.hh" - -namespace nix { -static std::string formatProtocol(unsigned int proto) { - if (proto != 0u) { - auto major = GET_PROTOCOL_MAJOR(proto) >> 8; - auto minor = GET_PROTOCOL_MINOR(proto); - return (format("%1%.%2%") % major % minor).str(); - } - return "unknown"; -} - -struct CmdDoctor final : StoreCommand { - bool success = true; - - std::string name() override { return "doctor"; } - - std::string description() override { - return "check your system for potential problems"; - } - - void run(ref<Store> store) override { - std::cout << "Store uri: " << store->getUri() << std::endl; - std::cout << std::endl; - - auto type = getStoreType(); - - if (type < tOther) { - success &= checkNixInPath(); - success &= checkProfileRoots(store); - } - success &= checkStoreProtocol(store->getProtocol()); - - if (!success) { - throw Exit(2); - } - } - - static bool checkNixInPath() { - PathSet dirs; - - for (auto& dir : absl::StrSplit(getEnv("PATH").value_or(""), - absl::ByChar(':'), absl::SkipEmpty())) { - if (pathExists(absl::StrCat(dir, "/nix-env"))) { - dirs.insert(dirOf(canonPath(absl::StrCat(dir, "/nix-env"), true))); - } - } - - if (dirs.size() != 1) { - std::cout << "Warning: multiple versions of nix found in PATH." - << std::endl; - std::cout << std::endl; - for (auto& dir : dirs) { - std::cout << " " << dir << std::endl; - } - std::cout << std::endl; - return false; - } - - return true; - } - - static bool checkProfileRoots(const ref<Store>& store) { - PathSet dirs; - - for (auto dir : absl::StrSplit(getEnv("PATH").value_or(""), - absl::ByChar(':'), absl::SkipEmpty())) { - Path profileDir = dirOf(dir); - try { - Path userEnv = canonPath(profileDir, true); - - if (store->isStorePath(userEnv) && - absl::EndsWith(userEnv, "user-environment")) { - while (profileDir.find("/profiles/") == std::string::npos && - isLink(profileDir)) { - profileDir = absPath(readLink(profileDir), dirOf(profileDir)); - } - - if (profileDir.find("/profiles/") == std::string::npos) { - dirs.insert(std::string(dir)); - } - } - } catch (SysError&) { - } - } - - if (!dirs.empty()) { - std::cout << "Warning: found profiles outside of " << settings.nixStateDir - << "/profiles." << std::endl; - std::cout << "The generation this profile points to might not have a " - "gcroot and could be" - << std::endl; - std::cout << "garbage collected, resulting in broken symlinks." - << std::endl; - std::cout << std::endl; - for (auto& dir : dirs) { - std::cout << " " << dir << std::endl; - } - std::cout << std::endl; - return false; - } - - return true; - } - - static bool checkStoreProtocol(unsigned int storeProto) { - unsigned int clientProto = GET_PROTOCOL_MAJOR(SERVE_PROTOCOL_VERSION) == - GET_PROTOCOL_MAJOR(storeProto) - ? SERVE_PROTOCOL_VERSION - : PROTOCOL_VERSION; - - if (clientProto != storeProto) { - std::cout << "Warning: protocol version of this client does not match " - "the store." - << std::endl; - std::cout << "While this is not necessarily a problem it's recommended " - "to keep the client in" - << std::endl; - std::cout << "sync with the daemon." << std::endl; - std::cout << std::endl; - std::cout << "Client protocol: " << formatProtocol(clientProto) - << std::endl; - std::cout << "Store protocol: " << formatProtocol(storeProto) - << std::endl; - std::cout << std::endl; - return false; - } - - return true; - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdDoctor>()); diff --git a/third_party/nix/src/nix/dump-path.cc b/third_party/nix/src/nix/dump-path.cc deleted file mode 100644 index 1d0a996e561c..000000000000 --- a/third_party/nix/src/nix/dump-path.cc +++ /dev/null @@ -1,28 +0,0 @@ -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdDumpPath final : StorePathCommand { - std::string name() override { return "dump-path"; } - - std::string description() override { - return "dump a store path to stdout (in NAR format)"; - } - - Examples examples() override { - return { - Example{"To get a NAR from the binary cache https://cache.nixos.org/:", - "nix dump-path --store https://cache.nixos.org/ " - "/nix/store/7crrmih8c52r8fbnqb933dxrsp44md93-glibc-2.25"}, - }; - } - - void run(ref<Store> store, const Path& storePath) override { - FdSink sink(STDOUT_FILENO); - store->narFromPath(storePath, sink); - sink.flush(); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdDumpPath>()); diff --git a/third_party/nix/src/nix/edit.cc b/third_party/nix/src/nix/edit.cc deleted file mode 100644 index 04c67acb94c6..000000000000 --- a/third_party/nix/src/nix/edit.cc +++ /dev/null @@ -1,75 +0,0 @@ -#include <absl/strings/str_split.h> -#include <glog/logging.h> -#include <unistd.h> - -#include "libexpr/attr-path.hh" -#include "libexpr/eval.hh" -#include "libmain/shared.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdEdit final : InstallableCommand { - std::string name() override { return "edit"; } - - std::string description() override { - return "open the Nix expression of a Nix package in $EDITOR"; - } - - Examples examples() override { - return { - Example{"To open the Nix expression of the GNU Hello package:", - "nix edit nixpkgs.hello"}, - }; - } - - void run(ref<Store> store) override { - auto state = getEvalState(); - - auto v = installable->toValue(*state); - - Value* v2; - try { - auto dummyArgs = Bindings::New(); - v2 = findAlongAttrPath(*state, "meta.position", dummyArgs.get(), *v); - } catch (Error&) { - throw Error("package '%s' has no source location information", - installable->what()); - } - - auto pos = state->forceString(*v2); - DLOG(INFO) << "position is " << pos; - - auto colon = pos.rfind(':'); - if (colon == std::string::npos) { - throw Error("cannot parse meta.position attribute '%s'", pos); - } - - std::string filename(pos, 0, colon); - int lineno; - try { - lineno = std::stoi(std::string(pos, colon + 1)); - } catch (std::invalid_argument& e) { - throw Error("cannot parse line number '%s'", pos); - } - - auto editor = getEnv("EDITOR").value_or("cat"); - - Strings args = - absl::StrSplit(editor, absl::ByAnyChar(" \t\n\r"), absl::SkipEmpty()); - - if (editor.find("emacs") != std::string::npos || - editor.find("nano") != std::string::npos || - editor.find("vim") != std::string::npos) { - args.push_back(fmt("+%d", lineno)); - } - - args.push_back(filename); - - execvp(args.front().c_str(), stringsToCharPtrs(args).data()); - - throw SysError("cannot run editor '%s'", editor); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdEdit>()); diff --git a/third_party/nix/src/nix/eval.cc b/third_party/nix/src/nix/eval.cc deleted file mode 100644 index 72fcbd82717d..000000000000 --- a/third_party/nix/src/nix/eval.cc +++ /dev/null @@ -1,56 +0,0 @@ -#include "libexpr/eval.hh" - -#include "libexpr/value-to-json.hh" -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "libutil/json.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdEval final : MixJSON, InstallableCommand { - bool raw = false; - - CmdEval() { mkFlag(0, "raw", "print strings unquoted", &raw); } - - std::string name() override { return "eval"; } - - std::string description() override { return "evaluate a Nix expression"; } - - Examples examples() override { - return { - Example{"To evaluate a Nix expression given on the command line:", - "nix eval '(1 + 2)'"}, - Example{"To evaluate a Nix expression from a file or URI:", - "nix eval -f channel:nixos-17.09 hello.name"}, - Example{"To get the current version of Nixpkgs:", - "nix eval --raw nixpkgs.lib.nixpkgsVersion"}, - Example{"To print the store path of the Hello package:", - "nix eval --raw nixpkgs.hello"}, - }; - } - - void run(ref<Store> store) override { - if (raw && json) { - throw UsageError("--raw and --json are mutually exclusive"); - } - - auto state = getEvalState(); - - auto v = installable->toValue(*state); - PathSet context; - - if (raw) { - std::cout << state->coerceToString(noPos, *v, context); - } else if (json) { - JSONPlaceholder jsonOut(std::cout); - printValueAsJSON(*state, true, *v, jsonOut, context); - } else { - state->forceValueDeep(*v); - std::cout << *v << "\n"; - } - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdEval>()); diff --git a/third_party/nix/src/nix/hash.cc b/third_party/nix/src/nix/hash.cc deleted file mode 100644 index 4fb262f1a8f0..000000000000 --- a/third_party/nix/src/nix/hash.cc +++ /dev/null @@ -1,152 +0,0 @@ -#include "libutil/hash.hh" - -#include "libmain/shared.hh" -#include "nix/command.hh" -#include "nix/legacy.hh" - -namespace nix { -struct CmdHash final : Command { - enum Mode { mFile, mPath }; - Mode mode; - Base base = SRI; - bool truncate = false; - HashType ht = htSHA256; - std::vector<std::string> paths; - - explicit CmdHash(Mode mode) : mode(mode) { - mkFlag(0, "sri", "print hash in SRI format", &base, SRI); - mkFlag(0, "base64", "print hash in base-64", &base, Base64); - mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32); - mkFlag(0, "base16", "print hash in base-16", &base, Base16); - mkFlag().longName("type").mkHashTypeFlag(&ht); - expectArgs("paths", &paths); - } - - std::string name() override { - return mode == mFile ? "hash-file" : "hash-path"; - } - - std::string description() override { - return mode == mFile - ? "print cryptographic hash of a regular file" - : "print cryptographic hash of the NAR serialisation of a path"; - } - - void run() override { - for (const auto& path : paths) { - Hash h = mode == mFile ? hashFile(ht, path) : hashPath(ht, path).first; - if (truncate && h.hashSize > nix::kStorePathHashSize) { - h = compressHash(h, nix::kStorePathHashSize); - } - std::cout << format("%1%\n") % h.to_string(base, base == SRI); - } - } -}; - -static RegisterCommand r1(make_ref<CmdHash>(CmdHash::mFile)); -static RegisterCommand r2(make_ref<CmdHash>(CmdHash::mPath)); - -struct CmdToBase final : Command { - Base base; - HashType ht = htUnknown; - std::vector<std::string> args; - - explicit CmdToBase(Base base) : base(base) { - mkFlag().longName("type").mkHashTypeFlag(&ht); - expectArgs("strings", &args); - } - - std::string name() override { - return base == Base16 ? "to-base16" - : base == Base32 ? "to-base32" - : base == Base64 ? "to-base64" - : "to-sri"; - } - - std::string description() override { - return fmt("convert a hash to %s representation", - base == Base16 ? "base-16" - : base == Base32 ? "base-32" - : base == Base64 ? "base-64" - : "SRI"); - } - - void run() override { - for (const auto& s : args) { - auto hash_ = Hash::deserialize(s, ht); - if (hash_.ok()) { - std::cout << hash_->to_string(base, base == SRI) << "\n"; - } else { - std::cerr << "failed to parse: " << hash_.status().ToString() << "\n"; - // create a matching blank line, for scripting - std::cout << "\n"; - } - } - } -}; - -static RegisterCommand r3(make_ref<CmdToBase>(Base16)); -static RegisterCommand r4(make_ref<CmdToBase>(Base32)); -static RegisterCommand r5(make_ref<CmdToBase>(Base64)); -static RegisterCommand r6(make_ref<CmdToBase>(SRI)); - -/* Legacy nix-hash command. */ -static int compatNixHash(int argc, char** argv) { - HashType ht = htMD5; - bool flat = false; - bool base32 = false; - bool truncate = false; - enum { opHash, opTo32, opTo16 } op = opHash; - std::vector<std::string> ss; - - parseCmdLine(argc, argv, - [&](Strings::iterator& arg, const Strings::iterator& end) { - if (*arg == "--help") { - showManPage("nix-hash"); - } else if (*arg == "--version") { - printVersion("nix-hash"); - } else if (*arg == "--flat") { - flat = true; - } else if (*arg == "--base32") { - base32 = true; - } else if (*arg == "--truncate") { - truncate = true; - } else if (*arg == "--type") { - std::string s = getArg(*arg, arg, end); - ht = parseHashType(s); - if (ht == htUnknown) { - throw UsageError(format("unknown hash type '%1%'") % s); - } - } else if (*arg == "--to-base16") { - op = opTo16; - } else if (*arg == "--to-base32") { - op = opTo32; - } else if (*arg != "" && arg->at(0) == '-') { - return false; - } else { - ss.push_back(*arg); - } - return true; - }); - - if (op == opHash) { - CmdHash cmd(flat ? CmdHash::mFile : CmdHash::mPath); - cmd.ht = ht; - cmd.base = base32 ? Base32 : Base16; - cmd.truncate = truncate; - cmd.paths = ss; - cmd.run(); - } - - else { - CmdToBase cmd(op == opTo32 ? Base32 : Base16); - cmd.args = ss; - cmd.ht = ht; - cmd.run(); - } - - return 0; -} - -static RegisterLegacyCommand s1("nix-hash", compatNixHash); -} // namespace nix diff --git a/third_party/nix/src/nix/installables.cc b/third_party/nix/src/nix/installables.cc deleted file mode 100644 index 7aa26b0dee8c..000000000000 --- a/third_party/nix/src/nix/installables.cc +++ /dev/null @@ -1,349 +0,0 @@ -#include <iostream> -#include <regex> -#include <utility> - -#include "libexpr/attr-path.hh" -#include "libexpr/common-eval-args.hh" -#include "libexpr/eval-inline.hh" -#include "libexpr/eval.hh" -#include "libexpr/get-drvs.hh" -#include "libmain/shared.hh" -#include "libstore/derivations.hh" -#include "libstore/store-api.hh" -#include "libutil/status.hh" -#include "nix/command.hh" - -namespace nix { - -SourceExprCommand::SourceExprCommand() { - mkFlag() - .shortName('f') - .longName("file") - .label("file") - .description("evaluate FILE rather than the default") - .dest(&file); -} - -Value* SourceExprCommand::getSourceExpr(EvalState& state) { - if (vSourceExpr != nullptr) { - return *vSourceExpr; - } - - auto sToplevel = state.symbols.Create("_toplevel"); - - // Allocate the vSourceExpr Value as uncollectable. Boehm GC doesn't - // consider the member variable "alive" during execution causing it to be - // GC'ed in the middle of evaluation. - vSourceExpr = allocRootValue(state.allocValue()); - - if (!file.empty()) { - state.evalFile(lookupFileArg(state, file), **vSourceExpr); - } else { - /* Construct the installation source from $NIX_PATH. */ - - auto searchPath = state.getSearchPath(); - - state.mkAttrs(**vSourceExpr, 1024); - - mkBool(*state.allocAttr(**vSourceExpr, sToplevel), true); - - std::unordered_set<std::string> seen; - - auto addEntry = [&](const std::string& name) { - if (name.empty()) { - return; - } - if (!seen.insert(name).second) { - return; - } - Value* v1 = state.allocValue(); - mkPrimOpApp(*v1, state.getBuiltin("findFile"), - state.getBuiltin("nixPath")); - Value* v2 = state.allocValue(); - mkApp(*v2, *v1, mkString(*state.allocValue(), name)); - mkApp(*state.allocAttr(**vSourceExpr, state.symbols.Create(name)), - state.getBuiltin("import"), *v2); - }; - - for (auto& i : searchPath) { /* Hack to handle channels. */ - if (i.first.empty() && pathExists(i.second + "/manifest.nix")) { - for (auto& j : readDirectory(i.second)) { - if (j.name != "manifest.nix" && - pathExists(fmt("%s/%s/default.nix", i.second, j.name))) { - addEntry(j.name); - } - } - } else { - addEntry(i.first); - } - } - } - - return *vSourceExpr; -} - -ref<EvalState> SourceExprCommand::getEvalState() { - if (!evalState) { - evalState = std::make_shared<EvalState>(searchPath, getStore()); - } - return ref<EvalState>(evalState); -} - -Buildable Installable::toBuildable() { - auto buildables = toBuildables(); - if (buildables.size() != 1) { - throw Error( - "installable '%s' evaluates to %d derivations, where only one is " - "expected", - what(), buildables.size()); - } - return std::move(buildables[0]); -} - -struct InstallableStorePath final : Installable { - Path storePath; - - explicit InstallableStorePath(Path storePath) - : storePath(std::move(storePath)) {} - - std::string what() override { return storePath; } - - Buildables toBuildables() override { - return {{isDerivation(storePath) ? storePath : "", {{"out", storePath}}}}; - } -}; - -struct InstallableValue : Installable { - SourceExprCommand& cmd; - - explicit InstallableValue(SourceExprCommand& cmd) : cmd(cmd) {} - - Buildables toBuildables() override { - auto state = cmd.getEvalState(); - - auto v = toValue(*state); - - std::unique_ptr<Bindings> autoArgs = cmd.getAutoArgs(*state); - - DrvInfos drvs; - getDerivations(*state, *v, "", autoArgs.get(), drvs, false); - - Buildables res; - - PathSet drvPaths; - - for (auto& drv : drvs) { - Buildable b{drv.queryDrvPath()}; - drvPaths.insert(b.drvPath); - - auto outputName = drv.queryOutputName(); - if (outputName.empty()) { - throw Error("derivation '%s' lacks an 'outputName' attribute", - b.drvPath); - } - - b.outputs.emplace(outputName, drv.queryOutPath()); - - res.push_back(std::move(b)); - } - - // Hack to recognize .all: if all drvs have the same drvPath, - // merge the buildables. - if (drvPaths.size() == 1) { - Buildable b{*drvPaths.begin()}; - for (auto& b2 : res) { - b.outputs.insert(b2.outputs.begin(), b2.outputs.end()); - } - return {b}; - } - return res; - } -}; - -struct InstallableExpr final : InstallableValue { - std::string text; - - InstallableExpr(SourceExprCommand& cmd, std::string text) - : InstallableValue(cmd), text(std::move(text)) {} - - std::string what() override { return text; } - - Value* toValue(EvalState& state) override { - auto v = state.allocValue(); - state.eval(state.parseExprFromString(text, absPath(".")), *v); - return v; - } -}; - -struct InstallableAttrPath final : InstallableValue { - std::string attrPath; - - InstallableAttrPath(SourceExprCommand& cmd, std::string attrPath) - : InstallableValue(cmd), attrPath(std::move(attrPath)) {} - - std::string what() override { return attrPath; } - - Value* toValue(EvalState& state) override { - auto source = cmd.getSourceExpr(state); - - std::unique_ptr<Bindings> autoArgs = cmd.getAutoArgs(state); - - Value* v = findAlongAttrPath(state, attrPath, autoArgs.get(), *source); - state.forceValue(*v); - - return v; - } -}; - -// FIXME: extend -std::string attrRegex = R"([A-Za-z_][A-Za-z0-9-_+]*)"; -static std::regex attrPathRegex(fmt(R"(%1%(\.%1%)*)", attrRegex)); - -static std::vector<std::shared_ptr<Installable>> parseInstallables( - SourceExprCommand& cmd, const ref<Store>& store, - std::vector<std::string> ss, bool useDefaultInstallables) { - std::vector<std::shared_ptr<Installable>> result; - - if (ss.empty() && useDefaultInstallables) { - if (cmd.file.empty()) { - cmd.file = "."; - } - ss = {""}; - } - - for (auto& s : ss) { - if (s.compare(0, 1, "(") == 0) { - result.push_back(std::make_shared<InstallableExpr>(cmd, s)); - - } else if (s.find('/') != std::string::npos) { - auto path = store->toStorePath(store->followLinksToStore(s)); - - if (store->isStorePath(path)) { - result.push_back(std::make_shared<InstallableStorePath>(path)); - } - } - - else if (s.empty() || std::regex_match(s, attrPathRegex)) { - result.push_back(std::make_shared<InstallableAttrPath>(cmd, s)); - - } else { - throw UsageError("don't know what to do with argument '%s'", s); - } - } - - return result; -} - -std::shared_ptr<Installable> parseInstallable(SourceExprCommand& cmd, - const ref<Store>& store, - const std::string& installable, - bool useDefaultInstallables) { - auto installables = parseInstallables(cmd, store, {installable}, false); - assert(installables.size() == 1); - return installables.front(); -} - -Buildables build( - const ref<Store>& store, RealiseMode mode, - const std::vector<std::shared_ptr<Installable>>& installables) { - if (mode != Build) { - settings.readOnlyMode = true; - } - - Buildables buildables; - - PathSet pathsToBuild; - - for (auto& i : installables) { - for (auto& b : i->toBuildables()) { - if (!b.drvPath.empty()) { - StringSet outputNames; - for (auto& output : b.outputs) { - outputNames.insert(output.first); - } - pathsToBuild.insert(b.drvPath + "!" + - concatStringsSep(",", outputNames)); - } else { - for (auto& output : b.outputs) { - pathsToBuild.insert(output.second); - } - } - buildables.push_back(std::move(b)); - } - } - - if (mode == DryRun) { - printMissing(store, pathsToBuild); - } else if (mode == Build) { - util::OkOrThrow(store->buildPaths(std::cerr, pathsToBuild)); - } - - return buildables; -} - -PathSet toStorePaths( - const ref<Store>& store, RealiseMode mode, - const std::vector<std::shared_ptr<Installable>>& installables) { - PathSet outPaths; - - for (auto& b : build(store, mode, installables)) { - for (auto& output : b.outputs) { - outPaths.insert(output.second); - } - } - - return outPaths; -} - -Path toStorePath(const ref<Store>& store, RealiseMode mode, - const std::shared_ptr<Installable>& installable) { - auto paths = toStorePaths(store, mode, {installable}); - - if (paths.size() != 1) { - throw Error("argument '%s' should evaluate to one store path", - installable->what()); - } - - return *paths.begin(); -} - -PathSet toDerivations( - const ref<Store>& store, - const std::vector<std::shared_ptr<Installable>>& installables, - bool useDeriver) { - PathSet drvPaths; - - for (auto& i : installables) { - for (auto& b : i->toBuildables()) { - if (b.drvPath.empty()) { - if (!useDeriver) { - throw Error("argument '%s' did not evaluate to a derivation", - i->what()); - } - for (auto& output : b.outputs) { - auto derivers = store->queryValidDerivers(output.second); - if (derivers.empty()) { - throw Error("'%s' does not have a known deriver", i->what()); - } - // FIXME: use all derivers? - drvPaths.insert(*derivers.begin()); - } - } else { - drvPaths.insert(b.drvPath); - } - } - } - - return drvPaths; -} - -void InstallablesCommand::prepare() { - installables = parseInstallables(*this, getStore(), _installables, - useDefaultInstallables()); -} - -void InstallableCommand::prepare() { - installable = parseInstallable(*this, getStore(), _installable, false); -} - -} // namespace nix diff --git a/third_party/nix/src/nix/legacy.cc b/third_party/nix/src/nix/legacy.cc deleted file mode 100644 index a0f9fc65b311..000000000000 --- a/third_party/nix/src/nix/legacy.cc +++ /dev/null @@ -1,7 +0,0 @@ -#include "nix/legacy.hh" - -namespace nix { - -RegisterLegacyCommand::Commands* RegisterLegacyCommand::commands = nullptr; - -} diff --git a/third_party/nix/src/nix/legacy.hh b/third_party/nix/src/nix/legacy.hh deleted file mode 100644 index a0fc88da244c..000000000000 --- a/third_party/nix/src/nix/legacy.hh +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include <functional> -#include <map> -#include <string> - -namespace nix { - -typedef std::function<void(int, char**)> MainFunction; - -struct RegisterLegacyCommand { - using Commands = std::map<std::string, MainFunction>; - static Commands* commands; - - RegisterLegacyCommand(const std::string& name, MainFunction fun) { - if (!commands) { - commands = new Commands; - } - (*commands)[name] = fun; - } -}; - -} // namespace nix diff --git a/third_party/nix/src/nix/log.cc b/third_party/nix/src/nix/log.cc deleted file mode 100644 index 84207d8576ea..000000000000 --- a/third_party/nix/src/nix/log.cc +++ /dev/null @@ -1,63 +0,0 @@ -#include <glog/logging.h> - -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdLog final : InstallableCommand { - CmdLog() = default; - - std::string name() override { return "log"; } - - std::string description() override { - return "show the build log of the specified packages or paths, if " - "available"; - } - - Examples examples() override { - return { - Example{"To get the build log of GNU Hello:", "nix log nixpkgs.hello"}, - Example{ - "To get the build log of a specific path:", - "nix log " - "/nix/store/lmngj4wcm9rkv3w4dfhzhcyij3195hiq-thunderbird-52.2.1"}, - Example{"To get a build log from a specific binary cache:", - "nix log --store https://cache.nixos.org nixpkgs.hello"}, - }; - } - - void run(ref<Store> store) override { - settings.readOnlyMode = true; - - auto subs = getDefaultSubstituters(); - - subs.push_front(store); - - auto b = installable->toBuildable(); - - RunPager pager; - for (auto& sub : subs) { - auto log = !b.drvPath.empty() ? sub->getBuildLog(b.drvPath) : nullptr; - for (auto& output : b.outputs) { - if (log) { - break; - } - log = sub->getBuildLog(output.second); - } - if (!log) { - continue; - } - LOG(INFO) << "got build log for '" << installable->what() << "' from '" - << sub->getUri() << "'"; - std::cout << *log; - return; - } - - throw Error("build log of '%s' is not available", installable->what()); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdLog>()); diff --git a/third_party/nix/src/nix/ls.cc b/third_party/nix/src/nix/ls.cc deleted file mode 100644 index 1da722babbd3..000000000000 --- a/third_party/nix/src/nix/ls.cc +++ /dev/null @@ -1,137 +0,0 @@ -#include "libmain/common-args.hh" -#include "libstore/fs-accessor.hh" -#include "libstore/nar-accessor.hh" -#include "libstore/store-api.hh" -#include "libutil/json.hh" -#include "nix/command.hh" - -namespace nix { -struct MixLs : virtual Args, MixJSON { - std::string path; - - bool recursive = false; - bool verbose = false; - bool showDirectory = false; - - MixLs() { - mkFlag('R', "recursive", "list subdirectories recursively", &recursive); - mkFlag('l', "long", "show more file information", &verbose); - mkFlag('d', "directory", "show directories rather than their contents", - &showDirectory); - } - - void listText(ref<FSAccessor> accessor) { - std::function<void(const FSAccessor::Stat&, const Path&, const std::string&, - bool)> - doPath; - - auto showFile = [&](const Path& curPath, const std::string& relPath) { - if (verbose) { - auto st = accessor->stat(curPath); - std::string tp = st.type == FSAccessor::Type::tRegular - ? (st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") - : st.type == FSAccessor::Type::tSymlink ? "lrwxrwxrwx" - : "dr-xr-xr-x"; - std::cout << (format("%s %20d %s") % tp % st.fileSize % relPath); - if (st.type == FSAccessor::Type::tSymlink) { - std::cout << " -> " << accessor->readLink(curPath); - } - std::cout << "\n"; - if (recursive && st.type == FSAccessor::Type::tDirectory) { - doPath(st, curPath, relPath, false); - } - } else { - std::cout << relPath << "\n"; - if (recursive) { - auto st = accessor->stat(curPath); - if (st.type == FSAccessor::Type::tDirectory) { - doPath(st, curPath, relPath, false); - } - } - } - }; - - doPath = [&](const FSAccessor::Stat& st, const Path& curPath, - const std::string& relPath, bool showDirectory) { - if (st.type == FSAccessor::Type::tDirectory && !showDirectory) { - auto names = accessor->readDirectory(curPath); - for (auto& name : names) { - showFile(curPath + "/" + name, relPath + "/" + name); - } - } else { - showFile(curPath, relPath); - } - }; - - auto st = accessor->stat(path); - if (st.type == FSAccessor::Type::tMissing) { - throw Error(format("path '%1%' does not exist") % path); - } - doPath(st, path, - st.type == FSAccessor::Type::tDirectory ? "." : baseNameOf(path), - showDirectory); - } - - void list(const ref<FSAccessor>& accessor) { - if (path == "/") { - path = ""; - } - - if (json) { - JSONPlaceholder jsonRoot(std::cout); - listNar(jsonRoot, accessor, path, recursive); - } else { - listText(accessor); - } - } -}; - -struct CmdLsStore final : StoreCommand, MixLs { - CmdLsStore() { expectArg("path", &path); } - - Examples examples() override { - return { - Example{"To list the contents of a store path in a binary cache:", - "nix ls-store --store https://cache.nixos.org/ -lR " - "/nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10"}, - }; - } - - std::string name() override { return "ls-store"; } - - std::string description() override { - return "show information about a store path"; - } - - void run(ref<Store> store) override { list(store->getFSAccessor()); } -}; - -struct CmdLsNar final : Command, MixLs { - Path narPath; - - CmdLsNar() { - expectArg("nar", &narPath); - expectArg("path", &path); - } - - Examples examples() override { - return { - Example{"To list a specific file in a NAR:", - "nix ls-nar -l hello.nar /bin/hello"}, - }; - } - - std::string name() override { return "ls-nar"; } - - std::string description() override { - return "show information about the contents of a NAR file"; - } - - void run() override { - list(makeNarAccessor(make_ref<std::string>(readFile(narPath, true)))); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdLsStore>()); -static nix::RegisterCommand r2(nix::make_ref<nix::CmdLsNar>()); diff --git a/third_party/nix/src/nix/main.cc b/third_party/nix/src/nix/main.cc deleted file mode 100644 index 08390fd24b9f..000000000000 --- a/third_party/nix/src/nix/main.cc +++ /dev/null @@ -1,185 +0,0 @@ -#include <algorithm> - -#include <glog/logging.h> -#include <ifaddrs.h> -#include <netdb.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/types.h> - -#include "libexpr/eval.hh" -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/download.hh" -#include "libstore/globals.hh" -#include "libstore/store-api.hh" -#include "libutil/finally.hh" -#include "nix/command.hh" -#include "nix/legacy.hh" - -extern std::string chrootHelperName; - -void chrootHelper(int argc, char** argv); - -namespace nix { - -/* Check if we have a non-loopback/link-local network interface. */ -static bool haveInternet() { - struct ifaddrs* addrs; - - if (getifaddrs(&addrs) != 0) { - return true; - } - - Finally free([&]() { freeifaddrs(addrs); }); - - for (auto i = addrs; i != nullptr; i = i->ifa_next) { - if (i->ifa_addr == nullptr) { - continue; - } - if (i->ifa_addr->sa_family == AF_INET) { - if (ntohl( - (reinterpret_cast<sockaddr_in*>(i->ifa_addr))->sin_addr.s_addr) != - INADDR_LOOPBACK) { - return true; - } - } else if (i->ifa_addr->sa_family == AF_INET6) { - if (!IN6_IS_ADDR_LOOPBACK(&((sockaddr_in6*)i->ifa_addr)->sin6_addr) && - !IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6*)i->ifa_addr)->sin6_addr)) { - return true; - } - } - } - - return false; -} - -std::string programPath; - -struct NixArgs : virtual MultiCommand, virtual MixCommonArgs { - bool printBuildLogs = false; - bool useNet = true; - - NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix") { - mkFlag() - .longName("help") - .description("show usage information") - .handler([&]() { showHelpAndExit(); }); - - mkFlag() - .longName("help-config") - .description("show configuration options") - .handler([&]() { - std::cout << "The following configuration options are available:\n\n"; - Table2 tbl; - std::map<std::string, Config::SettingInfo> settings; - globalConfig.getSettings(settings); - for (const auto& s : settings) { - tbl.emplace_back(s.first, s.second.description); - } - printTable(std::cout, tbl); - throw Exit(); - }); - - mkFlag() - .longName("print-build-logs") - .shortName('L') - .description("print full build logs on stderr") - .set(&printBuildLogs, true); - - mkFlag() - .longName("version") - .description("show version information") - .handler([&]() { printVersion(programName); }); - - mkFlag() - .longName("no-net") - .description( - "disable substituters and consider all previously downloaded files " - "up-to-date") - .handler([&]() { useNet = false; }); - } - - void printFlags(std::ostream& out) override { - Args::printFlags(out); - std::cout << "\n" - "In addition, most configuration settings can be overriden " - "using '--<name> <value>'.\n" - "Boolean settings can be overriden using '--<name>' or " - "'--no-<name>'. See 'nix\n" - "--help-config' for a list of configuration settings.\n"; - } - - void showHelpAndExit() { - printHelp(programName, std::cout); - std::cout - << "\nNote: this program is EXPERIMENTAL and subject to change.\n"; - throw Exit(); - } -}; - -void mainWrapped(int argc, char** argv) { - /* The chroot helper needs to be run before any threads have been - started. */ - if (argc > 0 && argv[0] == chrootHelperName) { - chrootHelper(argc, argv); - return; - } - - initNix(); - - programPath = argv[0]; - std::string programName = baseNameOf(programPath); - - { - auto legacy = (*RegisterLegacyCommand::commands)[programName]; - if (legacy) { - return legacy(argc, argv); - } - } - - settings.verboseBuild = false; - - NixArgs args; - - args.parseCmdline(argvToStrings(argc, argv)); - - if (!args.command) { - args.showHelpAndExit(); - } - - if (args.useNet && !haveInternet()) { - LOG(WARNING) << "you don't have Internet access; " - << "disabling some network-dependent features"; - args.useNet = false; - } - - if (!args.useNet) { - // FIXME: should check for command line overrides only. - if (!settings.useSubstitutes.overriden) { - settings.useSubstitutes = false; - } - if (!settings.tarballTtl.overriden) { - settings.tarballTtl = std::numeric_limits<unsigned int>::max(); - } - if (!downloadSettings.tries.overriden) { - downloadSettings.tries = 0; - } - if (!downloadSettings.connectTimeout.overriden) { - downloadSettings.connectTimeout = 1; - } - } - - args.command->prepare(); - args.command->run(); -} - -} // namespace nix - -int main(int argc, char* argv[]) { - FLAGS_logtostderr = true; - google::InitGoogleLogging(argv[0]); - - return nix::handleExceptions(argv[0], - [&]() { nix::mainWrapped(argc, argv); }); -} diff --git a/third_party/nix/src/nix/optimise-store.cc b/third_party/nix/src/nix/optimise-store.cc deleted file mode 100644 index ceb53aa77b17..000000000000 --- a/third_party/nix/src/nix/optimise-store.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include <atomic> - -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdOptimiseStore final : StoreCommand { - CmdOptimiseStore() = default; - - std::string name() override { return "optimise-store"; } - - std::string description() override { - return "replace identical files in the store by hard links"; - } - - Examples examples() override { - return { - Example{"To optimise the Nix store:", "nix optimise-store"}, - }; - } - - void run(ref<Store> store) override { store->optimiseStore(); } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdOptimiseStore>()); diff --git a/third_party/nix/src/nix/path-info.cc b/third_party/nix/src/nix/path-info.cc deleted file mode 100644 index fcf060d50d08..000000000000 --- a/third_party/nix/src/nix/path-info.cc +++ /dev/null @@ -1,133 +0,0 @@ -#include <algorithm> -#include <array> - -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "libutil/json.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdPathInfo final : StorePathsCommand, MixJSON { - bool showSize = false; - bool showClosureSize = false; - bool humanReadable = false; - bool showSigs = false; - - CmdPathInfo() { - mkFlag('s', "size", "print size of the NAR dump of each path", &showSize); - mkFlag('S', "closure-size", - "print sum size of the NAR dumps of the closure of each path", - &showClosureSize); - mkFlag('h', "human-readable", - "with -s and -S, print sizes like 1K 234M 5.67G etc.", - &humanReadable); - mkFlag(0, "sigs", "show signatures", &showSigs); - } - - std::string name() override { return "path-info"; } - - std::string description() override { - return "query information about store paths"; - } - - Examples examples() override { - return { - Example{"To show the closure sizes of every path in the current NixOS " - "system closure, sorted by size:", - "nix path-info -rS /run/current-system | sort -nk2"}, - Example{"To show a package's closure size and all its dependencies " - "with human readable sizes:", - "nix path-info -rsSh nixpkgs.rust"}, - Example{"To check the existence of a path in a binary cache:", - "nix path-info -r /nix/store/7qvk5c91...-geeqie-1.1 --store " - "https://cache.nixos.org/"}, - Example{"To print the 10 most recently added paths (using --json and " - "the jq(1) command):", - "nix path-info --json --all | jq -r " - "'sort_by(.registrationTime)[-11:-1][].path'"}, - Example{"To show the size of the entire Nix store:", - "nix path-info --json --all | jq 'map(.narSize) | add'"}, - Example{"To show every path whose closure is bigger than 1 GB, sorted " - "by closure size:", - "nix path-info --json --all -S | jq 'map(select(.closureSize > " - "1e9)) | sort_by(.closureSize) | map([.path, .closureSize])'"}, - }; - } - - void printSize(unsigned long long value) { - if (!humanReadable) { - std::cout << fmt("\t%11d", value); - return; - } - - static const std::array<char, 9> idents{ - {' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}}; - size_t power = 0; - double res = value; - while (res > 1024 && power < idents.size()) { - ++power; - res /= 1024; - } - std::cout << fmt("\t%6.1f%c", res, idents.at(power)); - } - - void run(ref<Store> store, Paths storePaths) override { - size_t pathLen = 0; - for (auto& storePath : storePaths) { - pathLen = std::max(pathLen, storePath.size()); - } - - if (json) { - JSONPlaceholder jsonRoot(std::cout); - store->pathInfoToJSON(jsonRoot, - // FIXME: preserve order? - PathSet(storePaths.begin(), storePaths.end()), true, - showClosureSize, AllowInvalid); - } - - else { - for (auto storePath : storePaths) { - auto info = store->queryPathInfo(storePath); - storePath = info->path; // FIXME: screws up padding - - std::cout << storePath; - - if (showSize || showClosureSize || showSigs) { - std::cout << std::string( - std::max(0, static_cast<int>(pathLen) - - static_cast<int>(storePath.size())), - ' '); - } - - if (showSize) { - printSize(info->narSize); - } - - if (showClosureSize) { - printSize(store->getClosureSize(storePath).first); - } - - if (showSigs) { - std::cout << '\t'; - Strings ss; - if (info->ultimate) { - ss.push_back("ultimate"); - } - if (!info->ca.empty()) { - ss.push_back("ca:" + info->ca); - } - for (auto& sig : info->sigs) { - ss.push_back(sig); - } - std::cout << concatStringsSep(" ", ss); - } - - std::cout << std::endl; - } - } - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdPathInfo>()); diff --git a/third_party/nix/src/nix/ping-store.cc b/third_party/nix/src/nix/ping-store.cc deleted file mode 100644 index 4a33486bf8c6..000000000000 --- a/third_party/nix/src/nix/ping-store.cc +++ /dev/null @@ -1,25 +0,0 @@ -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdPingStore final : StoreCommand { - std::string name() override { return "ping-store"; } - - std::string description() override { - return "test whether a store can be opened"; - } - - Examples examples() override { - return { - Example{ - "To test whether connecting to a remote Nix store via SSH works:", - "nix ping-store --store ssh://mac1"}, - }; - } - - void run(ref<Store> store) override { store->connect(); } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdPingStore>()); diff --git a/third_party/nix/src/nix/repl.cc b/third_party/nix/src/nix/repl.cc deleted file mode 100644 index b926d195aec1..000000000000 --- a/third_party/nix/src/nix/repl.cc +++ /dev/null @@ -1,819 +0,0 @@ -#include <climits> -#include <csetjmp> -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <utility> - -#include <absl/strings/ascii.h> -#include <absl/strings/match.h> -#include <editline.h> -#include <glog/logging.h> - -#include "libexpr/common-eval-args.hh" -#include "libexpr/eval-inline.hh" -#include "libexpr/eval.hh" -#include "libexpr/get-drvs.hh" -#include "libmain/shared.hh" -#include "libstore/derivations.hh" -#include "libstore/globals.hh" -#include "libstore/store-api.hh" -#include "libutil/affinity.hh" -#include "libutil/finally.hh" -#include "nix/command.hh" - -namespace nix { - -#define ESC_RED "\033[31m" -#define ESC_GRE "\033[32m" -#define ESC_YEL "\033[33m" -#define ESC_BLU "\033[34;1m" -#define ESC_MAG "\033[35m" -#define ESC_CYA "\033[36m" -#define ESC_END "\033[0m" - -struct NixRepl { - std::string curDir; - EvalState state; - std::unique_ptr<Bindings> autoArgs; - - Strings loadedFiles; - - const static int envSize = 32768; - StaticEnv staticEnv; - Env* env; - int displ; - StringSet varNames; - - const Path historyFile; - - NixRepl(const Strings& searchPath, const nix::ref<Store>& store); - ~NixRepl(); - void mainLoop(const std::vector<std::string>& files); - StringSet completePrefix(const std::string& prefix); - static bool getLine(std::string& input, const std::string& prompt); - Path getDerivationPath(Value& v); - bool processLine(std::string line); - void loadFile(const Path& path); - void initEnv(); - void reloadFiles(); - void addAttrsToScope(Value& attrs); - void addVarToScope(const Symbol& name, Value& v); - Expr* parseString(const std::string& s); - void evalString(std::string s, Value& v); - - using ValuesSeen = std::set<Value*>; - std::ostream& printValue(std::ostream& str, Value& v, unsigned int maxDepth); - std::ostream& printValue(std::ostream& str, Value& v, unsigned int maxDepth, - ValuesSeen& seen); -}; - -void printHelp() { - std::cout << "Usage: nix-repl [--help] [--version] [-I path] paths...\n" - << "\n" - << "nix-repl is a simple read-eval-print loop (REPL) for the Nix " - "package manager.\n" - << "\n" - << "Options:\n" - << " --help\n" - << " Prints out a summary of the command syntax and exits.\n" - << "\n" - << " --version\n" - << " Prints out the Nix version number on standard output " - "and exits.\n" - << "\n" - << " -I path\n" - << " Add a path to the Nix expression search path. This " - "option may be given\n" - << " multiple times. See the NIX_PATH environment variable " - "for information on\n" - << " the semantics of the Nix search path. Paths added " - "through -I take\n" - << " precedence over NIX_PATH.\n" - << "\n" - << " paths...\n" - << " A list of paths to files containing Nix expressions " - "which nix-repl will\n" - << " load and add to its scope.\n" - << "\n" - << " A path surrounded in < and > will be looked up in the " - "Nix expression search\n" - << " path, as in the Nix language itself.\n" - << "\n" - << " If an element of paths starts with http:// or " - "https://, it is interpreted\n" - << " as the URL of a tarball that will be downloaded and " - "unpacked to a temporary\n" - << " location. The tarball must include a single top-level " - "directory containing\n" - << " at least a file named default.nix.\n"; -} - -std::string removeWhitespace(std::string s) { - s = absl::StripTrailingAsciiWhitespace(s); - size_t n = s.find_first_not_of(" \n\r\t"); - if (n != std::string::npos) { - s = std::string(s, n); - } - return s; -} - -NixRepl::NixRepl(const Strings& searchPath, const nix::ref<Store>& store) - : state(searchPath, store), - staticEnv(false, &state.staticBaseEnv), - historyFile(getDataDir() + "/nix/repl-history") { - curDir = absPath("."); -} - -NixRepl::~NixRepl() { write_history(historyFile.c_str()); } - -static NixRepl* curRepl; // ugly - -static char* completionCallback(char* s, int* match) { - auto possible = curRepl->completePrefix(s); - if (possible.size() == 1) { - *match = 1; - auto* res = strdup(possible.begin()->c_str() + strlen(s)); - if (res == nullptr) { - throw Error("allocation failure"); - } - return res; - } - if (possible.size() > 1) { - auto checkAllHaveSameAt = [&](size_t pos) { - auto& first = *possible.begin(); - for (auto& p : possible) { - if (p.size() <= pos || p[pos] != first[pos]) { - return false; - } - } - return true; - }; - size_t start = strlen(s); - size_t len = 0; - while (checkAllHaveSameAt(start + len)) { - ++len; - } - if (len > 0) { - *match = 1; - auto* res = strdup(std::string(*possible.begin(), start, len).c_str()); - if (res == nullptr) { - throw Error("allocation failure"); - } - return res; - } - } - - *match = 0; - return nullptr; -} - -static int listPossibleCallback(char* s, char*** avp) { - auto possible = curRepl->completePrefix(s); - - if (possible.size() > (INT_MAX / sizeof(char*))) { - throw Error("too many completions"); - } - - int ac = 0; - char** vp = nullptr; - - auto check = [&](auto* p) { - if (!p) { - if (vp) { - while (--ac >= 0) { - free(vp[ac]); - } - free(vp); - } - throw Error("allocation failure"); - } - return p; - }; - - vp = check(static_cast<char**>(malloc(possible.size() * sizeof(char*)))); - - for (auto& p : possible) { - vp[ac++] = check(strdup(p.c_str())); - } - - *avp = vp; - - return ac; -} - -namespace { -// Used to communicate to NixRepl::getLine whether a signal occurred in -// ::readline. -volatile sig_atomic_t g_signal_received = 0; - -void sigintHandler(int signo) { g_signal_received = signo; } -} // namespace - -void NixRepl::mainLoop(const std::vector<std::string>& files) { - std::string error = ANSI_RED "error:" ANSI_NORMAL " "; - std::cout << "Welcome to Nix version " << nixVersion << ". Type :? for help." - << std::endl - << std::endl; - - for (auto& i : files) { - loadedFiles.push_back(i); - } - - reloadFiles(); - if (!loadedFiles.empty()) { - std::cout << std::endl; - } - - // Allow nix-repl specific settings in .inputrc - rl_readline_name = "nix-repl"; - createDirs(dirOf(historyFile)); - el_hist_size = 1000; - read_history(historyFile.c_str()); - curRepl = this; - rl_set_complete_func(completionCallback); - rl_set_list_possib_func(listPossibleCallback); - - std::string input; - - while (true) { - // When continuing input from previous lines, don't print a prompt, just - // align to the same number of chars as the prompt. - if (!getLine(input, input.empty() ? "nix-repl> " : " ")) { - break; - } - - try { - if (!removeWhitespace(input).empty() && !processLine(input)) { - return; - } - } catch (ParseError& e) { - if (e.msg().find("unexpected $end") != std::string::npos) { - // For parse errors on incomplete input, we continue waiting for the - // next line of input without clearing the input so far. - continue; - } - LOG(ERROR) << error << (settings.showTrace ? e.prefix() : "") << e.msg(); - - } catch (Error& e) { - LOG(ERROR) << error << (settings.showTrace ? e.prefix() : "") << e.msg(); - } catch (Interrupted& e) { - LOG(ERROR) << error << (settings.showTrace ? e.prefix() : "") << e.msg(); - } - - // We handled the current input fully, so we should clear it - // and read brand new input. - input.clear(); - std::cout << std::endl; - } -} - -bool NixRepl::getLine(std::string& input, const std::string& prompt) { - struct sigaction act; - struct sigaction old; - sigset_t savedSignalMask; - sigset_t set; - - auto setupSignals = [&]() { - act.sa_handler = sigintHandler; - sigfillset(&act.sa_mask); - act.sa_flags = 0; - if (sigaction(SIGINT, &act, &old) != 0) { - throw SysError("installing handler for SIGINT"); - } - - sigemptyset(&set); - sigaddset(&set, SIGINT); - if (sigprocmask(SIG_UNBLOCK, &set, &savedSignalMask) != 0) { - throw SysError("unblocking SIGINT"); - } - }; - auto restoreSignals = [&]() { - if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr) != 0) { - throw SysError("restoring signals"); - } - - if (sigaction(SIGINT, &old, nullptr) != 0) { - throw SysError("restoring handler for SIGINT"); - } - }; - - setupSignals(); - char* s = readline(prompt.c_str()); - Finally doFree([&]() { free(s); }); - restoreSignals(); - - if (g_signal_received != 0) { - g_signal_received = 0; - input.clear(); - return true; - } - - if (s == nullptr) { - return false; - } - input += s; - input += '\n'; - return true; -} - -StringSet NixRepl::completePrefix(const std::string& prefix) { - StringSet completions; - - size_t start = prefix.find_last_of(" \n\r\t(){}[]"); - std::string prev; - std::string cur; - if (start == std::string::npos) { - prev = ""; - cur = prefix; - } else { - prev = std::string(prefix, 0, start + 1); - cur = std::string(prefix, start + 1); - } - - size_t slash; - size_t dot; - - if ((slash = cur.rfind('/')) != std::string::npos) { - try { - auto dir = std::string(cur, 0, slash); - auto prefix2 = std::string(cur, slash + 1); - for (auto& entry : readDirectory(dir.empty() ? "/" : dir)) { - if (entry.name[0] != '.' && absl::StartsWith(entry.name, prefix2)) { - completions.insert(prev + dir + "/" + entry.name); - } - } - } catch (Error&) { - } - } else if ((dot = cur.rfind('.')) == std::string::npos) { - /* This is a variable name; look it up in the current scope. */ - auto i = varNames.lower_bound(cur); - while (i != varNames.end()) { - if (std::string(*i, 0, cur.size()) != cur) { - break; - } - completions.insert(prev + *i); - i++; - } - } else { - try { - /* This is an expression that should evaluate to an - attribute set. Evaluate it to get the names of the - attributes. */ - std::string expr(cur, 0, dot); - std::string cur2 = std::string(cur, dot + 1); - - Expr* e = parseString(expr); - Value v; - e->eval(state, *env, v); - state.forceAttrs(v); - - for (auto& i : *v.attrs) { - std::string name = i.second.name; - if (std::string(name, 0, cur2.size()) != cur2) { - continue; - } - completions.insert(prev + expr + "." + name); - } - - } catch (ParseError& e) { - // Quietly ignore parse errors. - } catch (EvalError& e) { - // Quietly ignore evaluation errors. - } catch (UndefinedVarError& e) { - // Quietly ignore undefined variable errors. - } - } - - return completions; -} - -static int runProgram(const std::string& program, const Strings& args) { - Strings args2(args); - args2.push_front(program); - - Pid pid; - pid = fork(); - if (pid == Pid(-1)) { - throw SysError("forking"); - } - if (pid == Pid(0)) { - restoreAffinity(); - execvp(program.c_str(), stringsToCharPtrs(args2).data()); - _exit(1); - } - - return pid.wait(); -} - -bool isVarName(const std::string& s) { - if (s.empty()) { - return false; - } - char c = s[0]; - if ((c >= '0' && c <= '9') || c == '-' || c == '\'') { - return false; - } - for (auto& i : s) { - if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || - (i >= '0' && i <= '9') || i == '_' || i == '-' || i == '\'')) { - return false; - } - } - return true; -} - -Path NixRepl::getDerivationPath(Value& v) { - auto drvInfo = getDerivation(state, v, false); - if (!drvInfo) { - throw Error( - "expression does not evaluate to a derivation, so I can't build it"); - } - Path drvPath = drvInfo->queryDrvPath(); - if (drvPath.empty() || !state.store->isValidPath(drvPath)) { - throw Error("expression did not evaluate to a valid derivation"); - } - return drvPath; -} - -bool NixRepl::processLine(std::string line) { - if (line.empty()) { - return true; - } - - std::string command; - std::string arg; - - if (line[0] == ':') { - size_t p = line.find_first_of(" \n\r\t"); - command = std::string(line, 0, p); - if (p != std::string::npos) { - arg = removeWhitespace(std::string(line, p)); - } - } else { - arg = line; - } - - if (command == ":?" || command == ":help") { - std::cout << "The following commands are available:\n" - << "\n" - << " <expr> Evaluate and print expression\n" - << " <x> = <expr> Bind expression to variable\n" - << " :a <expr> Add attributes from resulting set to scope\n" - << " :b <expr> Build derivation\n" - << " :i <expr> Build derivation, then install result into " - "current profile\n" - << " :l <path> Load Nix expression and add it to scope\n" - << " :p <expr> Evaluate and print expression recursively\n" - << " :q Exit nix-repl\n" - << " :r Reload all files\n" - << " :s <expr> Build dependencies of derivation, then start " - "nix-shell\n" - << " :t <expr> Describe result of evaluation\n" - << " :u <expr> Build derivation, then start nix-shell\n"; - } - - else if (command == ":a" || command == ":add") { - Value v; - evalString(arg, v); - addAttrsToScope(v); - } - - else if (command == ":l" || command == ":load") { - state.resetFileCache(); - loadFile(arg); - } - - else if (command == ":r" || command == ":reload") { - state.resetFileCache(); - reloadFiles(); - } - - else if (command == ":t") { - Value v; - evalString(arg, v); - std::cout << showType(v) << std::endl; - - } else if (command == ":u") { - Value v; - Value f; - Value result; - evalString(arg, v); - evalString( - "drv: (import <nixpkgs> {}).runCommand \"shell\" { buildInputs = [ drv " - "]; } \"\"", - f); - state.callFunction(f, v, result, Pos()); - - Path drvPath = getDerivationPath(result); - runProgram(settings.nixBinDir + "/nix-shell", Strings{drvPath}); - } - - else if (command == ":b" || command == ":i" || command == ":s") { - Value v; - evalString(arg, v); - Path drvPath = getDerivationPath(v); - - if (command == ":b") { - /* We could do the build in this process using buildPaths(), - but doing it in a child makes it easier to recover from - problems / SIGINT. */ - if (runProgram(settings.nixBinDir + "/nix", - Strings{"build", "--no-link", drvPath}) == 0) { - Derivation drv = readDerivation(drvPath); - std::cout << std::endl - << "this derivation produced the following outputs:" - << std::endl; - for (auto& i : drv.outputs) { - std::cout << format(" %1% -> %2%") % i.first % i.second.path - << std::endl; - } - } - } else if (command == ":i") { - runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPath}); - } else { - runProgram(settings.nixBinDir + "/nix-shell", Strings{drvPath}); - } - } - - else if (command == ":p" || command == ":print") { - Value v; - evalString(arg, v); - printValue(std::cout, v, 1000000000) << std::endl; - } - - else if (command == ":q" || command == ":quit") { - return false; - - } else if (!command.empty()) { - throw Error(format("unknown command '%1%'") % command); - - } else { - size_t p = line.find('='); - std::string name; - if (p != std::string::npos && p < line.size() && line[p + 1] != '=' && - isVarName(name = removeWhitespace(std::string(line, 0, p)))) { - Expr* e = parseString(std::string(line, p + 1)); - Value& v(*state.allocValue()); - v.type = tThunk; - v.thunk.env = env; - v.thunk.expr = e; - addVarToScope(state.symbols.Create(name), v); - } else { - Value v; - evalString(line, v); - printValue(std::cout, v, 1) << std::endl; - } - } - - return true; -} - -void NixRepl::loadFile(const Path& path) { - loadedFiles.remove(path); - loadedFiles.push_back(path); - Value v; - Value v2; - state.evalFile(lookupFileArg(state, path), v); - state.autoCallFunction(autoArgs.get(), v, v2); - addAttrsToScope(v2); -} - -void NixRepl::initEnv() { - env = &state.allocEnv(envSize); - env->up = &state.baseEnv; - displ = 0; - staticEnv.vars.clear(); - - varNames.clear(); - for (auto& i : state.staticBaseEnv.vars) { - varNames.insert(i.first); - } -} - -void NixRepl::reloadFiles() { - initEnv(); - - Strings old = loadedFiles; - loadedFiles.clear(); - - bool first = true; - for (auto& i : old) { - if (!first) { - std::cout << std::endl; - } - first = false; - std::cout << format("Loading '%1%'...") % i << std::endl; - loadFile(i); - } -} - -void NixRepl::addAttrsToScope(Value& attrs) { - state.forceAttrs(attrs); - for (auto& i : *attrs.attrs) { - addVarToScope(i.second.name, *i.second.value); - } - std::cout << format("Added %1% variables.") % attrs.attrs->size() - << std::endl; -} - -void NixRepl::addVarToScope(const Symbol& name, Value& v) { - if (displ >= envSize) { - throw Error("environment full; cannot add more variables"); - } - staticEnv.vars[name] = displ; - env->values[displ++] = &v; - varNames.insert(std::string(name)); -} - -Expr* NixRepl::parseString(const std::string& s) { - Expr* e = state.parseExprFromString(s, curDir, staticEnv); - return e; -} - -void NixRepl::evalString(std::string s, Value& v) { - Expr* e = parseString(std::move(s)); - e->eval(state, *env, v); - state.forceValue(v); -} - -std::ostream& NixRepl::printValue(std::ostream& str, Value& v, - unsigned int maxDepth) { - ValuesSeen seen; - return printValue(str, v, maxDepth, seen); -} - -std::ostream& printStringValue(std::ostream& str, const char* string) { - str << "\""; - for (const char* i = string; *i != 0; i++) { - if (*i == '\"' || *i == '\\') { - str << "\\" << *i; - } else if (*i == '\n') { - str << "\\n"; - } else if (*i == '\r') { - str << "\\r"; - } else if (*i == '\t') { - str << "\\t"; - } else { - str << *i; - } - } - str << "\""; - return str; -} - -// FIXME: lot of cut&paste from Nix's eval.cc. -std::ostream& NixRepl::printValue(std::ostream& str, Value& v, - unsigned int maxDepth, ValuesSeen& seen) { - str.flush(); - checkInterrupt(); - - state.forceValue(v); - - switch (v.type) { - case tInt: - str << ESC_CYA << v.integer << ESC_END; - break; - - case tBool: - str << ESC_CYA << (v.boolean ? "true" : "false") << ESC_END; - break; - - case tString: - str << ESC_YEL; - printStringValue(str, v.string.s); - str << ESC_END; - break; - - case tPath: - str << ESC_GRE << v.path << ESC_END; // !!! escaping? - break; - - case tNull: - str << ESC_CYA "null" ESC_END; - break; - - case tAttrs: { - seen.insert(&v); - - bool isDrv = state.isDerivation(v); - - if (isDrv) { - str << "«derivation "; - Bindings::iterator i = v.attrs->find(state.sDrvPath); - PathSet context; - Path drvPath = - i != v.attrs->end() - ? state.coerceToPath(*i->second.pos, *i->second.value, context) - : "???"; - str << drvPath << "»"; - } - - else if (maxDepth > 0) { - str << "{ "; - - typedef std::map<std::string, Value*> Sorted; - Sorted sorted; - for (auto& i : *v.attrs) { - sorted[i.second.name] = i.second.value; - } - - for (auto& i : sorted) { - if (isVarName(i.first)) { - str << i.first; - } else { - printStringValue(str, i.first.c_str()); - } - str << " = "; - if (seen.find(i.second) != seen.end()) { - str << "«repeated»"; - } else { - try { - printValue(str, *i.second, maxDepth - 1, seen); - } catch (AssertionError& e) { - str << ESC_RED "«error: " << e.msg() << "»" ESC_END; - } - } - str << "; "; - } - - str << "}"; - } else { - str << "{ ... }"; - } - - break; - } - - case tList: - seen.insert(&v); - - str << "[ "; - if (maxDepth > 0) { - for (unsigned int n = 0; n < v.listSize(); ++n) { - if (seen.find((*v.list)[n]) != seen.end()) { - str << "«repeated»"; - } else { - try { - printValue(str, *(*v.list)[n], maxDepth - 1, seen); - } catch (AssertionError& e) { - str << ESC_RED "«error: " << e.msg() << "»" ESC_END; - } - } - str << " "; - } - } else { - str << "... "; - } - - str << "]"; - break; - - case tLambda: { - std::ostringstream s; - s << v.lambda.fun->pos; - str << ESC_BLU "«lambda @ " << filterANSIEscapes(s.str()) << "»" ESC_END; - break; - } - - case tPrimOp: - str << ESC_MAG "«primop»" ESC_END; - break; - - case tPrimOpApp: - str << ESC_BLU "«primop-app»" ESC_END; - break; - - case tFloat: - str << v.fpoint; - break; - - default: - str << ESC_RED "«unknown»" ESC_END; - break; - } - - return str; -} - -struct CmdRepl final : StoreCommand, MixEvalArgs { - std::vector<std::string> files; - - CmdRepl() { expectArgs("files", &files); } - - std::string name() override { return "repl"; } - - std::string description() override { - return "start an interactive environment for evaluating Nix expressions"; - } - - void run(ref<Store> store) override { - auto repl = std::make_unique<NixRepl>(searchPath, openStore()); - repl->autoArgs = getAutoArgs(repl->state); - repl->mainLoop(files); - } -}; - -static RegisterCommand r1(make_ref<CmdRepl>()); - -} // namespace nix diff --git a/third_party/nix/src/nix/run.cc b/third_party/nix/src/nix/run.cc deleted file mode 100644 index b3b54f300b4a..000000000000 --- a/third_party/nix/src/nix/run.cc +++ /dev/null @@ -1,283 +0,0 @@ -#include <queue> - -#include <absl/strings/str_split.h> -#include <sys/mount.h> - -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/derivations.hh" -#include "libstore/fs-accessor.hh" -#include "libstore/local-store.hh" -#include "libstore/store-api.hh" -#include "libutil/affinity.hh" -#include "libutil/finally.hh" -#include "nix/command.hh" - -// note: exported in header file -std::string chrootHelperName = "__run_in_chroot"; - -namespace nix { -struct CmdRun final : InstallablesCommand { - std::vector<std::string> command = {"bash"}; - StringSet keep, unset; - bool ignoreEnvironment = false; - - CmdRun() { - mkFlag() - .longName("command") - .shortName('c') - .description("command and arguments to be executed; defaults to 'bash'") - .labels({"command", "args"}) - .arity(ArityAny) - .handler([&](const std::vector<std::string>& ss) { - if (ss.empty()) { - throw UsageError("--command requires at least one argument"); - } - command = ss; - }); - - mkFlag() - .longName("ignore-environment") - .shortName('i') - .description( - "clear the entire environment (except those specified with --keep)") - .set(&ignoreEnvironment, true); - - mkFlag() - .longName("keep") - .shortName('k') - .description("keep specified environment variable") - .arity(1) - .labels({"name"}) - .handler([&](std::vector<std::string> ss) { keep.insert(ss.front()); }); - - mkFlag() - .longName("unset") - .shortName('u') - .description("unset specified environment variable") - .arity(1) - .labels({"name"}) - .handler( - [&](std::vector<std::string> ss) { unset.insert(ss.front()); }); - } - - std::string name() override { return "run"; } - - std::string description() override { - return "run a shell in which the specified packages are available"; - } - - Examples examples() override { - return { - Example{"To start a shell providing GNU Hello from NixOS 17.03:", - "nix run -f channel:nixos-17.03 hello"}, - Example{"To start a shell providing youtube-dl from your 'nixpkgs' " - "channel:", - "nix run nixpkgs.youtube-dl"}, - Example{"To run GNU Hello:", - "nix run nixpkgs.hello -c hello --greeting 'Hi everybody!'"}, - Example{"To run GNU Hello in a chroot store:", - "nix run --store ~/my-nix nixpkgs.hello -c hello"}, - }; - } - - void run(ref<Store> store) override { - auto outPaths = toStorePaths(store, Build, installables); - - auto accessor = store->getFSAccessor(); - - if (ignoreEnvironment) { - if (!unset.empty()) { - throw UsageError( - "--unset does not make sense with --ignore-environment"); - } - - std::map<std::string, std::string> kept; - for (auto& var : keep) { - auto s = getenv(var.c_str()); - if (s != nullptr) { - kept[var] = s; - } - } - - clearEnv(); - - for (auto& var : kept) { - setenv(var.first.c_str(), var.second.c_str(), 1); - } - - } else { - if (!keep.empty()) { - throw UsageError( - "--keep does not make sense without --ignore-environment"); - } - - for (auto& var : unset) { - unsetenv(var.c_str()); - } - } - - std::unordered_set<Path> done; - std::queue<Path> todo; - for (auto& path : outPaths) { - todo.push(path); - } - - Strings unixPath = absl::StrSplit(getEnv("PATH").value_or(""), - absl::ByChar(':'), absl::SkipEmpty()); - - while (!todo.empty()) { - Path path = todo.front(); - todo.pop(); - if (!done.insert(path).second) { - continue; - } - - { unixPath.push_front(path + "/bin"); } - - auto propPath = path + "/nix-support/propagated-user-env-packages"; - if (accessor->stat(propPath).type == FSAccessor::tRegular) { - for (auto p : - absl::StrSplit(readFile(propPath), absl::ByAnyChar(" \t\n\r"), - absl::SkipEmpty())) { - todo.push(std::string(p)); - } - } - } - - setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); - - std::string cmd = *command.begin(); - Strings args; - for (auto& arg : command) { - args.push_back(arg); - } - - restoreSignals(); - - restoreAffinity(); - - /* If this is a diverted store (i.e. its "logical" location - (typically /nix/store) differs from its "physical" location - (e.g. /home/eelco/nix/store), then run the command in a - chroot. For non-root users, this requires running it in new - mount and user namespaces. Unfortunately, - unshare(CLONE_NEWUSER) doesn't work in a multithreaded - program (which "nix" is), so we exec() a single-threaded - helper program (chrootHelper() below) to do the work. */ - auto store2 = store.dynamic_pointer_cast<LocalStore>(); - - if (store2 && store->storeDir != store2->realStoreDir) { - Strings helperArgs = {chrootHelperName, store->storeDir, - store2->realStoreDir, cmd}; - for (auto& arg : args) { - helperArgs.push_back(arg); - } - - execv(readLink("/proc/self/exe").c_str(), - stringsToCharPtrs(helperArgs).data()); - - throw SysError("could not execute chroot helper"); - } - - execvp(cmd.c_str(), stringsToCharPtrs(args).data()); - - throw SysError("unable to exec '%s'", cmd); - } -}; - -static RegisterCommand r1(make_ref<CmdRun>()); -} // namespace nix - -void chrootHelper(int argc, char** argv) { - int p = 1; - std::string storeDir = argv[p++]; - std::string realStoreDir = argv[p++]; - std::string cmd = argv[p++]; - nix::Strings args; - while (p < argc) { - args.push_back(argv[p++]); - } - -#if __linux__ - uid_t uid = getuid(); - uid_t gid = getgid(); - - if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1) { - /* Try with just CLONE_NEWNS in case user namespaces are - specifically disabled. */ - if (unshare(CLONE_NEWNS) == -1) { - throw nix::SysError("setting up a private mount namespace"); - } - } - - /* Bind-mount realStoreDir on /nix/store. If the latter mount - point doesn't already exists, we have to create a chroot - environment containing the mount point and bind mounts for the - children of /. Would be nice if we could use overlayfs here, - but that doesn't work in a user namespace yet (Ubuntu has a - patch for this: - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1478578). */ - if (!nix::pathExists(storeDir)) { - // FIXME: Use overlayfs? - - nix::Path tmpDir = nix::createTempDir(); - - nix::createDirs(tmpDir + storeDir); - - if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, - nullptr) == -1) { - throw nix::SysError("mounting '%s' on '%s'", realStoreDir, storeDir); - } - - for (const auto& entry : nix::readDirectory("/")) { - auto src = "/" + entry.name; - auto st = nix::lstat(src); - if (!S_ISDIR(st.st_mode)) { - continue; - } - nix::Path dst = tmpDir + "/" + entry.name; - if (nix::pathExists(dst)) { - continue; - } - if (mkdir(dst.c_str(), 0700) == -1) { - throw nix::SysError("creating directory '%s'", dst); - } - if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, nullptr) == - -1) { - throw nix::SysError("mounting '%s' on '%s'", src, dst); - } - } - - char* cwd = getcwd(nullptr, 0); - if (cwd == nullptr) { - throw nix::SysError("getting current directory"); - } - ::Finally freeCwd([&]() { free(cwd); }); - - if (chroot(tmpDir.c_str()) == -1) { - throw nix::SysError(nix::format("chrooting into '%s'") % tmpDir); - } - - if (chdir(cwd) == -1) { - throw nix::SysError(nix::format("chdir to '%s' in chroot") % cwd); - } - } else if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, - nullptr) == -1) { - throw nix::SysError("mounting '%s' on '%s'", realStoreDir, storeDir); - } - - nix::writeFile("/proc/self/setgroups", "deny"); - nix::writeFile("/proc/self/uid_map", nix::fmt("%d %d %d", uid, uid, 1)); - nix::writeFile("/proc/self/gid_map", nix::fmt("%d %d %d", gid, gid, 1)); - - execvp(cmd.c_str(), nix::stringsToCharPtrs(args).data()); - - throw nix::SysError("unable to exec '%s'", cmd); - -#else - throw nix::Error( - "mounting the Nix store on '%s' is not supported on this platform", - storeDir); -#endif -} diff --git a/third_party/nix/src/nix/search.cc b/third_party/nix/src/nix/search.cc deleted file mode 100644 index 5a6bae6a1161..000000000000 --- a/third_party/nix/src/nix/search.cc +++ /dev/null @@ -1,276 +0,0 @@ -#include <fstream> -#include <regex> - -#include <glog/logging.h> - -#include "libexpr/eval-inline.hh" -#include "libexpr/eval.hh" -#include "libexpr/get-drvs.hh" -#include "libexpr/json-to-value.hh" -#include "libexpr/names.hh" -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/globals.hh" -#include "libutil/json.hh" -#include "nix/command.hh" - -namespace { -std::string wrap(const std::string& prefix, const std::string& s) { - return prefix + s + ANSI_NORMAL; -} - -std::string hilite(const std::string& s, const std::smatch& m, - const std::string& postfix) { - return m.empty() ? s - : std::string(m.prefix()) + ANSI_RED + std::string(m.str()) + - postfix + std::string(m.suffix()); -} -} // namespace - -namespace nix { -struct CmdSearch final : SourceExprCommand, MixJSON { - std::vector<std::string> res; - - bool writeCache = true; - bool useCache = true; - - CmdSearch() { - expectArgs("regex", &res); - - mkFlag() - .longName("update-cache") - .shortName('u') - .description("update the package search cache") - .handler([&]() { - writeCache = true; - useCache = false; - }); - - mkFlag() - .longName("no-cache") - .description("do not use or update the package search cache") - .handler([&]() { - writeCache = false; - useCache = false; - }); - } - - std::string name() override { return "search"; } - - std::string description() override { return "query available packages"; } - - Examples examples() override { - return {Example{"To show all available packages:", "nix search"}, - Example{"To show any packages containing 'blender' in its name or " - "description:", - "nix search blender"}, - Example{"To search for Firefox or Chromium:", - "nix search 'firefox|chromium'"}, - Example{"To search for git and frontend or gui:", - "nix search git 'frontend|gui'"}}; - } - - void run(ref<Store> store) override { - settings.readOnlyMode = true; - - // Empty search string should match all packages - // Use "^" here instead of ".*" due to differences in resulting highlighting - // (see #1893 -- libc++ claims empty search string is not in POSIX grammar) - if (res.empty()) { - res.emplace_back("^"); - } - - std::vector<std::regex> regexes; - regexes.reserve(res.size()); - - for (auto& re : res) { - regexes.emplace_back(re, std::regex::extended | std::regex::icase); - } - - auto state = getEvalState(); - - auto jsonOut = json ? std::make_unique<JSONObject>(std::cout) : nullptr; - - auto sToplevel = state->symbols.Create("_toplevel"); - auto sRecurse = state->symbols.Create("recurseForDerivations"); - - bool fromCache = false; - - std::map<std::string, std::string> results; - - std::function<void(Value*, std::string, bool, JSONObject*)> doExpr; - - doExpr = [&](Value* v, const std::string& attrPath, bool toplevel, - JSONObject* cache) { - DLOG(INFO) << "at attribute '" << attrPath << "'"; - - try { - uint found = 0; - - state->forceValue(*v); - - if (v->type == tLambda && toplevel) { - Value* v2 = state->allocValue(); - auto dummyArgs = Bindings::New(); - state->autoCallFunction(dummyArgs.get(), *v, *v2); - v = v2; - state->forceValue(*v); - } - - if (state->isDerivation(*v)) { - DrvInfo drv(*state, attrPath, v->attrs); - std::string description; - std::smatch attrPathMatch; - std::smatch descriptionMatch; - std::smatch nameMatch; - std::string name; - - DrvName parsed(drv.queryName()); - - for (auto& regex : regexes) { - std::regex_search(attrPath, attrPathMatch, regex); - - name = parsed.name; - std::regex_search(name, nameMatch, regex); - - description = drv.queryMetaString("description"); - std::replace(description.begin(), description.end(), '\n', ' '); - std::regex_search(description, descriptionMatch, regex); - - if (!attrPathMatch.empty() || !nameMatch.empty() || - !descriptionMatch.empty()) { - found++; - } - } - - if (found == res.size()) { - if (json) { - auto jsonElem = jsonOut->object(attrPath); - - jsonElem.attr("pkgName", parsed.name); - jsonElem.attr("version", parsed.version); - jsonElem.attr("description", description); - - } else { - auto name = hilite(parsed.name, nameMatch, "\e[0;2m") + - std::string(parsed.fullName, parsed.name.length()); - results[attrPath] = fmt( - "* %s (%s)\n %s\n", - wrap("\e[0;1m", hilite(attrPath, attrPathMatch, "\e[0;1m")), - wrap("\e[0;2m", hilite(name, nameMatch, "\e[0;2m")), - hilite(description, descriptionMatch, ANSI_NORMAL)); - } - } - - if (cache != nullptr) { - cache->attr("type", "derivation"); - cache->attr("name", drv.queryName()); - cache->attr("system", drv.querySystem()); - if (!description.empty()) { - auto meta(cache->object("meta")); - meta.attr("description", description); - } - } - } - - else if (v->type == tAttrs) { - if (!toplevel) { - auto attrs = v->attrs; - Bindings::iterator j = attrs->find(sRecurse); - if (j == attrs->end() || - !state->forceBool(*j->second.value, *j->second.pos)) { - DLOG(INFO) << "skip attribute '" << attrPath << "'"; - return; - } - } - - bool toplevel2 = false; - if (!fromCache) { - Bindings::iterator j = v->attrs->find(sToplevel); - toplevel2 = j != v->attrs->end() && - state->forceBool(*j->second.value, *j->second.pos); - } - - for (auto& i : *v->attrs) { - auto cache2 = - cache != nullptr - ? std::make_unique<JSONObject>(cache->object(i.second.name)) - : nullptr; - doExpr(i.second.value, - attrPath.empty() - ? std::string(i.second.name) - : attrPath + "." + std::string(i.second.name), - toplevel2 || fromCache, cache2 ? cache2.get() : nullptr); - } - } - - } catch (AssertionError& e) { - } catch (Error& e) { - if (!toplevel) { - e.addPrefix(fmt("While evaluating the attribute '%s':\n", attrPath)); - throw; - } - } - }; - - Path jsonCacheFileName = getCacheDir() + "/nix/package-search.json"; - - if (useCache && pathExists(jsonCacheFileName)) { - LOG(WARNING) << "using cached results; pass '-u' to update the cache"; - - Value vRoot; - parseJSON(*state, readFile(jsonCacheFileName), vRoot); - - fromCache = true; - - doExpr(&vRoot, "", true, nullptr); - } - - else { - createDirs(dirOf(jsonCacheFileName)); - - Path tmpFile = fmt("%s.tmp.%d", jsonCacheFileName, getpid()); - - std::ofstream jsonCacheFile; - - try { - // iostream considered harmful - jsonCacheFile.exceptions(std::ofstream::failbit); - jsonCacheFile.open(tmpFile); - - auto cache = writeCache - ? std::make_unique<JSONObject>(jsonCacheFile, false) - : nullptr; - - doExpr(getSourceExpr(*state), "", true, cache.get()); - - } catch (std::exception&) { - /* Fun fact: catching std::ios::failure does not work - due to C++11 ABI shenanigans. - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145 */ - if (!jsonCacheFile) { - throw Error("error writing to %s", tmpFile); - } - throw; - } - - if (writeCache && - rename(tmpFile.c_str(), jsonCacheFileName.c_str()) == -1) { - throw SysError("cannot rename '%s' to '%s'", tmpFile, - jsonCacheFileName); - } - } - - if (results.empty()) { - throw Error("no results for the given search term(s)!"); - } - - RunPager pager; - for (const auto& el : results) { - std::cout << el.second << "\n"; - } - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdSearch>()); diff --git a/third_party/nix/src/nix/show-config.cc b/third_party/nix/src/nix/show-config.cc deleted file mode 100644 index fd92e481e89a..000000000000 --- a/third_party/nix/src/nix/show-config.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include "libmain/common-args.hh" -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "libutil/json.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdShowConfig final : Command, MixJSON { - CmdShowConfig() = default; - - std::string name() override { return "show-config"; } - - std::string description() override { return "show the Nix configuration"; } - - void run() override { - if (json) { - // FIXME: use appropriate JSON types (bool, ints, etc). - JSONObject jsonObj(std::cout); - globalConfig.toJSON(jsonObj); - } else { - std::map<std::string, Config::SettingInfo> settings; - globalConfig.getSettings(settings); - for (auto& s : settings) { - std::cout << s.first + " = " + s.second.value + "\n"; - } - } - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdShowConfig>()); diff --git a/third_party/nix/src/nix/show-derivation.cc b/third_party/nix/src/nix/show-derivation.cc deleted file mode 100644 index efe554710ff8..000000000000 --- a/third_party/nix/src/nix/show-derivation.cc +++ /dev/null @@ -1,113 +0,0 @@ -// FIXME: integrate this with nix path-info? - -#include "libmain/common-args.hh" -#include "libstore/derivations.hh" -#include "libstore/store-api.hh" -#include "libutil/archive.hh" -#include "libutil/json.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdShowDerivation final : InstallablesCommand { - bool recursive = false; - - CmdShowDerivation() { - mkFlag() - .longName("recursive") - .shortName('r') - .description("include the dependencies of the specified derivations") - .set(&recursive, true); - } - - std::string name() override { return "show-derivation"; } - - std::string description() override { - return "show the contents of a store derivation"; - } - - Examples examples() override { - return { - Example{"To show the store derivation that results from evaluating the " - "Hello package:", - "nix show-derivation nixpkgs.hello"}, - Example{"To show the full derivation graph (if available) that " - "produced your NixOS system:", - "nix show-derivation -r /run/current-system"}, - }; - } - - void run(ref<Store> store) override { - auto drvPaths = toDerivations(store, installables, true); - - if (recursive) { - PathSet closure; - store->computeFSClosure(drvPaths, closure); - drvPaths = closure; - } - - { - JSONObject jsonRoot(std::cout, true); - - for (auto& drvPath : drvPaths) { - if (!isDerivation(drvPath)) { - continue; - } - - auto drvObj(jsonRoot.object(drvPath)); - - auto drv = readDerivation(drvPath); - - { - auto outputsObj(drvObj.object("outputs")); - for (auto& output : drv.outputs) { - auto outputObj(outputsObj.object(output.first)); - outputObj.attr("path", output.second.path); - if (!output.second.hash.empty()) { - outputObj.attr("hashAlgo", output.second.hashAlgo); - outputObj.attr("hash", output.second.hash); - } - } - } - - { - auto inputsList(drvObj.list("inputSrcs")); - for (auto& input : drv.inputSrcs) { - inputsList.elem(input); - } - } - - { - auto inputDrvsObj(drvObj.object("inputDrvs")); - for (auto& input : drv.inputDrvs) { - auto inputList(inputDrvsObj.list(input.first)); - for (auto& outputId : input.second) { - inputList.elem(outputId); - } - } - } - - drvObj.attr("platform", drv.platform); - drvObj.attr("builder", drv.builder); - - { - auto argsList(drvObj.list("args")); - for (auto& arg : drv.args) { - argsList.elem(arg); - } - } - - { - auto envObj(drvObj.object("env")); - for (auto& var : drv.env) { - envObj.attr(var.first, var.second); - } - } - } - } - - std::cout << "\n"; - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdShowDerivation>()); diff --git a/third_party/nix/src/nix/sigs.cc b/third_party/nix/src/nix/sigs.cc deleted file mode 100644 index cc42613d0713..000000000000 --- a/third_party/nix/src/nix/sigs.cc +++ /dev/null @@ -1,146 +0,0 @@ -#include <atomic> - -#include <glog/logging.h> - -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "libutil/thread-pool.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdCopySigs final : StorePathsCommand { - Strings substituterUris; - - CmdCopySigs() { - mkFlag() - .longName("substituter") - .shortName('s') - .labels({"store-uri"}) - .description("use signatures from specified store") - .arity(1) - .handler([&](std::vector<std::string> ss) { - substituterUris.push_back(ss[0]); - }); - } - - std::string name() override { return "copy-sigs"; } - - std::string description() override { - return "copy path signatures from substituters (like binary caches)"; - } - - void run(ref<Store> store, Paths storePaths) override { - if (substituterUris.empty()) { - throw UsageError("you must specify at least one substituter using '-s'"); - } - - // FIXME: factor out commonality with MixVerify. - std::vector<ref<Store>> substituters; - for (auto& s : substituterUris) { - substituters.push_back(openStore(s)); - } - - ThreadPool pool; - - std::string doneLabel = "done"; - std::atomic<size_t> added{0}; - - // logger->setExpected(doneLabel, storePaths.size()); - - auto doPath = [&](const Path& storePath) { - // Activity act(*logger, lvlInfo, format("getting signatures for '%s'") % - // storePath); - - checkInterrupt(); - - auto info = store->queryPathInfo(storePath); - - StringSet newSigs; - - for (auto& store2 : substituters) { - try { - auto info2 = store2->queryPathInfo(storePath); - - /* Don't import signatures that don't match this - binary. */ - if (info->narHash != info2->narHash || - info->narSize != info2->narSize || - info->references != info2->references) { - continue; - } - - for (auto& sig : info2->sigs) { - if (info->sigs.count(sig) == 0u) { - newSigs.insert(sig); - } - } - } catch (InvalidPath&) { - } - } - - if (!newSigs.empty()) { - store->addSignatures(storePath, newSigs); - added += newSigs.size(); - } - - // logger->incProgress(doneLabel); - }; - - for (auto& storePath : storePaths) { - pool.enqueue(std::bind(doPath, storePath)); - } - - pool.process(); - - LOG(INFO) << "imported " << added << " signatures"; - } -}; - -static nix::RegisterCommand r1(make_ref<CmdCopySigs>()); - -struct CmdSignPaths final : StorePathsCommand { - Path secretKeyFile; - - CmdSignPaths() { - mkFlag() - .shortName('k') - .longName("key-file") - .label("file") - .description("file containing the secret signing key") - .dest(&secretKeyFile); - } - - std::string name() override { return "sign-paths"; } - - std::string description() override { return "sign the specified paths"; } - - void run(ref<Store> store, Paths storePaths) override { - if (secretKeyFile.empty()) { - throw UsageError("you must specify a secret key file using '-k'"); - } - - SecretKey secretKey(readFile(secretKeyFile)); - - size_t added{0}; - - for (auto& storePath : storePaths) { - auto info = store->queryPathInfo(storePath); - - auto info2(*info); - info2.sigs.clear(); - info2.sign(secretKey); - assert(!info2.sigs.empty()); - - if (info->sigs.count(*info2.sigs.begin()) == 0u) { - store->addSignatures(storePath, info2.sigs); - added++; - } - } - - LOG(INFO) << "added " << added << " signatures"; - } -}; - -static RegisterCommand r3(make_ref<CmdSignPaths>()); - -} // namespace nix diff --git a/third_party/nix/src/nix/upgrade-nix.cc b/third_party/nix/src/nix/upgrade-nix.cc deleted file mode 100644 index c7f654d64884..000000000000 --- a/third_party/nix/src/nix/upgrade-nix.cc +++ /dev/null @@ -1,167 +0,0 @@ -#include <absl/strings/match.h> -#include <absl/strings/str_cat.h> -#include <absl/strings/str_split.h> -#include <glog/logging.h> - -#include "libexpr/attr-path.hh" -#include "libexpr/eval.hh" -#include "libexpr/names.hh" -#include "libmain/common-args.hh" -#include "libstore/download.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdUpgradeNix final : MixDryRun, StoreCommand { - Path profileDir; - std::string storePathsUrl = - "https://github.com/NixOS/nixpkgs/raw/master/nixos/modules/installer/" - "tools/nix-fallback-paths.nix"; - - CmdUpgradeNix() { - mkFlag() - .longName("profile") - .shortName('p') - .labels({"profile-dir"}) - .description("the Nix profile to upgrade") - .dest(&profileDir); - - mkFlag() - .longName("nix-store-paths-url") - .labels({"url"}) - .description( - "URL of the file that contains the store paths of the latest Nix " - "release") - .dest(&storePathsUrl); - } - - std::string name() override { return "upgrade-nix"; } - - std::string description() override { - return "upgrade Nix to the latest stable version"; - } - - Examples examples() override { - return { - Example{"To upgrade Nix to the latest stable version:", - "nix upgrade-nix"}, - Example{ - "To upgrade Nix in a specific profile:", - "nix upgrade-nix -p /nix/var/nix/profiles/per-user/alice/profile"}, - }; - } - - void run(ref<Store> store) override { - evalSettings.pureEval = true; - - if (profileDir.empty()) { - profileDir = getProfileDir(store); - } - - LOG(INFO) << "upgrading Nix in profile '" << profileDir << "'"; - - Path storePath; - { - LOG(INFO) << "querying latest Nix version"; - storePath = getLatestNix(store); - } - - auto version = DrvName(storePathToName(storePath)).version; - - if (dryRun) { - LOG(ERROR) << "would upgrade to version " << version; - return; - } - - { - LOG(INFO) << "downloading '" << storePath << "'..."; - store->ensurePath(storePath); - } - - { - LOG(INFO) << "verifying that '" << storePath << "' works..."; - auto program = storePath + "/bin/nix-env"; - auto s = runProgram(program, false, {"--version"}); - if (s.find("Nix") == std::string::npos) { - throw Error("could not verify that '%s' works", program); - } - } - - { - LOG(INFO) << "installing '" << storePath << "' into profile '" - << profileDir << "'..."; - runProgram(settings.nixBinDir + "/nix-env", false, - {"--profile", profileDir, "-i", storePath, "--no-sandbox"}); - } - - LOG(INFO) << ANSI_GREEN << "upgrade to version " << version << " done" - << ANSI_NORMAL; - } - - /* Return the profile in which Nix is installed. */ - static Path getProfileDir(const ref<Store>& store) { - Path where; - - for (auto& dir : absl::StrSplit(getEnv("PATH").value_or(""), - absl::ByChar(':'), absl::SkipEmpty())) { - if (pathExists(absl::StrCat(dir, "/nix-env"))) { - where = dir; - break; - } - } - - if (where.empty()) { - throw Error( - "couldn't figure out how Nix is installed, so I can't upgrade it"); - } - - LOG(INFO) << "found Nix in '" << where << "'"; - - if (absl::StartsWith(where, "/run/current-system")) { - throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'"); - } - - Path profileDir = dirOf(where); - - // Resolve profile to /nix/var/nix/profiles/<name> link. - while (canonPath(profileDir).find("/profiles/") == std::string::npos && - isLink(profileDir)) { - profileDir = readLink(profileDir); - } - - LOG(INFO) << "found profile '" << profileDir << "'"; - - Path userEnv = canonPath(profileDir, true); - - if (baseNameOf(where) != "bin" || - !absl::EndsWith(userEnv, "user-environment")) { - throw Error("directory '%s' does not appear to be part of a Nix profile", - where); - } - - if (!store->isValidPath(userEnv)) { - throw Error("directory '%s' is not in the Nix store", userEnv); - } - - return profileDir; - } - - /* Return the store path of the latest stable Nix. */ - Path getLatestNix(const ref<Store>& store) { - // FIXME: use nixos.org? - auto req = DownloadRequest(storePathsUrl); - auto res = getDownloader()->download(req); - - auto state = std::make_unique<EvalState>(Strings(), store); - auto v = state->allocValue(); - state->eval(state->parseExprFromString(*res.data, "/no-such-path"), *v); - std::unique_ptr<Bindings> bindings(Bindings::New()); - auto v2 = - findAlongAttrPath(*state, settings.thisSystem, bindings.get(), *v); - - return state->forceString(*v2); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdUpgradeNix>()); diff --git a/third_party/nix/src/nix/verify.cc b/third_party/nix/src/nix/verify.cc deleted file mode 100644 index 7de46f2a9c01..000000000000 --- a/third_party/nix/src/nix/verify.cc +++ /dev/null @@ -1,171 +0,0 @@ -#include <atomic> - -#include <glog/logging.h> - -#include "libmain/shared.hh" -#include "libstore/store-api.hh" -#include "libutil/sync.hh" -#include "libutil/thread-pool.hh" -#include "nix/command.hh" - -namespace nix { -struct CmdVerify final : StorePathsCommand { - bool noContents = false; - bool noTrust = false; - Strings substituterUris; - size_t sigsNeeded = 0; - - CmdVerify() { - mkFlag(0, "no-contents", "do not verify the contents of each store path", - &noContents); - mkFlag(0, "no-trust", "do not verify whether each store path is trusted", - &noTrust); - mkFlag() - .longName("substituter") - .shortName('s') - .labels({"store-uri"}) - .description("use signatures from specified store") - .arity(1) - .handler([&](std::vector<std::string> ss) { - substituterUris.push_back(ss[0]); - }); - mkIntFlag('n', "sigs-needed", - "require that each path has at least N valid signatures", - &sigsNeeded); - } - - std::string name() override { return "verify"; } - - std::string description() override { - return "verify the integrity of store paths"; - } - - Examples examples() override { - return { - Example{"To verify the entire Nix store:", "nix verify --all"}, - Example{"To check whether each path in the closure of Firefox has at " - "least 2 signatures:", - "nix verify -r -n2 --no-contents $(type -p firefox)"}, - }; - } - - void run(ref<Store> store, Paths storePaths) override { - std::vector<ref<Store>> substituters; - for (auto& s : substituterUris) { - substituters.push_back(openStore(s)); - } - - auto publicKeys = getDefaultPublicKeys(); - - std::atomic<size_t> done{0}; - std::atomic<size_t> untrusted{0}; - std::atomic<size_t> corrupted{0}; - std::atomic<size_t> failed{0}; - std::atomic<size_t> active{0}; - - ThreadPool pool; - - auto doPath = [&](const Path& storePath) { - try { - checkInterrupt(); - - LOG(INFO) << "checking '" << storePath << "'"; - - MaintainCount<std::atomic<size_t>> mcActive(active); - - auto info = store->queryPathInfo(storePath); - - if (!noContents) { - HashSink sink(info->narHash.type); - store->narFromPath(info->path, sink); - - auto hash = sink.finish(); - - if (hash.first != info->narHash) { - corrupted++; - LOG(WARNING) << "path '" << info->path - << "' was modified! expected hash '" - << info->narHash.to_string() << "', got '" - << hash.first.to_string() << "'"; - } - } - - if (!noTrust) { - bool good = false; - - if (info->ultimate && (sigsNeeded == 0u)) { - good = true; - - } else { - StringSet sigsSeen; - size_t actualSigsNeeded = - std::max(sigsNeeded, static_cast<size_t>(1)); - size_t validSigs = 0; - - auto doSigs = [&](const StringSet& sigs) { - for (const auto& sig : sigs) { - if (sigsSeen.count(sig) != 0u) { - continue; - } - sigsSeen.insert(sig); - if (validSigs < ValidPathInfo::maxSigs && - info->checkSignature(publicKeys, sig)) { - validSigs++; - } - } - }; - - if (info->isContentAddressed(*store)) { - validSigs = ValidPathInfo::maxSigs; - } - - doSigs(info->sigs); - - for (auto& store2 : substituters) { - if (validSigs >= actualSigsNeeded) { - break; - } - try { - auto info2 = store2->queryPathInfo(info->path); - if (info2->isContentAddressed(*store)) { - validSigs = ValidPathInfo::maxSigs; - } - doSigs(info2->sigs); - } catch (InvalidPath&) { - } catch (Error& e) { - LOG(ERROR) << e.what(); - } - } - - if (validSigs >= actualSigsNeeded) { - good = true; - } - } - - if (!good) { - untrusted++; - LOG(WARNING) << "path '" << info->path << "' is untrusted"; - } - } - - done++; - - } catch (Error& e) { - LOG(ERROR) << e.what(); - failed++; - } - }; - - for (auto& storePath : storePaths) { - pool.enqueue(std::bind(doPath, storePath)); - } - - pool.process(); - - throw Exit((corrupted != 0u ? 1 : 0) | (untrusted != 0u ? 2 : 0) | - (failed != 0u ? 4 : 0)); - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdVerify>()); diff --git a/third_party/nix/src/nix/why-depends.cc b/third_party/nix/src/nix/why-depends.cc deleted file mode 100644 index 954d619ef3ce..000000000000 --- a/third_party/nix/src/nix/why-depends.cc +++ /dev/null @@ -1,269 +0,0 @@ -#include <queue> - -#include <glog/logging.h> - -#include "libmain/shared.hh" -#include "libstore/fs-accessor.hh" -#include "libstore/store-api.hh" -#include "nix/command.hh" - -namespace { -static std::string hilite(const std::string& s, size_t pos, size_t len, - const std::string& colour = ANSI_RED) { - return std::string(s, 0, pos) + colour + std::string(s, pos, len) + - ANSI_NORMAL + std::string(s, pos + len); -} - -static std::string filterPrintable(const std::string& s) { - std::string res; - for (char c : s) { - res += isprint(c) != 0 ? c : '.'; - } - return res; -} -} // namespace - -namespace nix { -struct CmdWhyDepends final : SourceExprCommand { - std::string _package, _dependency; - bool all = false; - - CmdWhyDepends() { - expectArg("package", &_package); - expectArg("dependency", &_dependency); - - mkFlag() - .longName("all") - .shortName('a') - .description( - "show all edges in the dependency graph leading from 'package' to " - "'dependency', rather than just a shortest path") - .set(&all, true); - } - - std::string name() override { return "why-depends"; } - - std::string description() override { - return "show why a package has another package in its closure"; - } - - Examples examples() override { - return { - Example{"To show one path through the dependency graph leading from " - "Hello to Glibc:", - "nix why-depends nixpkgs.hello nixpkgs.glibc"}, - Example{ - "To show all files and paths in the dependency graph leading from " - "Thunderbird to libX11:", - "nix why-depends --all nixpkgs.thunderbird nixpkgs.xorg.libX11"}, - Example{"To show why Glibc depends on itself:", - "nix why-depends nixpkgs.glibc nixpkgs.glibc"}, - }; - } - - void run(ref<Store> store) override { - auto package = parseInstallable(*this, store, _package, false); - auto packagePath = toStorePath(store, Build, package); - auto dependency = parseInstallable(*this, store, _dependency, false); - auto dependencyPath = toStorePath(store, NoBuild, dependency); - auto dependencyPathHash = storePathToHash(dependencyPath); - - PathSet closure; - store->computeFSClosure({packagePath}, closure, false, false); - - if (closure.count(dependencyPath) == 0u) { - LOG(WARNING) << "'" << package->what() << "' does not depend on '" - << dependency->what() << "'"; - return; - } - - auto accessor = store->getFSAccessor(); - - auto const inf = std::numeric_limits<size_t>::max(); - - struct Node { - Path path; - PathSet refs; - PathSet rrefs; - size_t dist = inf; - Node* prev = nullptr; - bool queued = false; - bool visited = false; - }; - - std::map<Path, Node> graph; - - for (auto& path : closure) { - graph.emplace(path, Node{path, store->queryPathInfo(path)->references}); - } - - // Transpose the graph. - for (auto& node : graph) { - for (auto& ref : node.second.refs) { - graph[ref].rrefs.insert(node.first); - } - } - - /* Run Dijkstra's shortest path algorithm to get the distance - of every path in the closure to 'dependency'. */ - graph[dependencyPath].dist = 0; - - std::priority_queue<Node*> queue; - - queue.push(&graph.at(dependencyPath)); - - while (!queue.empty()) { - auto& node = *queue.top(); - queue.pop(); - - for (auto& rref : node.rrefs) { - auto& node2 = graph.at(rref); - auto dist = node.dist + 1; - if (dist < node2.dist) { - node2.dist = dist; - node2.prev = &node; - if (!node2.queued) { - node2.queued = true; - queue.push(&node2); - } - } - } - } - - /* Print the subgraph of nodes that have 'dependency' in their - closure (i.e., that have a non-infinite distance to - 'dependency'). Print every edge on a path between `package` - and `dependency`. */ - std::function<void(Node&, const std::string&, const std::string&)> - printNode; - - const std::string treeConn = "╠═══"; - const std::string treeLast = "╚═══"; - const std::string treeLine = "║ "; - const std::string treeNull = " "; - - struct BailOut {}; - - printNode = [&](Node& node, const std::string& firstPad, - const std::string& tailPad) { - assert(node.dist != inf); - std::cout << fmt("%s%s%s%s" ANSI_NORMAL "\n", firstPad, - node.visited ? "\e[38;5;244m" : "", - !firstPad.empty() ? "=> " : "", node.path); - - if (node.path == dependencyPath && !all && - packagePath != dependencyPath) { - throw BailOut(); - } - - if (node.visited) { - return; - } - node.visited = true; - - /* Sort the references by distance to `dependency` to - ensure that the shortest path is printed first. */ - std::multimap<size_t, Node*> refs; - std::set<std::string> hashes; - - for (auto& ref : node.refs) { - if (ref == node.path && packagePath != dependencyPath) { - continue; - } - auto& node2 = graph.at(ref); - if (node2.dist == inf) { - continue; - } - refs.emplace(node2.dist, &node2); - hashes.insert(storePathToHash(node2.path)); - } - - /* For each reference, find the files and symlinks that - contain the reference. */ - std::map<std::string, Strings> hits; - - std::function<void(const Path&)> visitPath; - - visitPath = [&](const Path& p) { - auto st = accessor->stat(p); - - auto p2 = p == node.path ? "/" : std::string(p, node.path.size() + 1); - - auto getColour = [&](const std::string& hash) { - return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE; - }; - - if (st.type == FSAccessor::Type::tDirectory) { - auto names = accessor->readDirectory(p); - for (auto& name : names) { - visitPath(p + "/" + name); - } - } - - else if (st.type == FSAccessor::Type::tRegular) { - auto contents = accessor->readFile(p); - - for (auto& hash : hashes) { - auto pos = contents.find(hash); - if (pos != std::string::npos) { - size_t margin = 32; - auto pos2 = pos >= margin ? pos - margin : 0; - hits[hash].emplace_back(fmt( - "%s: …%s…\n", p2, - hilite( - filterPrintable(std::string( - contents, pos2, pos - pos2 + hash.size() + margin)), - pos - pos2, storePathHashLen, getColour(hash)))); - } - } - } - - else if (st.type == FSAccessor::Type::tSymlink) { - auto target = accessor->readLink(p); - - for (auto& hash : hashes) { - auto pos = target.find(hash); - if (pos != std::string::npos) { - hits[hash].emplace_back( - fmt("%s -> %s\n", p2, - hilite(target, pos, storePathHashLen, getColour(hash)))); - } - } - } - }; - - // FIXME: should use scanForReferences(). - - visitPath(node.path); - - RunPager pager; - for (auto& ref : refs) { - auto hash = storePathToHash(ref.second->path); - - bool last = all ? ref == *refs.rbegin() : true; - - for (auto& hit : hits[hash]) { - bool first = hit == *hits[hash].begin(); - std::cout << tailPad - << (first ? (last ? treeLast : treeConn) - : (last ? treeNull : treeLine)) - << hit; - if (!all) { - break; - } - } - - printNode(*ref.second, tailPad + (last ? treeNull : treeLine), - tailPad + (last ? treeNull : treeLine)); - } - }; - - try { - printNode(graph.at(packagePath), "", ""); - } catch (BailOut&) { - } - } -}; -} // namespace nix - -static nix::RegisterCommand r1(nix::make_ref<nix::CmdWhyDepends>()); |