Fix relative submodule handling

Tested on

  nix flake prefetch 'git+https://github.com/blender/blender.git?rev=4ed8a360e956daf2591add4d3c9ec0719e2628fe&submodules=1'
This commit is contained in:
Eelco Dolstra 2023-11-14 16:00:21 +01:00
parent 6ec6b8aa36
commit 2964a9f562
5 changed files with 27 additions and 4 deletions

View file

@ -308,13 +308,21 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
std::vector<std::tuple<Submodule, Hash>> getSubmodules(const Hash & rev) override; std::vector<std::tuple<Submodule, Hash>> getSubmodules(const Hash & rev) override;
std::string resolveSubmoduleUrl(const std::string & url) override std::string resolveSubmoduleUrl(
const std::string & url,
const std::string & base) override
{ {
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
if (git_submodule_resolve_url(&buf, *this, url.c_str())) if (git_submodule_resolve_url(&buf, *this, url.c_str()))
throw Error("resolving Git submodule URL '%s'", url); throw Error("resolving Git submodule URL '%s'", url);
Finally cleanup = [&]() { git_buf_dispose(&buf); }; Finally cleanup = [&]() { git_buf_dispose(&buf); };
return buf.ptr;
std::string res(buf.ptr);
if (!hasPrefix(res, "/") && res.find("://") == res.npos)
res = parseURL(base + "/" + res).canonicalise().to_string();
return res;
} }
bool hasObject(const Hash & oid_) override bool hasObject(const Hash & oid_) override

View file

@ -59,7 +59,9 @@ struct GitRepo
*/ */
virtual std::vector<std::tuple<Submodule, Hash>> getSubmodules(const Hash & rev) = 0; virtual std::vector<std::tuple<Submodule, Hash>> getSubmodules(const Hash & rev) = 0;
virtual std::string resolveSubmoduleUrl(const std::string & url) = 0; virtual std::string resolveSubmoduleUrl(
const std::string & url,
const std::string & base) = 0;
struct TarballInfo struct TarballInfo
{ {

View file

@ -594,7 +594,7 @@ struct GitInputScheme : InputScheme
std::map<CanonPath, nix::ref<InputAccessor>> mounts; std::map<CanonPath, nix::ref<InputAccessor>> mounts;
for (auto & [submodule, submoduleRev] : repo->getSubmodules(rev)) { for (auto & [submodule, submoduleRev] : repo->getSubmodules(rev)) {
auto resolved = repo->resolveSubmoduleUrl(submodule.url); auto resolved = repo->resolveSubmoduleUrl(submodule.url, repoInfo.url);
debug("Git submodule %s: %s %s %s -> %s", debug("Git submodule %s: %s %s %s -> %s",
submodule.path, submodule.url, submodule.branch, submoduleRev.gitRev(), resolved); submodule.path, submodule.url, submodule.branch, submoduleRev.gitRev(), resolved);
fetchers::Attrs attrs; fetchers::Attrs attrs;

View file

@ -2,6 +2,7 @@
#include "url-parts.hh" #include "url-parts.hh"
#include "util.hh" #include "util.hh"
#include "split.hh" #include "split.hh"
#include "canon-path.hh"
namespace nix { namespace nix {
@ -141,6 +142,13 @@ bool ParsedURL::operator ==(const ParsedURL & other) const
&& fragment == other.fragment; && fragment == other.fragment;
} }
ParsedURL ParsedURL::canonicalise()
{
ParsedURL res(*this);
res.path = CanonPath(res.path).abs();
return res;
}
/** /**
* Parse a URL scheme of the form '(applicationScheme\+)?transportScheme' * Parse a URL scheme of the form '(applicationScheme\+)?transportScheme'
* into a tuple '(applicationScheme, transportScheme)' * into a tuple '(applicationScheme, transportScheme)'

View file

@ -19,6 +19,11 @@ struct ParsedURL
std::string to_string() const; std::string to_string() const;
bool operator ==(const ParsedURL & other) const; bool operator ==(const ParsedURL & other) const;
/**
* Remove `.` and `..` path elements.
*/
ParsedURL canonicalise();
}; };
MakeError(BadURL, Error); MakeError(BadURL, Error);