Add support for multiple sources in fetchGit #200

Open
opened 2025-10-13 17:00:45 +02:00 by rarias · 0 comments
Owner

When any of the git servers that are used to fetch sources is down, it causes an evaluation failure that prevents fetching the source. This could be solved by specifying multiple sources from where to fetch the git repository, but builtin.fetchGit only accepts one.

We could make a wrapper around it and try several urls until one works, but the error that fetchGit throws cannot be captured by tryEval. It seems this restriction may be done to prevent errors being through when the evaluation order is not fixed.

However, for this particular case, we don't care about that. The following patch makes tryEval catch any error, including those thrown by builtins.fetchGit.

From 4e9c59ec08484b71d662fe088fb7db9327241d8f Mon Sep 17 00:00:00 2001
From: Rodrigo Arias Mallo <rodarima@gmail.com>
Date: Mon, 13 Oct 2025 16:05:30 +0200
Subject: [PATCH] Catch all types of Errors in tryEval

Allows using tryEval to try fetching multiple Git repositories with
builtin.fetchGit.
---
 src/libexpr/primops.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 36a67a39d..4f6014f07 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -821,7 +821,7 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
         state.forceValue(*args[0], pos);
         attrs.insert(state.sValue, args[0]);
         attrs.alloc("success").mkBool(true);
-    } catch (AssertionError & e) {
+    } catch (Error & e) {
         attrs.alloc(state.sValue).mkBool(false);
         attrs.alloc("success").mkBool(false);
     }
--
2.51.0

And this is the difference:

% result/bin/nix eval --expr 'builtins.tryEval (builtins.fetchGit {})'
{ success = false; value = false; }

% nix eval --expr 'builtins.tryEval (builtins.fetchGit {})'
error:
       … while calling the 'tryEval' builtin
         at «string»:1:1:
            1| builtins.tryEval (builtins.fetchGit {})
             | ^

       … while calling the 'fetchGit' builtin
         at «string»:1:19:
            1| builtins.tryEval (builtins.fetchGit {})
             |                   ^

       error: input attribute 'url' is missing

We may want to move this to its own builtin (maybe builtins.catchAll?) so that we don't cause any difference in the evaluation of code that already uses tryEval. We can also use builtins ? catchAll to detect the presence of the builtin, and if not present fall back to the previous usage.

On top of this builtin we can implement a robust fetchGit that accepts multiple sources.

When any of the git servers that are used to fetch sources is down, it causes an evaluation failure that prevents fetching the source. This could be solved by specifying multiple sources from where to fetch the git repository, but `builtin.fetchGit` only accepts one. We could make a wrapper around it and try several urls until one works, but the error that fetchGit throws cannot be captured by tryEval. It seems this restriction may be done to prevent errors being through when the evaluation order is not fixed. However, for this particular case, we don't care about that. The following patch makes tryEval catch *any* error, including those thrown by `builtins.fetchGit`. ```patch From 4e9c59ec08484b71d662fe088fb7db9327241d8f Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo <rodarima@gmail.com> Date: Mon, 13 Oct 2025 16:05:30 +0200 Subject: [PATCH] Catch all types of Errors in tryEval Allows using tryEval to try fetching multiple Git repositories with builtin.fetchGit. --- src/libexpr/primops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 36a67a39d..4f6014f07 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -821,7 +821,7 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va state.forceValue(*args[0], pos); attrs.insert(state.sValue, args[0]); attrs.alloc("success").mkBool(true); - } catch (AssertionError & e) { + } catch (Error & e) { attrs.alloc(state.sValue).mkBool(false); attrs.alloc("success").mkBool(false); } -- 2.51.0 ``` And this is the difference: ``` % result/bin/nix eval --expr 'builtins.tryEval (builtins.fetchGit {})' { success = false; value = false; } % nix eval --expr 'builtins.tryEval (builtins.fetchGit {})' error: … while calling the 'tryEval' builtin at «string»:1:1: 1| builtins.tryEval (builtins.fetchGit {}) | ^ … while calling the 'fetchGit' builtin at «string»:1:19: 1| builtins.tryEval (builtins.fetchGit {}) | ^ error: input attribute 'url' is missing ``` We may want to move this to its own builtin (maybe `builtins.catchAll`?) so that we don't cause any difference in the evaluation of code that already uses tryEval. We can also use `builtins ? catchAll` to detect the presence of the builtin, and if not present fall back to the previous usage. On top of this builtin we can implement a robust fetchGit that accepts multiple sources.
rarias added the
nix
net
labels 2025-10-13 17:00:54 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rarias/jungle#200
No description provided.