aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThéophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com>2022-06-29 18:21:07 +0200
committerGitHub <noreply@github.com>2022-06-29 18:21:07 +0200
commitb7eb4ac1692e289912f3988c0e28bb2c778a4f7a (patch)
treecbceab8b9c8af98f9793c761a3dfaada4800edbf
parent4c8210095e7ed8de2eb4789b0ac6f9b4a39e394e (diff)
parent83f96e61a43b77677e14cdf415f1a30d37b17f18 (diff)
Merge pull request #6699 from tennox/better-flake-new-error-message
flakes: apply templates partially on conflicts
-rw-r--r--src/nix/flake.cc30
-rw-r--r--tests/flakes.sh16
2 files changed, 37 insertions, 9 deletions
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 8370b8dcf..c66b24e5c 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -740,7 +740,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
"If you've set '%s' to a string, try using a path instead.",
templateDir, templateDirAttr->getAttrPathStr());
- std::vector<Path> files;
+ std::vector<Path> changedFiles;
+ std::vector<Path> conflictedFiles;
std::function<void(const Path & from, const Path & to)> copyDir;
copyDir = [&](const Path & from, const Path & to)
@@ -757,31 +758,41 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
auto contents = readFile(from2);
if (pathExists(to2)) {
auto contents2 = readFile(to2);
- if (contents != contents2)
- throw Error("refusing to overwrite existing file '%s'", to2);
+ if (contents != contents2) {
+ printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2);
+ conflictedFiles.push_back(to2);
+ } else {
+ notice("skipping identical file: %s", from2);
+ }
+ continue;
} 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);
+ if (readLink(to2) != target) {
+ printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2);
+ conflictedFiles.push_back(to2);
+ } else {
+ notice("skipping identical file: %s", from2);
+ }
+ continue;
} else
createSymlink(target, to2);
}
else
throw Error("file '%s' has unsupported type", from2);
- files.push_back(to2);
+ changedFiles.push_back(to2);
notice("wrote: %s", to2);
}
};
copyDir(templateDir, flakeDir);
- if (pathExists(flakeDir + "/.git")) {
+ if (!changedFiles.empty() && pathExists(flakeDir + "/.git")) {
Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" };
- for (auto & s : files) args.push_back(s);
+ for (auto & s : changedFiles) args.push_back(s);
runProgram("git", true, args);
}
auto welcomeText = cursor->maybeGetAttr("welcomeText");
@@ -789,6 +800,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
notice("\n");
notice(renderMarkdownToTerminal(welcomeText->getString()));
}
+
+ if (!conflictedFiles.empty())
+ throw Error("Encountered %d conflicts - see above", conflictedFiles.size());
}
};
diff --git a/tests/flakes.sh b/tests/flakes.sh
index 36bffcf3b..35cf4d8e7 100644
--- a/tests/flakes.sh
+++ b/tests/flakes.sh
@@ -408,8 +408,10 @@ cat > $templatesDir/trivial/flake.nix <<EOF
};
}
EOF
+echo a > $templatesDir/trivial/a
+echo b > $templatesDir/trivial/b
-git -C $templatesDir add flake.nix trivial/flake.nix
+git -C $templatesDir add flake.nix trivial/
git -C $templatesDir commit -m 'Initial'
nix flake check templates
@@ -424,6 +426,18 @@ nix flake show $flake7Dir
nix flake show $flake7Dir --json | jq
git -C $flake7Dir commit -a -m 'Initial'
+# Test 'nix flake init' with benign conflicts
+rm -rf $flake7Dir && mkdir $flake7Dir && git -C $flake7Dir init
+echo a > $flake7Dir/a
+(cd $flake7Dir && nix flake init) # check idempotence
+
+# Test 'nix flake init' with conflicts
+rm -rf $flake7Dir && mkdir $flake7Dir && git -C $flake7Dir init
+echo b > $flake7Dir/a
+pushd $flake7Dir
+(! nix flake init) |& grep "refusing to overwrite existing file '$flake7Dir/a'"
+popd
+
# Test 'nix flake new'.
rm -rf $flake6Dir
nix flake new -t templates#trivial $flake6Dir