mirror of
https://github.com/NixOS/nix.git
synced 2025-11-24 11:19:35 +01:00
parent
5fcf7f04a9
commit
401b09b7fe
4 changed files with 150 additions and 138 deletions
138
src/nix/flake.cc
138
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<nix::Store> 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<Path> files;
|
||||
|
||||
std::function<void(const Path & from, const Path & to)> 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<CmdFlakeMetadata>(); }},
|
||||
{"info", []() { return make_ref<CmdFlakeInfo>(); }},
|
||||
{"check", []() { return make_ref<CmdFlakeCheck>(); }},
|
||||
{"init", []() { return make_ref<CmdFlakeInit>(); }},
|
||||
{"new", []() { return make_ref<CmdFlakeNew>(); }},
|
||||
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
|
||||
{"archive", []() { return make_ref<CmdFlakeArchive>(); }},
|
||||
{"show", []() { return make_ref<CmdFlakeShow>(); }},
|
||||
|
|
|
|||
150
src/nix/new.cc
Normal file
150
src/nix/new.cc
Normal file
|
|
@ -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<nix::Store> 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<Path> files;
|
||||
|
||||
std::function<void(const Path & from, const Path & to)> 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<CmdFlakeInit>("init");
|
||||
static auto r1 = registerCommand<CmdFlakeNew>("new");
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue