mirror of
https://github.com/NixOS/nix.git
synced 2025-12-08 18:11:02 +01:00
Merge pull request #14708 from obsidiansystems/version-path-info-outer
Make `nix path-info` follow the JSON guidelines
This commit is contained in:
commit
a4fc3863dd
9 changed files with 65 additions and 30 deletions
|
|
@ -18,16 +18,30 @@ This is the legacy format, preserved for backwards compatibility:
|
|||
|
||||
- String-based hash values (e.g., `"narHash": "sha256:FePFYIlM..."`)
|
||||
- String-based content addresses (e.g., `"ca": "fixed:r:sha256:1abc..."`)
|
||||
- Full store paths in references (e.g., `"/nix/store/abc...-foo"`)
|
||||
- Full store paths for map keys and references (e.g., `"/nix/store/abc...-foo"`)
|
||||
- Now includes `"storeDir"` field at the top level
|
||||
|
||||
### Version 2 (`--json-format 2`)
|
||||
|
||||
The new structured format with the following changes:
|
||||
The new structured format follows the [JSON guidelines](@docroot@/development/json-guideline.md) with the following changes:
|
||||
|
||||
- **Store path base names in references**:
|
||||
- **Nested structure with top-level metadata**:
|
||||
|
||||
References use store path base names (e.g., `"abc...-foo"`) instead of full paths.
|
||||
The output is now wrapped in an object with `version`, `storeDir`, and `info` fields:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 2,
|
||||
"storeDir": "/nix/store",
|
||||
"info": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
The map from store bath base names to store object info is nested under the `info` field.
|
||||
|
||||
- **Store path base names instead of full paths**:
|
||||
|
||||
Map keys and references use store path base names (e.g., `"abc...-foo"`) instead of full absolute store paths.
|
||||
Combined with `storeDir`, the full path can be reconstructed.
|
||||
|
||||
- **Structured `ca` field**:
|
||||
|
|
|
|||
|
|
@ -41,10 +41,14 @@ pathInfoToJSON(Store & store, const StorePathSet & storePaths, bool showClosureS
|
|||
{
|
||||
json::object_t jsonAllObjects = json::object();
|
||||
|
||||
auto makeKey = [&](const StorePath & path) {
|
||||
return format == PathInfoJsonFormat::V1 ? store.printStorePath(path) : std::string(path.to_string());
|
||||
};
|
||||
|
||||
for (auto & storePath : storePaths) {
|
||||
json jsonObject;
|
||||
|
||||
std::string key = store.printStorePath(storePath);
|
||||
std::string key = makeKey(storePath);
|
||||
|
||||
try {
|
||||
auto info = store.queryPathInfo(storePath);
|
||||
|
|
@ -52,7 +56,7 @@ pathInfoToJSON(Store & store, const StorePathSet & storePaths, bool showClosureS
|
|||
// `storePath` has the representation `<hash>-x` rather than
|
||||
// `<hash>-<name>` in case of binary-cache stores & `--all` because we don't
|
||||
// know the name yet until we've read the NAR info.
|
||||
key = store.printStorePath(info->path);
|
||||
key = makeKey(info->path);
|
||||
|
||||
jsonObject = info->toJSON(format == PathInfoJsonFormat::V1 ? &store : nullptr, true, format);
|
||||
|
||||
|
|
@ -87,7 +91,16 @@ pathInfoToJSON(Store & store, const StorePathSet & storePaths, bool showClosureS
|
|||
|
||||
jsonAllObjects[key] = std::move(jsonObject);
|
||||
}
|
||||
|
||||
if (format == PathInfoJsonFormat::V1) {
|
||||
return jsonAllObjects;
|
||||
} else {
|
||||
return {
|
||||
{"version", format},
|
||||
{"storeDir", store.storeDir},
|
||||
{"info", std::move(jsonAllObjects)},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
struct CmdPathInfo : StorePathsCommand, MixJSON
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ outPath=$(nix-build dependencies.nix --no-out-link)
|
|||
|
||||
nix copy --to "file://$cacheDir" "$outPath"
|
||||
|
||||
readarray -t paths < <(nix path-info --all --json --json-format 2 --store "file://$cacheDir" | jq 'keys|sort|.[]' -r)
|
||||
readarray -t paths < <(nix path-info --all --json --json-format 2 --store "file://$cacheDir" | jq '.info|keys|sort|.[]' -r)
|
||||
[[ "${#paths[@]}" -eq 3 ]]
|
||||
for path in "${paths[@]}"; do
|
||||
[[ "$path" =~ -dependencies-input-0$ ]] \
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ nix-build fixed.nix -A bad --no-out-link && fail "should fail"
|
|||
# a side-effect.
|
||||
[[ -e $path ]]
|
||||
nix path-info --json --json-format 2 "$path" | jq -e \
|
||||
'.[].ca == {
|
||||
'.info.[].ca == {
|
||||
method: "flat",
|
||||
hash: {
|
||||
algorithm: "md5",
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ try2 () {
|
|||
nix path-info --json --json-format 2 "$path" | jq -e \
|
||||
--arg algo "$hashAlgo" \
|
||||
--arg hash "$hashFromGit" \
|
||||
'.[].ca == {
|
||||
'.info.[].ca == {
|
||||
method: "git",
|
||||
hash: {
|
||||
algorithm: $algo,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ path1_stuff=$(echo "$json" | jq -r .[].outputs.stuff)
|
|||
[[ $(< "$path1"/n) = 0 ]]
|
||||
[[ $(< "$path1_stuff"/bla) = 0 ]]
|
||||
|
||||
nix path-info --json --json-format 2 "$path1" | jq -e '.[].ca | .method == "nar" and .hash.algorithm == "sha256"'
|
||||
nix path-info --json --json-format 2 "$path1" | jq -e '.info.[].ca | .method == "nar" and .hash.algorithm == "sha256"'
|
||||
|
||||
path2=$(nix build -L --no-link --json --file ./impure-derivations.nix impure | jq -r .[].outputs.out)
|
||||
[[ $(< "$path2"/n) = 1 ]]
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ printf 4.0 > "$flake1Dir"/version
|
|||
printf Utrecht > "$flake1Dir"/who
|
||||
nix profile add "$flake1Dir"
|
||||
[[ $("$TEST_HOME"/.nix-profile/bin/hello) = "Hello Utrecht" ]]
|
||||
nix path-info --json --json-format 2 "$(realpath "$TEST_HOME"/.nix-profile/bin/hello)" | jq -e '.[].ca | .method == "nar" and .hash.algorithm == "sha256"'
|
||||
nix path-info --json --json-format 2 "$(realpath "$TEST_HOME"/.nix-profile/bin/hello)" | jq -e '.info.[].ca | .method == "nar" and .hash.algorithm == "sha256"'
|
||||
|
||||
# Override the outputs.
|
||||
nix profile remove simple flake1
|
||||
|
|
|
|||
|
|
@ -4,36 +4,44 @@ source common.sh
|
|||
|
||||
echo foo > "$TEST_ROOT"/foo
|
||||
foo=$(nix store add-file "$TEST_ROOT"/foo)
|
||||
fooBase=$(basename "$foo")
|
||||
|
||||
echo bar > "$TEST_ROOT"/bar
|
||||
bar=$(nix store add-file "$TEST_ROOT"/bar)
|
||||
barBase=$(basename "$bar")
|
||||
|
||||
echo baz > "$TEST_ROOT"/baz
|
||||
baz=$(nix store add-file "$TEST_ROOT"/baz)
|
||||
bazBase=$(basename "$baz")
|
||||
nix-store --delete "$baz"
|
||||
|
||||
diff --unified --color=always \
|
||||
<(nix path-info --json --json-format 2 "$foo" "$bar" "$baz" |
|
||||
jq --sort-keys 'map_values(.narHash)') \
|
||||
jq --sort-keys '.info | map_values(.narHash)') \
|
||||
<(jq --sort-keys <<-EOF
|
||||
{
|
||||
"$foo": {
|
||||
"$fooBase": {
|
||||
"algorithm": "sha256",
|
||||
"format": "base16",
|
||||
"hash": "42fb4031b525feebe2f8b08e6e6a8e86f34e6a91dd036ada888e311b9cc8e690"
|
||||
},
|
||||
"$bar": {
|
||||
"$barBase": {
|
||||
"algorithm": "sha256",
|
||||
"format": "base16",
|
||||
"hash": "f5f8581aef5fab17100b629cf35aa1d91328d5070b054068f14fa93e7fa3b614"
|
||||
},
|
||||
"$baz": null
|
||||
"$bazBase": null
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Test that storeDir is returned in the JSON output
|
||||
# Test that storeDir is returned in the JSON output in individual store objects
|
||||
nix path-info --json --json-format 2 "$foo" | jq -e \
|
||||
--arg foo "$foo" \
|
||||
--arg fooBase "$fooBase" \
|
||||
--arg storeDir "${NIX_STORE_DIR:-/nix/store}" \
|
||||
'.[$foo].storeDir == $storeDir'
|
||||
'.info[$fooBase].storeDir == $storeDir'
|
||||
|
||||
# And also at the top -evel
|
||||
echo | nix path-info --json --json-format 2 --stdin | jq -e \
|
||||
--arg storeDir "${NIX_STORE_DIR:-/nix/store}" \
|
||||
'.storeDir == $storeDir'
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ outPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROO
|
|||
|
||||
# Verify that the path got signed.
|
||||
info=$(nix path-info --json --json-format 2 "$outPath")
|
||||
echo "$info" | jq -e '.[] | .ultimate == true'
|
||||
echo "$info" | jq -e '.info.[] | .ultimate == true'
|
||||
TODO_NixOS # looks like an actual bug? Following line fails on NixOS:
|
||||
echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))'
|
||||
echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))'
|
||||
echo "$info" | jq -e '.info.[] | .signatures.[] | select(startswith("cache1.example.org"))'
|
||||
echo "$info" | jq -e '.info.[] | .signatures.[] | select(startswith("cache2.example.org"))'
|
||||
|
||||
# Test "nix store verify".
|
||||
nix store verify -r "$outPath"
|
||||
|
|
@ -40,8 +40,8 @@ nix store verify -r "$outPath"
|
|||
|
||||
# Verify that the path did not get signed but does have the ultimate bit.
|
||||
info=$(nix path-info --json --json-format 2 "$outPath2")
|
||||
echo "$info" | jq -e '.[] | .ultimate == true'
|
||||
echo "$info" | jq -e '.[] | .signatures == []'
|
||||
echo "$info" | jq -e '.info.[] | .ultimate == true'
|
||||
echo "$info" | jq -e '.info.[] | .signatures == []'
|
||||
|
||||
# Test "nix store verify".
|
||||
nix store verify -r "$outPath2"
|
||||
|
|
@ -58,7 +58,7 @@ nix store verify -r "$outPath2" --sigs-needed 1 --trusted-public-keys "$pk1"
|
|||
# Build something content-addressed.
|
||||
outPathCA=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build ./fixed.nix -A good.0 --no-out-link)
|
||||
|
||||
nix path-info --json --json-format 2 "$outPathCA" | jq -e '.[].ca | .method == "flat" and .hash.algorithm == "md5"'
|
||||
nix path-info --json --json-format 2 "$outPathCA" | jq -e '.info.[].ca | .method == "flat" and .hash.algorithm == "md5"'
|
||||
|
||||
# Content-addressed paths don't need signatures, so they verify
|
||||
# regardless of --sigs-needed.
|
||||
|
|
@ -74,15 +74,15 @@ nix copy --to file://"$cacheDir" "$outPath2"
|
|||
|
||||
# Verify that signatures got copied.
|
||||
info=$(nix path-info --store file://"$cacheDir" --json --json-format 2 "$outPath2")
|
||||
echo "$info" | jq -e '.[] | .ultimate == false'
|
||||
echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))'
|
||||
echo "$info" | expect 4 jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))'
|
||||
echo "$info" | jq -e '.info.[] | .ultimate == false'
|
||||
echo "$info" | jq -e '.info.[] | .signatures.[] | select(startswith("cache1.example.org"))'
|
||||
echo "$info" | expect 4 jq -e '.info.[] | .signatures.[] | select(startswith("cache2.example.org"))'
|
||||
|
||||
# Verify that adding a signature to a path in a binary cache works.
|
||||
nix store sign --store file://"$cacheDir" --key-file "$TEST_ROOT"/sk2 "$outPath2"
|
||||
info=$(nix path-info --store file://"$cacheDir" --json --json-format 2 "$outPath2")
|
||||
echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))'
|
||||
echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))'
|
||||
echo "$info" | jq -e '.info.[] | .signatures.[] | select(startswith("cache1.example.org"))'
|
||||
echo "$info" | jq -e '.info.[] | .signatures.[] | select(startswith("cache2.example.org"))'
|
||||
|
||||
# Copying to a diverted store should fail due to a lack of signatures by trusted keys.
|
||||
chmod -R u+w "$TEST_ROOT"/store0 || true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue