aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-01-27 17:17:58 +0100
committerGitHub <noreply@github.com>2021-01-27 17:17:58 +0100
commitb8f345b29a65669f4d6966ba3837fda2341c5ec2 (patch)
tree7bfb6b59ad8e48454e4311307277017ab6b392de /src/nix
parent12de0466fea6558ccb0dd5b98b72d7a068c9b5e8 (diff)
parent6af6e41df06f0a8a3b919b4052b41d09f0a97678 (diff)
Merge pull request #4483 from shlevy/libcmd
Move command plugin interface to libnixcmd
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/command.cc237
-rw-r--r--src/nix/command.hh274
-rw-r--r--src/nix/daemon.cc2
-rw-r--r--src/nix/installables.cc824
-rw-r--r--src/nix/installables.hh137
-rw-r--r--src/nix/legacy.cc7
-rw-r--r--src/nix/legacy.hh23
-rw-r--r--src/nix/local.mk4
-rw-r--r--src/nix/markdown.cc50
-rw-r--r--src/nix/markdown.hh7
10 files changed, 3 insertions, 1562 deletions
diff --git a/src/nix/command.cc b/src/nix/command.cc
deleted file mode 100644
index 614dee788..000000000
--- a/src/nix/command.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-#include "command.hh"
-#include "store-api.hh"
-#include "local-fs-store.hh"
-#include "derivations.hh"
-#include "nixexpr.hh"
-#include "profiles.hh"
-
-#include <nlohmann/json.hpp>
-
-extern char * * environ __attribute__((weak));
-
-namespace nix {
-
-RegisterCommand::Commands * RegisterCommand::commands = nullptr;
-
-nix::Commands RegisterCommand::getCommandsFor(const std::vector<std::string> & prefix)
-{
- nix::Commands res;
- for (auto & [name, command] : *RegisterCommand::commands)
- if (name.size() == prefix.size() + 1) {
- bool equal = true;
- for (size_t i = 0; i < prefix.size(); ++i)
- if (name[i] != prefix[i]) equal = false;
- if (equal)
- res.insert_or_assign(name[prefix.size()], command);
- }
- return res;
-}
-
-nlohmann::json NixMultiCommand::toJSON()
-{
- // FIXME: use Command::toJSON() as well.
- return MultiCommand::toJSON();
-}
-
-StoreCommand::StoreCommand()
-{
-}
-
-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)
- addFlag({
- .longName = "no-recursive",
- .description = "Apply operation to specified paths only.",
- .category = installablesCategory,
- .handler = {&this->recursive, false},
- });
- else
- addFlag({
- .longName = "recursive",
- .shortName = 'r',
- .description = "Apply operation to closure of the specified paths.",
- .category = installablesCategory,
- .handler = {&this->recursive, true},
- });
-
- addFlag({
- .longName = "all",
- .description = "Apply the operation to every store path.",
- .category = installablesCategory,
- .handler = {&all, true},
- });
-}
-
-void StorePathsCommand::run(ref<Store> store)
-{
- StorePaths storePaths;
-
- if (all) {
- if (installables.size())
- throw UsageError("'--all' does not expect arguments");
- for (auto & p : store->queryAllValidPaths())
- storePaths.push_back(p);
- }
-
- else {
- for (auto & p : toStorePaths(store, realiseMode, operateOn, installables))
- storePaths.push_back(p);
-
- if (recursive) {
- StorePathSet closure;
- store->computeFSClosure(StorePathSet(storePaths.begin(), storePaths.end()), closure, false, false);
- storePaths.clear();
- for (auto & p : closure)
- storePaths.push_back(p);
- }
- }
-
- run(store, std::move(storePaths));
-}
-
-void StorePathCommand::run(ref<Store> store)
-{
- auto storePaths = toStorePaths(store, Realise::Nothing, operateOn, installables);
-
- if (storePaths.size() != 1)
- throw UsageError("this command requires exactly one store path");
-
- run(store, *storePaths.begin());
-}
-
-Strings editorFor(const Pos & pos)
-{
- auto editor = getEnv("EDITOR").value_or("cat");
- auto args = tokenizeString<Strings>(editor);
- if (pos.line > 0 && (
- editor.find("emacs") != std::string::npos ||
- editor.find("nano") != std::string::npos ||
- editor.find("vim") != std::string::npos))
- args.push_back(fmt("+%d", pos.line));
- args.push_back(pos.file);
- return args;
-}
-
-MixProfile::MixProfile()
-{
- addFlag({
- .longName = "profile",
- .description = "The profile to update.",
- .labels = {"path"},
- .handler = {&profile},
- .completer = completePath
- });
-}
-
-void MixProfile::updateProfile(const StorePath & storePath)
-{
- if (!profile) return;
- auto store = getStore().dynamic_pointer_cast<LocalFSStore>();
- if (!store) throw Error("'--profile' is not supported for this Nix store");
- auto profile2 = absPath(*profile);
- switchLink(profile2,
- createGeneration(
- ref<LocalFSStore>(store),
- profile2, storePath));
-}
-
-void MixProfile::updateProfile(const Buildables & buildables)
-{
- if (!profile) return;
-
- std::vector<StorePath> result;
-
- for (auto & buildable : buildables) {
- std::visit(overloaded {
- [&](BuildableOpaque bo) {
- result.push_back(bo.path);
- },
- [&](BuildableFromDrv bfd) {
- for (auto & output : bfd.outputs) {
- /* Output path should be known because we just tried to
- build it. */
- assert(output.second);
- result.push_back(*output.second);
- }
- },
- }, buildable);
- }
-
- if (result.size() != 1)
- throw Error("'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
-
- updateProfile(result[0]);
-}
-
-MixDefaultProfile::MixDefaultProfile()
-{
- profile = getDefaultProfile();
-}
-
-MixEnvironment::MixEnvironment() : ignoreEnvironment(false)
-{
- addFlag({
- .longName = "ignore-environment",
- .shortName = 'i',
- .description = "Clear the entire environment (except those specified with `--keep`).",
- .handler = {&ignoreEnvironment, true},
- });
-
- addFlag({
- .longName = "keep",
- .shortName = 'k',
- .description = "Keep the environment variable *name*.",
- .labels = {"name"},
- .handler = {[&](std::string s) { keep.insert(s); }},
- });
-
- addFlag({
- .longName = "unset",
- .shortName = 'u',
- .description = "Unset the environment variable *name*.",
- .labels = {"name"},
- .handler = {[&](std::string s) { unset.insert(s); }},
- });
-}
-
-void MixEnvironment::setEnviron() {
- if (ignoreEnvironment) {
- if (!unset.empty())
- throw UsageError("--unset does not make sense with --ignore-environment");
-
- for (const auto & var : keep) {
- auto val = getenv(var.c_str());
- if (val) stringsEnv.emplace_back(fmt("%s=%s", var.c_str(), val));
- }
-
- vectorEnv = stringsToCharPtrs(stringsEnv);
- environ = vectorEnv.data();
- } else {
- if (!keep.empty())
- throw UsageError("--keep does not make sense without --ignore-environment");
-
- for (const auto & var : unset)
- unsetenv(var.c_str());
- }
-}
-
-}
diff --git a/src/nix/command.hh b/src/nix/command.hh
deleted file mode 100644
index ed6980075..000000000
--- a/src/nix/command.hh
+++ /dev/null
@@ -1,274 +0,0 @@
-#pragma once
-
-#include "installables.hh"
-#include "args.hh"
-#include "common-eval-args.hh"
-#include "path.hh"
-#include "flake/lockfile.hh"
-#include "store-api.hh"
-
-#include <optional>
-
-namespace nix {
-
-extern std::string programPath;
-
-extern char * * savedArgv;
-
-class EvalState;
-struct Pos;
-class Store;
-
-static constexpr Command::Category catSecondary = 100;
-static constexpr Command::Category catUtility = 101;
-static constexpr Command::Category catNixInstallation = 102;
-
-static constexpr auto installablesCategory = "Options that change the interpretation of installables";
-
-struct NixMultiCommand : virtual MultiCommand, virtual Command
-{
- nlohmann::json toJSON() override;
-};
-
-/* A command that requires 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 EvalCommand : virtual StoreCommand, MixEvalArgs
-{
- ref<EvalState> getEvalState();
-
- std::shared_ptr<EvalState> evalState;
-};
-
-struct MixFlakeOptions : virtual Args, EvalCommand
-{
- flake::LockFlags lockFlags;
-
- MixFlakeOptions();
-
- virtual std::optional<FlakeRef> getFlakeRefForCompletion()
- { return {}; }
-};
-
-/* How to handle derivations in commands that operate on store paths. */
-enum class OperateOn {
- /* Operate on the output path. */
- Output,
- /* Operate on the .drv path. */
- Derivation
-};
-
-struct SourceExprCommand : virtual Args, MixFlakeOptions
-{
- std::optional<Path> file;
- std::optional<std::string> expr;
-
- // FIXME: move this; not all commands (e.g. 'nix run') use it.
- OperateOn operateOn = OperateOn::Output;
-
- SourceExprCommand();
-
- std::vector<std::shared_ptr<Installable>> parseInstallables(
- ref<Store> store, std::vector<std::string> ss);
-
- std::shared_ptr<Installable> parseInstallable(
- ref<Store> store, const std::string & installable);
-
- virtual Strings getDefaultFlakeAttrPaths();
-
- virtual Strings getDefaultFlakeAttrPathPrefixes();
-
- void completeInstallable(std::string_view prefix);
-};
-
-enum class Realise {
- /* Build the derivation. Postcondition: the
- derivation outputs exist. */
- Outputs,
- /* Don't build the derivation. Postcondition: the store derivation
- exists. */
- Derivation,
- /* Evaluate in dry-run mode. Postcondition: nothing. */
- Nothing
-};
-
-/* 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();
-
- void prepare() override;
-
- virtual bool useDefaultInstallables() { return true; }
-
- std::optional<FlakeRef> getFlakeRefForCompletion() override;
-
-private:
-
- std::vector<std::string> _installables;
-};
-
-/* A command that operates on exactly one "installable" */
-struct InstallableCommand : virtual Args, SourceExprCommand
-{
- std::shared_ptr<Installable> installable;
-
- InstallableCommand();
-
- void prepare() override;
-
- std::optional<FlakeRef> getFlakeRefForCompletion() override
- {
- return parseFlakeRef(_installable, absPath("."));
- }
-
-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;
-
-protected:
-
- Realise realiseMode = Realise::Derivation;
-
-public:
-
- StorePathsCommand(bool recursive = false);
-
- using StoreCommand::run;
-
- virtual void run(ref<Store> store, std::vector<StorePath> 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 StorePath & storePath) = 0;
-
- void run(ref<Store> store) override;
-};
-
-/* A helper class for registering commands globally. */
-struct RegisterCommand
-{
- typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
- static Commands * commands;
-
- RegisterCommand(std::vector<std::string> && name,
- std::function<ref<Command>()> command)
- {
- if (!commands) commands = new Commands;
- commands->emplace(name, command);
- }
-
- static nix::Commands getCommandsFor(const std::vector<std::string> & prefix);
-};
-
-template<class T>
-static RegisterCommand registerCommand(const std::string & name)
-{
- return RegisterCommand({name}, [](){ return make_ref<T>(); });
-}
-
-template<class T>
-static RegisterCommand registerCommand2(std::vector<std::string> && name)
-{
- return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
-}
-
-Buildables build(ref<Store> store, Realise mode,
- std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode = bmNormal);
-
-std::set<StorePath> toStorePaths(ref<Store> store,
- Realise mode, OperateOn operateOn,
- std::vector<std::shared_ptr<Installable>> installables);
-
-StorePath toStorePath(ref<Store> store,
- Realise mode, OperateOn operateOn,
- std::shared_ptr<Installable> installable);
-
-std::set<StorePath> toDerivations(ref<Store> store,
- std::vector<std::shared_ptr<Installable>> installables,
- bool useDeriver = false);
-
-/* Helper function to generate args that invoke $EDITOR on
- filename:lineno. */
-Strings editorFor(const Pos & pos);
-
-struct MixProfile : virtual StoreCommand
-{
- std::optional<Path> profile;
-
- MixProfile();
-
- /* If 'profile' is set, make it point at 'storePath'. */
- void updateProfile(const StorePath & storePath);
-
- /* If 'profile' is set, make it point at the store path produced
- by 'buildables'. */
- void updateProfile(const Buildables & buildables);
-};
-
-struct MixDefaultProfile : MixProfile
-{
- MixDefaultProfile();
-};
-
-struct MixEnvironment : virtual Args {
-
- StringSet keep, unset;
- Strings stringsEnv;
- std::vector<char*> vectorEnv;
- bool ignoreEnvironment;
-
- MixEnvironment();
-
- /* Modify global environ based on ignoreEnvironment, keep, and unset. It's expected that exec will be called before this class goes out of scope, otherwise environ will become invalid. */
- void setEnviron();
-};
-
-void completeFlakeRef(ref<Store> store, std::string_view prefix);
-
-void completeFlakeRefWithFragment(
- ref<EvalState> evalState,
- flake::LockFlags lockFlags,
- Strings attrPathPrefixes,
- const Strings & defaultFlakeAttrPaths,
- std::string_view prefix);
-
-std::string showVersions(const std::set<std::string> & versions);
-
-void printClosureDiff(
- ref<Store> store,
- const StorePath & beforePath,
- const StorePath & afterPath,
- std::string_view indent);
-
-}
diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc
index a358cb0d9..26006167d 100644
--- a/src/nix/daemon.cc
+++ b/src/nix/daemon.cc
@@ -8,7 +8,7 @@
#include "globals.hh"
#include "derivations.hh"
#include "finally.hh"
-#include "../nix/legacy.hh"
+#include "legacy.hh"
#include "daemon.hh"
#include <algorithm>
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
deleted file mode 100644
index 4e6bf4a9a..000000000
--- a/src/nix/installables.cc
+++ /dev/null
@@ -1,824 +0,0 @@
-#include "installables.hh"
-#include "command.hh"
-#include "attr-path.hh"
-#include "common-eval-args.hh"
-#include "derivations.hh"
-#include "eval-inline.hh"
-#include "eval.hh"
-#include "get-drvs.hh"
-#include "store-api.hh"
-#include "shared.hh"
-#include "flake/flake.hh"
-#include "eval-cache.hh"
-#include "url.hh"
-#include "registry.hh"
-
-#include <regex>
-#include <queue>
-
-#include <nlohmann/json.hpp>
-
-namespace nix {
-
-nlohmann::json BuildableOpaque::toJSON(ref<Store> store) const {
- nlohmann::json res;
- res["path"] = store->printStorePath(path);
- return res;
-}
-
-nlohmann::json BuildableFromDrv::toJSON(ref<Store> store) const {
- nlohmann::json res;
- res["drvPath"] = store->printStorePath(drvPath);
- for (const auto& [output, path] : outputs) {
- res["outputs"][output] = path ? store->printStorePath(*path) : "";
- }
- return res;
-}
-
-nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store) {
- auto res = nlohmann::json::array();
- for (const Buildable & buildable : buildables) {
- std::visit([&res, store](const auto & buildable) {
- res.push_back(buildable.toJSON(store));
- }, buildable);
- }
- return res;
-}
-
-void completeFlakeInputPath(
- ref<EvalState> evalState,
- const FlakeRef & flakeRef,
- std::string_view prefix)
-{
- auto flake = flake::getFlake(*evalState, flakeRef, true);
- for (auto & input : flake.inputs)
- if (hasPrefix(input.first, prefix))
- completions->add(input.first);
-}
-
-MixFlakeOptions::MixFlakeOptions()
-{
- auto category = "Common flake-related options";
-
- addFlag({
- .longName = "recreate-lock-file",
- .description = "Recreate the flake's lock file from scratch.",
- .category = category,
- .handler = {&lockFlags.recreateLockFile, true}
- });
-
- addFlag({
- .longName = "no-update-lock-file",
- .description = "Do not allow any updates to the flake's lock file.",
- .category = category,
- .handler = {&lockFlags.updateLockFile, false}
- });
-
- addFlag({
- .longName = "no-write-lock-file",
- .description = "Do not write the flake's newly generated lock file.",
- .category = category,
- .handler = {&lockFlags.writeLockFile, false}
- });
-
- addFlag({
- .longName = "no-registries",
- .description = "Don't allow lookups in the flake registries.",
- .category = category,
- .handler = {&lockFlags.useRegistries, false}
- });
-
- addFlag({
- .longName = "commit-lock-file",
- .description = "Commit changes to the flake's lock file.",
- .category = category,
- .handler = {&lockFlags.commitLockFile, true}
- });
-
- addFlag({
- .longName = "update-input",
- .description = "Update a specific flake input (ignoring its previous entry in the lock file).",
- .category = category,
- .labels = {"input-path"},
- .handler = {[&](std::string s) {
- lockFlags.inputUpdates.insert(flake::parseInputPath(s));
- }},
- .completer = {[&](size_t, std::string_view prefix) {
- if (auto flakeRef = getFlakeRefForCompletion())
- completeFlakeInputPath(getEvalState(), *flakeRef, prefix);
- }}
- });
-
- addFlag({
- .longName = "override-input",
- .description = "Override a specific flake input (e.g. `dwarffs/nixpkgs`).",
- .category = category,
- .labels = {"input-path", "flake-url"},
- .handler = {[&](std::string inputPath, std::string flakeRef) {
- lockFlags.inputOverrides.insert_or_assign(
- flake::parseInputPath(inputPath),
- parseFlakeRef(flakeRef, absPath(".")));
- }}
- });
-
- addFlag({
- .longName = "inputs-from",
- .description = "Use the inputs of the specified flake as registry entries.",
- .category = category,
- .labels = {"flake-url"},
- .handler = {[&](std::string flakeRef) {
- auto evalState = getEvalState();
- auto flake = flake::lockFlake(
- *evalState,
- parseFlakeRef(flakeRef, absPath(".")),
- { .writeLockFile = false });
- for (auto & [inputName, input] : flake.lockFile.root->inputs) {
- auto input2 = flake.lockFile.findInput({inputName}); // resolve 'follows' nodes
- if (auto input3 = std::dynamic_pointer_cast<const flake::LockedNode>(input2)) {
- overrideRegistry(
- fetchers::Input::fromAttrs({{"type","indirect"}, {"id", inputName}}),
- input3->lockedRef.input,
- {});
- }
- }
- }},
- .completer = {[&](size_t, std::string_view prefix) {
- completeFlakeRef(getEvalState()->store, prefix);
- }}
- });
-}
-
-SourceExprCommand::SourceExprCommand()
-{
- addFlag({
- .longName = "file",
- .shortName = 'f',
- .description = "Interpret installables as attribute paths relative to the Nix expression stored in *file*.",
- .category = installablesCategory,
- .labels = {"file"},
- .handler = {&file},
- .completer = completePath
- });
-
- addFlag({
- .longName = "expr",
- .description = "Interpret installables as attribute paths relative to the Nix expression *expr*.",
- .category = installablesCategory,
- .labels = {"expr"},
- .handler = {&expr}
- });
-
- addFlag({
- .longName = "derivation",
- .description = "Operate on the store derivation rather than its outputs.",
- .category = installablesCategory,
- .handler = {&operateOn, OperateOn::Derivation},
- });
-}
-
-Strings SourceExprCommand::getDefaultFlakeAttrPaths()
-{
- return {"defaultPackage." + settings.thisSystem.get()};
-}
-
-Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
-{
- return {
- // As a convenience, look for the attribute in
- // 'outputs.packages'.
- "packages." + settings.thisSystem.get() + ".",
- // As a temporary hack until Nixpkgs is properly converted
- // to provide a clean 'packages' set, look in 'legacyPackages'.
- "legacyPackages." + settings.thisSystem.get() + "."
- };
-}
-
-void SourceExprCommand::completeInstallable(std::string_view prefix)
-{
- if (file) return; // FIXME
-
- completeFlakeRefWithFragment(
- getEvalState(),
- lockFlags,
- getDefaultFlakeAttrPathPrefixes(),
- getDefaultFlakeAttrPaths(),
- prefix);
-}
-
-void completeFlakeRefWithFragment(
- ref<EvalState> evalState,
- flake::LockFlags lockFlags,
- Strings attrPathPrefixes,
- const Strings & defaultFlakeAttrPaths,
- std::string_view prefix)
-{
- /* Look for flake output attributes that match the
- prefix. */
- try {
- auto hash = prefix.find('#');
- if (hash != std::string::npos) {
- auto fragment = prefix.substr(hash + 1);
- auto flakeRefS = std::string(prefix.substr(0, hash));
- // FIXME: do tilde expansion.
- auto flakeRef = parseFlakeRef(flakeRefS, absPath("."));
-
- auto evalCache = openEvalCache(*evalState,
- std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags)));
-
- auto root = evalCache->getRoot();
-
- /* Complete 'fragment' relative to all the
- attrpath prefixes as well as the root of the
- flake. */
- attrPathPrefixes.push_back("");
-
- for (auto & attrPathPrefixS : attrPathPrefixes) {
- auto attrPathPrefix = parseAttrPath(*evalState, attrPathPrefixS);
- auto attrPathS = attrPathPrefixS + std::string(fragment);
- auto attrPath = parseAttrPath(*evalState, attrPathS);
-
- std::string lastAttr;
- if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) {
- lastAttr = attrPath.back();
- attrPath.pop_back();
- }
-
- auto attr = root->findAlongAttrPath(attrPath);
- if (!attr) continue;
-
- for (auto & attr2 : attr->getAttrs()) {
- if (hasPrefix(attr2, lastAttr)) {
- auto attrPath2 = attr->getAttrPath(attr2);
- /* Strip the attrpath prefix. */
- attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
- completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2));
- }
- }
- }
-
- /* And add an empty completion for the default
- attrpaths. */
- if (fragment.empty()) {
- for (auto & attrPath : defaultFlakeAttrPaths) {
- auto attr = root->findAlongAttrPath(parseAttrPath(*evalState, attrPath));
- if (!attr) continue;
- completions->add(flakeRefS + "#");
- }
- }
- }
- } catch (Error & e) {
- warn(e.msg());
- }
-
- completeFlakeRef(evalState->store, prefix);
-}
-
-ref<EvalState> EvalCommand::getEvalState()
-{
- if (!evalState)
- evalState = std::make_shared<EvalState>(searchPath, getStore());
- return ref<EvalState>(evalState);
-}
-
-void completeFlakeRef(ref<Store> store, std::string_view prefix)
-{
- if (prefix == "")
- completions->add(".");
-
- completeDir(0, prefix);
-
- /* Look for registry entries that match the prefix. */
- for (auto & registry : fetchers::getRegistries(store)) {
- for (auto & entry : registry->entries) {
- auto from = entry.from.to_string();
- if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) {
- std::string from2(from, 6);
- if (hasPrefix(from2, prefix))
- completions->add(from2);
- } else {
- if (hasPrefix(from, prefix))
- completions->add(from);
- }
- }
- }
-}
-
-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]);
-}
-
-std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
-Installable::getCursors(EvalState & state)
-{
- auto evalCache =
- std::make_shared<nix::eval_cache::EvalCache>(std::nullopt, state,
- [&]() { return toValue(state).first; });
- return {{evalCache->getRoot(), ""}};
-}
-
-std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>
-Installable::getCursor(EvalState & state)
-{
- auto cursors = getCursors(state);
- if (cursors.empty())
- throw Error("cannot find flake attribute '%s'", what());
- return cursors[0];
-}
-
-struct InstallableStorePath : Installable
-{
- ref<Store> store;
- StorePath storePath;
-
- InstallableStorePath(ref<Store> store, StorePath && storePath)
- : store(store), storePath(std::move(storePath)) { }
-
- std::string what() override { return store->printStorePath(storePath); }
-
- Buildables toBuildables() override
- {
- if (storePath.isDerivation()) {
- std::map<std::string, std::optional<StorePath>> outputs;
- auto drv = store->readDerivation(storePath);
- for (auto & [name, output] : drv.outputsAndOptPaths(*store))
- outputs.emplace(name, output.second);
- return {
- BuildableFromDrv {
- .drvPath = storePath,
- .outputs = std::move(outputs)
- }
- };
- } else {
- return {
- BuildableOpaque {
- .path = storePath,
- }
- };
- }
- }
-
- std::optional<StorePath> getStorePath() override
- {
- return storePath;
- }
-};
-
-Buildables InstallableValue::toBuildables()
-{
- Buildables res;
-
- std::map<StorePath, std::map<std::string, std::optional<StorePath>>> drvsToOutputs;
-
- // Group by derivation, helps with .all in particular
- for (auto & drv : toDerivations()) {
- auto outputName = drv.outputName;
- if (outputName == "")
- throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath));
- drvsToOutputs[drv.drvPath].insert_or_assign(outputName, drv.outPath);
- }
-
- for (auto & i : drvsToOutputs)
- res.push_back(BuildableFromDrv { i.first, i.second });
-
- return res;
-}
-
-struct InstallableAttrPath : InstallableValue
-{
- SourceExprCommand & cmd;
- RootValue v;
- std::string attrPath;
-
- InstallableAttrPath(ref<EvalState> state, SourceExprCommand & cmd, Value * v, const std::string & attrPath)
- : InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath)
- { }
-
- std::string what() override { return attrPath; }
-
- std::pair<Value *, Pos> toValue(EvalState & state) override
- {
- auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(state), **v);
- state.forceValue(*vRes);
- return {vRes, pos};
- }
-
- virtual std::vector<InstallableValue::DerivationInfo> toDerivations() override;
-};
-
-std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations()
-{
- auto v = toValue(*state).first;
-
- Bindings & autoArgs = *cmd.getAutoArgs(*state);
-
- DrvInfos drvInfos;
- getDerivations(*state, *v, "", autoArgs, drvInfos, false);
-
- std::vector<DerivationInfo> res;
- for (auto & drvInfo : drvInfos) {
- res.push_back({
- state->store->parseStorePath(drvInfo.queryDrvPath()),
- state->store->maybeParseStorePath(drvInfo.queryOutPath()),
- drvInfo.queryOutputName()
- });
- }
-
- return res;
-}
-
-std::vector<std::string> InstallableFlake::getActualAttrPaths()
-{
- std::vector<std::string> res;
-
- for (auto & prefix : prefixes)
- res.push_back(prefix + *attrPaths.begin());
-
- for (auto & s : attrPaths)
- res.push_back(s);
-
- return res;
-}
-
-Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::LockedFlake & lockedFlake)
-{
- auto vFlake = state.allocValue();
-
- callFlake(state, lockedFlake, *vFlake);
-
- auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
- assert(aOutputs);
-
- state.forceValue(*aOutputs->value);
-
- return aOutputs->value;
-}
-
-ref<eval_cache::EvalCache> openEvalCache(
- EvalState & state,
- std::shared_ptr<flake::LockedFlake> lockedFlake)
-{
- auto fingerprint = lockedFlake->getFingerprint();
- return make_ref<nix::eval_cache::EvalCache>(
- evalSettings.useEvalCache && evalSettings.pureEval
- ? std::optional { std::cref(fingerprint) }
- : std::nullopt,
- state,
- [&state, lockedFlake]()
- {
- /* For testing whether the evaluation cache is
- complete. */
- if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0")
- throw Error("not everything is cached, but evaluation is not allowed");
-
- auto vFlake = state.allocValue();
- flake::callFlake(state, *lockedFlake, *vFlake);
-
- state.forceAttrs(*vFlake);
-
- auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
- assert(aOutputs);
-
- return aOutputs->value;
- });
-}
-
-static std::string showAttrPaths(const std::vector<std::string> & paths)
-{
- std::string s;
- for (const auto & [n, i] : enumerate(paths)) {
- if (n > 0) s += n + 1 == paths.size() ? " or " : ", ";
- s += '\''; s += i; s += '\'';
- }
- return s;
-}
-
-std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableFlake::toDerivation()
-{
- auto lockedFlake = getLockedFlake();
-
- auto cache = openEvalCache(*state, lockedFlake);
- auto root = cache->getRoot();
-
- for (auto & attrPath : getActualAttrPaths()) {
- auto attr = root->findAlongAttrPath(parseAttrPath(*state, attrPath));
- if (!attr) continue;
-
- if (!attr->isDerivation())
- throw Error("flake output attribute '%s' is not a derivation", attrPath);
-
- auto drvPath = attr->forceDerivation();
-
- auto drvInfo = DerivationInfo{
- std::move(drvPath),
- state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
- attr->getAttr(state->sOutputName)->getString()
- };
-
- return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)};
- }
-
- throw Error("flake '%s' does not provide attribute %s",
- flakeRef, showAttrPaths(getActualAttrPaths()));
-}
-
-std::vector<InstallableValue::DerivationInfo> InstallableFlake::toDerivations()
-{
- std::vector<DerivationInfo> res;
- res.push_back(std::get<2>(toDerivation()));
- return res;
-}
-
-std::pair<Value *, Pos> InstallableFlake::toValue(EvalState & state)
-{
- auto lockedFlake = getLockedFlake();
-
- auto vOutputs = getFlakeOutputs(state, *lockedFlake);
-
- auto emptyArgs = state.allocBindings(0);
-
- for (auto & attrPath : getActualAttrPaths()) {
- try {
- auto [v, pos] = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs);
- state.forceValue(*v);
- return {v, pos};
- } catch (AttrPathNotFound & e) {
- }
- }
-
- throw Error("flake '%s' does not provide attribute %s",
- flakeRef, showAttrPaths(getActualAttrPaths()));
-}
-
-std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
-InstallableFlake::getCursors(EvalState & state)
-{
- auto evalCache = openEvalCache(state,
- std::make_shared<flake::LockedFlake>(lockFlake(state, flakeRef, lockFlags)));
-
- auto root = evalCache->getRoot();
-
- std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>> res;
-
- for (auto & attrPath : getActualAttrPaths()) {
- auto attr = root->findAlongAttrPath(parseAttrPath(state, attrPath));
- if (attr) res.push_back({attr, attrPath});
- }
-
- return res;
-}
-
-std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
-{
- if (!_lockedFlake) {
- _lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlags));
- _lockedFlake->flake.config.apply();
- // FIXME: send new config to the daemon.
- }
- return _lockedFlake;
-}
-
-FlakeRef InstallableFlake::nixpkgsFlakeRef() const
-{
- auto lockedFlake = getLockedFlake();
-
- if (auto nixpkgsInput = lockedFlake->lockFile.findInput({"nixpkgs"})) {
- if (auto lockedNode = std::dynamic_pointer_cast<const flake::LockedNode>(nixpkgsInput)) {
- debug("using nixpkgs flake '%s'", lockedNode->lockedRef);
- return std::move(lockedNode->lockedRef);
- }
- }
-
- return Installable::nixpkgsFlakeRef();
-}
-
-std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
- ref<Store> store, std::vector<std::string> ss)
-{
- std::vector<std::shared_ptr<Installable>> result;
-
- if (file || expr) {
- if (file && expr)
- throw UsageError("'--file' and '--expr' are exclusive");
-
- // FIXME: backward compatibility hack
- if (file) evalSettings.pureEval = false;
-
- auto state = getEvalState();
- auto vFile = state->allocValue();
-
- if (file)
- state->evalFile(lookupFileArg(*state, *file), *vFile);
- else {
- auto e = state->parseExprFromString(*expr, absPath("."));
- state->eval(e, *vFile);
- }
-
- for (auto & s : ss)
- result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s));
-
- } else {
-
- for (auto & s : ss) {
- std::exception_ptr ex;
-
- try {
- auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
- result.push_back(std::make_shared<InstallableFlake>(
- getEvalState(), std::move(flakeRef),
- fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment},
- getDefaultFlakeAttrPathPrefixes(), lockFlags));
- continue;
- } catch (...) {
- ex = std::current_exception();
- }
-
- if (s.find('/') != std::string::npos) {
- try {
- result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s)));
- continue;
- } catch (BadStorePath &) {
- } catch (...) {
- if (!ex)
- ex = std::current_exception();
- }
- }
-
- std::rethrow_exception(ex);
-
- /*
- throw Error(
- pathExists(s)
- ? "path '%s' is not a flake or a store path"
- : "don't know how to handle argument '%s'", s);
- */
- }
- }
-
- return result;
-}
-
-std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
- ref<Store> store, const std::string & installable)
-{
- auto installables = parseInstallables(store, {installable});
- assert(installables.size() == 1);
- return installables.front();
-}
-
-Buildables build(ref<Store> store, Realise mode,
- std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode)
-{
- if (mode == Realise::Nothing)
- settings.readOnlyMode = true;
-
- Buildables buildables;
-
- std::vector<StorePathWithOutputs> pathsToBuild;
-
- for (auto & i : installables) {
- for (auto & b : i->toBuildables()) {
- std::visit(overloaded {
- [&](BuildableOpaque bo) {
- pathsToBuild.push_back({bo.path});
- },
- [&](BuildableFromDrv bfd) {
- StringSet outputNames;
- for (auto & output : bfd.outputs)
- outputNames.insert(output.first);
- pathsToBuild.push_back({bfd.drvPath, outputNames});
- },
- }, b);
- buildables.push_back(std::move(b));
- }
- }
-
- if (mode == Realise::Nothing)
- printMissing(store, pathsToBuild, lvlError);
- else if (mode == Realise::Outputs)
- store->buildPaths(pathsToBuild, bMode);
-
- return buildables;
-}
-
-StorePathSet toStorePaths(ref<Store> store,
- Realise mode, OperateOn operateOn,
- std::vector<std::shared_ptr<Installable>> installables)
-{
- StorePathSet outPaths;
-
- if (operateOn == OperateOn::Output) {
- for (auto & b : build(store, mode, installables))
- std::visit(overloaded {
- [&](BuildableOpaque bo) {
- outPaths.insert(bo.path);
- },
- [&](BuildableFromDrv bfd) {
- for (auto & output : bfd.outputs) {
- if (!output.second)
- throw Error("Cannot operate on output of unbuilt CA drv");
- outPaths.insert(*output.second);
- }
- },
- }, b);
- } else {
- if (mode == Realise::Nothing)
- settings.readOnlyMode = true;
-
- for (auto & i : installables)
- for (auto & b : i->toBuildables())
- if (auto bfd = std::get_if<BuildableFromDrv>(&b))
- outPaths.insert(bfd->drvPath);
- }
-
- return outPaths;
-}
-
-StorePath toStorePath(ref<Store> store,
- Realise mode, OperateOn operateOn,
- std::shared_ptr<Installable> installable)
-{
- auto paths = toStorePaths(store, mode, operateOn, {installable});
-
- if (paths.size() != 1)
- throw Error("argument '%s' should evaluate to one store path", installable->what());
-
- return *paths.begin();
-}
-
-StorePathSet toDerivations(ref<Store> store,
- std::vector<std::shared_ptr<Installable>> installables, bool useDeriver)
-{
- StorePathSet drvPaths;
-
- for (auto & i : installables)
- for (auto & b : i->toBuildables())
- std::visit(overloaded {
- [&](BuildableOpaque bo) {
- if (!useDeriver)
- throw Error("argument '%s' did not evaluate to a derivation", i->what());
- auto derivers = store->queryValidDerivers(bo.path);
- if (derivers.empty())
- throw Error("'%s' does not have a known deriver", i->what());
- // FIXME: use all derivers?
- drvPaths.insert(*derivers.begin());
- },
- [&](BuildableFromDrv bfd) {
- drvPaths.insert(bfd.drvPath);
- },
- }, b);
-
- return drvPaths;
-}
-
-InstallablesCommand::InstallablesCommand()
-{
- expectArgs({
- .label = "installables",
- .handler = {&_installables},
- .completer = {[&](size_t, std::string_view prefix) {
- completeInstallable(prefix);
- }}
- });
-}
-
-void InstallablesCommand::prepare()
-{
- if (_installables.empty() && useDefaultInstallables())
- // FIXME: commands like "nix install" should not have a
- // default, probably.
- _installables.push_back(".");
- installables = parseInstallables(getStore(), _installables);
-}
-
-std::optional<FlakeRef> InstallablesCommand::getFlakeRefForCompletion()
-{
- if (_installables.empty()) {
- if (useDefaultInstallables())
- return parseFlakeRef(".", absPath("."));
- return {};
- }
- return parseFlakeRef(_installables.front(), absPath("."));
-}
-
-InstallableCommand::InstallableCommand()
-{
- expectArgs({
- .label = "installable",
- .optional = true,
- .handler = {&_installable},
- .completer = {[&](size_t, std::string_view prefix) {
- completeInstallable(prefix);
- }}
- });
-}
-
-void InstallableCommand::prepare()
-{
- installable = parseInstallable(getStore(), _installable);
-}
-
-}
diff --git a/src/nix/installables.hh b/src/nix/installables.hh
deleted file mode 100644
index f37b3f829..000000000
--- a/src/nix/installables.hh
+++ /dev/null
@@ -1,137 +0,0 @@
-#pragma once
-
-#include "util.hh"
-#include "path.hh"
-#include "eval.hh"
-#include "flake/flake.hh"
-
-#include <optional>
-
-#include <nlohmann/json_fwd.hpp>
-
-namespace nix {
-
-struct DrvInfo;
-struct SourceExprCommand;
-
-namespace eval_cache { class EvalCache; class AttrCursor; }
-
-struct BuildableOpaque {
- StorePath path;
- nlohmann::json toJSON(ref<Store> store) const;
-};
-
-struct BuildableFromDrv {
- StorePath drvPath;
- std::map<std::string, std::optional<StorePath>> outputs;
- nlohmann::json toJSON(ref<Store> store) const;
-};
-
-typedef std::variant<
- BuildableOpaque,
- BuildableFromDrv
-> Buildable;
-
-typedef std::vector<Buildable> Buildables;
-nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store);
-
-struct App
-{
- std::vector<StorePathWithOutputs> context;
- Path program;
- // FIXME: add args, sandbox settings, metadata, ...
-};
-
-struct Installable
-{
- virtual ~Installable() { }
-
- virtual std::string what() = 0;
-
- virtual Buildables toBuildables() = 0;
-
- Buildable toBuildable();
-
- App toApp(EvalState & state);
-
- virtual std::pair<Value *, Pos> toValue(EvalState & state)
- {
- throw Error("argument '%s' cannot be evaluated", what());
- }
-
- /* Return a value only if this installable is a store path or a
- symlink to it. */
- virtual std::optional<StorePath> getStorePath()
- {
- return {};
- }
-
- virtual std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
- getCursors(EvalState & state);
-
- std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>
- getCursor(EvalState & state);
-
- virtual FlakeRef nixpkgsFlakeRef() const
- {
- return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
- }
-};
-
-struct InstallableValue : Installable
-{
- ref<EvalState> state;
-
- InstallableValue(ref<EvalState> state) : state(state) {}
-
- struct DerivationInfo
- {
- StorePath drvPath;
- std::optional<StorePath> outPath;
- std::string outputName;
- };
-
- virtual std::vector<DerivationInfo> toDerivations() = 0;
-
- Buildables toBuildables() override;
-};
-
-struct InstallableFlake : InstallableValue
-{
- FlakeRef flakeRef;
- Strings attrPaths;
- Strings prefixes;
- const flake::LockFlags & lockFlags;
- mutable std::shared_ptr<flake::LockedFlake> _lockedFlake;
-
- InstallableFlake(ref<EvalState> state, FlakeRef && flakeRef,
- Strings && attrPaths, Strings && prefixes, const flake::LockFlags & lockFlags)
- : InstallableValue(state), flakeRef(flakeRef), attrPaths(attrPaths),
- prefixes(prefixes), lockFlags(lockFlags)
- { }
-
- std::string what() override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
-
- std::vector<std::string> getActualAttrPaths();
-
- Value * getFlakeOutputs(EvalState & state, const flake::LockedFlake & lockedFlake);
-
- std::tuple<std::string, FlakeRef, DerivationInfo> toDerivation();
-
- std::vector<DerivationInfo> toDerivations() override;
-
- std::pair<Value *, Pos> toValue(EvalState & state) override;
-
- std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
- getCursors(EvalState & state) override;
-
- std::shared_ptr<flake::LockedFlake> getLockedFlake() const;
-
- FlakeRef nixpkgsFlakeRef() const override;
-};
-
-ref<eval_cache::EvalCache> openEvalCache(
- EvalState & state,
- std::shared_ptr<flake::LockedFlake> lockedFlake);
-
-}
diff --git a/src/nix/legacy.cc b/src/nix/legacy.cc
deleted file mode 100644
index 6df09ee37..000000000
--- a/src/nix/legacy.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "legacy.hh"
-
-namespace nix {
-
-RegisterLegacyCommand::Commands * RegisterLegacyCommand::commands = 0;
-
-}
diff --git a/src/nix/legacy.hh b/src/nix/legacy.hh
deleted file mode 100644
index f503b0da3..000000000
--- a/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
-{
- typedef std::map<std::string, MainFunction> Commands;
- static Commands * commands;
-
- RegisterLegacyCommand(const std::string & name, MainFunction fun)
- {
- if (!commands) commands = new Commands;
- (*commands)[name] = fun;
- }
-};
-
-}
diff --git a/src/nix/local.mk b/src/nix/local.mk
index 23c08fc86..83b6dd08b 100644
--- a/src/nix/local.mk
+++ b/src/nix/local.mk
@@ -14,9 +14,9 @@ nix_SOURCES := \
$(wildcard src/nix-instantiate/*.cc) \
$(wildcard src/nix-store/*.cc) \
-nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr -I src/libmain
+nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr -I src/libmain -I src/libcmd
-nix_LIBS = libexpr libmain libfetchers libstore libutil
+nix_LIBS = libexpr libmain libfetchers libstore libutil libcmd
nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -llowdown
diff --git a/src/nix/markdown.cc b/src/nix/markdown.cc
deleted file mode 100644
index 40788a42f..000000000
--- a/src/nix/markdown.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "markdown.hh"
-#include "util.hh"
-#include "finally.hh"
-
-#include <sys/queue.h>
-extern "C" {
-#include <lowdown.h>
-}
-
-namespace nix {
-
-std::string renderMarkdownToTerminal(std::string_view markdown)
-{
- struct lowdown_opts opts {
- .type = LOWDOWN_TERM,
- .maxdepth = 20,
- .cols = std::min(getWindowSize().second, (unsigned short) 80),
- .hmargin = 0,
- .vmargin = 0,
- .feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
- .oflags = 0,
- };
-
- auto doc = lowdown_doc_new(&opts);
- if (!doc)
- throw Error("cannot allocate Markdown document");
- Finally freeDoc([&]() { lowdown_doc_free(doc); });
-
- size_t maxn = 0;
- auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size());
- if (!node)
- throw Error("cannot parse Markdown document");
- Finally freeNode([&]() { lowdown_node_free(node); });
-
- auto renderer = lowdown_term_new(&opts);
- if (!renderer)
- throw Error("cannot allocate Markdown renderer");
- Finally freeRenderer([&]() { lowdown_term_free(renderer); });
-
- auto buf = lowdown_buf_new(16384);
- if (!buf)
- throw Error("cannot allocate Markdown output buffer");
- Finally freeBuffer([&]() { lowdown_buf_free(buf); });
-
- lowdown_term_rndr(buf, nullptr, renderer, node);
-
- return std::string(buf->data, buf->size);
-}
-
-}
diff --git a/src/nix/markdown.hh b/src/nix/markdown.hh
deleted file mode 100644
index 78320fcf5..000000000
--- a/src/nix/markdown.hh
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "types.hh"
-
-namespace nix {
-
-std::string renderMarkdownToTerminal(std::string_view markdown);
-
-}