From 452ffe5464f20ac44a01c536349895d138150a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= <7226587+thufschmitt@users.noreply.github.com> Date: Wed, 18 May 2022 16:46:13 +0200 Subject: [PATCH 1/7] Hint at the source file on conflict in `flake new` Add a pointer to the source file (from the template) when `nix flake new` (or `init`) encounters an already existing file Fix #6542 --- src/nix/flake.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 1938ce4e6..a1edb5dbf 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -758,7 +758,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(to2)) { auto contents2 = readFile(to2); if (contents != contents2) - throw Error("refusing to overwrite existing file '%s'", to2); + throw Error("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); } else writeFile(to2, contents); } @@ -766,7 +766,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto target = readLink(from2); if (pathExists(to2)) { if (readLink(to2) != target) - throw Error("refusing to overwrite existing symlink '%s'", to2); + throw Error("refusing to overwrite existing symlink '%s' - please merge manually with '%s'", to2, from2); } else createSymlink(target, to2); } From 3a85fd077cf8a404e0b7c727e47b8fcee85280a5 Mon Sep 17 00:00:00 2001 From: "Manu [tennox]" <2084639+tennox@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:26:32 +0100 Subject: [PATCH 2/7] #6542 Apply flake templates partially on conflicts Will still exit with non-zero exit code and clearly prompt which files to merge: ``` nixx flake init -t github:numtide/devshell wrote: /home/manu/dev/stuff/gopassbridge/.envrc refusing to overwrite existing file '/home/manu/dev/stuff/gopassbridge/.gitignore' -> merge manually with '/nix/store/ksmwhyghjwb4d9dw6hcpbvng1msdvjim-source/template/.gitignore' wrote: /home/manu/dev/stuff/gopassbridge/devshell.toml wrote: /home/manu/dev/stuff/gopassbridge/flake.nix error: Encountered 1 conflicts - please merge manually ``` --- src/nix/flake.cc | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index a1edb5dbf..24255c247 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -740,7 +740,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand "If you've set '%s' to a string, try using a path instead.", templateDir, templateDirAttr->getAttrPathStr()); - std::vector files; + std::vector changedFiles; + std::vector conflictedFiles; + auto success = false; std::function copyDir; copyDir = [&](const Path & from, const Path & to) @@ -757,22 +759,33 @@ 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' - please merge manually with '%s'", to2, from2); + if (contents != contents2) { + printError("refusing to overwrite existing file '%s'\n-> merge manually with '%s'", to2, from2); + success = false; + 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' - please merge manually with '%s'", to2, from2); + if (readLink(to2) != target) { + printError("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); + success = false; + conflictedFiles.push_back(to2); + } else { + notice("skipping identical file: %s", from2); + } } 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); } }; @@ -781,7 +794,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (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 +802,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand notice("\n"); notice(renderMarkdownToTerminal(welcomeText->getString())); } + + if (!success) + throw Error("Encountered %d conflicts - please merge manually", conflictedFiles.size()); } }; From 117baee1b78f662291e980075668720179c1c455 Mon Sep 17 00:00:00 2001 From: Manuel <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 18:00:34 +0100 Subject: [PATCH 3/7] Update src/nix/flake.cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/NixOS/nix/pull/6699#discussion_r904096906 Co-authored-by: Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> --- src/nix/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 24255c247..fdb373f24 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -760,7 +760,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(to2)) { auto contents2 = readFile(to2); if (contents != contents2) { - printError("refusing to overwrite existing file '%s'\n-> merge manually with '%s'", to2, from2); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); success = false; conflictedFiles.push_back(to2); } else { From 58cbbdc5e78b952bfaf8ff36e9c94ccbd08469b7 Mon Sep 17 00:00:00 2001 From: Manuel <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 18:00:57 +0100 Subject: [PATCH 4/7] Update src/nix/flake.cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/NixOS/nix/pull/6699#discussion_r904097147 Co-authored-by: Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> --- src/nix/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index fdb373f24..10bbcaf43 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -774,7 +774,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto target = readLink(from2); if (pathExists(to2)) { if (readLink(to2) != target) { - printError("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); success = false; conflictedFiles.push_back(to2); } else { From 4374e3ec67a6c3ed8342908a5229437424926bf5 Mon Sep 17 00:00:00 2001 From: "Manu [tennox]" <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 18:12:30 +0100 Subject: [PATCH 5/7] #6699 flake init: Apply suggestions of @thufschmitt --- src/nix/flake.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 10bbcaf43..1140548e7 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -742,7 +742,6 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand std::vector changedFiles; std::vector conflictedFiles; - auto success = false; std::function copyDir; copyDir = [&](const Path & from, const Path & to) @@ -761,7 +760,6 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto contents2 = readFile(to2); if (contents != contents2) { printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); - success = false; conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -775,7 +773,6 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(to2)) { if (readLink(to2) != target) { printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); - success = false; conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -803,8 +800,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand notice(renderMarkdownToTerminal(welcomeText->getString())); } - if (!success) - throw Error("Encountered %d conflicts - please merge manually", conflictedFiles.size()); + if (!conflictedFiles.empty()) + throw Error("Encountered %d conflicts - see above", conflictedFiles.size()); } }; From ae4c9ef8e284eabf3624d9e9ad0f0b432e06da41 Mon Sep 17 00:00:00 2001 From: "Manu [tennox]" <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 21:29:45 +0100 Subject: [PATCH 6/7] #6699 flake init: fix trying to add unchanged file After skipping because of being of identical content it tried to git add it. --- src/nix/flake.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 1140548e7..895a7de76 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -777,6 +777,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } else { notice("skipping identical file: %s", from2); } + continue; } else createSymlink(target, to2); } @@ -789,7 +790,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand 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 : changedFiles) args.push_back(s); runProgram("git", true, args); From 83f96e61a43b77677e14cdf415f1a30d37b17f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= Date: Wed, 29 Jun 2022 16:28:46 +0200 Subject: [PATCH 7/7] Add some test for `nix flake init` with conflicts --- tests/flakes.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) 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 < $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