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
|
struct CmdFlakeClone : FlakeCommand
|
||||||
{
|
{
|
||||||
Path destDir;
|
Path destDir;
|
||||||
|
|
@ -1125,8 +989,6 @@ struct CmdFlake : NixMultiCommand
|
||||||
{"metadata", []() { return make_ref<CmdFlakeMetadata>(); }},
|
{"metadata", []() { return make_ref<CmdFlakeMetadata>(); }},
|
||||||
{"info", []() { return make_ref<CmdFlakeInfo>(); }},
|
{"info", []() { return make_ref<CmdFlakeInfo>(); }},
|
||||||
{"check", []() { return make_ref<CmdFlakeCheck>(); }},
|
{"check", []() { return make_ref<CmdFlakeCheck>(); }},
|
||||||
{"init", []() { return make_ref<CmdFlakeInit>(); }},
|
|
||||||
{"new", []() { return make_ref<CmdFlakeNew>(); }},
|
|
||||||
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
|
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
|
||||||
{"archive", []() { return make_ref<CmdFlakeArchive>(); }},
|
{"archive", []() { return make_ref<CmdFlakeArchive>(); }},
|
||||||
{"show", []() { return make_ref<CmdFlakeShow>(); }},
|
{"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