mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-09-24 14:18:13 +03:00
Merge branch 'master' into autorandr-module
This commit is contained in:
commit
7844c87ab7
@ -67,10 +67,6 @@ indent_style = unset
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
[pkgs/build-support/upstream-updater/**]
|
||||
indent_style = unset
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
[pkgs/development/compilers/elm/registry.dat]
|
||||
end_of_line = unset
|
||||
insert_final_newline = unset
|
||||
@ -84,10 +80,3 @@ trim_trailing_whitespace = unset
|
||||
|
||||
[pkgs/tools/misc/timidity/timidity.cfg]
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
[pkgs/tools/security/enpass/data.json]
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
[pkgs/top-level/emscripten-packages.nix]
|
||||
trim_trailing_whitespace = unset
|
||||
|
32
.git-blame-ignore-revs
Normal file
32
.git-blame-ignore-revs
Normal file
@ -0,0 +1,32 @@
|
||||
# This file contains a list of commits that are not likely what you
|
||||
# are looking for in a blame, such as mass reformatting or renaming.
|
||||
# You can set this file as a default ignore file for blame by running
|
||||
# the following command.
|
||||
#
|
||||
# $ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
#
|
||||
# To temporarily not use this file add
|
||||
# --ignore-revs-file=""
|
||||
# to your blame command.
|
||||
#
|
||||
# The ignoreRevsFile can't be set globally due to blame failing if the file isn't present.
|
||||
# To not have to set the option in every repository it is needed in,
|
||||
# save the following script in your path with the name "git-bblame"
|
||||
# now you can run
|
||||
# $ git bblame $FILE
|
||||
# to use the .git-blame-ignore-revs file if it is present.
|
||||
#
|
||||
# #!/usr/bin/env bash
|
||||
# repo_root=$(git rev-parse --show-toplevel)
|
||||
# if [[ -e $repo_root/.git-blame-ignore-revs ]]; then
|
||||
# git blame --ignore-revs-file="$repo_root/.git-blame-ignore-revs" $@
|
||||
# else
|
||||
# git blame $@
|
||||
# fi
|
||||
|
||||
|
||||
# nixos/modules/rename: Sort alphabetically
|
||||
1f71224fe86605ef4cd23ed327b3da7882dad382
|
||||
|
||||
# nixos: fix module paths in rename.nix
|
||||
d08ede042b74b8199dc748323768227b88efcf7c
|
23
.github/CODEOWNERS
vendored
23
.github/CODEOWNERS
vendored
@ -77,6 +77,12 @@
|
||||
# NixOS integration test driver
|
||||
/nixos/lib/test-driver @tfc
|
||||
|
||||
# Systemd
|
||||
/nixos/modules/system/boot/systemd.nix @NixOS/systemd
|
||||
/nixos/modules/system/boot/systemd @NixOS/systemd
|
||||
/nixos/lib/systemd-*.nix @NixOS/systemd
|
||||
/pkgs/os-specific/linux/systemd @NixOS/systemd
|
||||
|
||||
# Updaters
|
||||
## update.nix
|
||||
/maintainers/scripts/update.nix @jtojnar
|
||||
@ -104,9 +110,9 @@
|
||||
/pkgs/top-level/haskell-packages.nix @cdepillabout @sternenseemann @maralorn @expipiplus1
|
||||
|
||||
# Perl
|
||||
/pkgs/development/interpreters/perl @volth @stigtsp @zakame
|
||||
/pkgs/top-level/perl-packages.nix @volth @stigtsp @zakame
|
||||
/pkgs/development/perl-modules @volth @stigtsp @zakame
|
||||
/pkgs/development/interpreters/perl @stigtsp @zakame
|
||||
/pkgs/top-level/perl-packages.nix @stigtsp @zakame
|
||||
/pkgs/development/perl-modules @stigtsp @zakame
|
||||
|
||||
# R
|
||||
/pkgs/applications/science/math/R @jbedo @bcdarwin
|
||||
@ -119,6 +125,7 @@
|
||||
# Rust
|
||||
/pkgs/development/compilers/rust @Mic92 @LnL7 @zowoq
|
||||
/pkgs/build-support/rust @zowoq
|
||||
/doc/languages-frameworks/rust.section.md @zowoq
|
||||
|
||||
# Darwin-related
|
||||
/pkgs/stdenv/darwin @NixOS/darwin-maintainers
|
||||
@ -217,18 +224,18 @@
|
||||
/nixos/modules/services/mail/rspamd.nix @peti
|
||||
|
||||
# Emacs
|
||||
/pkgs/applications/editors/emacs-modes @adisbladis
|
||||
/pkgs/applications/editors/emacs @adisbladis
|
||||
/pkgs/top-level/emacs-packages.nix @adisbladis
|
||||
/pkgs/applications/editors/emacs/elisp-packages @adisbladis
|
||||
/pkgs/applications/editors/emacs @adisbladis
|
||||
/pkgs/top-level/emacs-packages.nix @adisbladis
|
||||
|
||||
# Neovim
|
||||
/pkgs/applications/editors/neovim @jonringer @teto
|
||||
|
||||
# VimPlugins
|
||||
/pkgs/misc/vim-plugins @jonringer @softinio
|
||||
/pkgs/applications/editors/vim/plugins @jonringer
|
||||
|
||||
# VsCode Extensions
|
||||
/pkgs/misc/vscode-extensions @jonringer
|
||||
/pkgs/applications/editors/vscode/extensions @jonringer
|
||||
|
||||
# Prometheus exporter modules and tests
|
||||
/nixos/modules/services/monitoring/prometheus/exporters.nix @WilliButz
|
||||
|
@ -13,10 +13,10 @@ assignees: ''
|
||||
<!-- Note that these are hard requirements -->
|
||||
|
||||
<!--
|
||||
You can use the "Go to file" functionality on github to find the package
|
||||
You can use the "Go to file" functionality on GitHub to find the package
|
||||
Then you can go to the history for this package
|
||||
Find the latest "package_name: old_version -> new_version" commit
|
||||
The "new_version" is the the current version of the package
|
||||
The "new_version" is the current version of the package
|
||||
-->
|
||||
- [ ] Checked the [nixpkgs master branch](https://github.com/NixOS/nixpkgs)
|
||||
<!--
|
||||
@ -29,7 +29,7 @@ There's a high chance that you'll have the new version right away while helping
|
||||
###### Project name
|
||||
`nix search` name:
|
||||
<!--
|
||||
The current version can be found easily with the same process than above for checking the master branch
|
||||
The current version can be found easily with the same process as above for checking the master branch
|
||||
If an open PR is present for the package, take this version as the current one and link to the PR
|
||||
-->
|
||||
current version:
|
||||
|
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,16 +1,10 @@
|
||||
###### Description of changes
|
||||
|
||||
<!--
|
||||
To help with the large amounts of pull requests, we would appreciate your
|
||||
reviews of other pull requests, especially simple package updates. Just leave a
|
||||
comment describing what you have tested in the relevant package/service.
|
||||
Reviewing helps to reduce the average time-to-merge for everyone.
|
||||
Thanks a lot if you do!
|
||||
List of open PRs: https://github.com/NixOS/nixpkgs/pulls
|
||||
Reviewing guidelines: https://nixos.org/manual/nixpkgs/unstable/#chap-reviewing-contributions
|
||||
For package updates please link to a changelog or describe changes, this helps your fellow maintainers discover breaking updates.
|
||||
For new packages please briefly describe the package or provide a link to its homepage.
|
||||
-->
|
||||
|
||||
###### Motivation for this change
|
||||
|
||||
|
||||
###### Things done
|
||||
|
||||
<!-- Please check what applies. Note that these are not hard requirements but merely serve as information for reviewers. -->
|
||||
@ -34,3 +28,14 @@ Reviewing guidelines: https://nixos.org/manual/nixpkgs/unstable/#chap-reviewing-
|
||||
- [ ] (Module addition) Added a release notes entry if adding a new NixOS module
|
||||
- [ ] (Release notes changes) Ran `nixos/doc/manual/md-to-db.sh` to update generated release notes
|
||||
- [ ] Fits [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md).
|
||||
|
||||
<!--
|
||||
To help with the large amounts of pull requests, we would appreciate your
|
||||
reviews of other pull requests, especially simple package updates. Just leave a
|
||||
comment describing what you have tested in the relevant package/service.
|
||||
Reviewing helps to reduce the average time-to-merge for everyone.
|
||||
Thanks a lot if you do!
|
||||
|
||||
List of open PRs: https://github.com/NixOS/nixpkgs/pulls
|
||||
Reviewing guidelines: https://nixos.org/manual/nixpkgs/unstable/#chap-reviewing-contributions
|
||||
-->
|
||||
|
8
.github/labeler.yml
vendored
8
.github/labeler.yml
vendored
@ -5,10 +5,6 @@
|
||||
- pkgs/development/libraries/agda/**/*
|
||||
- pkgs/top-level/agda-packages.nix
|
||||
|
||||
"6.topic: bsd":
|
||||
- pkgs/os-specific/bsd/**/*
|
||||
- pkgs/stdenv/freebsd/**/*
|
||||
|
||||
"6.topic: cinnamon":
|
||||
- pkgs/desktops/cinnamon/**/*
|
||||
|
||||
@ -16,7 +12,7 @@
|
||||
- nixos/modules/services/editors/emacs.nix
|
||||
- nixos/modules/services/editors/emacs.xml
|
||||
- nixos/tests/emacs-daemon.nix
|
||||
- pkgs/applications/editors/emacs-modes/**/*
|
||||
- pkgs/applications/editors/emacs/elisp-packages/**/*
|
||||
- pkgs/applications/editors/emacs/**/*
|
||||
- pkgs/build-support/emacs/**/*
|
||||
- pkgs/top-level/emacs-packages.nix
|
||||
@ -142,7 +138,7 @@
|
||||
"6.topic: vim":
|
||||
- doc/languages-frameworks/vim.section.md
|
||||
- pkgs/applications/editors/vim/**/*
|
||||
- pkgs/misc/vim-plugins/**/*
|
||||
- pkgs/applications/editors/vim/plugins/**/*
|
||||
- nixos/modules/programs/neovim.nix
|
||||
- pkgs/applications/editors/neovim/**/*
|
||||
|
||||
|
8
.github/workflows/backport.yml
vendored
8
.github/workflows/backport.yml
vendored
@ -2,13 +2,19 @@ name: Backport
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed, labeled]
|
||||
|
||||
# WARNING:
|
||||
# When extending this action, be aware that $GITHUB_TOKEN allows write access to
|
||||
# the GitHub repository. This means that it should not evaluate user input in a
|
||||
# way that allows code injection.
|
||||
|
||||
jobs:
|
||||
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:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# required to find all branches
|
||||
fetch-depth: 0
|
||||
|
7
.github/workflows/basic-eval.yml
vendored
7
.github/workflows/basic-eval.yml
vendored
@ -14,7 +14,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
# we don't limit this action to only NixOS repo since the checks are cheap and useful developer feedback
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: cachix/install-nix-action@v16
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
# explicit list of supportedSystems is needed until aarch64-darwin becomes part of the trunk jobset
|
||||
- run: nix-build pkgs/top-level/release.nix -A tarball.nixpkgs-basic-release-checks --arg supportedSystems '[ "aarch64-darwin" "aarch64-linux" "x86_64-linux" "x86_64-darwin" ]'
|
||||
|
2
.github/workflows/direct-push.yml
vendored
2
.github/workflows/direct-push.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
if: steps.ismerge.outputs.ismerge != 'true'
|
||||
- name: Warn if the commit was a direct push
|
||||
if: steps.ismerge.outputs.ismerge != 'true'
|
||||
uses: peter-evans/commit-comment@v1
|
||||
uses: peter-evans/commit-comment@v2
|
||||
with:
|
||||
body: |
|
||||
@${{ github.actor }}, you pushed a commit directly to master/release branch
|
||||
|
2
.github/workflows/editorconfig.yml
vendored
2
.github/workflows/editorconfig.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
- name: print list of changed files
|
||||
run: |
|
||||
cat "$HOME/changed_files"
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
7
.github/workflows/labels.yml
vendored
7
.github/workflows/labels.yml
vendored
@ -4,6 +4,11 @@ on:
|
||||
pull_request_target:
|
||||
types: [edited, opened, synchronize, reopened]
|
||||
|
||||
# WARNING:
|
||||
# When extending this action, be aware that $GITHUB_TOKEN allows some write
|
||||
# access to the GitHub API. This means that it should not evaluate user input in
|
||||
# a way that allows code injection.
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
@ -13,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/labeler@v3
|
||||
- uses: actions/labeler@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
sync-labels: true
|
||||
|
4
.github/workflows/manual-nixos.yml
vendored
4
.github/workflows/manual-nixos.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
@ -24,7 +24,7 @@ jobs:
|
||||
extra_nix_config: sandbox = true
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
# This cache is for the nixos/nixpkgs manual builds and should not be trusted or used elsewhere.
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
- name: Building NixOS manual
|
||||
|
4
.github/workflows/manual-nixpkgs.yml
vendored
4
.github/workflows/manual-nixpkgs.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
@ -24,7 +24,7 @@ jobs:
|
||||
extra_nix_config: sandbox = true
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
# This cache is for the nixos/nixpkgs manual builds and should not be trusted or used elsewhere.
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
- name: Building Nixpkgs manual
|
||||
|
2
.github/workflows/nixos-manual.yml
vendored
2
.github/workflows/nixos-manual.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
5
.github/workflows/pending-set.yml
vendored
5
.github/workflows/pending-set.yml
vendored
@ -3,6 +3,11 @@ name: "set pending status"
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
# WARNING:
|
||||
# When extending this action, be aware that $GITHUB_TOKEN allows write access to
|
||||
# the GitHub repository. This means that it should not evaluate user input in a
|
||||
# way that allows code injection.
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
|
2
.github/workflows/periodic-merge-24h.yml
vendored
2
.github/workflows/periodic-merge-24h.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
||||
into: staging-21.11
|
||||
name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
|
||||
uses: devmasx/merge-branch@1.4.0
|
||||
|
2
.github/workflows/periodic-merge-6h.yml
vendored
2
.github/workflows/periodic-merge-6h.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
||||
into: staging
|
||||
name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
|
||||
uses: devmasx/merge-branch@1.4.0
|
||||
|
@ -10,7 +10,7 @@ jobs:
|
||||
if: github.repository_owner == 'NixOS' && github.ref == 'refs/heads/master' # ensure workflow_dispatch only runs on master
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: cachix/install-nix-action@v16
|
||||
- name: setup
|
||||
id: setup
|
||||
@ -21,7 +21,7 @@ jobs:
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config user.name "github-actions[bot]"
|
||||
pushd pkgs/applications/networking/cluster/terraform-providers
|
||||
./update-all-providers
|
||||
./update-all-providers --no-build
|
||||
git commit -m "${{ steps.setup.outputs.title }}" providers.json
|
||||
popd
|
||||
- name: create PR
|
||||
|
11
README.md
11
README.md
@ -1,10 +1,15 @@
|
||||
<p align="center">
|
||||
<a href="https://nixos.org/nixos"><img src="https://nixos.org/logo/nixos-hires.png" width="500px" alt="NixOS logo" /></a>
|
||||
<a href="https://nixos.org#gh-light-mode-only">
|
||||
<img src="https://raw.githubusercontent.com/NixOS/nixos-homepage/master/logo/nixos-hires.png" width="500px" alt="NixOS logo"/>
|
||||
</a>
|
||||
<a href="https://nixos.org#gh-dark-mode-only">
|
||||
<img src="https://raw.githubusercontent.com/NixOS/nixos-artwork/master/logo/nixos-white.png" width="500px" alt="NixOS logo"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.codetriage.com/nixos/nixpkgs"><img src="https://www.codetriage.com/nixos/nixpkgs/badges/users.svg" alt="Code Triagers badge" /></a>
|
||||
<a href="https://opencollective.com/nixos"><img src="https://opencollective.com/nixos/tiers/supporter/badge.svg?label=Supporter&color=brightgreen" alt="Open Collective supporters" /></a>
|
||||
<a href="https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md"><img src="https://img.shields.io/github/contributors-anon/NixOS/nixpkgs" alt="Contributors badge" /></a>
|
||||
<a href="https://opencollective.com/nixos"><img src="https://opencollective.com/nixos/tiers/supporter/badge.svg?label=supporters&color=brightgreen" alt="Open Collective supporters" /></a>
|
||||
</p>
|
||||
|
||||
[Nixpkgs](https://github.com/nixos/nixpkgs) is a collection of over
|
||||
|
@ -40,6 +40,24 @@ Used with Git. Expects `url` to a Git repo, `rev`, and `sha256`. `rev` in this c
|
||||
|
||||
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.
|
||||
|
||||
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) and [git clone --filter](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---filterltfilter-specgt) for more infomation:
|
||||
|
||||
```nix
|
||||
{ stdenv, fetchgit }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "hello";
|
||||
src = fetchgit {
|
||||
url = "https://...";
|
||||
sparseCheckout = ''
|
||||
path/to/be/included
|
||||
another/path
|
||||
'';
|
||||
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `fetchfossil` {#fetchfossil}
|
||||
|
||||
Used with Fossil. Expects `url` to a Fossil archive, `rev`, and `sha256`.
|
||||
@ -54,6 +72,10 @@ Used with Mercurial. Expects `url`, `rev`, and `sha256`.
|
||||
|
||||
A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are mainly convenience functions intended for commonly used destinations of source code in Nixpkgs. These wrapper fetchers are listed below.
|
||||
|
||||
## `fetchFromGitea` {#fetchfromgitea}
|
||||
|
||||
`fetchFromGitea` expects five arguments. `domain` is the gitea server name. `owner` is a string corresponding to the Gitea user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every Gitea 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, `sha256` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available but `sha256` is currently preferred.
|
||||
|
||||
## `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. Finally, `sha256` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available but `sha256` is currently preferred.
|
||||
|
@ -56,7 +56,7 @@ Use `programs.steam.enable = true;` if you want to add steam to systemPackages a
|
||||
|
||||
## steam-run {#sec-steam-run}
|
||||
|
||||
The FHS-compatible chroot used for Steam can also be used to run other Linux games that expect a FHS environment. To use it, install the `steam-run-native` package and run the game with
|
||||
The FHS-compatible chroot used for Steam can also be used to run other Linux games that expect a FHS environment. To use it, install the `steam-run` package and run the game with
|
||||
|
||||
```
|
||||
steam-run ./foo
|
||||
|
@ -45,3 +45,5 @@ One can create a simple environment using a `shell.nix` like that:
|
||||
```
|
||||
|
||||
Running `nix-shell` would then drop you into a shell with these libraries and binaries available. You can use this to run closed-source applications which expect FHS structure without hassles: simply change `runScript` to the application path, e.g. `./bin/start.sh` -- relative paths are supported.
|
||||
|
||||
Additionally, the FHS builder links all relocated gsettings-schemas (the glib setup-hook moves them to `share/gsettings-schemas/${name}/glib-2.0/schemas`) to their standard FHS location. This means you don't need to wrap binaries with `wrapGAppsHook`.
|
||||
|
@ -224,7 +224,7 @@ There are a few naming guidelines:
|
||||
|
||||
- Dashes in the package name _should_ be preserved in new variable names, rather than converted to underscores or camel cased — e.g., `http-parser` instead of `http_parser` or `httpParser`. The hyphenated style is preferred in all three package names.
|
||||
|
||||
- If there are multiple versions of a package, this _should_ be reflected in the variable names in `all-packages.nix`, e.g. `json-c-0-9` and `json-c-0-11`. If there is an obvious “default” version, make an attribute like `json-c = json-c-0-9;`. See also [](#sec-versioning)
|
||||
- If there are multiple versions of a package, this _should_ be reflected in the variable names in `all-packages.nix`, e.g. `json-c_0_9` and `json-c_0_11`. If there is an obvious “default” version, make an attribute like `json-c = json-c_0_9;`. See also [](#sec-versioning)
|
||||
|
||||
## File naming and organisation {#sec-organisation}
|
||||
|
||||
@ -540,10 +540,11 @@ If you do need to do create this sort of patch file, one way to do so is with gi
|
||||
|
||||
If a patch is available online but does not cleanly apply, it can be modified in some fixed ways by using additional optional arguments for `fetchpatch`:
|
||||
|
||||
- `relative`: Similar to using `git-diff`'s `--relative` flag, only keep changes inside the specified directory, making paths relative to it.
|
||||
- `stripLen`: Remove the first `stripLen` components of pathnames in the patch.
|
||||
- `extraPrefix`: Prefix pathnames by this string.
|
||||
- `excludes`: Exclude files matching this pattern.
|
||||
- `includes`: Include only files matching this pattern.
|
||||
- `excludes`: Exclude files matching these patterns (applies after the above arguments).
|
||||
- `includes`: Include only files matching these patterns (applies after the above arguments).
|
||||
- `revert`: Revert the patch.
|
||||
|
||||
Note that because the checksum is computed after applying these effects, using or modifying these arguments will have no effect unless the `sha256` argument is changed as well.
|
||||
|
@ -103,7 +103,8 @@ Sample template for a new package review is provided below.
|
||||
- [ ] `meta.maintainers` is set
|
||||
- [ ] build time only dependencies are declared in `nativeBuildInputs`
|
||||
- [ ] source is fetched using the appropriate function
|
||||
- [ ] phases are respected
|
||||
- [ ] the list of `phases` is not overridden
|
||||
- [ ] when a phase (like `installPhase`) is overridden it starts with `runHook preInstall` and ends with `runHook postInstall`.
|
||||
- [ ] patches that are remotely available are fetched with `fetchpatch`
|
||||
|
||||
##### Possible improvements
|
||||
@ -121,10 +122,10 @@ Reviewing process:
|
||||
- [CODEOWNERS](https://help.github.com/articles/about-codeowners/) will make GitHub notify users based on the submitted changes, but it can happen that it misses some of the package maintainers.
|
||||
- Ensure that the module tests, if any, are succeeding.
|
||||
- Ensure that the introduced options are correct.
|
||||
- Type should be appropriate (string related types differs in their merging capabilities, `optionSet` and `string` types are deprecated).
|
||||
- Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
|
||||
- Description, default and example should be provided.
|
||||
- Ensure that option changes are backward compatible.
|
||||
- `mkRenamedOptionModule` and `mkAliasOptionModule` functions provide way to make option changes backward compatible.
|
||||
- `mkRenamedOptionModuleWith` provides a way to make option changes backward compatible.
|
||||
- Ensure that removed options are declared with `mkRemovedOptionModule`
|
||||
- Ensure that changes that are not backward compatible are mentioned in release notes.
|
||||
- Ensure that documentations affected by the change is updated.
|
||||
@ -156,7 +157,7 @@ Reviewing process:
|
||||
|
||||
- Ensure that the module tests, if any, are succeeding.
|
||||
- Ensure that the introduced options are correct.
|
||||
- Type should be appropriate (string related types differs in their merging capabilities, `optionSet` and `string` types are deprecated).
|
||||
- Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
|
||||
- Description, default and example should be provided.
|
||||
- Ensure that module `meta` field is present
|
||||
- Maintainers should be declared in `meta.maintainers`.
|
||||
|
@ -98,7 +98,7 @@ We use jbidwatcher as an example for a discontinued project here.
|
||||
1. Create a new branch for your change, e.g. `git checkout -b jbidwatcher`
|
||||
1. Remove the actual package including its directory, e.g. `rm -rf pkgs/applications/misc/jbidwatcher`
|
||||
1. Remove the package from the list of all packages (`pkgs/top-level/all-packages.nix`).
|
||||
1. Add an alias for the package name in `pkgs/top-level/aliases.nix` (There is also `pkgs/misc/vim-plugins/aliases.nix`. Package sets typically do not have aliases, so we can't add them there.)
|
||||
1. Add an alias for the package name in `pkgs/top-level/aliases.nix` (There is also `pkgs/applications/editors/vim/plugins/aliases.nix`. Package sets typically do not have aliases, so we can't add them there.)
|
||||
|
||||
For example in this case:
|
||||
|
||||
|
@ -1474,7 +1474,7 @@ lib.attrsets.zipAttrsWith
|
||||
<section xml:id="function-library-lib.attrsets.zipAttrs">
|
||||
<title><function>lib.attrsets.zipAttrs</function></title>
|
||||
|
||||
<subtitle><literal>zipAttrsWith :: [ AttrSet ] -> AttrSet</literal>
|
||||
<subtitle><literal>zipAttrs :: [ AttrSet ] -> AttrSet</literal>
|
||||
</subtitle>
|
||||
|
||||
<xi:include href="./locations.xml" xpointer="lib.attrsets.zipAttrs" />
|
||||
|
@ -29,7 +29,8 @@ The recommended way of defining a derivation for a Coq library, is to use the `c
|
||||
* `releaseRev` (optional, defaults to `(v: v)`), provides a default mapping from release names to revision hashes/branch names/tags,
|
||||
* `displayVersion` (optional), provides a way to alter the computation of `name` from `pname`, by explaining how to display version numbers,
|
||||
* `namePrefix` (optional, defaults to `[ "coq" ]`), provides a way to alter the computation of `name` from `pname`, by explaining which dependencies must occur in `name`,
|
||||
* `extraBuildInputs` (optional), by default `buildInputs` just contains `coq`, this allows to add more build inputs,
|
||||
* `extraNativeBuildInputs` (optional), by default `nativeBuildInputs` just contains `coq`, this allows to add more native build inputs, `nativeBuildInputs` are executables and `buildInputs` are libraries and dependencies,
|
||||
* `extraBuildInputs` (optional), this allows to add more build inputs,
|
||||
* `mlPlugin` (optional, defaults to `false`). Some extensions (plugins) might require OCaml and sometimes other OCaml packages. Standard dependencies can be added by setting the current option to `true`. For a finer grain control, the `coq.ocamlPackages` attribute can be used in `extraBuildInputs` to depend on the same package set Coq was built against.
|
||||
* `useDune2ifVersion` (optional, default to `(x: false)` uses Dune2 to build the package if the provided predicate evaluates to true on the version, e.g. `useDune2if = versions.isGe "1.1"` will use dune if the version of the package is greater or equal to `"1.1"`,
|
||||
* `useDune2` (optional, defaults to `false`) uses Dune2 to build the package if set to true, the presence of this attribute overrides the behavior of the previous one.
|
||||
|
@ -85,7 +85,7 @@ you will still need to commit the modified version of the lock files, but at lea
|
||||
|
||||
each tool has an abstraction to just build the node_modules (dependencies) directory. you can always use the stdenv.mkDerivation with the node_modules to build the package (symlink the node_modules directory and then use the package build command). the node_modules abstraction can be also used to build some web framework frontends. For an example of this see how [plausible](https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/web-apps/plausible/default.nix) is built. mkYarnModules to make the derivation containing node_modules. Then when building the frontend you can just symlink the node_modules directory
|
||||
|
||||
## javascript packages inside nixpkgs {#javascript-packages-nixpkgs}
|
||||
## Javascript packages inside nixpkgs {#javascript-packages-nixpkgs}
|
||||
|
||||
The `pkgs/development/node-packages` folder contains a generated collection of
|
||||
[NPM packages](https://npmjs.com/) that can be installed with the Nix package
|
||||
@ -121,12 +121,14 @@ requires `node-gyp-build`, so [we override](https://github.com/NixOS/nixpkgs/blo
|
||||
};
|
||||
```
|
||||
|
||||
### Adding and Updating Javascript packages in nixpkgs
|
||||
|
||||
To add a package from NPM to nixpkgs:
|
||||
|
||||
1. Modify `pkgs/development/node-packages/node-packages.json` to add, update
|
||||
or remove package entries to have it included in `nodePackages` and
|
||||
`nodePackages_latest`.
|
||||
2. Run the script: `cd pkgs/development/node-packages && ./generate.sh`.
|
||||
2. Run the script: `./pkgs/development/node-packages/generate.sh`.
|
||||
3. Build your new package to test your changes:
|
||||
`cd /path/to/nixpkgs && nix-build -A nodePackages.<new-or-updated-package>`.
|
||||
To build against the latest stable Current Node.js version (e.g. 14.x):
|
||||
@ -137,6 +139,26 @@ For more information about the generation process, consult the
|
||||
[README.md](https://github.com/svanderburg/node2nix) file of the `node2nix`
|
||||
tool.
|
||||
|
||||
To update NPM packages in nixpkgs, run the same `generate.sh` script:
|
||||
|
||||
```sh
|
||||
./pkgs/development/node-packages/generate.sh
|
||||
```
|
||||
|
||||
#### Git protocol error
|
||||
|
||||
Some packages may have Git dependencies from GitHub specified with `git://`.
|
||||
GitHub has
|
||||
[disabled unecrypted Git connections](https://github.blog/2021-09-01-improving-git-protocol-security-github/#no-more-unauthenticated-git),
|
||||
so you may see the following error when running the generate script:
|
||||
`The unauthenticated git protocol on port 9418 is no longer supported`.
|
||||
|
||||
Use the following Git configuration to resolve the issue:
|
||||
|
||||
```sh
|
||||
git config --global url."https://github.com/".insteadOf git://github.com/
|
||||
```
|
||||
|
||||
## Tool specific instructions {#javascript-tool-specific}
|
||||
|
||||
### node2nix {#javascript-node2nix}
|
||||
|
@ -32,14 +32,14 @@ Given that most of the OCaml ecosystem is now built with dune, nixpkgs includes
|
||||
|
||||
Here is a simple package example.
|
||||
|
||||
- It defines an (optional) attribute `minimalOCamlVersion` that will be used to
|
||||
throw a descriptive evaluation error if building with an older OCaml is
|
||||
attempted.
|
||||
- It defines an (optional) attribute `minimalOCamlVersion` (see note below)
|
||||
that will be used to throw a descriptive evaluation error if building with
|
||||
an older OCaml is attempted.
|
||||
|
||||
- It uses the `fetchFromGitHub` fetcher to get its source.
|
||||
|
||||
- `useDune2 = true` ensures that the latest version of Dune is used for the
|
||||
build (this may become the default value in a future release).
|
||||
- `useDune2 = true` ensures that Dune version 2 is used for the
|
||||
build (this is the default; set to `false` to use Dune version 1).
|
||||
|
||||
- It sets the optional `doCheck` attribute such that tests will be run with
|
||||
`dune runtest -p angstrom` after the build (`dune build -p angstrom`) is
|
||||
@ -117,3 +117,11 @@ buildDunePackage rec {
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Note about `minimalOCamlVersion`. A deprecated version of this argument was
|
||||
spelled `minimumOCamlVersion`; setting the old attribute wrongly modifies the
|
||||
derivation hash and is therefore inappropriate. As a technical dept, currently
|
||||
packaged libraries may still use the old spelling: maintainers are invited to
|
||||
fix this when updating packages. Massive renaming is strongly discouraged as it
|
||||
would be challenging to review, difficult to test, and will cause unnecessary
|
||||
rebuild.
|
||||
|
@ -979,6 +979,31 @@ with import <nixpkgs> {};
|
||||
in python.withPackages(ps: [ps.blaze])).env
|
||||
```
|
||||
|
||||
#### Optional extra dependencies
|
||||
|
||||
Some packages define optional dependencies for additional features. With
|
||||
`setuptools` this is called `extras_require` and `flit` calls it `extras-require`. A
|
||||
method for supporting this is by declaring the extras of a package in its
|
||||
`passthru`, e.g. in case of the package `dask`
|
||||
|
||||
```nix
|
||||
passthru.extras-require = {
|
||||
complete = [ distributed ];
|
||||
};
|
||||
```
|
||||
|
||||
and letting the package requiring the extra add the list to its dependencies
|
||||
|
||||
```nix
|
||||
propagatedBuildInputs = [
|
||||
...
|
||||
] ++ dask.extras-require.complete;
|
||||
```
|
||||
|
||||
Note this method is preferred over adding parameters to builders, as that can
|
||||
result in packages depending on different variants and thereby causing
|
||||
collisions.
|
||||
|
||||
#### `buildPythonApplication` function {#buildpythonapplication-function}
|
||||
|
||||
The `buildPythonApplication` function is practically the same as
|
||||
|
@ -464,6 +464,8 @@ you of the correct hash.
|
||||
be disabled by setting `dontUseCargoParallelTests`.
|
||||
* `cargoInstallHook`: install binaries and static/shared libraries
|
||||
that were built using `cargoBuildHook`.
|
||||
* `bindgenHook`: for crates which use `bindgen` as a build dependency, lets
|
||||
`bindgen` find `libclang` and `libclang` find the libraries in `buildInputs`.
|
||||
|
||||
### Examples {#examples}
|
||||
|
||||
|
@ -6,7 +6,7 @@ Since release 15.09 there is a new TeX Live packaging that lives entirely under
|
||||
|
||||
- For basic usage just pull `texlive.combined.scheme-basic` for an environment with basic LaTeX support.
|
||||
|
||||
- It typically won't work to use separately installed packages together. Instead, you can build a custom set of packages like this:
|
||||
- It typically won't work to use separately installed packages together. Instead, you can build a custom set of packages like this. Most CTAN packages should be available:
|
||||
|
||||
```nix
|
||||
texlive.combine {
|
||||
|
@ -309,9 +309,9 @@ Sample output2:
|
||||
|
||||
## Adding new plugins to nixpkgs {#adding-new-plugins-to-nixpkgs}
|
||||
|
||||
Nix expressions for Vim plugins are stored in [pkgs/misc/vim-plugins](https://github.com/NixOS/nixpkgs/tree/master/pkgs/misc/vim-plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`./update.py`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/update.py). This creates a [generated.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/vim-plugin-names). Plugins are listed in alphabetical order in `vim-plugin-names` using the format `[github username]/[repository]@[gitref]`. For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
|
||||
Nix expressions for Vim plugins are stored in [pkgs/applications/editors/vim/plugins](https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/editors/vim/plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`./update.py`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/update.py). This creates a [generated.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/vim-plugin-names). Plugins are listed in alphabetical order in `vim-plugin-names` using the format `[github username]/[repository]@[gitref]`. For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
|
||||
|
||||
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:
|
||||
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:
|
||||
|
||||
```nix
|
||||
deoplete-fish = super.deoplete-fish.overrideAttrs(old: {
|
||||
@ -330,13 +330,13 @@ Finally, there are some plugins that are also packaged in nodePackages because t
|
||||
Run the update script with a GitHub API token that has at least `public_repo` access. Running the script without the token is likely to result in rate-limiting (429 errors). For steps on creating an API token, please refer to [GitHub's token documentation](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token).
|
||||
|
||||
```sh
|
||||
GITHUB_API_TOKEN=my_token ./pkgs/misc/vim-plugins/update.py
|
||||
GITHUB_API_TOKEN=my_token ./pkgs/applications/editors/vim/plugins/update.py
|
||||
```
|
||||
|
||||
Alternatively, set the number of processes to a lower count to avoid rate-limiting.
|
||||
|
||||
```sh
|
||||
./pkgs/misc/vim-plugins/update.py --proc 1
|
||||
./pkgs/applications/editors/vim/plugins/update.py --proc 1
|
||||
```
|
||||
|
||||
## Important repositories {#important-repositories}
|
||||
|
@ -192,10 +192,6 @@ meta.hydraPlatforms = [];
|
||||
|
||||
If set to `true`, the package is marked as "broken", meaning that it won’t show up in `nix-env -qa`, and cannot be built or installed. Such packages should be removed from Nixpkgs eventually unless they are fixed.
|
||||
|
||||
### `updateWalker` {#var-meta-updateWalker}
|
||||
|
||||
If set to `true`, the package is tested to be updated correctly by the `update-walker.sh` script without additional settings. Such packages have `meta.version` set and their homepage (or the page specified by `meta.downloadPage`) contains a direct link to the package tarball.
|
||||
|
||||
## Licenses {#sec-meta-license}
|
||||
|
||||
The `meta.license` attribute should preferably contain a value from `lib.licenses` defined in [`nixpkgs/lib/licenses.nix`](https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix), or in-place license description of the same format if the license is unlikely to be useful in another expression.
|
||||
|
@ -319,10 +319,16 @@ For information about how to run the updates, execute `nix-shell maintainers/scr
|
||||
|
||||
## Phases {#sec-stdenv-phases}
|
||||
|
||||
The generic builder has a number of *phases*. Package builds are split into phases to make it easier to override specific parts of the build (e.g., unpacking the sources or installing the binaries). Furthermore, it allows a nicer presentation of build logs in the Nix build farm.
|
||||
`stdenv.mkDerivation` sets the Nix [derivation](https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations)'s builder to a script that loads the stdenv `setup.sh` bash library and calls `genericBuild`. Most packaging functions rely on this default builder.
|
||||
|
||||
This generic command invokes a number of *phases*. Package builds are split into phases to make it easier to override specific parts of the build (e.g., unpacking the sources or installing the binaries).
|
||||
|
||||
Each phase can be overridden in its entirety either by setting the environment variable `namePhase` to a string containing some shell commands to be executed, or by redefining the shell function `namePhase`. The former is convenient to override a phase from the derivation, while the latter is convenient from a build script. However, typically one only wants to *add* some commands to a phase, e.g. by defining `postInstall` or `preFixup`, as skipping some of the default actions may have unexpected consequences. The default script for each phase is defined in the file `pkgs/stdenv/generic/setup.sh`.
|
||||
|
||||
When overriding a phase, for example `installPhase`, it is important to start with `runHook preInstall` and end it with `runHook postInstall`, otherwise `preInstall` and `postInstall` will not be run. Even if you don't use them directly, it is good practice to do so anyways for downstream users who would want to add a `postInstall` by overriding your derivation.
|
||||
|
||||
While inside an interactive `nix-shell`, if you wanted to run all phases in the order they would be run in an actual build, you can invoke `genericBuild` yourself.
|
||||
|
||||
### Controlling phases {#ssec-controlling-phases}
|
||||
|
||||
There are a number of variables that control what phases are executed and in what order:
|
||||
@ -333,7 +339,8 @@ There are a number of variables that control what phases are executed and in wha
|
||||
|
||||
Specifies the phases. You can change the order in which phases are executed, or add new phases, by setting this variable. If it’s not set, the default value is used, which is `$prePhases unpackPhase patchPhase $preConfigurePhases configurePhase $preBuildPhases buildPhase checkPhase $preInstallPhases installPhase fixupPhase installCheckPhase $preDistPhases distPhase $postPhases`.
|
||||
|
||||
Usually, if you just want to add a few phases, it’s more convenient to set one of the variables below (such as `preInstallPhases`), as you then don’t specify all the normal phases.
|
||||
It is discouraged to set this variable, as it is easy to miss some important functionality hidden in some of the less obviously needed phases (like `fixupPhase` which patches the shebang of scripts).
|
||||
Usually, if you just want to add a few phases, it’s more convenient to set one of the variables below (such as `preInstallPhases`).
|
||||
|
||||
##### `prePhases` {#var-stdenv-prePhases}
|
||||
|
||||
@ -790,7 +797,7 @@ Hook executed at the start of the distribution phase.
|
||||
|
||||
Hook executed at the end of the distribution phase.
|
||||
|
||||
## Shell functions {#ssec-stdenv-functions}
|
||||
## Shell functions and utilities {#ssec-stdenv-functions}
|
||||
|
||||
The standard environment provides a number of useful functions.
|
||||
|
||||
@ -814,6 +821,19 @@ There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/bui
|
||||
|
||||
Using the `makeBinaryWrapper` implementation is usually preferred, as it creates a tiny _compiled_ wrapper executable, that can be used as a shebang interpreter. This is needed mostly on Darwin, where shebangs cannot point to scripts, [due to a limitation with the `execve`-syscall](https://stackoverflow.com/questions/67100831/macos-shebang-with-absolute-path-not-working). Compiled wrappers generated by `makeBinaryWrapper` can be inspected with `less <path-to-wrapper>` - by scrolling past the binary data you should be able to see the shell command that generated the executable and there see the environment variables that were injected into the wrapper.
|
||||
|
||||
### `remove-references-to -t` \<storepath\> [ `-t` \<storepath\> ... ] \<file\> ... {#fun-remove-references-to}
|
||||
|
||||
Removes the references of the specified files to the specified store files. This is done without changing the size of the file by replacing the hash by `eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`, and should work on compiled executables. This is meant to be used to remove the dependency of the output on inputs that are known to be unnecessary at runtime. Of course, reckless usage will break the patched programs.
|
||||
To use this, add `removeReferencesTo` to `nativeBuildInputs`.
|
||||
|
||||
As `remove-references-to` is an actual executable and not a shell function, it can be used with `find`.
|
||||
Example removing all references to the compiler in the output:
|
||||
```nix
|
||||
postInstall = ''
|
||||
find "$out" -type f -exec remove-references-to -t ${stdenv.cc} '{}' +
|
||||
'';
|
||||
```
|
||||
|
||||
### `substitute` \<infile\> \<outfile\> \<subs\> {#fun-substitute}
|
||||
|
||||
Performs string substitution on the contents of \<infile\>, writing the result to \<outfile\>. The substitutions in \<subs\> are of the following form:
|
||||
|
@ -77,7 +77,7 @@ In Nixpkgs, we have multiple implementations of the BLAS/LAPACK numerical linear
|
||||
|
||||
The Nixpkgs attribute is `openblas` for ILP64 (integer width = 64 bits) and `openblasCompat` for LP64 (integer width = 32 bits). `openblasCompat` is the default.
|
||||
|
||||
- [LAPACK reference](http://www.netlib.org/lapack/) (also provides BLAS)
|
||||
- [LAPACK reference](http://www.netlib.org/lapack/) (also provides BLAS and CBLAS)
|
||||
|
||||
The Nixpkgs attribute is `lapack-reference`.
|
||||
|
||||
@ -117,7 +117,23 @@ $ LD_LIBRARY_PATH=$(nix-build -A mkl)/lib${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH n
|
||||
|
||||
Intel MKL requires an `openmp` implementation when running with multiple processors. By default, `mkl` will use Intel's `iomp` implementation if no other is specified, but this is a runtime-only dependency and binary compatible with the LLVM implementation. To use that one instead, Intel recommends users set it with `LD_PRELOAD`. Note that `mkl` is only available on `x86_64-linux` and `x86_64-darwin`. Moreover, Hydra is not building and distributing pre-compiled binaries using it.
|
||||
|
||||
For BLAS/LAPACK switching to work correctly, all packages must depend on `blas` or `lapack`. This ensures that only one BLAS/LAPACK library is used at one time. There are two versions of BLAS/LAPACK currently in the wild, `LP64` (integer size = 32 bits) and `ILP64` (integer size = 64 bits). Some software needs special flags or patches to work with `ILP64`. You can check if `ILP64` is used in Nixpkgs with `blas.isILP64` and `lapack.isILP64`. Some software does NOT work with `ILP64`, and derivations need to specify an assertion to prevent this. You can prevent `ILP64` from being used with the following:
|
||||
To override `blas` and `lapack` with its reference implementations (i.e. for development purposes), one can use the following overlay:
|
||||
|
||||
```nix
|
||||
self: super:
|
||||
|
||||
{
|
||||
blas = super.blas.override {
|
||||
blasProvider = self.lapack-reference;
|
||||
};
|
||||
|
||||
lapack = super.lapack.override {
|
||||
lapackProvider = self.lapack-reference;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
For BLAS/LAPACK switching to work correctly, all packages must depend on `blas` or `lapack`. This ensures that only one BLAS/LAPACK library is used at one time. There are two versions of BLAS/LAPACK currently in the wild, `LP64` (integer size = 32 bits) and `ILP64` (integer size = 64 bits). The attributes `blas` and `lapack` are `LP64` by default. Their `ILP64` version are provided through the attributes `blas-ilp64` and `lapack-ilp64`. Some software needs special flags or patches to work with `ILP64`. You can check if `ILP64` is used in Nixpkgs with `blas.isILP64` and `lapack.isILP64`. Some software does NOT work with `ILP64`, and derivations need to specify an assertion to prevent this. You can prevent `ILP64` from being used with the following:
|
||||
|
||||
```nix
|
||||
{ stdenv, blas, lapack, ... }:
|
||||
|
40
flake.nix
40
flake.nix
@ -21,39 +21,13 @@
|
||||
|
||||
nixos = import ./nixos/lib { lib = final; };
|
||||
|
||||
nixosSystem = { modules, ... } @ args:
|
||||
nixosSystem = args:
|
||||
import ./nixos/lib/eval-config.nix (args // {
|
||||
modules =
|
||||
let
|
||||
moduleDeclarationFile =
|
||||
let
|
||||
# Even though `modules` is a mandatory argument for `nixosSystem`, it doesn't
|
||||
# mean that the evaluator always keeps track of its position. If there
|
||||
# are too many levels of indirection, the position gets lost at some point.
|
||||
intermediatePos = builtins.unsafeGetAttrPos "modules" args;
|
||||
in
|
||||
if intermediatePos == null then null else intermediatePos.file;
|
||||
|
||||
# Add the invoking file as error message location for modules
|
||||
# that don't have their own locations; presumably inline modules.
|
||||
addModuleDeclarationFile =
|
||||
m: if moduleDeclarationFile == null then m else {
|
||||
_file = moduleDeclarationFile;
|
||||
imports = [ m ];
|
||||
};
|
||||
|
||||
in
|
||||
map addModuleDeclarationFile modules ++ [
|
||||
{
|
||||
system.nixos.versionSuffix =
|
||||
".${final.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}.${self.shortRev or "dirty"}";
|
||||
system.nixos.revision = final.mkIf (self ? rev) self.rev;
|
||||
|
||||
# NOTE: This assumes that `nixpkgs.config` is _not_ used when
|
||||
# nixpkgs.pkgs is set OR _module.args.pkgs is set.
|
||||
nixpkgs.config.path = self.outPath;
|
||||
}
|
||||
];
|
||||
modules = args.modules ++ [ {
|
||||
system.nixos.versionSuffix =
|
||||
".${final.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}.${self.shortRev or "dirty"}";
|
||||
system.nixos.revision = final.mkIf (self ? rev) self.rev;
|
||||
} ];
|
||||
});
|
||||
});
|
||||
|
||||
@ -66,7 +40,7 @@
|
||||
}).nixos.manual.x86_64-linux;
|
||||
};
|
||||
|
||||
legacyPackages = forAllSystems (system: import ./. { inherit system; config.path = self.outPath; });
|
||||
legacyPackages = forAllSystems (system: import ./. { inherit system; });
|
||||
|
||||
nixosModules = {
|
||||
notDetected = import ./nixos/modules/installer/scan/not-detected.nix;
|
||||
|
119
lib/attrsets.nix
119
lib/attrsets.nix
@ -4,8 +4,8 @@
|
||||
let
|
||||
inherit (builtins) head tail length;
|
||||
inherit (lib.trivial) id;
|
||||
inherit (lib.strings) concatStringsSep sanitizeDerivationName;
|
||||
inherit (lib.lists) foldr foldl' concatMap concatLists elemAt all;
|
||||
inherit (lib.strings) concatStringsSep concatMapStringsSep escapeNixIdentifier sanitizeDerivationName;
|
||||
inherit (lib.lists) foldr foldl' concatMap concatLists elemAt all partition groupBy take foldl;
|
||||
in
|
||||
|
||||
rec {
|
||||
@ -78,6 +78,103 @@ rec {
|
||||
in attrByPath attrPath (abort errorMsg);
|
||||
|
||||
|
||||
/* Update or set specific paths of an attribute set.
|
||||
|
||||
Takes a list of updates to apply and an attribute set to apply them to,
|
||||
and returns the attribute set with the updates applied. Updates are
|
||||
represented as { path = ...; update = ...; } values, where `path` is a
|
||||
list of strings representing the attribute path that should be updated,
|
||||
and `update` is a function that takes the old value at that attribute path
|
||||
as an argument and returns the new
|
||||
value it should be.
|
||||
|
||||
Properties:
|
||||
- Updates to deeper attribute paths are applied before updates to more
|
||||
shallow attribute paths
|
||||
- Multiple updates to the same attribute path are applied in the order
|
||||
they appear in the update list
|
||||
- If any but the last `path` element leads into a value that is not an
|
||||
attribute set, an error is thrown
|
||||
- If there is an update for an attribute path that doesn't exist,
|
||||
accessing the argument in the update function causes an error, but
|
||||
intermediate attribute sets are implicitly created as needed
|
||||
|
||||
Example:
|
||||
updateManyAttrsByPath [
|
||||
{
|
||||
path = [ "a" "b" ];
|
||||
update = old: { d = old.c; };
|
||||
}
|
||||
{
|
||||
path = [ "a" "b" "c" ];
|
||||
update = old: old + 1;
|
||||
}
|
||||
{
|
||||
path = [ "x" "y" ];
|
||||
update = old: "xy";
|
||||
}
|
||||
] { a.b.c = 0; }
|
||||
=> { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
|
||||
*/
|
||||
updateManyAttrsByPath = let
|
||||
# When recursing into attributes, instead of updating the `path` of each
|
||||
# update using `tail`, which needs to allocate an entirely new list,
|
||||
# we just pass a prefix length to use and make sure to only look at the
|
||||
# path without the prefix length, so that we can reuse the original list
|
||||
# entries.
|
||||
go = prefixLength: hasValue: value: updates:
|
||||
let
|
||||
# Splits updates into ones on this level (split.right)
|
||||
# And ones on levels further down (split.wrong)
|
||||
split = partition (el: length el.path == prefixLength) updates;
|
||||
|
||||
# Groups updates on further down levels into the attributes they modify
|
||||
nested = groupBy (el: elemAt el.path prefixLength) split.wrong;
|
||||
|
||||
# Applies only nested modification to the input value
|
||||
withNestedMods =
|
||||
# Return the value directly if we don't have any nested modifications
|
||||
if split.wrong == [] then
|
||||
if hasValue then value
|
||||
else
|
||||
# Throw an error if there is no value. This `head` call here is
|
||||
# safe, but only in this branch since `go` could only be called
|
||||
# with `hasValue == false` for nested updates, in which case
|
||||
# it's also always called with at least one update
|
||||
let updatePath = (head split.right).path; in
|
||||
throw
|
||||
( "updateManyAttrsByPath: Path '${showAttrPath updatePath}' does "
|
||||
+ "not exist in the given value, but the first update to this "
|
||||
+ "path tries to access the existing value.")
|
||||
else
|
||||
# If there are nested modifications, try to apply them to the value
|
||||
if ! hasValue then
|
||||
# But if we don't have a value, just use an empty attribute set
|
||||
# as the value, but simplify the code a bit
|
||||
mapAttrs (name: go (prefixLength + 1) false null) nested
|
||||
else if isAttrs value then
|
||||
# If we do have a value and it's an attribute set, override it
|
||||
# with the nested modifications
|
||||
value //
|
||||
mapAttrs (name: go (prefixLength + 1) (value ? ${name}) value.${name}) nested
|
||||
else
|
||||
# However if it's not an attribute set, we can't apply the nested
|
||||
# modifications, throw an error
|
||||
let updatePath = (head split.wrong).path; in
|
||||
throw
|
||||
( "updateManyAttrsByPath: Path '${showAttrPath updatePath}' needs to "
|
||||
+ "be updated, but path '${showAttrPath (take prefixLength updatePath)}' "
|
||||
+ "of the given value is not an attribute set, so we can't "
|
||||
+ "update an attribute inside of it.");
|
||||
|
||||
# We get the final result by applying all the updates on this level
|
||||
# after having applied all the nested updates
|
||||
# We use foldl instead of foldl' so that in case of multiple updates,
|
||||
# intermediate values aren't evaluated if not needed
|
||||
in foldl (acc: el: el.update acc) withNestedMods split.right;
|
||||
|
||||
in updates: value: go 0 true value updates;
|
||||
|
||||
/* Return the specified attributes from a set.
|
||||
|
||||
Example:
|
||||
@ -276,7 +373,7 @@ rec {
|
||||
|
||||
|
||||
/* Like `mapAttrsRecursive', but it takes an additional predicate
|
||||
function that tells it whether to recursive into an attribute
|
||||
function that tells it whether to recurse into an attribute
|
||||
set. If it returns false, `mapAttrsRecursiveCond' does not
|
||||
recurse, but does apply the map function. If it returns true, it
|
||||
does recurse, and does not apply the map function.
|
||||
@ -327,7 +424,7 @@ rec {
|
||||
isDerivation "foobar"
|
||||
=> false
|
||||
*/
|
||||
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
|
||||
isDerivation = x: x.type or null == "derivation";
|
||||
|
||||
/* Converts a store path to a fake derivation. */
|
||||
toDerivation = path:
|
||||
@ -477,6 +574,20 @@ rec {
|
||||
overrideExisting = old: new:
|
||||
mapAttrs (name: value: new.${name} or value) old;
|
||||
|
||||
/* Turns a list of strings into a human-readable description of those
|
||||
strings represented as an attribute path. The result of this function is
|
||||
not intended to be machine-readable.
|
||||
|
||||
Example:
|
||||
showAttrPath [ "foo" "10" "bar" ]
|
||||
=> "foo.\"10\".bar"
|
||||
showAttrPath []
|
||||
=> "<root attribute path>"
|
||||
*/
|
||||
showAttrPath = path:
|
||||
if path == [] then "<root attribute path>"
|
||||
else concatMapStringsSep "." escapeNixIdentifier path;
|
||||
|
||||
/* Get a package output.
|
||||
If no output is found, fallback to `.out` and then to the default.
|
||||
|
||||
|
@ -67,8 +67,9 @@ let
|
||||
inherit (self.trivial) id const pipe concat or and bitAnd bitOr bitXor
|
||||
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
|
||||
importJSON importTOML warn warnIf throwIfNot checkListOfEnum
|
||||
info showWarnings nixpkgsVersion version
|
||||
mod compare splitByAndCompare functionArgs setFunctionArgs isFunction
|
||||
info showWarnings nixpkgsVersion version isInOldestRelease
|
||||
mod compare splitByAndCompare
|
||||
functionArgs setFunctionArgs isFunction toFunction
|
||||
toHexString toBaseDigits;
|
||||
inherit (self.fixedPoints) fix fix' converge extends composeExtensions
|
||||
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
|
||||
@ -78,9 +79,10 @@ let
|
||||
mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond
|
||||
genAttrs isDerivation toDerivation optionalAttrs
|
||||
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
|
||||
recursiveUpdate matchAttrs overrideExisting getOutput getBin
|
||||
recursiveUpdate matchAttrs overrideExisting showAttrPath getOutput getBin
|
||||
getLib getDev getMan chooseDevOutputs zipWithNames zip
|
||||
recurseIntoAttrs dontRecurseIntoAttrs cartesianProductOfSets;
|
||||
recurseIntoAttrs dontRecurseIntoAttrs cartesianProductOfSets
|
||||
updateManyAttrsByPath;
|
||||
inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
|
||||
concatMap flatten remove findSingle findFirst any all count
|
||||
optional optionals toList range partition zipListsWith zipLists
|
||||
@ -111,21 +113,23 @@ let
|
||||
cleanSource sourceByRegex sourceFilesBySuffices
|
||||
commitIdFromGitRepo cleanSourceWith pathHasContext
|
||||
canCleanSource pathIsRegularFile pathIsGitRepo;
|
||||
inherit (self.modules) evalModules unifyModuleSyntax
|
||||
applyIfFunction mergeModules
|
||||
inherit (self.modules) evalModules setDefaultModuleLocation
|
||||
unifyModuleSyntax applyModuleArgsIfFunction mergeModules
|
||||
mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
|
||||
pushDownProperties dischargeProperties filterOverrides
|
||||
sortProperties fixupOptionType mkIf mkAssert mkMerge mkOverride
|
||||
mkOptionDefault mkDefault mkImageMediaOverride mkForce mkVMOverride
|
||||
mkFixStrictness mkOrder mkBefore mkAfter mkAliasDefinitions
|
||||
mkAliasAndWrapDefinitions fixMergeModules mkRemovedOptionModule
|
||||
mkRenamedOptionModule mkMergedOptionModule mkChangedOptionModule
|
||||
mkRenamedOptionModule mkRenamedOptionModuleWith
|
||||
mkMergedOptionModule mkChangedOptionModule
|
||||
mkAliasOptionModule mkDerivedConfig doRename;
|
||||
inherit (self.options) isOption mkEnableOption mkSinkUndeclaredOptions
|
||||
mergeDefaultOption mergeOneOption mergeEqualOption getValues
|
||||
getFiles optionAttrSetToDocList optionAttrSetToDocList'
|
||||
mergeDefaultOption mergeOneOption mergeEqualOption mergeUniqueOption
|
||||
getValues getFiles
|
||||
optionAttrSetToDocList optionAttrSetToDocList'
|
||||
scrubOptionValue literalExpression literalExample literalDocBook
|
||||
showOption showFiles unknownModule mkOption;
|
||||
showOption showFiles unknownModule mkOption mkPackageOption;
|
||||
inherit (self.types) isType setType defaultTypeMerge defaultFunctor
|
||||
isOptionType mkOptionType;
|
||||
inherit (self.asserts)
|
||||
|
@ -465,6 +465,11 @@ in mkLicense lset) ({
|
||||
spdxId = "imagemagick";
|
||||
};
|
||||
|
||||
imlib2 = {
|
||||
spdxId = "Imlib2";
|
||||
fullName = "Imlib2 License";
|
||||
};
|
||||
|
||||
inria-compcert = {
|
||||
fullName = "INRIA Non-Commercial License Agreement for the CompCert verified compiler";
|
||||
url = "https://compcert.org/doc/LICENSE.txt";
|
||||
@ -591,6 +596,16 @@ in mkLicense lset) ({
|
||||
spdxId = "MIT";
|
||||
fullName = "MIT License";
|
||||
};
|
||||
# https://spdx.org/licenses/MIT-feh.html
|
||||
mit-feh = {
|
||||
spdxId = "MIT-feh";
|
||||
fullName = "feh License";
|
||||
};
|
||||
|
||||
mitAdvertising = {
|
||||
spdxId = "MIT-advertising";
|
||||
fullName = "Enlightenment License (e16)";
|
||||
};
|
||||
|
||||
mpl10 = {
|
||||
spdxId = "MPL-1.0";
|
||||
|
@ -4,6 +4,7 @@
|
||||
let
|
||||
inherit (lib.strings) toInt;
|
||||
inherit (lib.trivial) compare min;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in
|
||||
rec {
|
||||
|
||||
@ -340,15 +341,15 @@ rec {
|
||||
groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
||||
=> { true = 12; false = 3; }
|
||||
*/
|
||||
groupBy' = op: nul: pred: lst:
|
||||
foldl' (r: e:
|
||||
let
|
||||
key = pred e;
|
||||
in
|
||||
r // { ${key} = op (r.${key} or nul) e; }
|
||||
) {} lst;
|
||||
groupBy' = op: nul: pred: lst: mapAttrs (name: foldl op nul) (groupBy pred lst);
|
||||
|
||||
groupBy = groupBy' (sum: e: sum ++ [e]) [];
|
||||
groupBy = builtins.groupBy or (
|
||||
pred: foldl' (r: e:
|
||||
let
|
||||
key = pred e;
|
||||
in
|
||||
r // { ${key} = (r.${key} or []) ++ [e]; }
|
||||
) {});
|
||||
|
||||
/* Merges two lists of the same size together. If the sizes aren't the same
|
||||
the merging stops at the shortest. How both lists are merged is defined
|
||||
|
143
lib/modules.nix
143
lib/modules.nix
@ -9,7 +9,7 @@ let
|
||||
catAttrs
|
||||
concatLists
|
||||
concatMap
|
||||
count
|
||||
concatStringsSep
|
||||
elem
|
||||
filter
|
||||
findFirst
|
||||
@ -47,6 +47,20 @@ let
|
||||
showOption
|
||||
unknownModule
|
||||
;
|
||||
|
||||
showDeclPrefix = loc: decl: prefix:
|
||||
" - option(s) with prefix `${showOption (loc ++ [prefix])}' in module `${decl._file}'";
|
||||
showRawDecls = loc: decls:
|
||||
concatStringsSep "\n"
|
||||
(sort (a: b: a < b)
|
||||
(concatMap
|
||||
(decl: map
|
||||
(showDeclPrefix loc decl)
|
||||
(attrNames decl.options)
|
||||
)
|
||||
decls
|
||||
));
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
@ -138,7 +152,7 @@ rec {
|
||||
# support for that, in turn it's lazy in its values. This means e.g.
|
||||
# a `_module.args.pkgs = import (fetchTarball { ... }) {}` won't
|
||||
# start a download when `pkgs` wasn't evaluated.
|
||||
type = types.lazyAttrsOf types.unspecified;
|
||||
type = types.lazyAttrsOf types.raw;
|
||||
internal = true;
|
||||
description = "Arguments passed to each module.";
|
||||
};
|
||||
@ -151,8 +165,7 @@ rec {
|
||||
};
|
||||
|
||||
_module.freeformType = mkOption {
|
||||
# Disallow merging for now, but could be implemented nicely with a `types.optionType`
|
||||
type = types.nullOr (types.uniq types.attrs);
|
||||
type = types.nullOr types.optionType;
|
||||
internal = true;
|
||||
default = null;
|
||||
description = ''
|
||||
@ -269,11 +282,11 @@ rec {
|
||||
# Like unifyModuleSyntax, but also imports paths and calls functions if necessary
|
||||
loadModule = args: fallbackFile: fallbackKey: m:
|
||||
if isFunction m || isAttrs m then
|
||||
unifyModuleSyntax fallbackFile fallbackKey (applyIfFunction fallbackKey m args)
|
||||
unifyModuleSyntax fallbackFile fallbackKey (applyModuleArgsIfFunction fallbackKey m args)
|
||||
else if isList m then
|
||||
let defs = [{ file = fallbackFile; value = m; }]; in
|
||||
throw "Module imports can't be nested lists. Perhaps you meant to remove one level of lists? Definitions: ${showDefs defs}"
|
||||
else unifyModuleSyntax (toString m) (toString m) (applyIfFunction (toString m) (import m) args);
|
||||
else unifyModuleSyntax (toString m) (toString m) (applyModuleArgsIfFunction (toString m) (import m) args);
|
||||
|
||||
/*
|
||||
Collects all modules recursively into the form
|
||||
@ -334,6 +347,10 @@ rec {
|
||||
in modulesPath: initialModules: args:
|
||||
filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
|
||||
|
||||
/* Wrap a module with a default location for reporting errors. */
|
||||
setDefaultModuleLocation = file: m:
|
||||
{ _file = file; imports = [ m ]; };
|
||||
|
||||
/* Massage a module into canonical form, that is, a set consisting
|
||||
of ‘options’, ‘config’ and ‘imports’ attributes. */
|
||||
unifyModuleSyntax = file: key: m:
|
||||
@ -366,7 +383,7 @@ rec {
|
||||
config = addFreeformType (addMeta (removeAttrs m ["_file" "key" "disabledModules" "require" "imports" "freeformType"]));
|
||||
};
|
||||
|
||||
applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
|
||||
applyModuleArgsIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
|
||||
let
|
||||
# Module arguments are resolved in a strict manner when attribute set
|
||||
# deconstruction is used. As the arguments are now defined with the
|
||||
@ -471,26 +488,61 @@ rec {
|
||||
[{ inherit (module) file; inherit value; }]
|
||||
) configs;
|
||||
|
||||
# Convert an option tree decl to a submodule option decl
|
||||
optionTreeToOption = decl:
|
||||
if isOption decl.options
|
||||
then decl
|
||||
else decl // {
|
||||
options = mkOption {
|
||||
type = types.submoduleWith {
|
||||
modules = [ { options = decl.options; } ];
|
||||
# `null` is not intended for use by modules. It is an internal
|
||||
# value that means "whatever the user has declared elsewhere".
|
||||
# This might become obsolete with https://github.com/NixOS/nixpkgs/issues/162398
|
||||
shorthandOnlyDefinesConfig = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
resultsByName = mapAttrs (name: decls:
|
||||
# We're descending into attribute ‘name’.
|
||||
let
|
||||
loc = prefix ++ [name];
|
||||
defns = defnsByName.${name} or [];
|
||||
defns' = defnsByName'.${name} or [];
|
||||
nrOptions = count (m: isOption m.options) decls;
|
||||
optionDecls = filter (m: isOption m.options) decls;
|
||||
in
|
||||
if nrOptions == length decls then
|
||||
if length optionDecls == length decls then
|
||||
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
|
||||
in {
|
||||
matchedOptions = evalOptionValue loc opt defns';
|
||||
unmatchedDefns = [];
|
||||
}
|
||||
else if nrOptions != 0 then
|
||||
let
|
||||
firstOption = findFirst (m: isOption m.options) "" decls;
|
||||
firstNonOption = findFirst (m: !isOption m.options) "" decls;
|
||||
in
|
||||
throw "The option `${showOption loc}' in `${firstOption._file}' is a prefix of options in `${firstNonOption._file}'."
|
||||
else if optionDecls != [] then
|
||||
if all (x: x.options.type.name == "submodule") optionDecls
|
||||
# Raw options can only be merged into submodules. Merging into
|
||||
# attrsets might be nice, but ambiguous. Suppose we have
|
||||
# attrset as a `attrsOf submodule`. User declares option
|
||||
# attrset.foo.bar, this could mean:
|
||||
# a. option `bar` is only available in `attrset.foo`
|
||||
# b. option `foo.bar` is available in all `attrset.*`
|
||||
# c. reject and require "<name>" as a reminder that it behaves like (b).
|
||||
# d. magically combine (a) and (c).
|
||||
# All of the above are merely syntax sugar though.
|
||||
then
|
||||
let opt = fixupOptionType loc (mergeOptionDecls loc (map optionTreeToOption decls));
|
||||
in {
|
||||
matchedOptions = evalOptionValue loc opt defns';
|
||||
unmatchedDefns = [];
|
||||
}
|
||||
else
|
||||
let
|
||||
firstNonOption = findFirst (m: !isOption m.options) "" decls;
|
||||
nonOptions = filter (m: !isOption m.options) decls;
|
||||
in
|
||||
throw "The option `${showOption loc}' in module `${(lib.head optionDecls)._file}' would be a parent of the following options, but its type `${(lib.head optionDecls).options.type.description or "<no description>"}' does not support nested options.\n${
|
||||
showRawDecls loc nonOptions
|
||||
}"
|
||||
else
|
||||
mergeModules' loc decls defns) declsByName;
|
||||
|
||||
@ -534,11 +586,9 @@ rec {
|
||||
correspond to the definition of 'loc' in 'opt.file'. */
|
||||
mergeOptionDecls =
|
||||
let
|
||||
packSubmodule = file: m:
|
||||
{ _file = file; imports = [ m ]; };
|
||||
coerceOption = file: opt:
|
||||
if isFunction opt then packSubmodule file opt
|
||||
else packSubmodule file { options = opt; };
|
||||
if isFunction opt then setDefaultModuleLocation file opt
|
||||
else setDefaultModuleLocation file { options = opt; };
|
||||
in loc: opts:
|
||||
foldl' (res: opt:
|
||||
let t = res.type;
|
||||
@ -559,17 +609,9 @@ rec {
|
||||
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
|
||||
else
|
||||
let
|
||||
/* Add the modules of the current option to the list of modules
|
||||
already collected. The options attribute except either a list of
|
||||
submodules or a submodule. For each submodule, we add the file of the
|
||||
current option declaration as the file use for the submodule. If the
|
||||
submodule defines any filename, then we ignore the enclosing option file. */
|
||||
options' = toList opt.options.options;
|
||||
|
||||
getSubModules = opt.options.type.getSubModules or null;
|
||||
submodules =
|
||||
if getSubModules != null then map (packSubmodule opt._file) getSubModules ++ res.options
|
||||
else if opt.options ? options then map (coerceOption opt._file) options' ++ res.options
|
||||
if getSubModules != null then map (setDefaultModuleLocation opt._file) getSubModules ++ res.options
|
||||
else res.options;
|
||||
in opt.options // res //
|
||||
{ declarations = res.declarations ++ [opt._file];
|
||||
@ -752,26 +794,13 @@ rec {
|
||||
compare = a: b: (a.priority or 1000) < (b.priority or 1000);
|
||||
in sort compare defs';
|
||||
|
||||
/* Hack for backward compatibility: convert options of type
|
||||
optionSet to options of type submodule. FIXME: remove
|
||||
eventually. */
|
||||
# This calls substSubModules, whose entire purpose is only to ensure that
|
||||
# option declarations in submodules have accurate position information.
|
||||
# TODO: Merge this into mergeOptionDecls
|
||||
fixupOptionType = loc: opt:
|
||||
let
|
||||
options = opt.options or
|
||||
(throw "Option `${showOption loc}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
|
||||
f = tp:
|
||||
let optionSetIn = type: (tp.name == type) && (tp.functor.wrapped.name == "optionSet");
|
||||
in
|
||||
if tp.name == "option set" || tp.name == "submodule" then
|
||||
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
|
||||
else if optionSetIn "attrsOf" then types.attrsOf (types.submodule options)
|
||||
else if optionSetIn "listOf" then types.listOf (types.submodule options)
|
||||
else if optionSetIn "nullOr" then types.nullOr (types.submodule options)
|
||||
else tp;
|
||||
in
|
||||
if opt.type.getSubModules or null == null
|
||||
then opt // { type = f (opt.type or types.unspecified); }
|
||||
else opt // { type = opt.type.substSubModules opt.options; options = []; };
|
||||
if opt.type.getSubModules or null == null
|
||||
then opt // { type = opt.type or types.unspecified; }
|
||||
else opt // { type = opt.type.substSubModules opt.options; options = []; };
|
||||
|
||||
|
||||
/* Properties. */
|
||||
@ -903,6 +932,26 @@ rec {
|
||||
use = builtins.trace "Obsolete option `${showOption from}' is used. It was renamed to `${showOption to}'.";
|
||||
};
|
||||
|
||||
mkRenamedOptionModuleWith = {
|
||||
/* Old option path as list of strings. */
|
||||
from,
|
||||
/* New option path as list of strings. */
|
||||
to,
|
||||
|
||||
/*
|
||||
Release number of the first release that contains the rename, ignoring backports.
|
||||
Set it to the upcoming release, matching the nixpkgs/.version file.
|
||||
*/
|
||||
sinceRelease,
|
||||
|
||||
}: doRename {
|
||||
inherit from to;
|
||||
visible = false;
|
||||
warn = lib.isInOldestRelease sinceRelease;
|
||||
use = lib.warnIf (lib.isInOldestRelease sinceRelease)
|
||||
"Obsolete option `${showOption from}' is used. It was renamed to `${showOption to}'.";
|
||||
};
|
||||
|
||||
/* Return a module that causes a warning to be shown if any of the "from"
|
||||
option is defined; the defined values can be used in the "mergeFn" to set
|
||||
the "to" value.
|
||||
|
@ -79,8 +79,6 @@ rec {
|
||||
visible ? null,
|
||||
# Whether the option can be set only once
|
||||
readOnly ? null,
|
||||
# Deprecated, used by types.optionSet.
|
||||
options ? null
|
||||
} @ attrs:
|
||||
attrs // { _type = "option"; };
|
||||
|
||||
@ -172,11 +170,13 @@ rec {
|
||||
else if all isInt list && all (x: x == head list) list then head list
|
||||
else throw "Cannot merge definitions of `${showOption loc}'. Definition values:${showDefs defs}";
|
||||
|
||||
mergeOneOption = loc: defs:
|
||||
if defs == [] then abort "This case should never happen."
|
||||
else if length defs != 1 then
|
||||
throw "The unique option `${showOption loc}' is defined multiple times. Definition values:${showDefs defs}"
|
||||
else (head defs).value;
|
||||
mergeOneOption = mergeUniqueOption { message = ""; };
|
||||
|
||||
mergeUniqueOption = { message }: loc: defs:
|
||||
if length defs == 1
|
||||
then (head defs).value
|
||||
else assert length defs > 1;
|
||||
throw "The option `${showOption loc}' is defined multiple times.\n${message}\nDefinition values:${showDefs defs}";
|
||||
|
||||
/* "Merge" option definitions by checking that they all have the same value. */
|
||||
mergeEqualOption = loc: defs:
|
||||
@ -229,7 +229,7 @@ rec {
|
||||
then true
|
||||
else opt.visible or true;
|
||||
readOnly = opt.readOnly or false;
|
||||
type = opt.type.description or null;
|
||||
type = opt.type.description or "unspecified";
|
||||
}
|
||||
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
|
||||
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
|
||||
|
115
lib/sources.nix
115
lib/sources.nix
@ -20,17 +20,26 @@ let
|
||||
readFile
|
||||
;
|
||||
|
||||
# Returns the type of a path: regular (for file), symlink, or directory
|
||||
pathType = p: getAttr (baseNameOf p) (readDir (dirOf p));
|
||||
/*
|
||||
Returns the type of a path: regular (for file), symlink, or directory.
|
||||
*/
|
||||
pathType = path: getAttr (baseNameOf path) (readDir (dirOf path));
|
||||
|
||||
# Returns true if the path exists and is a directory, false otherwise
|
||||
pathIsDirectory = p: if pathExists p then (pathType p) == "directory" else false;
|
||||
/*
|
||||
Returns true if the path exists and is a directory, false otherwise.
|
||||
*/
|
||||
pathIsDirectory = path: if pathExists path then (pathType path) == "directory" else false;
|
||||
|
||||
# Returns true if the path exists and is a regular file, false otherwise
|
||||
pathIsRegularFile = p: if pathExists p then (pathType p) == "regular" else false;
|
||||
/*
|
||||
Returns true if the path exists and is a regular file, false otherwise.
|
||||
*/
|
||||
pathIsRegularFile = path: if pathExists path then (pathType path) == "regular" else false;
|
||||
|
||||
# Bring in a path as a source, filtering out all Subversion and CVS
|
||||
# directories, as well as backup files (*~).
|
||||
/*
|
||||
A basic filter for `cleanSourceWith` that removes
|
||||
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")) ||
|
||||
@ -48,43 +57,48 @@ let
|
||||
(type == "unknown")
|
||||
);
|
||||
|
||||
# Filters a source tree removing version control files and directories using cleanSourceWith
|
||||
#
|
||||
# Example:
|
||||
# cleanSource ./.
|
||||
/*
|
||||
Filters a source tree removing version control files and directories using cleanSourceFilter.
|
||||
|
||||
Example:
|
||||
cleanSource ./.
|
||||
*/
|
||||
cleanSource = src: cleanSourceWith { filter = cleanSourceFilter; inherit src; };
|
||||
|
||||
# Like `builtins.filterSource`, except it will compose with itself,
|
||||
# allowing you to chain multiple calls together without any
|
||||
# intermediate copies being put in the nix store.
|
||||
#
|
||||
# lib.cleanSourceWith {
|
||||
# filter = f;
|
||||
# src = lib.cleanSourceWith {
|
||||
# filter = g;
|
||||
# src = ./.;
|
||||
# };
|
||||
# }
|
||||
# # Succeeds!
|
||||
#
|
||||
# builtins.filterSource f (builtins.filterSource g ./.)
|
||||
# # Fails!
|
||||
#
|
||||
# Parameters:
|
||||
#
|
||||
# src: A path or cleanSourceWith result to filter and/or rename.
|
||||
#
|
||||
# filter: A function (path -> type -> bool)
|
||||
# Optional with default value: constant true (include everything)
|
||||
# The function will be combined with the && operator such
|
||||
# that src.filter is called lazily.
|
||||
# For implementing a filter, see
|
||||
# https://nixos.org/nix/manual/#builtin-filterSource
|
||||
#
|
||||
# name: Optional name to use as part of the store path.
|
||||
# This defaults to `src.name` or otherwise `"source"`.
|
||||
#
|
||||
cleanSourceWith = { filter ? _path: _type: true, src, name ? null }:
|
||||
/*
|
||||
Like `builtins.filterSource`, except it will compose with itself,
|
||||
allowing you to chain multiple calls together without any
|
||||
intermediate copies being put in the nix store.
|
||||
|
||||
Example:
|
||||
lib.cleanSourceWith {
|
||||
filter = f;
|
||||
src = lib.cleanSourceWith {
|
||||
filter = g;
|
||||
src = ./.;
|
||||
};
|
||||
}
|
||||
# Succeeds!
|
||||
|
||||
builtins.filterSource f (builtins.filterSource g ./.)
|
||||
# Fails!
|
||||
|
||||
*/
|
||||
cleanSourceWith =
|
||||
{
|
||||
# A path or cleanSourceWith result to filter and/or rename.
|
||||
src,
|
||||
# Optional with default value: constant true (include everything)
|
||||
# The function will be combined with the && operator such
|
||||
# that src.filter is called lazily.
|
||||
# For implementing a filter, see
|
||||
# https://nixos.org/nix/manual/#builtin-filterSource
|
||||
# Type: A function (path -> type -> bool)
|
||||
filter ? _path: _type: true,
|
||||
# Optional name to use as part of the store path.
|
||||
# This defaults to `src.name` or otherwise `"source"`.
|
||||
name ? null
|
||||
}:
|
||||
let
|
||||
orig = toSourceAttributes src;
|
||||
in fromSourceAttributes {
|
||||
@ -116,9 +130,11 @@ let
|
||||
satisfiesSubpathInvariant = src ? satisfiesSubpathInvariant && src.satisfiesSubpathInvariant;
|
||||
};
|
||||
|
||||
# Filter sources by a list of regular expressions.
|
||||
#
|
||||
# E.g. `src = sourceByRegex ./my-subproject [".*\.py$" "^database.sql$"]`
|
||||
/*
|
||||
Filter sources by a list of regular expressions.
|
||||
|
||||
Example: src = sourceByRegex ./my-subproject [".*\.py$" "^database.sql$"]
|
||||
*/
|
||||
sourceByRegex = src: regexes:
|
||||
let
|
||||
isFiltered = src ? _isLibCleanSourceWith;
|
||||
@ -153,8 +169,11 @@ let
|
||||
|
||||
pathIsGitRepo = path: (tryEval (commitIdFromGitRepo path)).success;
|
||||
|
||||
# Get the commit id of a git repo
|
||||
# Example: commitIdFromGitRepo <nixpkgs/.git>
|
||||
/*
|
||||
Get the commit id of a git repo.
|
||||
|
||||
Example: commitIdFromGitRepo <nixpkgs/.git>
|
||||
*/
|
||||
commitIdFromGitRepo =
|
||||
let readCommitFromFile = file: path:
|
||||
let fileName = toString path + "/" + file;
|
||||
|
@ -105,7 +105,8 @@ rec {
|
||||
else if final.isAarch64 then "arm64"
|
||||
else if final.isx86_32 then "i386"
|
||||
else if final.isx86_64 then "x86_64"
|
||||
else if final.isMips then "mips"
|
||||
else if final.isMips32 then "mips"
|
||||
else if final.isMips64 then "mips" # linux kernel does not distinguish mips32/mips64
|
||||
else if final.isPower then "powerpc"
|
||||
else if final.isRiscV then "riscv"
|
||||
else if final.isS390 then "s390"
|
||||
|
@ -26,7 +26,7 @@ let
|
||||
|
||||
# Linux
|
||||
"aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux"
|
||||
"armv7l-linux" "i686-linux" "m68k-linux" "mipsel-linux"
|
||||
"armv7l-linux" "i686-linux" "m68k-linux" "mipsel-linux" "mips64el-linux"
|
||||
"powerpc64-linux" "powerpc64le-linux" "riscv32-linux"
|
||||
"riscv64-linux" "s390-linux" "s390x-linux" "x86_64-linux"
|
||||
|
||||
@ -87,7 +87,11 @@ in {
|
||||
darwin = filterDoubles predicates.isDarwin;
|
||||
freebsd = filterDoubles predicates.isFreeBSD;
|
||||
# Should be better, but MinGW is unclear.
|
||||
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
|
||||
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; })
|
||||
++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; })
|
||||
++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; })
|
||||
++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabin32; })
|
||||
++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabi64; });
|
||||
illumos = filterDoubles predicates.isSunOS;
|
||||
linux = filterDoubles predicates.isLinux;
|
||||
netbsd = filterDoubles predicates.isNetBSD;
|
||||
|
@ -93,6 +93,26 @@ rec {
|
||||
config = "mipsel-unknown-linux-gnu";
|
||||
} // platforms.fuloong2f_n32;
|
||||
|
||||
# MIPS ABI table transcribed from here: https://wiki.debian.org/Multiarch/Tuples
|
||||
|
||||
# can execute on 32bit chip
|
||||
mips-linux-gnu = { config = "mips-linux-gnu"; } // platforms.gcc_mips32r2_o32;
|
||||
mipsel-linux-gnu = { config = "mipsel-linux-gnu"; } // platforms.gcc_mips32r2_o32;
|
||||
mipsisa32r6-linux-gnu = { config = "mipsisa32r6-linux-gnu"; } // platforms.gcc_mips32r6_o32;
|
||||
mipsisa32r6el-linux-gnu = { config = "mipsisa32r6el-linux-gnu"; } // platforms.gcc_mips32r6_o32;
|
||||
|
||||
# require 64bit chip (for more registers, 64-bit floating point, 64-bit "long long") but use 32bit pointers
|
||||
mips64-linux-gnuabin32 = { config = "mips64-linux-gnuabin32"; } // platforms.gcc_mips64r2_n32;
|
||||
mips64el-linux-gnuabin32 = { config = "mips64el-linux-gnuabin32"; } // platforms.gcc_mips64r2_n32;
|
||||
mipsisa64r6-linux-gnuabin32 = { config = "mipsisa64r6-linux-gnuabin32"; } // platforms.gcc_mips64r6_n32;
|
||||
mipsisa64r6el-linux-gnuabin32 = { config = "mipsisa64r6el-linux-gnuabin32"; } // platforms.gcc_mips64r6_n32;
|
||||
|
||||
# 64bit pointers
|
||||
mips64-linux-gnuabi64 = { config = "mips64-linux-gnuabi64"; } // platforms.gcc_mips64r2_64;
|
||||
mips64el-linux-gnuabi64 = { config = "mips64el-linux-gnuabi64"; } // platforms.gcc_mips64r2_64;
|
||||
mipsisa64r6-linux-gnuabi64 = { config = "mipsisa64r6-linux-gnuabi64"; } // platforms.gcc_mips64r6_64;
|
||||
mipsisa64r6el-linux-gnuabi64 = { config = "mipsisa64r6el-linux-gnuabi64"; } // platforms.gcc_mips64r6_64;
|
||||
|
||||
muslpi = raspberryPi // {
|
||||
config = "armv6l-unknown-linux-musleabihf";
|
||||
};
|
||||
|
@ -17,6 +17,10 @@ rec {
|
||||
isAarch32 = { cpu = { family = "arm"; bits = 32; }; };
|
||||
isAarch64 = { cpu = { family = "arm"; bits = 64; }; };
|
||||
isMips = { cpu = { family = "mips"; }; };
|
||||
isMips32 = { cpu = { family = "mips"; bits = 32; }; };
|
||||
isMips64 = { cpu = { family = "mips"; bits = 64; }; };
|
||||
isMips64n32 = { cpu = { family = "mips"; bits = 64; }; abi = { abi = "n32"; }; };
|
||||
isMips64n64 = { cpu = { family = "mips"; bits = 64; }; abi = { abi = "64"; }; };
|
||||
isMmix = { cpu = { family = "mmix"; }; };
|
||||
isRiscV = { cpu = { family = "riscv"; }; };
|
||||
isSparc = { cpu = { family = "sparc"; }; };
|
||||
@ -57,7 +61,7 @@ rec {
|
||||
|
||||
isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ];
|
||||
isGnu = with abis; map (a: { abi = a; }) [ gnuabi64 gnu gnueabi gnueabihf ];
|
||||
isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];
|
||||
isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf muslabin32 muslabi64 ];
|
||||
isUClibc = with abis; map (a: { abi = a; }) [ uclibc uclibceabi uclibceabihf ];
|
||||
|
||||
isEfi = map (family: { cpu.family = family; })
|
||||
|
@ -359,13 +359,20 @@ rec {
|
||||
];
|
||||
};
|
||||
gnuabi64 = { abi = "64"; };
|
||||
muslabi64 = { abi = "64"; };
|
||||
|
||||
# NOTE: abi=n32 requires a 64-bit MIPS chip! That is not a typo.
|
||||
# It is basically the 64-bit abi with 32-bit pointers. Details:
|
||||
# https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf
|
||||
gnuabin32 = { abi = "n32"; };
|
||||
muslabin32 = { abi = "n32"; };
|
||||
|
||||
musleabi = { float = "soft"; };
|
||||
musleabihf = { float = "hard"; };
|
||||
musl = {};
|
||||
|
||||
uclibceabihf = { float = "soft"; };
|
||||
uclibceabi = { float = "hard"; };
|
||||
uclibceabi = { float = "soft"; };
|
||||
uclibceabihf = { float = "hard"; };
|
||||
uclibc = {};
|
||||
|
||||
unknown = {};
|
||||
|
@ -1,3 +1,10 @@
|
||||
# Note: lib/systems/default.nix takes care of producing valid,
|
||||
# fully-formed "platform" values (e.g. hostPlatform, buildPlatform,
|
||||
# targetPlatform, etc) containing at least the minimal set of attrs
|
||||
# required (see types.parsedPlatform in lib/systems/parse.nix). This
|
||||
# file takes an already-valid platform and further elaborates it with
|
||||
# optional fields such as linux-kernel, gcc, etc.
|
||||
|
||||
{ lib }:
|
||||
rec {
|
||||
pc = {
|
||||
@ -482,6 +489,43 @@ rec {
|
||||
};
|
||||
};
|
||||
|
||||
# can execute on 32bit chip
|
||||
gcc_mips32r2_o32 = { gcc = { arch = "mips32r2"; abi = "o32"; }; };
|
||||
gcc_mips32r6_o32 = { gcc = { arch = "mips32r6"; abi = "o32"; }; };
|
||||
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
|
||||
# https://gmplib.org/~tege/qemu.html#mips64-debian
|
||||
mips64el-qemu-linux-gnuabi64 = (import ./examples).mips64el-linux-gnuabi64 // {
|
||||
linux-kernel = {
|
||||
name = "mips64el";
|
||||
baseConfig = "64r2el_defconfig";
|
||||
target = "vmlinuz";
|
||||
autoModules = false;
|
||||
DTB = true;
|
||||
# for qemu 9p passthrough filesystem
|
||||
extraConfig = ''
|
||||
MIPS_MALTA y
|
||||
PAGE_SIZE_4KB y
|
||||
CPU_LITTLE_ENDIAN y
|
||||
CPU_MIPS64_R2 y
|
||||
64BIT y
|
||||
CPU_MIPS64_R2 y
|
||||
|
||||
NET_9P y
|
||||
NET_9P_VIRTIO y
|
||||
9P_FS y
|
||||
9P_FS_POSIX_ACL y
|
||||
PCI y
|
||||
VIRTIO_PCI y
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
##
|
||||
## Other
|
||||
##
|
||||
@ -499,6 +543,9 @@ 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:
|
||||
# x86
|
||||
/**/ if platform.isx86 then pc
|
||||
|
@ -761,4 +761,156 @@ runTests {
|
||||
{ a = 3; b = 30; c = 300; }
|
||||
];
|
||||
};
|
||||
|
||||
# The example from the showAttrPath documentation
|
||||
testShowAttrPathExample = {
|
||||
expr = showAttrPath [ "foo" "10" "bar" ];
|
||||
expected = "foo.\"10\".bar";
|
||||
};
|
||||
|
||||
testShowAttrPathEmpty = {
|
||||
expr = showAttrPath [];
|
||||
expected = "<root attribute path>";
|
||||
};
|
||||
|
||||
testShowAttrPathVarious = {
|
||||
expr = showAttrPath [
|
||||
"."
|
||||
"foo"
|
||||
"2"
|
||||
"a2-b"
|
||||
"_bc'de"
|
||||
];
|
||||
expected = ''".".foo."2".a2-b._bc'de'';
|
||||
};
|
||||
|
||||
testGroupBy = {
|
||||
expr = groupBy (n: toString (mod n 5)) (range 0 16);
|
||||
expected = {
|
||||
"0" = [ 0 5 10 15 ];
|
||||
"1" = [ 1 6 11 16 ];
|
||||
"2" = [ 2 7 12 ];
|
||||
"3" = [ 3 8 13 ];
|
||||
"4" = [ 4 9 14 ];
|
||||
};
|
||||
};
|
||||
|
||||
testGroupBy' = {
|
||||
expr = groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ];
|
||||
expected = { false = 3; true = 12; };
|
||||
};
|
||||
|
||||
# The example from the updateManyAttrsByPath documentation
|
||||
testUpdateManyAttrsByPathExample = {
|
||||
expr = updateManyAttrsByPath [
|
||||
{
|
||||
path = [ "a" "b" ];
|
||||
update = old: { d = old.c; };
|
||||
}
|
||||
{
|
||||
path = [ "a" "b" "c" ];
|
||||
update = old: old + 1;
|
||||
}
|
||||
{
|
||||
path = [ "x" "y" ];
|
||||
update = old: "xy";
|
||||
}
|
||||
] { a.b.c = 0; };
|
||||
expected = { a = { b = { d = 1; }; }; x = { y = "xy"; }; };
|
||||
};
|
||||
|
||||
# If there are no updates, the value is passed through
|
||||
testUpdateManyAttrsByPathNone = {
|
||||
expr = updateManyAttrsByPath [] "something";
|
||||
expected = "something";
|
||||
};
|
||||
|
||||
# A single update to the root path is just like applying the function directly
|
||||
testUpdateManyAttrsByPathSingleIncrement = {
|
||||
expr = updateManyAttrsByPath [
|
||||
{
|
||||
path = [ ];
|
||||
update = old: old + 1;
|
||||
}
|
||||
] 0;
|
||||
expected = 1;
|
||||
};
|
||||
|
||||
# Multiple updates can be applied are done in order
|
||||
testUpdateManyAttrsByPathMultipleIncrements = {
|
||||
expr = updateManyAttrsByPath [
|
||||
{
|
||||
path = [ ];
|
||||
update = old: old + "a";
|
||||
}
|
||||
{
|
||||
path = [ ];
|
||||
update = old: old + "b";
|
||||
}
|
||||
{
|
||||
path = [ ];
|
||||
update = old: old + "c";
|
||||
}
|
||||
] "";
|
||||
expected = "abc";
|
||||
};
|
||||
|
||||
# If an update doesn't use the value, all previous updates are not evaluated
|
||||
testUpdateManyAttrsByPathLazy = {
|
||||
expr = updateManyAttrsByPath [
|
||||
{
|
||||
path = [ ];
|
||||
update = old: old + throw "nope";
|
||||
}
|
||||
{
|
||||
path = [ ];
|
||||
update = old: "untainted";
|
||||
}
|
||||
] (throw "start");
|
||||
expected = "untainted";
|
||||
};
|
||||
|
||||
# Deeply nested attributes can be updated without affecting others
|
||||
testUpdateManyAttrsByPathDeep = {
|
||||
expr = updateManyAttrsByPath [
|
||||
{
|
||||
path = [ "a" "b" "c" ];
|
||||
update = old: old + 1;
|
||||
}
|
||||
] {
|
||||
a.b.c = 0;
|
||||
|
||||
a.b.z = 0;
|
||||
a.y.z = 0;
|
||||
x.y.z = 0;
|
||||
};
|
||||
expected = {
|
||||
a.b.c = 1;
|
||||
|
||||
a.b.z = 0;
|
||||
a.y.z = 0;
|
||||
x.y.z = 0;
|
||||
};
|
||||
};
|
||||
|
||||
# Nested attributes are updated first
|
||||
testUpdateManyAttrsByPathNestedBeforehand = {
|
||||
expr = updateManyAttrsByPath [
|
||||
{
|
||||
path = [ "a" ];
|
||||
update = old: old // { x = old.b; };
|
||||
}
|
||||
{
|
||||
path = [ "a" "b" ];
|
||||
update = old: old + 1;
|
||||
}
|
||||
] {
|
||||
a.b = 0;
|
||||
};
|
||||
expected = {
|
||||
a.b = 1;
|
||||
a.x = 1;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,13 @@ checkConfigError() {
|
||||
checkConfigOutput '^false$' config.enable ./declare-enable.nix
|
||||
checkConfigError 'The option .* does not exist. Definition values:\n\s*- In .*: true' config.enable ./define-enable.nix
|
||||
|
||||
checkConfigOutput '^1$' config.bare-submodule.nested ./declare-bare-submodule.nix ./declare-bare-submodule-nested-option.nix
|
||||
checkConfigOutput '^2$' config.bare-submodule.deep ./declare-bare-submodule.nix ./declare-bare-submodule-deep-option.nix
|
||||
checkConfigOutput '^42$' config.bare-submodule.nested ./declare-bare-submodule.nix ./declare-bare-submodule-nested-option.nix ./declare-bare-submodule-deep-option.nix ./define-bare-submodule-values.nix
|
||||
checkConfigOutput '^420$' config.bare-submodule.deep ./declare-bare-submodule.nix ./declare-bare-submodule-nested-option.nix ./declare-bare-submodule-deep-option.nix ./define-bare-submodule-values.nix
|
||||
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 integer types.
|
||||
# unsigned
|
||||
checkConfigOutput '^42$' config.value ./declare-int-unsigned-value.nix ./define-value-int-positive.nix
|
||||
@ -240,6 +247,11 @@ checkConfigOutput '^"24"$' config.foo ./freeform-attrsOf.nix ./freeform-str-dep-
|
||||
checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.nix ./freeform-unstr-dep-str.nix
|
||||
checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix
|
||||
checkConfigOutput '^"24"$' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix
|
||||
# submodules in freeformTypes should have their locations annotated
|
||||
checkConfigOutput '/freeform-submodules.nix"$' config.fooDeclarations.0 ./freeform-submodules.nix
|
||||
# freeformTypes can get merged using `types.type`, including submodules
|
||||
checkConfigOutput '^10$' config.free.xxx.foo ./freeform-submodules.nix
|
||||
checkConfigOutput '^10$' config.free.yyy.bar ./freeform-submodules.nix
|
||||
|
||||
## types.anything
|
||||
# Check that attribute sets are merged recursively
|
||||
@ -284,6 +296,37 @@ checkConfigOutput '^"a b"$' config.resultFoo ./declare-variants.nix ./define-var
|
||||
checkConfigOutput '^"a y z"$' config.resultFooBar ./declare-variants.nix ./define-variant.nix
|
||||
checkConfigOutput '^"a b c"$' config.resultFooFoo ./declare-variants.nix ./define-variant.nix
|
||||
|
||||
## emptyValue's
|
||||
checkConfigOutput "[ ]" config.list.a ./emptyValues.nix
|
||||
checkConfigOutput "{ }" config.attrs.a ./emptyValues.nix
|
||||
checkConfigOutput "null" config.null.a ./emptyValues.nix
|
||||
checkConfigOutput "{ }" config.submodule.a ./emptyValues.nix
|
||||
# These types don't have empty values
|
||||
checkConfigError 'The option .int.a. is used but not defined' config.int.a ./emptyValues.nix
|
||||
checkConfigError 'The option .nonEmptyList.a. is used but not defined' config.nonEmptyList.a ./emptyValues.nix
|
||||
|
||||
## types.raw
|
||||
checkConfigOutput "{ foo = <CODE>; }" config.unprocessedNesting ./raw.nix
|
||||
checkConfigOutput "10" config.processedToplevel ./raw.nix
|
||||
checkConfigError "The option .multiple. is defined multiple times" config.multiple ./raw.nix
|
||||
checkConfigOutput "bar" config.priorities ./raw.nix
|
||||
|
||||
## Option collision
|
||||
checkConfigError \
|
||||
'The option .set. in module .*/declare-set.nix. would be a parent of the following options, but its type .attribute set of signed integers. does not support nested options.\n\s*- option[(]s[)] with prefix .set.enable. in module .*/declare-enable-nested.nix.' \
|
||||
config.set \
|
||||
./declare-set.nix ./declare-enable-nested.nix
|
||||
|
||||
# Test that types.optionType merges types correctly
|
||||
checkConfigOutput '^10$' config.theOption.int ./optionTypeMerging.nix
|
||||
checkConfigOutput '^"hello"$' config.theOption.str ./optionTypeMerging.nix
|
||||
|
||||
# Test that types.optionType correctly annotates option locations
|
||||
checkConfigError 'The option .theOption.nested. in .other.nix. is already declared in .optionTypeFile.nix.' config.theOption.nested ./optionTypeFile.nix
|
||||
|
||||
# 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
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
|
14
lib/tests/modules/adhoc-freeformType-survives-type-merge.nix
Normal file
14
lib/tests/modules/adhoc-freeformType-survives-type-merge.nix
Normal file
@ -0,0 +1,14 @@
|
||||
{ lib, ... }: {
|
||||
options.dummy = lib.mkOption { type = lib.types.anything; default = {}; };
|
||||
freeformType =
|
||||
let
|
||||
a = lib.types.attrsOf (lib.types.submodule { options.bar = lib.mkOption { }; });
|
||||
in
|
||||
# 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 // {
|
||||
merge = loc: defs: { freeformItems = a.merge loc defs; };
|
||||
};
|
||||
config.foo.bar = "ok";
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
options.bare-submodule.deep = mkOption {
|
||||
type = types.int;
|
||||
default = 2;
|
||||
};
|
||||
}
|
10
lib/tests/modules/declare-bare-submodule-deep-option.nix
Normal file
10
lib/tests/modules/declare-bare-submodule-deep-option.nix
Normal file
@ -0,0 +1,10 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
options.bare-submodule.deep = mkOption {
|
||||
type = types.int;
|
||||
default = 2;
|
||||
};
|
||||
}
|
19
lib/tests/modules/declare-bare-submodule-nested-option.nix
Normal file
19
lib/tests/modules/declare-bare-submodule-nested-option.nix
Normal file
@ -0,0 +1,19 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
options.bare-submodule = mkOption {
|
||||
type = types.submoduleWith {
|
||||
shorthandOnlyDefinesConfig = config.shorthandOnlyDefinesConfig;
|
||||
modules = [
|
||||
{
|
||||
options.nested = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
18
lib/tests/modules/declare-bare-submodule.nix
Normal file
18
lib/tests/modules/declare-bare-submodule.nix
Normal file
@ -0,0 +1,18 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
options.bare-submodule = mkOption {
|
||||
type = types.submoduleWith {
|
||||
modules = [ ];
|
||||
shorthandOnlyDefinesConfig = config.shorthandOnlyDefinesConfig;
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
|
||||
# config-dependent options: won't recommend, but useful for making this test parameterized
|
||||
options.shorthandOnlyDefinesConfig = mkOption {
|
||||
default = false;
|
||||
};
|
||||
}
|
12
lib/tests/modules/declare-set.nix
Normal file
12
lib/tests/modules/declare-set.nix
Normal file
@ -0,0 +1,12 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
options.set = lib.mkOption {
|
||||
default = { };
|
||||
example = { a = 1; };
|
||||
type = lib.types.attrsOf lib.types.int;
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
}
|
4
lib/tests/modules/define-bare-submodule-values.nix
Normal file
4
lib/tests/modules/define-bare-submodule-values.nix
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
bare-submodule.nested = 42;
|
||||
bare-submodule.deep = 420;
|
||||
}
|
@ -0,0 +1 @@
|
||||
{ shorthandOnlyDefinesConfig = true; }
|
36
lib/tests/modules/emptyValues.nix
Normal file
36
lib/tests/modules/emptyValues.nix
Normal file
@ -0,0 +1,36 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
in {
|
||||
|
||||
options = {
|
||||
int = lib.mkOption {
|
||||
type = types.lazyAttrsOf types.int;
|
||||
};
|
||||
list = lib.mkOption {
|
||||
type = types.lazyAttrsOf (types.listOf types.int);
|
||||
};
|
||||
nonEmptyList = lib.mkOption {
|
||||
type = types.lazyAttrsOf (types.nonEmptyListOf types.int);
|
||||
};
|
||||
attrs = lib.mkOption {
|
||||
type = types.lazyAttrsOf (types.attrsOf types.int);
|
||||
};
|
||||
null = lib.mkOption {
|
||||
type = types.lazyAttrsOf (types.nullOr types.int);
|
||||
};
|
||||
submodule = lib.mkOption {
|
||||
type = types.lazyAttrsOf (types.submodule {});
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
int.a = lib.mkIf false null;
|
||||
list.a = lib.mkIf false null;
|
||||
nonEmptyList.a = lib.mkIf false null;
|
||||
attrs.a = lib.mkIf false null;
|
||||
null.a = lib.mkIf false null;
|
||||
submodule.a = lib.mkIf false null;
|
||||
};
|
||||
|
||||
}
|
22
lib/tests/modules/freeform-submodules.nix
Normal file
22
lib/tests/modules/freeform-submodules.nix
Normal file
@ -0,0 +1,22 @@
|
||||
{ lib, options, ... }: with lib.types; {
|
||||
|
||||
options.fooDeclarations = lib.mkOption {
|
||||
default = (options.free.type.getSubOptions [])._freeformOptions.foo.declarations;
|
||||
};
|
||||
|
||||
options.free = lib.mkOption {
|
||||
type = submodule {
|
||||
config._module.freeformType = lib.mkMerge [
|
||||
(attrsOf (submodule {
|
||||
options.foo = lib.mkOption {};
|
||||
}))
|
||||
(attrsOf (submodule {
|
||||
options.bar = lib.mkOption {};
|
||||
}))
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config.free.xxx.foo = 10;
|
||||
config.free.yyy.bar = 10;
|
||||
}
|
28
lib/tests/modules/optionTypeFile.nix
Normal file
28
lib/tests/modules/optionTypeFile.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ config, lib, ... }: {
|
||||
|
||||
_file = "optionTypeFile.nix";
|
||||
|
||||
options.theType = lib.mkOption {
|
||||
type = lib.types.optionType;
|
||||
};
|
||||
|
||||
options.theOption = lib.mkOption {
|
||||
type = config.theType;
|
||||
default = {};
|
||||
};
|
||||
|
||||
config.theType = lib.mkMerge [
|
||||
(lib.types.submodule {
|
||||
options.nested = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
};
|
||||
})
|
||||
(lib.types.submodule {
|
||||
_file = "other.nix";
|
||||
options.nested = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
}
|
27
lib/tests/modules/optionTypeMerging.nix
Normal file
27
lib/tests/modules/optionTypeMerging.nix
Normal file
@ -0,0 +1,27 @@
|
||||
{ config, lib, ... }: {
|
||||
|
||||
options.theType = lib.mkOption {
|
||||
type = lib.types.optionType;
|
||||
};
|
||||
|
||||
options.theOption = lib.mkOption {
|
||||
type = config.theType;
|
||||
};
|
||||
|
||||
config.theType = lib.mkMerge [
|
||||
(lib.types.submodule {
|
||||
options.int = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 10;
|
||||
};
|
||||
})
|
||||
(lib.types.submodule {
|
||||
options.str = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
config.theOption.str = "hello";
|
||||
|
||||
}
|
30
lib/tests/modules/raw.nix
Normal file
30
lib/tests/modules/raw.nix
Normal file
@ -0,0 +1,30 @@
|
||||
{ lib, ... }: {
|
||||
|
||||
options = {
|
||||
processedToplevel = lib.mkOption {
|
||||
type = lib.types.raw;
|
||||
};
|
||||
unprocessedNesting = lib.mkOption {
|
||||
type = lib.types.raw;
|
||||
};
|
||||
multiple = lib.mkOption {
|
||||
type = lib.types.raw;
|
||||
};
|
||||
priorities = lib.mkOption {
|
||||
type = lib.types.raw;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
processedToplevel = lib.mkIf true 10;
|
||||
unprocessedNesting.foo = throw "foo";
|
||||
multiple = lib.mkMerge [
|
||||
"foo"
|
||||
"foo"
|
||||
];
|
||||
priorities = lib.mkMerge [
|
||||
"foo"
|
||||
(lib.mkForce "bar")
|
||||
];
|
||||
};
|
||||
}
|
@ -17,7 +17,7 @@ with lib.systems.doubles; lib.runTests {
|
||||
|
||||
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-netbsd" "armv6l-none" "armv7a-linux" "armv7a-netbsd" "armv7l-linux" "armv7l-netbsd" "arm-none" "armv7a-darwin" ];
|
||||
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
|
||||
testmips = mseteq mips [ "mipsel-linux" "mipsel-netbsd" ];
|
||||
testmips = mseteq mips [ "mips64el-linux" "mipsel-linux" "mipsel-netbsd" ];
|
||||
testmmix = mseteq mmix [ "mmix-mmixware" ];
|
||||
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
|
||||
|
||||
@ -28,7 +28,7 @@ with lib.systems.doubles; lib.runTests {
|
||||
testredox = mseteq redox [ "x86_64-redox" ];
|
||||
testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
|
||||
testillumos = mseteq illumos [ "x86_64-solaris" ];
|
||||
testlinux = mseteq linux [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64-linux" "powerpc64le-linux" "m68k-linux" "s390-linux" "s390x-linux" ];
|
||||
testlinux = mseteq linux [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "mips64el-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64-linux" "powerpc64le-linux" "m68k-linux" "s390-linux" "s390x-linux" ];
|
||||
testnetbsd = mseteq netbsd [ "aarch64-netbsd" "armv6l-netbsd" "armv7a-netbsd" "armv7l-netbsd" "i686-netbsd" "m68k-netbsd" "mipsel-netbsd" "powerpc-netbsd" "riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd" ];
|
||||
testopenbsd = mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ];
|
||||
testwindows = mseteq windows [ "i686-cygwin" "x86_64-cygwin" "i686-windows" "x86_64-windows" ];
|
||||
|
@ -61,11 +61,11 @@ rec {
|
||||
pipe = val: functions:
|
||||
let reverseApply = x: f: f x;
|
||||
in builtins.foldl' reverseApply val functions;
|
||||
/* note please don’t add a function like `compose = flip pipe`.
|
||||
This would confuse users, because the order of the functions
|
||||
in the list is not clear. With pipe, it’s obvious that it
|
||||
goes first-to-last. With `compose`, not so much.
|
||||
*/
|
||||
|
||||
# note please don’t add a function like `compose = flip pipe`.
|
||||
# This would confuse users, because the order of the functions
|
||||
# in the list is not clear. With pipe, it’s obvious that it
|
||||
# goes first-to-last. With `compose`, not so much.
|
||||
|
||||
## Named versions corresponding to some builtin operators.
|
||||
|
||||
@ -166,6 +166,30 @@ rec {
|
||||
/* Returns the current nixpkgs release number as string. */
|
||||
release = lib.strings.fileContents ../.version;
|
||||
|
||||
/* The latest release that is supported, at the time of release branch-off,
|
||||
if applicable.
|
||||
|
||||
Ideally, out-of-tree modules should be able to evaluate cleanly with all
|
||||
supported Nixpkgs versions (master, release and old release until EOL).
|
||||
So if possible, deprecation warnings should take effect only when all
|
||||
out-of-tree expressions/libs/modules can upgrade to the new way without
|
||||
losing support for supported Nixpkgs versions.
|
||||
|
||||
This release number allows deprecation warnings to be implemented such that
|
||||
they take effect as soon as the oldest release reaches end of life. */
|
||||
oldestSupportedRelease =
|
||||
# Update on master only. Do not backport.
|
||||
2111;
|
||||
|
||||
/* Whether a feature is supported in all supported releases (at the time of
|
||||
release branch-off, if applicable). See `oldestSupportedRelease`. */
|
||||
isInOldestRelease =
|
||||
/* Release number of feature introduction as an integer, e.g. 2111 for 21.11.
|
||||
Set it to the upcoming release, matching the nixpkgs/.version file.
|
||||
*/
|
||||
release:
|
||||
release <= lib.trivial.oldestSupportedRelease;
|
||||
|
||||
/* Returns the current nixpkgs release code name.
|
||||
|
||||
On each release the first letter is bumped and a new animal is chosen
|
||||
@ -323,7 +347,14 @@ rec {
|
||||
|
||||
Type: bool -> string -> a -> a
|
||||
*/
|
||||
warnIf = cond: msg: if cond then warn msg else id;
|
||||
warnIf = cond: msg: if cond then warn msg else x: x;
|
||||
|
||||
/*
|
||||
Like warnIf, but negated (warn if the first argument is `false`).
|
||||
|
||||
Type: bool -> string -> a -> a
|
||||
*/
|
||||
warnIfNot = cond: msg: if cond then x: x else warn msg;
|
||||
|
||||
/*
|
||||
Like the `assert b; e` expression, but with a custom error message and
|
||||
@ -347,6 +378,13 @@ rec {
|
||||
*/
|
||||
throwIfNot = cond: msg: if cond then x: x else throw msg;
|
||||
|
||||
/*
|
||||
Like throwIfNot, but negated (throw if the first argument is `true`).
|
||||
|
||||
Type: bool -> string -> a -> a
|
||||
*/
|
||||
throwIf = cond: msg: if cond then throw msg else x: x;
|
||||
|
||||
/* Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
|
||||
|
||||
Example:
|
||||
@ -403,6 +441,25 @@ rec {
|
||||
isFunction = f: builtins.isFunction f ||
|
||||
(f ? __functor && isFunction (f.__functor f));
|
||||
|
||||
/*
|
||||
Turns any non-callable values into constant functions.
|
||||
Returns callable values as is.
|
||||
|
||||
Example:
|
||||
|
||||
nix-repl> lib.toFunction 1 2
|
||||
1
|
||||
|
||||
nix-repl> lib.toFunction (x: x + 1) 2
|
||||
3
|
||||
*/
|
||||
toFunction =
|
||||
# Any value
|
||||
v:
|
||||
if isFunction v
|
||||
then v
|
||||
else k: v;
|
||||
|
||||
/* Convert the given positive integer to a string of its hexadecimal
|
||||
representation. For example:
|
||||
|
||||
|
103
lib/types.nix
103
lib/types.nix
@ -32,7 +32,6 @@ let
|
||||
last
|
||||
length
|
||||
tail
|
||||
unique
|
||||
;
|
||||
inherit (lib.attrsets)
|
||||
attrNames
|
||||
@ -48,6 +47,7 @@ let
|
||||
mergeDefaultOption
|
||||
mergeEqualOption
|
||||
mergeOneOption
|
||||
mergeUniqueOption
|
||||
showFiles
|
||||
showOption
|
||||
;
|
||||
@ -61,7 +61,11 @@ let
|
||||
boolToString
|
||||
;
|
||||
|
||||
inherit (lib.modules) mergeDefinitions;
|
||||
inherit (lib.modules)
|
||||
mergeDefinitions
|
||||
fixupOptionType
|
||||
mergeOptionDecls
|
||||
;
|
||||
outer_types =
|
||||
rec {
|
||||
isType = type: x: (x._type or "") == type;
|
||||
@ -162,6 +166,13 @@ rec {
|
||||
# nixos/doc/manual/development/option-types.xml!
|
||||
types = rec {
|
||||
|
||||
raw = mkOptionType rec {
|
||||
name = "raw";
|
||||
description = "raw value";
|
||||
check = value: true;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
anything = mkOptionType {
|
||||
name = "anything";
|
||||
description = "anything";
|
||||
@ -357,13 +368,21 @@ rec {
|
||||
emptyValue = { value = {}; };
|
||||
};
|
||||
|
||||
# derivation is a reserved keyword.
|
||||
# A package is a top-level store path (/nix/store/hash-name). This includes:
|
||||
# - derivations
|
||||
# - more generally, attribute sets with an `outPath` or `__toString` attribute
|
||||
# pointing to a store path, e.g. flake inputs
|
||||
# - strings with context, e.g. "${pkgs.foo}" or (toString pkgs.foo)
|
||||
# - hardcoded store path literals (/nix/store/hash-foo) or strings without context
|
||||
# ("/nix/store/hash-foo"). These get a context added to them using builtins.storePath.
|
||||
package = mkOptionType {
|
||||
name = "package";
|
||||
check = x: isDerivation x || isStorePath x;
|
||||
merge = loc: defs:
|
||||
let res = mergeOneOption loc defs;
|
||||
in if isDerivation res then res else toDerivation res;
|
||||
in if builtins.isPath res || (builtins.isString res && ! builtins.hasContext res)
|
||||
then toDerivation res
|
||||
else res;
|
||||
};
|
||||
|
||||
shellPackage = package // {
|
||||
@ -390,7 +409,7 @@ rec {
|
||||
).optionalValue
|
||||
) def.value
|
||||
) defs)));
|
||||
emptyValue = { value = {}; };
|
||||
emptyValue = { value = []; };
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: listOf (elemType.substSubModules m);
|
||||
@ -402,7 +421,7 @@ rec {
|
||||
let list = addCheck (types.listOf elemType) (l: l != []);
|
||||
in list // {
|
||||
description = "non-empty " + list.description;
|
||||
# Note: emptyValue is left as is, because another module may define an element.
|
||||
emptyValue = { }; # no .value attr, meaning unset
|
||||
};
|
||||
|
||||
attrsOf = elemType: mkOptionType rec {
|
||||
@ -470,6 +489,18 @@ rec {
|
||||
nestedTypes.elemType = elemType;
|
||||
};
|
||||
|
||||
unique = { message }: type: mkOptionType rec {
|
||||
name = "unique";
|
||||
inherit (type) description check;
|
||||
merge = mergeUniqueOption { inherit message; };
|
||||
emptyValue = type.emptyValue;
|
||||
getSubOptions = type.getSubOptions;
|
||||
getSubModules = type.getSubModules;
|
||||
substSubModules = m: uniq (type.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = type; };
|
||||
nestedTypes.elemType = type;
|
||||
};
|
||||
|
||||
# Null or value of ...
|
||||
nullOr = elemType: mkOptionType rec {
|
||||
name = "nullOr";
|
||||
@ -491,7 +522,7 @@ rec {
|
||||
|
||||
functionTo = elemType: mkOptionType {
|
||||
name = "functionTo";
|
||||
description = "function that evaluates to a(n) ${elemType.name}";
|
||||
description = "function that evaluates to a(n) ${elemType.description}";
|
||||
check = isFunction;
|
||||
merge = loc: defs:
|
||||
fnArgs: (mergeDefinitions (loc ++ [ "[function body]" ]) elemType (map (fn: { inherit (fn) file; value = fn.value fnArgs; }) defs)).mergedValue;
|
||||
@ -506,6 +537,33 @@ rec {
|
||||
modules = toList modules;
|
||||
};
|
||||
|
||||
# The type of a type!
|
||||
optionType = mkOptionType {
|
||||
name = "optionType";
|
||||
description = "optionType";
|
||||
check = value: value._type or null == "option-type";
|
||||
merge = loc: defs:
|
||||
if length defs == 1
|
||||
then (head defs).value
|
||||
else let
|
||||
# Prepares the type definitions for mergeOptionDecls, which
|
||||
# annotates submodules types with file locations
|
||||
optionModules = map ({ value, file }:
|
||||
{
|
||||
_file = file;
|
||||
# There's no way to merge types directly from the module system,
|
||||
# but we can cheat a bit by just declaring an option with the type
|
||||
options = lib.mkOption {
|
||||
type = value;
|
||||
};
|
||||
}
|
||||
) defs;
|
||||
# Merges all the types into a single one, including submodule merging.
|
||||
# This also propagates file information to all submodules
|
||||
mergedOption = fixupOptionType loc (mergeOptionDecls loc optionModules);
|
||||
in mergedOption.type;
|
||||
};
|
||||
|
||||
submoduleWith =
|
||||
{ modules
|
||||
, specialArgs ? {}
|
||||
@ -514,14 +572,18 @@ rec {
|
||||
let
|
||||
inherit (lib.modules) evalModules;
|
||||
|
||||
coerce = unify: value: if isFunction value
|
||||
then setFunctionArgs (args: unify (value args)) (functionArgs value)
|
||||
else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
|
||||
shorthandToModule = if shorthandOnlyDefinesConfig == false
|
||||
then value: value
|
||||
else value: { config = value; };
|
||||
|
||||
allModules = defs: imap1 (n: { value, file }:
|
||||
if isAttrs value || isFunction value then
|
||||
# Annotate the value with the location of its definition for better error messages
|
||||
coerce (lib.modules.unifyModuleSyntax file "${toString file}-${toString n}") value
|
||||
if isFunction value
|
||||
then setFunctionArgs
|
||||
(args: lib.modules.unifyModuleSyntax file "${toString file}-${toString n}" (value args))
|
||||
(functionArgs value)
|
||||
else if isAttrs value
|
||||
then
|
||||
lib.modules.unifyModuleSyntax file "${toString file}-${toString n}" (shorthandToModule value)
|
||||
else value
|
||||
) defs;
|
||||
|
||||
@ -589,7 +651,11 @@ rec {
|
||||
then lhs.specialArgs // rhs.specialArgs
|
||||
else throw "A submoduleWith option is declared multiple times with the same specialArgs \"${toString (attrNames intersecting)}\"";
|
||||
shorthandOnlyDefinesConfig =
|
||||
if lhs.shorthandOnlyDefinesConfig == rhs.shorthandOnlyDefinesConfig
|
||||
if lhs.shorthandOnlyDefinesConfig == null
|
||||
then rhs.shorthandOnlyDefinesConfig
|
||||
else if rhs.shorthandOnlyDefinesConfig == null
|
||||
then lhs.shorthandOnlyDefinesConfig
|
||||
else if lhs.shorthandOnlyDefinesConfig == rhs.shorthandOnlyDefinesConfig
|
||||
then lhs.shorthandOnlyDefinesConfig
|
||||
else throw "A submoduleWith option is declared multiple times with conflicting shorthandOnlyDefinesConfig values";
|
||||
};
|
||||
@ -599,6 +665,7 @@ rec {
|
||||
# A value from a set of allowed ones.
|
||||
enum = values:
|
||||
let
|
||||
inherit (lib.lists) unique;
|
||||
show = v:
|
||||
if builtins.isString v then ''"${v}"''
|
||||
else if builtins.isInt v then builtins.toString v
|
||||
@ -682,14 +749,6 @@ rec {
|
||||
nestedTypes.finalType = finalType;
|
||||
};
|
||||
|
||||
# Obsolete alternative to configOf. It takes its option
|
||||
# declarations from the ‘options’ attribute of containing option
|
||||
# declaration.
|
||||
optionSet = mkOptionType {
|
||||
name = "optionSet";
|
||||
description = "option set";
|
||||
deprecationMessage = "Use `types.submodule' instead";
|
||||
};
|
||||
# Augment the given type with an additional type check function.
|
||||
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,7 @@ HACKAGE2NIX="${HACKAGE2NIX:-hackage2nix}"
|
||||
# See: https://github.com/NixOS/nixpkgs/pull/122023
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
extraction_derivation='with import ./. {}; runCommand "unpacked-cabal-hashes" { } "tar xf ${all-cabal-hashes} --strip-components=1 --one-top-level=$out"'
|
||||
extraction_derivation='with import ./. {}; runCommandLocal "unpacked-cabal-hashes" { } "tar xf ${all-cabal-hashes} --strip-components=1 --one-top-level=$out"'
|
||||
unpacked_hackage="$(nix-build -E "$extraction_derivation" --no-out-link)"
|
||||
config_dir=pkgs/development/haskell-modules/configuration-hackage2nix
|
||||
|
||||
|
@ -68,7 +68,7 @@ luautf8,,,,,,pstn
|
||||
luazip,,,,,,
|
||||
lua-yajl,,,,,,pstn
|
||||
luuid,,,,,,
|
||||
luv,,,,1.42.0-0,,
|
||||
luv,,,,1.43.0-0,,
|
||||
lyaml,,,,,,lblasc
|
||||
markdown,,,,,,
|
||||
mediator_lua,,,,,,
|
||||
|
|
@ -1,4 +1,4 @@
|
||||
# Used by pkgs/misc/vim-plugins/update.py and pkgs/applications/editors/kakoune/plugins/update.py
|
||||
# Used by pkgs/applications/editors/vim/plugins/update.py and pkgs/applications/editors/kakoune/plugins/update.py
|
||||
|
||||
# format:
|
||||
# $ nix run nixpkgs.python3Packages.black -c black update.py
|
||||
@ -73,9 +73,13 @@ def retry(ExceptionToCheck: Any, tries: int = 4, delay: float = 3, backoff: floa
|
||||
|
||||
return deco_retry
|
||||
|
||||
@dataclass
|
||||
class FetchConfig:
|
||||
proc: int
|
||||
github_token: str
|
||||
|
||||
def make_request(url: str) -> urllib.request.Request:
|
||||
token = os.getenv("GITHUB_API_TOKEN")
|
||||
|
||||
def make_request(url: str, token=None) -> urllib.request.Request:
|
||||
headers = {}
|
||||
if token is not None:
|
||||
headers["Authorization"] = f"token {token}"
|
||||
@ -90,6 +94,7 @@ class Repo:
|
||||
self.branch = branch
|
||||
self.alias = alias
|
||||
self.redirect: Dict[str, str] = {}
|
||||
self.token = "dummy_token"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@ -132,10 +137,11 @@ class Repo:
|
||||
|
||||
class RepoGitHub(Repo):
|
||||
def __init__(
|
||||
self, owner: str, repo: str, branch: str, alias: Optional[str]
|
||||
self, owner: str, repo: str, branch: str, alias: Optional[str]
|
||||
) -> None:
|
||||
self.owner = owner
|
||||
self.repo = repo
|
||||
self.token = None
|
||||
'''Url to the repo'''
|
||||
super().__init__(self.url(""), branch, alias)
|
||||
log.debug("Instantiating github repo %s/%s", self.owner, self.repo)
|
||||
@ -150,7 +156,7 @@ class RepoGitHub(Repo):
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def has_submodules(self) -> bool:
|
||||
try:
|
||||
req = make_request(self.url(f"blob/{self.branch}/.gitmodules"))
|
||||
req = make_request(self.url(f"blob/{self.branch}/.gitmodules"), self.token)
|
||||
urllib.request.urlopen(req, timeout=10).close()
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 404:
|
||||
@ -162,7 +168,7 @@ class RepoGitHub(Repo):
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def latest_commit(self) -> Tuple[str, datetime]:
|
||||
commit_url = self.url(f"commits/{self.branch}.atom")
|
||||
commit_req = make_request(commit_url)
|
||||
commit_req = make_request(commit_url, self.token)
|
||||
with urllib.request.urlopen(commit_req, timeout=10) as req:
|
||||
self._check_for_redirect(commit_url, req)
|
||||
xml = req.read()
|
||||
@ -291,15 +297,41 @@ class Editor:
|
||||
"""To fill the cache"""
|
||||
return get_current_plugins(self)
|
||||
|
||||
def load_plugin_spec(self, plugin_file) -> List[PluginDesc]:
|
||||
return load_plugin_spec(plugin_file)
|
||||
def load_plugin_spec(self, config: FetchConfig, plugin_file) -> List[PluginDesc]:
|
||||
plugins = []
|
||||
with open(plugin_file) as f:
|
||||
for line in f:
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
plugin = parse_plugin_line(config, line)
|
||||
plugins.append(plugin)
|
||||
return plugins
|
||||
|
||||
def generate_nix(self, plugins, outfile: str):
|
||||
'''Returns nothing for now, writes directly to outfile'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_update(self, input_file: str, outfile: str, proc: int):
|
||||
return get_update(input_file, outfile, proc, editor=self)
|
||||
def get_update(self, input_file: str, outfile: str, config: FetchConfig):
|
||||
cache: Cache = Cache(self.get_current_plugins(), self.cache_file)
|
||||
_prefetch = functools.partial(prefetch, cache=cache)
|
||||
|
||||
def update() -> dict:
|
||||
plugin_names = self.load_plugin_spec(config, input_file)
|
||||
|
||||
try:
|
||||
pool = Pool(processes=config.proc)
|
||||
results = pool.map(_prefetch, plugin_names)
|
||||
finally:
|
||||
cache.store()
|
||||
|
||||
plugins, redirects = check_results(results)
|
||||
|
||||
self.generate_nix(plugins, outfile)
|
||||
|
||||
return redirects
|
||||
|
||||
return update
|
||||
|
||||
|
||||
@property
|
||||
def attr_path(self):
|
||||
@ -345,7 +377,15 @@ class Editor:
|
||||
dest="proc",
|
||||
type=int,
|
||||
default=30,
|
||||
help="Number of concurrent processes to spawn. Export GITHUB_API_TOKEN allows higher values.",
|
||||
help="Number of concurrent processes to spawn. Setting --github-token allows higher values.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--github-token",
|
||||
"-t",
|
||||
type=str,
|
||||
default=os.getenv("GITHUB_API_TOKEN"),
|
||||
help="""Allows to set --proc to higher values.
|
||||
Uses GITHUB_API_TOKEN environment variables as the default value.""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-commit", "-n", action="store_true", default=False,
|
||||
@ -414,8 +454,8 @@ def prefetch_plugin(
|
||||
)
|
||||
|
||||
|
||||
def fetch_plugin_from_pluginline(plugin_line: str) -> Plugin:
|
||||
plugin, _ = prefetch_plugin(parse_plugin_line(plugin_line))
|
||||
def fetch_plugin_from_pluginline(config: FetchConfig, plugin_line: str) -> Plugin:
|
||||
plugin, _ = prefetch_plugin(parse_plugin_line(config, plugin_line))
|
||||
return plugin
|
||||
|
||||
|
||||
@ -465,7 +505,7 @@ def make_repo(uri, branch, alias) -> Repo:
|
||||
repo = Repo(uri.strip(), branch, alias)
|
||||
return repo
|
||||
|
||||
def parse_plugin_line(line: str) -> PluginDesc:
|
||||
def parse_plugin_line(config: FetchConfig, line: str) -> PluginDesc:
|
||||
branch = "HEAD"
|
||||
alias = None
|
||||
uri = line
|
||||
@ -476,21 +516,11 @@ def parse_plugin_line(line: str) -> PluginDesc:
|
||||
uri, branch = uri.split("@")
|
||||
|
||||
repo = make_repo(uri.strip(), branch.strip(), alias)
|
||||
repo.token = config.github_token
|
||||
|
||||
return PluginDesc(repo, branch.strip(), alias)
|
||||
|
||||
|
||||
def load_plugin_spec(plugin_file: str) -> List[PluginDesc]:
|
||||
plugins = []
|
||||
with open(plugin_file) as f:
|
||||
for line in f:
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
plugin = parse_plugin_line(line)
|
||||
plugins.append(plugin)
|
||||
return plugins
|
||||
|
||||
|
||||
def get_cache_path(cache_file_name: str) -> Optional[Path]:
|
||||
xdg_cache = os.environ.get("XDG_CACHE_HOME", None)
|
||||
if xdg_cache is None:
|
||||
@ -556,6 +586,7 @@ def prefetch(
|
||||
|
||||
|
||||
def rewrite_input(
|
||||
config: FetchConfig,
|
||||
input_file: Path,
|
||||
deprecated: Path,
|
||||
redirects: Dict[str, str] = None,
|
||||
@ -573,8 +604,8 @@ def rewrite_input(
|
||||
with open(deprecated, "r") as f:
|
||||
deprecations = json.load(f)
|
||||
for old, new in redirects.items():
|
||||
old_plugin = fetch_plugin_from_pluginline(old)
|
||||
new_plugin = fetch_plugin_from_pluginline(new)
|
||||
old_plugin = fetch_plugin_from_pluginline(config, old)
|
||||
new_plugin = fetch_plugin_from_pluginline(config, new)
|
||||
if old_plugin.normalized_name != new_plugin.normalized_name:
|
||||
deprecations[old_plugin.normalized_name] = {
|
||||
"new": new_plugin.normalized_name,
|
||||
@ -600,40 +631,21 @@ def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
|
||||
print("no changes in working tree to commit")
|
||||
|
||||
|
||||
def get_update(input_file: str, outfile: str, proc: int, editor: Editor):
|
||||
cache: Cache = Cache(editor.get_current_plugins(), editor.cache_file)
|
||||
_prefetch = functools.partial(prefetch, cache=cache)
|
||||
|
||||
def update() -> dict:
|
||||
plugin_names = editor.load_plugin_spec(input_file)
|
||||
|
||||
try:
|
||||
pool = Pool(processes=proc)
|
||||
results = pool.map(_prefetch, plugin_names)
|
||||
finally:
|
||||
cache.store()
|
||||
|
||||
plugins, redirects = check_results(results)
|
||||
|
||||
editor.generate_nix(plugins, outfile)
|
||||
|
||||
return redirects
|
||||
|
||||
return update
|
||||
|
||||
|
||||
def update_plugins(editor: Editor, args):
|
||||
"""The main entry function of this module. All input arguments are grouped in the `Editor`."""
|
||||
|
||||
log.setLevel(LOG_LEVELS[args.debug])
|
||||
log.info("Start updating plugins")
|
||||
update = editor.get_update(args.input_file, args.outfile, args.proc)
|
||||
fetch_config = FetchConfig(args.proc, args.github_token)
|
||||
update = editor.get_update(args.input_file, args.outfile, fetch_config)
|
||||
|
||||
redirects = update()
|
||||
editor.rewrite_input(args.input_file, editor.deprecated, redirects)
|
||||
editor.rewrite_input(fetch_config, args.input_file, editor.deprecated, redirects)
|
||||
|
||||
autocommit = not args.no_commit
|
||||
|
||||
nixpkgs_repo = None
|
||||
if autocommit:
|
||||
nixpkgs_repo = git.Repo(editor.root, search_parent_directories=True)
|
||||
commit(nixpkgs_repo, f"{editor.attr_path}: update", [args.outfile])
|
||||
@ -648,9 +660,9 @@ def update_plugins(editor: Editor, args):
|
||||
)
|
||||
|
||||
for plugin_line in args.add_plugins:
|
||||
editor.rewrite_input(args.input_file, editor.deprecated, append=(plugin_line + "\n",))
|
||||
editor.rewrite_input(fetch_config, args.input_file, editor.deprecated, append=(plugin_line + "\n",))
|
||||
update()
|
||||
plugin = fetch_plugin_from_pluginline(plugin_line)
|
||||
plugin = fetch_plugin_from_pluginline(fetch_config, plugin_line)
|
||||
if autocommit:
|
||||
commit(
|
||||
nixpkgs_repo,
|
||||
|
202
maintainers/scripts/remove-old-aliases.py
Executable file
202
maintainers/scripts/remove-old-aliases.py
Executable file
@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ ])" nix
|
||||
"""
|
||||
A program to remove old aliases or convert old aliases to throws
|
||||
Example usage:
|
||||
./maintainers/scripts/remove-old-aliases.py --year 2018 --file ./pkgs/top-level/aliases.nix
|
||||
|
||||
Check this file with mypy after every change!
|
||||
$ mypy --strict maintainers/scripts/remove-old-aliases.py
|
||||
"""
|
||||
import argparse
|
||||
import shutil
|
||||
import subprocess
|
||||
from datetime import date as datetimedate
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def process_args() -> argparse.Namespace:
|
||||
"""process args"""
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument(
|
||||
"--year", required=True, type=int, help="operate on aliases older than $year"
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--month",
|
||||
type=int,
|
||||
default=1,
|
||||
help="operate on aliases older than $year-$month",
|
||||
)
|
||||
arg_parser.add_argument("--file", required=True, type=Path, help="alias file")
|
||||
arg_parser.add_argument(
|
||||
"--dry-run", action="store_true", help="don't modify files, only print results"
|
||||
)
|
||||
return arg_parser.parse_args()
|
||||
|
||||
|
||||
def get_date_lists(
|
||||
txt: list[str], cutoffdate: datetimedate
|
||||
) -> tuple[list[str], list[str], list[str]]:
|
||||
"""get a list of lines in which the date is older than $cutoffdate"""
|
||||
date_older_list: list[str] = []
|
||||
date_older_throw_list: list[str] = []
|
||||
date_sep_line_list: list[str] = []
|
||||
|
||||
for lineno, line in enumerate(txt, start=1):
|
||||
line = line.rstrip()
|
||||
my_date = None
|
||||
for string in line.split():
|
||||
string = string.strip(":")
|
||||
try:
|
||||
# strip ':' incase there is a string like 2019-11-01:
|
||||
my_date = datetime.strptime(string, "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
try:
|
||||
my_date = datetime.strptime(string, "%Y-%m").date()
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if my_date is None or my_date > cutoffdate or "preserve, reason:" in line.lower():
|
||||
continue
|
||||
|
||||
if "=" not in line:
|
||||
date_sep_line_list.append(f"{lineno} {line}")
|
||||
# 'if' lines could be complicated
|
||||
elif "if " in line and "if =" not in line:
|
||||
print(f"RESOLVE MANUALLY {line}")
|
||||
elif "throw" in line:
|
||||
date_older_throw_list.append(line)
|
||||
else:
|
||||
date_older_list.append(line)
|
||||
|
||||
return (
|
||||
date_older_list,
|
||||
date_sep_line_list,
|
||||
date_older_throw_list,
|
||||
)
|
||||
|
||||
|
||||
def convert_to_throw(date_older_list: list[str]) -> list[tuple[str, str]]:
|
||||
"""convert a list of lines to throws"""
|
||||
converted_list = []
|
||||
for line in date_older_list.copy():
|
||||
indent: str = " " * (len(line) - len(line.lstrip()))
|
||||
before_equal = ""
|
||||
after_equal = ""
|
||||
try:
|
||||
before_equal, after_equal = (x.strip() for x in line.split("=", maxsplit=2))
|
||||
except ValueError as err:
|
||||
print(err, line, "\n")
|
||||
date_older_list.remove(line)
|
||||
continue
|
||||
|
||||
alias = before_equal.strip()
|
||||
after_equal_list = [x.strip(";:") for x in after_equal.split()]
|
||||
|
||||
converted = (
|
||||
f"{indent}{alias} = throw \"'{alias}' has been renamed to/replaced by"
|
||||
f" '{after_equal_list.pop(0)}'\";"
|
||||
f' # Converted to throw {datetime.today().strftime("%Y-%m-%d")}'
|
||||
)
|
||||
converted_list.append((line, converted))
|
||||
|
||||
return converted_list
|
||||
|
||||
|
||||
def generate_text_to_write(
|
||||
txt: list[str],
|
||||
date_older_list: list[str],
|
||||
converted_to_throw: list[tuple[str, str]],
|
||||
date_older_throw_list: list[str],
|
||||
) -> list[str]:
|
||||
"""generate a list of text to be written to the aliasfile"""
|
||||
text_to_write: list[str] = []
|
||||
for line in txt:
|
||||
text_to_append: str = ""
|
||||
if converted_to_throw:
|
||||
for tupl in converted_to_throw:
|
||||
if line == tupl[0]:
|
||||
text_to_append = f"{tupl[1]}\n"
|
||||
if line not in date_older_list and line not in date_older_throw_list:
|
||||
text_to_append = f"{line}\n"
|
||||
if text_to_append:
|
||||
text_to_write.append(text_to_append)
|
||||
|
||||
return text_to_write
|
||||
|
||||
|
||||
def write_file(
|
||||
aliasfile: Path,
|
||||
text_to_write: list[str],
|
||||
) -> None:
|
||||
"""write file"""
|
||||
temp_aliasfile = Path(f"{aliasfile}.raliases")
|
||||
with open(temp_aliasfile, "w", encoding="utf-8") as far:
|
||||
for line in text_to_write:
|
||||
far.write(line)
|
||||
print("\nChecking the syntax of the new aliasfile")
|
||||
try:
|
||||
subprocess.run(
|
||||
["nix-instantiate", "--eval", temp_aliasfile],
|
||||
check=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
print(
|
||||
"\nSyntax check failed,",
|
||||
"there may have been a line which only has\n"
|
||||
'aliasname = "reason why";\n'
|
||||
"when it should have been\n"
|
||||
'aliasname = throw "reason why";',
|
||||
)
|
||||
temp_aliasfile.unlink()
|
||||
return
|
||||
shutil.move(f"{aliasfile}.raliases", aliasfile)
|
||||
print(f"{aliasfile} modified! please verify with 'git diff'.")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""main"""
|
||||
args = process_args()
|
||||
|
||||
aliasfile = Path(args.file).absolute()
|
||||
cutoffdate = (datetime.strptime(f"{args.year}-{args.month}-01", "%Y-%m-%d")).date()
|
||||
|
||||
txt: list[str] = (aliasfile.read_text(encoding="utf-8")).splitlines()
|
||||
|
||||
date_older_list: list[str] = []
|
||||
date_sep_line_list: list[str] = []
|
||||
date_older_throw_list: list[str] = []
|
||||
|
||||
date_older_list, date_sep_line_list, date_older_throw_list = get_date_lists(
|
||||
txt, cutoffdate
|
||||
)
|
||||
|
||||
converted_to_throw: list[tuple[str, str]] = []
|
||||
converted_to_throw = convert_to_throw(date_older_list)
|
||||
|
||||
if date_older_list:
|
||||
print(" Will be converted to throws. ".center(100, "-"))
|
||||
for l_n in date_older_list:
|
||||
print(l_n)
|
||||
|
||||
if date_older_throw_list:
|
||||
print(" Will be removed. ".center(100, "-"))
|
||||
for l_n in date_older_throw_list:
|
||||
print(l_n)
|
||||
|
||||
if date_sep_line_list:
|
||||
print(" On separate line, resolve manually. ".center(100, "-"))
|
||||
for l_n in date_sep_line_list:
|
||||
print(l_n)
|
||||
|
||||
if not args.dry_run:
|
||||
text_to_write = generate_text_to_write(
|
||||
txt, date_older_list, converted_to_throw, date_older_throw_list
|
||||
)
|
||||
write_file(aliasfile, text_to_write)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -25,8 +25,8 @@ from pathlib import Path
|
||||
log = logging.getLogger()
|
||||
log.addHandler(logging.StreamHandler())
|
||||
|
||||
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent
|
||||
from pluginupdate import Editor, update_plugins, PluginDesc, CleanEnvironment, LOG_LEVELS, Cache
|
||||
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent # type: ignore
|
||||
from pluginupdate import Editor, update_plugins, FetchConfig, CleanEnvironment
|
||||
|
||||
PKG_LIST="maintainers/scripts/luarocks-packages.csv"
|
||||
TMP_FILE="$(mktemp)"
|
||||
@ -118,7 +118,7 @@ class LuaEditor(Editor):
|
||||
def attr_path(self):
|
||||
return "luaPackages"
|
||||
|
||||
def get_update(self, input_file: str, outfile: str, proc: int):
|
||||
def get_update(self, input_file: str, outfile: str, config: FetchConfig):
|
||||
_prefetch = generate_pkg_nix
|
||||
|
||||
def update() -> dict:
|
||||
@ -126,14 +126,14 @@ class LuaEditor(Editor):
|
||||
sorted_plugin_specs = sorted(plugin_specs, key=lambda v: v.name.lower())
|
||||
|
||||
try:
|
||||
pool = Pool(processes=proc)
|
||||
pool = Pool(processes=config.proc)
|
||||
results = pool.map(_prefetch, sorted_plugin_specs)
|
||||
finally:
|
||||
pass
|
||||
|
||||
self.generate_nix(results, outfile)
|
||||
|
||||
redirects = []
|
||||
redirects = {}
|
||||
return redirects
|
||||
|
||||
return update
|
||||
@ -181,11 +181,9 @@ def generate_pkg_nix(plug: LuaPlugin):
|
||||
|
||||
cmd.append(plug.version)
|
||||
|
||||
#
|
||||
if plug.server != "src" and plug.server:
|
||||
cmd.append(f"--only-server={plug.server}")
|
||||
|
||||
|
||||
if plug.luaversion:
|
||||
with CleanEnvironment():
|
||||
local_pkgs = str(ROOT.resolve())
|
||||
@ -209,7 +207,6 @@ def main():
|
||||
|
||||
parser = editor.create_parser()
|
||||
args = parser.parse_args()
|
||||
log.setLevel(LOG_LEVELS[args.debug])
|
||||
|
||||
update_plugins(editor, args)
|
||||
|
||||
|
@ -147,7 +147,7 @@ let
|
||||
|
||||
to run update script for specific package, or
|
||||
|
||||
% nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: builtins.isList pkg.updateScript && builtins.length pkg.updateScript >= 1 && (let script = builtins.head pkg.updateScript; in builtins.isAttrs script && script.name == "gnome-update-script"))'
|
||||
% nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: pkg.updateScript.name or null == "gnome-update-script")'
|
||||
|
||||
to run update script for all packages matching given predicate, or
|
||||
|
||||
|
@ -88,6 +88,10 @@ async def commit_changes(name: str, merge_lock: asyncio.Lock, worktree: str, bra
|
||||
async with merge_lock:
|
||||
await check_subprocess('git', 'add', *change['files'], cwd=worktree)
|
||||
commit_message = '{attrPath}: {oldVersion} → {newVersion}'.format(**change)
|
||||
if 'commitMessage' in change:
|
||||
commit_message = change['commitMessage']
|
||||
elif 'commitBody' in change:
|
||||
commit_message = commit_message + '\n\n' + change['commitBody']
|
||||
await check_subprocess('git', 'commit', '--quiet', '-m', commit_message, cwd=worktree)
|
||||
await check_subprocess('git', 'cherry-pick', branch)
|
||||
|
||||
|
@ -50,6 +50,7 @@ with lib.maintainers; {
|
||||
DianaOlympos
|
||||
gleber
|
||||
happysalada
|
||||
minijackson
|
||||
yurrriq
|
||||
];
|
||||
scope = "Maintain BEAM-related packages and modules.";
|
||||
@ -64,7 +65,6 @@ with lib.maintainers; {
|
||||
|
||||
chia = {
|
||||
members = [
|
||||
atemu
|
||||
lourkeur
|
||||
];
|
||||
scope = "Maintain the Chia blockchain and its dependencies";
|
||||
@ -214,7 +214,6 @@ with lib.maintainers; {
|
||||
mguentner
|
||||
ekleog
|
||||
ralith
|
||||
mjlbach
|
||||
dandellion
|
||||
sumnerevans
|
||||
];
|
||||
@ -223,7 +222,7 @@ with lib.maintainers; {
|
||||
|
||||
openstack = {
|
||||
members = [
|
||||
angustrau
|
||||
emilytrau
|
||||
SuperSandro2000
|
||||
];
|
||||
scope = "Maintain the ecosystem around OpenStack";
|
||||
@ -278,6 +277,13 @@ with lib.maintainers; {
|
||||
scope = "Maintain SageMath and the dependencies that are likely to break it.";
|
||||
};
|
||||
|
||||
sphinx = {
|
||||
members = [
|
||||
SuperSandro2000
|
||||
];
|
||||
scope = "Maintain Sphinx related packages.";
|
||||
};
|
||||
|
||||
serokell = {
|
||||
# Verify additions by approval of an already existing member of the team.
|
||||
members = [
|
||||
|
72
nixos/doc/manual/development/activation-script.section.md
Normal file
72
nixos/doc/manual/development/activation-script.section.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Activation script {#sec-activation-script}
|
||||
|
||||
The activation script is a bash script called to activate the new
|
||||
configuration which resides in a NixOS system in `$out/activate`. Since its
|
||||
contents depend on your system configuration, the contents may differ.
|
||||
This chapter explains how the script works in general and some common NixOS
|
||||
snippets. Please be aware that the script is executed on every boot and system
|
||||
switch, so tasks that can be performed in other places should be performed
|
||||
there (for example letting a directory of a service be created by systemd using
|
||||
mechanisms like `StateDirectory`, `CacheDirectory`, ... or if that's not
|
||||
possible using `preStart` of the service).
|
||||
|
||||
Activation scripts are defined as snippets using
|
||||
[](#opt-system.activationScripts). They can either be a simple multiline string
|
||||
or an attribute set that can depend on other snippets. The builder for the
|
||||
activation script will take these dependencies into account and order the
|
||||
snippets accordingly. As a simple example:
|
||||
|
||||
```nix
|
||||
system.activationScripts.my-activation-script = {
|
||||
deps = [ "etc" ];
|
||||
# supportsDryActivation = true;
|
||||
text = ''
|
||||
echo "Hallo i bims"
|
||||
'';
|
||||
};
|
||||
```
|
||||
|
||||
This example creates an activation script snippet that is run after the `etc`
|
||||
snippet. The special variable `supportsDryActivation` can be set so the snippet
|
||||
is also run when `nixos-rebuild dry-activate` is run. To differentiate between
|
||||
real and dry activation, the `$NIXOS_ACTION` environment variable can be
|
||||
read which is set to `dry-activate` when a dry activation is done.
|
||||
|
||||
An activation script can write to special files instructing
|
||||
`switch-to-configuration` to restart/reload units. The script will take these
|
||||
requests into account and will incorperate the unit configuration as described
|
||||
above. This means that the activation script will "fake" a modified unit file
|
||||
and `switch-to-configuration` will act accordingly. By doing so, configuration
|
||||
like [systemd.services.\<name\>.restartIfChanged](#opt-systemd.services) is
|
||||
respected. Since the activation script is run **after** services are already
|
||||
stopped, [systemd.services.\<name\>.stopIfChanged](#opt-systemd.services)
|
||||
cannot be taken into account anymore and the unit is always restarted instead
|
||||
of being stopped and started afterwards.
|
||||
|
||||
The files that can be written to are `/run/nixos/activation-restart-list` and
|
||||
`/run/nixos/activation-reload-list` with their respective counterparts for
|
||||
dry activation being `/run/nixos/dry-activation-restart-list` and
|
||||
`/run/nixos/dry-activation-reload-list`. Those files can contain
|
||||
newline-separated lists of unit names where duplicates are being ignored. These
|
||||
files are not create automatically and activation scripts must take the
|
||||
possiblility into account that they have to create them first.
|
||||
|
||||
## NixOS snippets {#sec-activation-script-nixos-snippets}
|
||||
|
||||
There are some snippets NixOS enables by default because disabling them would
|
||||
most likely break you system. This section lists a few of them and what they
|
||||
do:
|
||||
|
||||
- `binsh` creates `/bin/sh` which points to the runtime shell
|
||||
- `etc` sets up the contents of `/etc`, this includes systemd units and
|
||||
excludes `/etc/passwd`, `/etc/group`, and `/etc/shadow` (which are managed by
|
||||
the `users` snippet)
|
||||
- `hostname` sets the system's hostname in the kernel (not in `/etc`)
|
||||
- `modprobe` sets the path to the `modprobe` binary for module auto-loading
|
||||
- `nix` prepares the nix store and adds a default initial channel
|
||||
- `specialfs` is responsible for mounting filesystems like `/proc` and `sys`
|
||||
- `users` creates and removes users and groups by managing `/etc/passwd`,
|
||||
`/etc/group` and `/etc/shadow`. This also creates home directories
|
||||
- `usrbinenv` creates `/usr/bin/env`
|
||||
- `var` creates some directories in `/var` that are not service-specific
|
||||
- `wrappers` creates setuid wrappers like `ping` and `sudo`
|
@ -12,6 +12,7 @@
|
||||
<xi:include href="../from_md/development/sources.chapter.xml" />
|
||||
<xi:include href="../from_md/development/writing-modules.chapter.xml" />
|
||||
<xi:include href="../from_md/development/building-parts.chapter.xml" />
|
||||
<xi:include href="../from_md/development/what-happens-during-a-system-switch.chapter.xml" />
|
||||
<xi:include href="../from_md/development/writing-documentation.chapter.xml" />
|
||||
<xi:include href="../from_md/development/building-nixos.chapter.xml" />
|
||||
<xi:include href="../from_md/development/nixos-tests.chapter.xml" />
|
||||
|
@ -27,9 +27,10 @@ The function `mkOption` accepts the following arguments.
|
||||
|
||||
`type`
|
||||
|
||||
: The type of the option (see [](#sec-option-types)). It may be
|
||||
omitted, but that's not advisable since it may lead to errors that
|
||||
are hard to diagnose.
|
||||
: The type of the option (see [](#sec-option-types)). This
|
||||
argument is mandatory for nixpkgs modules. Setting this is highly
|
||||
recommended for the sake of documentation and type checking. In case it is
|
||||
not set, a fallback type with unspecified behavior is used.
|
||||
|
||||
`default`
|
||||
|
||||
@ -145,26 +146,26 @@ As an example, we will take the case of display managers. There is a
|
||||
central display manager module for generic display manager options and a
|
||||
module file per display manager backend (sddm, gdm \...).
|
||||
|
||||
There are two approach to this module structure:
|
||||
There are two approaches we could take with this module structure:
|
||||
|
||||
- Managing the display managers independently by adding an enable
|
||||
- Configuring the display managers independently by adding an enable
|
||||
option to every display manager module backend. (NixOS)
|
||||
|
||||
- Managing the display managers in the central module by adding an
|
||||
option to select which display manager backend to use.
|
||||
- Configuring the display managers in the central module by adding
|
||||
an option to select which display manager backend to use.
|
||||
|
||||
Both approaches have problems.
|
||||
|
||||
Making backends independent can quickly become hard to manage. For
|
||||
display managers, there can be only one enabled at a time, but the type
|
||||
system can not enforce this restriction as there is no relation between
|
||||
each backend `enable` option. As a result, this restriction has to be
|
||||
done explicitely by adding assertions in each display manager backend
|
||||
module.
|
||||
display managers, there can only be one enabled at a time, but the
|
||||
type system cannot enforce this restriction as there is no relation
|
||||
between each backend's `enable` option. As a result, this restriction
|
||||
has to be done explicitly by adding assertions in each display manager
|
||||
backend module.
|
||||
|
||||
On the other hand, managing the display managers backends in the central
|
||||
module will require to change the central module option every time a new
|
||||
backend is added or removed.
|
||||
On the other hand, managing the display manager backends in the
|
||||
central module will require changing the central module option every
|
||||
time a new backend is added or removed.
|
||||
|
||||
By using extensible option types, it is possible to create a placeholder
|
||||
option in the central module
|
||||
@ -175,7 +176,7 @@ and to extend it in each backend module
|
||||
|
||||
As a result, `displayManager.enable` option values can be added without
|
||||
changing the main service module file and the type system automatically
|
||||
enforce that there can only be a single display manager enabled.
|
||||
enforces that there can only be a single display manager enabled.
|
||||
|
||||
::: {#ex-option-declaration-eot-service .example}
|
||||
::: {.title}
|
||||
|
@ -16,13 +16,14 @@ merging is handled.
|
||||
|
||||
`types.path`
|
||||
|
||||
: A filesystem path, defined as anything that when coerced to a string
|
||||
starts with a slash. Even if derivations can be considered as path,
|
||||
the more specific `types.package` should be preferred.
|
||||
: A filesystem path is anything that starts with a slash when
|
||||
coerced to a string. Even if derivations can be considered as
|
||||
paths, the more specific `types.package` should be preferred.
|
||||
|
||||
`types.package`
|
||||
|
||||
: A derivation or a store path.
|
||||
: A top-level store path. This can be an attribute set pointing
|
||||
to a store path, like a derivation or a flake input.
|
||||
|
||||
`types.anything`
|
||||
|
||||
@ -63,6 +64,24 @@ merging is handled.
|
||||
```
|
||||
:::
|
||||
|
||||
`types.raw`
|
||||
|
||||
: A type which doesn't do any checking, merging or nested evaluation. It
|
||||
accepts a single arbitrary value that is not recursed into, making it
|
||||
useful for values coming from outside the module system, such as package
|
||||
sets or arbitrary data. Options of this type are still evaluated according
|
||||
to priorities and conditionals, so `mkForce`, `mkIf` and co. still work on
|
||||
the option value itself, but not for any value nested within it. This type
|
||||
should only be used when checking, merging and nested evaluation are not
|
||||
desirable.
|
||||
|
||||
`types.optionType`
|
||||
|
||||
: The type of an option's type. Its merging operation ensures that nested
|
||||
options have the correct file location annotated, and that if possible,
|
||||
multiple option definitions are correctly merged together. The main use
|
||||
case is as the type of the `_module.freeformType` option.
|
||||
|
||||
`types.attrs`
|
||||
|
||||
: A free-form attribute set.
|
||||
@ -250,6 +269,12 @@ Composed types are types that take a type as parameter. `listOf
|
||||
: Ensures that type *`t`* cannot be merged. It is used to ensure option
|
||||
definitions are declared only once.
|
||||
|
||||
`types.unique` `{ message = m }` *`t`*
|
||||
|
||||
: Ensures that type *`t`* cannot be merged. Prints the message *`m`*, after
|
||||
the line `The option <option path> is defined multiple times.` and before
|
||||
a list of definition locations.
|
||||
|
||||
`types.either` *`t1 t2`*
|
||||
|
||||
: Type *`t1`* or type *`t2`*, e.g. `with types; either int str`.
|
||||
|
@ -5,7 +5,7 @@ when developing or debugging a test:
|
||||
|
||||
```ShellSession
|
||||
$ nix-build . -A nixosTests.login.driverInteractive
|
||||
$ ./result/bin/nixos-test-driver --interactive
|
||||
$ ./result/bin/nixos-test-driver
|
||||
[...]
|
||||
>>>
|
||||
```
|
||||
@ -28,7 +28,7 @@ You can re-use the VM states coming from a previous run by setting the
|
||||
`--keep-vm-state` flag.
|
||||
|
||||
```ShellSession
|
||||
$ ./result/bin/nixos-test-driver --interactive --keep-vm-state
|
||||
$ ./result/bin/nixos-test-driver --keep-vm-state
|
||||
```
|
||||
|
||||
The machine state is stored in the `$TMPDIR/vm-state-machinename`
|
||||
|
@ -24,8 +24,8 @@ After building/downloading all required dependencies, this will perform
|
||||
a build that starts a QEMU/KVM virtual machine containing a NixOS
|
||||
system. The virtual machine mounts the Nix store of the host; this makes
|
||||
VM creation very fast, as no disk image needs to be created. Afterwards,
|
||||
you can view a pretty-printed log of the test:
|
||||
you can view a log of the test:
|
||||
|
||||
```ShellSession
|
||||
$ firefox result/log.html
|
||||
$ nix-store --read-log result
|
||||
```
|
||||
|
@ -66,6 +66,45 @@ have a predefined type and string generator already declared under
|
||||
and returning a set with TOML-specific attributes `type` and
|
||||
`generate` as specified [below](#pkgs-formats-result).
|
||||
|
||||
`pkgs.formats.elixirConf { elixir ? pkgs.elixir }`
|
||||
|
||||
: A function taking an attribute set with values
|
||||
|
||||
`elixir`
|
||||
|
||||
: The Elixir package which will be used to format the generated output
|
||||
|
||||
It returns a set with Elixir-Config-specific attributes `type`, `lib`, and
|
||||
`generate` as specified [below](#pkgs-formats-result).
|
||||
|
||||
The `lib` attribute contains functions to be used in settings, for
|
||||
generating special Elixir values:
|
||||
|
||||
`mkRaw elixirCode`
|
||||
|
||||
: Outputs the given string as raw Elixir code
|
||||
|
||||
`mkGetEnv { envVariable, fallback ? null }`
|
||||
|
||||
: Makes the configuration fetch an environment variable at runtime
|
||||
|
||||
`mkAtom atom`
|
||||
|
||||
: Outputs the given string as an Elixir atom, instead of the default
|
||||
Elixir binary string. Note: lowercase atoms still needs to be prefixed
|
||||
with `:`
|
||||
|
||||
`mkTuple array`
|
||||
|
||||
: Outputs the given array as an Elixir tuple, instead of the default
|
||||
Elixir list
|
||||
|
||||
`mkMap attrset`
|
||||
|
||||
: Outputs the given attribute set as an Elixir map, instead of the
|
||||
default Elixir keyword list
|
||||
|
||||
|
||||
::: {#pkgs-formats-result}
|
||||
These functions all return an attribute set with these values:
|
||||
:::
|
||||
@ -74,6 +113,12 @@ These functions all return an attribute set with these values:
|
||||
|
||||
: A module system type representing a value of the format
|
||||
|
||||
`lib`
|
||||
|
||||
: Utility functions for convenience, or special interactions with the format.
|
||||
This attribute is optional. It may contain inside a `types` attribute
|
||||
containing types specific to this format.
|
||||
|
||||
`generate` *`filename jsonValue`*
|
||||
|
||||
: A function that can render a value of the format to a file. Returns
|
||||
|
62
nixos/doc/manual/development/unit-handling.section.md
Normal file
62
nixos/doc/manual/development/unit-handling.section.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Unit handling {#sec-unit-handling}
|
||||
|
||||
To figure out what units need to be started/stopped/restarted/reloaded, the
|
||||
script first checks the current state of the system, similar to what `systemctl
|
||||
list-units` shows. For each of the units, the script goes through the following
|
||||
checks:
|
||||
|
||||
- Is the unit file still in the new system? If not, **stop** the service unless
|
||||
it sets `X-StopOnRemoval` in the `[Unit]` section to `false`.
|
||||
|
||||
- Is it a `.target` unit? If so, **start** it unless it sets
|
||||
`RefuseManualStart` in the `[Unit]` section to `true` or `X-OnlyManualStart`
|
||||
in the `[Unit]` section to `true`. Also **stop** the unit again unless it
|
||||
sets `X-StopOnReconfiguration` to `false`.
|
||||
|
||||
- Are the contents of the unit files different? They are compared by parsing
|
||||
them and comparing their contents. If they are different but only
|
||||
`X-Reload-Triggers` in the `[Unit]` section is changed, **reload** the unit.
|
||||
The NixOS module system allows setting these triggers with the option
|
||||
[systemd.services.\<name\>.reloadTriggers](#opt-systemd.services). There are
|
||||
some additional keys in the `[Unit]` section that are ignored as well. If the
|
||||
unit files differ in any way, the following actions are performed:
|
||||
|
||||
- `.path` and `.slice` units are ignored. There is no need to restart them
|
||||
since changes in their values are applied by systemd when systemd is
|
||||
reloaded.
|
||||
|
||||
- `.mount` units are **reload**ed. These mostly come from the `/etc/fstab`
|
||||
parser.
|
||||
|
||||
- `.socket` units are currently ignored. This is to be fixed at a later
|
||||
point.
|
||||
|
||||
- The rest of the units (mostly `.service` units) are then **reload**ed if
|
||||
`X-ReloadIfChanged` in the `[Service]` section is set to `true` (exposed
|
||||
via [systemd.services.\<name\>.reloadIfChanged](#opt-systemd.services)).
|
||||
A little exception is done for units that were deactivated in the meantime,
|
||||
for example because they require a unit that got stopped before. These
|
||||
are **start**ed instead of reloaded.
|
||||
|
||||
- If the reload flag is not set, some more flags decide if the unit is
|
||||
skipped. These flags are `X-RestartIfChanged` in the `[Service]` section
|
||||
(exposed via
|
||||
[systemd.services.\<name\>.restartIfChanged](#opt-systemd.services)),
|
||||
`RefuseManualStop` in the `[Unit]` section, and `X-OnlyManualStart` in the
|
||||
`[Unit]` section.
|
||||
|
||||
- Further behavior depends on the unit having `X-StopIfChanged` in the
|
||||
`[Service]` section set to `true` (exposed via
|
||||
[systemd.services.\<name\>.stopIfChanged](#opt-systemd.services)). This is
|
||||
set to `true` by default and must be explicitly turned off if not wanted.
|
||||
If the flag is enabled, the unit is **stop**ped and then **start**ed. If
|
||||
not, the unit is **restart**ed. The goal of the flag is to make sure that
|
||||
the new unit never runs in the old environment which is still in place
|
||||
before the activation script is run. This behavior is different when the
|
||||
service is socket-activated, as outlined in the following steps.
|
||||
|
||||
- The last thing that is taken into account is whether the unit is a service
|
||||
and socket-activated. If `X-StopIfChanged` is **not** set, the service
|
||||
is **restart**ed with the others. If it is set, both the service and the
|
||||
socket are **stop**ped and the socket is **start**ed, leaving socket
|
||||
activation to start the service when it's needed.
|
@ -0,0 +1,53 @@
|
||||
# What happens during a system switch? {#sec-switching-systems}
|
||||
|
||||
Running `nixos-rebuild switch` is one of the more common tasks under NixOS.
|
||||
This chapter explains some of the internals of this command to make it simpler
|
||||
for new module developers to configure their units correctly and to make it
|
||||
easier to understand what is happening and why for curious administrators.
|
||||
|
||||
`nixos-rebuild`, like many deployment solutions, calls `switch-to-configuration`
|
||||
which resides in a NixOS system at `$out/bin/switch-to-configuration`. The
|
||||
script is called with the action that is to be performed like `switch`, `test`,
|
||||
`boot`. There is also the `dry-activate` action which does not really perform
|
||||
the actions but rather prints what it would do if you called it with `test`.
|
||||
This feature can be used to check what service states would be changed if the
|
||||
configuration was switched to.
|
||||
|
||||
If the action is `switch` or `boot`, the bootloader is updated first so the
|
||||
configuration will be the next one to boot. Unless `NIXOS_NO_SYNC` is set to
|
||||
`1`, `/nix/store` is synced to disk.
|
||||
|
||||
If the action is `switch` or `test`, the currently running system is inspected
|
||||
and the actions to switch to the new system are calculated. This process takes
|
||||
two data sources into account: `/etc/fstab` and the current systemd status.
|
||||
Mounts and swaps are read from `/etc/fstab` and the corresponding actions are
|
||||
generated. If a new mount is added, for example, the proper `.mount` unit is
|
||||
marked to be started. The current systemd state is inspected, the difference
|
||||
between the current system and the desired configuration is calculated and
|
||||
actions are generated to get to this state. There are a lot of nuances that can
|
||||
be controlled by the units which are explained here.
|
||||
|
||||
After calculating what should be done, the actions are carried out. The order
|
||||
of actions is always the same:
|
||||
- Stop units (`systemctl stop`)
|
||||
- Run activation script (`$out/activate`)
|
||||
- See if the activation script requested more units to restart
|
||||
- Restart systemd if needed (`systemd daemon-reexec`)
|
||||
- Forget about the failed state of units (`systemctl reset-failed`)
|
||||
- Reload systemd (`systemctl daemon-reload`)
|
||||
- Reload systemd user instances (`systemctl --user daemon-reload`)
|
||||
- Set up tmpfiles (`systemd-tmpfiles --create`)
|
||||
- Reload units (`systemctl reload`)
|
||||
- Restart units (`systemctl restart`)
|
||||
- Start units (`systemctl start`)
|
||||
- Inspect what changed during these actions and print units that failed and
|
||||
that were newly started
|
||||
|
||||
Most of these actions are either self-explaining but some of them have to do
|
||||
with our units or the activation script. For this reason, these topics are
|
||||
explained in the next sections.
|
||||
|
||||
```{=docbook}
|
||||
<xi:include href="unit-handling.section.xml" />
|
||||
<xi:include href="activation-script.section.xml" />
|
||||
```
|
@ -90,6 +90,17 @@ modules: `systemd.services` (the set of all systemd services) and
|
||||
`systemd.timers` (the list of commands to be executed periodically by
|
||||
`systemd`).
|
||||
|
||||
Care must be taken when writing systemd services using `Exec*` directives. By
|
||||
default systemd performs substitution on `%<char>` specifiers in these
|
||||
directives, expands environment variables from `$FOO` and `${FOO}`, splits
|
||||
arguments on whitespace, and splits commands on `;`. All of these must be escaped
|
||||
to avoid unexpected substitution or splitting when interpolating into an `Exec*`
|
||||
directive, e.g. when using an `extraArgs` option to pass additional arguments to
|
||||
the service. The functions `utils.escapeSystemdExecArg` and
|
||||
`utils.escapeSystemdExecArgs` are provided for this, see [Example: Escaping in
|
||||
Exec directives](#exec-escaping-example) for an example. When using these
|
||||
functions system environment substitution should *not* be disabled explicitly.
|
||||
|
||||
::: {#locate-example .example}
|
||||
::: {.title}
|
||||
**Example: NixOS Module for the "locate" Service**
|
||||
@ -153,6 +164,37 @@ in {
|
||||
```
|
||||
:::
|
||||
|
||||
::: {#exec-escaping-example .example}
|
||||
::: {.title}
|
||||
**Example: Escaping in Exec directives**
|
||||
:::
|
||||
```nix
|
||||
{ config, lib, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.echo;
|
||||
echoAll = pkgs.writeScript "echo-all" ''
|
||||
#! ${pkgs.runtimeShell}
|
||||
for s in "$@"; do
|
||||
printf '%s\n' "$s"
|
||||
done
|
||||
'';
|
||||
args = [ "a%Nything" "lang=\${LANG}" ";" "/bin/sh -c date" ];
|
||||
in {
|
||||
systemd.services.echo =
|
||||
{ description = "Echo to the journal";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.ExecStart = ''
|
||||
${echoAll} ${utils.escapeSystemdExecArgs args}
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
```{=docbook}
|
||||
<xi:include href="option-declarations.section.xml" />
|
||||
<xi:include href="option-types.section.xml" />
|
||||
|
@ -158,6 +158,12 @@ The following methods are available on machine objects:
|
||||
e.g., `send_chars("foobar\n")` will type the string `foobar`
|
||||
followed by the Enter key.
|
||||
|
||||
`send_console`
|
||||
|
||||
: Send keys to the kernel console. This allows interaction with the systemd
|
||||
emergency mode, for example. Takes a string that is sent, e.g.,
|
||||
`send_console("\n\nsystemctl default\n")`.
|
||||
|
||||
`execute`
|
||||
|
||||
: Execute a shell command, returning a list `(status, stdout)`.
|
||||
@ -272,6 +278,13 @@ The following methods are available on machine objects:
|
||||
Killing the interactive session with `Ctrl-d` or `Ctrl-c` also ends
|
||||
the guest session.
|
||||
|
||||
`console_interact`
|
||||
|
||||
: Allows you to directly interact with QEMU's stdin. This should
|
||||
only be used during test development, not in production tests.
|
||||
Output from QEMU is only read line-wise. `Ctrl-c` kills QEMU and
|
||||
`Ctrl-d` closes console and returns to the test runner.
|
||||
|
||||
To test user units declared by `systemd.user.services` the optional
|
||||
`user` argument can be used:
|
||||
|
||||
|
@ -0,0 +1,150 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-activation-script">
|
||||
<title>Activation script</title>
|
||||
<para>
|
||||
The activation script is a bash script called to activate the new
|
||||
configuration which resides in a NixOS system in
|
||||
<literal>$out/activate</literal>. Since its contents depend on your
|
||||
system configuration, the contents may differ. This chapter explains
|
||||
how the script works in general and some common NixOS snippets.
|
||||
Please be aware that the script is executed on every boot and system
|
||||
switch, so tasks that can be performed in other places should be
|
||||
performed there (for example letting a directory of a service be
|
||||
created by systemd using mechanisms like
|
||||
<literal>StateDirectory</literal>,
|
||||
<literal>CacheDirectory</literal>, … or if that’s not possible using
|
||||
<literal>preStart</literal> of the service).
|
||||
</para>
|
||||
<para>
|
||||
Activation scripts are defined as snippets using
|
||||
<xref linkend="opt-system.activationScripts" />. They can either be
|
||||
a simple multiline string or an attribute set that can depend on
|
||||
other snippets. The builder for the activation script will take
|
||||
these dependencies into account and order the snippets accordingly.
|
||||
As a simple example:
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
system.activationScripts.my-activation-script = {
|
||||
deps = [ "etc" ];
|
||||
# supportsDryActivation = true;
|
||||
text = ''
|
||||
echo "Hallo i bims"
|
||||
'';
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
This example creates an activation script snippet that is run after
|
||||
the <literal>etc</literal> snippet. The special variable
|
||||
<literal>supportsDryActivation</literal> can be set so the snippet
|
||||
is also run when <literal>nixos-rebuild dry-activate</literal> is
|
||||
run. To differentiate between real and dry activation, the
|
||||
<literal>$NIXOS_ACTION</literal> environment variable can be read
|
||||
which is set to <literal>dry-activate</literal> when a dry
|
||||
activation is done.
|
||||
</para>
|
||||
<para>
|
||||
An activation script can write to special files instructing
|
||||
<literal>switch-to-configuration</literal> to restart/reload units.
|
||||
The script will take these requests into account and will
|
||||
incorperate the unit configuration as described above. This means
|
||||
that the activation script will <quote>fake</quote> a modified unit
|
||||
file and <literal>switch-to-configuration</literal> will act
|
||||
accordingly. By doing so, configuration like
|
||||
<link linkend="opt-systemd.services">systemd.services.<name>.restartIfChanged</link>
|
||||
is respected. Since the activation script is run
|
||||
<emphasis role="strong">after</emphasis> services are already
|
||||
stopped,
|
||||
<link linkend="opt-systemd.services">systemd.services.<name>.stopIfChanged</link>
|
||||
cannot be taken into account anymore and the unit is always
|
||||
restarted instead of being stopped and started afterwards.
|
||||
</para>
|
||||
<para>
|
||||
The files that can be written to are
|
||||
<literal>/run/nixos/activation-restart-list</literal> and
|
||||
<literal>/run/nixos/activation-reload-list</literal> with their
|
||||
respective counterparts for dry activation being
|
||||
<literal>/run/nixos/dry-activation-restart-list</literal> and
|
||||
<literal>/run/nixos/dry-activation-reload-list</literal>. Those
|
||||
files can contain newline-separated lists of unit names where
|
||||
duplicates are being ignored. These files are not create
|
||||
automatically and activation scripts must take the possiblility into
|
||||
account that they have to create them first.
|
||||
</para>
|
||||
<section xml:id="sec-activation-script-nixos-snippets">
|
||||
<title>NixOS snippets</title>
|
||||
<para>
|
||||
There are some snippets NixOS enables by default because disabling
|
||||
them would most likely break you system. This section lists a few
|
||||
of them and what they do:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>binsh</literal> creates <literal>/bin/sh</literal>
|
||||
which points to the runtime shell
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>etc</literal> sets up the contents of
|
||||
<literal>/etc</literal>, this includes systemd units and
|
||||
excludes <literal>/etc/passwd</literal>,
|
||||
<literal>/etc/group</literal>, and
|
||||
<literal>/etc/shadow</literal> (which are managed by the
|
||||
<literal>users</literal> snippet)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>hostname</literal> sets the system’s hostname in the
|
||||
kernel (not in <literal>/etc</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>modprobe</literal> sets the path to the
|
||||
<literal>modprobe</literal> binary for module auto-loading
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>nix</literal> prepares the nix store and adds a
|
||||
default initial channel
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>specialfs</literal> is responsible for mounting
|
||||
filesystems like <literal>/proc</literal> and
|
||||
<literal>sys</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>users</literal> creates and removes users and groups
|
||||
by managing <literal>/etc/passwd</literal>,
|
||||
<literal>/etc/group</literal> and
|
||||
<literal>/etc/shadow</literal>. This also creates home
|
||||
directories
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>usrbinenv</literal> creates
|
||||
<literal>/usr/bin/env</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>var</literal> creates some directories in
|
||||
<literal>/var</literal> that are not service-specific
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>wrappers</literal> creates setuid wrappers like
|
||||
<literal>ping</literal> and <literal>sudo</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
@ -38,9 +38,11 @@ options = {
|
||||
<listitem>
|
||||
<para>
|
||||
The type of the option (see
|
||||
<xref linkend="sec-option-types" />). It may be omitted, but
|
||||
that’s not advisable since it may lead to errors that are hard
|
||||
to diagnose.
|
||||
<xref linkend="sec-option-types" />). This argument is
|
||||
mandatory for nixpkgs modules. Setting this is highly
|
||||
recommended for the sake of documentation and type checking.
|
||||
In case it is not set, a fallback type with unspecified
|
||||
behavior is used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -215,21 +217,22 @@ lib.mkOption {
|
||||
manager backend (sddm, gdm ...).
|
||||
</para>
|
||||
<para>
|
||||
There are two approach to this module structure:
|
||||
There are two approaches we could take with this module
|
||||
structure:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Managing the display managers independently by adding an
|
||||
enable option to every display manager module backend.
|
||||
(NixOS)
|
||||
Configuring the display managers independently by adding
|
||||
an enable option to every display manager module
|
||||
backend. (NixOS)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Managing the display managers in the central module by
|
||||
adding an option to select which display manager backend
|
||||
to use.
|
||||
Configuring the display managers in the central module
|
||||
by adding an option to select which display manager
|
||||
backend to use.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@ -238,16 +241,16 @@ lib.mkOption {
|
||||
</para>
|
||||
<para>
|
||||
Making backends independent can quickly become hard to
|
||||
manage. For display managers, there can be only one enabled
|
||||
at a time, but the type system can not enforce this
|
||||
restriction as there is no relation between each backend
|
||||
manage. For display managers, there can only be one enabled
|
||||
at a time, but the type system cannot enforce this
|
||||
restriction as there is no relation between each backend’s
|
||||
<literal>enable</literal> option. As a result, this
|
||||
restriction has to be done explicitely by adding assertions
|
||||
restriction has to be done explicitly by adding assertions
|
||||
in each display manager backend module.
|
||||
</para>
|
||||
<para>
|
||||
On the other hand, managing the display managers backends in
|
||||
the central module will require to change the central module
|
||||
On the other hand, managing the display manager backends in
|
||||
the central module will require changing the central module
|
||||
option every time a new backend is added or removed.
|
||||
</para>
|
||||
<para>
|
||||
@ -268,7 +271,7 @@ lib.mkOption {
|
||||
<para>
|
||||
As a result, <literal>displayManager.enable</literal> option
|
||||
values can be added without changing the main service module
|
||||
file and the type system automatically enforce that there
|
||||
file and the type system automatically enforces that there
|
||||
can only be a single display manager enabled.
|
||||
</para>
|
||||
<anchor xml:id="ex-option-declaration-eot-service" />
|
||||
|
@ -30,10 +30,10 @@
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A filesystem path, defined as anything that when coerced to
|
||||
a string starts with a slash. Even if derivations can be
|
||||
considered as path, the more specific
|
||||
<literal>types.package</literal> should be preferred.
|
||||
A filesystem path is anything that starts with a slash when
|
||||
coerced to a string. Even if derivations can be considered
|
||||
as paths, the more specific <literal>types.package</literal>
|
||||
should be preferred.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -43,7 +43,9 @@
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A derivation or a store path.
|
||||
A top-level store path. This can be an attribute set
|
||||
pointing to a store path, like a derivation or a flake
|
||||
input.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -92,6 +94,39 @@
|
||||
</programlisting>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>types.raw</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A type which doesn’t do any checking, merging or nested
|
||||
evaluation. It accepts a single arbitrary value that is not
|
||||
recursed into, making it useful for values coming from
|
||||
outside the module system, such as package sets or arbitrary
|
||||
data. Options of this type are still evaluated according to
|
||||
priorities and conditionals, so <literal>mkForce</literal>,
|
||||
<literal>mkIf</literal> and co. still work on the option
|
||||
value itself, but not for any value nested within it. This
|
||||
type should only be used when checking, merging and nested
|
||||
evaluation are not desirable.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>types.optionType</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The type of an option’s type. Its merging operation ensures
|
||||
that nested options have the correct file location
|
||||
annotated, and that if possible, multiple option definitions
|
||||
are correctly merged together. The main use case is as the
|
||||
type of the <literal>_module.freeformType</literal> option.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>types.attrs</literal>
|
||||
@ -496,6 +531,22 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>types.unique</literal>
|
||||
<literal>{ message = m }</literal>
|
||||
<emphasis><literal>t</literal></emphasis>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Ensures that type <emphasis><literal>t</literal></emphasis>
|
||||
cannot be merged. Prints the message
|
||||
<emphasis><literal>m</literal></emphasis>, after the line
|
||||
<literal>The option <option path> is defined multiple times.</literal>
|
||||
and before a list of definition locations.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>types.either</literal>
|
||||
|
@ -6,7 +6,7 @@
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-build . -A nixosTests.login.driverInteractive
|
||||
$ ./result/bin/nixos-test-driver --interactive
|
||||
$ ./result/bin/nixos-test-driver
|
||||
[...]
|
||||
>>>
|
||||
</programlisting>
|
||||
@ -30,7 +30,7 @@ $ ./result/bin/nixos-test-driver --interactive
|
||||
the <literal>--keep-vm-state</literal> flag.
|
||||
</para>
|
||||
<programlisting>
|
||||
$ ./result/bin/nixos-test-driver --interactive --keep-vm-state
|
||||
$ ./result/bin/nixos-test-driver --keep-vm-state
|
||||
</programlisting>
|
||||
<para>
|
||||
The machine state is stored in the
|
||||
|
@ -26,9 +26,9 @@ machine: QEMU running (pid 8841)
|
||||
perform a build that starts a QEMU/KVM virtual machine containing a
|
||||
NixOS system. The virtual machine mounts the Nix store of the host;
|
||||
this makes VM creation very fast, as no disk image needs to be
|
||||
created. Afterwards, you can view a pretty-printed log of the test:
|
||||
created. Afterwards, you can view a log of the test:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ firefox result/log.html
|
||||
$ nix-store --read-log result
|
||||
</programlisting>
|
||||
</section>
|
||||
|
@ -137,6 +137,97 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>pkgs.formats.elixirConf { elixir ? pkgs.elixir }</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function taking an attribute set with values
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>elixir</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The Elixir package which will be used to format the
|
||||
generated output
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
It returns a set with Elixir-Config-specific attributes
|
||||
<literal>type</literal>, <literal>lib</literal>, and
|
||||
<literal>generate</literal> as specified
|
||||
<link linkend="pkgs-formats-result">below</link>.
|
||||
</para>
|
||||
<para>
|
||||
The <literal>lib</literal> attribute contains functions to
|
||||
be used in settings, for generating special Elixir values:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>mkRaw elixirCode</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Outputs the given string as raw Elixir code
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>mkGetEnv { envVariable, fallback ? null }</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Makes the configuration fetch an environment variable
|
||||
at runtime
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>mkAtom atom</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Outputs the given string as an Elixir atom, instead of
|
||||
the default Elixir binary string. Note: lowercase
|
||||
atoms still needs to be prefixed with
|
||||
<literal>:</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>mkTuple array</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Outputs the given array as an Elixir tuple, instead of
|
||||
the default Elixir list
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>mkMap attrset</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Outputs the given attribute set as an Elixir map,
|
||||
instead of the default Elixir keyword list
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para xml:id="pkgs-formats-result">
|
||||
These functions all return an attribute set with these values:
|
||||
@ -152,6 +243,19 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>lib</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Utility functions for convenience, or special interactions
|
||||
with the format. This attribute is optional. It may contain
|
||||
inside a <literal>types</literal> attribute containing types
|
||||
specific to this format.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>generate</literal>
|
||||
|
131
nixos/doc/manual/from_md/development/unit-handling.section.xml
Normal file
131
nixos/doc/manual/from_md/development/unit-handling.section.xml
Normal file
@ -0,0 +1,131 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-unit-handling">
|
||||
<title>Unit handling</title>
|
||||
<para>
|
||||
To figure out what units need to be
|
||||
started/stopped/restarted/reloaded, the script first checks the
|
||||
current state of the system, similar to what
|
||||
<literal>systemctl list-units</literal> shows. For each of the
|
||||
units, the script goes through the following checks:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Is the unit file still in the new system? If not,
|
||||
<emphasis role="strong">stop</emphasis> the service unless it
|
||||
sets <literal>X-StopOnRemoval</literal> in the
|
||||
<literal>[Unit]</literal> section to <literal>false</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Is it a <literal>.target</literal> unit? If so,
|
||||
<emphasis role="strong">start</emphasis> it unless it sets
|
||||
<literal>RefuseManualStart</literal> in the
|
||||
<literal>[Unit]</literal> section to <literal>true</literal> or
|
||||
<literal>X-OnlyManualStart</literal> in the
|
||||
<literal>[Unit]</literal> section to <literal>true</literal>.
|
||||
Also <emphasis role="strong">stop</emphasis> the unit again
|
||||
unless it sets <literal>X-StopOnReconfiguration</literal> to
|
||||
<literal>false</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Are the contents of the unit files different? They are compared
|
||||
by parsing them and comparing their contents. If they are
|
||||
different but only <literal>X-Reload-Triggers</literal> in the
|
||||
<literal>[Unit]</literal> section is changed,
|
||||
<emphasis role="strong">reload</emphasis> the unit. The NixOS
|
||||
module system allows setting these triggers with the option
|
||||
<link linkend="opt-systemd.services">systemd.services.<name>.reloadTriggers</link>.
|
||||
There are some additional keys in the <literal>[Unit]</literal>
|
||||
section that are ignored as well. If the unit files differ in
|
||||
any way, the following actions are performed:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>.path</literal> and <literal>.slice</literal> units
|
||||
are ignored. There is no need to restart them since changes
|
||||
in their values are applied by systemd when systemd is
|
||||
reloaded.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>.mount</literal> units are
|
||||
<emphasis role="strong">reload</emphasis>ed. These mostly
|
||||
come from the <literal>/etc/fstab</literal> parser.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>.socket</literal> units are currently ignored. This
|
||||
is to be fixed at a later point.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The rest of the units (mostly <literal>.service</literal>
|
||||
units) are then <emphasis role="strong">reload</emphasis>ed
|
||||
if <literal>X-ReloadIfChanged</literal> in the
|
||||
<literal>[Service]</literal> section is set to
|
||||
<literal>true</literal> (exposed via
|
||||
<link linkend="opt-systemd.services">systemd.services.<name>.reloadIfChanged</link>).
|
||||
A little exception is done for units that were deactivated
|
||||
in the meantime, for example because they require a unit
|
||||
that got stopped before. These are
|
||||
<emphasis role="strong">start</emphasis>ed instead of
|
||||
reloaded.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
If the reload flag is not set, some more flags decide if the
|
||||
unit is skipped. These flags are
|
||||
<literal>X-RestartIfChanged</literal> in the
|
||||
<literal>[Service]</literal> section (exposed via
|
||||
<link linkend="opt-systemd.services">systemd.services.<name>.restartIfChanged</link>),
|
||||
<literal>RefuseManualStop</literal> in the
|
||||
<literal>[Unit]</literal> section, and
|
||||
<literal>X-OnlyManualStart</literal> in the
|
||||
<literal>[Unit]</literal> section.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Further behavior depends on the unit having
|
||||
<literal>X-StopIfChanged</literal> in the
|
||||
<literal>[Service]</literal> section set to
|
||||
<literal>true</literal> (exposed via
|
||||
<link linkend="opt-systemd.services">systemd.services.<name>.stopIfChanged</link>).
|
||||
This is set to <literal>true</literal> by default and must
|
||||
be explicitly turned off if not wanted. If the flag is
|
||||
enabled, the unit is
|
||||
<emphasis role="strong">stop</emphasis>ped and then
|
||||
<emphasis role="strong">start</emphasis>ed. If not, the unit
|
||||
is <emphasis role="strong">restart</emphasis>ed. The goal of
|
||||
the flag is to make sure that the new unit never runs in the
|
||||
old environment which is still in place before the
|
||||
activation script is run. This behavior is different when
|
||||
the service is socket-activated, as outlined in the
|
||||
following steps.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The last thing that is taken into account is whether the
|
||||
unit is a service and socket-activated. If
|
||||
<literal>X-StopIfChanged</literal> is
|
||||
<emphasis role="strong">not</emphasis> set, the service is
|
||||
<emphasis role="strong">restart</emphasis>ed with the
|
||||
others. If it is set, both the service and the socket are
|
||||
<emphasis role="strong">stop</emphasis>ped and the socket is
|
||||
<emphasis role="strong">start</emphasis>ed, leaving socket
|
||||
activation to start the service when it’s needed.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
@ -0,0 +1,122 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="sec-switching-systems">
|
||||
<title>What happens during a system switch?</title>
|
||||
<para>
|
||||
Running <literal>nixos-rebuild switch</literal> is one of the more
|
||||
common tasks under NixOS. This chapter explains some of the
|
||||
internals of this command to make it simpler for new module
|
||||
developers to configure their units correctly and to make it easier
|
||||
to understand what is happening and why for curious administrators.
|
||||
</para>
|
||||
<para>
|
||||
<literal>nixos-rebuild</literal>, like many deployment solutions,
|
||||
calls <literal>switch-to-configuration</literal> which resides in a
|
||||
NixOS system at <literal>$out/bin/switch-to-configuration</literal>.
|
||||
The script is called with the action that is to be performed like
|
||||
<literal>switch</literal>, <literal>test</literal>,
|
||||
<literal>boot</literal>. There is also the
|
||||
<literal>dry-activate</literal> action which does not really perform
|
||||
the actions but rather prints what it would do if you called it with
|
||||
<literal>test</literal>. This feature can be used to check what
|
||||
service states would be changed if the configuration was switched
|
||||
to.
|
||||
</para>
|
||||
<para>
|
||||
If the action is <literal>switch</literal> or
|
||||
<literal>boot</literal>, the bootloader is updated first so the
|
||||
configuration will be the next one to boot. Unless
|
||||
<literal>NIXOS_NO_SYNC</literal> is set to <literal>1</literal>,
|
||||
<literal>/nix/store</literal> is synced to disk.
|
||||
</para>
|
||||
<para>
|
||||
If the action is <literal>switch</literal> or
|
||||
<literal>test</literal>, the currently running system is inspected
|
||||
and the actions to switch to the new system are calculated. This
|
||||
process takes two data sources into account:
|
||||
<literal>/etc/fstab</literal> and the current systemd status. Mounts
|
||||
and swaps are read from <literal>/etc/fstab</literal> and the
|
||||
corresponding actions are generated. If a new mount is added, for
|
||||
example, the proper <literal>.mount</literal> unit is marked to be
|
||||
started. The current systemd state is inspected, the difference
|
||||
between the current system and the desired configuration is
|
||||
calculated and actions are generated to get to this state. There are
|
||||
a lot of nuances that can be controlled by the units which are
|
||||
explained here.
|
||||
</para>
|
||||
<para>
|
||||
After calculating what should be done, the actions are carried out.
|
||||
The order of actions is always the same:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
Stop units (<literal>systemctl stop</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Run activation script (<literal>$out/activate</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
See if the activation script requested more units to restart
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Restart systemd if needed
|
||||
(<literal>systemd daemon-reexec</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Forget about the failed state of units
|
||||
(<literal>systemctl reset-failed</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Reload systemd (<literal>systemctl daemon-reload</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Reload systemd user instances
|
||||
(<literal>systemctl --user daemon-reload</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Set up tmpfiles (<literal>systemd-tmpfiles --create</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Reload units (<literal>systemctl reload</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Restart units (<literal>systemctl restart</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Start units (<literal>systemctl start</literal>)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Inspect what changed during these actions and print units that
|
||||
failed and that were newly started
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Most of these actions are either self-explaining but some of them
|
||||
have to do with our units or the activation script. For this reason,
|
||||
these topics are explained in the next sections.
|
||||
</para>
|
||||
<xi:include href="unit-handling.section.xml" />
|
||||
<xi:include href="activation-script.section.xml" />
|
||||
</chapter>
|
@ -122,6 +122,25 @@
|
||||
services) and <literal>systemd.timers</literal> (the list of
|
||||
commands to be executed periodically by <literal>systemd</literal>).
|
||||
</para>
|
||||
<para>
|
||||
Care must be taken when writing systemd services using
|
||||
<literal>Exec*</literal> directives. By default systemd performs
|
||||
substitution on <literal>%<char></literal> specifiers in these
|
||||
directives, expands environment variables from
|
||||
<literal>$FOO</literal> and <literal>${FOO}</literal>, splits
|
||||
arguments on whitespace, and splits commands on
|
||||
<literal>;</literal>. All of these must be escaped to avoid
|
||||
unexpected substitution or splitting when interpolating into an
|
||||
<literal>Exec*</literal> directive, e.g. when using an
|
||||
<literal>extraArgs</literal> option to pass additional arguments to
|
||||
the service. The functions
|
||||
<literal>utils.escapeSystemdExecArg</literal> and
|
||||
<literal>utils.escapeSystemdExecArgs</literal> are provided for
|
||||
this, see <link linkend="exec-escaping-example">Example: Escaping in
|
||||
Exec directives</link> for an example. When using these functions
|
||||
system environment substitution should <emphasis>not</emphasis> be
|
||||
disabled explicitly.
|
||||
</para>
|
||||
<anchor xml:id="locate-example" />
|
||||
<para>
|
||||
<emphasis role="strong">Example: NixOS Module for the
|
||||
@ -183,6 +202,36 @@ in {
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<anchor xml:id="exec-escaping-example" />
|
||||
<para>
|
||||
<emphasis role="strong">Example: Escaping in Exec
|
||||
directives</emphasis>
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
{ config, lib, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.echo;
|
||||
echoAll = pkgs.writeScript "echo-all" ''
|
||||
#! ${pkgs.runtimeShell}
|
||||
for s in "$@"; do
|
||||
printf '%s\n' "$s"
|
||||
done
|
||||
'';
|
||||
args = [ "a%Nything" "lang=\${LANG}" ";" "/bin/sh -c date" ];
|
||||
in {
|
||||
systemd.services.echo =
|
||||
{ description = "Echo to the journal";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.ExecStart = ''
|
||||
${echoAll} ${utils.escapeSystemdExecArgs args}
|
||||
'';
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<xi:include href="option-declarations.section.xml" />
|
||||
<xi:include href="option-types.section.xml" />
|
||||
|
@ -261,6 +261,19 @@ start_all()
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_console</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Send keys to the kernel console. This allows interaction
|
||||
with the systemd emergency mode, for example. Takes a string
|
||||
that is sent, e.g.,
|
||||
<literal>send_console("\n\nsystemctl default\n")</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>execute</literal>
|
||||
@ -502,6 +515,21 @@ machine.systemctl("list-jobs --no-pager", "any-user") # spaw
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>console_interact</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allows you to directly interact with QEMU’s stdin. This
|
||||
should only be used during test development, not in
|
||||
production tests. Output from QEMU is only read line-wise.
|
||||
<literal>Ctrl-c</literal> kills QEMU and
|
||||
<literal>Ctrl-d</literal> closes console and returns to the
|
||||
test runner.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
To test user units declared by
|
||||
|
@ -7,11 +7,11 @@
|
||||
<para>
|
||||
These instructions assume that you have an existing PXE or iPXE
|
||||
infrastructure and simply want to add the NixOS installer as another
|
||||
option. To build the necessary files from a recent version of
|
||||
option. To build the necessary files from your current version of
|
||||
nixpkgs, you can run:
|
||||
</para>
|
||||
<programlisting>
|
||||
nix-build -A netboot.x86_64-linux nixos/release.nix
|
||||
nix-build -A netboot.x86_64-linux '<nixpkgs/nixos/release.nix>'
|
||||
</programlisting>
|
||||
<para>
|
||||
This will create a <literal>result</literal> directory containing: *
|
||||
|
@ -26,8 +26,36 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>iptables</literal> now uses
|
||||
<literal>nf_tables</literal> backend.
|
||||
<literal>iptables</literal> is now using
|
||||
<literal>nf_tables</literal> under the hood, by using
|
||||
<literal>iptables-nft</literal>, similar to
|
||||
<link xlink:href="https://wiki.debian.org/nftables#Current_status">Debian</link>
|
||||
and
|
||||
<link xlink:href="https://fedoraproject.org/wiki/Changes/iptables-nft-default">Fedora</link>.
|
||||
This means, <literal>ip[6]tables</literal>,
|
||||
<literal>arptables</literal> and <literal>ebtables</literal>
|
||||
commands will actually show rules from some specific tables in
|
||||
the <literal>nf_tables</literal> kernel subsystem. In case
|
||||
you’re migrating from an older release without rebooting,
|
||||
there might be cases where you end up with iptable rules
|
||||
configured both in the legacy <literal>iptables</literal>
|
||||
kernel backend, as well as in the <literal>nf_tables</literal>
|
||||
backend. This can lead to confusing firewall behaviour. An
|
||||
<literal>iptables-save</literal> after switching will complain
|
||||
about <quote>iptables-legacy tables present</quote>. It’s
|
||||
probably best to reboot after the upgrade, or manually
|
||||
removing all legacy iptables rules (via the
|
||||
<literal>iptables-legacy</literal> package).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
systemd got an <literal>nftables</literal> backend, and
|
||||
configures (networkd) rules in their own
|
||||
<literal>io.systemd.*</literal> tables. Check
|
||||
<literal>nft list ruleset</literal> to see these rules, not
|
||||
<literal>iptables-save</literal> (which only shows
|
||||
<literal>iptables</literal>-created rules.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@ -1429,6 +1457,17 @@ Superuser created successfully.
|
||||
knob.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>/usr</literal> will always be included in the initial
|
||||
ramdisk. See the
|
||||
<literal>fileSystems.<name>.neededForBoot</literal>
|
||||
option. If any files exist under <literal>/usr</literal>
|
||||
(which is not typical for NixOS), they will be included in the
|
||||
initial ramdisk, increasing its size to a possibly problematic
|
||||
extent.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-21.11-notable-changes">
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user