From 0e59e5b3082203b4eda15e0df0ec7ac8020875df Mon Sep 17 00:00:00 2001 From: Julian Stecklina Date: Wed, 12 Mar 2025 16:21:36 +0100 Subject: [PATCH] libfetchers: ensure that lastModified is a uint64_t When lastModified comes via inputFromAttrs it ends up as string in the Attrs map. This results in: error: input attribute 'lastModified' is not an integer Fix by handling it like revCount, which already does the right thing. If added a test and confirmed that it catches the issue. Also kudos to alexander.sieg@cyberus-technology.de for helping with debugging this! Change-Id: I8378fcaea986d798cb8458d4e6e15c2a92c2520a --- doc/manual/change-authors.yml | 7 +++++++ doc/manual/rl-next/last-modified.md | 17 +++++++++++++++++ lix/libfetchers/tarball.cc | 2 +- tests/nixos/tarball-flakes.nix | 12 +++++++++--- 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 doc/manual/rl-next/last-modified.md diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index bf2e96572..337f9ac33 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -53,6 +53,10 @@ bb010g: forgejo: bb010g github: bb010g +blitz: + display_name: Julian Stecklina + github: blitz + cole-h: display_name: Cole Helbling github: cole-h @@ -197,6 +201,9 @@ winter: forgejo: winter github: winterqt +xanderio: + github: xanderio + yshui: github: yshui diff --git a/doc/manual/rl-next/last-modified.md b/doc/manual/rl-next/last-modified.md new file mode 100644 index 000000000..38d98c475 --- /dev/null +++ b/doc/manual/rl-next/last-modified.md @@ -0,0 +1,17 @@ +--- +synopsis: "Fix handling of `lastModified` in tarball inputs" +issues: [] +cls: [2792] +category: Fixes +credits: [xanderio, blitz] +--- + +Previous versions of Lix would fail with the following error, if a +[tarball flake input](@docroot@/protocols/tarball-fetcher.md) redirect +to a URL that contains a `lastModified` field: + +``` +error: input attribute 'lastModified' is not an integer +``` + +This is now fixed. diff --git a/lix/libfetchers/tarball.cc b/lix/libfetchers/tarball.cc index 51faace1b..77b37a1a8 100644 --- a/lix/libfetchers/tarball.cc +++ b/lix/libfetchers/tarball.cc @@ -219,7 +219,7 @@ struct CurlInputScheme : InputScheme url.scheme = parseUrlScheme(url.scheme).transport; - emplaceURLQueryIntoAttrs(url, attrs, {"revCount"}, {}); + emplaceURLQueryIntoAttrs(url, attrs, {"revCount", "lastModified"}, {}); attrs.emplace("url", url.to_string()); return inputFromAttrs(attrs); diff --git a/tests/nixos/tarball-flakes.nix b/tests/nixos/tarball-flakes.nix index 5deba4a12..705fe2d72 100644 --- a/tests/nixos/tarball-flakes.nix +++ b/tests/nixos/tarball-flakes.nix @@ -3,6 +3,8 @@ let pkgs = config.nodes.machine.nixpkgs.pkgs; + lastModified = builtins.toString nixpkgs.lastModified; + root = pkgs.runCommand "nixpkgs-flake" {} '' mkdir -p $out/{stable,tags} @@ -19,7 +21,7 @@ let # arbitrary headers. cat >$out/tags/.htaccess <; rel=\"immutable\"" + Header always set Link "; rel=\"immutable\"" EOF ''; in @@ -69,23 +71,27 @@ in # Check that we got redirected to the immutable URL. locked_url = info["locked"]["url"] - assert locked_url == "http://localhost/stable/${nixpkgs.rev}.tar.gz?rev=${nixpkgs.rev}&revCount=1234", f"{locked_url=} != http://localhost/stable/${nixpkgs.rev}.tar.gz" + assert locked_url == "http://localhost/stable/${nixpkgs.rev}.tar.gz?lastModified=${lastModified}&rev=${nixpkgs.rev}&revCount=1234", f"{locked_url=} != http://localhost/stable/${nixpkgs.rev}.tar.gz" - # Check that we got the rev and revCount attributes. + # Check that we got the right attributes. revision = info["revision"] rev_count = info["revCount"] + last_modified = info["lastModified"] assert revision == "${nixpkgs.rev}", f"{revision=} != ${nixpkgs.rev}" assert rev_count == 1234, f"{rev_count=} != 1234" + assert last_modified == ${lastModified}, f"{last_modified=} != ${lastModified}" # Check that fetching with rev/revCount/narHash succeeds. machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?rev=" + revision) machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?revCount=" + str(rev_count)) machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?narHash=" + info["locked"]["narHash"]) + machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?lastModified=" + str(last_modified)) # Check that fetching fails if we provide incorrect attributes. machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?rev=493300eb13ae6fb387fbd47bf54a85915acc31c0") machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?revCount=789") machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?narHash=sha256-tbudgBSg+bHWHiHnlteNzN8TUvI80ygS9IULh4rklEw=") + machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?lastModified=1111111111") ''; }