-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fetchSubmodules to builtins.fetchGit #3166
Conversation
0fc3a9b
to
ead3356
Compare
I've added documentation and a test. |
@edolstra WDYT? this would be super helpful! |
ead3356
to
45b1f1d
Compare
@edolstra It would be really nice to find a solution here to get submodule support working with |
Here is a patch with my proposed changes: diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk
index 26b9f14ba..e8c019365 100644
--- a/src/libexpr/local.mk
+++ b/src/libexpr/local.mk
@@ -8,7 +8,7 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexe
libexpr_LIBS = libutil libstore libnixrust
-libexpr_LDFLAGS =
+libexpr_LDFLAGS = -lstdc++fs
ifneq ($(OS), FreeBSD)
libexpr_LDFLAGS += -ldl
endif
diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc
index b08e48404..c58d28bbc 100644
--- a/src/libexpr/primops/fetchGit.cc
+++ b/src/libexpr/primops/fetchGit.cc
@@ -6,6 +6,7 @@
#include "hash.hh"
#include "tarfile.hh"
+#include <filesystem>
#include <sys/time.h>
#include <regex>
@@ -182,9 +183,13 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
runProgram("git", true, { "-C", tmpDir, "checkout", "--quiet", "FETCH_HEAD" });
runProgram("git", true, { "-C", tmpDir, "remote", "add", "origin", uri });
- runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init" });
+ runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" });
- deletePath(tmpDir + "/.git");
+ for (const auto& p : std::filesystem::recursive_directory_iterator(tmpDir)) {
+ if (p.path().filename() == ".git") {
+ std::filesystem::remove_all(p.path());
+ }
+ }
gitInfo.submodules = true;
} else {
diff --git a/tests/fetchGitSubmodules.sh b/tests/fetchGitSubmodules.sh
index c821d2caa..987bfd69e 100644
--- a/tests/fetchGitSubmodules.sh
+++ b/tests/fetchGitSubmodules.sh
@@ -47,4 +47,5 @@ pathWithSubmodules=$(nix eval --raw "(builtins.fetchGit { url = file://$rootRepo
[[ ! -e $pathWithoutSubmodules/sub/content ]]
[[ -e $pathWithSubmodules/sub/content ]]
-
+# No .git directory or submodule reference files must be left
+test "$(find "$pathWithSubmodules" -name .git)" = "" I used std::filesystem for removing the .git paths. Nix already depends on C++17, but apparently one needs -lstdc++fs to get this library. The internet says clang needs a different flag, but the current flag worked in my testing ( |
By the way, I had a chat with @edolstra . He's refactoring the fetcher, which will need to land before this. Sharing this to clarify, and ideally to save people some time in case some of the changes don't apply anymore! |
@bjornfor Thanks for the review and fixes! As @nmattia pointed out this will likely conflict with upcoming changes, so I'd rather wait before spending more time here. Or do you think there is a chance of sneaking this in before the refactoring? @nmattia @edolstra It would be nice if there is some issue to watch regarding the fetcher changes. |
I'm eagerly awaiting a status update here :-) |
I did some real life testing with this patch and found two issues.
Allowing @edolstra: Are you refactoring the fetcher(s)? I would really like for nix to have git submodule support and can probably spend a bit more time on this if there is interest. But no sign of interest kills my motivation. |
Yes, the new fetcher infrastructure is in the flakes branch: https://github.com/NixOS/nix/tree/flakes/src/libstore/fetchers. It replaces |
@edolstra @tfc @bjornfor I was wondering how to implement submodule support while keeping all the nice caching in place. I'm thinking about something along the lines of:
This would keep the normal caching of git repositories in place and submodules wouldn't be treated any differently from normal git checkouts. The downside is that the implementation is somewhat complex compared to just using To limit the complexity in Nix itself, most of this could be implemented as Nix expression, given that a builtin is available that returns a list of submodules and their properties. Opinions? |
I think we should ignore the caching issue for now. I still want to add a generic caching mechanism to the fetcher infrastructure that generalizes the Git-specific caching (in |
@blitz @edolstra: I'm confused about what the next action is. Ok, so flakes branch has new fetcher infrastructure, and this is where the future git fetcher with submodule support will live. But flakes is an experimental branch and it would be nice to have submodules support in standard Nix. (I don't know how long until flakes get stabilized and land in master.) So, if this PR is refreshed (fixing the outstanding issues as commented in this thread), would it be merged? |
@bjornfor I'll post an updated version soon. If I should rebuild this on top of flakes, this would be good to know. |
@bjornfor Yes, I'll take care of porting it to the new fetcher infrastructure. |
45b1f1d
to
020066c
Compare
I've incorporated all fixes. I just have to investigate the test failures. |
@edolstra @bjornfor @nmattia @tfc I'd appreciate a second look here. I think I have added tests for all issues that were pointed out and these tests are passing now. Two tests are failing ( |
@blitz: Did you build it? I'm getting this error:
In my patch I added |
My understanding was that
|
Some platforms seem to still require linking with stdc++fs to enable STL std::filesystem support.
…ue with submodules
Before this change it would be false for all evaluations but the first. Now it follows the input argument (as it should).
The .link file is used as a lock, so I think we should put the "submodule" attribute in there since turning on submodules creates a new .link file path.
Major bugfix for the submodules = true code path. TODO: Add tests.
Due to fetchGit not checking if rev is an ancestor of ref (there is even a FIXME comment about it in the code), the cache repo might not have the ref even though it has the rev. This doesn't matter when submodule = false, but the submodule = true code blows up because it tries to fetch the (missing) ref from the cache repo. Fix this in the simplest way possible: fetch all refs from the local cache repo when submodules = true. TODO: Add tests.
Using std::filesystem means also having to link with -lstdc++fs on some platforms and it's hard to discover for what platforms this is needed. As all the functionality is already implemented as utilities, use those instead.
514a025
to
40c023e
Compare
Merged, thanks! |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/why-doesnt-fetchfromgithub-support-submodules-with-private/6600/6 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/nix-flakes-and-submodules/7904/2 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
This pull request adds the ability to fetch submodules with
builtins.fetchGit
. Use it like:builtins.fetchGit { fetchSubmodules = true; ... }
There are some downsides to this feature:
These could be fixed, but require far more code and would require re-implementing some of the submodule cloning feature. This PR does not change any of the
fetchGit
behavior when submodules are not used (the default), so only people using this feature are paying these costs.Other missing things:
Note: This is my first contribution to Nix, so please expect stupid mistakes. :)
Fixes #2151
@edolstra @tfc