nixpkgs: add file that fetches pinned revision
This commit is contained in:
parent
1a380f1245
commit
ad628ccbd2
4 changed files with 249 additions and 0 deletions
|
|
@ -25,6 +25,10 @@
|
|||
excludes = [
|
||||
# sema-unused-def-lambda-noarg-formal
|
||||
"ci/rust-analyzer/default.nix"
|
||||
|
||||
# sema-primop-overridden
|
||||
# sema-primop-removed-prefix
|
||||
"nixpkgs.nix"
|
||||
];
|
||||
};
|
||||
nixfmt = {
|
||||
|
|
|
|||
91
nixpkgs.nix
Normal file
91
nixpkgs.nix
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
Fetches Nixvim's pinned revision of Nixpkgs without evaluating the flake.
|
||||
*/
|
||||
let
|
||||
# fetchTree was added in Nix 2.4 as an experimental feature, so provide a fetchTarball-based polyfill
|
||||
# Based on https://github.com/NixOS/flake-compat/blob/5edf11c4/default.nix#L20-L36
|
||||
fetchTree =
|
||||
builtins.fetchTree or (
|
||||
info:
|
||||
if info.type == "github" then
|
||||
{
|
||||
inherit (info) rev narHash lastModified;
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
lastModifiedDate = formatSecondsSinceEpoch info.lastModified;
|
||||
outPath = fetchTarball {
|
||||
url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}";
|
||||
sha256 = info.narHash;
|
||||
};
|
||||
}
|
||||
else
|
||||
throw "fetchTree: unsupported type '${info.type}'"
|
||||
);
|
||||
|
||||
# Format number of seconds since the Unix epoch as %Y%m%d%H%M%S.
|
||||
# Based on https://github.com/NixOS/flake-compat/blob/5edf11c4/default.nix#L172-L197
|
||||
# Uses Howard Hinnant civil date algorithm.
|
||||
formatSecondsSinceEpoch =
|
||||
let
|
||||
rem = x: y: x - x / y * y;
|
||||
pad = s: if builtins.stringLength s < 2 then "0" + s else s;
|
||||
|
||||
second = 1;
|
||||
minute = 60 * second;
|
||||
hour = 60 * minute;
|
||||
day = 24 * hour;
|
||||
|
||||
# Gregorian leap year rules:
|
||||
# - leap year every 4 years
|
||||
# - except every 100 years
|
||||
# - except every 400 years
|
||||
daysPerYear = 365;
|
||||
daysPer4Years = daysPerYear * 4 + 1;
|
||||
daysPer100Years = daysPerYear * 100 + 24;
|
||||
daysPer400Years = daysPerYear * 400 + 97;
|
||||
|
||||
monthsToDaysDivisor = 153;
|
||||
monthsToDaysOffset = 2;
|
||||
|
||||
# Days between civil date epoch 0000-03-01 and Unix epoch 1970-01-01.
|
||||
civilDayOffset = 719468;
|
||||
in
|
||||
t:
|
||||
let
|
||||
z = (t / day) + civilDayOffset;
|
||||
secondsInDay = rem t day;
|
||||
hours = secondsInDay / hour;
|
||||
minutes = (rem secondsInDay hour) / minute;
|
||||
seconds = rem t minute;
|
||||
|
||||
# Gregorian calendars repeat every 400 years.
|
||||
era = (if z >= 0 then z else z - (daysPer400Years - 1)) / daysPer400Years;
|
||||
|
||||
dayOfEra = z - era * daysPer400Years;
|
||||
|
||||
yearOfEra =
|
||||
(
|
||||
dayOfEra - dayOfEra / daysPer4Years + dayOfEra / daysPer100Years - dayOfEra / (daysPer400Years - 1)
|
||||
)
|
||||
/ daysPerYear;
|
||||
|
||||
year' = yearOfEra + era * 400;
|
||||
dayOfYear = dayOfEra - (daysPerYear * yearOfEra + yearOfEra / 4 - yearOfEra / 100);
|
||||
month' = (5 * dayOfYear + monthsToDaysOffset) / monthsToDaysDivisor;
|
||||
dayOfMonth = dayOfYear - (monthsToDaysDivisor * month' + monthsToDaysOffset) / 5 + 1;
|
||||
|
||||
# The algorithm uses March-indexed months, so offset back to January-index
|
||||
month = month' + (if month' < 10 then 3 else -9);
|
||||
year = year' + (if month <= 2 then 1 else 0);
|
||||
in
|
||||
toString year
|
||||
+ pad (toString month)
|
||||
+ pad (toString dayOfMonth)
|
||||
+ pad (toString hours)
|
||||
+ pad (toString minutes)
|
||||
+ pad (toString seconds);
|
||||
|
||||
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||
node = lock.nodes.${lock.nodes.${lock.root}.inputs.nixpkgs};
|
||||
in
|
||||
assert !(node.locked ? dir);
|
||||
fetchTree node.locked
|
||||
|
|
@ -49,6 +49,7 @@ let
|
|||
no-flake = callTest ./no-flake.nix { };
|
||||
lib-tests = callTest ./lib-tests.nix { };
|
||||
maintainers = callTest ./maintainers.nix { };
|
||||
nixpkgs-fetch = callTest ./nixpkgs-fetch.nix { };
|
||||
nixpkgs-module = callTest ./nixpkgs-module.nix { };
|
||||
plugins-by-name = callTest ./plugins-by-name.nix { };
|
||||
generated = callTest ./generated.nix { };
|
||||
|
|
|
|||
153
tests/nixpkgs-fetch.nix
Normal file
153
tests/nixpkgs-fetch.nix
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
lib,
|
||||
self,
|
||||
jq,
|
||||
nix,
|
||||
linkFarmFromDrvs,
|
||||
runCommandLocal,
|
||||
writableTmpDirAsHomeHook,
|
||||
}:
|
||||
|
||||
# nixpkgs.nix fetches our pinned nixpkgs using the `fetchTree` primop.
|
||||
#
|
||||
# In this file, we test that it is identical to our `inputs.nixpkgs` flake input.
|
||||
#
|
||||
# The primop is only available with `experimental-features = flakes` or `experimental-features = fetch-tree`,
|
||||
# so we have a `fetchTree` polyfill that delegates to `fetchTarball`.
|
||||
#
|
||||
# Permutations to test:
|
||||
# 1. fetchTree primop
|
||||
# a. attrs
|
||||
# b. outPath derivation
|
||||
# 2. fetchTree polyfill
|
||||
# a. attrs
|
||||
# b. outPath derivation
|
||||
#
|
||||
# As we run this test from a flake, we have `experimental-features = flakes` and `fetchTree` primop is available.
|
||||
# Therefore, we can test the `fetchTree` primop easily.
|
||||
#
|
||||
# By running `nix-instantiate` _within_ a build sandbox, we can configure `experimental-features =`
|
||||
# to test the polyfill's attrs. However, we cannot do an actual fetch in the sandbox.
|
||||
#
|
||||
# Since we can't do an actual fetch in the sandbox, the polyfill's outPath can be tested manually.
|
||||
# These should both evaluate to the same derivation:
|
||||
# nix-instantiate --eval nixpkgs.nix --attr outPath --option experimental-features flakes
|
||||
# nix-instantiate --eval nixpkgs.nix --attr outPath --option experimental-features ''
|
||||
|
||||
let
|
||||
flake-input = self.inputs.nixpkgs.sourceInfo;
|
||||
pinned-input = import ../nixpkgs.nix;
|
||||
in
|
||||
linkFarmFromDrvs "nixpkgs-fetch-test" [
|
||||
|
||||
(runCommandLocal "nixpkgs-fetch-test-with-primop"
|
||||
{
|
||||
__structuredAttrs = true;
|
||||
unsafeDiscardReferences.out = true;
|
||||
strictDeps = true;
|
||||
|
||||
hasPrimop = builtins ? fetchTree;
|
||||
expected = flake-input;
|
||||
actual = pinned-input;
|
||||
|
||||
expectedAttrs = removeAttrs flake-input [ "outPath" ];
|
||||
actualAttrs = removeAttrs pinned-input [ "outPath" ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
jq
|
||||
];
|
||||
}
|
||||
''
|
||||
echo 'Sanity check that `fetchTree` is enabled'
|
||||
if [ -n "$hasPrimop" ]; then
|
||||
echo "fetchTree is available" >&2
|
||||
else
|
||||
echo "fetchTree is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo "Expectation met: '$expected'" >&2
|
||||
else
|
||||
echo "Expected '$actual' to be '$expected'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir "$out"
|
||||
jq --sort-keys .expectedAttrs "$NIX_ATTRS_JSON_FILE" > "$out/expected.json"
|
||||
jq --sort-keys .actualAttrs "$NIX_ATTRS_JSON_FILE" > "$out/actual.json"
|
||||
|
||||
# Compare actual.json and expected.json
|
||||
if ! diff --unified "$out/expected.json" "$out/actual.json"; then
|
||||
echo 'Unexpected difference between `expected.json` and `actual.json`' >&2
|
||||
exit 1
|
||||
fi
|
||||
''
|
||||
)
|
||||
|
||||
(runCommandLocal "nixpkgs-fetch-test-with-polyfill"
|
||||
{
|
||||
__structuredAttrs = true;
|
||||
unsafeDiscardReferences.out = true;
|
||||
strictDeps = true;
|
||||
|
||||
src = lib.fileset.toSource {
|
||||
root = ../.;
|
||||
fileset = lib.fileset.unions [
|
||||
../flake.lock
|
||||
../nixpkgs.nix
|
||||
];
|
||||
};
|
||||
|
||||
expectedAttrs = removeAttrs flake-input [ "outPath" ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
jq
|
||||
nix
|
||||
writableTmpDirAsHomeHook
|
||||
];
|
||||
}
|
||||
''
|
||||
# Setup nix environment
|
||||
export TEST_ROOT="$PWD/test-tmp"
|
||||
export NIX_CONF_DIR="$TEST_ROOT/etc"
|
||||
export NIX_LOCALSTATE_DIR="$TEST_ROOT/var"
|
||||
export NIX_LOG_DIR="$TEST_ROOT/var/log/nix"
|
||||
export NIX_STATE_DIR="$TEST_ROOT/var/nix"
|
||||
export PAGER=cat
|
||||
|
||||
mkdir -p "$NIX_CONF_DIR"
|
||||
cat > "$NIX_CONF_DIR/nix.conf" <<EOF
|
||||
store = dummy://
|
||||
experimental-features =
|
||||
EOF
|
||||
|
||||
echo 'Sanity check that `fetchTree` is disabled'
|
||||
echo "NOTE: if this assertion fails, then 'fetch-tree' may no longer be an experimental feature"
|
||||
nix-instantiate --eval --raw --expr '
|
||||
if builtins ? fetchTree then
|
||||
throw "fetchTree is available"
|
||||
else
|
||||
"fetchTree is not available\n"
|
||||
'
|
||||
|
||||
mkdir "$out"
|
||||
|
||||
echo "Evaluating expected"
|
||||
jq --sort-keys .expectedAttrs "$NIX_ATTRS_JSON_FILE" > "$out/expected.json"
|
||||
|
||||
echo "Evaluating actual"
|
||||
nix-instantiate --eval --strict --json \
|
||||
--argstr actual "$src/nixpkgs.nix" \
|
||||
--expr '{ actual }: removeAttrs (import actual) [ "outPath" ]' \
|
||||
| jq --sort-keys . > "$out/actual.json"
|
||||
|
||||
# Compare actual.json and expected.json
|
||||
if ! diff --unified "$out/expected.json" "$out/actual.json"; then
|
||||
echo 'Unexpected difference between `expected.json` and `actual.json`' >&2
|
||||
exit 1
|
||||
fi
|
||||
''
|
||||
)
|
||||
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue