From c9210f7629e88d542558bfa6398d9ed107442f73 Mon Sep 17 00:00:00 2001 From: Gabriel Parreiras Date: Mon, 23 Mar 2026 22:21:57 +0000 Subject: [PATCH 1/3] Fix using lfs.url config --- src/libfetchers/git-lfs-fetch.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/git-lfs-fetch.cc b/src/libfetchers/git-lfs-fetch.cc index 0333570ea80..178adbe85af 100644 --- a/src/libfetchers/git-lfs-fetch.cc +++ b/src/libfetchers/git-lfs-fetch.cc @@ -137,7 +137,7 @@ typedef std::unique_ptr> GitCon static std::string getLfsEndpointUrl(git_repository * repo) { GitConfig config; - if (git_repository_config(Setter(config), repo)) { + if (!git_repository_config(Setter(config), repo)) { GitConfigEntry entry; if (!git_config_get_entry(Setter(entry), config.get(), "lfs.url")) { auto value = std::string(entry->value); From f70ca9fb44605fcf482c3f290ea673c8f9d7c009 Mon Sep 17 00:00:00 2001 From: Gabriel Parreiras Date: Mon, 23 Mar 2026 23:03:02 +0000 Subject: [PATCH 2/3] Strip /info/lfs from lfs.url --- src/libfetchers/git-lfs-fetch.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libfetchers/git-lfs-fetch.cc b/src/libfetchers/git-lfs-fetch.cc index 178adbe85af..35319e5bf41 100644 --- a/src/libfetchers/git-lfs-fetch.cc +++ b/src/libfetchers/git-lfs-fetch.cc @@ -142,6 +142,9 @@ static std::string getLfsEndpointUrl(git_repository * repo) if (!git_config_get_entry(Setter(entry), config.get(), "lfs.url")) { auto value = std::string(entry->value); if (!value.empty()) { + const std::string suffix = "/info/lfs"; + if (value.ends_with(suffix)) + value.resize(value.size() - suffix.size()); debug("Found explicit lfs.url value: %s", value); return value; } From 0a4f3ecc0cf7f0cb77d702168a0370d4d0912a0a Mon Sep 17 00:00:00 2001 From: Lily Foster Date: Tue, 24 Mar 2026 12:44:18 -0400 Subject: [PATCH 3/3] Fix LFS api endpoint discovery behavior to more closely match git-lfs Fixes: * Only add `/info/lfs` (and possibly `.git`) to remotes * Properly have `href` field from SSH server discovery be optional * Do not remove/re-add `/info/lfs` to `lfs.url` config and use it directly as LFS API endpoint --- src/libfetchers/git-lfs-fetch.cc | 40 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/libfetchers/git-lfs-fetch.cc b/src/libfetchers/git-lfs-fetch.cc index 35319e5bf41..f1ad99fc7c7 100644 --- a/src/libfetchers/git-lfs-fetch.cc +++ b/src/libfetchers/git-lfs-fetch.cc @@ -53,14 +53,6 @@ struct LfsApiInfo } // namespace -static std::string lfsEndpointUrl(const ParsedURL & url) -{ - auto endpoint = url.to_string(); - if (!endpoint.ends_with(".git")) - endpoint += ".git"; - return endpoint + "/info/lfs"; -} - static LfsApiInfo getLfsApi(const ParsedURL & url) { assert(url.authority.has_value()); @@ -95,7 +87,12 @@ static LfsApiInfo getLfsApi(const ParsedURL & url) if (authIt == headerIt->end()) throw Error("no Authorization in git-lfs-authenticate response"); - return {queryResp.at("href").get(), authIt->get()}; + auto href = url.to_string(); + auto hrefIt = queryResp.find("href"); + if (hrefIt != queryResp.end()) + href = hrefIt->get(); + + return {href, authIt->get()}; } else { std::ostringstream inputCredDescr; @@ -125,10 +122,10 @@ static LfsApiInfo getLfsApi(const ParsedURL & url) if (username.empty() || password.empty()) throw Error("git-credential-fill: no credentials returned (cmd: 'git credential fill' for protocol=%s, host=%s, path=%s)", url.scheme, url.authority->host, url.renderPath(true)); - return {lfsEndpointUrl(url), "Basic " + base64::encode(std::as_bytes(std::span{username + ":" + password}))}; + return {url.to_string(), "Basic " + base64::encode(std::as_bytes(std::span{username + ":" + password}))}; } - return {lfsEndpointUrl(url), std::nullopt}; + return {url.to_string(), std::nullopt}; } typedef std::unique_ptr> GitConfig; @@ -142,9 +139,6 @@ static std::string getLfsEndpointUrl(git_repository * repo) if (!git_config_get_entry(Setter(entry), config.get(), "lfs.url")) { auto value = std::string(entry->value); if (!value.empty()) { - const std::string suffix = "/info/lfs"; - if (value.ends_with(suffix)) - value.resize(value.size() - suffix.size()); debug("Found explicit lfs.url value: %s", value); return value; } @@ -152,14 +146,18 @@ static std::string getLfsEndpointUrl(git_repository * repo) } git_remote * remote = nullptr; - if (git_remote_lookup(&remote, repo, "origin")) - return ""; - - const char * url_c_str = git_remote_url(remote); - if (!url_c_str) - return ""; + if (!git_remote_lookup(&remote, repo, "origin")) { + const char * url_c_str = git_remote_url(remote); + if (url_c_str) { + auto remote = std::string(url_c_str); + if (remote.ends_with(".git")) + return remote + "/info/lfs"; + else + return remote + ".git/info/lfs"; + } + } - return std::string(url_c_str); + return ""; } static std::optional parseLfsPointer(std::string_view content, std::string_view filename)