Compare commits

..

1 Commits

Author SHA1 Message Date
Tristan Ross
8b27c1239e 24.11 beta release 2024-11-14 08:57:15 -08:00
27017 changed files with 894787 additions and 982865 deletions

View File

@@ -204,20 +204,5 @@ ce21e97a1f20dee15da85c084f9d1148d84f853b
# sqlc: format with nixfmt
2bdec131b2bb2c8563f4556d741d34ccb77409e2
# ant: format with nixfmt-rfc-style
2538d58436b8d0b56d29780aeebf4bf720ddb9ea
# treewide: migrate packages to pkgs/by-name, take 1
571c71e6f73af34a229414f51585738894211408
# format files with nixfmt (#347275)
adb9714bd909df283c66bbd641bd631ff50a4260
# treewide: incus packages
9ab59bb5fb943ad6740f64f5a79eae9642fb8211
# treewide nixfmt reformat pass 1, master, staging and staging-next
4f0dadbf38ee4cf4cc38cbc232b7708fddf965bc
667d42c00d566e091e6b9a19b365099315d0e611
84d4f874c2bac9f3118cb6907d7113b3318dcb5e

View File

@@ -1,39 +0,0 @@
---
name: Tracking issue
about: Provide an overview on a multi-step effort
title: 'Tracking issue: ISSUENAME'
labels: '5.scope: tracking'
assignees: ''
---
### Tracking description
<!--
Provide a brief summary of the project or multi-step effort. Explain why it is
necessary and what the goals are.
You may include way to reproduce the problem, screenshots or any information
that you find relevant.
-->
#### Reference Issue(s)/PR(s)
- ...
### Follow-up issues/notes
<!--
List any follow-up issues that need to be addressed after the main tasks are
completed, or any notes related to the project.
-->
#### Additional context
Add any other context about the problem here.
---
Add a :+1: [reaction] to [issues you find important].
[reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/
[issues you find important]: https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc

View File

@@ -25,7 +25,7 @@ For new packages please briefly describe the package or provide a link to its ho
- made sure NixOS tests are [linked](https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#linking-nixos-module-tests-to-a-package) to the relevant packages
- [ ] Tested compilation of all packages that depend on this change using `nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"`. Note: all changes have to be committed, also see [nixpkgs-review usage](https://github.com/Mic92/nixpkgs-review#usage)
- [ ] Tested basic functionality of all binary files (usually in `./result/bin/`)
- [25.05 Release Notes](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2505.section.md) (or backporting [24.11](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2411.section.md) and [25.05](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2505.section.md) Release notes)
- [24.11 Release Notes](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2411.section.md) (or backporting [23.11](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2311.section.md) and [24.05](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2405.section.md) Release notes)
- [ ] (Package updates) Added a release notes entry if the change is major or breaking
- [ ] (Module updates) Added a release notes entry if the change is significant
- [ ] (Module addition) Added a release notes entry if adding a new NixOS module

24
.github/labeler.yml vendored
View File

@@ -176,32 +176,13 @@
- any:
- changed-files:
- any-glob-to-any-file:
# Distributions
- pkgs/development/compilers/adoptopenjdk-icedtea-web/**/*
- pkgs/development/compilers/corretto/**/*
- nixos/modules/programs/java.nix
- pkgs/development/compilers/graalvm/**/*
- pkgs/development/compilers/openjdk/**/*
- pkgs/development/compilers/semeru-bin/**/*
- pkgs/development/compilers/temurin-bin/**/*
- pkgs/development/compilers/zulu/**/*
# Documentation
- doc/languages-frameworks/java.section.md
# Gradle
- doc/languages-frameworks/gradle.section.md
- pkgs/development/tools/build-managers/gradle/**/*
- pkgs/by-name/gr/gradle-completion/**/*
# Maven
- pkgs/by-name/ma/maven/**/*
- doc/languages-frameworks/maven.section.md
# Ant
- pkgs/by-name/an/ant/**/*
# javaPackages attrset
- pkgs/development/java-modules/**/*
- pkgs/top-level/java-packages.nix
# Maintainer tooling
- pkgs/by-name/ni/nixpkgs-openjdk-updater/**/*
# Misc
- nixos/modules/programs/java.nix
"6.topic: jitsi":
- any:
@@ -312,7 +293,6 @@
- any-glob-to-any-file:
- nixos/**/*
- pkgs/by-name/sw/switch-to-configuration-ng/**/*
- pkgs/by-name/ni/nixos-rebuild-ng/**/*
- pkgs/os-specific/linux/nixos-rebuild/**/*
"6.topic: nixos-container":
@@ -328,7 +308,6 @@
- any-glob-to-any-file:
- doc/languages-frameworks/nim.section.md
- pkgs/build-support/build-nim-package.nix
- pkgs/build-support/build-nim-sbom.nix
- pkgs/by-name/ni/nim*
- pkgs/top-level/nim-overrides.nix
@@ -446,7 +425,6 @@
- doc/languages-frameworks/ruby.section.md
- pkgs/development/interpreters/ruby/**/*
- pkgs/development/ruby-modules/**/*
- pkgs/top-level/ruby-packages.nix
"6.topic: rust":
- any:

View File

@@ -8,31 +8,26 @@ on:
# the GitHub repository. This means that it should not evaluate user input in a
# way that allows code injection.
permissions: {}
permissions:
contents: read
jobs:
backport:
permissions:
contents: write # for korthout/backport-action to create branch
pull-requests: write # for korthout/backport-action to create PR to backport
name: Backport Pull Request
if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
runs-on: ubuntu-latest
steps:
# Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
- uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
id: app-token
with:
app-id: ${{ vars.BACKPORT_APP_ID }}
private-key: ${{ secrets.BACKPORT_PRIVATE_KEY }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
token: ${{ steps.app-token.outputs.token }}
- name: Create backport PRs
uses: korthout/backport-action@be567af183754f6a5d831ae90f648954763f17f5 # v3.1.0
uses: korthout/backport-action@bd410d37cdcae80be6d969823ff5a225fe5c833f # v3.0.2
with:
# Config README: https://github.com/korthout/backport-action#backport-action
copy_labels_pattern: 'severity:\ssecurity'
github_token: ${{ steps.app-token.outputs.token }}
pull_description: |-
Bot-based backport to `${target_branch}`, triggered by a label in #${pull_number}.

View File

@@ -13,19 +13,15 @@ permissions:
contents: read
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
nixos:
name: nixfmt-check
runs-on: ubuntu-latest
needs: get-merge-commit
if: "needs.get-merge-commit.outputs.mergedSha && !contains(github.event.pull_request.title, '[skip treewide]')"
if: "!contains(github.event.pull_request.title, '[skip treewide]')"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
# pull_request_target checks out the base branch by default
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
ref: refs/pull/${{ github.event.pull_request.number }}/merge
# Fetches the merge commit and its parents
fetch-depth: 2
- name: Checking out base branch
@@ -87,9 +83,8 @@ jobs:
if (( "${#unformattedFiles[@]}" > 0 )); then
echo "Some new/changed Nix files are not properly formatted"
echo "Please format them using the Nixpkgs-specific \`nixfmt\` by going to the Nixpkgs root directory, running \`nix-shell\`, then:"
echo "Please go to the Nixpkgs root directory, run \`nix-shell\`, then:"
echo "nixfmt ${unformattedFiles[*]@Q}"
echo "Make sure your branch is up to date with master, rebase if not."
echo "If you're having trouble, please ping @NixOS/nix-formatting"
exit 1
fi

View File

@@ -107,7 +107,7 @@ jobs:
echo "$errors"
else
# just print in plain text
echo "${errors/::/}"
echo "$errors" | sed 's/^:://'
echo # add one empty line
fi
failedFiles+=("$dest")

View File

@@ -2,9 +2,6 @@ name: "Check shell"
on:
pull_request_target:
paths:
- 'shell.nix'
- 'ci/**'
permissions: {}

View File

@@ -33,15 +33,10 @@ env:
DRY_MODE: ${{ github.event.pull_request.draft && '1' || '' }}
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
# Check that code owners is valid
check:
name: Check
runs-on: ubuntu-latest
needs: get-merge-commit
if: needs.get-merge-commit.outputs.mergedSha
steps:
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
@@ -70,7 +65,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
ref: refs/pull/${{ github.event.number }}/merge
path: pr
- name: Validate codeowners

View File

@@ -11,14 +11,10 @@ on:
- 'release-**'
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
tests:
name: editorconfig-check
runs-on: ubuntu-latest
needs: get-merge-commit
if: "needs.get-merge-commit.outputs.mergedSha && github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
if: "github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
steps:
- name: Get list of changed files from PR
env:
@@ -34,7 +30,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
# pull_request_target checks out the base branch by default
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
with:
# nixpkgs commit is pinned so that it doesn't break
@@ -42,7 +38,7 @@ jobs:
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/c473cc8714710179df205b153f4e9fa007107ff9.tar.gz
- name: Checking EditorConfig
run: |
< "$HOME/changed_files" nix-shell -p editorconfig-checker --run 'xargs -r editorconfig-checker -disable-indent-size'
cat "$HOME/changed_files" | nix-shell -p editorconfig-checker --run 'xargs -r editorconfig-checker -disable-indent-size'
- if: ${{ failure() }}
run: |
echo "::error :: Hey! It looks like your changes don't follow our editorconfig settings. Read https://editorconfig.org/#download to configure your editor so you never see this error again."

View File

@@ -1,30 +0,0 @@
name: "Building Nixpkgs lib-tests"
permissions:
contents: read
on:
pull_request_target:
paths:
- 'lib/**'
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
nixpkgs-lib-tests:
name: nixpkgs-lib-tests
runs-on: ubuntu-latest
needs: get-merge-commit
if: needs.get-merge-commit.outputs.mergedSha
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
# pull_request_target checks out the base branch by default
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true
- name: Building Nixpkgs lib-tests
run: |
nix-build --arg pkgs "(import ./ci/. {}).pkgs" ./lib/tests/release.nix

View File

@@ -1,277 +0,0 @@
name: Eval
on:
pull_request_target:
push:
# Keep this synced with ci/request-reviews/dev-branches.txt
branches:
- master
- staging
- release-*
- staging-*
- haskell-updates
- python-updates
permissions:
contents: read
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
attrs:
name: Attributes
runs-on: ubuntu-latest
needs: get-merge-commit
# Skip this and dependent steps if the PR can't be merged
if: needs.get-merge-commit.outputs.mergedSha
outputs:
baseSha: ${{ steps.baseSha.outputs.baseSha }}
systems: ${{ steps.systems.outputs.systems }}
steps:
- name: Check out the PR at the test merge commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
fetch-depth: 2
path: nixpkgs
- name: Determine base commit
if: github.event_name == 'pull_request_target'
id: baseSha
run: |
baseSha=$(git -C nixpkgs rev-parse HEAD^1)
echo "baseSha=$baseSha" >> "$GITHUB_OUTPUT"
- name: Install Nix
uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
- name: Evaluate the list of all attributes and get the systems matrix
id: systems
run: |
nix-build nixpkgs/ci -A eval.attrpathsSuperset
echo "systems=$(<result/systems.json)" >> "$GITHUB_OUTPUT"
- name: Upload the list of all attributes
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: paths
path: result/*
eval-aliases:
name: Eval nixpkgs with aliases enabled
runs-on: ubuntu-latest
needs: [ attrs, get-merge-commit ]
steps:
- name: Check out the PR at the test merge commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
path: nixpkgs
- name: Install Nix
uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
- name: Query nixpkgs with aliases enabled to check for basic syntax errors
run: |
time nix-env -I ./nixpkgs -f ./nixpkgs -qa '*' --option restrict-eval true --option allow-import-from-derivation false >/dev/null
outpaths:
name: Outpaths
runs-on: ubuntu-latest
needs: [ attrs, get-merge-commit ]
strategy:
matrix:
system: ${{ fromJSON(needs.attrs.outputs.systems) }}
steps:
- name: Download the list of all attributes
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: paths
path: paths
- name: Check out the PR at the test merge commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
path: nixpkgs
- name: Install Nix
uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
- name: Evaluate the ${{ matrix.system }} output paths for all derivation attributes
env:
MATRIX_SYSTEM: ${{ matrix.system }}
run: |
nix-build nixpkgs/ci -A eval.singleSystem \
--argstr evalSystem "$MATRIX_SYSTEM" \
--arg attrpathFile ./paths/paths.json \
--arg chunkSize 10000
# If it uses too much memory, slightly decrease chunkSize
- name: Upload the output paths and eval stats
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: intermediate-${{ matrix.system }}
path: result/*
process:
name: Process
runs-on: ubuntu-latest
needs: [ outpaths, attrs, get-merge-commit ]
outputs:
baseRunId: ${{ steps.baseRunId.outputs.baseRunId }}
steps:
- name: Download output paths and eval stats for all systems
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
pattern: intermediate-*
path: intermediate
- name: Check out the PR at the test merge commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
path: nixpkgs
- name: Install Nix
uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
- name: Combine all output paths and eval stats
run: |
nix-build nixpkgs/ci -A eval.combine \
--arg resultsDir ./intermediate \
-o prResult
- name: Upload the combined results
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: result
path: prResult/*
- name: Get base run id
if: needs.attrs.outputs.baseSha
id: baseRunId
run: |
# Get the latest eval.yml workflow run for the PR's base commit
if ! run=$(gh api --method GET /repos/"$REPOSITORY"/actions/workflows/eval.yml/runs \
-f head_sha="$BASE_SHA" -f event=push \
--jq '.workflow_runs | sort_by(.run_started_at) | .[-1]') \
|| [[ -z "$run" ]]; then
echo "Could not find an eval.yml workflow run for $BASE_SHA, cannot make comparison"
exit 0
fi
echo "Comparing against $(jq .html_url <<< "$run")"
runId=$(jq .id <<< "$run")
conclusion=$(jq -r .conclusion <<< "$run")
while [[ "$conclusion" == null || "$conclusion" == "" ]]; do
echo "Workflow not done, waiting 10 seconds before checking again"
sleep 10
conclusion=$(gh api /repos/"$REPOSITORY"/actions/runs/"$runId" --jq '.conclusion')
done
if [[ "$conclusion" != "success" ]]; then
echo "Workflow was not successful (conclusion: $conclusion), cannot make comparison"
exit 0
fi
echo "baseRunId=$runId" >> "$GITHUB_OUTPUT"
env:
REPOSITORY: ${{ github.repository }}
BASE_SHA: ${{ needs.attrs.outputs.baseSha }}
GH_TOKEN: ${{ github.token }}
- uses: actions/download-artifact@v4
if: steps.baseRunId.outputs.baseRunId
with:
name: result
path: baseResult
github-token: ${{ github.token }}
run-id: ${{ steps.baseRunId.outputs.baseRunId }}
- name: Compare against the base branch
if: steps.baseRunId.outputs.baseRunId
run: |
nix-build nixpkgs/ci -A eval.compare \
--arg beforeResultDir ./baseResult \
--arg afterResultDir ./prResult \
-o comparison
cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY"
# TODO: Request reviews from maintainers for packages whose files are modified in the PR
- name: Upload the combined results
if: steps.baseRunId.outputs.baseRunId
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: comparison
path: comparison/*
# Separate job to have a very tightly scoped PR write token
tag:
name: Tag
runs-on: ubuntu-latest
needs: process
if: needs.process.outputs.baseRunId
permissions:
pull-requests: write
statuses: write
steps:
- name: Download process result
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: comparison
path: comparison
- name: Tagging pull request
run: |
# Get all currently set rebuild labels
gh api \
/repos/"$REPOSITORY"/issues/"$NUMBER"/labels \
--jq '.[].name | select(startswith("10.rebuild"))' \
| sort > before
# And the labels that should be there
jq -r '.labels[]' comparison/changed-paths.json \
| sort > after
# Remove the ones not needed anymore
while read -r toRemove; do
echo "Removing label $toRemove"
gh api \
--method DELETE \
/repos/"$REPOSITORY"/issues/"$NUMBER"/labels/"$toRemove"
done < <(comm -23 before after)
# And add the ones that aren't set already
while read -r toAdd; do
echo "Adding label $toAdd"
gh api \
--method POST \
/repos/"$REPOSITORY"/issues/"$NUMBER"/labels \
-f "labels[]=$toAdd"
done < <(comm -13 before after)
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
NUMBER: ${{ github.event.number }}
- name: Add eval summary to commit statuses
if: ${{ github.event_name == 'pull_request_target' }}
run: |
description=$(jq -r '
"Package: added " + (.attrdiff.added | length | tostring) +
", removed " + (.attrdiff.removed | length | tostring) +
", changed " + (.attrdiff.changed | length | tostring) +
", Rebuild: linux " + (.rebuildCountByKernel.linux | tostring) +
", darwin " + (.rebuildCountByKernel.darwin | tostring)
' <comparison/changed-paths.json)
target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID?pr=$NUMBER"
gh api --method POST \
-H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$GITHUB_REPOSITORY/statuses/$PR_HEAD_SHA" \
-f "context=Eval / Summary" -f "state=success" -f "description=$description" -f "target_url=$target_url"
env:
GH_TOKEN: ${{ github.token }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
NUMBER: ${{ github.event.number }}

View File

@@ -1,43 +0,0 @@
name: Get merge commit
on:
workflow_call:
outputs:
mergedSha:
description: "The merge commit SHA"
value: ${{ jobs.resolve-merge-commit.outputs.mergedSha }}
# We need a token to query the API, but it doesn't need any special permissions
permissions: {}
jobs:
resolve-merge-commit:
runs-on: ubuntu-latest
outputs:
mergedSha: ${{ steps.merged.outputs.mergedSha }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: base
sparse-checkout: ci
- name: Check if the PR can be merged and get the test merge commit
id: merged
env:
GH_TOKEN: ${{ github.token }}
GH_EVENT: ${{ github.event_name }}
run: |
case "$GH_EVENT" in
push)
echo "mergedSha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
;;
pull_request_target)
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
echo "Checking the merge commit $mergedSha"
echo "mergedSha=$mergedSha" >> "$GITHUB_OUTPUT"
else
# Skipping so that no notifications are sent
echo "Skipping the rest..."
fi
;;
esac
rm -rf base

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash actionlint shellcheck -I nixpkgs=../..
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
cd "$SCRIPT_DIR/../.."
actionlint

View File

@@ -11,14 +11,10 @@ on:
- 'release-**'
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
tests:
name: nix-files-parseable-check
runs-on: ubuntu-latest
needs: get-merge-commit
if: "needs.get-merge-commit.outputs.mergedSha && github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
if: "github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
steps:
- name: Get list of changed files from PR
env:
@@ -34,7 +30,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
# pull_request_target checks out the base branch by default
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
ref: refs/pull/${{ github.event.pull_request.number }}/merge
if: ${{ env.CHANGED_FILES && env.CHANGED_FILES != '' }}
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
with:

View File

@@ -19,31 +19,46 @@ permissions: {}
# There is a feature request for suppressing notifications on concurrency-canceled runs: https://github.com/orgs/community/discussions/13015
jobs:
get-merge-commit:
uses: ./.github/workflows/get-merge-commit.yml
check:
name: nixpkgs-vet
# This needs to be x86_64-linux, because we depend on the tooling being pre-built in the GitHub releases.
runs-on: ubuntu-latest
# This should take 1 minute at most, but let's be generous. The default of 6 hours is definitely too long.
timeout-minutes: 10
needs: get-merge-commit
if: needs.get-merge-commit.outputs.mergedSha
steps:
# This checks out the base branch because of pull_request_target
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: base
sparse-checkout: ci
- name: Resolving the merge commit
env:
GH_TOKEN: ${{ github.token }}
run: |
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
echo "Checking the merge commit $mergedSha"
echo "mergedSha=$mergedSha" >> "$GITHUB_ENV"
else
echo "Skipping the rest..."
fi
rm -rf base
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
if: env.mergedSha
with:
# pull_request_target checks out the base branch by default
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
ref: ${{ env.mergedSha }}
# Fetches the merge commit and its parents
fetch-depth: 2
- name: Checking out base branch
if: env.mergedSha
run: |
base=$(mktemp -d)
git worktree add "$base" "$(git rev-parse HEAD^1)"
echo "base=$base" >> "$GITHUB_ENV"
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
if: env.mergedSha
- name: Fetching the pinned tool
if: env.mergedSha
# Update the pinned version using ci/nixpkgs-vet/update-pinned-tool.sh
run: |
# The pinned version of the tooling to use.
@@ -56,6 +71,7 @@ jobs:
# Adds a result symlink as a GC root.
nix-store --realise "$toolPath" --add-root result
- name: Running nixpkgs-vet
if: env.mergedSha
env:
# Force terminal colors to be enabled. The library that `nixpkgs-vet` uses respects https://bixense.com/clicolors/
CLICOLOR_FORCE: 1

View File

@@ -39,10 +39,6 @@ jobs:
into: staging-next-24.05
- from: staging-next-24.05
into: staging-24.05
- from: release-24.11
into: staging-next-24.11
- from: staging-next-24.11
into: staging-24.11
name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

View File

@@ -14,7 +14,6 @@ Jörg Thalheim <joerg@thalheim.io> <Mic92@users.noreply.github.com>
Lin Jian <me@linj.tech> <linj.dev@outlook.com>
Lin Jian <me@linj.tech> <75130626+jian-lin@users.noreply.github.com>
Martin Weinelt <hexa@darmstadt.ccc.de> <mweinelt@users.noreply.github.com>
moni <lythe1107@gmail.com> <lythe1107@icloud.com>
R. RyanTM <ryantm-bot@ryantm.com>
Robert Hensing <robert@roberthensing.nl> <roberth@users.noreply.github.com>
Sandro Jäckel <sandro.jaeckel@gmail.com>

View File

@@ -1,21 +0,0 @@
queue_rules:
# This rule is for https://docs.mergify.com/commands/queue/
# and can be triggered with: @mergifyio queue
- name: default
merge_conditions:
# all github action checks in this list are required to merge a pull request
- check-success=Attributes
- check-success=Check
- check-success=Outpaths (aarch64-darwin)
- check-success=Outpaths (aarch64-linux)
- check-success=Outpaths (x86_64-darwin)
- check-success=Outpaths (x86_64-linux)
- check-success=Process
- check-success=Request
- check-success=editorconfig-check
- check-success=label-pr
- check-success=nix-files-parseable-check
- check-success=nixfmt-check
- check-success=nixpkgs-vet
# queue up to 5 pull requests at a time
batch_size: 5

View File

@@ -345,7 +345,7 @@ See [Nix Channel Status](https://status.nixos.org/) for the current channels and
Here's a brief overview of the main Git branches and what channels they're used for:
- `master`: The main branch, used for the unstable channels such as `nixpkgs-unstable`, `nixos-unstable` and `nixos-unstable-small`.
- `release-YY.MM` (e.g. `release-25.05`): The NixOS release branches, used for the stable channels such as `nixos-25.05`, `nixos-25.05-small` and `nixpkgs-25.05-darwin`.
- `release-YY.MM` (e.g. `release-24.05`): The NixOS release branches, used for the stable channels such as `nixos-24.05`, `nixos-24.05-small` and `nixpkgs-24.05-darwin`.
When a channel is updated, a corresponding Git branch is also updated to point to the corresponding commit.
So e.g. the [`nixpkgs-unstable` branch](https://github.com/nixos/nixpkgs/tree/nixpkgs-unstable) corresponds to the Git commit from the [`nixpkgs-unstable` channel](https://channels.nixos.org/nixpkgs-unstable).

View File

@@ -52,9 +52,9 @@ Nixpkgs and NixOS are built and tested by our continuous integration
system, [Hydra](https://hydra.nixos.org/).
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Continuous package builds for the NixOS 24.11 release](https://hydra.nixos.org/jobset/nixos/release-24.11)
* [Continuous package builds for the NixOS 24.05 release](https://hydra.nixos.org/jobset/nixos/release-24.05)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for the NixOS 24.11 release](https://hydra.nixos.org/job/nixos/release-24.11/tested#tabs-constituents)
* [Tests for the NixOS 24.05 release](https://hydra.nixos.org/job/nixos/release-24.05/tested#tabs-constituents)
Artifacts successfully built with Hydra are published to cache at
https://cache.nixos.org/. When successful build and test criteria are

View File

@@ -14,7 +14,7 @@
# Processing of this file is implemented in workflows/codeowners-v2.yml
# CI
/.github/workflows @NixOS/Security @Mic92 @zowoq @infinisil @azuwis
/.github/workflows @NixOS/Security @Mic92 @zowoq
/.github/workflows/check-nix-format.yml @infinisil
/.github/workflows/nixpkgs-vet.yml @infinisil @philiptaron
/.github/workflows/codeowners-v2.yml @infinisil
@@ -105,11 +105,6 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
/nixos/modules/system/activation/bootspec.nix @grahamc @cole-h @raitobezarius
/nixos/modules/system/activation/bootspec.cue @grahamc @cole-h @raitobezarius
# NixOS Render Docs
/pkgs/by-name/ni/nixos-render-docs @fricklerhandwerk @GetPsyched @hsjobeki
/doc/redirects.json @fricklerhandwerk @GetPsyched @hsjobeki
/nixos/doc/manual/redirects.json @fricklerhandwerk @GetPsyched @hsjobeki
# NixOS integration test driver
/nixos/lib/test-driver @tfc
@@ -143,8 +138,6 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
/nixos/tests/amazon-ssm-agent.nix @arianvp
/nixos/modules/system/boot/grow-partition.nix @arianvp
# nixos-rebuild-ng
/pkgs/by-name/ni/nixos-rebuild-ng @thiagokokada
# Updaters
@@ -157,7 +150,6 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
# Python-related code and docs
/doc/languages-frameworks/python.section.md @mweinelt @natsukium
/maintainers/scripts/update-python-libraries @mweinelt @natsukium
/pkgs/by-name/up/update-python-libraries @mweinelt @natsukium
/pkgs/development/interpreters/python @mweinelt @natsukium
/pkgs/top-level/python-packages.nix @natsukium
/pkgs/top-level/release-python.nix @natsukium
@@ -183,7 +175,6 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
# Rust
/pkgs/development/compilers/rust @alyssais @Mic92 @zowoq @winterqt @figsoda
/pkgs/build-support/rust @zowoq @winterqt @figsoda
/pkgs/build-support/rust/fetch-cargo-vendor* @TomaSajt
/doc/languages-frameworks/rust.section.md @zowoq @winterqt @figsoda
# Tcl
@@ -207,8 +198,8 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
# Browsers
/pkgs/applications/networking/browsers/firefox @mweinelt
/pkgs/applications/networking/browsers/chromium @emilylange @networkException
/nixos/tests/chromium.nix @emilylange @networkException
/pkgs/applications/networking/browsers/chromium @emilylange
/nixos/tests/chromium.nix @emilylange
# Certificate Authorities
pkgs/data/misc/cacert/ @ajs124 @lukegb @mweinelt
@@ -219,11 +210,10 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/doc/languages-frameworks/java.section.md @NixOS/java
/doc/languages-frameworks/gradle.section.md @NixOS/java
/doc/languages-frameworks/maven.section.md @NixOS/java
/nixos/modules/programs/java.nix @NixOS/java
/pkgs/top-level/java-packages.nix @NixOS/java
# Jetbrains
/pkgs/applications/editors/jetbrains @edwtjo @leona-ya @theCapypara
/pkgs/applications/editors/jetbrains @edwtjo
# Licenses
/lib/licenses.nix @alyssais
@@ -243,7 +233,6 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
# PostgreSQL and related stuff
/pkgs/servers/sql/postgresql @NixOS/postgres
/pkgs/development/tools/rust/cargo-pgrx @NixOS/postgres
/nixos/modules/services/databases/postgresql.md @NixOS/postgres
/nixos/modules/services/databases/postgresql.nix @NixOS/postgres
/nixos/tests/postgresql @NixOS/postgres
@@ -361,7 +350,6 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
# nim
/doc/languages-frameworks/nim.section.md @ehmry
/pkgs/build-support/build-nim-package.nix @ehmry
/pkgs/build-support/build-nim-sbom.nix @ehmry
/pkgs/top-level/nim-overrides.nix @ehmry
# terraform providers

View File

@@ -58,7 +58,7 @@ Exit codes:
### Usage
This script is implemented as a reusable GitHub Actions workflow, and can be used as follows:
This script can be used in GitHub Actions workflows as follows:
```yaml
on: pull_request_target
@@ -67,19 +67,32 @@ on: pull_request_target
permissions: {}
jobs:
get-merge-commit:
# use the relative path of the get-merge-commit workflow yaml here
uses: ./.github/workflows/get-merge-commit.yml
build:
name: Build
runs-on: ubuntu-latest
needs: get-merge-commit
steps:
# Important: Because of `pull_request_target`, this doesn't check out the PR,
# but rather the base branch of the PR, which is needed so we don't run untrusted code
- uses: actions/checkout@<VERSION>
with:
path: base
sparse-checkout: ci
- name: Resolving the merge commit
env:
GH_TOKEN: ${{ github.token }}
run: |
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
echo "Checking the merge commit $mergedSha"
echo "mergedSha=$mergedSha" >> "$GITHUB_ENV"
else
# Skipping so that no notifications are sent
echo "Skipping the rest..."
fi
rm -rf base
- uses: actions/checkout@<VERSION>
# Add this to _all_ subsequent steps to skip them
if: needs.get-merge-commit.outputs.mergedSha
if: env.mergedSha
with:
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
ref: ${{ env.mergedSha }}
- ...
```

View File

@@ -26,5 +26,4 @@ in
inherit pkgs;
requestReviews = pkgs.callPackage ./request-reviews { };
codeownersValidator = pkgs.callPackage ./codeowners-validator { };
eval = pkgs.callPackage ./eval { };
}

View File

@@ -1,21 +0,0 @@
# Nixpkgs CI evaluation
The code in this directory is used by the [eval.yml](../../.github/workflows/eval.yml) GitHub Actions workflow to evaluate the majority of Nixpkgs for all PRs, effectively making sure that when the development branches are processed by Hydra, no evaluation failures are encountered.
Furthermore it also allows local evaluation using
```
nix-build ci -A eval.full \
--max-jobs 4 \
--cores 2 \
--arg chunkSize 10000 \
--arg evalSystems '["x86_64-linux" "aarch64-darwin"]'
```
- `--max-jobs`: The maximum number of derivations to run at the same time. Only each [supported system](../supportedSystems.nix) gets a separate derivation, so it doesn't make sense to set this higher than that number.
- `--cores`: The number of cores to use for each job. Recommended to set this to the amount of cores on your system divided by `--max-jobs`.
- `chunkSize`: The number of attributes that are evaluated simultaneously on a single core. Lowering this decreases memory usage at the cost of increased evaluation time. If this is too high, there won't be enough chunks to process them in parallel, and will also increase evaluation time.
- `evalSystems`: The set of systems for which `nixpkgs` should be evaluated. Defaults to the four official platforms (`x86_64-linux`, `aarch64-linux`, `x86_64-darwin` and `aarch64-darwin`).
A good default is to set `chunkSize` to 10000, which leads to about 3.6GB max memory usage per core, so suitable for fully utilising machines with 4 cores and 16GB memory, 8 cores and 32GB memory or 16 cores and 64GB memory.
Note that 16GB memory is the recommended minimum, while with less than 8GB memory evaluation time suffers greatly.

View File

@@ -1,114 +0,0 @@
{
lib,
jq,
runCommand,
writeText,
...
}:
{ beforeResultDir, afterResultDir }:
let
/*
Derivation that computes which packages are affected (added, changed or removed) between two revisions of nixpkgs.
Note: "platforms" are "x86_64-linux", "aarch64-darwin", ...
---
Inputs:
- beforeResultDir, afterResultDir: The evaluation result from before and after the change.
They can be obtained by running `nix-build -A ci.eval.full` on both revisions.
---
Outputs:
- changed-paths.json: Various information about the changes:
{
attrdiff: {
added: ["package1"],
changed: ["package2", "package3"],
removed: ["package4"],
},
labels: [
"10.rebuild-darwin: 1-10",
"10.rebuild-linux: 1-10"
],
rebuildsByKernel: {
darwin: ["package1", "package2"],
linux: ["package1", "package2", "package3"]
},
rebuildCountByKernel: {
darwin: 2,
linux: 3,
},
rebuildsByPlatform: {
aarch64-darwin: ["package1", "package2"],
aarch64-linux: ["package1", "package2"],
x86_64-linux: ["package1", "package2", "package3"],
x86_64-darwin: ["package1"],
},
}
- step-summary.md: A markdown render of the changes
---
Implementation details:
Helper functions can be found in ./utils.nix.
Two main "types" are important:
- `packagePlatformPath`: A string of the form "<PACKAGE_PATH>.<PLATFORM>"
Example: "python312Packages.numpy.x86_64-linux"
- `packagePlatformAttr`: An attrs representation of a packagePlatformPath:
Example: { name = "python312Packages.numpy"; platform = "x86_64-linux"; }
*/
inherit (import ./utils.nix { inherit lib; })
diff
groupByKernel
convertToPackagePlatformAttrs
groupByPlatform
extractPackageNames
getLabels
uniqueStrings
;
getAttrs = dir: builtins.fromJSON (builtins.readFile "${dir}/outpaths.json");
beforeAttrs = getAttrs beforeResultDir;
afterAttrs = getAttrs afterResultDir;
# Attrs
# - keys: "added", "changed" and "removed"
# - values: lists of `packagePlatformPath`s
diffAttrs = diff beforeAttrs afterAttrs;
changed-paths =
let
rebuilds = uniqueStrings (diffAttrs.added ++ diffAttrs.changed);
rebuildsPackagePlatformAttrs = convertToPackagePlatformAttrs rebuilds;
rebuildsByPlatform = groupByPlatform rebuildsPackagePlatformAttrs;
rebuildsByKernel = groupByKernel rebuildsPackagePlatformAttrs;
rebuildCountByKernel = lib.mapAttrs (
kernel: kernelRebuilds: lib.length kernelRebuilds
) rebuildsByKernel;
in
writeText "changed-paths.json" (
builtins.toJSON {
attrdiff = lib.mapAttrs (_: extractPackageNames) diffAttrs;
inherit
rebuildsByPlatform
rebuildsByKernel
rebuildCountByKernel
;
labels = getLabels rebuildCountByKernel;
}
);
in
runCommand "compare"
{
nativeBuildInputs = [ jq ];
}
''
mkdir $out
cp ${changed-paths} $out/changed-paths.json
jq -r -f ${./generate-step-summary.jq} < ${changed-paths} > $out/step-summary.md
# TODO: Compare eval stats
''

View File

@@ -1,30 +0,0 @@
def truncate(xs; n):
if xs | length > n then xs[:n] + ["..."]
else xs
end;
def itemize_packages(xs):
truncate(xs; 2000) |
map("- [\(.)](https://search.nixos.org/packages?channel=unstable&show=\(.)&from=0&size=50&sort=relevance&type=packages&query=\(.))") |
join("\n");
def get_title(s; xs):
s + " (" + (xs | length | tostring) + ")";
def section(title; xs):
"<details> <summary>" + get_title(title; xs) + "</summary>\n\n" + itemize_packages(xs) + "</details>";
def fallback_document(content; n):
if content | utf8bytelength > n then
get_title("Added packages"; .attrdiff.added) + "\n\n" +
get_title("Removed packages"; .attrdiff.removed) + "\n\n" +
get_title("Changed packages"; .attrdiff.changed)
else content
end;
# we truncate the list to stay below the GitHub limit of 1MB per step summary.
fallback_document(
section("Added packages"; .attrdiff.added) + "\n\n" +
section("Removed packages"; .attrdiff.removed) + "\n\n" +
section("Changed packages"; .attrdiff.changed); 1000 * 1000
)

View File

@@ -1,213 +0,0 @@
{ lib, ... }:
rec {
# Borrowed from https://github.com/NixOS/nixpkgs/pull/355616
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
/*
Converts a `packagePlatformPath` into a `packagePlatformAttr`
Turns
"hello.aarch64-linux"
into
{
name = "hello";
platform = "aarch64-linux";
}
*/
convertToPackagePlatformAttr =
packagePlatformPath:
let
# python312Packages.numpy.aarch64-linux -> ["python312Packages" "numpy" "aarch64-linux"]
splittedPath = lib.splitString "." packagePlatformPath;
# ["python312Packages" "numpy" "aarch64-linux"] -> ["python312Packages" "numpy"]
packagePath = lib.sublist 0 (lib.length splittedPath - 1) splittedPath;
# "python312Packages.numpy"
name = lib.concatStringsSep "." packagePath;
in
if name == "" then
null
else
{
# python312Packages.numpy
inherit name;
# "aarch64-linux"
platform = lib.last splittedPath;
};
/*
Converts a list of `packagePlatformPath`s into a list of `packagePlatformAttr`s
Turns
[
"hello.aarch64-linux"
"hello.x86_64-linux"
"hello.aarch64-darwin"
"hello.x86_64-darwin"
"bye.x86_64-darwin"
"bye.aarch64-darwin"
"release-checks" <- Will be dropped
]
into
[
{ name = "hello"; platform = "aarch64-linux"; }
{ name = "hello"; platform = "x86_64-linux"; }
{ name = "hello"; platform = "aarch64-darwin"; }
{ name = "hello"; platform = "x86_64-darwin"; }
{ name = "bye"; platform = "aarch64-darwin"; }
{ name = "bye"; platform = "x86_64-darwin"; }
]
*/
convertToPackagePlatformAttrs =
packagePlatformPaths:
builtins.filter (x: x != null) (builtins.map convertToPackagePlatformAttr packagePlatformPaths);
/*
Converts a list of `packagePlatformPath`s directly to a list of (unique) package names
Turns
[
"hello.aarch64-linux"
"hello.x86_64-linux"
"hello.aarch64-darwin"
"hello.x86_64-darwin"
"bye.x86_64-darwin"
"bye.aarch64-darwin"
]
into
[
"hello"
"bye"
]
*/
extractPackageNames =
packagePlatformPaths:
let
packagePlatformAttrs = convertToPackagePlatformAttrs (uniqueStrings packagePlatformPaths);
in
uniqueStrings (builtins.map (p: p.name) packagePlatformAttrs);
/*
Computes the key difference between two attrs
{
added: [ <keys only in the second object> ],
removed: [ <keys only in the first object> ],
changed: [ <keys with different values between the two objects> ],
}
*/
diff =
let
filterKeys = cond: attrs: lib.attrNames (lib.filterAttrs cond attrs);
in
old: new: {
added = filterKeys (n: _: !(old ? ${n})) new;
removed = filterKeys (n: _: !(new ? ${n})) old;
changed = filterKeys (
n: v:
# Filter out attributes that don't exist anymore
(new ? ${n})
# Filter out attributes that are the same as the new value
&& (v != (new.${n}))
) old;
};
/*
Group a list of `packagePlatformAttr`s by platforms
Turns
[
{ name = "hello"; platform = "aarch64-linux"; }
{ name = "hello"; platform = "x86_64-linux"; }
{ name = "hello"; platform = "aarch64-darwin"; }
{ name = "hello"; platform = "x86_64-darwin"; }
{ name = "bye"; platform = "aarch64-darwin"; }
{ name = "bye"; platform = "x86_64-darwin"; }
]
into
{
aarch64-linux = [ "hello" ];
x86_64-linux = [ "hello" ];
aarch64-darwin = [ "hello" "bye" ];
x86_64-darwin = [ "hello" "bye" ];
}
*/
groupByPlatform =
packagePlatformAttrs:
let
packagePlatformAttrsByPlatform = builtins.groupBy (p: p.platform) packagePlatformAttrs;
extractPackageNames = map (p: p.name);
in
lib.mapAttrs (_: extractPackageNames) packagePlatformAttrsByPlatform;
# Turns
# [
# { name = "hello"; platform = "aarch64-linux"; }
# { name = "hello"; platform = "x86_64-linux"; }
# { name = "hello"; platform = "aarch64-darwin"; }
# { name = "hello"; platform = "x86_64-darwin"; }
# { name = "bye"; platform = "aarch64-darwin"; }
# { name = "bye"; platform = "x86_64-darwin"; }
# ]
#
# into
#
# {
# linux = [ "hello" ];
# darwin = [ "hello" "bye" ];
# }
groupByKernel =
packagePlatformAttrs:
let
filterKernel =
kernel:
builtins.attrNames (
builtins.groupBy (p: p.name) (
builtins.filter (p: lib.hasSuffix kernel p.platform) packagePlatformAttrs
)
);
in
lib.genAttrs [ "linux" "darwin" ] filterKernel;
/*
Maps an attrs of `kernel - rebuild counts` mappings to a list of labels
Turns
{
linux = 56;
darwin = 8;
}
into
[
"10.rebuild-darwin: 1-10"
"10.rebuild-linux: 11-100"
]
*/
getLabels = lib.mapAttrsToList (
kernel: rebuildCount:
let
number =
if rebuildCount == 0 then
"0"
else if rebuildCount <= 10 then
"1-10"
else if rebuildCount <= 100 then
"11-100"
else if rebuildCount <= 500 then
"101-500"
else if rebuildCount <= 1000 then
"501-1000"
else if rebuildCount <= 2500 then
"1001-2500"
else if rebuildCount <= 5000 then
"2501-5000"
else
"5001+";
in
"10.rebuild-${kernel}: ${number}"
);
}

View File

@@ -1,294 +0,0 @@
{
lib,
runCommand,
writeShellScript,
writeText,
linkFarm,
time,
procps,
nixVersions,
jq,
sta,
}:
let
nixpkgs =
with lib.fileset;
toSource {
root = ../..;
fileset = unions (
map (lib.path.append ../..) [
"default.nix"
"doc"
"lib"
"maintainers"
"nixos"
"pkgs"
".version"
"ci/supportedSystems.nix"
]
);
};
nix = nixVersions.nix_2_24;
supportedSystems = import ../supportedSystems.nix;
attrpathsSuperset =
runCommand "attrpaths-superset.json"
{
src = nixpkgs;
nativeBuildInputs = [
nix
time
];
env.supportedSystems = builtins.toJSON supportedSystems;
passAsFile = [ "supportedSystems" ];
}
''
export NIX_STATE_DIR=$(mktemp -d)
mkdir $out
export GC_INITIAL_HEAP_SIZE=4g
command time -f "Attribute eval done [%MKB max resident, %Es elapsed] %C" \
nix-instantiate --eval --strict --json --show-trace \
"$src/pkgs/top-level/release-attrpaths-superset.nix" \
-A paths \
-I "$src" \
--option restrict-eval true \
--option allow-import-from-derivation false \
--arg enableWarnings false > $out/paths.json
mv "$supportedSystemsPath" $out/systems.json
'';
singleSystem =
{
# The system to evaluate.
# Note that this is intentionally not called `system`,
# because `--argstr system` would only be passed to the ci/default.nix file!
evalSystem,
# The path to the `paths.json` file from `attrpathsSuperset`
attrpathFile,
# The number of attributes per chunk, see ./README.md for more info.
chunkSize,
checkMeta ? true,
includeBroken ? true,
# Whether to just evaluate a single chunk for quick testing
quickTest ? false,
}:
let
singleChunk = writeShellScript "single-chunk" ''
set -euo pipefail
chunkSize=$1
myChunk=$2
system=$3
outputDir=$4
export NIX_SHOW_STATS=1
export NIX_SHOW_STATS_PATH="$outputDir/stats/$myChunk"
echo "Chunk $myChunk on $system start"
set +e
command time -f "Chunk $myChunk on $system done [%MKB max resident, %Es elapsed] %C" \
nix-env -f "${nixpkgs}/pkgs/top-level/release-attrpaths-parallel.nix" \
--option restrict-eval true \
--option allow-import-from-derivation false \
--query --available \
--no-name --attr-path --out-path \
--show-trace \
--arg chunkSize "$chunkSize" \
--arg myChunk "$myChunk" \
--arg attrpathFile "${attrpathFile}" \
--arg systems "[ \"$system\" ]" \
--arg checkMeta ${lib.boolToString checkMeta} \
--arg includeBroken ${lib.boolToString includeBroken} \
-I ${nixpkgs} \
-I ${attrpathFile} \
> "$outputDir/result/$myChunk"
exitCode=$?
set -e
if (( exitCode != 0 )); then
echo "Evaluation failed with exit code $exitCode"
# This immediately halts all xargs processes
kill $PPID
fi
'';
in
runCommand "nixpkgs-eval-${evalSystem}"
{
nativeBuildInputs = [
nix
time
procps
jq
];
env = {
inherit evalSystem chunkSize;
};
}
''
export NIX_STATE_DIR=$(mktemp -d)
nix-store --init
echo "System: $evalSystem"
cores=$NIX_BUILD_CORES
echo "Cores: $cores"
attrCount=$(jq length "${attrpathFile}")
echo "Attribute count: $attrCount"
echo "Chunk size: $chunkSize"
# Same as `attrCount / chunkSize` but rounded up
chunkCount=$(( (attrCount - 1) / chunkSize + 1 ))
echo "Chunk count: $chunkCount"
mkdir $out
# Record and print stats on free memory and swap in the background
(
while true; do
availMemory=$(free -b | grep Mem | awk '{print $7}')
freeSwap=$(free -b | grep Swap | awk '{print $4}')
echo "Available memory: $(( availMemory / 1024 / 1024 )) MiB, free swap: $(( freeSwap / 1024 / 1024 )) MiB"
if [[ ! -f "$out/min-avail-memory" ]] || (( availMemory < $(<$out/min-avail-memory) )); then
echo "$availMemory" > $out/min-avail-memory
fi
if [[ ! -f $out/min-free-swap ]] || (( availMemory < $(<$out/min-free-swap) )); then
echo "$freeSwap" > $out/min-free-swap
fi
sleep 4
done
) &
seq_end=$(( chunkCount - 1 ))
${lib.optionalString quickTest ''
seq_end=0
''}
chunkOutputDir=$(mktemp -d)
mkdir "$chunkOutputDir"/{result,stats}
seq -w 0 "$seq_end" |
command time -f "%e" -o "$out/total-time" \
xargs -I{} -P"$cores" \
${singleChunk} "$chunkSize" {} "$evalSystem" "$chunkOutputDir"
if (( chunkSize * chunkCount != attrCount )); then
# A final incomplete chunk would mess up the stats, don't include it
rm "$chunkOutputDir"/stats/"$seq_end"
fi
# Make sure the glob doesn't break when there's no files
shopt -s nullglob
cat "$chunkOutputDir"/result/* > $out/paths
cat "$chunkOutputDir"/stats/* > $out/stats.jsonstream
'';
combine =
{
resultsDir,
}:
runCommand "combined-result"
{
nativeBuildInputs = [
jq
sta
];
}
''
mkdir -p $out
# Transform output paths to JSON
cat ${resultsDir}/*/paths |
jq --sort-keys --raw-input --slurp '
split("\n") |
map(select(. != "") | split(" ") | map(select(. != ""))) |
map(
{
key: .[0],
value: .[1] | split(";") | map(split("=") |
if length == 1 then
{ key: "out", value: .[0] }
else
{ key: .[0], value: .[1] }
end) | from_entries}
) | from_entries
' > $out/outpaths.json
# Computes min, mean, error, etc. for a list of values and outputs a JSON from that
statistics() {
local stat=$1
sta --transpose |
jq --raw-input --argjson stat "$stat" -n '
[
inputs |
split("\t") |
{ key: .[0], value: (.[1] | fromjson) }
] |
from_entries |
{
key: ($stat | join(".")),
value: .
}'
}
# Gets all available number stats (without .sizes because those are constant and not interesting)
readarray -t stats < <(jq -cs '.[0] | del(.sizes) | paths(type == "number")' ${resultsDir}/*/stats.jsonstream)
# Combines the statistics from all evaluations
{
echo "{ \"key\": \"minAvailMemory\", \"value\": $(cat ${resultsDir}/*/min-avail-memory | sta --brief --min) }"
echo "{ \"key\": \"minFreeSwap\", \"value\": $(cat ${resultsDir}/*/min-free-swap | sta --brief --min) }"
cat ${resultsDir}/*/total-time | statistics '["totalTime"]'
for stat in "''${stats[@]}"; do
cat ${resultsDir}/*/stats.jsonstream |
jq --argjson stat "$stat" 'getpath($stat)' |
statistics "$stat"
done
} |
jq -s from_entries > $out/stats.json
'';
compare = import ./compare {
inherit
lib
jq
runCommand
writeText
supportedSystems
;
};
full =
{
# Whether to evaluate on a specific set of systems, by default all are evaluated
evalSystems ? if quickTest then [ "x86_64-linux" ] else supportedSystems,
# The number of attributes per chunk, see ./README.md for more info.
chunkSize,
quickTest ? false,
}:
let
results = linkFarm "results" (
map (evalSystem: {
name = evalSystem;
path = singleSystem {
inherit quickTest evalSystem chunkSize;
attrpathFile = attrpathsSuperset + "/paths.json";
};
}) evalSystems
);
in
combine {
resultsDir = results;
};
in
{
inherit
attrpathsSuperset
singleSystem
combine
compare
# The above three are used by separate VMs in a GitHub workflow,
# while the below is intended for testing on a single local machine
full
;
}

View File

@@ -1,4 +1,4 @@
{
"rev": "929116e316068c7318c54eb4d827f7d9756d5e9c",
"sha256": "1am61kcakn9j47435k4cgsarvypb8klv4avszxza0jn362hp3ck8"
"rev": "4de4818c1ffa76d57787af936e8a23648bda6be4",
"sha256": "0l3b9jr5ydzqgvd10j12imc9jqb6jv5v2bdi1gyy5cwkwplfay67"
}

View File

@@ -1,9 +1,7 @@
# Trusted development branches:
# These generally require PRs to update and are built by Hydra.
# Keep this synced with the branches in .github/workflows/eval.yml
master
staging
release-*
staging-*
haskell-updates
python-updates

View File

@@ -1,6 +0,0 @@
[
"aarch64-linux"
"aarch64-darwin"
"x86_64-linux"
"x86_64-darwin"
]

View File

@@ -1,8 +1,6 @@
let
requiredVersion = import ./lib/minver.nix;
in
let requiredVersion = import ./lib/minver.nix; in
if !builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
abort ''

View File

@@ -21,7 +21,7 @@ Rendered documentation:
- [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/)
- [Stable (from latest release)](https://nixos.org/manual/nixpkgs/stable/)
The rendering tool is [nixos-render-docs](../pkgs/by-name/ni/nixos-render-docs), sometimes abbreviated `nrd`.
The rendering tool is [nixos-render-docs](../pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs), sometimes abbreviated `nrd`.
## Contributing to this documentation
@@ -42,12 +42,6 @@ It is a daemon, that:
2. HTTP serves the manual, injecting a script that triggers reload on changes
3. opens the manual in the default browser
### Testing redirects
Once you have a successful build, you can open the relevant HTML (path mentioned above) in a browser along with the anchor, and observe the redirection.
Note that if you already loaded the page and *then* input the anchor, you will need to perform a reload. This is because browsers do not re-run client JS code when only the anchor has changed.
## Syntax
As per [RFC 0072](https://github.com/NixOS/rfcs/pull/72), all new documentation content should be written in [CommonMark](https://commonmark.org/) Markdown dialect.
@@ -95,7 +89,6 @@ Inlining HTML is not allowed. Parts of the documentation gets rendered to variou
#### Roles
If you want to link to a man page, you can use `` {manpage}`nix.conf(5)` ``. The references will turn into links when a mapping exists in [`doc/manpage-urls.json`](./manpage-urls.json).
Please keep the `manpage-urls.json` file alphabetically sorted.
A few markups for other kinds of literals are also available:

View File

@@ -755,66 +755,25 @@ Used with Subversion. Expects `url` to a Subversion directory, `rev`, and `hash`
Used with Git. Expects `url` to a Git repo, `rev`, and `hash`. `rev` in this case can be full the git commit id (SHA1 hash) or a tag name like `refs/tags/v1.0`.
If you want to fetch a tag you should pass the `tag` parameter instead of `rev` which has the same effect as setting `rev = "refs/tags"/${version}"`.
This is safer than just setting `rev = version` w.r.t. possible branch and tag name conflicts.
Additionally, the following optional arguments can be given: `fetchSubmodules = true` makes `fetchgit` also fetch the submodules of a repository. If `deepClone` is set to true, the entire repository is cloned as opposing to just creating a shallow clone. `deepClone = true` also implies `leaveDotGit = true` which means that the `.git` directory of the clone won't be removed after checkout.
Additionally, the following optional arguments can be given:
If only parts of the repository are needed, `sparseCheckout` can be used. This will prevent git from fetching unnecessary blobs from server, see [git sparse-checkout](https://git-scm.com/docs/git-sparse-checkout) for more information:
*`fetchSubmodules`* (Boolean)
```nix
{ stdenv, fetchgit }:
: Whether to also fetch the submodules of a repository.
*`fetchLFS`* (Boolean)
: Whether to fetch LFS objects.
*`postFetch`* (String)
: Shell code executed after the file has been fetched successfully.
This can do things like check or transform the file.
*`leaveDotGit`* (Boolean)
: Whether the `.git` directory of the clone should *not* be removed after checkout.
Be warned though that the git repository format is not stable and this flag is therefore not suitable for actual use by itself.
Only use this for testing purposes or in conjunction with removing the `.git` directory in `postFetch`.
*`deepClone`* (Boolean)
: Clone the entire repository as opposing to just creating a shallow clone.
This implies `leaveDotGit`.
*`sparseCheckout`* (List of String)
: Prevent git from fetching unnecessary blobs from server.
This is useful if only parts of the repository are needed.
::: {.example #ex-fetchgit-sparseCheckout}
# Use `sparseCheckout` to only include some directories:
```nix
{ stdenv, fetchgit }:
stdenv.mkDerivation {
name = "hello";
src = fetchgit {
url = "https://...";
sparseCheckout = [
"directory/to/be/included"
"another/directory"
];
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
}
```
:::
See [git sparse-checkout](https://git-scm.com/docs/git-sparse-checkout) for more information.
Some additional parameters for niche use-cases can be found listed in the function parameters in the declaration of `fetchgit`: `pkgs/build-support/fetchgit/default.nix`.
Future parameters additions might also happen without immediately being documented here.
stdenv.mkDerivation {
name = "hello";
src = fetchgit {
url = "https://...";
sparseCheckout = [
"directory/to/be/included"
"another/directory"
];
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
}
```
## `fetchfossil` {#fetchfossil}
@@ -836,7 +795,7 @@ A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are m
## `fetchFromGitHub` {#fetchfromgithub}
`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. If you need to fetch a tag however, you should prefer to use the `tag` parameter which achieves this in a safer way with less boilerplate. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred.
`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred.
To use a different GitHub instance, use `githubBase` (defaults to `"github.com"`).

View File

@@ -881,7 +881,7 @@ dockerTools.pullImage {
imageDigest = "sha256:b8ea88f763f33dfda2317b55eeda3b1a4006692ee29e60ee54ccf6d07348c598";
finalImageName = "nix";
finalImageTag = "2.19.3";
hash = "sha256-zRwlQs1FiKrvHPaf8vWOR/Tlp1C5eLn1d9pE4BZg3oA=";
sha256 = "zRwlQs1FiKrvHPaf8vWOR/Tlp1C5eLn1d9pE4BZg3oA=";
}
```
:::
@@ -898,7 +898,7 @@ dockerTools.pullImage {
imageDigest = "sha256:24a23053f29266fb2731ebea27f915bb0fb2ae1ea87d42d890fe4e44f2e27c5d";
finalImageName = "etcd";
finalImageTag = "v3.5.11";
hash = "sha256-Myw+85f2/EVRyMB3axECdmQ5eh9p1q77FWYKy8YpRWU=";
sha256 = "Myw+85f2/EVRyMB3axECdmQ5eh9p1q77FWYKy8YpRWU=";
}
```
:::
@@ -922,7 +922,7 @@ Writing manifest to image destination
{
imageName = "nixos/nix";
imageDigest = "sha256:498fa2d7f2b5cb3891a4edf20f3a8f8496e70865099ba72540494cd3e2942634";
hash = "sha256-OEgs3uRPMb4Y629FJXAWZW9q9LqHS/A/GUqr3K5wzOA=";
sha256 = "1q6cf2pdrasa34zz0jw7pbs6lvv52rq2aibgxccbwcagwkg2qj1q";
finalImageName = "nixos/nix";
finalImageTag = "latest";
}

View File

@@ -364,7 +364,7 @@ including `nativeBuildInputs` to specify dependencies available to the `script`.
```nix
testers.runCommand {
name = "access-the-internet";
script = ''
command = ''
curl -o /dev/null https://example.com
touch $out
'';

View File

@@ -754,6 +754,10 @@ This creates a derivation with a directory structure like the following:
...
```
## `writeReferencesToFile` {#trivial-builder-writeReferencesToFile}
Deprecated. Use [`writeClosure`](#trivial-builder-writeClosure) instead.
## `writeClosure` {#trivial-builder-writeClosure}
Given a list of [store paths](https://nixos.org/manual/nix/stable/glossary#gloss-store-path) (or string-like expressions coercible to store paths), write their collective [closure](https://nixos.org/manual/nix/stable/glossary#gloss-closure) to a text file.

View File

@@ -95,7 +95,7 @@ stdenvNoCC.mkDerivation {
fileset = ../../lib;
};
nativeBuildInputs = [
buildInputs = [
nixdoc
nix
];

View File

@@ -1,82 +1,74 @@
{
nixpkgsPath,
revision,
libsetsJSON,
}:
{ nixpkgsPath, revision, libsetsJSON }:
let
lib = import (nixpkgsPath + "/lib");
libsets = builtins.fromJSON libsetsJSON;
libDefPos =
prefix: set:
builtins.concatMap (
name:
[
{
name = builtins.concatStringsSep "." (prefix ++ [ name ]);
location = builtins.unsafeGetAttrPos name set;
}
]
++ lib.optionals (builtins.length prefix == 0 && builtins.isAttrs set.${name}) (
libDefPos (prefix ++ [ name ]) set.${name}
)
) (builtins.attrNames set);
libDefPos = prefix: set:
builtins.concatMap
(name: [{
name = builtins.concatStringsSep "." (prefix ++ [name]);
location = builtins.unsafeGetAttrPos name set;
}] ++ lib.optionals
(builtins.length prefix == 0 && builtins.isAttrs set.${name})
(libDefPos (prefix ++ [name]) set.${name})
) (builtins.attrNames set);
libset =
toplib:
builtins.map (subsetname: {
subsetname = subsetname;
functions = libDefPos [ ] toplib.${subsetname};
}) (builtins.map (x: x.name) libsets);
libset = toplib:
builtins.map
(subsetname: {
subsetname = subsetname;
functions = libDefPos [] toplib.${subsetname};
})
(builtins.map (x: x.name) libsets);
flattenedLibSubset =
{ subsetname, functions }:
builtins.map (fn: {
flattenedLibSubset = { subsetname, functions }:
builtins.map
(fn: {
name = "lib.${subsetname}.${fn.name}";
value = fn.location;
}) functions;
})
functions;
locatedlibsets = libs: builtins.map flattenedLibSubset (libset libs);
removeFilenamePrefix =
prefix: filename:
removeFilenamePrefix = prefix: filename:
let
prefixLen = (builtins.stringLength prefix) + 1; # +1 to remove the leading /
prefixLen = (builtins.stringLength prefix) + 1; # +1 to remove the leading /
filenameLen = builtins.stringLength filename;
substr = builtins.substring prefixLen filenameLen filename;
in
substr;
in substr;
removeNixpkgs = removeFilenamePrefix (builtins.toString nixpkgsPath);
liblocations = builtins.filter (elem: elem.value != null) (lib.lists.flatten (locatedlibsets lib));
liblocations =
builtins.filter
(elem: elem.value != null)
(lib.lists.flatten
(locatedlibsets lib));
fnLocationRelative =
{ name, value }:
fnLocationRelative = { name, value }:
{
inherit name;
value = value // {
file = removeNixpkgs value.file;
};
value = value // { file = removeNixpkgs value.file; };
};
relativeLocs = (builtins.map fnLocationRelative liblocations);
sanitizeId = builtins.replaceStrings [ "'" ] [ "-prime" ];
sanitizeId = builtins.replaceStrings
[ "'" ]
[ "-prime" ];
urlPrefix = "https://github.com/NixOS/nixpkgs/blob/${revision}";
jsonLocs = builtins.listToAttrs (
builtins.map (
{ name, value }:
{
jsonLocs = builtins.listToAttrs
(builtins.map
({ name, value }: {
name = sanitizeId name;
value =
let
text = "${value.file}:${builtins.toString value.line}";
target = "${urlPrefix}/${value.file}#L${builtins.toString value.line}";
in
"[${text}](${target}) in `<nixpkgs>`";
}
) relativeLocs
);
"[${text}](${target}) in `<nixpkgs>`";
})
relativeLocs);
in
jsonLocs

View File

@@ -9,8 +9,6 @@
mkShellNoCC,
documentation-highlighter,
nixos-render-docs,
nixos-render-docs-redirects,
writeShellScriptBin,
nixpkgs ? { },
}:
@@ -33,7 +31,6 @@ stdenvNoCC.mkDerivation (
../anchor-use.js
../anchor.min.js
../manpage-urls.json
../redirects.json
];
};
@@ -65,7 +62,6 @@ stdenvNoCC.mkDerivation (
nixos-render-docs manual html \
--manpage-urls ./manpage-urls.json \
--redirects ./redirects.json \
--revision ${nixpkgs.rev or "master"} \
--stylesheet style.css \
--stylesheet highlightjs/mono-blue.css \
@@ -107,14 +103,8 @@ stdenvNoCC.mkDerivation (
buildArgs = "./.";
open = "/share/doc/nixpkgs/manual.html";
};
nixos-render-docs-redirects' = writeShellScriptBin "redirects" "${lib.getExe nixos-render-docs-redirects} --file ${toString ../redirects.json} $@";
in
mkShellNoCC {
packages = [
devmode'
nixos-render-docs-redirects'
];
};
mkShellNoCC { packages = [ devmode' ]; };
tests.manpage-urls = callPackage ../tests/manpage-urls.nix { };
};

View File

@@ -14,13 +14,15 @@ In Nixpkgs, `cargo-tauri.hook` overrides the default build and install phases.
rustPlatform,
fetchNpmDeps,
cargo-tauri,
darwin,
glib-networking,
libsoup,
nodejs,
npmHooks,
openssl,
pkg-config,
webkitgtk_4_1,
wrapGAppsHook4,
webkitgtk_4_0,
wrapGAppsHook3,
}:
rustPlatform.buildRustPackage rec {
@@ -45,15 +47,25 @@ rustPlatform.buildRustPackage rec {
# Make sure we can find our libraries
pkg-config
wrapGAppsHook4
wrapGAppsHook3
];
buildInputs =
[ openssl ]
++ lib.optionals stdenv.hostPlatform.isLinux [
glib-networking # Most Tauri apps need networking
webkitgtk_4_1
];
libsoup
webkitgtk_4_0
]
++ lib.optionals stdenv.hostPlatform.isDarwin (
with darwin.apple_sdk.frameworks;
[
AppKit
CoreServices
Security
WebKit
]
);
# Set our Tauri source directory
cargoRoot = "src-tauri";

View File

@@ -60,13 +60,13 @@ all the other eggs:
```nix
let
myChickenPackages = pkgs.chickenPackages.overrideScope (self: super: {
myChickenPackages = pkgs.chickenPackages.overrideScope' (self: super: {
# The chicken package itself can be overridden to effect the whole ecosystem.
# chicken = super.chicken.overrideAttrs {
# src = ...
# };
chickenEggs = super.chickenEggs.overrideScope (eggself: eggsuper: {
chickenEggs = super.chickenEggs.overrideScope' (eggself: eggsuper: {
srfi-180 = eggsuper.srfi-180.overrideAttrs {
# path to a local copy of srfi-180
src = <...>;

View File

@@ -27,48 +27,42 @@ mkShell {
name = "dotnet-env";
packages = [
(with dotnetCorePackages; combinePackages [
sdk_8_0
sdk_9_0
sdk_6_0
sdk_7_0
])
];
}
```
This will produce a dotnet installation that has the dotnet 8.0 9.0 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output:
This will produce a dotnet installation that has the dotnet 6.0 7.0 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output:
```ShellSession
$ dotnet --info
.NET SDK:
Version: 9.0.100
Commit: 59db016f11
Workload version: 9.0.100-manifests.3068a692
MSBuild version: 17.12.7+5b8665660
Version: 7.0.202
Commit: 6c74320bc3
Runtime Environment:
Środowisko uruchomieniowe:
OS Name: nixos
OS Version: 25.05
OS Version: 23.05
OS Platform: Linux
RID: linux-x64
Base Path: /nix/store/a03c70i7x6rjdr6vikczsp5ck3v6rixh-dotnet-sdk-9.0.100/share/dotnet/sdk/9.0.100/
.NET workloads installed:
There are no installed workloads to display.
Configured to use loose manifests when installing new manifests.
Base Path: /nix/store/n2pm44xq20hz7ybsasgmd7p3yh31gnh4-dotnet-sdk-7.0.202/sdk/7.0.202/
Host:
Version: 9.0.0
Version: 7.0.4
Architecture: x64
Commit: 9d5a6a9aa4
Commit: 0a396acafe
.NET SDKs installed:
8.0.404 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/sdk]
9.0.100 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/sdk]
6.0.407 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/sdk]
7.0.202 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.11 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.0 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.11 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.0 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.AspNetCore.App 6.0.15 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.4 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.15 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.4 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.NETCore.App]
Other architectures found:
None
@@ -99,9 +93,9 @@ The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given
To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions:
* `projectFile` is used for specifying the dotnet project file, relative to the source root. These have `.sln` (entire solution) or `.csproj` (single project) file extensions. This can be a list of multiple projects as well. When omitted, will attempt to find and build the solution (`.sln`). If running into problems, make sure to set it to a file (or a list of files) with the `.csproj` extension - building applications as entire solutions is not fully supported by the .NET CLI.
* `nugetDeps` should be a path to a JSON file, a path to a nix file (deprecated), a derivation, or a list of derivations. A `deps.json` file can be generated using the script attached to `passthru.fetch-deps`, which is the preferred method. All `nugetDeps` packages are added to `buildInputs`.
* `nugetDeps` takes either a path to a `deps.nix` file, or a derivation. The `deps.nix` file can be generated using the script attached to `passthru.fetch-deps`. For compatibility, if the argument is a list of derivations, they will be added to `buildInputs`.
::: {.note}
For more detail about managing the `deps.json` file, see [Generating and updating NuGet dependencies](#generating-and-updating-nuget-dependencies)
For more detail about managing the `deps.nix` file, see [Generating and updating NuGet dependencies](#generating-and-updating-nuget-dependencies)
:::
* `packNupkg` is used to pack project as a `nupkg`, and installs it to `$out/share`. If set to `true`, the derivation can be used as a dependency for another dotnet project by adding it to `buildInputs`.
@@ -133,7 +127,7 @@ For more detail about managing the `deps.json` file, see [Generating and updatin
* `dotnetPackFlags` can be used to pass flags to `dotnet pack`. Used only if `packNupkg` is set to `true`.
* `dotnetFlags` can be used to pass flags to all of the above phases.
When packaging a new application, you need to fetch its dependencies. Create an empty `deps.json`, set `nugetDeps = ./deps.json`, then run `nix-build -A package.fetch-deps` to generate a script that will build the lockfile for you.
When packaging a new application, you need to fetch its dependencies. Create an empty `deps.nix`, set `nugetDeps = ./deps.nix`, then run `nix-build -A package.fetch-deps` to generate a script that will build the lockfile for you.
Here is an example `default.nix`, using some of the previously discussed arguments:
```nix
@@ -148,12 +142,12 @@ in buildDotnetModule rec {
src = ./.;
projectFile = "src/project.sln";
nugetDeps = ./deps.json; # see "Generating and updating NuGet dependencies" section for details
nugetDeps = ./deps.nix; # see "Generating and updating NuGet dependencies" section for details
buildInputs = [ referencedProject ]; # `referencedProject` must contain `nupkg` in the folder structure.
dotnet-sdk = dotnetCorePackages.sdk_8_0;
dotnet-runtime = dotnetCorePackages.runtime_8_0;
dotnet-sdk = dotnetCorePackages.sdk_6_0;
dotnet-runtime = dotnetCorePackages.runtime_6_0;
executables = [ "foo" ]; # This wraps "$out/lib/$pname/foo" to `$out/bin/foo`.
executables = []; # Don't install any executables.
@@ -225,7 +219,7 @@ buildDotnetGlobalTool {
## Generating and updating NuGet dependencies {#generating-and-updating-nuget-dependencies}
When writing a new expression, you can use the generated `fetch-deps` script to initialise the lockfile.
After setting `nugetDeps` to the desired location of the lockfile (e.g. `./deps.json`),
After setting `nugetDeps` to the desired location of the lockfile (e.g. `./deps.nix`),
build the script with `nix-build -A package.fetch-deps` and then run the result.
(When the root attr is your package, it's simply `nix-build -A fetch-deps`.)
@@ -236,54 +230,31 @@ the upstream repository and you are inside it.
```bash
$ dotnet restore --packages out
Determining projects to restore...
Restored /home/ggg/git-credential-manager/src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj (in 1.21 sec).
Restored /home/lychee/Celeste64/Celeste64.csproj (in 1.21 sec).
```
Next, use `nuget-to-json` tool provided in nixpkgs to generate a lockfile to `deps.json` from
Next, use `nuget-to-nix` tool provided in nixpkgs to generate a lockfile to `deps.nix` from
the packages inside the `out` directory.
```bash
$ nuget-to-json out > deps.json
$ nuget-to-nix out > deps.nix
```
Which `nuget-to-json` will generate an output similar to below
```json
[
{
"pname": "Avalonia",
"version": "11.1.3",
"hash": "sha256-kz+k/vkuWoL0XBvRT8SadMOmmRCFk9W/J4k/IM6oYX0="
},
{
"pname": "Avalonia.Angle.Windows.Natives",
"version": "2.1.22045.20230930",
"hash": "sha256-RxPcWUT3b/+R3Tu5E5ftpr5ppCLZrhm+OTsi0SwW3pc="
},
{
"pname": "Avalonia.BuildServices",
"version": "0.0.29",
"hash": "sha256-WPHRMNowRnYSCh88DWNBCltWsLPyOfzXGzBqLYE7tRY="
},
// ...
{
"pname": "System.Runtime.CompilerServices.Unsafe",
"version": "6.0.0",
"hash": "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I="
},
{
"pname": "System.Security.Cryptography.ProtectedData",
"version": "4.5.0",
"hash": "sha256-Z+X1Z2lErLL7Ynt2jFszku6/IgrngO3V1bSfZTBiFIc="
},
{
"pname": "Tmds.DBus.Protocol",
"version": "0.16.0",
"hash": "sha256-vKYEaa1EszR7alHj48R8G3uYArhI+zh2ZgiBv955E98="
}
Which `nuget-to-nix` will generate an output similar to below
```nix
{ fetchNuGet }: [
(fetchNuGet { pname = "FosterFramework"; version = "0.1.15-alpha"; hash = "sha256-lM6eYgOGjl1fx6WFD7rnRi/YAQieM0mx60h0p5dr+l8="; })
(fetchNuGet { pname = "Microsoft.AspNetCore.App.Runtime.linux-x64"; version = "8.0.1"; hash = "sha256-QbUQXjCzr8j8u/5X0af9jE++EugdoxMhT08F49MZX74="; })
(fetchNuGet { pname = "Microsoft.NET.ILLink.Tasks"; version = "8.0.1"; hash = "sha256-SopZpGaZ48/8dpUwDFDM3ix+g1rP4Yqs1PGuzRp+K7c="; })
(fetchNuGet { pname = "Microsoft.NETCore.App.Runtime.linux-x64"; version = "8.0.1"; hash = "sha256-jajBI5GqG2IIcsIMgxTHfXbMapoXrZGl/EEhShwYq7w="; })
(fetchNuGet { pname = "SharpGLTF.Core"; version = "1.0.0-alpha0031"; hash = "sha256-Bs4baD5wNIH6wAbGK4Xaem0i3luQkOQs37izBWdFx1I="; })
(fetchNuGet { pname = "SharpGLTF.Runtime"; version = "1.0.0-alpha0031"; hash = "sha256-TwJO6b8ubmwBQh6NyHha8+JT5zHDJ4dROBbsEbUaa1M="; })
(fetchNuGet { pname = "Sledge.Formats"; version = "1.2.2"; hash = "sha256-0Ddhuwpu3wwIzA4NuPaEVdMkx6tUukh8uKD6nKoxFPg="; })
(fetchNuGet { pname = "Sledge.Formats.Map"; version = "1.1.5"; hash = "sha256-hkYJ2iWIz7vhPWlDOw2fvTenlh+4/D/37Z71tCEwnK8="; })
(fetchNuGet { pname = "System.Numerics.Vectors"; version = "4.5.0"; hash = "sha256-qdSTIFgf2htPS+YhLGjAGiLN8igCYJnCCo6r78+Q+c8="; })
]
```
Finally, you move the `deps.json` file to the appropriate location to be used by `nugetDeps`, then you're all set!
Finally, you move the `deps.nix` file to the appropriate location to be used by `nugetDeps`, then you're all set!
If you ever need to update the dependencies of a package, you instead do

View File

@@ -7,6 +7,32 @@ The function `buildGoModule` builds Go programs managed with Go modules. It buil
- An intermediate fetcher derivation called `goModules`. This derivation will be used to fetch all the dependencies of the Go module.
- A final derivation will use the output of the intermediate derivation to build the binaries and produce the final output.
### Attributes of `buildGoModule` {#buildgomodule-parameters}
The `buildGoModule` function accepts the following parameters in addition to the [attributes accepted by both Go builders](#ssec-go-common-attributes):
- `vendorHash`: is the hash of the output of the intermediate fetcher derivation (the dependencies of the Go modules).
`vendorHash` can be set to `null`.
In that case, rather than fetching the dependencies, the dependencies already vendored in the `vendor` directory of the source repo will be used.
To avoid updating this field when dependencies change, run `go mod vendor` in your source repo and set `vendorHash = null;`.
You can read more about [vendoring in the Go documentation](https://go.dev/ref/mod#vendoring).
To obtain the actual hash, set `vendorHash = lib.fakeHash;` and run the build ([more details here](#sec-source-hashes)).
- `proxyVendor`: If `true`, the intermediate fetcher downloads dependencies from the
[Go module proxy](https://go.dev/ref/mod#module-proxy) (using `go mod download`) instead of vendoring them. The resulting
[module cache](https://go.dev/ref/mod#module-cache) is then passed to the final derivation.
This is useful if your code depends on C code and `go mod tidy` does not include the needed sources to build or
if any dependency has case-insensitive conflicts which will produce platform-dependent `vendorHash` checksums.
Defaults to `false`.
- `modPostBuild`: Shell commands to run after the build of the goModules executes `go mod vendor`, and before calculating fixed output derivation's `vendorHash`.
Note that if you change this attribute, you need to update `vendorHash` attribute.
- `modRoot`: The root directory of the Go module that contains the `go.mod` file.
Defaults to `./`, which is the root of `src`.
### Example for `buildGoModule` {#ex-buildGoModule}
The following is an example expression using `buildGoModule`:
@@ -36,45 +62,17 @@ The following is an example expression using `buildGoModule`:
}
```
## Attributes of `buildGoModule` {#buildgomodule-parameters}
Many attributes [controlling the build phase](#variables-controlling-the-build-phase) are respected by `buildGoModule`. Note that `buildGoModule` reads the following attributes also when building the `vendor/` goModules fixed output derivation as well:
- [`sourceRoot`](#var-stdenv-sourceRoot)
- [`prePatch`](#var-stdenv-prePatch)
- [`patches`](#var-stdenv-patches)
- [`patchFlags`](#var-stdenv-patchFlags)
- [`postPatch`](#var-stdenv-postPatch)
- [`preBuild`](#var-stdenv-preBuild)
- `env`: useful for passing down variables such as `GOWORK`.
To control test execution of the build derivation, the following attributes are of interest:
- [`checkInputs`](#var-stdenv-checkInputs)
- [`preCheck`](#var-stdenv-preCheck)
- [`checkFlags`](#var-stdenv-checkFlags)
In addition to the above attributes, and the many more variables respected also by `stdenv.mkDerivation`, `buildGoModule` respects Go-specific attributes that tweak them to behave slightly differently:
### `vendorHash` {#var-go-vendorHash}
Hash of the output of the intermediate fetcher derivation (the dependencies of the Go modules).
`vendorHash` can be set to `null`.
In that case, rather than fetching the dependencies, the dependencies already vendored in the `vendor` directory of the source repo will be used.
To avoid updating this field when dependencies change, run `go mod vendor` in your source repo and set `vendorHash = null;`.
You can read more about [vendoring in the Go documentation](https://go.dev/ref/mod#vendoring).
To obtain the hash, set `vendorHash = lib.fakeHash;` and run the build. ([more details here](#sec-source-hashes)).
Another way is to use use `nix-prefetch` to obtain the hash. The following command gets the value of `vendorHash` for package `pet`:
### Obtaining and overriding `vendorHash` for `buildGoModule` {#buildGoModule-vendorHash}
We can use `nix-prefetch` to obtain the actual hash. The following command gets the value of `vendorHash` for package `pet`:
```sh
cd path/to/nixpkgs
nix-prefetch -E "{ sha256 }: ((import ./. { }).my-package.overrideAttrs { vendorHash = sha256; }).goModules"
```
To obtain the hash without external tools, set `vendorHash = lib.fakeHash;` and run the build. ([more details here](#sec-source-hashes)).
`vendorHash` can be overridden with `overrideAttrs`. Override the above example like this:
```nix
@@ -93,29 +91,144 @@ nix-prefetch -E "{ sha256 }: ((import ./. { }).my-package.overrideAttrs { vendor
}
```
### `proxyVendor` {#var-go-proxyVendor}
### Overriding `goModules` {#buildGoModule-goModules-override}
If `true`, the intermediate fetcher downloads dependencies from the
[Go module proxy](https://go.dev/ref/mod#module-proxy) (using `go mod download`) instead of vendoring them. The resulting
[module cache](https://go.dev/ref/mod#module-cache) is then passed to the final derivation.
Overriding `<pkg>.goModules` by calling `goModules.overrideAttrs` is unsupported. Still, it is possible to override the `vendorHash` (`goModules`'s `outputHash`) and the `pre`/`post` hooks for both the build and patch phases of the primary and `goModules` derivation. Alternatively, the primary derivation provides an overridable `passthru.overrideModAttrs` function to store the attribute overlay implicitly taken by `goModules.overrideAttrs`. Here's an example usage of `overrideModAttrs`:
This is useful if your code depends on C code and `go mod tidy` does not include the needed sources to build or
if any dependency has case-insensitive conflicts which will produce platform-dependent `vendorHash` checksums.
```nix
{
pet-overridden = pet.overrideAttrs (
finalAttrs: previousAttrs: {
passthru = previousAttrs.passthru // {
# If the original package has an `overrideModAttrs` attribute set, you'd
# want to extend it, and not replace it. Hence we use
# `lib.composeExtensions`. If you are sure the `overrideModAttrs` of the
# original package trivially does nothing, you can safely replace it
# with your own by not using `lib.composeExtensions`.
overrideModAttrs = lib.composeExtensions previousAttrs.passthru.overrideModAttrs (
finalModAttrs: previousModAttrs: {
# goModules-specific overriding goes here
postBuild = ''
# Here you have access to the `vendor` directory.
substituteInPlace vendor/github.com/example/repo/file.go \
--replace-fail "panic(err)" ""
'';
}
);
};
}
);
}
```
Defaults to `false`.
## `buildGoPackage` (legacy) {#ssec-go-legacy}
The function `buildGoPackage` builds legacy Go programs, not supporting Go modules.
### `modPostBuild` {#var-go-modPostBuild}
::: {.warning}
`buildGoPackage` is deprecated and will be removed for the 25.05 release.
:::
Shell commands to run after the build of the goModules executes `go mod vendor`, and before calculating fixed output derivation's `vendorHash`.
Note that if you change this attribute, you need to update `vendorHash` attribute.
### Migrating from `buildGoPackage` to `buildGoModule` {#buildGoPackage-migration}
Go modules, released 6y ago, are now widely adopted in the ecosystem.
Most upstream projects are using Go modules, and the tooling previously used for dependency management in Go is mostly deprecated, archived or at least unmaintained at this point.
### `modRoot` {#var-go-modRoot}
In case a project doesn't have external dependencies or dependencies are vendored in a way understood by `go mod init`, migration can be done with a few changes in the package.
The root directory of the Go module that contains the `go.mod` file.
- Switch the builder from `buildGoPackage` to `buildGoModule`
- Remove `goPackagePath` and other attributes specific to `buildGoPackage`
- Set `vendorHash = null;`
- Run `go mod init <module name>` in `postPatch`
Defaults to `./`, which is the root of `src`.
In case the package has external dependencies that aren't vendored or the build setup is more complex the upstream source might need to be patched.
Examples for the migration can be found in the [issue tracking migration withing nixpkgs](https://github.com/NixOS/nixpkgs/issues/318069).
### Example for `buildGoPackage` {#example-for-buildgopackage}
In the following is an example expression using `buildGoPackage`, the following arguments are of special significance to the function:
- `goPackagePath` specifies the package's canonical Go import path.
- `goDeps` is where the Go dependencies of a Go program are listed as a list of package source identified by Go import path. It could be imported as a separate `deps.nix` file for readability. The dependency data structure is described below.
```nix
{
deis = buildGoPackage rec {
pname = "deis";
version = "1.13.0";
goPackagePath = "github.com/deis/deis";
src = fetchFromGitHub {
owner = "deis";
repo = "deis";
rev = "v${version}";
hash = "sha256-XCPD4LNWtAd8uz7zyCLRfT8rzxycIUmTACjU03GnaeM=";
};
goDeps = ./deps.nix;
};
}
```
The `goDeps` attribute can be imported from a separate `nix` file that defines which Go libraries are needed and should be included in `GOPATH` for `buildPhase`:
```nix
# deps.nix
[ # goDeps is a list of Go dependencies.
{
# goPackagePath specifies Go package import path.
goPackagePath = "gopkg.in/yaml.v2";
fetch = {
# `fetch type` that needs to be used to get package source.
# If `git` is used there should be `url`, `rev` and `hash` defined next to it.
type = "git";
url = "https://gopkg.in/yaml.v2";
rev = "a83829b6f1293c91addabc89d0571c246397bbf4";
hash = "sha256-EMrdy0M0tNuOcITaTAmT5/dPSKPXwHDKCXFpkGbVjdQ=";
};
}
{
goPackagePath = "github.com/docopt/docopt-go";
fetch = {
type = "git";
url = "https://github.com/docopt/docopt-go";
rev = "784ddc588536785e7299f7272f39101f7faccc3f";
hash = "sha256-Uo89zjE+v3R7zzOq/gbQOHj3SMYt2W1nDHS7RCUin3M=";
};
}
]
```
To extract dependency information from a Go package in automated way use [go2nix (deprecated)](https://github.com/kamilchm/go2nix). It can produce complete derivation and `goDeps` file for Go programs.
You may use Go packages installed into the active Nix profiles by adding the following to your ~/.bashrc:
```bash
for p in $NIX_PROFILES; do
GOPATH="$p/share/go:$GOPATH"
done
```
## Attributes used by both builders {#ssec-go-common-attributes}
Many attributes [controlling the build phase](#variables-controlling-the-build-phase) are respected by both `buildGoModule` and `buildGoPackage`. Note that `buildGoModule` reads the following attributes also when building the `vendor/` goModules fixed output derivation as well:
- [`sourceRoot`](#var-stdenv-sourceRoot)
- [`prePatch`](#var-stdenv-prePatch)
- [`patches`](#var-stdenv-patches)
- [`patchFlags`](#var-stdenv-patchFlags)
- [`postPatch`](#var-stdenv-postPatch)
- [`preBuild`](#var-stdenv-preBuild)
- `env`: useful for passing down variables such as `GOWORK`.
To control test execution of the build derivation, the following attributes are of interest:
- [`checkInputs`](#var-stdenv-checkInputs)
- [`preCheck`](#var-stdenv-preCheck)
- [`checkFlags`](#var-stdenv-checkFlags)
In addition to the above attributes, and the many more variables respected also by `stdenv.mkDerivation`, both `buildGoModule` and `buildGoPackage` respect Go-specific attributes that tweak them to behave slightly differently:
### `ldflags` {#var-go-ldflags}
@@ -176,63 +289,13 @@ Following example could be used to only build the example-cli and example-server
Specified as a string or list of strings. Causes the builder to skip building child packages that match any of the provided values.
### `enableParallelBuilding` {#var-go-enableParallelBuilding}
Whether builds and tests should run in parallel.
Defaults to `true`.
### `allowGoReference` {#var-go-allowGoReference}
Whether the build result should be allowed to contain references to the Go tool chain. This might be needed for programs that are coupled with the compiler, but shouldn't be set without a good reason.
Defaults to `false`
## Overriding `goModules` {#buildGoModule-goModules-override}
Overriding `<pkg>.goModules` by calling `goModules.overrideAttrs` is unsupported. Still, it is possible to override the `vendorHash` (`goModules`'s `outputHash`) and the `pre`/`post` hooks for both the build and patch phases of the primary and `goModules` derivation.
Alternatively, the primary derivation provides an overridable `passthru.overrideModAttrs` function to store the attribute overlay implicitly taken by `goModules.overrideAttrs`. Here's an example usage of `overrideModAttrs`:
```nix
{
pet-overridden = pet.overrideAttrs (
finalAttrs: previousAttrs: {
passthru = previousAttrs.passthru // {
# If the original package has an `overrideModAttrs` attribute set, you'd
# want to extend it, and not replace it. Hence we use
# `lib.composeExtensions`. If you are sure the `overrideModAttrs` of the
# original package trivially does nothing, you can safely replace it
# with your own by not using `lib.composeExtensions`.
overrideModAttrs = lib.composeExtensions previousAttrs.passthru.overrideModAttrs (
finalModAttrs: previousModAttrs: {
# goModules-specific overriding goes here
postBuild = ''
# Here you have access to the `vendor` directory.
substituteInPlace vendor/github.com/example/repo/file.go \
--replace-fail "panic(err)" ""
'';
}
);
};
}
);
}
```
## Controlling the Go environment {#ssec-go-environment}
The Go build can be further tweaked by setting environment variables via the `env` attribute. In most cases, this isn't needed. Possible values can be found in the [Go documentation of accepted environment variables](https://pkg.go.dev/cmd/go#hdr-Environment_variables). Notice that some of these flags are set by the build helper itself and should not be set explicitly. If in doubt, grep the implementation of the build helper.
`buildGoModule` officially supports the following environment variables:
### `env.CGO_ENABLED` {#var-go-CGO_ENABLED}
### `CGO_ENABLED` {#var-go-CGO_ENABLED}
When set to `0`, the [cgo](https://pkg.go.dev/cmd/cgo) command is disabled. As consequence, the build
program can't link against C libraries anymore, and the resulting binary is statically linked.
When building with CGO enabled, Go will likely link some packages from the Go standard library against C libraries,
even when the target code does not explicitly call into C dependencies. With `env.CGO_ENABLED = 0;`, Go
even when the target code does not explicitly call into C dependencies. With `CGO_ENABLED = 0;`, Go
will always use the Go native implementation of these internal packages. For reference see
[net](https://pkg.go.dev/net#hdr-Name_Resolution) and [os/user](https://pkg.go.dev/os/user#pkg-overview) packages.
Notice that the decision whether these packages should use native Go implementation or not can also be controlled
@@ -249,7 +312,23 @@ When a Go program depends on C libraries, place those dependencies in `buildInpu
}
```
`env.CGO_ENABLED` defaults to `1`.
`CGO_ENABLED` defaults to `1`.
### `enableParallelBuilding` {#var-go-enableParallelBuilding}
Whether builds and tests should run in parallel.
Defaults to `true`.
### `allowGoReference` {#var-go-allowGoReference}
Whether the build result should be allowed to contain references to the Go tool chain. This might be needed for programs that are coupled with the compiler, but shouldn't be set without a good reason.
Defaults to `false`
## Controlling the Go environment {#ssec-go-environment}
The Go build can be further tweaked by setting environment variables. In most cases, this isn't needed. Possible values can be found in the [Go documentation of accepted environment variables](https://pkg.go.dev/cmd/go#hdr-Environment_variables). Notice that some of these flags are set by the builder itself and should not be set explicitly. If in doubt, grep the implementation of the builder.
## Skipping tests {#ssec-skip-go-tests}
@@ -285,23 +364,4 @@ If a larger amount of tests should be skipped, the following pattern can be used
```
To disable tests altogether, set `doCheck = false;`.
## Migrating from `buildGoPackage` to `buildGoModule` {#buildGoPackage-migration}
::: {.warning}
`buildGoPackage` was removed for the 25.05 release. It was used to build legacy Go programs
that do not support Go modules.
:::
Go modules, released 6y ago, are now widely adopted in the ecosystem.
Most upstream projects are using Go modules, and the tooling previously used for dependency management in Go is mostly deprecated, archived or at least unmaintained at this point.
In case a project doesn't have external dependencies or dependencies are vendored in a way understood by `go mod init`, migration can be done with a few changes in the package.
- Switch the builder from `buildGoPackage` to `buildGoModule`
- Remove `goPackagePath` and other attributes specific to `buildGoPackage`
- Set `vendorHash = null;`
- Run `go mod init <module name>` in `postPatch`
In case the package has external dependencies that aren't vendored or the build setup is more complex the upstream source might need to be patched.
Examples for the migration can be found in the [issue tracking migration withing nixpkgs](https://github.com/NixOS/nixpkgs/issues/318069).
`buildGoPackage` does not execute tests by default.

View File

@@ -67,14 +67,3 @@ nix-shell -p 'julia.withPackages ["Plots"]' --run julia
This normally points at a special augmented version of the Julia [General packages registry](https://github.com/JuliaRegistries/General).
If you want to use a bleeding-edge version to pick up the latest package updates, you can plug in a later revision than the one in Nixpkgs.
* `juliaCpuTarget`: Allows you to set `JULIA_CPU_TARGET` when precompiling. Has no effect if `precompile=false`.
You may want to use this if you're building a Julia depot that will end up in a Nix cache and used on machines with
different CPUs.
Why? Julia will detect the CPU microarchitecture of the build machine and include this information in the precompiled
`*.ji` files. Starting in 1.10 Julia became more strict about checking the CPU target compatibility, so it may reject
your precompiled files if they were compiled on a different machine.
A good option to provide wide compatibility is to set this to `"generic"`, although this may reduce performance.
You can also set a semicolon-separated list of multiple different targets. See the Julia documentation for details.

View File

@@ -49,90 +49,6 @@ This package calls `maven.buildMavenPackage` to do its work. The primary differe
After setting `maven.buildMavenPackage`, we then do standard Java `.jar` installation by saving the `.jar` to `$out/share/java` and then making a wrapper which allows executing that file; see [](#sec-language-java) for additional generic information about packaging Java applications.
:::
### Overriding Maven package attributes {#maven-overriding-package-attributes}
```
overrideMavenAttrs :: (AttrSet -> Derivation) | ((AttrSet -> Attrset) -> Derivation) -> Derivation
```
The output of `buildMavenPackage` has an `overrideMavenAttrs` attribute, which is a function that takes either
- any subset of the attributes that can be passed to `buildMavenPackage`
or
- a function that takes the argument passed to the previous invocation of `buildMavenPackage` (conventionally called `old`) and returns an attribute set that can be passed to `buildMavenPackage`
and returns a derivation that builds a Maven package based on the old and new arguments merged.
This is similar to [](#sec-pkg-overrideAttrs), but notably does not allow accessing the final value of the argument to `buildMavenPackage`.
:::{.example}
### `overrideMavenAttrs` Example
Use `overrideMavenAttrs` to build `jd-cli` version 1.2.0 and disable some flaky test:
```nix
jd-cli.overrideMavenAttrs (old: rec {
version = "1.2.0";
src = fetchFromGitHub {
owner = old.src.owner;
repo = old.src.repo;
rev = "${old.pname}-${version}";
# old source hash of 1.2.0 version
hash = "sha256-US7j6tQ6mh1libeHnQdFxPGoxHzbZHqehWSgCYynKx8=";
};
# tests can be disabled by prefixing it with `!`
# see Maven documentation for more details:
# https://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One
mvnParameters = lib.escapeShellArgs [
"-Dsurefire.failIfNoSpecifiedTests=false"
"-Dtest=!JavaDecompilerTest#basicTest,!JavaDecompilerTest#patternMatchingTest"
];
# old mvnHash of 1.2.0 maven dependencies
mvnHash = "sha256-N9XC1pg6Y4sUiBWIQUf16QSXCuiAPpXEHGlgApviF4I=";
});
```
:::
### Offline build {#maven-offline-build}
By default, `buildMavenPackage` does the following:
1. Run `mvn package -Dmaven.repo.local=$out/.m2 ${mvnParameters}` in the
`fetchedMavenDeps` [fixed-output derivation](https://nixos.org/manual/nix/stable/glossary.html#gloss-fixed-output-derivation).
2. Run `mvn package -o -nsu "-Dmaven.repo.local=$mvnDeps/.m2"
${mvnParameters}` again in the main derivation.
As a result, tests are run twice.
This also means that a failing test will trigger a new attempt to realise the fixed-output derivation, which in turn downloads all dependencies again.
For bigger Maven projects, this might lead to a long feedback cycle.
Use `buildOffline = true` to change the behaviour of `buildMavenPackage to the following:
1. Run `mvn de.qaware.maven:go-offline-maven-plugin:1.2.8:resolve-dependencies
-Dmaven.repo.local=$out/.m2 ${mvnDepsParameters}` in the fixed-output derivation.
2. Run `mvn package -o -nsu "-Dmaven.repo.local=$mvnDeps/.m2"
${mvnParameters}` in the main derivation.
As a result, all dependencies are downloaded in step 1 and the tests are executed in step 2.
A failing test only triggers a rebuild of step 2 as it can reuse the dependencies of step 1 because they have not changed.
::: {.warning}
Test dependencies are not downloaded in step 1 and are therefore missing in
step 2 which will most probably fail the build. The `go-offline` plugin cannot
handle these so-called [dynamic dependencies](https://github.com/qaware/go-offline-maven-plugin?tab=readme-ov-file#dynamic-dependencies).
In that case you must add these dynamic dependencies manually with:
```nix
maven.buildMavenPackage rec {
manualMvnArtifacts = [
# add dynamic test dependencies here
"org.apache.maven.surefire:surefire-junit-platform:3.1.2"
"org.junit.platform:junit-platform-launcher:1.10.0"
];
};
```
:::
### Stable Maven plugins {#stable-maven-plugins}
Maven defines default versions for its core plugins, e.g. `maven-compiler-plugin`. If your project does not override these versions, an upgrade of Maven will change the version of the used plugins, and therefore the derivation and hash.

View File

@@ -1,9 +1,7 @@
# Nim {#sec-language-nim}
# Nim {#nim}
The Nim compiler and a builder function is available.
Nim programs are built using a lockfile and either `buildNimPackage` or `buildNimSbom`.
## buildNimPackage {#buildNimPackage}
Nim programs are built using `buildNimPackage` and a lockfile containing Nim dependencies.
The following example shows a Nim program that depends only on Nim libraries:
```nix
@@ -17,7 +15,7 @@ buildNimPackage (finalAttrs: {
owner = "inv2004";
repo = "ttop";
rev = "v${finalAttrs.version}";
hash = lib.fakeHash;
hash = "sha256-oPdaUqh6eN1X5kAYVvevOndkB/xnQng9QVLX9bu5P5E=";
};
lockFile = ./lock.json;
@@ -28,7 +26,7 @@ buildNimPackage (finalAttrs: {
})
```
### `buildNimPackage` parameters {#buildnimpackage-parameters}
## `buildNimPackage` parameters {#buildnimpackage-parameters}
The `buildNimPackage` function takes an attrset of parameters that are passed on to `stdenv.mkDerivation`.
@@ -43,7 +41,7 @@ The following parameters are specific to `buildNimPackage`:
Use this to specify defines with arguments in the form of `-d:${name}=${value}`.
* `nimDoc` ? false`: Build and install HTML documentation.
### Lockfiles {#nim-lockfiles}
## Lockfiles {#nim-lockfiles}
Nim lockfiles are created with the `nim_lk` utility.
Run `nim_lk` with the source directory as an argument and it will print a lockfile to stdout.
```sh
@@ -52,41 +50,9 @@ $ nix build -f . ttop.src
$ nix run -f . nim_lk ./result | jq --sort-keys > pkgs/by-name/tt/ttop/lock.json
```
## buildNimSbom {#buildNimSbom}
An alternative to `buildNimPackage` is `buildNimSbom` which builds packages from [CycloneDX SBOM](https://cyclonedx.org/) files.
`buildNimSbom` resolves Nim dependencies to [fixed-output derivations](https://nixos.org/manual/nix/stable/glossary#gloss-fixed-output-derivation) using the [nix:fod namespace](#sec-interop.cylonedx-fod).
In the following minimal example only the source code checkout and a `buildInput` are specified.
The SBOM file provides metadata such as `pname` and `version` as well as the sources to Nim dependencies.
```nix
# pkgs/by-name/ni/nim_lk/package.nix
{
lib,
buildNimSbom,
fetchFromSourcehut,
openssl,
}:
buildNimSbom (finalAttrs: {
src = fetchFromSourcehut {
owner = "~ehmry";
repo = "nim_lk";
rev = finalAttrs.version;
hash = lib.fakeHash;
};
buildInputs = [ openssl ];
}) ./sbom.json
```
### Generating SBOMs {#generating-nim-sboms}
The [nim_lk](https://git.sr.ht/~ehmry/nim_lk) utility can generate SBOMs from [Nimble](https://github.com/nim-lang/nimble) package metadata.
See the [nim_lk documentation](https://git.sr.ht/~ehmry/nim_lk#nimble-to-cyclonedx-sbom) for more information.
## Overriding Nim packages {#nim-overrides}
The `buildNimPackage` and `buildNimSbom` functions generate flags and additional build dependencies from the `lockFile` parameter passed to `buildNimPackage`. Using [`overrideAttrs`](#sec-pkg-overrideAttrs) on the final package will apply after this has already been generated, so this can't be used to override the `lockFile` in a package built with `buildNimPackage`. To be able to override parameters before flags and build dependencies are generated from the `lockFile`, use `overrideNimAttrs` instead with the same syntax as `overrideAttrs`:
The `buildNimPackage` function generates flags and additional build dependencies from the `lockFile` parameter passed to `buildNimPackage`. Using [`overrideAttrs`](#sec-pkg-overrideAttrs) on the final package will apply after this has already been generated, so this can't be used to override the `lockFile` in a package built with `buildNimPackage`. To be able to override parameters before flags and build dependencies are generated from the `lockFile`, use `overrideNimAttrs` instead with the same syntax as `overrideAttrs`:
```nix
pkgs.nitter.overrideNimAttrs {

View File

@@ -551,9 +551,9 @@ are used in [`buildPythonPackage`](#buildpythonpackage-function).
Several versions of the Python interpreter are available on Nix, as well as a
high amount of packages. The attribute `python3` refers to the default
interpreter, which is currently CPython 3.12. The attribute `python` refers to
interpreter, which is currently CPython 3.11. The attribute `python` refers to
CPython 2.7 for backwards-compatibility. It is also possible to refer to
specific versions, e.g. `python312` refers to CPython 3.12, and `pypy` refers to
specific versions, e.g. `python311` refers to CPython 3.11, and `pypy` refers to
the default PyPy interpreter.
Python is used a lot, and in different ways. This affects also how it is
@@ -569,10 +569,10 @@ however, are in separate sets, with one set per interpreter version.
The interpreters have several common attributes. One of these attributes is
`pkgs`, which is a package set of Python libraries for this specific
interpreter. E.g., the `toolz` package corresponding to the default interpreter
is `python3.pkgs.toolz`, and the CPython 3.12 version is `python312.pkgs.toolz`.
is `python3.pkgs.toolz`, and the CPython 3.11 version is `python311.pkgs.toolz`.
The main package set contains aliases to these package sets, e.g.
`pythonPackages` refers to `python.pkgs` and `python312Packages` to
`python312.pkgs`.
`pythonPackages` refers to `python.pkgs` and `python311Packages` to
`python311.pkgs`.
#### Installing Python and packages {#installing-python-and-packages}
@@ -597,7 +597,7 @@ with [`python.buildEnv`](#python.buildenv-function) or [`python.withPackages`](#
executables are wrapped to be able to find each other and all of the modules.
In the following examples we will start by creating a simple, ad-hoc environment
with a nix-shell that has `numpy` and `toolz` in Python 3.12; then we will create
with a nix-shell that has `numpy` and `toolz` in Python 3.11; then we will create
a re-usable environment in a single-file Python script; then we will create a
full Python environment for development with this same environment.
@@ -613,10 +613,10 @@ temporary shell session with a Python and a *precise* list of packages (plus
their runtime dependencies), with no other Python packages in the Python
interpreter's scope.
To create a Python 3.12 session with `numpy` and `toolz` available, run:
To create a Python 3.11 session with `numpy` and `toolz` available, run:
```sh
$ nix-shell -p 'python312.withPackages(ps: with ps; [ numpy toolz ])'
$ nix-shell -p 'python311.withPackages(ps: with ps; [ numpy toolz ])'
```
By default `nix-shell` will start a `bash` session with this interpreter in our
@@ -624,7 +624,7 @@ By default `nix-shell` will start a `bash` session with this interpreter in our
```Python console
[nix-shell:~/src/nixpkgs]$ python3
Python 3.12.4 (main, Jun 6 2024, 18:26:44) [GCC 13.3.0] on linux
Python 3.11.3 (main, Apr 4 2023, 22:36:41) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy; import toolz
```
@@ -644,8 +644,12 @@ will still get 1 wrapped Python interpreter. We can start the interpreter
directly like so:
```sh
$ nix-shell -p "python312.withPackages (ps: with ps; [ numpy toolz requests ])" --run python3
Python 3.12.4 (main, Jun 6 2024, 18:26:44) [GCC 13.3.0] on linux
$ nix-shell -p "python311.withPackages (ps: with ps; [ numpy toolz requests ])" --run python3
this derivation will be built:
/nix/store/r19yf5qgfiakqlhkgjahbg3zg79549n4-python3-3.11.2-env.drv
building '/nix/store/r19yf5qgfiakqlhkgjahbg3zg79549n4-python3-3.11.2-env.drv'...
created 273 symlinks in user environment
Python 3.11.2 (main, Feb 7 2023, 13:52:42) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>>
@@ -685,7 +689,7 @@ Executing this script requires a `python3` that has `numpy`. Using what we learn
in the previous section, we could startup a shell and just run it like so:
```ShellSession
$ nix-shell -p 'python312.withPackages (ps: with ps; [ numpy ])' --run 'python3 foo.py'
$ nix-shell -p 'python311.withPackages (ps: with ps; [ numpy ])' --run 'python3 foo.py'
The dot product of [1 2] and [3 4] is: 11
```
@@ -748,12 +752,12 @@ create a single script with Python dependencies, but in the course of normal
development we're usually working in an entire package repository.
As explained [in the `nix-shell` section](https://nixos.org/manual/nix/stable/command-ref/nix-shell) of the Nix manual, `nix-shell` can also load an expression from a `.nix` file.
Say we want to have Python 3.12, `numpy` and `toolz`, like before,
Say we want to have Python 3.11, `numpy` and `toolz`, like before,
in an environment. We can add a `shell.nix` file describing our dependencies:
```nix
with import <nixpkgs> {};
(python312.withPackages (ps: with ps; [
(python311.withPackages (ps: with ps; [
numpy
toolz
])).env
@@ -770,7 +774,7 @@ What's happening here?
imports the `<nixpkgs>` function, `{}` calls it and the `with` statement
brings all attributes of `nixpkgs` in the local scope. These attributes form
the main package set.
2. Then we create a Python 3.12 environment with the [`withPackages`](#python.withpackages-function) function, as before.
2. Then we create a Python 3.11 environment with the [`withPackages`](#python.withpackages-function) function, as before.
3. The [`withPackages`](#python.withpackages-function) function expects us to provide a function as an argument
that takes the set of all Python packages and returns a list of packages to
include in the environment. Here, we select the packages `numpy` and `toolz`
@@ -781,7 +785,7 @@ To combine this with `mkShell` you can:
```nix
with import <nixpkgs> {};
let
pythonEnv = python312.withPackages (ps: [
pythonEnv = python311.withPackages (ps: [
ps.numpy
ps.toolz
]);
@@ -935,8 +939,8 @@ information. The output of the function is a derivation.
An expression for `toolz` can be found in the Nixpkgs repository. As explained
in the introduction of this Python section, a derivation of `toolz` is available
for each interpreter version, e.g. `python312.pkgs.toolz` refers to the `toolz`
derivation corresponding to the CPython 3.12 interpreter.
for each interpreter version, e.g. `python311.pkgs.toolz` refers to the `toolz`
derivation corresponding to the CPython 3.11 interpreter.
The above example works when you're directly working on
`pkgs/top-level/python-packages.nix` in the Nixpkgs repository. Often though,
@@ -949,7 +953,7 @@ and adds it along with a `numpy` package to a Python environment.
with import <nixpkgs> {};
( let
my_toolz = python312.pkgs.buildPythonPackage rec {
my_toolz = python311.pkgs.buildPythonPackage rec {
pname = "toolz";
version = "0.10.0";
pyproject = true;
@@ -960,7 +964,7 @@ with import <nixpkgs> {};
};
build-system = [
python312.pkgs.setuptools
python311.pkgs.setuptools
];
# has no tests
@@ -973,7 +977,7 @@ with import <nixpkgs> {};
};
};
in python312.withPackages (ps: with ps; [
in python311.withPackages (ps: with ps; [
numpy
my_toolz
])
@@ -981,7 +985,7 @@ with import <nixpkgs> {};
```
Executing `nix-shell` will result in an environment in which you can use
Python 3.12 and the `toolz` package. As you can see we had to explicitly mention
Python 3.11 and the `toolz` package. As you can see we had to explicitly mention
for which Python version we want to build a package.
So, what did we do here? Well, we took the Nix expression that we used earlier
@@ -1987,7 +1991,7 @@ has security implications and is relevant for those using Python in a
When the environment variable `DETERMINISTIC_BUILD` is set, all bytecode will
have timestamp 1. The [`buildPythonPackage`](#buildpythonpackage-function) function sets `DETERMINISTIC_BUILD=1`
and [PYTHONHASHSEED=0](https://docs.python.org/3.12/using/cmdline.html#envvar-PYTHONHASHSEED).
and [PYTHONHASHSEED=0](https://docs.python.org/3.11/using/cmdline.html#envvar-PYTHONHASHSEED).
Both are also exported in `nix-shell`.
### How to provide automatic tests to Python packages? {#automatic-tests}
@@ -2058,12 +2062,10 @@ The following rules are desired to be respected:
* `meta.platforms` takes the default value in many cases.
It does not need to be set explicitly unless the package requires a specific platform.
* The file is formatted with `nixfmt-rfc-style`.
* Commit names of Python libraries must reflect that they are Python
libraries (e.g. `python312Packages.numpy: 1.11 -> 1.12` rather than `numpy: 1.11 -> 1.12`).
* The current default version of python should be included
in commit messages to enable automatic builds by ofborg.
For example `python312Packages.numpy: 1.11 -> 1.12` should be used rather
than `python3Packages.numpy: 1.11 -> 1.12`.
* Commit names of Python libraries should reflect that they are Python
libraries, so write for example `python311Packages.numpy: 1.11 -> 1.12`.
It is highly recommended to specify the current default version to enable
automatic build by ofborg.
Note that `pythonPackages` is an alias for `python27Packages`.
* Attribute names in `python-packages.nix` as well as `pname`s should match the
library's name on PyPI, but be normalized according to [PEP

View File

@@ -64,18 +64,10 @@ hash using `nix-hash --to-sri --type sha256 "<original sha256>"`.
```
Exception: If the application has cargo `git` dependencies, the `cargoHash`
approach will not work by default. In this case, you can set `useFetchCargoVendor = true`
to use an improved fetcher that supports handling `git` dependencies.
approach will not work, and you will need to copy the `Cargo.lock` file of the application
to nixpkgs and continue with the next section for specifying the options of the `cargoLock`
section.
```nix
{
useFetchCargoVendor = true;
cargoHash = "sha256-RqPVFovDaD2rW31HyETJfQ0qVwFxoGEvqkIgag3H6KU=";
}
```
If this method still does not work, you can resort to copying the `Cargo.lock` file into nixpkgs
and importing it as described in the [next section](#importing-a-cargo.lock-file).
Both types of hashes are permitted when contributing to nixpkgs. The
Cargo hash is obtained by inserting a fake checksum into the
@@ -470,17 +462,6 @@ also be used:
the `Cargo.lock`/`Cargo.toml` files need to be patched before
vendoring.
In case the lockfile contains cargo `git` dependencies, you can use
`fetchCargoVendor` instead.
```nix
{
cargoDeps = rustPlatform.fetchCargoVendor {
inherit src;
hash = "sha256-RqPVFovDaD2rW31HyETJfQ0qVwFxoGEvqkIgag3H6KU=";
};
}
```
If a `Cargo.lock` file is available, you can alternatively use the
`importCargoLock` function. In contrast to `fetchCargoTarball`, this
function does not require a hash (unless git dependencies are used)

View File

@@ -1,6 +1,6 @@
# TeX Live {#sec-language-texlive}
There is a TeX Live packaging that lives entirely under attribute `texlive`.
Since release 15.09 there is a new TeX Live packaging that lives entirely under attribute `texlive`.
## User's guide (experimental new interface) {#sec-language-texlive-user-guide-experimental}

View File

@@ -264,15 +264,10 @@ nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater --github-token=mytoken
Alternatively, set the number of processes to a lower count to avoid rate-limiting.
```sh
nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater --proc 1'
```
If you want to update only certain plugins, you can specify them after the `update` command. Note that you must use the same plugin names as the `pkgs/applications/editors/vim/plugins/vim-plugin-names` file.
```sh
nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater update "nvim-treesitter" "LazyVim"'
```
## How to maintain an out-of-tree overlay of vim plugins ? {#vim-out-of-tree-overlays}
You can use the updater script to generate basic packages out of a custom vim

View File

@@ -1,30 +1,66 @@
{
"30-systemd-environment-d-generator(8)": "https://www.freedesktop.org/software/systemd/man/30-systemd-environment-d-generator.html",
"binfmt.d(5)": "https://www.freedesktop.org/software/systemd/man/binfmt.d.html",
"gnunet.conf(5)": "https://docs.gnunet.org/latest/users/configuration.html",
"mpd(1)": "https://mpd.readthedocs.io/en/latest/mpd.1.html",
"mpd.conf(5)": "https://mpd.readthedocs.io/en/latest/mpd.conf.5.html",
"nix.conf(5)": "https://nixos.org/manual/nix/stable/command-ref/conf-file.html",
"portals.conf(5)": "https://github.com/flatpak/xdg-desktop-portal/blob/1.18.1/doc/portals.conf.rst.in",
"bootctl(1)": "https://www.freedesktop.org/software/systemd/man/bootctl.html",
"bootup(7)": "https://www.freedesktop.org/software/systemd/man/bootup.html",
"busctl(1)": "https://www.freedesktop.org/software/systemd/man/busctl.html",
"cat(1)": "https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html",
"coredumpctl(1)": "https://www.freedesktop.org/software/systemd/man/coredumpctl.html",
"homectl(1)": "https://www.freedesktop.org/software/systemd/man/homectl.html",
"hostnamectl(1)": "https://www.freedesktop.org/software/systemd/man/hostnamectl.html",
"init(1)": "https://www.freedesktop.org/software/systemd/man/init.html",
"journalctl(1)": "https://www.freedesktop.org/software/systemd/man/journalctl.html",
"localectl(1)": "https://www.freedesktop.org/software/systemd/man/localectl.html",
"loginctl(1)": "https://www.freedesktop.org/software/systemd/man/loginctl.html",
"machinectl(1)": "https://www.freedesktop.org/software/systemd/man/machinectl.html",
"mount.ddi(1)": "https://www.freedesktop.org/software/systemd/man/mount.ddi.html",
"networkctl(1)": "https://www.freedesktop.org/software/systemd/man/networkctl.html",
"oomctl(1)": "https://www.freedesktop.org/software/systemd/man/oomctl.html",
"portablectl(1)": "https://www.freedesktop.org/software/systemd/man/portablectl.html",
"resolvconf(1)": "https://www.freedesktop.org/software/systemd/man/resolvconf.html",
"resolvectl(1)": "https://www.freedesktop.org/software/systemd/man/resolvectl.html",
"systemctl(1)": "https://www.freedesktop.org/software/systemd/man/systemctl.html",
"systemd-ac-power(1)": "https://www.freedesktop.org/software/systemd/man/systemd-ac-power.html",
"systemd-analyze(1)": "https://www.freedesktop.org/software/systemd/man/systemd-analyze.html",
"systemd-ask-password(1)": "https://www.freedesktop.org/software/systemd/man/systemd-ask-password.html",
"systemd-cat(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cat.html",
"systemd-cgls(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cgls.html",
"systemd-cgtop(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cgtop.html",
"systemd-creds(1)": "https://www.freedesktop.org/software/systemd/man/systemd-creds.html",
"systemd-cryptenroll(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cryptenroll.html",
"systemd-delta(1)": "https://www.freedesktop.org/software/systemd/man/systemd-delta.html",
"systemd-detect-virt(1)": "https://www.freedesktop.org/software/systemd/man/systemd-detect-virt.html",
"systemd-dissect(1)": "https://www.freedesktop.org/software/systemd/man/systemd-dissect.html",
"systemd-escape(1)": "https://www.freedesktop.org/software/systemd/man/systemd-escape.html",
"systemd-id128(1)": "https://www.freedesktop.org/software/systemd/man/systemd-id128.html",
"systemd-inhibit(1)": "https://www.freedesktop.org/software/systemd/man/systemd-inhibit.html",
"systemd-machine-id-setup(1)": "https://www.freedesktop.org/software/systemd/man/systemd-machine-id-setup.html",
"systemd-measure(1)": "https://www.freedesktop.org/software/systemd/man/systemd-measure.html",
"systemd-mount(1)": "https://www.freedesktop.org/software/systemd/man/systemd-mount.html",
"systemd-notify(1)": "https://www.freedesktop.org/software/systemd/man/systemd-notify.html",
"systemd-nspawn(1)": "https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html",
"systemd-path(1)": "https://www.freedesktop.org/software/systemd/man/systemd-path.html",
"systemd-run(1)": "https://www.freedesktop.org/software/systemd/man/systemd-run.html",
"systemd-socket-activate(1)": "https://www.freedesktop.org/software/systemd/man/systemd-socket-activate.html",
"systemd-stdio-bridge(1)": "https://www.freedesktop.org/software/systemd/man/systemd-stdio-bridge.html",
"systemd-tty-ask-password-agent(1)": "https://www.freedesktop.org/software/systemd/man/systemd-tty-ask-password-agent.html",
"systemd-umount(1)": "https://www.freedesktop.org/software/systemd/man/systemd-umount.html",
"systemd(1)": "https://www.freedesktop.org/software/systemd/man/systemd.html",
"timedatectl(1)": "https://www.freedesktop.org/software/systemd/man/timedatectl.html",
"userdbctl(1)": "https://www.freedesktop.org/software/systemd/man/userdbctl.html",
"binfmt.d(5)": "https://www.freedesktop.org/software/systemd/man/binfmt.d.html",
"coredump.conf(5)": "https://www.freedesktop.org/software/systemd/man/coredump.conf.html",
"coredump.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/coredump.conf.d.html",
"coredumpctl(1)": "https://www.freedesktop.org/software/systemd/man/coredumpctl.html",
"crypttab(5)": "https://www.freedesktop.org/software/systemd/man/crypttab.html",
"curl(1)": "https://curl.se/docs/manpage.html",
"daemon(7)": "https://www.freedesktop.org/software/systemd/man/daemon.html",
"dnssec-trust-anchors.d(5)": "https://www.freedesktop.org/software/systemd/man/dnssec-trust-anchors.d.html",
"environment.d(5)": "https://www.freedesktop.org/software/systemd/man/environment.d.html",
"extension-release(5)": "https://www.freedesktop.org/software/systemd/man/extension-release.html",
"file-hierarchy(7)": "https://www.freedesktop.org/software/systemd/man/file-hierarchy.html",
"gnunet.conf(5)": "https://docs.gnunet.org/latest/users/configuration.html",
"group(5)": "https://man.archlinux.org/man/group.5",
"halt(8)": "https://www.freedesktop.org/software/systemd/man/halt.html",
"homectl(1)": "https://www.freedesktop.org/software/systemd/man/homectl.html",
"homed.conf(5)": "https://www.freedesktop.org/software/systemd/man/homed.conf.html",
"homed.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/homed.conf.d.html",
"hostname(5)": "https://www.freedesktop.org/software/systemd/man/hostname.html",
"hostnamectl(1)": "https://www.freedesktop.org/software/systemd/man/hostnamectl.html",
"hwdb(7)": "https://www.freedesktop.org/software/systemd/man/hwdb.html",
"init(1)": "https://www.freedesktop.org/software/systemd/man/init.html",
"initrd-release(5)": "https://www.freedesktop.org/software/systemd/man/initrd-release.html",
"integritytab(5)": "https://www.freedesktop.org/software/systemd/man/integritytab.html",
"iocost.conf(5)": "https://www.freedesktop.org/software/systemd/man/iocost.conf.html",
@@ -32,46 +68,19 @@
"journal-remote.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/journal-remote.conf.d.html",
"journal-upload.conf(5)": "https://www.freedesktop.org/software/systemd/man/journal-upload.conf.html",
"journal-upload.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/journal-upload.conf.d.html",
"journalctl(1)": "https://www.freedesktop.org/software/systemd/man/journalctl.html",
"journald.conf(5)": "https://www.freedesktop.org/software/systemd/man/journald.conf.html",
"journald.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/journald.conf.d.html",
"journald@.conf(5)": "https://www.freedesktop.org/software/systemd/man/journald@.conf.html",
"kernel-command-line(7)": "https://www.freedesktop.org/software/systemd/man/kernel-command-line.html",
"kernel-install(8)": "https://www.freedesktop.org/software/systemd/man/kernel-install.html",
"libnss_myhostname.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_myhostname.so.2.html",
"libnss_mymachines.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_mymachines.so.2.html",
"libnss_resolve.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_resolve.so.2.html",
"libnss_systemd.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_systemd.so.2.html",
"linuxaa64.efi.stub(7)": "https://www.freedesktop.org/software/systemd/man/linuxaa64.efi.stub.html",
"linuxia32.efi.stub(7)": "https://www.freedesktop.org/software/systemd/man/linuxia32.efi.stub.html",
"linuxx64.efi.stub(7)": "https://www.freedesktop.org/software/systemd/man/linuxx64.efi.stub.html",
"loader.conf(5)": "https://www.freedesktop.org/software/systemd/man/loader.conf.html",
"locale.conf(5)": "https://www.freedesktop.org/software/systemd/man/locale.conf.html",
"localectl(1)": "https://www.freedesktop.org/software/systemd/man/localectl.html",
"localtime(5)": "https://www.freedesktop.org/software/systemd/man/localtime.html",
"login.defs(5)": "https://man.archlinux.org/man/login.defs.5",
"loginctl(1)": "https://www.freedesktop.org/software/systemd/man/loginctl.html",
"logind.conf(5)": "https://www.freedesktop.org/software/systemd/man/logind.conf.html",
"logind.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/logind.conf.d.html",
"machine-id(5)": "https://www.freedesktop.org/software/systemd/man/machine-id.html",
"machine-info(5)": "https://www.freedesktop.org/software/systemd/man/machine-info.html",
"machinectl(1)": "https://www.freedesktop.org/software/systemd/man/machinectl.html",
"mksquashfs(1)": "https://man.archlinux.org/man/extra/squashfs-tools/mksquashfs.1.en",
"modules-load.d(5)": "https://www.freedesktop.org/software/systemd/man/modules-load.d.html",
"mount.ddi(1)": "https://www.freedesktop.org/software/systemd/man/mount.ddi.html",
"mpd(1)": "https://mpd.readthedocs.io/en/latest/mpd.1.html",
"mpd.conf(5)": "https://mpd.readthedocs.io/en/latest/mpd.conf.5.html",
"netrc(5)": "https://man.cx/netrc",
"networkctl(1)": "https://www.freedesktop.org/software/systemd/man/networkctl.html",
"networkd.conf(5)": "https://www.freedesktop.org/software/systemd/man/networkd.conf.html",
"networkd.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/networkd.conf.d.html",
"nix-shell(1)": "https://nixos.org/manual/nix/stable/command-ref/nix-shell.html",
"nix.conf(5)": "https://nixos.org/manual/nix/stable/command-ref/conf-file.html",
"nss-myhostname(8)": "https://www.freedesktop.org/software/systemd/man/nss-myhostname.html",
"nss-mymachines(8)": "https://www.freedesktop.org/software/systemd/man/nss-mymachines.html",
"nss-resolve(8)": "https://www.freedesktop.org/software/systemd/man/nss-resolve.html",
"nss-systemd(8)": "https://www.freedesktop.org/software/systemd/man/nss-systemd.html",
"oomctl(1)": "https://www.freedesktop.org/software/systemd/man/oomctl.html",
"oomd.conf(5)": "https://www.freedesktop.org/software/systemd/man/oomd.conf.html",
"oomd.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/oomd.conf.d.html",
"org.freedesktop.LogControl1(5)": "https://www.freedesktop.org/software/systemd/man/org.freedesktop.LogControl1.html",
@@ -88,32 +97,94 @@
"org.freedesktop.systemd1(5)": "https://www.freedesktop.org/software/systemd/man/org.freedesktop.systemd1.html",
"org.freedesktop.timedate1(5)": "https://www.freedesktop.org/software/systemd/man/org.freedesktop.timedate1.html",
"os-release(5)": "https://www.freedesktop.org/software/systemd/man/os-release.html",
"pam_systemd(8)": "https://www.freedesktop.org/software/systemd/man/pam_systemd.html",
"pam_systemd_home(8)": "https://www.freedesktop.org/software/systemd/man/pam_systemd_home.html",
"passwd(5)": "https://man.archlinux.org/man/passwd.5",
"portablectl(1)": "https://www.freedesktop.org/software/systemd/man/portablectl.html",
"portals.conf(5)": "https://github.com/flatpak/xdg-desktop-portal/blob/1.18.1/doc/portals.conf.rst.in",
"poweroff(8)": "https://www.freedesktop.org/software/systemd/man/poweroff.html",
"pstore.conf(5)": "https://www.freedesktop.org/software/systemd/man/pstore.conf.html",
"pstore.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/pstore.conf.d.html",
"reboot(8)": "https://www.freedesktop.org/software/systemd/man/reboot.html",
"repart.d(5)": "https://www.freedesktop.org/software/systemd/man/repart.d.html",
"resolvconf(1)": "https://www.freedesktop.org/software/systemd/man/resolvconf.html",
"resolvectl(1)": "https://www.freedesktop.org/software/systemd/man/resolvectl.html",
"resolved.conf(5)": "https://www.freedesktop.org/software/systemd/man/resolved.conf.html",
"resolved.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/resolved.conf.d.html",
"sd-boot(7)": "https://www.freedesktop.org/software/systemd/man/sd-boot.html",
"sd-stub(7)": "https://www.freedesktop.org/software/systemd/man/sd-stub.html",
"shutdown(8)": "https://www.freedesktop.org/software/systemd/man/shutdown.html",
"sleep.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/sleep.conf.d.html",
"smbios-type-11(7)": "https://www.freedesktop.org/software/systemd/man/smbios-type-11.html",
"sysctl.d(5)": "https://www.freedesktop.org/software/systemd/man/sysctl.d.html",
"system.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/system.conf.d.html",
"systemctl(1)": "https://www.freedesktop.org/software/systemd/man/systemctl.html",
"systemd(1)": "https://www.freedesktop.org/software/systemd/man/systemd.html",
"systemd-ac-power(1)": "https://www.freedesktop.org/software/systemd/man/systemd-ac-power.html",
"systemd-analyze(1)": "https://www.freedesktop.org/software/systemd/man/systemd-analyze.html",
"systemd-ask-password(1)": "https://www.freedesktop.org/software/systemd/man/systemd-ask-password.html",
"systemd-sleep.conf(5)": "https://www.freedesktop.org/software/systemd/man/systemd-sleep.conf.html",
"systemd-system.conf(5)": "https://www.freedesktop.org/software/systemd/man/systemd-system.conf.html",
"systemd-user-runtime-dir(5)": "https://www.freedesktop.org/software/systemd/man/systemd-user-runtime-dir.html",
"systemd-user.conf(5)": "https://www.freedesktop.org/software/systemd/man/systemd-user.conf.html",
"systemd.automount(5)": "https://www.freedesktop.org/software/systemd/man/systemd.automount.html",
"systemd.device(5)": "https://www.freedesktop.org/software/systemd/man/systemd.device.html",
"systemd.dnssd(5)": "https://www.freedesktop.org/software/systemd/man/systemd.dnssd.html",
"systemd.exec(5)": "https://www.freedesktop.org/software/systemd/man/systemd.exec.html",
"systemd.kill(5)": "https://www.freedesktop.org/software/systemd/man/systemd.kill.html",
"systemd.link(5)": "https://www.freedesktop.org/software/systemd/man/systemd.link.html",
"systemd.mount(5)": "https://www.freedesktop.org/software/systemd/man/systemd.mount.html",
"systemd.negative(5)": "https://www.freedesktop.org/software/systemd/man/systemd.negative.html",
"systemd.netdev(5)": "https://www.freedesktop.org/software/systemd/man/systemd.netdev.html",
"systemd.network(5)": "https://www.freedesktop.org/software/systemd/man/systemd.network.html",
"systemd.nspawn(5)": "https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html",
"systemd.path(5)": "https://www.freedesktop.org/software/systemd/man/systemd.path.html",
"systemd.positive(5)": "https://www.freedesktop.org/software/systemd/man/systemd.positive.html",
"systemd.preset(5)": "https://www.freedesktop.org/software/systemd/man/systemd.preset.html",
"systemd.resource-control(5)": "https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html",
"systemd.scope(5)": "https://www.freedesktop.org/software/systemd/man/systemd.scope.html",
"systemd.service(5)": "https://www.freedesktop.org/software/systemd/man/systemd.service.html",
"systemd.slice(5)": "https://www.freedesktop.org/software/systemd/man/systemd.slice.html",
"systemd.socket(5)": "https://www.freedesktop.org/software/systemd/man/systemd.socket.html",
"systemd.swap(5)": "https://www.freedesktop.org/software/systemd/man/systemd.swap.html",
"systemd.target(5)": "https://www.freedesktop.org/software/systemd/man/systemd.target.html",
"systemd.timer(5)": "https://www.freedesktop.org/software/systemd/man/systemd.timer.html",
"systemd.unit(5)": "https://www.freedesktop.org/software/systemd/man/systemd.unit.html",
"sysupdate.d(5)": "https://www.freedesktop.org/software/systemd/man/sysupdate.d.html",
"sysusers.d(5)": "https://www.freedesktop.org/software/systemd/man/sysusers.d.html",
"timesyncd.conf(5)": "https://www.freedesktop.org/software/systemd/man/timesyncd.conf.html",
"timesyncd.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/timesyncd.conf.d.html",
"tmpfiles.d(5)": "https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html",
"udev.conf(5)": "https://www.freedesktop.org/software/systemd/man/udev.conf.html",
"user-runtime-dir@.service(5)": "https://www.freedesktop.org/software/systemd/man/user-runtime-dir@.service.html",
"user.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/user.conf.d.html",
"user@.service(5)": "https://www.freedesktop.org/software/systemd/man/user@.service.html",
"vconsole.conf(5)": "https://www.freedesktop.org/software/systemd/man/vconsole.conf.html",
"veritytab(5)": "https://www.freedesktop.org/software/systemd/man/veritytab.html",
"bootup(7)": "https://www.freedesktop.org/software/systemd/man/bootup.html",
"daemon(7)": "https://www.freedesktop.org/software/systemd/man/daemon.html",
"file-hierarchy(7)": "https://www.freedesktop.org/software/systemd/man/file-hierarchy.html",
"hwdb(7)": "https://www.freedesktop.org/software/systemd/man/hwdb.html",
"kernel-command-line(7)": "https://www.freedesktop.org/software/systemd/man/kernel-command-line.html",
"linuxaa64.efi.stub(7)": "https://www.freedesktop.org/software/systemd/man/linuxaa64.efi.stub.html",
"linuxia32.efi.stub(7)": "https://www.freedesktop.org/software/systemd/man/linuxia32.efi.stub.html",
"linuxx64.efi.stub(7)": "https://www.freedesktop.org/software/systemd/man/linuxx64.efi.stub.html",
"sd-boot(7)": "https://www.freedesktop.org/software/systemd/man/sd-boot.html",
"sd-stub(7)": "https://www.freedesktop.org/software/systemd/man/sd-stub.html",
"smbios-type-11(7)": "https://www.freedesktop.org/software/systemd/man/smbios-type-11.html",
"systemd-boot(7)": "https://www.freedesktop.org/software/systemd/man/systemd-boot.html",
"systemd-stub(7)": "https://www.freedesktop.org/software/systemd/man/systemd-stub.html",
"systemd.directives(7)": "https://www.freedesktop.org/software/systemd/man/systemd.directives.html",
"systemd.environment-generator(7)": "https://www.freedesktop.org/software/systemd/man/systemd.environment-generator.html",
"systemd.generator(7)": "https://www.freedesktop.org/software/systemd/man/systemd.generator.html",
"systemd.image-policy(7)": "https://www.freedesktop.org/software/systemd/man/systemd.image-policy.html",
"systemd.index(7)": "https://www.freedesktop.org/software/systemd/man/systemd.index.html",
"systemd.journal-fields(7)": "https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html",
"systemd.net-naming-scheme(7)": "https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html",
"systemd.offline-updates(7)": "https://www.freedesktop.org/software/systemd/man/systemd.offline-updates.html",
"systemd.special(7)": "https://www.freedesktop.org/software/systemd/man/systemd.special.html",
"systemd.syntax(7)": "https://www.freedesktop.org/software/systemd/man/systemd.syntax.html",
"systemd.system-credentials(7)": "https://www.freedesktop.org/software/systemd/man/systemd.system-credentials.html",
"systemd.time(7)": "https://www.freedesktop.org/software/systemd/man/systemd.time.html",
"udev(7)": "https://www.freedesktop.org/software/systemd/man/udev.html",
"30-systemd-environment-d-generator(8)": "https://www.freedesktop.org/software/systemd/man/30-systemd-environment-d-generator.html",
"halt(8)": "https://www.freedesktop.org/software/systemd/man/halt.html",
"kernel-install(8)": "https://www.freedesktop.org/software/systemd/man/kernel-install.html",
"libnss_myhostname.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_myhostname.so.2.html",
"libnss_mymachines.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_mymachines.so.2.html",
"libnss_resolve.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_resolve.so.2.html",
"libnss_systemd.so.2(8)": "https://www.freedesktop.org/software/systemd/man/libnss_systemd.so.2.html",
"nss-myhostname(8)": "https://www.freedesktop.org/software/systemd/man/nss-myhostname.html",
"nss-mymachines(8)": "https://www.freedesktop.org/software/systemd/man/nss-mymachines.html",
"nss-resolve(8)": "https://www.freedesktop.org/software/systemd/man/nss-resolve.html",
"nss-systemd(8)": "https://www.freedesktop.org/software/systemd/man/nss-systemd.html",
"pam_systemd(8)": "https://www.freedesktop.org/software/systemd/man/pam_systemd.html",
"pam_systemd_home(8)": "https://www.freedesktop.org/software/systemd/man/pam_systemd_home.html",
"poweroff(8)": "https://www.freedesktop.org/software/systemd/man/poweroff.html",
"reboot(8)": "https://www.freedesktop.org/software/systemd/man/reboot.html",
"shutdown(8)": "https://www.freedesktop.org/software/systemd/man/shutdown.html",
"systemd-ask-password-console.path(8)": "https://www.freedesktop.org/software/systemd/man/systemd-ask-password-console.path.html",
"systemd-ask-password-console.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-ask-password-console.service.html",
"systemd-ask-password-wall.path(8)": "https://www.freedesktop.org/software/systemd/man/systemd-ask-password-wall.path.html",
@@ -122,63 +193,51 @@
"systemd-backlight@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-backlight@.service.html",
"systemd-battery-check(8)": "https://www.freedesktop.org/software/systemd/man/systemd-battery-check.html",
"systemd-binfmt(8)": "https://www.freedesktop.org/software/systemd/man/systemd-binfmt.html",
"systemd-bless-boot(8)": "https://www.freedesktop.org/software/systemd/man/systemd-bless-boot.html",
"systemd-bless-boot-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-bless-boot-generator.html",
"systemd-boot(7)": "https://www.freedesktop.org/software/systemd/man/systemd-boot.html",
"systemd-bless-boot(8)": "https://www.freedesktop.org/software/systemd/man/systemd-bless-boot.html",
"systemd-boot-check-no-failures(8)": "https://www.freedesktop.org/software/systemd/man/systemd-boot-check-no-failures.html",
"systemd-boot-random-seed.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-boot-random-seed.service.html",
"systemd-cat(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cat.html",
"systemd-cgls(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cgls.html",
"systemd-cgtop(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cgtop.html",
"systemd-confext(8)": "https://www.freedesktop.org/software/systemd/man/systemd-confext.html",
"systemd-confext.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-confext.service.html",
"systemd-coredump(8)": "https://www.freedesktop.org/software/systemd/man/systemd-coredump.html",
"systemd-coredump.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-coredump.socket.html",
"systemd-coredump@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-coredump@.service.html",
"systemd-creds(1)": "https://www.freedesktop.org/software/systemd/man/systemd-creds.html",
"systemd-cryptenroll(1)": "https://www.freedesktop.org/software/systemd/man/systemd-cryptenroll.html",
"systemd-cryptsetup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-cryptsetup.html",
"systemd-cryptsetup-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-cryptsetup-generator.html",
"systemd-cryptsetup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-cryptsetup.html",
"systemd-cryptsetup@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-cryptsetup@.service.html",
"systemd-debug-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-debug-generator.html",
"systemd-delta(1)": "https://www.freedesktop.org/software/systemd/man/systemd-delta.html",
"systemd-detect-virt(1)": "https://www.freedesktop.org/software/systemd/man/systemd-detect-virt.html",
"systemd-dissect(1)": "https://www.freedesktop.org/software/systemd/man/systemd-dissect.html",
"systemd-environment-d-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-environment-d-generator.html",
"systemd-escape(1)": "https://www.freedesktop.org/software/systemd/man/systemd-escape.html",
"systemd-fsck(8)": "https://www.freedesktop.org/software/systemd/man/systemd-fsck.html",
"systemd-fsck-root.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-fsck-root.service.html",
"systemd-fsck-usr.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-fsck-usr.service.html",
"systemd-fsck(8)": "https://www.freedesktop.org/software/systemd/man/systemd-fsck.html",
"systemd-fsck@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-fsck@.service.html",
"systemd-fstab-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-fstab-generator.html",
"systemd-getty-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-getty-generator.html",
"systemd-gpt-auto-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-gpt-auto-generator.html",
"systemd-growfs(8)": "https://www.freedesktop.org/software/systemd/man/systemd-growfs.html",
"systemd-growfs-root.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-growfs-root.service.html",
"systemd-growfs(8)": "https://www.freedesktop.org/software/systemd/man/systemd-growfs.html",
"systemd-growfs@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-growfs@.service.html",
"systemd-halt.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-halt.service.html",
"systemd-hibernate-resume(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hibernate-resume.html",
"systemd-hibernate-resume-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hibernate-resume-generator.html",
"systemd-hibernate-resume(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hibernate-resume.html",
"systemd-hibernate.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hibernate.service.html",
"systemd-homed(8)": "https://www.freedesktop.org/software/systemd/man/systemd-homed.html",
"systemd-hostnamed(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hostnamed.html",
"systemd-hwdb(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hwdb.html",
"systemd-hybrid-sleep.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-hybrid-sleep.service.html",
"systemd-id128(1)": "https://www.freedesktop.org/software/systemd/man/systemd-id128.html",
"systemd-importd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-importd.html",
"systemd-inhibit(1)": "https://www.freedesktop.org/software/systemd/man/systemd-inhibit.html",
"systemd-integritysetup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-integritysetup.html",
"systemd-integritysetup-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-integritysetup-generator.html",
"systemd-integritysetup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-integritysetup.html",
"systemd-integritysetup@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-integritysetup@.service.html",
"systemd-journal-gatewayd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journal-gatewayd.html",
"systemd-journal-gatewayd.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journal-gatewayd.socket.html",
"systemd-journal-remote(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journal-remote.html",
"systemd-journal-remote.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journal-remote.socket.html",
"systemd-journal-upload(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journal-upload.html",
"systemd-journald(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald.html",
"systemd-journald-audit.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald-audit.socket.html",
"systemd-journald-dev-log.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald-dev-log.socket.html",
"systemd-journald-varlink@.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald-varlink@.socket.html",
"systemd-journald(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald.html",
"systemd-journald.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald.socket.html",
"systemd-journald@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald@.service.html",
"systemd-journald@.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-journald@.socket.html",
@@ -186,28 +245,22 @@
"systemd-localed(8)": "https://www.freedesktop.org/software/systemd/man/systemd-localed.html",
"systemd-logind(8)": "https://www.freedesktop.org/software/systemd/man/systemd-logind.html",
"systemd-machine-id-commit.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-machine-id-commit.service.html",
"systemd-machine-id-setup(1)": "https://www.freedesktop.org/software/systemd/man/systemd-machine-id-setup.html",
"systemd-machined(8)": "https://www.freedesktop.org/software/systemd/man/systemd-machined.html",
"systemd-makefs(8)": "https://www.freedesktop.org/software/systemd/man/systemd-makefs.html",
"systemd-makefs@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-makefs@.service.html",
"systemd-measure(1)": "https://www.freedesktop.org/software/systemd/man/systemd-measure.html",
"systemd-mkswap@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-mkswap@.service.html",
"systemd-modules-load(8)": "https://www.freedesktop.org/software/systemd/man/systemd-modules-load.html",
"systemd-mount(1)": "https://www.freedesktop.org/software/systemd/man/systemd-mount.html",
"systemd-network-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-network-generator.html",
"systemd-networkd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-networkd.html",
"systemd-networkd-wait-online(8)": "https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.html",
"systemd-networkd-wait-online@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online@.service.html",
"systemd-notify(1)": "https://www.freedesktop.org/software/systemd/man/systemd-notify.html",
"systemd-nspawn(1)": "https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html",
"systemd-networkd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-networkd.html",
"systemd-oomd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-oomd.html",
"systemd-path(1)": "https://www.freedesktop.org/software/systemd/man/systemd-path.html",
"systemd-pcrfs-root.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrfs-root.service.html",
"systemd-pcrfs@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrfs@.service.html",
"systemd-pcrmachine.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrmachine.service.html",
"systemd-pcrphase(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrphase.html",
"systemd-pcrphase-initrd.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrphase-initrd.service.html",
"systemd-pcrphase-sysinit.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrphase-sysinit.service.html",
"systemd-pcrphase(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pcrphase.html",
"systemd-portabled(8)": "https://www.freedesktop.org/software/systemd/man/systemd-portabled.html",
"systemd-poweroff.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-poweroff.service.html",
"systemd-pstore(8)": "https://www.freedesktop.org/software/systemd/man/systemd-pstore.html",
@@ -219,26 +272,20 @@
"systemd-resolved(8)": "https://www.freedesktop.org/software/systemd/man/systemd-resolved.html",
"systemd-rfkill(8)": "https://www.freedesktop.org/software/systemd/man/systemd-rfkill.html",
"systemd-rfkill.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-rfkill.socket.html",
"systemd-run(1)": "https://www.freedesktop.org/software/systemd/man/systemd-run.html",
"systemd-run-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-run-generator.html",
"systemd-shutdown(8)": "https://www.freedesktop.org/software/systemd/man/systemd-shutdown.html",
"systemd-sleep(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sleep.html",
"systemd-sleep.conf(5)": "https://www.freedesktop.org/software/systemd/man/systemd-sleep.conf.html",
"systemd-socket-activate(1)": "https://www.freedesktop.org/software/systemd/man/systemd-socket-activate.html",
"systemd-socket-proxyd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-socket-proxyd.html",
"systemd-soft-reboot.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-soft-reboot.service.html",
"systemd-stdio-bridge(1)": "https://www.freedesktop.org/software/systemd/man/systemd-stdio-bridge.html",
"systemd-stub(7)": "https://www.freedesktop.org/software/systemd/man/systemd-stub.html",
"systemd-suspend-then-hibernate.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-suspend-then-hibernate.service.html",
"systemd-suspend.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-suspend.service.html",
"systemd-sysctl(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysctl.html",
"systemd-sysext(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysext.html",
"systemd-sysext.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysext.service.html",
"systemd-system-update-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-system-update-generator.html",
"systemd-system.conf(5)": "https://www.freedesktop.org/software/systemd/man/systemd-system.conf.html",
"systemd-sysupdate(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html",
"systemd-sysupdate-reboot.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysupdate-reboot.service.html",
"systemd-sysupdate-reboot.timer(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysupdate-reboot.timer.html",
"systemd-sysupdate(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html",
"systemd-sysupdate.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.service.html",
"systemd-sysupdate.timer(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.timer.html",
"systemd-sysusers(8)": "https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html",
@@ -246,80 +293,34 @@
"systemd-time-wait-sync(8)": "https://www.freedesktop.org/software/systemd/man/systemd-time-wait-sync.html",
"systemd-timedated(8)": "https://www.freedesktop.org/software/systemd/man/systemd-timedated.html",
"systemd-timesyncd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-timesyncd.html",
"systemd-tmpfiles(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles.html",
"systemd-tmpfiles-clean.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles-clean.service.html",
"systemd-tmpfiles-clean.timer(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles-clean.timer.html",
"systemd-tmpfiles-setup-dev-early.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles-setup-dev-early.service.html",
"systemd-tmpfiles-setup-dev.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles-setup-dev.service.html",
"systemd-tmpfiles-setup.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles-setup.service.html",
"systemd-tty-ask-password-agent(1)": "https://www.freedesktop.org/software/systemd/man/systemd-tty-ask-password-agent.html",
"systemd-tmpfiles(8)": "https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles.html",
"systemd-udev-settle.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-udev-settle.service.html",
"systemd-udevd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-udevd.html",
"systemd-udevd-control.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-udevd-control.socket.html",
"systemd-udevd-kernel.socket(8)": "https://www.freedesktop.org/software/systemd/man/systemd-udevd-kernel.socket.html",
"systemd-umount(1)": "https://www.freedesktop.org/software/systemd/man/systemd-umount.html",
"systemd-udevd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-udevd.html",
"systemd-update-done(8)": "https://www.freedesktop.org/software/systemd/man/systemd-update-done.html",
"systemd-update-utmp(8)": "https://www.freedesktop.org/software/systemd/man/systemd-update-utmp.html",
"systemd-update-utmp-runlevel.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-update-utmp-runlevel.service.html",
"systemd-user-runtime-dir(5)": "https://www.freedesktop.org/software/systemd/man/systemd-user-runtime-dir.html",
"systemd-update-utmp(8)": "https://www.freedesktop.org/software/systemd/man/systemd-update-utmp.html",
"systemd-user-sessions(8)": "https://www.freedesktop.org/software/systemd/man/systemd-user-sessions.html",
"systemd-user.conf(5)": "https://www.freedesktop.org/software/systemd/man/systemd-user.conf.html",
"systemd-userdbd(8)": "https://www.freedesktop.org/software/systemd/man/systemd-userdbd.html",
"systemd-vconsole-setup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-vconsole-setup.html",
"systemd-veritysetup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-veritysetup.html",
"systemd-veritysetup-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-veritysetup-generator.html",
"systemd-veritysetup(8)": "https://www.freedesktop.org/software/systemd/man/systemd-veritysetup.html",
"systemd-veritysetup@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-veritysetup@.service.html",
"systemd-volatile-root(8)": "https://www.freedesktop.org/software/systemd/man/systemd-volatile-root.html",
"systemd-xdg-autostart-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-xdg-autostart-generator.html",
"systemd.automount(5)": "https://www.freedesktop.org/software/systemd/man/systemd.automount.html",
"systemd.device(5)": "https://www.freedesktop.org/software/systemd/man/systemd.device.html",
"systemd.directives(7)": "https://www.freedesktop.org/software/systemd/man/systemd.directives.html",
"systemd.dnssd(5)": "https://www.freedesktop.org/software/systemd/man/systemd.dnssd.html",
"systemd.environment-generator(7)": "https://www.freedesktop.org/software/systemd/man/systemd.environment-generator.html",
"systemd.exec(5)": "https://www.freedesktop.org/software/systemd/man/systemd.exec.html",
"systemd.generator(7)": "https://www.freedesktop.org/software/systemd/man/systemd.generator.html",
"systemd.image-policy(7)": "https://www.freedesktop.org/software/systemd/man/systemd.image-policy.html",
"systemd.index(7)": "https://www.freedesktop.org/software/systemd/man/systemd.index.html",
"systemd.journal-fields(7)": "https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html",
"systemd.kill(5)": "https://www.freedesktop.org/software/systemd/man/systemd.kill.html",
"systemd.link(5)": "https://www.freedesktop.org/software/systemd/man/systemd.link.html",
"systemd.mount(5)": "https://www.freedesktop.org/software/systemd/man/systemd.mount.html",
"systemd.negative(5)": "https://www.freedesktop.org/software/systemd/man/systemd.negative.html",
"systemd.net-naming-scheme(7)": "https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html",
"systemd.netdev(5)": "https://www.freedesktop.org/software/systemd/man/systemd.netdev.html",
"systemd.network(5)": "https://www.freedesktop.org/software/systemd/man/systemd.network.html",
"systemd.nspawn(5)": "https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html",
"systemd.offline-updates(7)": "https://www.freedesktop.org/software/systemd/man/systemd.offline-updates.html",
"systemd.path(5)": "https://www.freedesktop.org/software/systemd/man/systemd.path.html",
"systemd.positive(5)": "https://www.freedesktop.org/software/systemd/man/systemd.positive.html",
"systemd.preset(5)": "https://www.freedesktop.org/software/systemd/man/systemd.preset.html",
"systemd.resource-control(5)": "https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html",
"systemd.scope(5)": "https://www.freedesktop.org/software/systemd/man/systemd.scope.html",
"systemd.service(5)": "https://www.freedesktop.org/software/systemd/man/systemd.service.html",
"systemd.slice(5)": "https://www.freedesktop.org/software/systemd/man/systemd.slice.html",
"systemd.socket(5)": "https://www.freedesktop.org/software/systemd/man/systemd.socket.html",
"systemd.special(7)": "https://www.freedesktop.org/software/systemd/man/systemd.special.html",
"systemd.swap(5)": "https://www.freedesktop.org/software/systemd/man/systemd.swap.html",
"systemd.syntax(7)": "https://www.freedesktop.org/software/systemd/man/systemd.syntax.html",
"systemd.system-credentials(7)": "https://www.freedesktop.org/software/systemd/man/systemd.system-credentials.html",
"systemd.target(5)": "https://www.freedesktop.org/software/systemd/man/systemd.target.html",
"systemd.time(7)": "https://www.freedesktop.org/software/systemd/man/systemd.time.html",
"systemd.timer(5)": "https://www.freedesktop.org/software/systemd/man/systemd.timer.html",
"systemd.unit(5)": "https://www.freedesktop.org/software/systemd/man/systemd.unit.html",
"sysupdate.d(5)": "https://www.freedesktop.org/software/systemd/man/sysupdate.d.html",
"sysusers.d(5)": "https://www.freedesktop.org/software/systemd/man/sysusers.d.html",
"timedatectl(1)": "https://www.freedesktop.org/software/systemd/man/timedatectl.html",
"timesyncd.conf(5)": "https://www.freedesktop.org/software/systemd/man/timesyncd.conf.html",
"timesyncd.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/timesyncd.conf.d.html",
"tmpfiles.d(5)": "https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html",
"udev(7)": "https://www.freedesktop.org/software/systemd/man/udev.html",
"udev.conf(5)": "https://www.freedesktop.org/software/systemd/man/udev.conf.html",
"udevadm(8)": "https://www.freedesktop.org/software/systemd/man/udevadm.html",
"passwd(5)": "https://man.archlinux.org/man/passwd.5",
"group(5)": "https://man.archlinux.org/man/group.5",
"login.defs(5)": "https://man.archlinux.org/man/login.defs.5",
"unshare(1)": "https://man.archlinux.org/man/unshare.1.en",
"user-runtime-dir@.service(5)": "https://www.freedesktop.org/software/systemd/man/user-runtime-dir@.service.html",
"user.conf.d(5)": "https://www.freedesktop.org/software/systemd/man/user.conf.d.html",
"user@.service(5)": "https://www.freedesktop.org/software/systemd/man/user@.service.html",
"userdbctl(1)": "https://www.freedesktop.org/software/systemd/man/userdbctl.html",
"vconsole.conf(5)": "https://www.freedesktop.org/software/systemd/man/vconsole.conf.html",
"veritytab(5)": "https://www.freedesktop.org/software/systemd/man/veritytab.html"
"nix-shell(1)": "https://nixos.org/manual/nix/stable/command-ref/nix-shell.html",
"mksquashfs(1)": "https://man.archlinux.org/man/extra/squashfs-tools/mksquashfs.1.en",
"curl(1)": "https://curl.se/docs/manpage.html",
"netrc(5)": "https://man.cx/netrc"
}

View File

@@ -8,4 +8,4 @@ HTTP has a couple of different mechanisms for caching to prevent clients from ha
Fortunately, HTTP supports an alternative (and more effective) caching mechanism: the [`ETag`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) response header. The value of the `ETag` header specifies some identifier for the particular content that the server is sending (e.g., a hash). When a client makes a second request for the same resource, it sends that value back in an `If-None-Match` header. If the ETag value is unchanged, then the server does not need to resend the content.
The nginx package in Nixpkgs is patched such that when nginx serves a file out of `/nix/store`, the hash in the store path is used as the `ETag` header in the HTTP response, thus providing proper caching functionality. With NixOS 24.05 and later, the `ETag` additionally includes the response content length, to ensure files served with static compression do not share `ETag`s with their uncompressed version. This `ETag` functionality is enabled automatically; you do not need to do modify any configuration to get this behavior.
As of NixOS 19.09, the nginx package in Nixpkgs is patched such that when nginx serves a file out of `/nix/store`, the hash in the store path is used as the `ETag` header in the HTTP response, thus providing proper caching functionality. With NixOS 24.05 and later, the `ETag` additionally includes the response content length, to ensure files served with static compression do not share `ETag`s with their uncompressed version. This `ETag` functionality is enabled automatically; you do not need to do modify any configuration to get this behavior.

View File

@@ -31,6 +31,7 @@ Use `programs.steam.enable = true;` if you want to add steam to `systemPackages`
- **Using the FOSS Radeon or nouveau (nvidia) drivers**
- The `newStdcpp` parameter was removed since NixOS 17.09 and should not be needed anymore.
- Steam ships statically linked with a version of `libcrypto` that conflicts with the one dynamically loaded by radeonsi_dri.so. If you get the error:
```

File diff suppressed because it is too large Load Diff

View File

@@ -165,7 +165,7 @@ These paths will need to be replaced with relative paths and the xcbuild package
stdenv.mkDerivation {
name = "libfoo-1.2.3";
postPatch = ''
substituteInPlace Makefile \
subsituteInPlace Makefile \
--replace-fail '/usr/bin/xcodebuild' 'xcodebuild' \
--replace-fail '/usr/bin/xcrun' 'xcrun' \
--replace-fail '/usr/bin/PListBuddy' 'PListBuddy'

View File

@@ -886,7 +886,7 @@ Like `stripAllList`, but only applies to packages target platform. By default
##### `stripAllFlags` {#var-stdenv-stripAllFlags}
Flags passed to the `strip` command applied to the files in the directories listed in `stripAllList`. Defaults to `-s -p` (i.e. `--strip-all --preserve-dates`).
Flags passed to the `strip` command applied to the files in the directories listed in `stripAllList`. Defaults to `-s` (i.e. `--strip-all`).
##### `stripDebugList` {#var-stdenv-stripDebugList}
@@ -898,7 +898,7 @@ Like `stripDebugList`, but only applies to packages target platform. By defau
##### `stripDebugFlags` {#var-stdenv-stripDebugFlags}
Flags passed to the `strip` command applied to the files in the directories listed in `stripDebugList`. Defaults to `-S -p` (i.e. `--strip-debug --preserve-dates`).
Flags passed to the `strip` command applied to the files in the directories listed in `stripDebugList`. Defaults to `-S` (i.e. `--strip-debug`).
##### `stripExclude` {#var-stdenv-stripExclude}

View File

@@ -17,7 +17,7 @@ invalidateFetcherByDrvHash (
{
nativeBuildInputs = [
cacert
(python3.pythonOnBuildForHost.withPackages (p: [
(python3.withPackages (p: [
p.aiohttp
p.rich
p.structlog

View File

@@ -154,13 +154,11 @@ There are several ways to tweak how Nix handles a package which has been marked
The `allowInsecurePredicate` option is a function which accepts a package and returns a boolean, much like `allowUnfreePredicate`.
The following configuration example allows any version of the `ovftool` package:
The following configuration example only allows insecure packages with very short names:
```nix
{
allowInsecurePredicate = pkg: builtins.elem (lib.getName pkg) [
"ovftool"
];
allowInsecurePredicate = pkg: builtins.stringLength (lib.getName pkg) <= 5;
}
```

View File

@@ -1 +1 @@
25.05
24.11

View File

@@ -1,100 +1,99 @@
{
"\t" = 9;
{ "\t" = 9;
"\n" = 10;
"\r" = 13;
" " = 32;
"!" = 33;
" " = 32;
"!" = 33;
"\"" = 34;
"#" = 35;
"$" = 36;
"%" = 37;
"&" = 38;
"'" = 39;
"(" = 40;
")" = 41;
"*" = 42;
"+" = 43;
"," = 44;
"-" = 45;
"." = 46;
"/" = 47;
"0" = 48;
"1" = 49;
"2" = 50;
"3" = 51;
"4" = 52;
"5" = 53;
"6" = 54;
"7" = 55;
"8" = 56;
"9" = 57;
":" = 58;
";" = 59;
"<" = 60;
"=" = 61;
">" = 62;
"?" = 63;
"@" = 64;
"A" = 65;
"B" = 66;
"C" = 67;
"D" = 68;
"E" = 69;
"F" = 70;
"G" = 71;
"H" = 72;
"I" = 73;
"J" = 74;
"K" = 75;
"L" = 76;
"M" = 77;
"N" = 78;
"O" = 79;
"P" = 80;
"Q" = 81;
"R" = 82;
"S" = 83;
"T" = 84;
"U" = 85;
"V" = 86;
"W" = 87;
"X" = 88;
"Y" = 89;
"Z" = 90;
"[" = 91;
"#" = 35;
"$" = 36;
"%" = 37;
"&" = 38;
"'" = 39;
"(" = 40;
")" = 41;
"*" = 42;
"+" = 43;
"," = 44;
"-" = 45;
"." = 46;
"/" = 47;
"0" = 48;
"1" = 49;
"2" = 50;
"3" = 51;
"4" = 52;
"5" = 53;
"6" = 54;
"7" = 55;
"8" = 56;
"9" = 57;
":" = 58;
";" = 59;
"<" = 60;
"=" = 61;
">" = 62;
"?" = 63;
"@" = 64;
"A" = 65;
"B" = 66;
"C" = 67;
"D" = 68;
"E" = 69;
"F" = 70;
"G" = 71;
"H" = 72;
"I" = 73;
"J" = 74;
"K" = 75;
"L" = 76;
"M" = 77;
"N" = 78;
"O" = 79;
"P" = 80;
"Q" = 81;
"R" = 82;
"S" = 83;
"T" = 84;
"U" = 85;
"V" = 86;
"W" = 87;
"X" = 88;
"Y" = 89;
"Z" = 90;
"[" = 91;
"\\" = 92;
"]" = 93;
"^" = 94;
"_" = 95;
"`" = 96;
"a" = 97;
"b" = 98;
"c" = 99;
"d" = 100;
"e" = 101;
"f" = 102;
"g" = 103;
"h" = 104;
"i" = 105;
"j" = 106;
"k" = 107;
"l" = 108;
"m" = 109;
"n" = 110;
"o" = 111;
"p" = 112;
"q" = 113;
"r" = 114;
"s" = 115;
"t" = 116;
"u" = 117;
"v" = 118;
"w" = 119;
"x" = 120;
"y" = 121;
"z" = 122;
"{" = 123;
"|" = 124;
"}" = 125;
"~" = 126;
"]" = 93;
"^" = 94;
"_" = 95;
"`" = 96;
"a" = 97;
"b" = 98;
"c" = 99;
"d" = 100;
"e" = 101;
"f" = 102;
"g" = 103;
"h" = 104;
"i" = 105;
"j" = 106;
"k" = 107;
"l" = 108;
"m" = 109;
"n" = 110;
"o" = 111;
"p" = 112;
"q" = 113;
"r" = 114;
"s" = 115;
"t" = 116;
"u" = 117;
"v" = 118;
"w" = 119;
"x" = 120;
"y" = 121;
"z" = 122;
"{" = 123;
"|" = 124;
"}" = 125;
"~" = 126;
}

View File

@@ -36,7 +36,10 @@ rec {
:::
*/
# TODO(Profpatsch): add tests that check stderr
assertMsg = pred: msg: pred || builtins.throw msg;
assertMsg =
pred:
msg:
pred || builtins.throw msg;
/**
Specialized `assertMsg` for checking if `val` is one of the elements
@@ -78,10 +81,14 @@ rec {
:::
*/
assertOneOf =
name: val: xs:
assertMsg (lib.elem val xs) "${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${
lib.generators.toPretty { } val
}";
name:
val:
xs:
assertMsg
(lib.elem val xs)
"${name} must be one of ${
lib.generators.toPretty {} xs}, but is: ${
lib.generators.toPretty {} val}";
/**
Specialized `assertMsg` for checking if every one of `vals` is one of the elements
@@ -126,9 +133,12 @@ rec {
:::
*/
assertEachOneOf =
name: vals: xs:
assertMsg (lib.all (val: lib.elem val xs) vals)
"each element in ${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${
lib.generators.toPretty { } vals
}";
name:
vals:
xs:
assertMsg
(lib.all (val: lib.elem val xs) vals)
"each element in ${name} must be one of ${
lib.generators.toPretty {} xs}, but is: ${
lib.generators.toPretty {} vals}";
}

View File

@@ -9,6 +9,7 @@ rec {
`toGNUCommandLineShell` returns an escaped shell string.
# Inputs
`options`
@@ -19,6 +20,7 @@ rec {
: The attributes to transform into arguments.
# Examples
:::{.example}
## `lib.cli.toGNUCommandLineShell` usage example
@@ -38,13 +40,15 @@ rec {
:::
*/
toGNUCommandLineShell = options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);
toGNUCommandLineShell =
options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);
/**
Automatically convert an attribute set to a list of command-line options.
`toGNUCommandLine` returns a list of string arguments.
# Inputs
`options`
@@ -72,6 +76,7 @@ rec {
: How to format a list value to a command list;
By default the option name is repeated for each value and `mkOption` is applied to the values themselves.
`mkOption`
: How to format any remaining value to a command list;
@@ -84,6 +89,7 @@ rec {
By default, there is no separator, so option `-c` and value `5` would become ["-c" "5"].
This is useful if the command requires equals, for example, `-c=5`.
# Examples
:::{.example}
## `lib.cli.toGNUCommandLine` usage example
@@ -110,39 +116,33 @@ rec {
:::
*/
toGNUCommandLine =
{
mkOptionName ? k: if builtins.stringLength k == 1 then "-${k}" else "--${k}",
toGNUCommandLine = {
mkOptionName ?
k: if builtins.stringLength k == 1
then "-${k}"
else "--${k}",
mkBool ? k: v: lib.optional v (mkOptionName k),
mkBool ? k: v: lib.optional v (mkOptionName k),
mkList ? k: v: lib.concatMap (mkOption k) v,
mkList ? k: v: lib.concatMap (mkOption k) v,
mkOption ?
k: v:
if v == null then
[ ]
else if optionValueSeparator == null then
[
(mkOptionName k)
(lib.generators.mkValueStringDefault { } v)
]
else
[ "${mkOptionName k}${optionValueSeparator}${lib.generators.mkValueStringDefault { } v}" ],
mkOption ?
k: v: if v == null
then []
else if optionValueSeparator == null then
[ (mkOptionName k) (lib.generators.mkValueStringDefault {} v) ]
else
[ "${mkOptionName k}${optionValueSeparator}${lib.generators.mkValueStringDefault {} v}" ],
optionValueSeparator ? null,
optionValueSeparator ? null
}:
options:
let
render =
k: v:
if builtins.isBool v then
mkBool k v
else if builtins.isList v then
mkList k v
else
mkOption k v;
let
render = k: v:
if builtins.isBool v then mkBool k v
else if builtins.isList v then mkList k v
else mkOption k v;
in
builtins.concatLists (lib.mapAttrsToList render options);
in
builtins.concatLists (lib.mapAttrsToList render options);
}

View File

@@ -2,41 +2,19 @@
let
inherit (builtins)
intersectAttrs
;
intersectAttrs;
inherit (lib)
functionArgs
isFunction
mirrorFunctionArgs
isAttrs
setFunctionArgs
optionalAttrs
attrNames
filter
elemAt
concatStringsSep
sortOn
take
length
filterAttrs
optionalString
flip
pathIsDirectory
head
pipe
isDerivation
listToAttrs
mapAttrs
seq
flatten
deepSeq
extends
functionArgs isFunction mirrorFunctionArgs isAttrs setFunctionArgs
optionalAttrs attrNames filter elemAt concatStringsSep sortOn take length
filterAttrs optionalString flip pathIsDirectory head pipe isDerivation listToAttrs
mapAttrs seq flatten deepSeq warnIf isInOldestRelease extends
;
inherit (lib.strings) levenshtein levenshteinAtMost;
in
rec {
/**
`overrideDerivation drv f` takes a derivation (i.e., the result
of a call to the builtin function `derivation`) and returns a new
@@ -62,6 +40,7 @@ rec {
You should in general prefer `drv.overrideAttrs` over this function;
see the nixpkgs manual for more information on overriding.
# Inputs
`drv`
@@ -95,21 +74,20 @@ rec {
:::
*/
overrideDerivation =
drv: f:
overrideDerivation = drv: f:
let
newDrv = derivation (drv.drvAttrs // (f drv));
in
flip (extendDerivation (seq drv.drvPath true)) newDrv (
{
meta = drv.meta or { };
passthru = if drv ? passthru then drv.passthru else { };
in flip (extendDerivation (seq drv.drvPath true)) newDrv (
{ meta = drv.meta or {};
passthru = if drv ? passthru then drv.passthru else {};
}
// (drv.passthru or { })
// optionalAttrs (drv ? __spliced) {
__spliced = { } // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
}
);
//
(drv.passthru or {})
//
optionalAttrs (drv ? __spliced) {
__spliced = {} // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
});
/**
`makeOverridable` takes a function from attribute set to attribute set and
@@ -119,6 +97,7 @@ rec {
Please refer to documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
related to its use.
# Inputs
`f`
@@ -149,42 +128,37 @@ rec {
:::
*/
makeOverridable =
f:
makeOverridable = f:
let
# Creates a functor with the same arguments as f
mirrorArgs = mirrorFunctionArgs f;
in
mirrorArgs (
origArgs:
let
result = f origArgs;
mirrorArgs (origArgs:
let
result = f origArgs;
# Changes the original arguments with (potentially a function that returns) a set of new attributes
overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs);
# Changes the original arguments with (potentially a function that returns) a set of new attributes
overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs);
# Re-call the function but with different arguments
overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
# Change the result of the function call by applying g to it
overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
in
# Re-call the function but with different arguments
overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
# Change the result of the function call by applying g to it
overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
in
if isAttrs result then
result
// {
result // {
override = overrideArgs;
overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
${if result ? overrideAttrs then "overrideAttrs" else null} =
fdrv: overrideResult (x: x.overrideAttrs fdrv);
${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv:
overrideResult (x: x.overrideAttrs fdrv);
}
else if isFunction result then
# Transform the result into a functor while propagating its arguments
setFunctionArgs result (functionArgs result)
// {
setFunctionArgs result (functionArgs result) // {
override = overrideArgs;
}
else
result
);
else result);
/**
Call the package function in the file `fn` with the required
@@ -214,6 +188,7 @@ rec {
<!-- TODO: Apply "Example:" tag to the examples above -->
# Inputs
`autoArgs`
@@ -234,8 +209,7 @@ rec {
callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
```
*/
callPackageWith =
autoArgs: fn: args:
callPackageWith = autoArgs: fn: args:
let
f = if isFunction fn then fn else import fn;
fargs = functionArgs f;
@@ -248,72 +222,59 @@ rec {
# wouldn't be passed to it
missingArgs =
# Filter out arguments that have a default value
(
filterAttrs (name: value: !value)
# Filter out arguments that would be passed
(removeAttrs fargs (attrNames allArgs))
);
(filterAttrs (name: value: ! value)
# Filter out arguments that would be passed
(removeAttrs fargs (attrNames allArgs)));
# Get a list of suggested argument names for a given missing one
getSuggestions =
arg:
pipe (autoArgs // args) [
attrNames
# Only use ones that are at most 2 edits away. While mork would work,
# levenshteinAtMost is only fast for 2 or less.
(filter (levenshteinAtMost 2 arg))
# Put strings with shorter distance first
(sortOn (levenshtein arg))
# Only take the first couple results
(take 3)
# Quote all entries
(map (x: "\"" + x + "\""))
];
getSuggestions = arg: pipe (autoArgs // args) [
attrNames
# Only use ones that are at most 2 edits away. While mork would work,
# levenshteinAtMost is only fast for 2 or less.
(filter (levenshteinAtMost 2 arg))
# Put strings with shorter distance first
(sortOn (levenshtein arg))
# Only take the first couple results
(take 3)
# Quote all entries
(map (x: "\"" + x + "\""))
];
prettySuggestions =
suggestions:
if suggestions == [ ] then
""
else if length suggestions == 1 then
", did you mean ${elemAt suggestions 0}?"
else
", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
prettySuggestions = suggestions:
if suggestions == [] then ""
else if length suggestions == 1 then ", did you mean ${elemAt suggestions 0}?"
else ", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
errorForArg =
arg:
errorForArg = arg:
let
loc = builtins.unsafeGetAttrPos arg fargs;
# loc' can be removed once lib/minver.nix is >2.3.4, since that includes
# https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
loc' =
if loc != null then
loc.file + ":" + toString loc.line
else if !isFunction fn then
loc' = if loc != null then loc.file + ":" + toString loc.line
else if ! isFunction fn then
toString fn + optionalString (pathIsDirectory fn) "/default.nix"
else
"<unknown location>";
in
"Function called without required argument \"${arg}\" at "
else "<unknown location>";
in "Function called without required argument \"${arg}\" at "
+ "${loc'}${prettySuggestions (getSuggestions arg)}";
# Only show the error for the first missing argument
error = errorForArg (head (attrNames missingArgs));
in
if missingArgs == { } then
makeOverridable f allArgs
# This needs to be an abort so it can't be caught with `builtins.tryEval`,
# which is used by nix-env and ofborg to filter out packages that don't evaluate.
# This way we're forced to fix such errors in Nixpkgs,
# which is especially relevant with allowAliases = false
else
abort "lib.customisation.callPackageWith: ${error}";
in if missingArgs == {}
then makeOverridable f allArgs
# This needs to be an abort so it can't be caught with `builtins.tryEval`,
# which is used by nix-env and ofborg to filter out packages that don't evaluate.
# This way we're forced to fix such errors in Nixpkgs,
# which is especially relevant with allowAliases = false
else abort "lib.customisation.callPackageWith: ${error}";
/**
Like callPackage, but for a function that returns an attribute
set of derivations. The override function is added to the
individual attributes.
# Inputs
`autoArgs`
@@ -334,8 +295,7 @@ rec {
callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
```
*/
callPackagesWith =
autoArgs: fn: args:
callPackagesWith = autoArgs: fn: args:
let
f = if isFunction fn then fn else import fn;
auto = intersectAttrs (functionArgs f) autoArgs;
@@ -344,19 +304,18 @@ rec {
pkgs = f origArgs;
mkAttrOverridable = name: _: makeOverridable (mirrorArgs (newArgs: (f newArgs).${name})) origArgs;
in
if isDerivation pkgs then
throw (
"function `callPackages` was called on a *single* derivation "
+ ''"${pkgs.name or "<unknown-name>"}";''
+ " did you mean to use `callPackage` instead?"
)
else
mapAttrs mkAttrOverridable pkgs;
if isDerivation pkgs then throw
("function `callPackages` was called on a *single* derivation "
+ ''"${pkgs.name or "<unknown-name>"}";''
+ " did you mean to use `callPackage` instead?")
else mapAttrs mkAttrOverridable pkgs;
/**
Add attributes to each output of a derivation without changing
the derivation itself and check a given condition when evaluating.
# Inputs
`condition`
@@ -377,48 +336,34 @@ rec {
extendDerivation :: Bool -> Any -> Derivation -> Derivation
```
*/
extendDerivation =
condition: passthru: drv:
extendDerivation = condition: passthru: drv:
let
outputs = drv.outputs or [ "out" ];
commonAttrs =
drv // (listToAttrs outputsList) // ({ all = map (x: x.value) outputsList; }) // passthru;
commonAttrs = drv // (listToAttrs outputsList) //
({ all = map (x: x.value) outputsList; }) // passthru;
outputToAttrListElement = outputName: {
name = outputName;
value =
commonAttrs
// {
outputToAttrListElement = outputName:
{ name = outputName;
value = commonAttrs // {
inherit (drv.${outputName}) type outputName;
outputSpecified = true;
drvPath =
assert condition;
drv.${outputName}.drvPath;
outPath =
assert condition;
drv.${outputName}.outPath;
}
//
drvPath = assert condition; drv.${outputName}.drvPath;
outPath = assert condition; drv.${outputName}.outPath;
} //
# TODO: give the derivation control over the outputs.
# `overrideAttrs` may not be the only attribute that needs
# updating when switching outputs.
optionalAttrs (passthru ? overrideAttrs) {
optionalAttrs (passthru?overrideAttrs) {
# TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
};
};
};
outputsList = map outputToAttrListElement outputs;
in
commonAttrs
// {
drvPath =
assert condition;
drv.drvPath;
outPath =
assert condition;
drv.outPath;
in commonAttrs // {
drvPath = assert condition; drv.drvPath;
outPath = assert condition; drv.outPath;
};
/**
@@ -427,6 +372,7 @@ rec {
result to ensure that there are no thunks kept alive to prevent
garbage collection.
# Inputs
`drv`
@@ -439,29 +385,21 @@ rec {
hydraJob :: (Derivation | Null) -> (Derivation | Null)
```
*/
hydraJob =
drv:
hydraJob = drv:
let
outputs = drv.outputs or [ "out" ];
outputs = drv.outputs or ["out"];
commonAttrs =
{
inherit (drv) name system meta;
inherit outputs;
}
{ inherit (drv) name system meta; inherit outputs; }
// optionalAttrs (drv._hydraAggregate or false) {
_hydraAggregate = true;
constituents = map hydraJob (flatten drv.constituents);
}
// (listToAttrs outputsList);
makeOutput =
outputName:
let
output = drv.${outputName};
in
{
name = outputName;
makeOutput = outputName:
let output = drv.${outputName}; in
{ name = outputName;
value = commonAttrs // {
outPath = output.outPath;
drvPath = output.drvPath;
@@ -473,8 +411,8 @@ rec {
outputsList = map makeOutput outputs;
drv' = (head outputsList).value;
in
if drv == null then null else deepSeq drv' drv';
in if drv == null then null else
deepSeq drv' drv';
/**
Make an attribute set (a "scope") from functions that take arguments from that same attribute set.
@@ -600,21 +538,23 @@ rec {
makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope
```
*/
makeScope =
newScope: f:
let
self = f self // {
newScope = scope: newScope (self // scope);
callPackage = self.newScope { };
overrideScope = g: makeScope newScope (extends g f);
packages = f;
};
in
self;
makeScope = newScope: f:
let self = f self // {
newScope = scope: newScope (self // scope);
callPackage = self.newScope {};
overrideScope = g: makeScope newScope (extends g f);
# Remove after 24.11 is released.
overrideScope' = g: warnIf (isInOldestRelease 2311)
"`overrideScope'` (from `lib.makeScope`) has been renamed to `overrideScope`."
(makeScope newScope (extends g f));
packages = f;
};
in self;
/**
backward compatibility with old uncurried form; deprecated
# Inputs
`splicePackages`
@@ -643,14 +583,9 @@ rec {
*/
makeScopeWithSplicing =
splicePackages: newScope: otherSplices: keep: extra: f:
makeScopeWithSplicing' { inherit splicePackages newScope; } {
inherit
otherSplices
keep
extra
f
;
};
makeScopeWithSplicing'
{ inherit splicePackages newScope; }
{ inherit otherSplices keep extra f; };
/**
Like makeScope, but aims to support cross compilation. It's still ugly, but
@@ -677,32 +612,30 @@ rec {
```
*/
makeScopeWithSplicing' =
{
splicePackages,
newScope,
{ splicePackages
, newScope
}:
{
otherSplices,
# Attrs from `self` which won't be spliced.
# Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
# ex: `keep = (self: { inherit (self) aAttr; })`
keep ? (_self: { }),
# Additional attrs to add to the sets `callPackage`.
# When the package is from a subset (but not a subset within a package IS #211340)
# within `spliced0` it will be spliced.
# When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
# If the package is not available within the set or in `pkgs`, such as a package in a let binding, it will not be spliced
# ex:
# ```
# nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
# «derivation ...CoreFoundation-11.0.0.drv»
# nix-repl> darwin.CoreFoundation
# error: attribute 'CoreFoundation' missing
# nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
# «derivation ...CoreFoundation-11.0.0.drv»
# ```
extra ? (_spliced0: { }),
f,
{ otherSplices
# Attrs from `self` which won't be spliced.
# Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
# ex: `keep = (self: { inherit (self) aAttr; })`
, keep ? (_self: {})
# Additional attrs to add to the sets `callPackage`.
# When the package is from a subset (but not a subset within a package IS #211340)
# within `spliced0` it will be spliced.
# When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
# If the package is not available within the set or in `pkgs`, such as a package in a let binding, it will not be spliced
# ex:
# ```
# nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
# «derivation ...CoreFoundation-11.0.0.drv»
# nix-repl> darwin.CoreFoundation
# error: attribute 'CoreFoundation' missing
# nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
# «derivation ...CoreFoundation-11.0.0.drv»
# ```
, extra ? (_spliced0: {})
, f
}:
let
spliced0 = splicePackages {
@@ -719,15 +652,13 @@ rec {
callPackage = newScope spliced; # == self.newScope {};
# N.B. the other stages of the package set spliced in are *not*
# overridden.
overrideScope =
g:
(makeScopeWithSplicing' { inherit splicePackages newScope; } {
inherit otherSplices keep extra;
overrideScope = g: (makeScopeWithSplicing'
{ inherit splicePackages newScope; }
{ inherit otherSplices keep extra;
f = extends g f;
});
packages = f;
};
in
self;
in self;
}

View File

@@ -26,8 +26,7 @@ let
generators
id
mapAttrs
trace
;
trace;
in
rec {
@@ -37,6 +36,7 @@ rec {
/**
Conditionally trace the supplied message, based on a predicate.
# Inputs
`pred`
@@ -70,13 +70,15 @@ rec {
:::
*/
traceIf =
pred: msg: x:
if pred then trace msg x else x;
pred:
msg:
x: if pred then trace msg x else x;
/**
Trace the supplied value after applying a function to it, and
return the original value.
# Inputs
`f`
@@ -105,7 +107,9 @@ rec {
:::
*/
traceValFn = f: x: trace (f x) x;
traceValFn =
f:
x: trace (f x) x;
/**
Trace the supplied value and return it.
@@ -139,6 +143,7 @@ rec {
/**
`builtins.trace`, but the value is `builtins.deepSeq`ed first.
# Inputs
`x`
@@ -170,13 +175,16 @@ rec {
:::
*/
traceSeq = x: y: trace (builtins.deepSeq x x) y;
traceSeq =
x:
y: trace (builtins.deepSeq x x) y;
/**
Like `traceSeq`, but only evaluate down to depth n.
This is very useful because lots of `traceSeq` usages
lead to an infinite recursion.
# Inputs
`depth`
@@ -209,39 +217,25 @@ rec {
:::
*/
traceSeqN =
depth: x: y:
let
snip =
v:
if isList v then
noQuotes "[]" v
else if isAttrs v then
noQuotes "{}" v
else
v;
noQuotes = str: v: {
__pretty = const str;
val = v;
};
modify =
n: fn: v:
if (n == 0) then
fn v
else if isList v then
map (modify (n - 1) fn) v
else if isAttrs v then
mapAttrs (const (modify (n - 1) fn)) v
else
v;
in
trace (generators.toPretty { allowPrettyValues = true; } (modify depth snip x)) y;
traceSeqN = depth: x: y:
let snip = v: if isList v then noQuotes "[]" v
else if isAttrs v then noQuotes "{}" v
else v;
noQuotes = str: v: { __pretty = const str; val = v; };
modify = n: fn: v: if (n == 0) then fn v
else if isList v then map (modify (n - 1) fn) v
else if isAttrs v then mapAttrs
(const (modify (n - 1) fn)) v
else v;
in trace (generators.toPretty { allowPrettyValues = true; }
(modify depth snip x)) y;
/**
A combination of `traceVal` and `traceSeq` that applies a
provided function to the value to be traced after `deepSeq`ing
it.
# Inputs
`f`
@@ -252,7 +246,9 @@ rec {
: Value to trace
*/
traceValSeqFn = f: v: traceValFn f (builtins.deepSeq v v);
traceValSeqFn =
f:
v: traceValFn f (builtins.deepSeq v v);
/**
A combination of `traceVal` and `traceSeq`.
@@ -262,6 +258,7 @@ rec {
`v`
: Value to trace
*/
traceValSeq = traceValSeqFn id;
@@ -269,6 +266,7 @@ rec {
A combination of `traceVal` and `traceSeqN` that applies a
provided function to the value to be traced.
# Inputs
`f`
@@ -284,8 +282,9 @@ rec {
: Value to trace
*/
traceValSeqNFn =
f: depth: v:
traceSeqN depth (f v) v;
f:
depth:
v: traceSeqN depth (f v) v;
/**
A combination of `traceVal` and `traceSeqN`.
@@ -309,6 +308,7 @@ rec {
This is useful for adding around a function call,
to see the before/after of values as they are transformed.
# Inputs
`depth`
@@ -327,6 +327,7 @@ rec {
: 4\. Function argument
# Examples
:::{.example}
## `lib.debug.traceFnSeqN` usage example
@@ -339,16 +340,17 @@ rec {
:::
*/
traceFnSeqN =
depth: name: f: v:
let
res = f v;
in
lib.traceSeqN (depth + 1) {
fn = name;
from = v;
to = res;
} res;
traceFnSeqN = depth: name: f: v:
let res = f v;
in lib.traceSeqN
(depth + 1)
{
fn = name;
from = v;
to = res;
}
res;
# -- TESTING --
@@ -373,6 +375,7 @@ rec {
- If you want to run only a subset of the tests add the attribute `tests = ["testName"];`
# Inputs
`tests`
@@ -427,42 +430,26 @@ rec {
:::
*/
runTests =
tests:
concatLists (
attrValues (
mapAttrs (
name: test:
let
testsToRun = if tests ? tests then tests.tests else [ ];
in
if
(substring 0 4 name == "test" || elem name testsToRun)
&& ((testsToRun == [ ]) || elem name tests.tests)
&& (test.expr != test.expected)
tests: concatLists (attrValues (mapAttrs (name: test:
let testsToRun = if tests ? tests then tests.tests else [];
in if (substring 0 4 name == "test" || elem name testsToRun)
&& ((testsToRun == []) || elem name tests.tests)
&& (test.expr != test.expected)
then
[
{
inherit name;
expected = test.expected;
result = test.expr;
}
]
else
[ ]
) tests
)
);
then [ { inherit name; expected = test.expected; result = test.expr; } ]
else [] ) tests));
/**
Create a test assuming that list elements are `true`.
# Inputs
`expr`
: 1\. Function argument
# Examples
:::{.example}
## `lib.debug.testAllTrue` usage example
@@ -473,8 +460,5 @@ rec {
:::
*/
testAllTrue = expr: {
inherit expr;
expected = map (x: true) expr;
};
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
}

View File

@@ -71,7 +71,7 @@ let
# these are the only ones that are currently not
inherit (builtins) addErrorContext isPath trace typeOf unsafeGetAttrPos;
inherit (self.trivial) id const pipe concat or and xor bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip defaultTo mapNullable inNixShell isFloat min max
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
importJSON importTOML warn warnIf warnIfNot throwIf throwIfNot checkListOfEnum
info showWarnings nixpkgsVersion version isInOldestRelease oldestSupportedReleaseIsAtLeast
mod compare splitByAndCompare seq deepSeq lessThan add sub
@@ -100,7 +100,7 @@ let
length head tail elem elemAt isList;
inherit (self.strings) concatStrings concatMapStrings concatImapStrings
stringLength substring isString replaceStrings
intersperse concatStringsSep concatMapStringsSep concatMapAttrsStringSep
intersperse concatStringsSep concatMapStringsSep
concatImapStringsSep concatLines makeSearchPath makeSearchPathOutput
makeLibraryPath makeIncludePath makeBinPath optionalString
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
@@ -121,7 +121,7 @@ let
inherit (self.customisation) overrideDerivation makeOverridable
callPackageWith callPackagesWith extendDerivation hydraJob
makeScope makeScopeWithSplicing makeScopeWithSplicing';
inherit (self.derivations) lazyDerivation optionalDrvAttr warnOnInstantiate;
inherit (self.derivations) lazyDerivation optionalDrvAttr;
inherit (self.meta) addMetaAttrs dontDistribute setName updateName
appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
hiPrioSet licensesSpdx getLicenseFromSpdxId getLicenseFromSpdxIdOr
@@ -152,7 +152,7 @@ let
scrubOptionValue literalExpression literalExample
showOption showOptionWithDefLocs showFiles
unknownModule mkOption mkPackageOption mkPackageOptionMD
literalMD;
mdDoc literalMD;
inherit (self.types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType;
inherit (self.asserts)

View File

@@ -4,21 +4,17 @@ let
inherit (lib)
genAttrs
isString
mapAttrs
removeAttrs
throwIfNot
;
showMaybeAttrPosPre =
prefix: attrName: v:
let
pos = builtins.unsafeGetAttrPos attrName v;
in
if pos == null then "" else "${prefix}${pos.file}:${toString pos.line}:${toString pos.column}";
showMaybeAttrPosPre = prefix: attrName: v:
let pos = builtins.unsafeGetAttrPos attrName v;
in if pos == null then "" else "${prefix}${pos.file}:${toString pos.line}:${toString pos.column}";
showMaybePackagePosPre =
prefix: pkg:
if pkg ? meta.position && isString pkg.meta.position then "${prefix}${pkg.meta.position}" else "";
showMaybePackagePosPre = prefix: pkg:
if pkg?meta.position && isString pkg.meta.position
then "${prefix}${pkg.meta.position}"
else "";
in
{
/**
@@ -96,14 +92,15 @@ in
derivation,
meta ? null,
passthru ? { },
outputs ? [ "out" ],
outputs ? [ "out" ]
}:
let
# These checks are strict in `drv` and some `drv` attributes, but the
# attrset spine returned by lazyDerivation does not depend on it.
# Instead, the individual derivation attributes do depend on it.
checked =
throwIfNot (derivation.type or null == "derivation") "lazyDerivation: input must be a derivation."
throwIfNot (derivation.type or null == "derivation")
"lazyDerivation: input must be a derivation."
throwIfNot
# NOTE: Technically we could require our outputs to be a subset of the
# actual ones, or even leave them unchecked and fail on a lazy basis.
@@ -153,13 +150,7 @@ in
# A fixed set of derivation values, so that `lazyDerivation` can return
# its attrset before evaluating `derivation`.
# This must only list attributes that are available on _all_ derivations.
inherit (checked)
outPath
outputName
drvPath
name
system
;
inherit (checked) outPath outputName drvPath name system;
inherit outputs;
# The meta attribute can either be taken from the derivation, or if the
@@ -177,6 +168,7 @@ in
Thus, this function passes through its `value` argument if the `cond`
is `true`, but returns `null` if not.
# Inputs
`cond`
@@ -211,42 +203,7 @@ in
:::
*/
optionalDrvAttr = cond: value: if cond then value else null;
/**
Wrap a derivation such that instantiating it produces a warning.
All attributes apart from `meta`, `name`, and `type` (which are used by
`nix search`) will be wrapped in `lib.warn`.
# Inputs
`msg`
: The warning message to emit (via `lib.warn`).
`drv`
: The derivation to wrap.
# Examples
:::{.example}
## `lib.derivations.warnOnInstantiate` usage example
```nix
{
myPackage = warnOnInstantiate "myPackage has been renamed to my-package" my-package;
}
```
:::
*/
warnOnInstantiate =
msg: drv:
let
drvToWrap = removeAttrs drv [
"meta"
"name"
"type"
];
in
drv // mapAttrs (_: lib.warn msg) drvToWrap;
optionalDrvAttr =
cond:
value: if cond then value else null;
}

View File

@@ -2,8 +2,8 @@
{ lib }:
let
commonH = hashTypes: rec {
hashNames = [ "hash" ] ++ hashTypes;
hashSet = lib.genAttrs hashNames (lib.const { });
hashNames = [ "hash" ] ++ hashTypes;
hashSet = lib.genAttrs hashNames (lib.const {});
};
fakeH = {
@@ -11,24 +11,15 @@ let
sha256 = lib.fakeSha256;
sha512 = lib.fakeSha512;
};
in
rec {
in rec {
proxyImpureEnvVars = [
# We borrow these environment variables from the caller to allow
# easy proxy configuration. This is impure, but a fixed-output
# derivation like fetchurl is allowed to do so since its result is
# by definition pure.
"http_proxy"
"https_proxy"
"ftp_proxy"
"all_proxy"
"no_proxy"
"HTTP_PROXY"
"HTTPS_PROXY"
"FTP_PROXY"
"ALL_PROXY"
"NO_PROXY"
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
"HTTP_PROXY" "HTTPS_PROXY" "FTP_PROXY" "ALL_PROXY" "NO_PROXY"
# https proxies typically need to inject custom root CAs too
"NIX_SSL_CERT_FILE"
@@ -86,56 +77,42 @@ rec {
required
: whether to throw if no hash was present in the input; otherwise returns the original input, unmodified
*/
normalizeHash =
{
hashTypes ? [ "sha256" ],
required ? true,
}:
normalizeHash = {
hashTypes ? [ "sha256" ],
required ? true,
}:
let
inherit (lib)
concatMapStringsSep
head
tail
throwIf
;
inherit (lib.attrsets)
attrsToList
intersectAttrs
removeAttrs
optionalAttrs
;
inherit (lib) concatMapStringsSep head tail throwIf;
inherit (lib.attrsets) attrsToList intersectAttrs removeAttrs optionalAttrs;
inherit (commonH hashTypes) hashNames hashSet;
in
args:
if args ? "outputHash" then
args
else
let
# The argument hash, as a {name, value} pair
h =
# All hashes passed in arguments (possibly 0 or >1) as a list of {name, value} pairs
args:
if args ? "outputHash" then
args
else
let
hashesAsNVPairs = attrsToList (intersectAttrs hashSet args);
# The argument hash, as a {name, value} pair
h =
# All hashes passed in arguments (possibly 0 or >1) as a list of {name, value} pairs
let hashesAsNVPairs = attrsToList (intersectAttrs hashSet args); in
if hashesAsNVPairs == [] then
throwIf required "fetcher called without `hash`" null
else if tail hashesAsNVPairs != [] then
throw "fetcher called with mutually-incompatible arguments: ${concatMapStringsSep ", " (a: a.name) hashesAsNVPairs}"
else
head hashesAsNVPairs
;
in
if hashesAsNVPairs == [ ] then
throwIf required "fetcher called without `hash`" null
else if tail hashesAsNVPairs != [ ] then
throw "fetcher called with mutually-incompatible arguments: ${
concatMapStringsSep ", " (a: a.name) hashesAsNVPairs
}"
else
head hashesAsNVPairs;
in
removeAttrs args hashNames
// (optionalAttrs (h != null) {
outputHashAlgo = if h.name == "hash" then null else h.name;
outputHash =
if h.value == "" then
fakeH.${h.name} or (throw "no fake hash defined for ${h.name}")
else
h.value;
});
removeAttrs args hashNames // (optionalAttrs (h != null) {
outputHashAlgo = if h.name == "hash" then null else h.name;
outputHash =
if h.value == "" then
fakeH.${h.name} or (throw "no fake hash defined for ${h.name}")
else
h.value;
})
;
/**
Wraps a function which accepts `outputHash{,Algo}` into one which accepts `hash` or `sha{256,512}`
@@ -187,11 +164,9 @@ rec {
However, `withNormalizedHash` preserves `functionArgs` metadata insofar as possible,
and is implemented somewhat more efficiently.
*/
withNormalizedHash =
{
hashTypes ? [ "sha256" ],
}:
fetcher:
withNormalizedHash = {
hashTypes ? [ "sha256" ]
}: fetcher:
let
inherit (lib.attrsets) genAttrs intersectAttrs removeAttrs;
inherit (lib.trivial) const functionArgs setFunctionArgs;
@@ -206,15 +181,9 @@ rec {
in
# The o.g. fetcher must *only* accept outputHash and outputHashAlgo
assert fArgs ? outputHash && fArgs ? outputHashAlgo;
assert intersectAttrs fArgs hashSet == { };
assert intersectAttrs fArgs hashSet == {};
setFunctionArgs (args: fetcher (normalize args)) (
removeAttrs fArgs [
"outputHash"
"outputHashAlgo"
]
// {
hash = fArgs.outputHash;
}
);
setFunctionArgs
(args: fetcher (normalize args))
(removeAttrs fArgs [ "outputHash" "outputHashAlgo" ] // { hash = fArgs.outputHash; });
}

View File

@@ -57,6 +57,7 @@
If you need more file set functions,
see [this issue](https://github.com/NixOS/nixpkgs/issues/266356) to request it.
# Implicit coercion from paths to file sets {#sec-fileset-path-coercion}
All functions accepting file sets as arguments can also accept [paths](https://nixos.org/manual/nix/stable/language/values.html#type-path) as arguments.
@@ -154,14 +155,14 @@ let
pipe
;
in
{
in {
/**
Create a file set from a path that may or may not exist:
- If the path does exist, the path is [coerced to a file set](#sec-fileset-path-coercion).
- If the path does not exist, a file set containing no files is returned.
# Inputs
`path`
@@ -187,12 +188,14 @@ in
*/
maybeMissing =
path:
if !isPath path then
if ! isPath path then
if isStringLike path then
throw ''lib.fileset.maybeMissing: Argument ("${toString path}") is a string-like value, but it should be a path instead.''
throw ''
lib.fileset.maybeMissing: Argument ("${toString path}") is a string-like value, but it should be a path instead.''
else
throw ''lib.fileset.maybeMissing: Argument is of type ${typeOf path}, but it should be a path instead.''
else if !pathExists path then
throw ''
lib.fileset.maybeMissing: Argument is of type ${typeOf path}, but it should be a path instead.''
else if ! pathExists path then
_emptyWithoutBase
else
_singleton path;
@@ -208,6 +211,7 @@ in
This variant is useful for tracing file sets in the Nix repl.
# Inputs
`fileset`
@@ -244,14 +248,15 @@ in
:::
*/
trace =
fileset:
trace = fileset:
let
# "fileset" would be a better name, but that would clash with the argument name,
# and we cannot change that because of https://github.com/nix-community/nixdoc/issues/76
actualFileset = _coerce "lib.fileset.trace: Argument" fileset;
in
seq (_printFileset actualFileset) (x: x);
seq
(_printFileset actualFileset)
(x: x);
/**
Incrementally evaluate and trace a file set in a pretty way.
@@ -263,6 +268,7 @@ in
This variant is useful for tracing file sets passed as arguments to other functions.
# Inputs
`fileset`
@@ -302,14 +308,14 @@ in
:::
*/
traceVal =
fileset:
traceVal = fileset:
let
# "fileset" would be a better name, but that would clash with the argument name,
# and we cannot change that because of https://github.com/nix-community/nixdoc/issues/76
actualFileset = _coerce "lib.fileset.traceVal: Argument" fileset;
in
seq (_printFileset actualFileset)
seq
(_printFileset actualFileset)
# We could also return the original fileset argument here,
# but that would then duplicate work for consumers of the fileset, because then they have to coerce it again
actualFileset;
@@ -417,11 +423,10 @@ in
:::
*/
toSource =
{
root,
fileset,
}:
toSource = {
root,
fileset,
}:
let
# We cannot rename matched attribute arguments, so let's work around it with an extra `let in` statement
filesetArg = fileset;
@@ -432,7 +437,7 @@ in
filesetFilesystemRoot = (splitRoot fileset._internalBase).root;
sourceFilter = _toSourceFilter fileset;
in
if !isPath root then
if ! isPath root then
if root ? _isLibCleanSourceWith then
throw ''
lib.fileset.toSource: `root` is a `lib.sources`-based value, but it should be a path instead.
@@ -443,34 +448,38 @@ in
lib.fileset.toSource: `root` (${toString root}) is a string-like value, but it should be a path instead.
Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
else
throw ''lib.fileset.toSource: `root` is of type ${typeOf root}, but it should be a path instead.''
throw ''
lib.fileset.toSource: `root` is of type ${typeOf root}, but it should be a path instead.''
# Currently all Nix paths have the same filesystem root, but this could change in the future.
# See also ../path/README.md
else if !fileset._internalIsEmptyWithoutBase && rootFilesystemRoot != filesetFilesystemRoot then
else if ! fileset._internalIsEmptyWithoutBase && rootFilesystemRoot != filesetFilesystemRoot then
throw ''
lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` (${toString root}):
`root`: Filesystem root is "${toString rootFilesystemRoot}"
`fileset`: Filesystem root is "${toString filesetFilesystemRoot}"
Different filesystem roots are not supported.''
else if !pathExists root then
throw ''lib.fileset.toSource: `root` (${toString root}) is a path that does not exist.''
else if ! pathExists root then
throw ''
lib.fileset.toSource: `root` (${toString root}) is a path that does not exist.''
else if pathType root != "directory" then
throw ''
lib.fileset.toSource: `root` (${toString root}) is a file, but it should be a directory instead. Potential solutions:
- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as ${toString (dirOf root)}, and set `fileset` to the file path.''
else if !fileset._internalIsEmptyWithoutBase && !hasPrefix root fileset._internalBase then
else if ! fileset._internalIsEmptyWithoutBase && ! hasPrefix root fileset._internalBase then
throw ''
lib.fileset.toSource: `fileset` could contain files in ${toString fileset._internalBase}, which is not under the `root` (${toString root}). Potential solutions:
- Set `root` to ${toString fileset._internalBase} or any directory higher up. This changes the layout of the resulting store path.
- Set `fileset` to a file set that cannot contain files outside the `root` (${toString root}). This could change the files included in the result.''
else
seq sourceFilter cleanSourceWith {
seq sourceFilter
cleanSourceWith {
name = "source";
src = root;
filter = sourceFilter;
};
/**
The list of file paths contained in the given file set.
@@ -485,6 +494,7 @@ in
The resulting list of files can be turned back into a file set using [`lib.fileset.unions`](#function-library-lib.fileset.unions).
# Inputs
`fileset`
@@ -511,7 +521,8 @@ in
:::
*/
toList = fileset: _toList (_coerce "lib.fileset.toList: Argument" fileset);
toList = fileset:
_toList (_coerce "lib.fileset.toList: Argument" fileset);
/**
The file set containing all files that are in either of two given file sets.
@@ -522,6 +533,7 @@ in
The given file sets are evaluated as lazily as possible,
with the first argument being evaluated first if needed.
# Inputs
`fileset1`
@@ -555,9 +567,10 @@ in
:::
*/
union =
fileset1: fileset2:
_unionMany (
_coerceMany "lib.fileset.union" [
fileset1:
fileset2:
_unionMany
(_coerceMany "lib.fileset.union" [
{
context = "First argument";
value = fileset1;
@@ -566,8 +579,7 @@ in
context = "Second argument";
value = fileset2;
}
]
);
]);
/**
The file set containing all files that are in any of the given file sets.
@@ -578,6 +590,7 @@ in
The given file sets are evaluated as lazily as possible,
with earlier elements being evaluated first if needed.
# Inputs
`filesets`
@@ -618,17 +631,16 @@ in
*/
unions =
filesets:
if !isList filesets then
throw ''lib.fileset.unions: Argument is of type ${typeOf filesets}, but it should be a list instead.''
if ! isList filesets then
throw ''
lib.fileset.unions: Argument is of type ${typeOf filesets}, but it should be a list instead.''
else
pipe filesets [
# Annotate the elements with context, used by _coerceMany for better errors
(imap0 (
i: el: {
context = "Element ${toString i}";
value = el;
}
))
(imap0 (i: el: {
context = "Element ${toString i}";
value = el;
}))
(_coerceMany "lib.fileset.unions")
_unionMany
];
@@ -640,6 +652,7 @@ in
The given file sets are evaluated as lazily as possible,
with the first argument being evaluated first if needed.
# Inputs
`fileset1`
@@ -668,7 +681,8 @@ in
:::
*/
intersection =
fileset1: fileset2:
fileset1:
fileset2:
let
filesets = _coerceMany "lib.fileset.intersection" [
{
@@ -681,7 +695,9 @@ in
}
];
in
_intersection (elemAt filesets 0) (elemAt filesets 1);
_intersection
(elemAt filesets 0)
(elemAt filesets 1);
/**
The file set containing all files from the first file set that are not in the second file set.
@@ -690,6 +706,7 @@ in
The given file sets are evaluated as lazily as possible,
with the first argument being evaluated first if needed.
# Inputs
`positive`
@@ -727,7 +744,8 @@ in
:::
*/
difference =
positive: negative:
positive:
negative:
let
filesets = _coerceMany "lib.fileset.difference" [
{
@@ -740,11 +758,14 @@ in
}
];
in
_difference (elemAt filesets 0) (elemAt filesets 1);
_difference
(elemAt filesets 0)
(elemAt filesets 1);
/**
Filter a file set to only contain files matching some predicate.
# Inputs
`predicate`
@@ -806,18 +827,22 @@ in
:::
*/
fileFilter =
predicate: path:
if !isFunction predicate then
throw ''lib.fileset.fileFilter: First argument is of type ${typeOf predicate}, but it should be a function instead.''
else if !isPath path then
predicate:
path:
if ! isFunction predicate then
throw ''
lib.fileset.fileFilter: First argument is of type ${typeOf predicate}, but it should be a function instead.''
else if ! isPath path then
if path._type or "" == "fileset" then
throw ''
lib.fileset.fileFilter: Second argument is a file set, but it should be a path instead.
If you need to filter files in a file set, use `intersection fileset (fileFilter pred ./.)` instead.''
else
throw ''lib.fileset.fileFilter: Second argument is of type ${typeOf path}, but it should be a path instead.''
else if !pathExists path then
throw ''lib.fileset.fileFilter: Second argument (${toString path}) is a path that does not exist.''
throw ''
lib.fileset.fileFilter: Second argument is of type ${typeOf path}, but it should be a path instead.''
else if ! pathExists path then
throw ''
lib.fileset.fileFilter: Second argument (${toString path}) is a path that does not exist.''
else
_fileFilter predicate path;
@@ -834,6 +859,7 @@ in
Turning the result of this function back into a source using `toSource` will therefore not preserve empty directories.
:::
# Inputs
`source`
@@ -879,8 +905,7 @@ in
:::
*/
fromSource =
source:
fromSource = source:
let
# This function uses `._isLibCleanSourceWith`, `.origSrc` and `.filter`,
# which are technically internal to lib.sources,
@@ -890,15 +915,17 @@ in
path = if isFiltered then source.origSrc else source;
in
# We can only support sources created from paths
if !isPath path then
if ! isPath path then
if isStringLike path then
throw ''
lib.fileset.fromSource: The source origin of the argument is a string-like value ("${toString path}"), but it should be a path instead.
Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.''
else
throw ''lib.fileset.fromSource: The source origin of the argument is of type ${typeOf path}, but it should be a path instead.''
else if !pathExists path then
throw ''lib.fileset.fromSource: The source origin (${toString path}) of the argument is a path that does not exist.''
throw ''
lib.fileset.fromSource: The source origin of the argument is of type ${typeOf path}, but it should be a path instead.''
else if ! pathExists path then
throw ''
lib.fileset.fromSource: The source origin (${toString path}) of the argument is a path that does not exist.''
else if isFiltered then
_fromSourceFilter path source.filter
else
@@ -910,6 +937,7 @@ in
This function behaves like [`gitTrackedWith { }`](#function-library-lib.fileset.gitTrackedWith) - using the defaults.
# Inputs
`path`
@@ -938,7 +966,13 @@ in
:::
*/
gitTracked = path: _fromFetchGit "gitTracked" "argument" path { };
gitTracked =
path:
_fromFetchGit
"gitTracked"
"argument"
path
{};
/**
Create a file set containing all [Git-tracked files](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) in a repository.
@@ -964,6 +998,7 @@ in
This may change in the future.
:::
# Inputs
`options` (attribute set)
@@ -998,18 +1033,19 @@ in
recurseSubmodules ? false,
}:
path:
if !isBool recurseSubmodules then
if ! isBool recurseSubmodules then
throw "lib.fileset.gitTrackedWith: Expected the attribute `recurseSubmodules` of the first argument to be a boolean, but it's a ${typeOf recurseSubmodules} instead."
else if recurseSubmodules && versionOlder nixVersion _fetchGitSubmodulesMinver then
throw "lib.fileset.gitTrackedWith: Setting the attribute `recurseSubmodules` to `true` is only supported for Nix version ${_fetchGitSubmodulesMinver} and after, but Nix version ${nixVersion} is used."
else
_fromFetchGit "gitTrackedWith" "second argument" path
_fromFetchGit
"gitTrackedWith"
"second argument"
path
# This is the only `fetchGit` parameter that makes sense in this context.
# We can't just pass `submodules = recurseSubmodules` here because
# this would fail for Nix versions that don't support `submodules`.
(
lib.optionalAttrs recurseSubmodules {
submodules = true;
}
);
(lib.optionalAttrs recurseSubmodules {
submodules = true;
});
}

View File

@@ -1,6 +1,4 @@
{
lib ? import ../.,
}:
{ lib ? import ../. }:
let
inherit (builtins)
@@ -89,8 +87,7 @@ rec {
let
parts = splitRoot filesetV0._internalBase;
in
filesetV0
// {
filesetV0 // {
_internalVersion = 1;
_internalBaseRoot = parts.root;
_internalBaseComponents = components parts.subpath;
@@ -101,8 +98,7 @@ rec {
(
filesetV1:
# This change is backwards compatible (but not forwards compatible, so we still need a new version)
filesetV1
// {
filesetV1 // {
_internalVersion = 2;
}
)
@@ -110,8 +106,7 @@ rec {
# Convert v2 into v3: filesetTree's now have a representation for an empty file set without a base path
(
filesetV2:
filesetV2
// {
filesetV2 // {
# All v1 file sets are not the new empty file set
_internalIsEmptyWithoutBase = false;
_internalVersion = 3;
@@ -141,8 +136,7 @@ rec {
# Create a fileset, see ./README.md#fileset
# Type: path -> filesetTree -> fileset
_create =
base: tree:
_create = base: tree:
let
# Decompose the base into its components
# See ../path/README.md for why we're not just using `toString`
@@ -168,8 +162,7 @@ rec {
# Coerce a value to a fileset, erroring when the value cannot be coerced.
# The string gives the context for error messages.
# Type: String -> (fileset | Path) -> fileset
_coerce =
context: value:
_coerce = context: value:
if value._type or "" == "fileset" then
if value._internalVersion > _currentVersion then
throw ''
@@ -180,14 +173,12 @@ rec {
else if value._internalVersion < _currentVersion then
let
# Get all the migration functions necessary to convert from the old to the current version
migrationsToApply = sublist value._internalVersion (
_currentVersion - value._internalVersion
) migrations;
migrationsToApply = sublist value._internalVersion (_currentVersion - value._internalVersion) migrations;
in
foldl' (value: migration: migration value) value migrationsToApply
else
value
else if !isPath value then
else if ! isPath value then
if value ? _isLibCleanSourceWith then
throw ''
${context} is a `lib.sources`-based value, but it should be a file set or a path instead.
@@ -198,8 +189,9 @@ rec {
${context} ("${toString value}") is a string-like value, but it should be a file set or a path instead.
Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
else
throw ''${context} is of type ${typeOf value}, but it should be a file set or a path instead.''
else if !pathExists value then
throw ''
${context} is of type ${typeOf value}, but it should be a file set or a path instead.''
else if ! pathExists value then
throw ''
${context} (${toString value}) is a path that does not exist.
To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.''
@@ -209,21 +201,22 @@ rec {
# Coerce many values to filesets, erroring when any value cannot be coerced,
# or if the filesystem root of the values doesn't match.
# Type: String -> [ { context :: String, value :: fileset | Path } ] -> [ fileset ]
_coerceMany =
functionContext: list:
_coerceMany = functionContext: list:
let
filesets = map ({ context, value }: _coerce "${functionContext}: ${context}" value) list;
filesets = map ({ context, value }:
_coerce "${functionContext}: ${context}" value
) list;
# Find the first value with a base, there may be none!
firstWithBase = findFirst (fileset: !fileset._internalIsEmptyWithoutBase) null filesets;
firstWithBase = findFirst (fileset: ! fileset._internalIsEmptyWithoutBase) null filesets;
# This value is only accessed if first != null
firstBaseRoot = firstWithBase._internalBaseRoot;
# Finds the first element with a filesystem root different than the first element, if any
differentIndex = findFirstIndex (
fileset:
differentIndex = findFirstIndex (fileset:
# The empty value without a base doesn't have a base path
!fileset._internalIsEmptyWithoutBase && firstBaseRoot != fileset._internalBaseRoot
! fileset._internalIsEmptyWithoutBase
&& firstBaseRoot != fileset._internalBaseRoot
) null filesets;
in
# Only evaluates `differentIndex` if there are any elements with a base
@@ -238,8 +231,7 @@ rec {
# Create a file set from a path.
# Type: Path -> fileset
_singleton =
path:
_singleton = path:
let
type = pathType path;
in
@@ -252,20 +244,21 @@ rec {
# "default.nix" = <type>;
# }
# See ./README.md#single-files
_create (dirOf path) {
${baseNameOf path} = type;
};
_create (dirOf path)
{
${baseNameOf path} = type;
};
# Expand a directory representation to an equivalent one in attribute set form.
# All directory entries are included in the result.
# Type: Path -> filesetTree -> { <name> = filesetTree; }
_directoryEntries =
path: value:
_directoryEntries = path: value:
if value == "directory" then
readDir path
else
# Set all entries not present to null
mapAttrs (name: value: null) (readDir path) // value;
mapAttrs (name: value: null) (readDir path)
// value;
/*
A normalisation of a filesetTree suitable filtering with `builtins.path`:
@@ -278,8 +271,7 @@ rec {
Type: Path -> filesetTree -> filesetTree
*/
_normaliseTreeFilter =
path: tree:
_normaliseTreeFilter = path: tree:
if tree == "directory" || isAttrs tree then
let
entries = _directoryEntries path tree;
@@ -309,8 +301,7 @@ rec {
Type: Path -> filesetTree -> filesetTree (with "emptyDir"'s)
*/
_normaliseTreeMinimal =
path: tree:
_normaliseTreeMinimal = path: tree:
if tree == "directory" || isAttrs tree then
let
entries = _directoryEntries path tree;
@@ -343,11 +334,9 @@ rec {
# Trace a filesetTree in a pretty way when the resulting value is evaluated.
# This can handle both normal filesetTree's, and ones returned from _normaliseTreeMinimal
# Type: Path -> filesetTree (with "emptyDir"'s) -> Null
_printMinimalTree =
base: tree:
_printMinimalTree = base: tree:
let
treeSuffix =
tree:
treeSuffix = tree:
if isAttrs tree then
""
else if tree == "directory" then
@@ -360,15 +349,14 @@ rec {
" (${tree})";
# Only for attribute set trees
traceTreeAttrs =
prevLine: indent: tree:
foldl' (
prevLine: name:
traceTreeAttrs = prevLine: indent: tree:
foldl' (prevLine: name:
let
subtree = tree.${name};
# Evaluating this prints the line for this subtree
thisLine = trace "${indent}- ${name}${treeSuffix subtree}" prevLine;
thisLine =
trace "${indent}- ${name}${treeSuffix subtree}" prevLine;
in
if subtree == null || subtree == "emptyDir" then
# Don't print anything at all if this subtree is empty
@@ -390,24 +378,24 @@ rec {
else
trace "${toString base}${treeSuffix tree}" null;
in
if isAttrs tree then traceTreeAttrs firstLine "" tree else firstLine;
if isAttrs tree then
traceTreeAttrs firstLine "" tree
else
firstLine;
# Pretty-print a file set in a pretty way when the resulting value is evaluated
# Type: fileset -> Null
_printFileset =
fileset:
_printFileset = fileset:
if fileset._internalIsEmptyWithoutBase then
trace "(empty)" null
else
_printMinimalTree fileset._internalBase (
_normaliseTreeMinimal fileset._internalBase fileset._internalTree
);
_printMinimalTree fileset._internalBase
(_normaliseTreeMinimal fileset._internalBase fileset._internalTree);
# Turn a fileset into a source filter function suitable for `builtins.path`
# Only directories recursively containing at least one files are recursed into
# Type: fileset -> (String -> String -> Bool)
_toSourceFilter =
fileset:
_toSourceFilter = fileset:
let
# Simplify the tree, necessary to make sure all empty directories are null
# which has the effect that they aren't included in the result
@@ -415,7 +403,7 @@ rec {
# The base path as a string with a single trailing slash
baseString =
if fileset._internalBaseComponents == [ ] then
if fileset._internalBaseComponents == [] then
# Need to handle the filesystem root specially
"/"
else
@@ -426,11 +414,9 @@ rec {
# Check whether a list of path components under the base path exists in the tree.
# This function is called often, so it should be fast.
# Type: [ String ] -> Bool
inTree =
components:
inTree = components:
let
recurse =
index: localTree:
recurse = index: localTree:
if isAttrs localTree then
# We have an attribute set, meaning this is a directory with at least one file
if index >= length components then
@@ -445,8 +431,7 @@ rec {
# If it's not an attribute set it can only be either null (in which case it's not included)
# or a string ("directory" or "regular", etc.) in which case it's included
localTree != null;
in
recurse 0 tree;
in recurse 0 tree;
# Filter suited when there's no files
empty = _: _: false;
@@ -498,14 +483,16 @@ rec {
# Special case because the code below assumes that the _internalBase is always included in the result
# which shouldn't be done when we have no files at all in the base
# This also forces the tree before returning the filter, leads to earlier error messages
if fileset._internalIsEmptyWithoutBase || tree == null then empty else nonEmpty;
if fileset._internalIsEmptyWithoutBase || tree == null then
empty
else
nonEmpty;
# Turn a builtins.filterSource-based source filter on a root path into a file set
# containing only files included by the filter.
# The filter is lazily called as necessary to determine whether paths are included
# Type: Path -> (String -> String -> Bool) -> fileset
_fromSourceFilter =
root: sourceFilter:
_fromSourceFilter = root: sourceFilter:
let
# During the recursion we need to track both:
# - The path value such that we can safely call `readDir` on it
@@ -516,10 +503,9 @@ rec {
# which is a fairly expensive operation
# Create a file set from a directory entry
fromDirEntry =
path: pathString: type:
fromDirEntry = path: pathString: type:
# The filter needs to run on the path as a string
if !sourceFilter pathString type then
if ! sourceFilter pathString type then
null
else if type == "directory" then
fromDir path pathString
@@ -527,8 +513,7 @@ rec {
type;
# Create a file set from a directory
fromDir =
path: pathString:
fromDir = path: pathString:
mapAttrs
# This looks a bit funny, but we need both the path-based and the path string-based values
(name: fromDirEntry (path + "/${name}") (pathString + "/${name}"))
@@ -551,19 +536,20 @@ rec {
else
# Direct files are always included by builtins.path without calling the filter
# But we need to lift up the base path to its parent to satisfy the base path invariant
_create (dirOf root) {
${baseNameOf root} = rootPathType;
};
_create (dirOf root)
{
${baseNameOf root} = rootPathType;
};
# Turns a file set into the list of file paths it includes.
# Type: fileset -> [ Path ]
_toList =
fileset:
_toList = fileset:
let
recurse =
path: tree:
recurse = path: tree:
if isAttrs tree then
concatLists (mapAttrsToList (name: value: recurse (path + "/${name}") value) tree)
concatLists (mapAttrsToList (name: value:
recurse (path + "/${name}") value
) tree)
else if tree == "directory" then
recurse path (readDir path)
else if tree == null then
@@ -579,11 +565,9 @@ rec {
# Transforms the filesetTree of a file set to a shorter base path, e.g.
# _shortenTreeBase [ "foo" ] (_create /foo/bar null)
# => { bar = null; }
_shortenTreeBase =
targetBaseComponents: fileset:
_shortenTreeBase = targetBaseComponents: fileset:
let
recurse =
index:
recurse = index:
# If we haven't reached the required depth yet
if index < length fileset._internalBaseComponents then
# Create an attribute set and recurse as the value, this can be lazily evaluated this way
@@ -597,11 +581,9 @@ rec {
# Transforms the filesetTree of a file set to a longer base path, e.g.
# _lengthenTreeBase [ "foo" "bar" ] (_create /foo { bar.baz = "regular"; })
# => { baz = "regular"; }
_lengthenTreeBase =
targetBaseComponents: fileset:
_lengthenTreeBase = targetBaseComponents: fileset:
let
recurse =
index: tree:
recurse = index: tree:
# If the filesetTree is an attribute set and we haven't reached the required depth yet
if isAttrs tree && index < length targetBaseComponents then
# Recurse with the tree under the right component (which might not exist)
@@ -620,11 +602,10 @@ rec {
# Computes the union of a list of filesets.
# The filesets must already be coerced and validated to be in the same filesystem root
# Type: [ Fileset ] -> Fileset
_unionMany =
filesets:
_unionMany = filesets:
let
# All filesets that have a base, aka not the ones that are the empty value without a base
filesetsWithBase = filter (fileset: !fileset._internalIsEmptyWithoutBase) filesets;
filesetsWithBase = filter (fileset: ! fileset._internalIsEmptyWithoutBase) filesets;
# The first fileset that has a base.
# This value is only accessed if there are at all.
@@ -637,13 +618,13 @@ rec {
# A list of path components common to all base paths.
# Note that commonPrefix can only be fully evaluated,
# so this cannot cause a stack overflow due to a build-up of unevaluated thunks.
commonBaseComponents =
foldl' (components: el: commonPrefix components el._internalBaseComponents)
firstWithBase._internalBaseComponents
# We could also not do the `tail` here to avoid a list allocation,
# but then we'd have to pay for a potentially expensive
# but unnecessary `commonPrefix` call
(tail filesetsWithBase);
commonBaseComponents = foldl'
(components: el: commonPrefix components el._internalBaseComponents)
firstWithBase._internalBaseComponents
# We could also not do the `tail` here to avoid a list allocation,
# but then we'd have to pay for a potentially expensive
# but unnecessary `commonPrefix` call
(tail filesetsWithBase);
# The common base path assembled from a filesystem root and the common components
commonBase = append firstWithBase._internalBaseRoot (join commonBaseComponents);
@@ -662,13 +643,15 @@ rec {
resultTree = _unionTrees trees;
in
# If there's no values with a base, we have no files
if filesetsWithBase == [ ] then _emptyWithoutBase else _create commonBase resultTree;
if filesetsWithBase == [ ] then
_emptyWithoutBase
else
_create commonBase resultTree;
# The union of multiple filesetTree's with the same base path.
# Later elements are only evaluated if necessary.
# Type: [ filesetTree ] -> filesetTree
_unionTrees =
trees:
_unionTrees = trees:
let
stringIndex = findFirstIndex isString null trees;
withoutNull = filter (tree: tree != null) trees;
@@ -688,15 +671,18 @@ rec {
# Computes the intersection of a list of filesets.
# The filesets must already be coerced and validated to be in the same filesystem root
# Type: Fileset -> Fileset -> Fileset
_intersection =
fileset1: fileset2:
_intersection = fileset1: fileset2:
let
# The common base components prefix, e.g.
# (/foo/bar, /foo/bar/baz) -> /foo/bar
# (/foo/bar, /foo/baz) -> /foo
commonBaseComponentsLength =
# TODO: Have a `lib.lists.commonPrefixLength` function such that we don't need the list allocation from commonPrefix here
length (commonPrefix fileset1._internalBaseComponents fileset2._internalBaseComponents);
length (
commonPrefix
fileset1._internalBaseComponents
fileset2._internalBaseComponents
);
# To be able to intersect filesetTree's together, they need to have the same base path.
# Base paths can be intersected by taking the longest one (if any)
@@ -739,11 +725,12 @@ rec {
# The intersection of two filesetTree's with the same base path
# The second element is only evaluated as much as necessary.
# Type: filesetTree -> filesetTree -> filesetTree
_intersectTree =
lhs: rhs:
_intersectTree = lhs: rhs:
if isAttrs lhs && isAttrs rhs then
# Both sides are attribute sets, we can recurse for the attributes existing on both sides
mapAttrs (name: _intersectTree lhs.${name}) (builtins.intersectAttrs lhs rhs)
mapAttrs
(name: _intersectTree lhs.${name})
(builtins.intersectAttrs lhs rhs)
else if lhs == null || isString rhs then
# If the lhs is null, the result should also be null
# And if the rhs is the identity element
@@ -756,15 +743,18 @@ rec {
# Compute the set difference between two file sets.
# The filesets must already be coerced and validated to be in the same filesystem root.
# Type: Fileset -> Fileset -> Fileset
_difference =
positive: negative:
_difference = positive: negative:
let
# The common base components prefix, e.g.
# (/foo/bar, /foo/bar/baz) -> /foo/bar
# (/foo/bar, /foo/baz) -> /foo
commonBaseComponentsLength =
# TODO: Have a `lib.lists.commonPrefixLength` function such that we don't need the list allocation from commonPrefix here
length (commonPrefix positive._internalBaseComponents negative._internalBaseComponents);
length (
commonPrefix
positive._internalBaseComponents
negative._internalBaseComponents
);
# We need filesetTree's with the same base to be able to compute the difference between them
# This here is the filesetTree from the negative file set, but for a base path that matches the positive file set.
@@ -796,7 +786,9 @@ rec {
null;
resultingTree =
_differenceTree positive._internalBase positive._internalTree
_differenceTree
positive._internalBase
positive._internalTree
negativeTreeWithPositiveBase;
in
# If the first file set is empty, we can never have any files in the result
@@ -813,8 +805,7 @@ rec {
# Computes the set difference of two filesetTree's
# Type: Path -> filesetTree -> filesetTree
_differenceTree =
path: lhs: rhs:
_differenceTree = path: lhs: rhs:
# If the lhs doesn't have any files, or the right hand side includes all files
if lhs == null || isString rhs then
# The result will always be empty
@@ -825,19 +816,17 @@ rec {
lhs
else
# Otherwise we always have two attribute sets to recurse into
mapAttrs (name: lhsValue: _differenceTree (path + "/${name}") lhsValue (rhs.${name} or null)) (
_directoryEntries path lhs
);
mapAttrs (name: lhsValue:
_differenceTree (path + "/${name}") lhsValue (rhs.${name} or null)
) (_directoryEntries path lhs);
# Filters all files in a path based on a predicate
# Type: ({ name, type, ... } -> Bool) -> Path -> FileSet
_fileFilter =
predicate: root:
_fileFilter = predicate: root:
let
# Check the predicate for a single file
# Type: String -> String -> filesetTree
fromFile =
name: type:
fromFile = name: type:
if
predicate {
inherit name type;
@@ -845,8 +834,7 @@ rec {
# To ensure forwards compatibility with more arguments being added in the future,
# adding an attribute which can't be deconstructed :)
"lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you're using `{ name, file, hasExt }:`, use `{ name, file, hasExt, ... }:` instead." =
null;
"lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you're using `{ name, file, hasExt }:`, use `{ name, file, hasExt, ... }:` instead." = null;
}
then
type
@@ -855,10 +843,12 @@ rec {
# Check the predicate for all files in a directory
# Type: Path -> filesetTree
fromDir =
path:
mapAttrs (
name: type: if type == "directory" then fromDir (path + "/${name}") else fromFile name type
fromDir = path:
mapAttrs (name: type:
if type == "directory" then
fromDir (path + "/${name}")
else
fromFile name type
) (readDir path);
rootType = pathType root;
@@ -868,7 +858,8 @@ rec {
else
# Single files are turned into a directory containing that file or nothing.
_create (dirOf root) {
${baseNameOf root} = fromFile (baseNameOf root) rootType;
${baseNameOf root} =
fromFile (baseNameOf root) rootType;
};
# Support for `builtins.fetchGit` with `submodules = true` was introduced in 2.4
@@ -885,21 +876,22 @@ rec {
# - The store path must not include files that don't exist in the respective local path.
#
# Type: Path -> String -> FileSet
_mirrorStorePath =
localPath: storePath:
_mirrorStorePath = localPath: storePath:
let
recurse =
focusedStorePath:
mapAttrs (
name: type: if type == "directory" then recurse (focusedStorePath + "/${name}") else type
recurse = focusedStorePath:
mapAttrs (name: type:
if type == "directory" then
recurse (focusedStorePath + "/${name}")
else
type
) (builtins.readDir focusedStorePath);
in
_create localPath (recurse storePath);
_create localPath
(recurse storePath);
# Create a file set from the files included in the result of a fetchGit call
# Type: String -> String -> Path -> Attrs -> FileSet
_fromFetchGit =
function: argument: path: extraFetchGitAttrs:
_fromFetchGit = function: argument: path: extraFetchGitAttrs:
let
# The code path for when isStorePath is true
tryStorePath =
@@ -930,33 +922,31 @@ rec {
# With the [lazy trees PR](https://github.com/NixOS/nix/pull/6530),
# the unnecessarily import could be avoided.
# However a simpler alternative still would be [a builtins.gitLsFiles](https://github.com/NixOS/nix/issues/2944).
fetchResult = fetchGit (
{
url = path;
}
# In older Nix versions, repositories were always assumed to be deep clones, which made `fetchGit` fail for shallow clones
# For newer versions this was fixed, but the `shallow` flag is required.
# The only behavioral difference is that for shallow clones, `fetchGit` doesn't return a `revCount`,
# which we don't need here, so it's fine to always pass it.
fetchResult = fetchGit ({
url = path;
}
# In older Nix versions, repositories were always assumed to be deep clones, which made `fetchGit` fail for shallow clones
# For newer versions this was fixed, but the `shallow` flag is required.
# The only behavioral difference is that for shallow clones, `fetchGit` doesn't return a `revCount`,
# which we don't need here, so it's fine to always pass it.
# Unfortunately this means older Nix versions get a poor error message for shallow repositories, and there's no good way to improve that.
# Checking for `.git/shallow` doesn't seem worth it, especially since that's more of an implementation detail,
# and would also require more code to handle worktrees where `.git` is a file.
// optionalAttrs (versionAtLeast nixVersion _fetchGitShallowMinver) { shallow = true; }
// extraFetchGitAttrs
);
# Unfortunately this means older Nix versions get a poor error message for shallow repositories, and there's no good way to improve that.
# Checking for `.git/shallow` doesn't seem worth it, especially since that's more of an implementation detail,
# and would also require more code to handle worktrees where `.git` is a file.
// optionalAttrs (versionAtLeast nixVersion _fetchGitShallowMinver) { shallow = true; }
// extraFetchGitAttrs);
in
# We can identify local working directories by checking for .git,
# see https://git-scm.com/docs/gitrepository-layout#_description.
# Note that `builtins.fetchGit` _does_ work for bare repositories (where there's no `.git`),
# even though `git ls-files` wouldn't return any files in that case.
if !pathExists (path + "/.git") then
if ! pathExists (path + "/.git") then
throw "lib.fileset.${function}: Expected the ${argument} (${toString path}) to point to a local working tree of a Git repository, but it's not."
else
_mirrorStorePath path fetchResult.outPath;
in
if !isPath path then
if ! isPath path then
throw "lib.fileset.${function}: Expected the ${argument} to be a path, but it's a ${typeOf path} instead."
else if pathType path != "directory" then
throw "lib.fileset.${function}: Expected the ${argument} (${toString path}) to be a directory, but it's a file instead."

View File

@@ -8,21 +8,18 @@
# }
self: super: {
path = super.path // {
splitRoot =
path:
splitRoot = path:
let
parts = super.path.splitRoot path;
components = self.path.subpath.components parts.subpath;
count = self.length components;
rootIndex =
count
- self.lists.findFirstIndex (component: component == "mock-root") (self.length components) (
self.reverseList components
);
rootIndex = count - self.lists.findFirstIndex
(component: component == "mock-root")
(self.length components)
(self.reverseList components);
root = self.path.append parts.root (self.path.subpath.join (self.take rootIndex components));
subpath = self.path.subpath.join (self.drop rootIndex components);
in
{
in {
inherit root subpath;
};
};

View File

@@ -306,29 +306,35 @@ in
As a result, directories with no `.nix` files (including empty
directories) will be transformed into empty attribute sets.
# Inputs
Structured function argument
: Attribute set containing the following attributes.
Additional attributes are ignored.
`callPackage`
: `pkgs.callPackage`
Type: `Path -> AttrSet -> a`
`directory`
: The directory to read package files from
Type: `Path`
# Type
```
packagesFromDirectoryRecursive :: {
callPackage :: Path -> {} -> a,
directory :: Path,
...
} -> AttrSet
packagesFromDirectoryRecursive :: AttrSet -> AttrSet
```
# Inputs
`callPackage`
: The function used to convert a Nix file's path into a leaf of the attribute set.
It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`.
`directory`
: The directory to read package files from.
# Examples
:::{.example}
## Basic use of `lib.packagesFromDirectoryRecursive`
## `lib.filesystem.packagesFromDirectoryRecursive` usage example
```nix
packagesFromDirectoryRecursive {
@@ -336,48 +342,17 @@ in
directory = ./my-packages;
}
=> { ... }
```
In this case, `callPackage` will only search `pkgs` for a file's input parameters.
In other words, a file cannot refer to another file in the directory in its input parameters.
:::
::::{.example}
## Create a scope for the nix files found in a directory
```nix
lib.makeScope pkgs.newScope (
self: packagesFromDirectoryRecursive {
inherit (self) callPackage;
callPackage = self.callPackage;
directory = ./my-packages;
}
)
=> { ... }
```
For example, take the following directory structure:
```
my-packages
a.nix { b }: assert b ? b1; ...
b
b1.nix { a }: ...
b2.nix
```
Here, `b1.nix` can specify `{ a }` as a parameter, which `callPackage` will resolve as expected.
Likewise, `a.nix` receive an attrset corresponding to the contents of the `b` directory.
:::{.note}
`a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`.
:::
:::{.warning}
As of now, `lib.packagesFromDirectoryRecursive` cannot create nested scopes for sub-directories.
In particular, files under `b/` can only require (as inputs) other files under `my-packages`,
but not to those in the same directory, nor those in a parent directory; e.g, `b2.nix` cannot directly
require `b1`.
:::
::::
*/
packagesFromDirectoryRecursive =
{

View File

@@ -13,9 +13,8 @@ finalLib: prevLib: # lib overlay
{
trivial = prevLib.trivial // {
versionSuffix = ".${
finalLib.substring 0 8 (self.lastModifiedDate or "19700101")
}.${self.shortRev or "dirty"}";
versionSuffix =
".${finalLib.substring 0 8 (self.lastModifiedDate or "19700101")}.${self.shortRev or "dirty"}";
revisionWithDefault = default: self.rev or default;
};
}

View File

@@ -1,12 +1,10 @@
{
description = "Library of low-level helper functions for nix expressions.";
outputs =
{ self }:
outputs = { self }:
let
lib0 = import ./.;
in
{
in {
lib = lib0.extend (import ./flake-version-info.nix self);
};
}

View File

@@ -14,12 +14,7 @@
let
inherit (lib)
concatMapStringsSep
concatStrings
escape
head
replaceStrings
;
concatMapStringsSep concatStrings escape head replaceStrings;
mkPrimitive = t: v: {
_type = "gvariant";
@@ -54,6 +49,7 @@ rec {
/**
Check if a value is a GVariant value
# Inputs
`v`
@@ -119,6 +115,7 @@ rec {
Returns the GVariant value that most closely matches the given Nix value.
If no GVariant value can be found unambiguously then error is thrown.
# Inputs
`v`
@@ -131,8 +128,7 @@ rec {
mkValue :: Any -> gvariant
```
*/
mkValue =
v:
mkValue = v:
if builtins.isBool v then
mkBoolean v
else if builtins.isFloat v then
@@ -145,17 +141,13 @@ rec {
v
else if builtins.isInt v then
let
validConstructors = builtins.filter (
{ min, max, ... }: (min == null || min <= v) && (max == null || v <= max)
) intConstructors;
validConstructors = builtins.filter ({ min, max, ... }: (min == null || min <= v) && (max == null || v <= max)) intConstructors;
in
throw ''
The GVariant type for number ${builtins.toString v} is unclear.
Please wrap the value with one of the following, depending on the value type in GSettings schema:
${lib.concatMapStringsSep "\n" (
{ name, type, ... }: "- `lib.gvariant.${name}` for `${type}`"
) validConstructors}
${lib.concatMapStringsSep "\n" ({ name, type, ...}: "- `lib.gvariant.${name}` for `${type}`") validConstructors}
''
else if builtins.isAttrs v then
throw "Cannot construct GVariant value from an attribute set. If you want to construct a dictionary, you will need to create an array containing items constructed with `lib.gvariant.mkDictionaryEntry`."
@@ -165,6 +157,7 @@ rec {
/**
Returns the GVariant array from the given type of the elements and a Nix list.
# Inputs
`elems`
@@ -188,22 +181,22 @@ rec {
:::
*/
mkArray =
elems:
mkArray = elems:
let
vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems);
elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (
map (v: v.type) vs
)) "Elements in a list should have same type." (head vs).type;
elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs))
"Elements in a list should have same type."
(head vs).type;
in
mkPrimitive (type.arrayOf elemType) vs
// {
__toString = self: "@${self.type} [${concatMapStringsSep "," toString self.value}]";
mkPrimitive (type.arrayOf elemType) vs // {
__toString = self:
"@${self.type} [${concatMapStringsSep "," toString self.value}]";
};
/**
Returns the GVariant array from the given empty Nix list.
# Inputs
`elemType`
@@ -227,17 +220,16 @@ rec {
:::
*/
mkEmptyArray =
elemType:
mkPrimitive (type.arrayOf elemType) [ ]
// {
__toString = self: "@${self.type} []";
};
mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // {
__toString = self: "@${self.type} []";
};
/**
Returns the GVariant variant from the given Nix value. Variants are containers
of different GVariant type.
# Inputs
`elem`
@@ -263,19 +255,16 @@ rec {
:::
*/
mkVariant =
elem:
let
gvarElem = mkValue elem;
in
mkPrimitive type.variant gvarElem
// {
mkVariant = elem:
let gvarElem = mkValue elem;
in mkPrimitive type.variant gvarElem // {
__toString = self: "<${toString self.value}>";
};
/**
Returns the GVariant dictionary entry from the given key and value.
# Inputs
`name`
@@ -308,20 +297,21 @@ rec {
:::
*/
mkDictionaryEntry =
name: value:
name:
value:
let
name' = mkValue name;
value' = mkValue value;
dictionaryType = type.dictionaryEntryOf name'.type value'.type;
in
mkPrimitive dictionaryType { inherit name value; }
// {
mkPrimitive dictionaryType { inherit name value; } // {
__toString = self: "@${self.type} {${name'},${value'}}";
};
/**
Returns the GVariant maybe from the given element type.
# Inputs
`elemType`
@@ -338,17 +328,19 @@ rec {
mkMaybe :: gvariant.type -> Any -> gvariant
```
*/
mkMaybe =
elemType: elem:
mkPrimitive (type.maybeOf elemType) elem
// {
__toString =
self: if self.value == null then "@${self.type} nothing" else "just ${toString self.value}";
mkMaybe = elemType: elem:
mkPrimitive (type.maybeOf elemType) elem // {
__toString = self:
if self.value == null then
"@${self.type} nothing"
else
"just ${toString self.value}";
};
/**
Returns the GVariant nothing from the given element type.
# Inputs
`elemType`
@@ -366,6 +358,7 @@ rec {
/**
Returns the GVariant just from the given Nix value.
# Inputs
`elem`
@@ -378,16 +371,12 @@ rec {
mkJust :: Any -> gvariant
```
*/
mkJust =
elem:
let
gvarElem = mkValue elem;
in
mkMaybe gvarElem.type gvarElem;
mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
/**
Returns the GVariant tuple from the given Nix list.
# Inputs
`elems`
@@ -400,20 +389,20 @@ rec {
mkTuple :: [Any] -> gvariant
```
*/
mkTuple =
elems:
mkTuple = elems:
let
gvarElems = map mkValue elems;
tupleType = type.tupleOf (map (e: e.type) gvarElems);
in
mkPrimitive tupleType gvarElems
// {
__toString = self: "@${self.type} (${concatMapStringsSep "," toString self.value})";
mkPrimitive tupleType gvarElems // {
__toString = self:
"@${self.type} (${concatMapStringsSep "," toString self.value})";
};
/**
Returns the GVariant boolean from the given Nix bool value.
# Inputs
`v`
@@ -426,16 +415,15 @@ rec {
mkBoolean :: Bool -> gvariant
```
*/
mkBoolean =
v:
mkPrimitive type.boolean v
// {
mkBoolean = v:
mkPrimitive type.boolean v // {
__toString = self: if self.value then "true" else "false";
};
/**
Returns the GVariant string from the given Nix string value.
# Inputs
`v`
@@ -448,19 +436,16 @@ rec {
mkString :: String -> gvariant
```
*/
mkString =
v:
let
sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
in
mkPrimitive type.string v
// {
mkString = v:
let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
in mkPrimitive type.string v // {
__toString = self: "'${sanitize self.value}'";
};
/**
Returns the GVariant object path from the given Nix string value.
# Inputs
`v`
@@ -473,10 +458,8 @@ rec {
mkObjectpath :: String -> gvariant
```
*/
mkObjectpath =
v:
mkPrimitive type.string v
// {
mkObjectpath = v:
mkPrimitive type.string v // {
__toString = self: "objectpath '${escape [ "'" ] self.value}'";
};
@@ -516,6 +499,7 @@ rec {
/**
Returns the GVariant int32 from the given Nix int value.
# Inputs
`v`
@@ -528,10 +512,8 @@ rec {
mkInt32 :: Int -> gvariant
```
*/
mkInt32 =
v:
mkPrimitive type.int32 v
// {
mkInt32 = v:
mkPrimitive type.int32 v // {
__toString = self: toString self.value;
};
@@ -571,6 +553,7 @@ rec {
/**
Returns the GVariant double from the given Nix float value.
# Inputs
`v`
@@ -583,10 +566,8 @@ rec {
mkDouble :: Float -> gvariant
```
*/
mkDouble =
v:
mkPrimitive type.double v
// {
mkDouble = v:
mkPrimitive type.double v // {
__toString = self: toString self.value;
};
}

View File

@@ -5,34 +5,22 @@ let
in
{
# Keeping these around in case we decide to change this horrible implementation :)
option = x: x // { optional = true; };
yes = {
tristate = "y";
optional = false;
};
no = {
tristate = "n";
optional = false;
};
module = {
tristate = "m";
optional = false;
};
unset = {
tristate = null;
optional = false;
};
freeform = x: {
freeform = x;
optional = false;
};
# Keeping these around in case we decide to change this horrible implementation :)
option = x:
x // { optional = true; };
yes = { tristate = "y"; optional = false; };
no = { tristate = "n"; optional = false; };
module = { tristate = "m"; optional = false; };
unset = { tristate = null; optional = false; };
freeform = x: { freeform = x; optional = false; };
# Common patterns/legacy used in common-config/hardened/config.nix
whenHelpers = version: {
whenAtLeast = ver: mkIf (versionAtLeast version ver);
whenOlder = ver: mkIf (versionOlder version ver);
whenOlder = ver: mkIf (versionOlder version ver);
# range is (inclusive, exclusive)
whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh);
};

View File

@@ -115,6 +115,7 @@ lib.mapAttrs mkLicense ({
arphicpl = {
spdxId = "Arphic-1999";
fullName = "Arphic Public License";
url = "https://www.freedesktop.org/wiki/Arphic_Public_License/";
};
artistic1 = {
@@ -240,6 +241,7 @@ lib.mapAttrs mkLicense ({
bsl11 = {
spdxId = "BUSL-1.1";
fullName = "Business Source License 1.1";
url = "https://mariadb.com/bsl11";
free = false;
redistributable = true;
};
@@ -252,11 +254,13 @@ lib.mapAttrs mkLicense ({
cal10 = {
spdxId = "CAL-1.0";
fullName = "Cryptographic Autonomy License version 1.0 (CAL-1.0)";
url = "https://opensource.org/licenses/CAL-1.0";
};
caldera = {
spdxId = "Caldera";
fullName = "Caldera License";
url = "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf";
};
capec = {
@@ -460,6 +464,7 @@ lib.mapAttrs mkLicense ({
ecl20 = {
fullName = "Educational Community License, Version 2.0";
url = "https://opensource.org/licenses/ECL-2.0";
shortName = "ECL 2.0";
spdxId = "ECL-2.0";
};
@@ -477,6 +482,7 @@ lib.mapAttrs mkLicense ({
elastic20 = {
spdxId = "Elastic-2.0";
fullName = "Elastic License 2.0";
url = "https://github.com/elastic/elasticsearch/blob/main/licenses/ELASTIC-LICENSE-2.0.txt";
free = false;
};
@@ -670,6 +676,7 @@ lib.mapAttrs mkLicense ({
iasl = {
spdxId = "Intel-ACPI";
fullName = "Intel ACPI Software License Agreement";
url = "https://old.calculate-linux.org/packages/licenses/iASL";
};
icu = {
@@ -695,6 +702,7 @@ lib.mapAttrs mkLicense ({
info-zip = {
spdxId = "Info-ZIP";
fullName = "Info-ZIP License";
url = "https://infozip.sourceforge.net/license.html";
};
inria-compcert = {
@@ -792,7 +800,7 @@ lib.mapAttrs mkLicense ({
lens = {
fullName = "Lens Terms of Service Agreement";
url = "https://k8slens.dev/legal/tos";
url = "https://k8slens.dev/licenses/tos";
free = false;
};
@@ -879,6 +887,7 @@ lib.mapAttrs mkLicense ({
miros = {
spdxId = "MirOS";
fullName = "MirOS License";
url = "https://opensource.org/licenses/MirOS";
};
mit = {
@@ -940,6 +949,7 @@ lib.mapAttrs mkLicense ({
mulan-psl2 = {
spdxId = "MulanPSL-2.0";
fullName = "Mulan Permissive Software License, Version 2";
url = "https://license.coscl.org.cn/MulanPSL2";
};
naist-2003 = {
@@ -974,6 +984,7 @@ lib.mapAttrs mkLicense ({
fullName = "Netdata Cloud UI License v1.0";
free = false;
redistributable = true; # Only if used in Netdata products.
url = "https://raw.githubusercontent.com/netdata/netdata/master/web/gui/v2/LICENSE.md";
};
nistSoftware = {
@@ -1071,6 +1082,7 @@ lib.mapAttrs mkLicense ({
parity70 = {
spdxId = "Parity-7.0.0";
fullName = "Parity Public License 7.0.0";
url = "https://paritylicense.com/versions/7.0.0.html";
};
php301 = {
@@ -1092,6 +1104,7 @@ lib.mapAttrs mkLicense ({
psfl = {
spdxId = "Python-2.0";
fullName = "Python Software Foundation License version 2";
url = "https://docs.python.org/license.html";
};
publicDomain = {
@@ -1220,8 +1233,8 @@ lib.mapAttrs mkLicense ({
};
ufl = {
spdxId = "Ubuntu-font-1.0";
fullName = "Ubuntu Font License 1.0";
url = "https://ubuntu.com/legal/font-licence";
};
unfree = {
@@ -1265,6 +1278,7 @@ lib.mapAttrs mkLicense ({
upl = {
spdxId = "UPL-1.0";
fullName = "Universal Permissive License";
url = "https://oss.oracle.com/licenses/upl/";
};
vim = {
@@ -1330,6 +1344,7 @@ lib.mapAttrs mkLicense ({
xfig = {
spdxId = "Xfig";
fullName = "xfig";
url = "https://mcj.sourceforge.net/authors.html#xfig";
};
xinetd = {

View File

@@ -751,47 +751,17 @@ let
t' = opt.options.type;
mergedType = t.typeMerge t'.functor;
typesMergeable = mergedType != null;
# TODO: Remove this when all downstream reliances of internals: 'functor.wrapped' are sufficiently migrated.
# A function that adds the deprecated wrapped message to a type.
addDeprecatedWrapped = t:
t // {
functor = t.functor // {
wrapped = t.functor.wrappedDeprecationMessage {
inherit loc;
};
};
};
typeSet =
if opt.options ? type then
if res ? type then
if typesMergeable then
{
type =
if mergedType ? functor.wrappedDeprecationMessage then
addDeprecatedWrapped mergedType
else
mergedType;
}
else
# Keep in sync with the same error below!
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
else if opt.options.type ? functor.wrappedDeprecationMessage then
{ type = addDeprecatedWrapped opt.options.type; }
else
{}
else
{};
typeSet = if (bothHave "type") && typesMergeable
then { type = mergedType; }
else {};
bothHave = k: opt.options ? ${k} && res ? ${k};
in
if bothHave "default" ||
bothHave "example" ||
bothHave "description" ||
bothHave "apply"
bothHave "apply" ||
(bothHave "type" && (! typesMergeable))
then
# Keep in sync with the same error above!
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
else
let

View File

@@ -399,6 +399,13 @@ rec {
literalExample = lib.warn "lib.literalExample is deprecated, use lib.literalExpression instead, or use lib.literalMD for a non-Nix description." literalExpression;
/* Transition marker for documentation that's already migrated to markdown
syntax. Has been a no-op for some while and been removed from nixpkgs.
Kept here to alert downstream users who may not be aware of the migration's
completion that it should be removed from modules.
*/
mdDoc = lib.warn "lib.mdDoc will be removed from nixpkgs in 24.11. Option descriptions are now in Markdown by default; you can remove any remaining uses of lib.mdDoc.";
/* For use in the `defaultText` and `example` option attributes. Causes the
given MD text to be inserted verbatim in the documentation, for when
a `literalExpression` would be too hard to read.
@@ -420,17 +427,20 @@ rec {
Placeholders will not be quoted as they are not actual values:
(showOption ["foo" "*" "bar"]) == "foo.*.bar"
(showOption ["foo" "<name>" "bar"]) == "foo.<name>.bar"
(showOption ["foo" "<myPlaceholder>" "bar"]) == "foo.<myPlaceholder>.bar"
*/
showOption = parts: let
# If the part is a named placeholder of the form "<...>" don't escape it.
# It may cause misleading escaping if somebody uses literally "<...>" in their option names.
# This is the trade-off to allow for placeholders in option names.
isNamedPlaceholder = builtins.match "\<(.*)\>";
escapeOptionPart = part:
if part == "*" || isNamedPlaceholder part != null
then part
else lib.strings.escapeNixIdentifier part;
let
# We assume that these are "special values" and not real configuration data.
# If it is real configuration data, it is rendered incorrectly.
specialIdentifiers = [
"<name>" # attrsOf (submodule {})
"*" # listOf (submodule {})
"<function body>" # functionTo
];
in if builtins.elem part specialIdentifiers
then part
else lib.strings.escapeNixIdentifier part;
in (concatStringsSep ".") (map escapeOptionPart parts);
showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files);

View File

@@ -1,4 +1,4 @@
# Functions for working with path values.
/* Functions for working with path values. */
# See ./README.md for internal docs
{ lib }:
let
@@ -41,9 +41,8 @@ let
;
# Return the reason why a subpath is invalid, or `null` if it's valid
subpathInvalidReason =
value:
if !isString value then
subpathInvalidReason = value:
if ! isString value then
"The given value is of type ${builtins.typeOf value}, but a string was expected"
else if value == "" then
"The given string is empty"
@@ -52,13 +51,11 @@ let
# We don't support ".." components, see ./path.md#parent-directory
else if match "(.*/)?\\.\\.(/.*)?" value != null then
"The given string \"${value}\" contains a `..` component, which is not allowed in subpaths"
else
null;
else null;
# Split and normalise a relative path string into its components.
# Error for ".." components and doesn't include "." components
splitRelPath =
path:
splitRelPath = path:
let
# Split the string into its parts using regex for efficiency. This regex
# matches patterns like "/", "/./", "/././", with arbitrarily many "/"s
@@ -89,31 +86,26 @@ let
componentCount = partCount - skipEnd - skipStart;
in
# Special case of a single "." path component. Such a case leaves a
# componentCount of -1 due to the skipStart/skipEnd not verifying that
# they don't refer to the same character
if path == "." then
[ ]
# Special case of a single "." path component. Such a case leaves a
# componentCount of -1 due to the skipStart/skipEnd not verifying that
# they don't refer to the same character
if path == "." then []
# Generate the result list directly. This is more efficient than a
# combination of `filter`, `init` and `tail`, because here we don't
# allocate any intermediate lists
else
genList (
index:
# Generate the result list directly. This is more efficient than a
# combination of `filter`, `init` and `tail`, because here we don't
# allocate any intermediate lists
else genList (index:
# To get to the element we need to add the number of parts we skip and
# multiply by two due to the interleaved layout of `parts`
elemAt parts ((skipStart + index) * 2)
) componentCount;
# Join relative path components together
joinRelPath =
components:
joinRelPath = components:
# Always return relative paths with `./` as a prefix (./path.md#leading-dots-for-relative-paths)
"./"
+
# An empty string is not a valid relative path, so we need to return a `.` when we have no components
(if components == [ ] then "." else concatStringsSep "/" components);
"./" +
# An empty string is not a valid relative path, so we need to return a `.` when we have no components
(if components == [] then "." else concatStringsSep "/" components);
# Type: Path -> { root :: Path, components :: [ String ] }
#
@@ -125,18 +117,11 @@ let
# because it can distinguish different filesystem roots
deconstructPath =
let
recurse =
components: base:
recurse = components: base:
# If the parent of a path is the path itself, then it's a filesystem root
if base == dirOf base then
{
root = base;
inherit components;
}
else
recurse ([ (baseNameOf base) ] ++ components) (dirOf base);
in
recurse [ ];
if base == dirOf base then { root = base; inherit components; }
else recurse ([ (baseNameOf base) ] ++ components) (dirOf base);
in recurse [];
# The components of the store directory, typically [ "nix" "store" ]
storeDirComponents = splitRelPath ("./" + storeDir);
@@ -147,8 +132,7 @@ let
#
# Whether path components have a store path as a prefix, according to
# https://nixos.org/manual/nix/stable/store/store-path.html#store-path.
componentsHaveStorePathPrefix =
components:
componentsHaveStorePathPrefix = components:
# path starts with the store directory (typically /nix/store)
listHasPrefix storeDirComponents components
# is not the store directory itself, meaning there's at least one extra component
@@ -161,9 +145,7 @@ let
# We care more about discerning store path-ness on realistic values. Making it airtight would be fragile and slow.
&& match ".{32}-.+" (elemAt components storeDirLength) != null;
in
# No rec! Add dependencies on this file at the top.
{
in /* No rec! Add dependencies on this file at the top. */ {
/*
Append a subpath string to a path.
@@ -212,8 +194,8 @@ in
path:
# The subpath string to append
subpath:
assert assertMsg (isPath path)
''lib.path.append: The first argument is of type ${builtins.typeOf path}, but a path was expected'';
assert assertMsg (isPath path) ''
lib.path.append: The first argument is of type ${builtins.typeOf path}, but a path was expected'';
assert assertMsg (isValid subpath) ''
lib.path.append: Second argument is not a valid subpath string:
${subpathInvalidReason subpath}'';
@@ -243,23 +225,25 @@ in
*/
hasPrefix =
path1:
assert assertMsg (isPath path1)
assert assertMsg
(isPath path1)
"lib.path.hasPrefix: First argument is of type ${typeOf path1}, but a path was expected";
let
path1Deconstructed = deconstructPath path1;
in
path2:
assert assertMsg (isPath path2)
"lib.path.hasPrefix: Second argument is of type ${typeOf path2}, but a path was expected";
let
path2Deconstructed = deconstructPath path2;
in
assert assertMsg (path1Deconstructed.root == path2Deconstructed.root) ''
lib.path.hasPrefix: Filesystem roots must be the same for both paths, but paths with different roots were given:
first argument: "${toString path1}" with root "${toString path1Deconstructed.root}"
second argument: "${toString path2}" with root "${toString path2Deconstructed.root}"'';
take (length path1Deconstructed.components) path2Deconstructed.components
== path1Deconstructed.components;
path2:
assert assertMsg
(isPath path2)
"lib.path.hasPrefix: Second argument is of type ${typeOf path2}, but a path was expected";
let
path2Deconstructed = deconstructPath path2;
in
assert assertMsg
(path1Deconstructed.root == path2Deconstructed.root) ''
lib.path.hasPrefix: Filesystem roots must be the same for both paths, but paths with different roots were given:
first argument: "${toString path1}" with root "${toString path1Deconstructed.root}"
second argument: "${toString path2}" with root "${toString path2Deconstructed.root}"'';
take (length path1Deconstructed.components) path2Deconstructed.components == path1Deconstructed.components;
/*
Remove the first path as a component-wise prefix from the second path.
@@ -286,29 +270,33 @@ in
*/
removePrefix =
path1:
assert assertMsg (isPath path1)
assert assertMsg
(isPath path1)
"lib.path.removePrefix: First argument is of type ${typeOf path1}, but a path was expected.";
let
path1Deconstructed = deconstructPath path1;
path1Length = length path1Deconstructed.components;
in
path2:
assert assertMsg (isPath path2)
"lib.path.removePrefix: Second argument is of type ${typeOf path2}, but a path was expected.";
let
path2Deconstructed = deconstructPath path2;
success = take path1Length path2Deconstructed.components == path1Deconstructed.components;
components =
if success then
drop path1Length path2Deconstructed.components
else
throw ''lib.path.removePrefix: The first path argument "${toString path1}" is not a component-wise prefix of the second path argument "${toString path2}".'';
in
assert assertMsg (path1Deconstructed.root == path2Deconstructed.root) ''
lib.path.removePrefix: Filesystem roots must be the same for both paths, but paths with different roots were given:
first argument: "${toString path1}" with root "${toString path1Deconstructed.root}"
second argument: "${toString path2}" with root "${toString path2Deconstructed.root}"'';
joinRelPath components;
path2:
assert assertMsg
(isPath path2)
"lib.path.removePrefix: Second argument is of type ${typeOf path2}, but a path was expected.";
let
path2Deconstructed = deconstructPath path2;
success = take path1Length path2Deconstructed.components == path1Deconstructed.components;
components =
if success then
drop path1Length path2Deconstructed.components
else
throw ''
lib.path.removePrefix: The first path argument "${toString path1}" is not a component-wise prefix of the second path argument "${toString path2}".'';
in
assert assertMsg
(path1Deconstructed.root == path2Deconstructed.root) ''
lib.path.removePrefix: Filesystem roots must be the same for both paths, but paths with different roots were given:
first argument: "${toString path1}" with root "${toString path1Deconstructed.root}"
second argument: "${toString path2}" with root "${toString path2Deconstructed.root}"'';
joinRelPath components;
/*
Split the filesystem root from a [path](https://nixos.org/manual/nix/stable/language/values.html#type-path).
@@ -348,12 +336,12 @@ in
splitRoot =
# The path to split the root off of
path:
assert assertMsg (isPath path)
assert assertMsg
(isPath path)
"lib.path.splitRoot: Argument is of type ${typeOf path}, but a path was expected";
let
deconstructed = deconstructPath path;
in
{
in {
root = deconstructed.root;
subpath = joinRelPath deconstructed.components;
};
@@ -399,12 +387,12 @@ in
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv
=> true
*/
hasStorePathPrefix =
path:
hasStorePathPrefix = path:
let
deconstructed = deconstructPath path;
in
assert assertMsg (isPath path)
assert assertMsg
(isPath path)
"lib.path.hasStorePathPrefix: Argument is of type ${typeOf path}, but a path was expected";
assert assertMsg
# This function likely breaks or needs adjustment if used with other filesystem roots, if they ever get implemented.
@@ -458,7 +446,9 @@ in
*/
subpath.isValid =
# The value to check
value: subpathInvalidReason value == null;
value:
subpathInvalidReason value == null;
/*
Join subpath strings together using `/`, returning a normalised subpath string.
@@ -521,20 +511,18 @@ in
# The list of subpaths to join together
subpaths:
# Fast in case all paths are valid
if all isValid subpaths then
joinRelPath (concatMap splitRelPath subpaths)
if all isValid subpaths
then joinRelPath (concatMap splitRelPath subpaths)
else
# Otherwise we take our time to gather more info for a better error message
# Strictly go through each path, throwing on the first invalid one
# Tracks the list index in the fold accumulator
foldl' (
i: path:
if isValid path then
i + 1
else
throw ''
lib.path.subpath.join: Element at index ${toString i} is not a valid subpath string:
${subpathInvalidReason path}''
foldl' (i: path:
if isValid path
then i + 1
else throw ''
lib.path.subpath.join: Element at index ${toString i} is not a valid subpath string:
${subpathInvalidReason path}''
) 0 subpaths;
/*

View File

@@ -2,8 +2,8 @@
nixpkgs ? ../../..,
system ? builtins.currentSystem,
pkgs ? import nixpkgs {
config = { };
overlays = [ ];
config = {};
overlays = [];
inherit system;
},
nixVersions ? import ../../tests/nix-for-tests.nix { inherit pkgs; },
@@ -12,38 +12,34 @@
seed ? null,
}:
pkgs.runCommand "lib-path-tests"
{
nativeBuildInputs =
[
nixVersions.stable
]
++ (with pkgs; [
jq
bc
]);
}
''
# Needed to make Nix evaluation work
export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK=
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 NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
pkgs.runCommand "lib-path-tests" {
nativeBuildInputs = [
nixVersions.stable
] ++ (with pkgs; [
jq
bc
]);
} ''
# Needed to make Nix evaluation work
export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK=
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 NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
cp -r ${libpath} lib
export TEST_LIB=$PWD/lib
cp -r ${libpath} lib
export TEST_LIB=$PWD/lib
echo "Running unit tests lib/path/tests/unit.nix"
nix-instantiate --eval --show-trace \
--argstr libpath "$TEST_LIB" \
lib/path/tests/unit.nix
echo "Running unit tests lib/path/tests/unit.nix"
nix-instantiate --eval --show-trace \
--argstr libpath "$TEST_LIB" \
lib/path/tests/unit.nix
echo "Running property tests lib/path/tests/prop.sh"
bash lib/path/tests/prop.sh ${toString seed}
echo "Running property tests lib/path/tests/prop.sh"
bash lib/path/tests/prop.sh ${toString seed}
touch $out
''
touch $out
''

View File

@@ -16,15 +16,14 @@ let
lib = import libpath;
# read each file into a string
strings = map (name: builtins.readFile (dir + "/${name}")) (
builtins.attrNames (builtins.readDir dir)
);
strings = map (name:
builtins.readFile (dir + "/${name}")
) (builtins.attrNames (builtins.readDir dir));
inherit (lib.path.subpath) normalise isValid;
inherit (lib.asserts) assertMsg;
normaliseAndCheck =
str:
normaliseAndCheck = str:
let
originalValid = isValid str;
@@ -34,27 +33,28 @@ let
absConcatOrig = /. + ("/" + str);
absConcatNormalised = /. + ("/" + tryOnce.value);
in
# Check the lib.path.subpath.normalise property to only error on invalid subpaths
assert assertMsg (
originalValid -> tryOnce.success
) "Even though string \"${str}\" is valid as a subpath, the normalisation for it failed";
assert assertMsg (
!originalValid -> !tryOnce.success
) "Even though string \"${str}\" is invalid as a subpath, the normalisation for it succeeded";
# Check the lib.path.subpath.normalise property to only error on invalid subpaths
assert assertMsg
(originalValid -> tryOnce.success)
"Even though string \"${str}\" is valid as a subpath, the normalisation for it failed";
assert assertMsg
(! originalValid -> ! tryOnce.success)
"Even though string \"${str}\" is invalid as a subpath, the normalisation for it succeeded";
# Check normalisation idempotency
assert assertMsg (
originalValid -> tryTwice.success
) "For valid subpath \"${str}\", the normalisation \"${tryOnce.value}\" was not a valid subpath";
assert assertMsg (originalValid -> tryOnce.value == tryTwice.value)
"For valid subpath \"${str}\", normalising it once gives \"${tryOnce.value}\" but normalising it twice gives a different result: \"${tryTwice.value}\"";
# Check normalisation idempotency
assert assertMsg
(originalValid -> tryTwice.success)
"For valid subpath \"${str}\", the normalisation \"${tryOnce.value}\" was not a valid subpath";
assert assertMsg
(originalValid -> tryOnce.value == tryTwice.value)
"For valid subpath \"${str}\", normalising it once gives \"${tryOnce.value}\" but normalising it twice gives a different result: \"${tryTwice.value}\"";
# Check that normalisation doesn't change a string when appended to an absolute Nix path value
assert assertMsg (originalValid -> absConcatOrig == absConcatNormalised)
"For valid subpath \"${str}\", appending to an absolute Nix path value gives \"${absConcatOrig}\", but appending the normalised result \"${tryOnce.value}\" gives a different value \"${absConcatNormalised}\"";
# Check that normalisation doesn't change a string when appended to an absolute Nix path value
assert assertMsg
(originalValid -> absConcatOrig == absConcatNormalised)
"For valid subpath \"${str}\", appending to an absolute Nix path value gives \"${absConcatOrig}\", but appending the normalised result \"${tryOnce.value}\" gives a different value \"${absConcatNormalised}\"";
# Return an empty string when failed
if tryOnce.success then tryOnce.value else "";
# Return an empty string when failed
if tryOnce.success then tryOnce.value else "";
in
lib.genAttrs strings normaliseAndCheck
in lib.genAttrs strings normaliseAndCheck

View File

@@ -3,14 +3,7 @@
{ libpath }:
let
lib = import libpath;
inherit (lib.path)
hasPrefix
removePrefix
append
splitRoot
hasStorePathPrefix
subpath
;
inherit (lib.path) hasPrefix removePrefix append splitRoot hasStorePathPrefix subpath;
# This is not allowed generally, but we're in the tests here, so we'll allow ourselves.
storeDirPath = /. + builtins.storeDir;
@@ -86,24 +79,15 @@ let
testSplitRootExample1 = {
expr = splitRoot /foo/bar;
expected = {
root = /.;
subpath = "./foo/bar";
};
expected = { root = /.; subpath = "./foo/bar"; };
};
testSplitRootExample2 = {
expr = splitRoot /.;
expected = {
root = /.;
subpath = "./.";
};
expected = { root = /.; subpath = "./."; };
};
testSplitRootExample3 = {
expr = splitRoot /foo/../bar;
expected = {
root = /.;
subpath = "./bar";
};
expected = { root = /.; subpath = "./bar"; };
};
testSplitRootExample4 = {
expr = (builtins.tryEval (splitRoot "/foo/bar")).success;
@@ -127,9 +111,7 @@ let
expected = false;
};
testHasStorePathPrefixExample5 = {
expr = hasStorePathPrefix (
storeDirPath + "/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq"
);
expr = hasStorePathPrefix (storeDirPath + "/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq");
expected = false;
};
testHasStorePathPrefixExample6 = {
@@ -206,18 +188,11 @@ let
# Test examples from the lib.path.subpath.join documentation
testSubpathJoinExample1 = {
expr = subpath.join [
"foo"
"bar/baz"
];
expr = subpath.join [ "foo" "bar/baz" ];
expected = "./foo/bar/baz";
};
testSubpathJoinExample2 = {
expr = subpath.join [
"./foo"
"."
"bar//./baz/"
];
expr = subpath.join [ "./foo" "." "bar//./baz/" ];
expected = "./foo/bar/baz";
};
testSubpathJoinExample3 = {
@@ -298,11 +273,7 @@ let
};
testSubpathComponentsExample2 = {
expr = subpath.components "./foo//bar/./baz/";
expected = [
"foo"
"bar"
"baz"
];
expected = [ "foo" "bar" "baz" ];
};
testSubpathComponentsExample3 = {
expr = (builtins.tryEval (subpath.components "/foo")).success;
@@ -310,7 +281,5 @@ let
};
};
in
if cases == [ ] then
"Unit tests successful"
else
throw "Path unit tests failed: ${lib.generators.toPretty { } cases}"
if cases == [] then "Unit tests successful"
else throw "Path unit tests failed: ${lib.generators.toPretty {} cases}"

View File

@@ -5,16 +5,15 @@ let
shortName = tname;
isSource = false;
};
in
lib.mapAttrs (tname: tset: defaultSourceType tname // tset) {
in lib.mapAttrs (tname: tset: defaultSourceType tname // tset) {
fromSource = {
isSource = true;
};
binaryNativeCode = { };
binaryNativeCode = {};
binaryBytecode = { };
binaryBytecode = {};
binaryFirmware = { };
binaryFirmware = {};
}

View File

@@ -1,4 +1,4 @@
# Functions for copying sources to the Nix store.
/* Functions for copying sources to the Nix store. */
{ lib }:
# Tested in lib/tests/sources.sh
@@ -23,34 +23,22 @@ let
directories of version control system, backup files (*~)
and some generated files.
*/
cleanSourceFilter =
name: type:
let
baseName = baseNameOf (toString name);
in
!(
# Filter out version control software files/directories
(
baseName == ".git"
|| type == "directory" && (baseName == ".svn" || baseName == "CVS" || baseName == ".hg")
)
||
# Filter out editor backup / swap files.
lib.hasSuffix "~" baseName
|| match "^\\.sw[a-z]$" baseName != null
|| match "^\\..*\\.sw[a-z]$" baseName != null
||
cleanSourceFilter = name: type: let baseName = baseNameOf (toString name); in ! (
# Filter out version control software files/directories
(baseName == ".git" || type == "directory" && (baseName == ".svn" || baseName == "CVS" || baseName == ".hg")) ||
# Filter out editor backup / swap files.
lib.hasSuffix "~" baseName ||
match "^\\.sw[a-z]$" baseName != null ||
match "^\\..*\\.sw[a-z]$" baseName != null ||
# Filter out generates files.
lib.hasSuffix ".o" baseName
|| lib.hasSuffix ".so" baseName
||
# Filter out nix-build result symlinks
(type == "symlink" && lib.hasPrefix "result" baseName)
||
# Filter out sockets and other types of files we can't have in the store.
(type == "unknown")
);
# Filter out generates files.
lib.hasSuffix ".o" baseName ||
lib.hasSuffix ".so" baseName ||
# Filter out nix-build result symlinks
(type == "symlink" && lib.hasPrefix "result" baseName) ||
# Filter out sockets and other types of files we can't have in the store.
(type == "unknown")
);
/*
Filters a source tree removing version control files and directories using cleanSourceFilter.
@@ -58,12 +46,7 @@ let
Example:
cleanSource ./.
*/
cleanSource =
src:
cleanSourceWith {
filter = cleanSourceFilter;
inherit src;
};
cleanSource = src: cleanSourceWith { filter = cleanSourceFilter; inherit src; };
/*
Like `builtins.filterSource`, except it will compose with itself,
@@ -82,6 +65,7 @@ let
builtins.filterSource f (builtins.filterSource g ./.)
# Fails!
*/
cleanSourceWith =
{
@@ -96,12 +80,11 @@ let
filter ? _path: _type: true,
# Optional name to use as part of the store path.
# This defaults to `src.name` or otherwise `"source"`.
name ? null,
name ? null
}:
let
orig = toSourceAttributes src;
in
fromSourceAttributes {
in fromSourceAttributes {
inherit (orig) origSrc;
filter = path: type: filter path type && orig.filter path type;
name = if name != null then name else orig.name;
@@ -118,40 +101,31 @@ let
let
attrs = toSourceAttributes src;
in
fromSourceAttributes (
attrs
// {
filter =
path: type:
let
r = attrs.filter path type;
in
builtins.trace "${attrs.name}.filter ${path} = ${boolToString r}" r;
}
)
// {
satisfiesSubpathInvariant = src ? satisfiesSubpathInvariant && src.satisfiesSubpathInvariant;
};
fromSourceAttributes (
attrs // {
filter = path: type:
let
r = attrs.filter path type;
in
builtins.trace "${attrs.name}.filter ${path} = ${boolToString r}" r;
}
) // {
satisfiesSubpathInvariant = src ? satisfiesSubpathInvariant && src.satisfiesSubpathInvariant;
};
/*
Filter sources by a list of regular expressions.
Example: src = sourceByRegex ./my-subproject [".*\.py$" "^database.sql$"]
*/
sourceByRegex =
src: regexes:
sourceByRegex = src: regexes:
let
isFiltered = src ? _isLibCleanSourceWith;
origSrc = if isFiltered then src.origSrc else src;
in
lib.cleanSourceWith {
filter = (
path: type:
let
relPath = lib.removePrefix (toString origSrc + "/") (toString path);
in
lib.any (re: match re relPath != null) regexes
);
in lib.cleanSourceWith {
filter = (path: type:
let relPath = lib.removePrefix (toString origSrc + "/") (toString path);
in lib.any (re: match re relPath != null) regexes);
inherit src;
};
@@ -171,29 +145,21 @@ let
src:
# A list of file suffix strings
exts:
let
filter =
name: type:
let
base = baseNameOf (toString name);
in
type == "directory" || lib.any (ext: lib.hasSuffix ext base) exts;
in
cleanSourceWith { inherit filter src; };
let filter = name: type:
let base = baseNameOf (toString name);
in type == "directory" || lib.any (ext: lib.hasSuffix ext base) exts;
in cleanSourceWith { inherit filter src; };
pathIsGitRepo = path: (_commitIdFromGitRepoOrError path) ? value;
pathIsGitRepo = path: (_commitIdFromGitRepoOrError path)?value;
/*
Get the commit id of a git repo.
Example: commitIdFromGitRepo <nixpkgs/.git>
*/
commitIdFromGitRepo =
path:
let
commitIdOrError = _commitIdFromGitRepoOrError path;
in
commitIdOrError.value or (throw commitIdOrError.error);
commitIdFromGitRepo = path:
let commitIdOrError = _commitIdFromGitRepoOrError path;
in commitIdOrError.value or (throw commitIdOrError.error);
# Get the commit id of a git repo.
@@ -202,68 +168,55 @@ let
# Example: commitIdFromGitRepo <nixpkgs/.git>
# not exported, used for commitIdFromGitRepo
_commitIdFromGitRepoOrError =
let
readCommitFromFile =
file: path:
let
fileName = path + "/${file}";
packedRefsName = path + "/packed-refs";
absolutePath =
base: path: if lib.hasPrefix "/" path then path else toString (/. + "${base}/${path}");
in
if
pathIsRegularFile path
# Resolve git worktrees. See gitrepository-layout(5)
then
let
m = match "^gitdir: (.*)$" (lib.fileContents path);
in
if m == null then
{ error = "File contains no gitdir reference: " + path; }
else
let
gitDir = absolutePath (dirOf path) (lib.head m);
commonDir'' =
if pathIsRegularFile "${gitDir}/commondir" then lib.fileContents "${gitDir}/commondir" else gitDir;
commonDir' = lib.removeSuffix "/" commonDir'';
commonDir = absolutePath gitDir commonDir';
refFile = lib.removePrefix "${commonDir}/" "${gitDir}/${file}";
in
readCommitFromFile refFile commonDir
let readCommitFromFile = file: path:
let fileName = path + "/${file}";
packedRefsName = path + "/packed-refs";
absolutePath = base: path:
if lib.hasPrefix "/" path
then path
else toString (/. + "${base}/${path}");
in if pathIsRegularFile path
# Resolve git worktrees. See gitrepository-layout(5)
then
let m = match "^gitdir: (.*)$" (lib.fileContents path);
in if m == null
then { error = "File contains no gitdir reference: " + path; }
else
let gitDir = absolutePath (dirOf path) (lib.head m);
commonDir'' = if pathIsRegularFile "${gitDir}/commondir"
then lib.fileContents "${gitDir}/commondir"
else gitDir;
commonDir' = lib.removeSuffix "/" commonDir'';
commonDir = absolutePath gitDir commonDir';
refFile = lib.removePrefix "${commonDir}/" "${gitDir}/${file}";
in readCommitFromFile refFile commonDir
else if
pathIsRegularFile fileName
# Sometimes git stores the commitId directly in the file but
# sometimes it stores something like: «ref: refs/heads/branch-name»
then
let
fileContent = lib.fileContents fileName;
matchRef = match "^ref: (.*)$" fileContent;
in
if matchRef == null then { value = fileContent; } else readCommitFromFile (lib.head matchRef) path
else if pathIsRegularFile fileName
# Sometimes git stores the commitId directly in the file but
# sometimes it stores something like: «ref: refs/heads/branch-name»
then
let fileContent = lib.fileContents fileName;
matchRef = match "^ref: (.*)$" fileContent;
in if matchRef == null
then { value = fileContent; }
else readCommitFromFile (lib.head matchRef) path
else if
pathIsRegularFile packedRefsName
# Sometimes, the file isn't there at all and has been packed away in the
# packed-refs file, so we have to grep through it:
then
let
fileContent = readFile packedRefsName;
matchRef = match "([a-z0-9]+) ${file}";
isRef = s: isString s && (matchRef s) != null;
# there is a bug in libstdc++ leading to stackoverflow for long strings:
# https://github.com/NixOS/nix/issues/2147#issuecomment-659868795
refs = filter isRef (split "\n" fileContent);
in
if refs == [ ] then
{ error = "Could not find " + file + " in " + packedRefsName; }
else
{ value = lib.head (matchRef (lib.head refs)); }
else if pathIsRegularFile packedRefsName
# Sometimes, the file isn't there at all and has been packed away in the
# packed-refs file, so we have to grep through it:
then
let fileContent = readFile packedRefsName;
matchRef = match "([a-z0-9]+) ${file}";
isRef = s: isString s && (matchRef s) != null;
# there is a bug in libstdc++ leading to stackoverflow for long strings:
# https://github.com/NixOS/nix/issues/2147#issuecomment-659868795
refs = filter isRef (split "\n" fileContent);
in if refs == []
then { error = "Could not find " + file + " in " + packedRefsName; }
else { value = lib.head (matchRef (lib.head refs)); }
else
{ error = "Not a .git directory: " + toString path; };
in
readCommitFromFile "HEAD";
else { error = "Not a .git directory: " + toString path; };
in readCommitFromFile "HEAD";
pathHasContext = builtins.hasContext or (lib.hasPrefix storeDir);
@@ -280,8 +233,7 @@ let
# like class of objects in the wild.
# (Existing ones being: paths, strings, sources and x//{outPath})
# So instead of exposing internals, we build a library of combinator functions.
toSourceAttributes =
src:
toSourceAttributes = src:
let
isFiltered = src ? _isLibCleanSourceWith;
in
@@ -295,38 +247,26 @@ let
# fromSourceAttributes : SourceAttrs -> Source
#
# Inverse of toSourceAttributes for Source objects.
fromSourceAttributes =
{
origSrc,
filter,
name,
}:
fromSourceAttributes = { origSrc, filter, name }:
{
_isLibCleanSourceWith = true;
inherit origSrc filter name;
outPath = builtins.path {
inherit filter name;
path = origSrc;
};
outPath = builtins.path { inherit filter name; path = origSrc; };
};
in
{
in {
pathType =
lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305)
"lib.sources.pathType has been moved to lib.filesystem.pathType."
lib.filesystem.pathType;
pathType = lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305)
"lib.sources.pathType has been moved to lib.filesystem.pathType."
lib.filesystem.pathType;
pathIsDirectory =
lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305)
"lib.sources.pathIsDirectory has been moved to lib.filesystem.pathIsDirectory."
lib.filesystem.pathIsDirectory;
pathIsDirectory = lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305)
"lib.sources.pathIsDirectory has been moved to lib.filesystem.pathIsDirectory."
lib.filesystem.pathIsDirectory;
pathIsRegularFile =
lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305)
"lib.sources.pathIsRegularFile has been moved to lib.filesystem.pathIsRegularFile."
lib.filesystem.pathIsRegularFile;
pathIsRegularFile = lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305)
"lib.sources.pathIsRegularFile has been moved to lib.filesystem.pathIsRegularFile."
lib.filesystem.pathIsRegularFile;
inherit
pathIsGitRepo

View File

@@ -269,43 +269,6 @@ rec {
f:
list: concatStringsSep sep (lib.imap1 f list);
/**
Like [`concatMapStringsSep`](#function-library-lib.strings.concatMapStringsSep)
but takes an attribute set instead of a list.
# Inputs
`sep`
: Separator to add between item strings
`f`
: Function that takes each key and value and return a string
`attrs`
: Attribute set to map from
# Type
```
concatMapAttrsStringSep :: String -> (String -> Any -> String) -> AttrSet -> String
```
# Examples
:::{.example}
## `lib.strings.concatMapAttrsStringSep` usage example
```nix
concatMapAttrsStringSep "\n" (name: value: "${name}: foo-${value}") { a = "0.1.0"; b = "0.2.0"; }
=> "a: foo-0.1.0\nb: foo-0.2.0"
```
:::
*/
concatMapAttrsStringSep =
sep: f: attrs:
concatStringsSep sep (lib.attrValues (lib.mapAttrs f attrs));
/**
Concatenate a list of strings, adding a newline at the end of each one.
Defined as `concatMapStrings (s: s + "\n")`.

View File

@@ -11,13 +11,12 @@ rec {
x86-64-v3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" "avx2" "fma" ];
x86-64-v4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" "avx2" "avx512" "fma" ];
# x86_64 Intel
nehalem = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
westmere = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
silvermont = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
sandybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" ];
ivybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" ];
haswell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" "avx2" "fma" ];
broadwell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "avx" "avx2" "fma" ];
nehalem = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
westmere = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
sandybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
ivybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
haswell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
broadwell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
skylake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
skylake-avx512 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
cannonlake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];

View File

@@ -6,9 +6,9 @@ let
filterAttrs
foldl
hasInfix
isAttrs
isFunction
isList
isString
mapAttrs
optional
optionalAttrs
@@ -55,34 +55,24 @@ let
*/
flakeExposed = import ./flake-systems.nix { };
# Turn localSystem or crossSystem, which could be system-string or attrset, into
# attrset.
systemToAttrs = systemOrArgs:
if isAttrs systemOrArgs then systemOrArgs else { system = systemOrArgs; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary.
#
# `parsed` is inferred from args, both because there are two options with one
# clearly preferred, and to prevent cycles. A simpler fixed point where the RHS
# always just used `final.*` would fail on both counts.
elaborate = systemOrArgs: let
allArgs = systemToAttrs systemOrArgs;
# Those two will always be derived from "config", if given, so they should NOT
# be overridden further down with "// args".
args = builtins.removeAttrs allArgs [ "parsed" "system" ];
elaborate = args': let
args = if isString args' then { system = args'; }
else args';
# TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL.
rust = args.rust or args.rustc or {};
final = {
# Prefer to parse `config` as it is strictly more informative.
parsed = parse.mkSystemFromString (args.config or allArgs.system);
# This can be losslessly-extracted from `parsed` iff parsing succeeds.
parsed = parse.mkSystemFromString (if args ? config then args.config else args.system);
# Either of these can be losslessly-extracted from `parsed` iff parsing succeeds.
system = parse.doubleFromSystem final.parsed;
# TODO: This currently can't be losslessly-extracted from `parsed`, for example
# because of -mingw32.
config = parse.tripleFromSystem final.parsed;
# Determine whether we can execute binaries built for the provided platform.
canExecute = platform:
@@ -445,6 +435,5 @@ in
inspect
parse
platforms
systemToAttrs
;
}

View File

@@ -13,7 +13,7 @@ let
"x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
# FreeBSD
"i686-freebsd" "x86_64-freebsd" "aarch64-freebsd"
"i686-freebsd" "x86_64-freebsd"
# Genode
"aarch64-genode" "i686-genode" "x86_64-genode"

View File

@@ -167,11 +167,6 @@ rec {
config = "avr";
};
amdgcn = {
config = "amdgcn-amdhsa";
libc = "newlib";
};
vc4 = {
config = "vc4-elf";
libc = "newlib";
@@ -334,17 +329,11 @@ rec {
ucrtAarch64 = {
config = "aarch64-w64-mingw32";
libc = "ucrt";
rust.rustcTarget = "aarch64-pc-windows-gnullvm";
useLLVM = true;
};
# BSDs
aarch64-freebsd = {
config = "aarch64-unknown-freebsd";
useLLVM = true;
};
x86_64-freebsd = {
config = "x86_64-unknown-freebsd";
useLLVM = true;

View File

@@ -163,8 +163,6 @@ rec {
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
avr = { bits = 8; family = "avr"; };
amdgcn = { bits = 64; significantByte = littleEndian; family = "amdgcn"; };
vc4 = { bits = 32; significantByte = littleEndian; family = "vc4"; };
or1k = { bits = 32; significantByte = bigEndian; family = "or1k"; };
@@ -340,7 +338,6 @@ rec {
ghcjs = { execFormat = unknown; families = { }; };
genode = { execFormat = elf; families = { }; };
mmixware = { execFormat = unknown; families = { }; };
amdhsa = { execFormat = unknown; families = { }; };
} // { # aliases
# 'darwin' is the kernel for all of them. We choose macOS by default.
darwin = kernels.macos;
@@ -444,7 +441,7 @@ rec {
mkSkeletonFromList = l: {
"1" = if elemAt l 0 == "avr"
then { cpu = elemAt l 0; kernel = "none"; abi = "unknown"; }
else throw "system string '${lib.concatStringsSep "-" l}' with 1 component is ambiguous";
else throw "Target specification with 1 components is ambiguous";
"2" = # We only do 2-part hacks for things Nix already supports
if elemAt l 1 == "cygwin"
then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
@@ -482,10 +479,10 @@ rec {
then "windows" # autotools breaks on -gnu for window
else elemAt l 2;
}
else throw "system string '${lib.concatStringsSep "-" l}' with 3 components is ambiguous";
else throw "Target specification with 3 components is ambiguous";
"4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
}.${toString (length l)}
or (throw "system string '${lib.concatStringsSep "-" l}' has invalid number of hyphen-separated components");
or (throw "system string has invalid number of hyphen-separated components");
# This should revert the job done by config.guess from the gcc compiler.
mkSystemFromSkeleton = { cpu

View File

@@ -491,42 +491,12 @@ rec {
};
# can execute on 32bit chip
gcc_mips32r2_o32 = {
gcc = {
arch = "mips32r2";
abi = "32";
};
};
gcc_mips32r6_o32 = {
gcc = {
arch = "mips32r6";
abi = "32";
};
};
gcc_mips64r2_n32 = {
gcc = {
arch = "mips64r2";
abi = "n32";
};
};
gcc_mips64r6_n32 = {
gcc = {
arch = "mips64r6";
abi = "n32";
};
};
gcc_mips64r2_64 = {
gcc = {
arch = "mips64r2";
abi = "64";
};
};
gcc_mips64r6_64 = {
gcc = {
arch = "mips64r6";
abi = "64";
};
};
gcc_mips32r2_o32 = { gcc = { arch = "mips32r2"; abi = "32"; }; };
gcc_mips32r6_o32 = { gcc = { arch = "mips32r6"; abi = "32"; }; };
gcc_mips64r2_n32 = { gcc = { arch = "mips64r2"; abi = "n32"; }; };
gcc_mips64r6_n32 = { gcc = { arch = "mips64r6"; abi = "n32"; }; };
gcc_mips64r2_64 = { gcc = { arch = "mips64r2"; abi = "64"; }; };
gcc_mips64r6_64 = { gcc = { arch = "mips64r6"; abi = "64"; }; };
# based on:
# https://www.mail-archive.com/qemu-discuss@nongnu.org/msg05179.html
@@ -575,38 +545,27 @@ rec {
# This function takes a minimally-valid "platform" and returns an
# attrset containing zero or more additional attrs which should be
# included in the platform in order to further elaborate it.
select =
platform:
select = platform:
# x86
if platform.isx86 then
pc
/**/ if platform.isx86 then pc
# ARM
else if platform.isAarch32 then
let
version = platform.parsed.cpu.version or null;
in
if version == null then
pc
else if lib.versionOlder version "6" then
sheevaplug
else if lib.versionOlder version "7" then
raspberrypi
else
armv7l-hf-multiplatform
else if platform.isAarch32 then let
version = platform.parsed.cpu.version or null;
in if version == null then pc
else if lib.versionOlder version "6" then sheevaplug
else if lib.versionOlder version "7" then raspberrypi
else armv7l-hf-multiplatform
else if platform.isAarch64 then
if platform.isDarwin then apple-m1 else aarch64-multiplatform
if platform.isDarwin then apple-m1
else aarch64-multiplatform
else if platform.isRiscV then
riscv-multiplatform
else if platform.isRiscV then riscv-multiplatform
else if platform.parsed.cpu == lib.systems.parse.cpuTypes.mipsel then
(import ./examples.nix { inherit lib; }).mipsel-linux-gnu
else if platform.parsed.cpu == lib.systems.parse.cpuTypes.mipsel then (import ./examples.nix { inherit lib; }).mipsel-linux-gnu
else if platform.parsed.cpu == lib.systems.parse.cpuTypes.powerpc64le then
powernv
else if platform.parsed.cpu == lib.systems.parse.cpuTypes.powerpc64le then powernv
else
{ };
else { };
}

View File

@@ -1,10 +1,7 @@
# Throws an error if any of our lib tests fail.
let
tests = [
"misc"
"systems"
];
all = builtins.concatLists (map (f: import (./. + "/${f}.nix")) tests);
in
if all == [ ] then null else throw (builtins.toJSON all)
let tests = [ "misc" "systems" ];
all = builtins.concatLists (map (f: import (./. + "/${f}.nix")) tests);
in if all == []
then null
else throw (builtins.toJSON all)

View File

@@ -1,8 +1,7 @@
{ lib, ... }:
let
inherit (lib) types;
in
{
in {
options = {
name = lib.mkOption {
type = types.str;
@@ -24,12 +23,10 @@ in
default = null;
};
keys = lib.mkOption {
type = types.listOf (
types.submodule {
options.fingerprint = lib.mkOption { type = types.str; };
}
);
default = [ ];
type = types.listOf (types.submodule {
options.fingerprint = lib.mkOption { type = types.str; };
});
default = [];
};
};
}

View File

@@ -1,76 +1,53 @@
# to run these tests (and the others)
# nix-build nixpkgs/lib/tests/release.nix
# These tests should stay in sync with the comment in maintainers/maintainers-list.nix
{
# The pkgs used for dependencies for the testing itself
pkgs ? import ../.. { },
lib ? pkgs.lib,
{ # The pkgs used for dependencies for the testing itself
pkgs ? import ../.. {}
, lib ? pkgs.lib
}:
let
checkMaintainer =
handle: uncheckedAttrs:
let
prefix = [
"lib"
"maintainers"
handle
];
checkedAttrs =
(lib.modules.evalModules {
inherit prefix;
modules = [
./maintainer-module.nix
{
_file = toString ../../maintainers/maintainer-list.nix;
config = uncheckedAttrs;
}
];
}).config;
checkMaintainer = handle: uncheckedAttrs:
let
prefix = [ "lib" "maintainers" handle ];
checkedAttrs = (lib.modules.evalModules {
inherit prefix;
modules = [
./maintainer-module.nix
{
_file = toString ../../maintainers/maintainer-list.nix;
config = uncheckedAttrs;
}
];
}).config;
checks =
lib.optional (checkedAttrs.github != null && checkedAttrs.githubId == null) ''
echo ${lib.escapeShellArg (lib.showOption prefix)}': If `github` is specified, `githubId` must be too.'
# Calling this too often would hit non-authenticated API limits, but this
# shouldn't happen since such errors will get fixed rather quickly
info=$(curl -sS https://api.github.com/users/${checkedAttrs.github})
id=$(jq -r '.id' <<< "$info")
echo "The GitHub ID for GitHub user ${checkedAttrs.github} is $id:"
echo -e " githubId = $id;\n"
''
++
lib.optional
(checkedAttrs.email == null && checkedAttrs.github == null && checkedAttrs.matrix == null)
''
echo ${lib.escapeShellArg (lib.showOption prefix)}': At least one of `email`, `github` or `matrix` must be specified, so that users know how to reach you.'
''
++
lib.optional (checkedAttrs.email != null && lib.hasSuffix "noreply.github.com" checkedAttrs.email)
''
echo ${lib.escapeShellArg (lib.showOption prefix)}': If an email address is given, it should allow people to reach you. If you do not want that, you can just provide `github` or `matrix` instead.'
'';
in
lib.deepSeq checkedAttrs checks;
checks = lib.optional (checkedAttrs.github != null && checkedAttrs.githubId == null) ''
echo ${lib.escapeShellArg (lib.showOption prefix)}': If `github` is specified, `githubId` must be too.'
# Calling this too often would hit non-authenticated API limits, but this
# shouldn't happen since such errors will get fixed rather quickly
info=$(curl -sS https://api.github.com/users/${checkedAttrs.github})
id=$(jq -r '.id' <<< "$info")
echo "The GitHub ID for GitHub user ${checkedAttrs.github} is $id:"
echo -e " githubId = $id;\n"
'' ++ lib.optional (checkedAttrs.email == null && checkedAttrs.github == null && checkedAttrs.matrix == null) ''
echo ${lib.escapeShellArg (lib.showOption prefix)}': At least one of `email`, `github` or `matrix` must be specified, so that users know how to reach you.'
'' ++ lib.optional (checkedAttrs.email != null && lib.hasSuffix "noreply.github.com" checkedAttrs.email) ''
echo ${lib.escapeShellArg (lib.showOption prefix)}': If an email address is given, it should allow people to reach you. If you do not want that, you can just provide `github` or `matrix` instead.'
'';
in lib.deepSeq checkedAttrs checks;
missingGithubIds = lib.concatLists (lib.mapAttrsToList checkMaintainer lib.maintainers);
success = pkgs.runCommand "checked-maintainers-success" { } ">$out";
success = pkgs.runCommand "checked-maintainers-success" {} ">$out";
failure =
pkgs.runCommand "checked-maintainers-failure"
{
nativeBuildInputs = [
pkgs.curl
pkgs.jq
];
outputHash = "sha256:${lib.fakeSha256}";
outputHAlgo = "sha256";
outputHashMode = "flat";
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
}
''
${lib.concatStringsSep "\n" missingGithubIds}
exit 1
'';
in
if missingGithubIds == [ ] then success else failure
failure = pkgs.runCommand "checked-maintainers-failure" {
nativeBuildInputs = [ pkgs.curl pkgs.jq ];
outputHash = "sha256:${lib.fakeSha256}";
outputHAlgo = "sha256";
outputHashMode = "flat";
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
} ''
${lib.concatStringsSep "\n" missingGithubIds}
exit 1
'';
in if missingGithubIds == [] then success else failure

View File

@@ -39,7 +39,6 @@ let
composeManyExtensions
concatLines
concatMapAttrs
concatMapAttrsStringSep
concatMapStrings
concatStrings
concatStringsSep
@@ -329,11 +328,6 @@ runTests {
expected = "a,b,c";
};
testConcatMapAttrsStringSepExamples = {
expr = concatMapAttrsStringSep "\n" (name: value: "${name}: foo-${value}") { a = "0.1.0"; b = "0.2.0"; };
expected = "a: foo-0.1.0\nb: foo-0.2.0";
};
testConcatLines = {
expr = concatLines ["a" "b" "c"];
expected = "a\nb\nc\n";
@@ -1877,44 +1871,6 @@ runTests {
expected = [ [ "_module" "args" ] [ "foo" ] [ "foo" "<name>" "bar" ] [ "foo" "bar" ] ];
};
testAttrsWithName = {
expr = let
eval = evalModules {
modules = [
{
options = {
foo = lib.mkOption {
type = lib.types.attrsWith {
placeholder = "MyCustomPlaceholder";
elemType = lib.types.submodule {
options.bar = lib.mkOption {
type = lib.types.int;
default = 42;
};
};
};
};
};
}
];
};
opt = eval.options.foo;
in
(opt.type.getSubOptions opt.loc).bar.loc;
expected = [
"foo"
"<MyCustomPlaceholder>"
"bar"
];
};
testShowOptionWithPlaceholder = {
# <name>, *, should not be escaped. It is used as a placeholder by convention.
# Other symbols should be escaped. `{}`
expr = lib.showOption ["<name>" "<myName>" "*" "{foo}"];
expected = "<name>.<myName>.*.\"{foo}\"";
};
testCartesianProductOfEmptySet = {
expr = cartesianProduct {};
expected = [ {} ];

View File

@@ -190,9 +190,6 @@ checkConfigOutput '^420$' config.bare-submodule.deep ./declare-bare-submodule.ni
checkConfigOutput '^2$' config.bare-submodule.deep ./declare-bare-submodule.nix ./declare-bare-submodule-deep-option.nix ./define-shorthandOnlyDefinesConfig-true.nix
checkConfigError 'The option .bare-submodule.deep. in .*/declare-bare-submodule-deep-option.nix. is already declared in .*/declare-bare-submodule-deep-option-duplicate.nix' config.bare-submodule.deep ./declare-bare-submodule.nix ./declare-bare-submodule-deep-option.nix ./declare-bare-submodule-deep-option-duplicate.nix
# Check that strMatching can be merged
checkConfigOutput '^"strMatching.*"$' options.sm.type.name ./strMatching-merge.nix
# Check integer types.
# unsigned
checkConfigOutput '^42$' config.value ./declare-int-unsigned-value.nix ./define-value-int-positive.nix
@@ -389,14 +386,6 @@ checkConfigOutput '^true$' config.conditionalWorks ./declare-attrsOf.nix ./attrs
checkConfigOutput '^false$' config.conditionalWorks ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
checkConfigOutput '^"empty"$' config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
# Check attrsWith type merging
checkConfigError 'The option `mergedLazyNonLazy'\'' in `.*'\'' is already declared in `.*'\''\.' options.mergedLazyNonLazy ./lazy-attrsWith.nix
checkConfigOutput '^11$' config.lazyResult ./lazy-attrsWith.nix
checkConfigError 'infinite recursion encountered' config.nonLazyResult ./lazy-attrsWith.nix
# AttrsWith placeholder tests
checkConfigOutput '^"mergedName.<id>.nested"$' config.result ./name-merge-attrsWith-1.nix
checkConfigError 'The option .mergedName. in .*\.nix. is already declared in .*\.nix' config.mergedName ./name-merge-attrsWith-2.nix
# Even with multiple assignments, a type error should be thrown if any of them aren't valid
checkConfigError 'A definition for option .* is not of type .*' \
@@ -527,10 +516,6 @@ checkConfigError 'The option .theOption.nested. in .other.nix. is already declar
# Test that types.optionType leaves types untouched as long as they don't need to be merged
checkConfigOutput 'ok' config.freeformItems.foo.bar ./adhoc-freeformType-survives-type-merge.nix
# Test that specifying both functor.wrapped and functor.payload isn't allowed
checkConfigError 'Type foo defines both `functor.payload` and `functor.wrapped` at the same time, which is not supported.' config.result ./default-type-merge-both.nix
# Anonymous submodules don't get nixed by import resolution/deduplication
# because of an `extendModules` bug, issue 168767.
checkConfigOutput '^1$' config.sub.specialisation.value ./extendModules-168767-imports.nix
@@ -586,7 +571,6 @@ checkConfigOutput '^38|27$' options.submoduleLine38.declarationPositions.1.line
# nested options work
checkConfigOutput '^34$' options.nested.nestedLine34.declarationPositions.0.line ./declaration-positions.nix
cat <<EOF
====== module tests ======
$pass Pass

View File

@@ -1,9 +1,5 @@
{ lib, ... }:
{
options.dummy = lib.mkOption {
type = lib.types.anything;
default = { };
};
{ lib, ... }: {
options.dummy = lib.mkOption { type = lib.types.anything; default = {}; };
freeformType =
let
a = lib.types.attrsOf (lib.types.submodule { options.bar = lib.mkOption { }; });
@@ -11,8 +7,7 @@
# modifying types like this breaks type merging.
# This test makes sure that type merging is not performed when only a single declaration exists.
# Don't modify types in practice!
a
// {
a // {
merge = loc: defs: { freeformItems = a.merge loc defs; };
};
config.foo.bar = "ok";

View File

@@ -30,7 +30,7 @@ in
# mkAliasOptionModule sets warnings, so this has to be defined.
warnings = mkOption {
internal = true;
default = [ ];
default = [];
type = types.listOf types.str;
example = [ "The `foo' service is deprecated and will go away soon!" ];
description = ''
@@ -46,16 +46,14 @@ in
# Disable the aliased option with a high priority so it
# should override the next import.
(
{ config, lib, ... }:
( { config, lib, ... }:
{
enableAlias = mkForce false;
}
)
# Enable the normal (non-aliased) option.
(
{ config, lib, ... }:
( { config, lib, ... }:
{
enable = true;
}

Some files were not shown because too many files have changed in this diff Show More