From 401b09b7fe031206ad1715543cd087d52fd82362 Mon Sep 17 00:00:00 2001 From: regnat Date: Tue, 6 Jul 2021 15:28:50 +0200 Subject: [PATCH] Move `nix flake {new,init}` at toplevel Fix #4502 --- src/nix/flake.cc | 138 -------------------------- src/nix/{flake-init.md => init.md} | 0 src/nix/new.cc | 150 +++++++++++++++++++++++++++++ src/nix/{flake-new.md => new.md} | 0 4 files changed, 150 insertions(+), 138 deletions(-) rename src/nix/{flake-init.md => init.md} (100%) create mode 100644 src/nix/new.cc rename src/nix/{flake-new.md => new.md} (100%) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 97f4d911c..5e958a527 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -638,142 +638,6 @@ struct CmdFlakeCheck : FlakeCommand } }; -struct CmdFlakeInitCommon : virtual Args, EvalCommand -{ - std::string templateUrl = "templates"; - Path destDir; - - const Strings attrsPathPrefixes{"templates."}; - const LockFlags lockFlags{ .writeLockFile = false }; - - CmdFlakeInitCommon() - { - addFlag({ - .longName = "template", - .shortName = 't', - .description = "The template to use.", - .labels = {"template"}, - .handler = {&templateUrl}, - .completer = {[&](size_t, std::string_view prefix) { - completeFlakeRefWithFragment( - getEvalState(), - lockFlags, - attrsPathPrefixes, - {"defaultTemplate"}, - prefix); - }} - }); - } - - void run(nix::ref store) override - { - auto flakeDir = absPath(destDir); - - auto evalState = getEvalState(); - - auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath(".")); - - auto installable = InstallableFlake(nullptr, - evalState, std::move(templateFlakeRef), - Strings{templateName == "" ? "defaultTemplate" : templateName}, - Strings(attrsPathPrefixes), lockFlags); - - auto [cursor, attrPath] = installable.getCursor(*evalState); - - auto templateDir = cursor->getAttr("path")->getString(); - - assert(store->isInStore(templateDir)); - - std::vector files; - - std::function copyDir; - copyDir = [&](const Path & from, const Path & to) - { - createDirs(to); - - for (auto & entry : readDirectory(from)) { - auto from2 = from + "/" + entry.name; - auto to2 = to + "/" + entry.name; - auto st = lstat(from2); - if (S_ISDIR(st.st_mode)) - copyDir(from2, to2); - else if (S_ISREG(st.st_mode)) { - auto contents = readFile(from2); - if (pathExists(to2)) { - auto contents2 = readFile(to2); - if (contents != contents2) - throw Error("refusing to overwrite existing file '%s'", to2); - } else - writeFile(to2, contents); - } - else if (S_ISLNK(st.st_mode)) { - auto target = readLink(from2); - if (pathExists(to2)) { - if (readLink(to2) != target) - throw Error("refusing to overwrite existing symlink '%s'", to2); - } else - createSymlink(target, to2); - } - else - throw Error("file '%s' has unsupported type", from2); - files.push_back(to2); - } - }; - - copyDir(templateDir, flakeDir); - - if (pathExists(flakeDir + "/.git")) { - Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" }; - for (auto & s : files) args.push_back(s); - runProgram("git", true, args); - } - } -}; - -struct CmdFlakeInit : CmdFlakeInitCommon -{ - std::string description() override - { - return "create a flake in the current directory from a template"; - } - - std::string doc() override - { - return - #include "flake-init.md" - ; - } - - CmdFlakeInit() - { - destDir = "."; - } -}; - -struct CmdFlakeNew : CmdFlakeInitCommon -{ - std::string description() override - { - return "create a flake in the specified directory from a template"; - } - - std::string doc() override - { - return - #include "flake-new.md" - ; - } - - CmdFlakeNew() - { - expectArgs({ - .label = "dest-dir", - .handler = {&destDir}, - .completer = completePath - }); - } -}; - struct CmdFlakeClone : FlakeCommand { Path destDir; @@ -1125,8 +989,6 @@ struct CmdFlake : NixMultiCommand {"metadata", []() { return make_ref(); }}, {"info", []() { return make_ref(); }}, {"check", []() { return make_ref(); }}, - {"init", []() { return make_ref(); }}, - {"new", []() { return make_ref(); }}, {"clone", []() { return make_ref(); }}, {"archive", []() { return make_ref(); }}, {"show", []() { return make_ref(); }}, diff --git a/src/nix/flake-init.md b/src/nix/init.md similarity index 100% rename from src/nix/flake-init.md rename to src/nix/init.md diff --git a/src/nix/new.cc b/src/nix/new.cc new file mode 100644 index 000000000..4b9df4d6f --- /dev/null +++ b/src/nix/new.cc @@ -0,0 +1,150 @@ +#include "command.hh" +#include "common-args.hh" +#include "shared.hh" +#include "store-api.hh" +#include "local-fs-store.hh" +#include "fs-accessor.hh" +#include "eval-cache.hh" + +using namespace nix; +using namespace nix::flake; + +struct CmdFlakeInitCommon : virtual Args, EvalCommand +{ + std::string templateUrl = "templates"; + Path destDir; + + const Strings attrsPathPrefixes{"templates."}; + const LockFlags lockFlags{ .writeLockFile = false }; + + CmdFlakeInitCommon() + { + addFlag({ + .longName = "template", + .shortName = 't', + .description = "The template to use.", + .labels = {"template"}, + .handler = {&templateUrl}, + .completer = {[&](size_t, std::string_view prefix) { + completeFlakeRefWithFragment( + getEvalState(), + lockFlags, + attrsPathPrefixes, + {"defaultTemplate"}, + prefix); + }} + }); + } + + void run(nix::ref store) override + { + auto flakeDir = absPath(destDir); + + auto evalState = getEvalState(); + + auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath(".")); + + auto installable = InstallableFlake(nullptr, + evalState, std::move(templateFlakeRef), + Strings{templateName == "" ? "defaultTemplate" : templateName}, + Strings(attrsPathPrefixes), lockFlags); + + auto [cursor, attrPath] = installable.getCursor(*evalState); + + auto templateDir = cursor->getAttr("path")->getString(); + + assert(store->isInStore(templateDir)); + + std::vector files; + + std::function copyDir; + copyDir = [&](const Path & from, const Path & to) + { + createDirs(to); + + for (auto & entry : readDirectory(from)) { + auto from2 = from + "/" + entry.name; + auto to2 = to + "/" + entry.name; + auto st = lstat(from2); + if (S_ISDIR(st.st_mode)) + copyDir(from2, to2); + else if (S_ISREG(st.st_mode)) { + auto contents = readFile(from2); + if (pathExists(to2)) { + auto contents2 = readFile(to2); + if (contents != contents2) + throw Error("refusing to overwrite existing file '%s'", to2); + } else + writeFile(to2, contents); + } + else if (S_ISLNK(st.st_mode)) { + auto target = readLink(from2); + if (pathExists(to2)) { + if (readLink(to2) != target) + throw Error("refusing to overwrite existing symlink '%s'", to2); + } else + createSymlink(target, to2); + } + else + throw Error("file '%s' has unsupported type", from2); + files.push_back(to2); + } + }; + + copyDir(templateDir, flakeDir); + + if (pathExists(flakeDir + "/.git")) { + Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" }; + for (auto & s : files) args.push_back(s); + runProgram("git", true, args); + } + } +}; + +struct CmdFlakeInit : CmdFlakeInitCommon +{ + std::string description() override + { + return "create a flake in the current directory from a template"; + } + + std::string doc() override + { + return + #include "init.md" + ; + } + + CmdFlakeInit() + { + destDir = "."; + } +}; + +struct CmdFlakeNew : CmdFlakeInitCommon +{ + std::string description() override + { + return "create a flake in the specified directory from a template"; + } + + std::string doc() override + { + return + #include "new.md" + ; + } + + CmdFlakeNew() + { + expectArgs({ + .label = "dest-dir", + .handler = {&destDir}, + .completer = completePath + }); + } +}; + +static auto r0 = registerCommand("init"); +static auto r1 = registerCommand("new"); + diff --git a/src/nix/flake-new.md b/src/nix/new.md similarity index 100% rename from src/nix/flake-new.md rename to src/nix/new.md