aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-12 02:33:44 +0000
committertv <tv@krebsco.de>2026-11-12 02:33:44 +0000
commitd1fe05cba1747f24fa16a51348fd0387f54897e6 (patch)
tree23ff98bd7613024bb92f146bdad0c542ec825fce
parentfd1485d077c06414752a90d2aef84b09d8a4cca2 (diff)
populate flake-input: remove uploads left behind
Uploads an interrupted run left behind in .populate/flake-uploads only got removed before the same source uploaded again. Delivering a flake or flake input removes its upload directory now, and the empty .populate/flake-inputs once the last roots are gone. An edge case leaves an upload behind between two deploys.
-rw-r--r--pkgs/populate/default.nix5
-rw-r--r--tests/scenarios.nix17
2 files changed, 22 insertions, 0 deletions
diff --git a/pkgs/populate/default.nix b/pkgs/populate/default.nix
index 3e5f47b..bd7e5e4 100644
--- a/pkgs/populate/default.nix
+++ b/pkgs/populate/default.nix
@@ -427,6 +427,8 @@ let
fi
${sentinelDirectory sentinel}
+ # Left behind by an interrupted run, or not needed anymore.
+ ${removeUpload}
mkdir -p ${quote inputsRoots}
roots=
while read -r path; do
@@ -450,6 +452,9 @@ let
# An input without own inputs leaves the directory empty.
if test -z "$roots"; then
rmdir ${quote inputsRoots}
+ if test -z "$(ls -A ${quote (dirOf inputsRoots)})"; then
+ rmdir ${quote (dirOf inputsRoots)}
+ fi
fi
'';
# Reads the selection, as selected produces it, and the store path of the
diff --git a/tests/scenarios.nix b/tests/scenarios.nix
index 6dbb84d..eb6bbec 100644
--- a/tests/scenarios.nix
+++ b/tests/scenarios.nix
@@ -956,6 +956,23 @@ assert !(krops.isLocalTarget (targets.remote "/"));
'';
};
})
+ # An upload an interrupted run left behind.
+ (s "upload-leftover" {
+ phases = [
+ {
+ sources.x.flake = { flake = "/fixtures/top"; fetchOnTarget = true; };
+ check = checkFlake { attr = "msg"; expected = "top:dep+inner,sub"; };
+ mutate = ''
+ mkdir -p "$T"/.populate/flake-uploads/x/tree
+ echo half > "$T"/.populate/flake-uploads/x/tree/half
+ '';
+ }
+ {
+ sources.x.flake = { flake = "/fixtures/top"; fetchOnTarget = true; };
+ check = checkFlake { attr = "msg"; expected = "top:dep+inner,sub"; };
+ }
+ ];
+ })
] ++ lib.optional (targetKind == "local")
# The target has the path the input is locked to.
(s "uselocal" {