Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Bantyev
ff8fd21304 nixos-rebuild: use sudo when whoami != root
Currently, executing `nixos-rebuild switch` as a non-root user will
result in a somewhat confusing error about being unable to link a
profile to a nix store path. This is not ideal, especially as we already
have most of the code to handle this properly and use `sudo` to elevate
permissions to install.

This is preferrable for flakes (better eval caching), and also more
intuitive for new users.
2023-02-17 19:14:51 +04:00
11632 changed files with 175031 additions and 793073 deletions

View File

@@ -95,9 +95,3 @@ trim_trailing_whitespace = unset
[pkgs/tools/misc/timidity/timidity.cfg]
trim_trailing_whitespace = unset
[pkgs/tools/virtualization/ovftool/*.ova]
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
charset = unset

1
.gitattributes vendored
View File

@@ -1,6 +1,5 @@
**/deps.nix linguist-generated
**/deps.json linguist-generated
**/deps.toml lingust-generated
**/node-packages.nix linguist-generated
pkgs/applications/editors/emacs-modes/*-generated.nix linguist-generated

15
.github/CODEOWNERS vendored
View File

@@ -45,7 +45,6 @@
/pkgs/build-support/setup-hooks @Ericson2314
/pkgs/build-support/setup-hooks/auto-patchelf.sh @layus
/pkgs/build-support/setup-hooks/auto-patchelf.py @layus
/pkgs/pkgs-lib @infinisil
# Nixpkgs build-support
/pkgs/build-support/writers @lassulus @Profpatsch
@@ -90,9 +89,6 @@
# NixOS integration test driver
/nixos/lib/test-driver @tfc
# NixOS QEMU virtualisation
/nixos/virtualisation/qemu-vm.nix @raitobezarius
# Systemd
/nixos/modules/system/boot/systemd.nix @NixOS/systemd
/nixos/modules/system/boot/systemd @NixOS/systemd
@@ -108,7 +104,9 @@
# Python-related code and docs
/maintainers/scripts/update-python-libraries @FRidh
/pkgs/top-level/python-packages.nix @FRidh @jonringer
/pkgs/development/interpreters/python @FRidh
/pkgs/development/python-modules @FRidh @jonringer
/doc/languages-frameworks/python.section.md @FRidh @mweinelt
/pkgs/development/tools/poetry2nix @adisbladis
/pkgs/development/interpreters/python/hooks @FRidh @jonringer
@@ -136,13 +134,13 @@
/pkgs/development/ruby-modules @marsam
# Rust
/pkgs/development/compilers/rust @Mic92 @zowoq @winterqt @figsoda
/pkgs/development/compilers/rust @Mic92 @LnL7 @zowoq @winterqt @figsoda
/pkgs/build-support/rust @zowoq @winterqt @figsoda
/doc/languages-frameworks/rust.section.md @zowoq @winterqt @figsoda
# C compilers
/pkgs/development/compilers/gcc @matthewbauer
/pkgs/development/compilers/llvm @matthewbauer @RaitoBezarius
/pkgs/development/compilers/llvm @matthewbauer
# Compatibility stuff
/pkgs/top-level/unix-tools.nix @matthewbauer
@@ -313,8 +311,3 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/build-support/node/build-npm-package @winterqt
/pkgs/build-support/node/fetch-npm-deps @winterqt
/doc/languages-frameworks/javascript.section.md @winterqt
# OCaml
/pkgs/build-support/ocaml @romildo @ulrikstrid
/pkgs/development/compilers/ocaml @romildo @ulrikstrid
/pkgs/development/ocaml-modules @romildo @ulrikstrid

View File

@@ -24,10 +24,9 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
uses: korthout/backport-action@v1.2.0
uses: korthout/backport-action@v1.1.0
with:
# Config README: https://github.com/korthout/backport-action#backport-action
copy_labels_pattern: 'severity:\ssecurity'
pull_description: |-
Bot-based backport to `${target_branch}`, triggered by a label in #${pull_number}.

View File

@@ -19,7 +19,7 @@ jobs:
# we don't limit this action to only NixOS repo since the checks are cheap and useful developer feedback
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v20
- uses: cachix/install-nix-action@v19
- uses: cachix/cachix-action@v12
with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.

View File

@@ -1,24 +0,0 @@
name: "Check that maintainer list is sorted"
on:
pull_request_target:
paths:
- 'maintainers/maintainer-list.nix'
permissions:
contents: read
jobs:
nixos:
runs-on: ubuntu-latest
if: github.repository_owner == 'NixOS'
steps:
- uses: actions/checkout@v3
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v20
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true
- name: Check that maintainer-list.nix is sorted
run: nix-instantiate --eval maintainers/scripts/check-maintainers-sorted.nix

View File

@@ -28,14 +28,16 @@ jobs:
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v20
- uses: cachix/install-nix-action@v19
with:
# nixpkgs commit is pinned so that it doesn't break
# editorconfig-checker 2.4.0
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/c473cc8714710179df205b153f4e9fa007107ff9.tar.gz
- name: install editorconfig-checker
run: nix-env -iA editorconfig-checker -f '<nixpkgs>'
- name: Checking EditorConfig
run: |
cat "$HOME/changed_files" | nix-shell -p editorconfig-checker --run 'xargs -r editorconfig-checker -disable-indent-size'
cat "$HOME/changed_files" | xargs -r editorconfig-checker -disable-indent-size
- if: ${{ failure() }}
run: |
echo "::error :: Hey! It looks like your changes don't follow our editorconfig settings. Read https://editorconfig.org/#download to configure your editor so you never see this error again."

View File

@@ -18,7 +18,7 @@ jobs:
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v20
- uses: cachix/install-nix-action@v19
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true

View File

@@ -8,7 +8,6 @@ on:
- master
paths:
- 'doc/**'
- 'lib/**'
jobs:
nixpkgs:
@@ -19,7 +18,7 @@ jobs:
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v20
- uses: cachix/install-nix-action@v19
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v20
- uses: cachix/install-nix-action@v19
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true
@@ -54,7 +54,7 @@ jobs:
# less noisy until all nixpkgs pull requests have stopped using
# docbook for option docs.
- name: Comment on failure
uses: peter-evans/create-or-update-comment@v3
uses: peter-evans/create-or-update-comment@v2
if: ${{ failure() && steps.check.conclusion == 'failure' }}
with:
issue-number: 189318

View File

@@ -51,7 +51,7 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on failure
uses: peter-evans/create-or-update-comment@v3
uses: peter-evans/create-or-update-comment@v2
if: ${{ failure() }}
with:
issue-number: 105153

View File

@@ -49,7 +49,7 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on failure
uses: peter-evans/create-or-update-comment@v3
uses: peter-evans/create-or-update-comment@v2
if: ${{ failure() }}
with:
issue-number: 105153

View File

@@ -12,12 +12,12 @@ jobs:
tf-providers:
permissions:
contents: write # for peter-evans/create-pull-request to create branch
pull-requests: write # for peter-evans/create-pull-request to create a PR
pull-requests: write # for peter-evans/create-pull-request to create a PR, for peter-evans/create-or-update-comment to create or update comment
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@v3
- uses: cachix/install-nix-action@v20
- uses: cachix/install-nix-action@v19
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
- name: setup
@@ -36,33 +36,21 @@ jobs:
--argstr keep-going true \
--argstr max-workers 2 \
--argstr path terraform-providers
- name: get failed updates
run: |
echo 'FAILED<<EOF' >> $GITHUB_ENV
git ls-files --others >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
# cleanup logs of failed updates so they aren't included in the PR
- name: clean repo
run: |
git clean -f
- name: create PR
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v4
with:
body: |
Automatic update by [update-terraform-providers](https://github.com/NixOS/nixpkgs/blob/master/.github/workflows/update-terraform-providers.yml) action.
https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}
These providers failed to update:
```
${{ env.FAILED }}
```
Check that all providers build with:
```
@ofborg build terraform.full
```
If there is more than ten commits in the PR `ofborg` won't build it automatically and you will need to use the above command.
branch: terraform-providers-update
delete-branch: false
title: ${{ steps.setup.outputs.title }}

View File

@@ -43,7 +43,6 @@ Below is a short excerpt of some points in there:
* Not start with the package name.
* More generally, it should not refer to the package name.
* Not end with a period (or any punctuation for that matter).
* Aim to inform while avoiding subjective language.
* `meta.license` must be set and fit the upstream license.
* If there is no upstream license, `meta.license` should default to `lib.licenses.unfree`.
* If in doubt, try to contact the upstream developers for clarification.

3
doc/.gitignore vendored
View File

@@ -6,6 +6,3 @@ functions/library/locations.xml
highlightjs
manual-full.xml
out
result
result-*
media

View File

@@ -19,9 +19,6 @@ pandoc_flags = --extract-media=$(pandoc_media_dir) \
.PHONY: all
all: validate format out/html/index.html out/epub/manual.epub
.PHONY: render-md
render-md: ${MD_TARGETS}
.PHONY: debug
debug:
nix-shell --run "xmloscopy --docbook5 ./manual.xml ./manual-full.xml"

View File

@@ -3,7 +3,7 @@
Building software with Nix often requires downloading source code and other files from the internet.
`nixpkgs` provides *fetchers* for different protocols and services. Fetchers are functions that simplify downloading files.
## Caveats {#chap-pkgs-fetchers-caveats}
## Caveats
Fetchers create [fixed output derivations](https://nixos.org/manual/nix/stable/#fixed-output-drvs) from downloaded files.
Nix can reuse the downloaded files via the hash of the resulting derivation.
@@ -71,7 +71,6 @@ The main difference between `fetchurl` and `fetchzip` is in how they store the c
- `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.
- `decode`: Pipe the downloaded data through this command before processing it as a patch.
- `extraPrefix`: Prefix pathnames by this string.
- `excludes`: Exclude files matching these patterns (applies after the above arguments).
- `includes`: Include only files matching these patterns (applies after the above arguments).

View File

@@ -6,7 +6,7 @@ Nix packages are most commonly shared between machines using [HTTP, SSH, or S3](
Note that this function is meant for advanced use-cases. The more idiomatic way to work with flat-file binary caches is via the [nix-copy-closure](https://nixos.org/manual/nix/stable/command-ref/nix-copy-closure.html) command. You may also want to consider [dockerTools](#sec-pkgs-dockerTools) for your containerization needs.
## Example {#sec-pkgs-binary-cache-example}
## Example
The following derivation will construct a flat-file binary cache containing the closure of `hello`.

View File

@@ -410,7 +410,7 @@ If the derivation is fully buildable (i.e. `nix-build` can be used on it), runni
The behavior doesn't match `nix-shell` or `nix-build` exactly and this function is known not to work correctly for e.g. fixed-output derivations, content-addressed derivations, impure derivations and other special types of derivations.
:::
### Arguments {#ssec-pkgs-dockerTools-buildNixShellImage-arguments}
### Arguments
`drv`
@@ -473,7 +473,7 @@ The behavior doesn't match `nix-shell` or `nix-build` exactly and this function
*Default:* (none)
### Example {#ssec-pkgs-dockerTools-buildNixShellImage-example}
### Example
The following shows how to build the `pkgs.hello` package inside a Docker container built with `buildNixShellImage`.

View File

@@ -12,12 +12,12 @@ Whereas for many web servers, applications, it is possible to work with a Nix st
NixOS tests also use this function when preparing the VM. The `cptofs` method is used when `virtualisation.useBootLoader` is false (the default). Otherwise the second method is used.
## Features {#sec-make-disk-image-features}
## Features
For reference, read the function signature source code for documentation on arguments: <https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/make-disk-image.nix>.
Features are separated in various sections depending on if you opt for a Nix-store only image or a full NixOS image.
### Common {#sec-make-disk-image-features-common}
### Common
- arbitrary NixOS configuration
- automatic or bound disk size: `diskSize` parameter, `additionalSpace` can be set when `diskSize` is `auto` to add a constant of disk space
@@ -29,7 +29,7 @@ Features are separated in various sections depending on if you opt for a Nix-sto
- the current nixpkgs can be realized as a channel in the disk image, which will change the hash of the image when the sources are updated
- additional store paths can be provided through `additionalPaths`
### Full NixOS image {#sec-make-disk-image-features-full-image}
### Full NixOS image
- arbitrary contents with permissions can be placed in the target filesystem using `contents`
- a `/etc/nixpkgs/nixos/configuration.nix` can be provided through `configFile`
@@ -37,7 +37,7 @@ Features are separated in various sections depending on if you opt for a Nix-sto
- EFI variables can be mutated during image production and the result is exposed in `$out`
- boot partition size when partition table is `efi` or `hybrid`
### On bit-to-bit reproducibility {#sec-make-disk-image-features-reproducibility}
### On bit-to-bit reproducibility
Images are **NOT** deterministic, please do not hesitate to try to fix this, source of determinisms are (not exhaustive) :
@@ -47,7 +47,7 @@ Images are **NOT** deterministic, please do not hesitate to try to fix this, sou
A `deterministic` flag is available for best efforts determinism.
## Usage {#sec-make-disk-image-usage}
## Usage
To produce a Nix-store only image:
```nix
@@ -101,7 +101,6 @@ in
diskSize = "auto";
additionalSpace = "0M"; # Defaults to 512M.
copyChannel = false;
memSize = 2048; # Qemu VM memory size in megabytes. Defaults to 1024M.
}
```

View File

@@ -6,8 +6,6 @@
This chapter describes several special builders.
</para>
<xi:include href="special/fhs-environments.section.xml" />
<xi:include href="special/makesetuphook.section.xml" />
<xi:include href="special/mkshell.section.xml" />
<xi:include href="special/darwin-builder.section.xml" />
<xi:include href="special/vm-tools.section.xml" />
</chapter>

View File

@@ -61,89 +61,3 @@ builders-use-substitutes = true
```ShellSession
$ sudo launchctl kickstart -k system/org.nixos.nix-daemon
```
## Example flake usage
```
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-22.11-darwin";
darwin.url = "github:lnl7/nix-darwin/master";
darwin.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, darwin, nixpkgs, ... }@inputs:
let
inherit (darwin.lib) darwinSystem;
system = "aarch64-darwin";
pkgs = nixpkgs.legacyPackages."${system}";
linuxSystem = builtins.replaceStrings [ "darwin" ] [ "linux" ] system;
darwin-builder = nixpkgs.lib.nixosSystem {
system = linuxSystem;
modules = [
"${nixpkgs}/nixos/modules/profiles/macos-builder.nix"
{ virtualisation.host.pkgs = pkgs; }
];
};
in {
darwinConfigurations = {
machine1 = darwinSystem {
inherit system;
modules = [
{
nix.distributedBuilds = true;
nix.buildMachines = [{
hostName = "ssh://builder@localhost";
system = linuxSystem;
maxJobs = 4;
supportedFeatures = [ "kvm" "benchmark" "big-parallel" ];
}];
launchd.daemons.darwin-builder = {
command = "${darwin-builder.config.system.build.macos-builder-installer}/bin/create-builder";
serviceConfig = {
KeepAlive = true;
RunAtLoad = true;
StandardOutPath = "/var/log/darwin-builder.log";
StandardErrorPath = "/var/log/darwin-builder.log";
};
};
}
];
};
};
};
}
```
## Reconfiguring the builder
Initially you should not change the builder configuration else you will not be
able to use the binary cache. However, after you have the builder running locally
you may use it to build a modified builder with additional storage or memory.
To do this, you just need to set the `virtualisation.darwin-builder.*` parameters as
in the example below and rebuild.
```
darwin-builder = nixpkgs.lib.nixosSystem {
system = linuxSystem;
modules = [
"${nixpkgs}/nixos/modules/profiles/macos-builder.nix"
{
virtualisation.host.pkgs = pkgs;
virtualisation.darwin-builder.diskSize = 5120;
virtualisation.darwin-builder.memorySize = 1024;
virtualisation.darwin-builder.hostPort = 33022;
virtualisation.darwin-builder.workingDirectory = "/var/lib/darwin-builder";
}
];
```
You may make any other changes to your VM in this attribute set. For example,
you could enable Docker or X11 forwarding to your Darwin host.

View File

@@ -1,6 +1,6 @@
# buildFHSEnv {#sec-fhs-environments}
# buildFHSUserEnv {#sec-fhs-environments}
`buildFHSEnv` provides a way to build and run FHS-compatible lightweight sandboxes. It creates an isolated root with bound `/nix/store`, so its footprint in terms of disk space needed is quite small. This allows one to run software which is hard or unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions, games distributed as tarballs, software with integrity checking and/or external self-updated binaries. It uses Linux namespaces feature to create temporary lightweight environments which are destroyed after all child processes exit, without root user rights requirement. Accepted arguments are:
`buildFHSUserEnv` provides a way to build and run FHS-compatible lightweight sandboxes. It creates an isolated root with bound `/nix/store`, so its footprint in terms of disk space needed is quite small. This allows one to run software which is hard or unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions, games distributed as tarballs, software with integrity checking and/or external self-updated binaries. It uses Linux namespaces feature to create temporary lightweight environments which are destroyed after all child processes exit, without root user rights requirement. Accepted arguments are:
- `name`
Environment name.
@@ -26,7 +26,7 @@ One can create a simple environment using a `shell.nix` like that:
```nix
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSEnv {
(pkgs.buildFHSUserEnv {
name = "simple-x11-env";
targetPkgs = pkgs: (with pkgs;
[ udev

View File

@@ -1,37 +0,0 @@
# pkgs.makeSetupHook {#sec-pkgs.makeSetupHook}
`pkgs.makeSetupHook` is a builder that produces hooks that go in to `nativeBuildInputs`
## Usage {#sec-pkgs.makeSetupHook-usage}
```nix
pkgs.makeSetupHook {
name = "something-hook";
propagatedBuildInputs = [ pkgs.commandsomething ];
depsTargetTargetPropagated = [ pkgs.libsomething ];
} ./script.sh
```
#### setup hook that depends on the hello package and runs hello and @shell@ is substituted with path to bash {#sec-pkgs.makeSetupHook-usage-example}
```nix
pkgs.makeSetupHook {
name = "run-hello-hook";
propagatedBuildInputs = [ pkgs.hello ];
substitutions = { shell = "${pkgs.bash}/bin/bash"; };
passthru.tests.greeting = callPackage ./test { };
meta.platforms = lib.platforms.linux;
} (writeScript "run-hello-hook.sh" ''
#!@shell@
hello
'')
```
## Attributes {#sec-pkgs.makeSetupHook-attributes}
* `name` Set the name of the hook.
* `propagatedBuildInputs` Runtime dependencies (such as binaries) of the hook.
* `depsTargetTargetPropagated` Non-binary dependencies.
* `meta`
* `passthru`
* `substitutions` Variables for `substituteAll`

View File

@@ -20,7 +20,7 @@ pkgs.mkShell {
}
```
## Attributes {#sec-pkgs-mkShell-attributes}
## Attributes
* `name` (default: `nix-shell`). Set the name of the derivation.
* `packages` (default: `[]`). Add executable packages to the `nix-shell` environment.
@@ -29,7 +29,7 @@ pkgs.mkShell {
... all the attributes of `stdenv.mkDerivation`.
## Building the shell {#sec-pkgs-mkShell-building}
## Building the shell
This derivation output will contain a text file that contains a reference to
all the build inputs. This is useful in CI where we want to make sure that

View File

@@ -1,148 +0,0 @@
# vmTools {#sec-vm-tools}
A set of VM related utilities, that help in building some packages in more advanced scenarios.
## `vmTools.createEmptyImage` {#vm-tools-createEmptyImage}
A bash script fragment that produces a disk image at `destination`.
### Attributes
* `size`. The disk size, in MiB.
* `fullName`. Name that will be written to `${destination}/nix-support/full-name`.
* `destination` (optional, default `$out`). Where to write the image files.
## `vmTools.runInLinuxVM` {#vm-tools-runInLinuxVM}
Run a derivation in a Linux virtual machine (using Qemu/KVM).
By default, there is no disk image; the root filesystem is a `tmpfs`, and the Nix store is shared with the host (via the [9P protocol](https://wiki.qemu.org/Documentation/9p#9p_Protocol)).
Thus, any pure Nix derivation should run unmodified.
If the build fails and Nix is run with the `-K/--keep-failed` option, a script `run-vm` will be left behind in the temporary build directory that allows you to boot into the VM and debug it interactively.
### Attributes
* `preVM` (optional). Shell command to be evaluated *before* the VM is started (i.e., on the host).
* `memSize` (optional, default `512`). The memory size of the VM in MiB.
* `diskImage` (optional). A file system image to be attached to `/dev/sda`.
Note that currently we expect the image to contain a filesystem, not a full disk image with a partition table etc.
### Examples
Build the derivation hello inside a VM:
```nix
{ pkgs }: with pkgs; with vmTools;
runInLinuxVM hello
```
Build inside a VM with extra memory:
```nix
{ pkgs }: with pkgs; with vmTools;
runInLinuxVM (hello.overrideAttrs (_: { memSize = 1024; }))
```
Use VM with a disk image (implicitly sets `diskImage`, see [`vmTools.createEmptyImage`](#vm-tools-createEmptyImage)):
```nix
{ pkgs }: with pkgs; with vmTools;
runInLinuxVM (hello.overrideAttrs (_: {
preVM = createEmptyImage {
size = 1024;
fullName = "vm-image";
};
}))
```
## `vmTools.extractFs` {#vm-tools-extractFs}
Takes a file, such as an ISO, and extracts its contents into the store.
### Attributes
* `file`. Path to the file to be extracted.
Note that currently we expect the image to contain a filesystem, not a full disk image with a partition table etc.
* `fs` (optional). Filesystem of the contents of the file.
### Examples
Extract the contents of an ISO file:
```nix
{ pkgs }: with pkgs; with vmTools;
extractFs { file = ./image.iso; }
```
## `vmTools.extractMTDfs` {#vm-tools-extractMTDfs}
Like [](#vm-tools-extractFs), but it makes use of a [Memory Technology Device (MTD)](https://en.wikipedia.org/wiki/Memory_Technology_Device).
## `vmTools.runInLinuxImage` {#vm-tools-runInLinuxImage}
Like [](#vm-tools-runInLinuxVM), but instead of using `stdenv` from the Nix store, run the build using the tools provided by `/bin`, `/usr/bin`, etc. from the specified filesystem image, which typically is a filesystem containing a [FHS](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard)-based Linux distribution.
## `vmTools.makeImageTestScript` {#vm-tools-makeImageTestScript}
Generate a script that can be used to run an interactive session in the given image.
### Examples
Create a script for running a Fedora 27 VM:
```nix
{ pkgs }: with pkgs; with vmTools;
makeImageTestScript diskImages.fedora27x86_64
```
Create a script for running an Ubuntu 20.04 VM:
```nix
{ pkgs }: with pkgs; with vmTools;
makeImageTestScript diskImages.ubuntu2004x86_64
```
## `vmTools.diskImageFuns` {#vm-tools-diskImageFuns}
A set of functions that build a predefined set of minimal Linux distributions images.
### Images
* Fedora
* `fedora26x86_64`
* `fedora27x86_64`
* CentOS
* `centos6i386`
* `centos6x86_64`
* `centos7x86_64`
* Ubuntu
* `ubuntu1404i386`
* `ubuntu1404x86_64`
* `ubuntu1604i386`
* `ubuntu1604x86_64`
* `ubuntu1804i386`
* `ubuntu1804x86_64`
* `ubuntu2004i386`
* `ubuntu2004x86_64`
* `ubuntu2204i386`
* `ubuntu2204x86_64`
* Debian
* `debian10i386`
* `debian10x86_64`
* `debian11i386`
* `debian11x86_64`
### Attributes
* `size` (optional, defaults to `4096`). The size of the image, in MiB.
* `extraPackages` (optional). A list names of additional packages from the distribution that should be included in the image.
### Examples
8GiB image containing Firefox in addition to the default packages:
```nix
{ pkgs }: with pkgs; with vmTools;
diskImageFuns.ubuntu2004x86_64 { extraPackages = [ "firefox" ]; size = 8192; }
```
## `vmTools.diskImageExtraFuns` {#vm-tools-diskImageExtraFuns}
Shorthand for `vmTools.diskImageFuns.<attr> { extraPackages = ... }`.
## `vmTools.diskImages` {#vm-tools-diskImages}
Shorthand for `vmTools.diskImageFuns.<attr> { }`.

View File

@@ -178,7 +178,7 @@ letting NixOS invoke Nixpkgs anew.
If a test machine needs to set NixOS options under `nixpkgs`, it must set only the
`nixpkgs.pkgs` option.
### Parameter {#tester-nixosTest-parameter}
### Parameter
A [NixOS VM test network](https://nixos.org/nixos/manual/index.html#sec-nixos-tests), or path to it. Example:
@@ -200,7 +200,7 @@ A [NixOS VM test network](https://nixos.org/nixos/manual/index.html#sec-nixos-te
}
```
### Result {#tester-nixosTest-result}
### Result
A derivation that runs the VM test.

View File

@@ -454,7 +454,7 @@ In the file `pkgs/top-level/all-packages.nix` you can find fetch helpers, these
owner = "NixOS";
repo = "nix";
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
hash = "ha256-7D4m+saJjbSFP5hOwpQq2FGR2rr+psQMTcyb1ZvtXsQ=";
hash = "ha256-7D4m+saJjbSFP5hOwpQq2FGR2rr+psQMTcyb1ZvtXsQ=;
}
```

View File

@@ -290,7 +290,7 @@ Other examples of reasons are:
- The previous download links were all broken
- Crash when starting on some X11 systems
#### Acceptable backport criteria {#acceptable-backport-criteria}
#### Acceptable backport criteria
The stable branch does have some changes which cannot be backported. Most notable are breaking changes. The desire is to have stable users be uninterrupted when updating packages.

View File

@@ -20,10 +20,6 @@ in pkgs.stdenv.mkDerivation {
ln -s ${doc-support} ./doc-support/result
'';
preBuild = ''
make -j$NIX_BUILD_CORES render-md
'';
installPhase = ''
dest="$out/share/doc/nixpkgs"
mkdir -p "$(dirname "$dest")"

View File

@@ -75,7 +75,7 @@ in pkgs.runCommand "doc-support" {}
ln -s ${epub-xsl} ./epub.xsl
ln -s ${xhtml-xsl} ./xhtml.xsl
ln -s ${./xmlformat.conf} ./xmlformat.conf
ln -s ${../../nixos/doc/xmlformat.conf} ./xmlformat.conf
ln -s ${pkgs.documentation-highlighter} ./highlightjs
echo -n "${version}" > ./version

View File

@@ -1,6 +1,6 @@
{ pkgs, nixpkgs ? { }, libsets }:
let
revision = pkgs.lib.trivial.revisionWithDefault (nixpkgs.rev or "master");
revision = pkgs.lib.trivial.revisionWithDefault (nixpkgs.revision or "master");
libDefPos = prefix: set:
builtins.concatMap

View File

@@ -216,7 +216,7 @@ you can test whether it builds correctly by writing in a comment:
@ofborg build agdaPackages.iowa-stdlib
```
### Maintaining Agda packages {#agda-maintaining-packages}
### Maintaining Agda packages
As mentioned before, the aim is to have a compatible, and up-to-date package set.
These two conditions sometimes exclude each other:

View File

@@ -14,7 +14,7 @@ nixpkgs follows the [official elixir deprecation schedule](https://hexdocs.pm/el
All BEAM-related expressions are available via the top-level `beam` attribute, which includes:
- `interpreters`: a set of compilers running on the BEAM, including multiple Erlang/OTP versions (`beam.interpreters.erlang_22`, etc), Elixir (`beam.interpreters.elixir`) and LFE (Lisp Flavoured Erlang) (`beam.interpreters.lfe`).
- `interpreters`: a set of compilers running on the BEAM, including multiple Erlang/OTP versions (`beam.interpreters.erlangR22`, etc), Elixir (`beam.interpreters.elixir`) and LFE (Lisp Flavoured Erlang) (`beam.interpreters.lfe`).
- `packages`: a set of package builders (Mix and rebar3), each compiled with a specific Erlang/OTP version, e.g. `beam.packages.erlang22`.
@@ -22,7 +22,7 @@ The default Erlang compiler, defined by `beam.interpreters.erlang`, is aliased a
To create a package builder built with a custom Erlang version, use the lambda, `beam.packagesWith`, which accepts an Erlang/OTP derivation and produces a package builder similar to `beam.packages.erlang`.
Many Erlang/OTP distributions available in `beam.interpreters` have versions with ODBC and/or Java enabled or without wx (no observer support). For example, there's `beam.interpreters.erlang_22_odbc_javac`, which corresponds to `beam.interpreters.erlang_22` and `beam.interpreters.erlang_22_nox`, which corresponds to `beam.interpreters.erlang_22`.
Many Erlang/OTP distributions available in `beam.interpreters` have versions with ODBC and/or Java enabled or without wx (no observer support). For example, there's `beam.interpreters.erlangR22_odbc_javac`, which corresponds to `beam.interpreters.erlangR22` and `beam.interpreters.erlangR22_nox`, which corresponds to `beam.interpreters.erlangR22`.
## Build Tools {#build-tools}
@@ -128,7 +128,7 @@ You will need to run the build process once to fix the hash to correspond to you
###### FOD {#fixed-output-derivation}
A fixed output derivation will download mix dependencies from the internet. To ensure reproducibility, a hash will be supplied. Note that mix is relatively reproducible. An FOD generating a different hash on each run hasn't been observed (as opposed to npm where the chances are relatively high). See [elixir-ls](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/beam-modules/elixir-ls/default.nix) for a usage example of FOD.
A fixed output derivation will download mix dependencies from the internet. To ensure reproducibility, a hash will be supplied. Note that mix is relatively reproducible. An FOD generating a different hash on each run hasn't been observed (as opposed to npm where the chances are relatively high). See [elixir_ls](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/beam-modules/elixir-ls/default.nix) for a usage example of FOD.
Practical steps
@@ -154,7 +154,7 @@ Here is how your `default.nix` file would look for a phoenix project.
with import <nixpkgs> { };
let
# beam.interpreters.erlang_23 is available if you need a particular version
# beam.interpreters.erlangR23 is available if you need a particular version
packages = beam.packagesWith beam.interpreters.erlang;
pname = "your_project";
@@ -274,18 +274,18 @@ Usually, we need to create a `shell.nix` file and do our development inside of t
with pkgs;
let
elixir = beam.packages.erlang_24.elixir_1_12;
elixir = beam.packages.erlangR24.elixir_1_12;
in
mkShell {
buildInputs = [ elixir ];
}
```
### Using an overlay {#beam-using-overlays}
### Using an overlay
If you need to use an overlay to change some attributes of a derivation, e.g. if you need a bugfix from a version that is not yet available in nixpkgs, you can override attributes such as `version` (and the corresponding `hash`) and then use this overlay in your development environment:
#### `shell.nix` {#beam-using-overlays-shell.nix}
#### `shell.nix`
```nix
let

View File

@@ -4,7 +4,7 @@
[R⁵RS](https://schemers.org/Documents/Standards/R5RS/HTML/)-compliant Scheme
compiler. It includes an interactive mode and a custom package format, "eggs".
## Using Eggs {#sec-chicken-using}
## Using Eggs
Eggs described in nixpkgs are available inside the
`chickenPackages.chickenEggs` attrset. Including an egg as a build input is
@@ -22,7 +22,7 @@ might write:
Both `chicken` and its eggs have a setup hook which configures the environment
variables `CHICKEN_INCLUDE_PATH` and `CHICKEN_REPOSITORY_PATH`.
## Updating Eggs {#sec-chicken-updating-eggs}
## Updating Eggs
nixpkgs only knows about a subset of all published eggs. It uses
[egg2nix](https://github.com/the-kenny/egg2nix) to generate a
@@ -36,7 +36,7 @@ $ cd pkgs/development/compilers/chicken/5/
$ egg2nix eggs.scm > eggs.nix
```
## Adding Eggs {#sec-chicken-adding-eggs}
## Adding Eggs
When we run `egg2nix`, we obtain one collection of eggs with
mutually-compatible versions. This means that when we add new eggs, we may

View File

@@ -37,7 +37,7 @@ The recommended way of defining a derivation for a Coq library, is to use the `c
* `buildInputs` (optional), is a list of libraries and dependencies that are required to build and run the current derivation, in addition to the default one `[ coq ]`,
* `extraBuildInputs` (optional, deprecated), an additional list of derivation to add to `buildInputs`,
* `overrideBuildInputs` (optional) replaces the default list of derivation to which `buildInputs` and `extraBuildInputs` adds extras elements,
* `propagatedBuildInputs` (optional) is passed as is to `mkDerivation`, we recommend to use this for Coq libraries and Coq plugin dependencies, as this makes sure the paths of the compiled libraries and plugins will always be added to the build environments of subsequent derivation, which is necessary for Coq packages to work correctly,
* `propagatedBuildInputs` (optional) is passed as is to `mkDerivation`, we recommend to use this for Coq libraries and Coq plugin dependencies, as this makes sure the paths of the compiled libraries and plugins will always be added to the build environements of subsequent derivation, which is necessary for Coq packages to work correctly,
* `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 `nativeBuildInputs`, `buildInputs`, and `propagatedBuildInputs` to depend on the same package set Coq was built against.
* `useDuneifVersion` (optional, default to `(x: false)` uses Dune to build the package if the provided predicate evaluates to true on the version, e.g. `useDuneifVersion = versions.isGe "1.1"` will use dune if the version of the package is greater or equal to `"1.1"`,
* `useDune` (optional, defaults to `false`) uses Dune to build the package if set to true, the presence of this attribute overrides the behavior of the previous one.

View File

@@ -7,7 +7,7 @@
- do configuration akin to [Dhall Lang](https://dhall-lang.org/)
- perform data validation
## Cuelang schema quick start {#cuelang-quickstart}
## Cuelang schema quick start
Cuelang schemas are similar to JSON, here is a quick cheatsheet:
@@ -21,7 +21,7 @@ Cuelang schemas are similar to JSON, here is a quick cheatsheet:
- Read <https://cuelang.org/docs/concepts/logic/> to learn more about the semantics.
- Read <https://cuelang.org/docs/references/spec/> to learn about the language specification.
## `writeCueValidator` {#cuelang-writeCueValidator}
## `writeCueValidator`
Nixpkgs provides a `pkgs.writeCueValidator` helper, which will write a validation script based on the provided Cuelang schema.

View File

@@ -11,7 +11,7 @@ with import <nixpkgs> {};
mkShell {
name = "dotnet-env";
packages = [
dotnet-sdk
dotnet-sdk_3
];
}
```
@@ -27,57 +27,36 @@ mkShell {
name = "dotnet-env";
packages = [
(with dotnetCorePackages; combinePackages [
sdk_3_1
sdk_6_0
sdk_7_0
])
];
}
```
This will produce a dotnet installation that has the dotnet 6.0 7.0 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output:
This will produce a dotnet installation that has the dotnet 3.1 6.0 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output:
```ShellSession
$ dotnet --info
.NET SDK:
Version: 7.0.202
Commit: 6c74320bc3
.NET Core SDK (reflecting any global.json):
Version: 3.1.101
Commit: b377529961
Środowisko uruchomieniowe:
OS Name: nixos
OS Version: 23.05
OS Platform: Linux
RID: linux-x64
Base Path: /nix/store/n2pm44xq20hz7ybsasgmd7p3yh31gnh4-dotnet-sdk-7.0.202/sdk/7.0.202/
...
Host:
Version: 7.0.4
Architecture: x64
Commit: 0a396acafe
.NET Core SDKs installed:
2.1.803 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/sdk]
3.0.102 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/sdk]
3.1.101 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/sdk]
.NET SDKs installed:
6.0.407 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/sdk]
7.0.202 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.15 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.4 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.15 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.4 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.15 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.15 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.2 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.1 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.15 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.2 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.1 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.NETCore.App]
```
## dotnet-sdk vs dotnetCorePackages.sdk {#dotnet-sdk-vs-dotnetcorepackages.sdk}
@@ -109,7 +88,7 @@ To package Dotnet applications, you can use `buildDotnetModule`. This has simila
* `runtimeDeps` is used to wrap libraries into `LD_LIBRARY_PATH`. This is how dotnet usually handles runtime dependencies.
* `buildType` is used to change the type of build. Possible values are `Release`, `Debug`, etc. By default, this is set to `Release`.
* `selfContainedBuild` allows to enable the [self-contained](https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-self-contained) build flag. By default, it is set to false and generated applications have a dependency on the selected dotnet runtime. If enabled, the dotnet runtime is bundled into the executable and the built app has no dependency on Dotnet.
* `dotnet-sdk` is useful in cases where you need to change what dotnet SDK is being used. You can also set this to the result of `dotnetSdkPackages.combinePackages`, if the project uses multiple SDKs to build.
* `dotnet-sdk` is useful in cases where you need to change what dotnet SDK is being used.
* `dotnet-runtime` is useful in cases where you need to change what dotnet runtime is being used. This can be either a regular dotnet runtime, or an aspnetcore.
* `dotnet-test-sdk` is useful in cases where unit tests expect a different dotnet SDK. By default, this is set to the `dotnet-sdk` attribute.
* `testProjectFile` is useful in cases where the regular project file does not contain the unit tests. It gets restored and build, but not installed. You may need to regenerate your nuget lockfile after setting this.
@@ -140,8 +119,8 @@ in buildDotnetModule rec {
projectReferences = [ referencedProject ]; # `referencedProject` must contain `nupkg` in the folder structure.
dotnet-sdk = dotnetCorePackages.sdk_6.0;
dotnet-runtime = dotnetCorePackages.runtime_6_0;
dotnet-sdk = dotnetCorePackages.sdk_3_1;
dotnet-runtime = dotnetCorePackages.net_6_0;
executables = [ "foo" ]; # This wraps "$out/lib/$pname/foo" to `$out/bin/foo`.
executables = []; # Don't install any executables.

View File

@@ -56,11 +56,11 @@ See the `zlib` example:
zlib = (pkgs.zlib.override {
stdenv = pkgs.emscriptenStdenv;
}).overrideAttrs
}).overrideDerivation
(old: rec {
buildInputs = old.buildInputs ++ [ pkg-config ];
# we need to reset this setting!
env = (old.env or { }) // { NIX_CFLAGS_COMPILE = ""; };
NIX_CFLAGS_COMPILE="";
configurePhase = ''
# FIXME: Some tests require writing at $HOME
HOME=$TMPDIR

View File

@@ -116,6 +116,10 @@ For convenience, it also adds `dconf.lib` for a GIO module implementing a GSetti
- []{#ssec-gnome-hooks-gobject-introspection} `gobject-introspection` setup hook populates `GI_TYPELIB_PATH` variable with `lib/girepository-1.0` directories of dependencies, which is then added to wrapper by `wrapGAppsHook`. It also adds `share` directories of dependencies to `XDG_DATA_DIRS`, which is intended to promote GIR files but it also [pollutes the closures](https://github.com/NixOS/nixpkgs/issues/32790) of packages using `wrapGAppsHook`.
::: {.warning}
The setup hook [currently](https://github.com/NixOS/nixpkgs/issues/56943) does not work in expressions with `strictDeps` enabled, like Python packages. In those cases, you will need to disable it with `strictDeps = false;`.
:::
- []{#ssec-gnome-hooks-gst-grl-plugins} Setup hooks of `gst_all_1.gstreamer` and `grilo` will populate the `GST_PLUGIN_SYSTEM_PATH_1_0` and `GRL_PLUGIN_PATH` variables, respectively, which will then be added to the wrapper by `wrapGAppsHook`.
You can also pass additional arguments to `makeWrapper` using `gappsWrapperArgs` in `preFixup` hook:

View File

@@ -20,7 +20,6 @@ In the following is an example expression using `buildGoModule`, the following a
To obtain the actual hash, set `vendorHash = lib.fakeSha256;` and run the build ([more details here](#sec-source-hashes)).
- `proxyVendor`: Fetches (go mod download) and proxies the vendor directory. This is useful if your code depends on c code and go mod tidy does not include the needed sources to build or if any dependency has case-insensitive conflicts which will produce platform dependant `vendorHash` checksums.
- `modPostBuild`: Shell commands to run after the build of the go-modules executes `go mod vendor`, and before calculating fixed output derivation's `vendorHash` (or `vendorSha256`). Note that if you change this attribute, you need to update `vendorHash` (or `vendorSha256`) attribute.
```nix
pet = buildGoModule rec {
@@ -115,16 +114,7 @@ done
## Attributes used by the builders {#ssec-go-common-attributes}
Many attributes [controlling the build phase](#variables-controlling-the-build-phase) are respected by both `buildGoModule` and `buildGoPackage`. Note that `buildGoModule` reads the following attributes also when building the `vendor/` go-modules fixed output derivation as well:
- [`sourceRoot`](#var-stdenv-sourceRoot)
- [`prePatch`](#var-stdenv-prePatch)
- [`patches`](#var-stdenv-patches)
- [`patchFlags`](#var-stdenv-patchFlags)
- [`postPatch`](#var-stdenv-postPatch)
- [`preBuild`](#var-stdenv-preBuild)
In addition to the above attributes, and the many more variables respected also by `stdenv.mkDerivation`, both `buildGoModule` and `buildGoPackage` respect Go-specific attributes that tweak them to behave slightly differently:
Both `buildGoModule` and `buildGoPackage` can be tweaked to behave slightly differently, if the following attributes are used:
### `ldflags` {#var-go-ldflags}

View File

@@ -71,10 +71,8 @@ $ nix-env -f '<nixpkgs>' -qaP -A haskell.compiler
haskell.compiler.ghc810 ghc-8.10.7
haskell.compiler.ghc88 ghc-8.8.4
haskell.compiler.ghc90 ghc-9.0.2
haskell.compiler.ghc924 ghc-9.2.4
haskell.compiler.ghc92 ghc-9.2.4
haskell.compiler.ghc925 ghc-9.2.5
haskell.compiler.ghc926 ghc-9.2.6
haskell.compiler.ghc92 ghc-9.2.7
haskell.compiler.ghc942 ghc-9.4.2
haskell.compiler.ghc943 ghc-9.4.3
haskell.compiler.ghc94 ghc-9.4.4
@@ -88,15 +86,13 @@ haskell.compiler.ghc924Binary ghc-binary-9.2.4
haskell.compiler.ghc924BinaryMinimal ghc-binary-9.2.4
haskell.compiler.integer-simple.ghc810 ghc-integer-simple-8.10.7
haskell.compiler.integer-simple.ghc8107 ghc-integer-simple-8.10.7
haskell.compiler.integer-simple.ghc88 ghc-integer-simple-8.8.4
haskell.compiler.integer-simple.ghc884 ghc-integer-simple-8.8.4
haskell.compiler.integer-simple.ghc88 ghc-integer-simple-8.8.4
haskell.compiler.native-bignum.ghc90 ghc-native-bignum-9.0.2
haskell.compiler.native-bignum.ghc902 ghc-native-bignum-9.0.2
haskell.compiler.native-bignum.ghc92 ghc-native-bignum-9.2.4
haskell.compiler.native-bignum.ghc924 ghc-native-bignum-9.2.4
haskell.compiler.native-bignum.ghc925 ghc-native-bignum-9.2.5
haskell.compiler.native-bignum.ghc926 ghc-native-bignum-9.2.6
haskell.compiler.native-bignum.ghc92 ghc-native-bignum-9.2.7
haskell.compiler.native-bignum.ghc927 ghc-native-bignum-9.2.7
haskell.compiler.native-bignum.ghc942 ghc-native-bignum-9.4.2
haskell.compiler.native-bignum.ghc943 ghc-native-bignum-9.4.3
haskell.compiler.native-bignum.ghc94 ghc-native-bignum-9.4.4
@@ -108,16 +104,16 @@ haskell.compiler.ghcjs ghcjs-8.10.7
Each of those compiler versions has a corresponding attribute set built using
it. However, the non-standard package sets are not tested regularly and, as a
result, contain fewer working packages. The corresponding package set for GHC
9.4.5 is `haskell.packages.ghc945`. In fact `haskellPackages` is just an alias
for `haskell.packages.ghc927`:
9.4.4 is `haskell.packages.ghc944`. In fact `haskellPackages` is just an alias
for `haskell.packages.ghc924`:
```console
$ nix-env -f '<nixpkgs>' -qaP -A haskell.packages.ghc927
haskell.packages.ghc927.a50 a50-0.5
haskell.packages.ghc927.AAI AAI-0.2.0.1
haskell.packages.ghc927.aasam aasam-0.2.0.0
haskell.packages.ghc927.abacate abacate-0.0.0.0
haskell.packages.ghc927.abc-puzzle abc-puzzle-0.2.1
$ nix-env -f '<nixpkgs>' -qaP -A haskell.packages.ghc924
haskell.packages.ghc924.a50 a50-0.5
haskell.packages.ghc924.AAI AAI-0.2.0.1
haskell.packages.ghc924.aasam aasam-0.2.0.0
haskell.packages.ghc924.abacate abacate-0.0.0.0
haskell.packages.ghc924.abc-puzzle abc-puzzle-0.2.1
```
@@ -141,12 +137,7 @@ set the default version to a version older than the newest on Hackage. We do
this to get them or their reverse dependencies to compile in our package set.
4. For all packages, for which the newest Hackage version is not the default
version, there will also be a `haskellPackages.foo_x_y_z` package with the
newest version. The `x_y_z` part encodes the version with dots replaced by
underscores. When the newest version changes by a new release to Hackage the
old package will disappear under that name and be replaced by a newer one under
the name with the new version. The package name including the version will
also disappear when the default version e.g. from Stackage catches up with the
newest version from Hackage.
newest version.
5. For some packages, we also manually add other `haskellPackages.foo_x_y_z`
versions, if they are required for a certain build.
@@ -160,7 +151,7 @@ All `haskell.packages.*` package sets use the same package descriptions and the
of versions by default. There are however GHC version specific override `.nix`
files to loosen this a bit.
### Dependency resolution {#haskell-dependency-resolution}
### Dependency resolution
Normally when you build Haskell packages with `cabal-install`, `cabal-install`
does dependency resolution. It will look at all Haskell package versions known
@@ -170,14 +161,12 @@ given in the `.cabal` file of your package and all its dependencies.
The [Haskell builder in nixpkgs](#haskell-mkderivation) does no such thing.
It will simply take as input packages with names off the desired dependencies
and just check whether they fulfill the version bounds and fail if they dont
(by default, see `jailbreak` to circumvent this).
and just check whether they fulfill the version bounds and (by default, see
`jailbreak`) fail if they dont.
The `haskellPackages.callPackage` function does the package resolution.
It will, e.g., use `haskellPackages.aeson`which has the default version as
described above for a package input of name `aeson`. (More general:
`<packages>.callPackage f` will call `f` with named inputs provided from the
package set `<packages>`.)
The package resolution is done by the `haskellPackages.callPackage` function
which will, e.g., use `haskellPackages.aeson` for a package input of name
`aeson`.
While this is the default behavior, it is possible to override the dependencies
for a specific package, see
[`override` and `overrideScope`](#haskell-overriding-haskell-packages).
@@ -230,7 +219,7 @@ specification, test suites, benchmarks etc. by compiling and invoking the
package's `Setup.hs`. It does *not* use or invoke the `cabal-install` binary,
but uses the underlying `Cabal` library instead.
### General arguments {#haskell-derivation-args}
### General arguments
`pname`
: Package name, assumed to be the same as on Hackage (if applicable)
@@ -479,7 +468,7 @@ are especially useful when writing [overrides](#haskell-overriding-haskell-packa
when you want to make sure that they are definitely included. However, it is
recommended to use the more accurate ones listed above when possible.
### Meta attributes {#haskell-derivation-meta}
### Meta attributes
`haskellPackages.mkDerivation` accepts the following attributes as direct
arguments which are transparently set in `meta` of the resulting derivation. See
@@ -714,7 +703,7 @@ editor plugin to achieve this.
## Overriding Haskell packages {#haskell-overriding-haskell-packages}
### Overriding a single package {#haskell-overriding-a-single-package}
### Overriding a single package
<!-- TODO(@sternenseemann): we should document /somewhere/ that base == null etc. -->
@@ -803,7 +792,7 @@ lib.pipe my-haskell-package [
]
```
#### `haskell.lib.compose` {#haskell-haskell.lib.compose}
#### `haskell.lib.compose`
The base interface for all overriding is the following function:
@@ -826,7 +815,7 @@ following overview. Refer to the
[documentation of `haskellPackages.mkDerivation`](#haskell-mkderivation)
for a more detailed description of the effects of the respective arguments.
##### Packaging Helpers {#haskell-packaging-helpers}
##### Packaging Helpers
`overrideSrc { src, version } drv`
: Replace the source used for building `drv` with the path or derivation given
@@ -875,7 +864,7 @@ sometimes necessary when working with versioned packages in
altogether. Useful if it fails to evaluate cleanly and is causing
noise in the evaluation errors tab on Hydra.
##### Development Helpers {#haskell-development-helpers}
##### Development Helpers
`sdistTarball drv`
: Create a source distribution tarball like those found on Hackage
@@ -913,7 +902,7 @@ for debugging with e.g. `gdb`.
<!-- TODO(@sternenseemann): shellAware -->
##### Trivial Helpers {#haskell-trivial-helpers}
##### Trivial Helpers
`doJailbreak drv`
: Sets the `jailbreak` argument to `true` for `drv`.
@@ -998,7 +987,7 @@ benchmark component.
`dontCoverage drv`
: Sets the `doCoverage` argument to `false` for `drv`.
#### Library functions in the Haskell package sets {#haskell-package-set-lib-functions}
#### Library functions in the Haskell package sets
Some library functions depend on packages from the Haskell package sets. Thus they are
exposed from those instead of from `haskell.lib.compose` which can only access what is
@@ -1062,7 +1051,7 @@ it does for the unstable branches.
## F.A.Q. {#haskell-faq}
### Why is topic X not covered in this section? Why is section Y missing? {#haskell-why-not-covered}
### Why is topic X not covered in this section? Why is section Y missing?
We have been working on [moving the nixpkgs Haskell documentation back into the
nixpkgs manual](https://github.com/NixOS/nixpkgs/issues/121403). Since this

View File

@@ -25,7 +25,6 @@
<xi:include href="ios.section.xml" />
<xi:include href="java.section.xml" />
<xi:include href="javascript.section.xml" />
<xi:include href="lisp.section.xml" />
<xi:include href="lua.section.xml" />
<xi:include href="maven.section.xml" />
<xi:include href="nim.section.xml" />

View File

@@ -6,16 +6,16 @@ This contains instructions on how to package javascript applications.
The various tools available will be listed in the [tools-overview](#javascript-tools-overview). Some general principles for packaging will follow. Finally some tool specific instructions will be given.
## Getting unstuck / finding code examples {#javascript-finding-examples}
## Getting unstuck / finding code examples
If you find you are lacking inspiration for packing javascript applications, the links below might prove useful. Searching online for prior art can be helpful if you are running into solved problems.
### Github {#javascript-finding-examples-github}
### Github
- Searching Nix files for `mkYarnPackage`: <https://github.com/search?q=mkYarnPackage+language%3ANix&type=code>
- Searching just `flake.nix` files for `mkYarnPackage`: <https://github.com/search?q=mkYarnPackage+filename%3Aflake.nix&type=code>
### Gitlab {#javascript-finding-examples-gitlab}
### Gitlab
- Searching Nix files for `mkYarnPackage`: <https://gitlab.com/search?scope=blobs&search=mkYarnPackage+extension%3Anix>
- Searching just `flake.nix` files for `mkYarnPackage`: <https://gitlab.com/search?scope=blobs&search=mkYarnPackage+filename%3Aflake.nix>
@@ -105,7 +105,7 @@ After you have identified the correct system, you need to override your package
});
```
### Adding and Updating Javascript packages in nixpkgs {#javascript-adding-or-updating-packages}
### Adding and Updating Javascript packages in nixpkgs
To add a package from NPM to nixpkgs:
@@ -140,7 +140,7 @@ To update NPM packages in nixpkgs, run the same `generate.sh` script:
./pkgs/development/node-packages/generate.sh
```
#### Git protocol error {#javascript-git-error}
#### 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:
@@ -229,7 +229,7 @@ See `node2nix` [docs](https://github.com/svanderburg/node2nix) for more info.
#### Pitfalls {#javascript-node2nix-pitfalls}
- If upstream package.json does not have a "version" attribute, `node2nix` will crash. You will need to add it like shown in [the package.json section](#javascript-upstream-package-json).
- `node2nix` has some [bugs](https://github.com/svanderburg/node2nix/issues/238) related to working with lock files from NPM distributed with `nodejs_16`.
- `node2nix` has some [bugs](https://github.com/svanderburg/node2nix/issues/238) related to working with lock files from NPM distributed with `nodejs-16_x`.
- `node2nix` does not like missing packages from NPM. If you see something like `Cannot resolve version: vue-loader-v16@undefined` then you might want to try another tool. The package might have been pulled off of NPM.
### yarn2nix {#javascript-yarn2nix}
@@ -288,7 +288,7 @@ configurePhase = ''
This will generate a derivation including the `node_modules` directory.
If you have to build a derivation for an integrated web framework (rails, phoenix..), this is probably the easiest way.
#### Overriding dependency behavior {#javascript-mkYarnPackage-overriding-dependencies}
#### Overriding dependency behavior
In the `mkYarnPackage` record the property `pkgConfig` can be used to override packages when you encounter problems building.

View File

@@ -1,304 +0,0 @@
# lisp-modules {#lisp}
This document describes the Nixpkgs infrastructure for building Common Lisp
libraries that use ASDF (Another System Definition Facility). It lives in
`pkgs/development/lisp-modules`.
## Overview {#lisp-overview}
The main entry point of the API are the Common Lisp implementation packages
(e.g. `abcl`, `ccl`, `clasp-common-lisp`, `clisp` `ecl`, `sbcl`)
themselves. They have the `pkgs` and `withPackages` attributes, which can be
used to discover available packages and to build wrappers, respectively.
The `pkgs` attribute set contains packages that were automatically imported from
Quicklisp, and any other manually defined ones. Not every package works for all
the CL implementations (e.g. `nyxt` only makes sense for `sbcl`).
The `withPackages` function is of primary utility. It is used to build runnable
wrappers, with a pinned and pre-built ASDF FASL available in the `ASDF`
environment variable, and `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS`
configured to find the desired systems on runtime.
With a few exceptions, the primary thing that the infrastructure does is to run
`asdf:load-system` for each system specified in the `systems` argument to
`build-asdf-system`, and save the FASLs to the Nix store. Then, it makes these
FASLs available to wrappers. Any other use-cases, such as producing SBCL
executables with `sb-ext:save-lisp-and-die`, are achieved via overriding the
`buildPhase` etc.
In addition, Lisps have the `withOverrides` function, which can be used to
substitute any package in the scope of their `pkgs`. This will be useful
together with `overrideLispAttrs` when dealing with slashy ASDF systems, because
they should stay in the main package and be build by specifying the `systems`
argument to `build-asdf-system`.
## The 90% use case example {#lisp-use-case-example}
The most common way to use the library is to run ad-hoc wrappers like this:
`nix-shell -p 'sbcl.withPackages (ps: with ps; [ alexandria ])'`
Then, in a shell:
```
$ result/bin/sbcl
* (load (sb-ext:posix-getenv "ASDF"))
* (asdf:load-system 'alexandria)
```
Also one can create a `pkgs.mkShell` environment in `shell.nix`/`flake.nix`:
```
let
sbcl' = sbcl.withPackages (ps: [ ps.alexandria ]);
in mkShell {
buildInputs = [ sbcl' ];
}
```
Such a Lisp can be now used e.g. to compile your sources:
```
buildPhase = ''
${sbcl'}/bin/sbcl --load my-build-file.lisp
''
```
## Importing packages from Quicklisp {#lisp-importing-packages-from-quicklisp}
The library is able to very quickly import all the packages distributed by
Quicklisp by parsing its `releases.txt` and `systems.txt` files. These files are
available from [http://beta.quicklisp.org/dist/quicklisp.txt].
The import process is implemented in the `import` directory as Common Lisp
functions in the `org.lispbuilds.nix` ASDF system. To run the script, one can
execute `ql-import.lisp`:
```
nix-shell --run 'sbcl --script ql-import.lisp'
```
The script will:
1. Download the latest Quicklisp `systems.txt` and `releases.txt` files
2. Generate an SQLite database of all QL systems in `packages.sqlite`
3. Generate an `imported.nix` file from the database
The maintainer's job there is to:
1. Re-run the `ql-import.lisp` script
2. Add missing native dependencies in `ql.nix`
3. For packages that still don't build, package them manually in `packages.nix`
Also, the `imported.nix` file **must not be edited manually**! It should only be
generated as described in this section.
### Adding native dependencies {#lisp-quicklisp-adding-native-dependencies}
The Quicklisp files contain ASDF dependency data, but don't include native
library (CFFI) dependencies, and, in the case of ABCL, Java dependencies.
The `ql.nix` file contains a long list of overrides, where these dependencies
can be added.
Packages defined in `packages.nix` contain these dependencies naturally.
### Trusting `systems.txt` and `releases.txt` {#lisp-quicklisp-trusting}
The previous implementation of `lisp-modules` didn't fully trust the Quicklisp
data, because there were times where the dependencies specified were not
complete, and caused broken builds. It instead used a `nix-shell` environment to
discover real dependencies by using the ASDF APIs.
The current implementation has chosen to trust this data, because it's faster to
parse a text file than to build each system to generate its Nix file, and
because that way packages can be mass-imported. Because of that, there may come
a day where some packages will break, due to bugs in Quicklisp. In that case,
the fix could be a manual override in `packages.nix` and `ql.nix`.
A known fact is that Quicklisp doesn't include dependencies on slashy systems in
its data. This is an example of a situation where such fixes were used, e.g. to
replace the `systems` attribute of the affected packages. (See the definition of
`iolib`).
### Quirks {#lisp-quicklisp-quirks}
During Quicklisp import:
- `+` in names are converted to `_plus{_,}`: `cl+ssl`->`cl_plus_ssl`, `alexandria+`->`alexandria_plus`
- `.` to `_dot_`: `iolib.base`->`iolib_dot_base`
- names starting with a number have a `_` prepended (`3d-vectors`->`_3d-vectors`)
- `_` in names is converted to `__` for reversibility
## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside}
New packages, that for some reason are not in Quicklisp, and so cannot be
auto-imported, can be written in the `packages.nix` file.
In that file, use the `build-asdf-system` function, which is a wrapper around
`mkDerivation` for building ASDF systems. Various other hacks are present, such
as `build-with-compile-into-pwd` for systems which create files during
compilation.
The `build-asdf-system` function is documented with comments in
`nix-cl.nix`. Also, `packages.nix` is full of examples of how to use it.
## Defining packages manually outside Nixpkgs {#lisp-defining-packages-outside}
Lisp derivations (`abcl`, `sbcl` etc.) also export the `buildASDFSystem`
function, which is the same as `build-asdf-system`, except for the `lisp`
argument which is set to the given CL implementation.
It can be used to define packages outside Nixpkgs, and, for example, add them
into the package scope with `withOverrides` which will be discussed later on.
### Including an external package in scope {#lisp-including-external-pkg-in-scope}
A package defined outside Nixpkgs using `buildASDFSystem` can be woven into the
Nixpkgs-provided scope like this:
```
let
alexandria = sbcl.buildASDFSystem rec {
pname = "alexandria";
version = "1.4";
src = fetchFromGitLab {
domain = "gitlab.common-lisp.net";
owner = "alexandria";
repo = "alexandria";
rev = "v${version}";
hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
};
};
sbcl' = sbcl.withOverrides (self: super: {
inherit alexandria;
});
in sbcl'.pkgs.alexandria
```
## Overriding package attributes {#lisp-overriding-package-attributes}
Packages export the `overrideLispAttrs` function, which can be used to build a
new package with different parameters.
Example of overriding `alexandria`:
```
sbcl.pkgs.alexandria.overrideLispAttrs (oldAttrs: rec {
version = "1.4";
src = fetchFromGitLab {
domain = "gitlab.common-lisp.net";
owner = "alexandria";
repo = "alexandria";
rev = "v${version}";
hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
};
})
```
## Overriding packages in scope {#lisp-overriding-packages-in-scope}
Packages can be woven into a new scope by using `withOverrides`:
```
let
sbcl' = sbcl.withOverrides (self: super: {
alexandria = super.alexandria.overrideLispAttrs (oldAttrs: rec {
pname = "alexandria";
version = "1.4";
src = fetchFromGitLab {
domain = "gitlab.common-lisp.net";
owner = "alexandria";
repo = "alexandria";
rev = "v${version}";
hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
};
});
});
in builtins.elemAt sbcl'.pkgs.bordeaux-threads.lispLibs 0
```
### Dealing with slashy systems {#lisp-dealing-with-slashy-systems}
Slashy (secondary) systems should not exist in their own packages! Instead, they
should be included in the parent package as an extra entry in the `systems`
argument to the `build-asdf-system`/`buildASDFSystem` functions.
The reason is that ASDF searches for a secondary system in the `.asd` of the
parent package. Thus, having them separate would cause either one of them not to
load cleanly, because one will contains FASLs of itself but not the other, and
vice versa.
To package slashy systems, use `overrideLispAttrs`, like so:
```
ecl.pkgs.alexandria.overrideLispAttrs (oldAttrs: {
systems = oldAttrs.systems ++ [ "alexandria/tests" ];
lispLibs = oldAttrs.lispLibs ++ [ ecl.pkgs.rt ];
})
```
See the respective section on using `withOverrides` for how to weave it back
into `ecl.pkgs`.
Note that sometimes the slashy systems might not only have more dependencies
than the main one, but create a circular dependency between `.asd`
files. Unfortunately, in this case an adhoc solution becomes necessary.
## Building Wrappers {#lisp-building-wrappers}
Wrappers can be built using the `withPackages` function of Common Lisp
implementations (`abcl`, `ecl`, `sbcl` etc.):
```
sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ])
```
Such a wrapper can then be executed like this:
```
result/bin/sbcl
```
### Loading ASDF {#lisp-loading-asdf}
For best results, avoid calling `(require 'asdf)` When using the
library-generated wrappers.
Use `(load (ext:getenv "ASDF"))` instead, supplying your implementation's way of
getting an environment variable for `ext:getenv`. This will load the
(pre-compiled to FASL) Nixpkgs-provided version of ASDF.
### Loading systems {#lisp-loading-systems}
There, you can simply use `asdf:load-system`. This works by setting the right
values for the `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` environment
variables, so that systems are found in the Nix store and pre-compiled FASLs are
loaded.
## Adding a new Lisp {#lisp-adding-a-new-lisp}
The function `wrapLisp` is used to wrap Common Lisp implementations. It adds the
`pkgs`, `withPackages`, `withOverrides` and `buildASDFSystem` attributes to the
derivation.
`wrapLisp` takes these arguments:
- `pkg`: the Lisp package
- `faslExt`: Implementation-specific extension for FASL files
- `program`: The name of executable file in `${pkg}/bin/` (Default: `pkg.pname`)
- `flags`: A list of flags to always pass to `program` (Default: `[]`)
- `asdf`: The ASDF version to use (Default: `pkgs.asdf_3_3`)
- `packageOverrides`: Package overrides config (Default: `(self: super: {})`)
This example wraps CLISP:
```
wrapLisp {
pkg = clisp;
faslExt = "fas";
flags = ["-E" "UTF8"];
}
```

View File

@@ -129,21 +129,16 @@ Let's present the luarocks way first and the manual one in a second time.
### Packaging a library on luarocks {#packaging-a-library-on-luarocks}
[Luarocks.org](https://luarocks.org/) is the main repository of lua packages.
The site proposes two types of packages, the `rockspec` and the `src.rock`
The site proposes two types of packages, the rockspec and the src.rock
(equivalent of a [rockspec](https://github.com/luarocks/luarocks/wiki/Rockspec-format) but with the source).
These packages can have different build types such as `cmake`, `builtin` etc .
Luarocks-based packages are generated in [pkgs/development/lua-modules/generated-packages.nix](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/lua-modules/generated-packages.nix) from
the whitelist maintainers/scripts/luarocks-packages.csv and updated by running
the script
[maintainers/scripts/update-luarocks-packages](https://github.com/NixOS/nixpkgs/tree/master/maintainers/scripts/update-luarocks-packages):
```sh
./maintainers/scripts/update-luarocks-packages update
```
Luarocks-based packages are generated in pkgs/development/lua-modules/generated-packages.nix from
the whitelist maintainers/scripts/luarocks-packages.csv and updated by running maintainers/scripts/update-luarocks-packages.
[luarocks2nix](https://github.com/nix-community/luarocks) is a tool capable of generating nix derivations from both rockspec and src.rock (and favors the src.rock).
The automation only goes so far though and some packages need to be customized.
These customizations go in [pkgs/development/lua-modules/overrides.nix](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/lua-modules/overrides.nix).
These customizations go in `pkgs/development/lua-modules/overrides.nix`.
For instance if the rockspec defines `external_dependencies`, these need to be manually added to the overrides.nix.
You can try converting luarocks packages to nix packages with the command `nix-shell -p luarocks-nix` and then `luarocks nix PKG_NAME`.

View File

@@ -4,7 +4,7 @@
Nixpkgs provides a couple of facilities for working with this tool.
## Writing packages providing pkg-config modules {#pkg-config-writing-packages}
## Writing packages providing pkg-config modules
Packages should set `meta.pkgConfigModules` with the list of package config modules they provide.
They should also use `testers.testMetaPkgConfig` to check that the final built package matches that list.
@@ -29,9 +29,9 @@ stdenv.mkDerivation (finalAttrs: {
})
```
## Accessing packages via pkg-config module name {#sec-pkg-config-usage}
## Accessing packages via pkg-config module name
### Within Nixpkgs {#sec-pkg-config-usage-internal}
### Within Nixpkgs
A [setup hook](#setup-hook-pkg-config) is bundled in the `pkg-config` package to bring a derivation's declared build inputs into the environment.
This will populate environment variables like `PKG_CONFIG_PATH`, `PKG_CONFIG_PATH_FOR_BUILD`, and `PKG_CONFIG_PATH_HOST` based on:
@@ -44,7 +44,7 @@ For more details see the section on [specifying dependencies in general](#ssec-s
Normal pkg-config commands to look up dependencies by name will then work with those environment variables defined by the hook.
### Externally {#sec-pkg-config-usage-external}
### Externally
The `defaultPkgConfigPackages` package set is a set of aliases, named after the modules they provide.
This is meant to be used by language-to-nix integrations.

View File

@@ -1019,7 +1019,7 @@ buildPythonPackage rec {
The `buildPythonPackage` mainly does four things:
* In the `buildPhase`, it calls `${python.pythonForBuild.interpreter} setup.py bdist_wheel` to
* In the `buildPhase`, it calls `${python.interpreter} setup.py bdist_wheel` to
build a wheel binary zipfile.
* In the `installPhase`, it installs the wheel file using `pip install *.whl`.
* In the `postFixup` phase, the `wrapPythonPrograms` bash function is called to
@@ -1117,7 +1117,7 @@ with import <nixpkgs> {};
in python.withPackages(ps: [ps.blaze])).env
```
#### Optional extra dependencies {#python-optional-dependencies}
#### Optional extra dependencies
Some packages define optional dependencies for additional features. With
`setuptools` this is called `extras_require` and `flit` calls it
@@ -1546,7 +1546,7 @@ of such package using the feature is `pkgs/tools/X11/xpra/default.nix`.
As workaround install it as an extra `preInstall` step:
```shell
${python.pythonForBuild.interpreter} setup.py install_data --install-dir=$out --root=$out
${python.interpreter} setup.py install_data --install-dir=$out --root=$out
sed -i '/ = data\_files/d' setup.py
```
@@ -1801,14 +1801,14 @@ The following rules are desired to be respected:
* Attribute names in `python-packages.nix` should be sorted alphanumerically to
avoid merge conflicts and ease locating attributes.
## Package set maintenance {#python-package-set-maintenance}
## Package set maintenance
The whole Python package set has a lot of packages that do not see regular
updates, because they either are a very fragile component in the Python
ecosystem, like for example the `hypothesis` package, or packages that have
no maintainer, so maintenance falls back to the package set maintainers.
### Updating packages in bulk {#python-package-bulk-updates}
### Updating packages in bulk
There is a tool to update alot of python libraries in bulk, it exists at
`maintainers/scripts/update-python-libraries` with this repository.
@@ -1821,11 +1821,6 @@ hosted on GitHub, exporting a `GITHUB_API_TOKEN` is highly recommended.
Updating packages in bulk leads to lots of breakages, which is why a
stabilization period on the `python-unstable` branch is required.
If a package is fragile and often breaks during these bulks updates, it
may be reasonable to set `passthru.skipBulkUpdate = true` in the
derivation. This decision should not be made on a whim and should
always be supported by a qualifying comment.
Once the branch is sufficiently stable it should normally be merged
into the `staging` branch.
@@ -1836,7 +1831,7 @@ would be:
$ maintainers/scripts/update-python-libraries --target minor --commit --use-pkgs-prefix pkgs/development/python-modules/**/default.nix
```
## CPython Update Schedule {#python-cpython-update-schedule}
## CPython Update Schedule
With [PEP 602](https://www.python.org/dev/peps/pep-0602/), CPython now
follows a yearly release cadence. In nixpkgs, all supported interpreters

View File

@@ -201,7 +201,7 @@ $ nix-shell --run 'ruby -rpg -e "puts PG.library_version"'
Of course for this use-case one could also use overlays since the configuration for `pg` depends on the `postgresql` alias, but for demonstration purposes this has to suffice.
### Platform-specific gems {#ruby-platform-specif-gems}
### Platform-specific gems
Right now, bundix has some issues with pre-built, platform-specific gems: [bundix PR #68](https://github.com/nix-community/bundix/pull/68).
Until this is solved, you can tell bundler to not use platform-specific gems and instead build them from source each time:

View File

@@ -13,7 +13,7 @@ into your `configuration.nix` or bring them into scope with `nix-shell -p rustc
For other versions such as daily builds (beta and nightly),
use either `rustup` from nixpkgs (which will manage the rust installation in your home directory),
or use [community maintained Rust toolchains](#using-community-maintained-rust-toolchains).
or use a community maintained [Rust overlay](#using-community-rust-overlays).
## `buildRustPackage`: Compiling Rust applications with Cargo {#compiling-rust-applications-with-cargo}
@@ -50,11 +50,6 @@ package. `cargoHash256` is used for traditional Nix SHA-256 hashes,
such as the one in the example above. `cargoHash` should instead be
used for [SRI](https://www.w3.org/TR/SRI/) hashes. For example:
Exception: If the application has cargo `git` dependencies, the `cargoHash`/`cargoSha256`
approach will not work, and you will need to copy the `Cargo.lock` file of the application
to nixpkgs and continue with the next section for specifying the options of the`cargoLock`
section.
```nix
cargoHash = "sha256-l1vL2ZdtDRxSGvP0X/l3nMw8+6WF67KPutJEzUROjg8=";
```
@@ -162,7 +157,7 @@ required to build a rust package. A simple fix is to use:
```nix
postPatch = ''
ln -s ${./Cargo.lock} Cargo.lock
cp ${./Cargo.lock} Cargo.lock
'';
```
@@ -416,13 +411,13 @@ rustPlatform.buildRustPackage rec {
}
```
### Compiling non-Rust packages that include Rust code {#compiling-non-rust-packages-that-include-rust-code}
## Compiling non-Rust packages that include Rust code {#compiling-non-rust-packages-that-include-rust-code}
Several non-Rust packages incorporate Rust code for performance- or
security-sensitive parts. `rustPlatform` exposes several functions and
hooks that can be used to integrate Cargo in non-Rust packages.
#### Vendoring of dependencies {#vendoring-of-dependencies}
### Vendoring of dependencies {#vendoring-of-dependencies}
Since network access is not allowed in sandboxed builds, Rust crate
dependencies need to be retrieved using a fetcher. `rustPlatform`
@@ -482,7 +477,7 @@ added. To find the correct hash, you can first use `lib.fakeSha256` or
`lib.fakeHash` as a stub hash. Building `cargoDeps` will then inform
you of the correct hash.
#### Hooks {#hooks}
### Hooks {#hooks}
`rustPlatform` provides the following hooks to automate Cargo builds:
@@ -518,7 +513,7 @@ you of the correct hash.
* `bindgenHook`: for crates which use `bindgen` as a build dependency, lets
`bindgen` find `libclang` and `libclang` find the libraries in `buildInputs`.
#### Examples {#examples}
### Examples {#examples}
#### Python package using `setuptools-rust` {#python-package-using-setuptools-rust}
@@ -647,127 +642,7 @@ buildPythonPackage rec {
}
```
## `buildRustCrate`: Compiling Rust crates using Nix instead of Cargo {#compiling-rust-crates-using-nix-instead-of-cargo}
### Simple operation {#simple-operation}
When run, `cargo build` produces a file called `Cargo.lock`,
containing pinned versions of all dependencies. Nixpkgs contains a
tool called `crate2Nix` (`nix-shell -p crate2nix`), which can be
used to turn a `Cargo.lock` into a Nix expression. That Nix
expression calls `rustc` directly (hence bypassing Cargo), and can
be used to compile a crate and all its dependencies.
See [`crate2nix`'s documentation](https://github.com/kolloch/crate2nix#known-restrictions)
for instructions on how to use it.
### Handling external dependencies {#handling-external-dependencies}
Some crates require external libraries. For crates from
[crates.io](https://crates.io), such libraries can be specified in
`defaultCrateOverrides` package in nixpkgs itself.
Starting from that file, one can add more overrides, to add features
or build inputs by overriding the hello crate in a separate file.
```nix
with import <nixpkgs> {};
((import ./hello.nix).hello {}).override {
crateOverrides = defaultCrateOverrides // {
hello = attrs: { buildInputs = [ openssl ]; };
};
}
```
Here, `crateOverrides` is expected to be a attribute set, where the
key is the crate name without version number and the value a function.
The function gets all attributes passed to `buildRustCrate` as first
argument and returns a set that contains all attribute that should be
overwritten.
For more complicated cases, such as when parts of the crate's
derivation depend on the crate's version, the `attrs` argument of
the override above can be read, as in the following example, which
patches the derivation:
```nix
with import <nixpkgs> {};
((import ./hello.nix).hello {}).override {
crateOverrides = defaultCrateOverrides // {
hello = attrs: lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0") {
postPatch = ''
substituteInPlace lib/zoneinfo.rs \
--replace "/usr/share/zoneinfo" "${tzdata}/share/zoneinfo"
'';
};
};
}
```
Another situation is when we want to override a nested
dependency. This actually works in the exact same way, since the
`crateOverrides` parameter is forwarded to the crate's
dependencies. For instance, to override the build inputs for crate
`libc` in the example above, where `libc` is a dependency of the main
crate, we could do:
```nix
with import <nixpkgs> {};
((import hello.nix).hello {}).override {
crateOverrides = defaultCrateOverrides // {
libc = attrs: { buildInputs = []; };
};
}
```
### Options and phases configuration {#options-and-phases-configuration}
Actually, the overrides introduced in the previous section are more
general. A number of other parameters can be overridden:
- The version of `rustc` used to compile the crate:
```nix
(hello {}).override { rust = pkgs.rust; };
```
- Whether to build in release mode or debug mode (release mode by
default):
```nix
(hello {}).override { release = false; };
```
- Whether to print the commands sent to `rustc` when building
(equivalent to `--verbose` in cargo:
```nix
(hello {}).override { verbose = false; };
```
- Extra arguments to be passed to `rustc`:
```nix
(hello {}).override { extraRustcOpts = "-Z debuginfo=2"; };
```
- Phases, just like in any other derivation, can be specified using
the following attributes: `preUnpack`, `postUnpack`, `prePatch`,
`patches`, `postPatch`, `preConfigure` (in the case of a Rust crate,
this is run before calling the "build" script), `postConfigure`
(after the "build" script),`preBuild`, `postBuild`, `preInstall` and
`postInstall`. As an example, here is how to create a new module
before running the build script:
```nix
(hello {}).override {
preConfigure = ''
echo "pub const PATH=\"${hi.out}\";" >> src/path.rs"
'';
};
```
### Setting Up `nix-shell` {#setting-up-nix-shell}
## Setting Up `nix-shell` {#setting-up-nix-shell}
Oftentimes you want to develop code from within `nix-shell`. Unfortunately
`buildRustCrate` does not support common `nix-shell` operations directly
@@ -811,61 +686,31 @@ $ cargo build
$ cargo test
```
## Using community maintained Rust toolchains {#using-community-maintained-rust-toolchains}
### Controlling Rust Version Inside `nix-shell` {#controlling-rust-version-inside-nix-shell}
::: {.note}
Note: The following projects cannot be used within nixpkgs since [IFD](#ssec-import-from-derivation) is disallowed.
To package things that require Rust nightly, `RUSTC_BOOTSTRAP = true;` can sometimes be used as a hack.
:::
There are two community maintained approaches to Rust toolchain management:
- [oxalica's Rust overlay](https://github.com/oxalica/rust-overlay)
- [fenix](https://github.com/nix-community/fenix)
Despite their names, both projects provides a similar set of packages and overlays under different APIs.
Oxalica's overlay allows you to select a particular Rust version without you providing a hash or a flake input,
but comes with a larger git repository than fenix.
Fenix also provides rust-analyzer nightly in addition to the Rust toolchains.
Both oxalica's overlay and fenix better integrate with nix and cache optimizations.
Because of this and ergonomics, either of those community projects
should be preferred to the Mozilla's Rust overlay ([nixpkgs-mozilla](https://github.com/mozilla/nixpkgs-mozilla)).
The following documentation demonstrates examples using fenix and oxalica's Rust overlay
with `nix-shell` and building derivations. More advanced usages like flake usage
are documented in their own repositories.
### Using Rust nightly with `nix-shell` {#using-rust-nightly-with-nix-shell}
Here is a simple `shell.nix` that provides Rust nightly (default profile) using fenix:
To control your rust version (i.e. use nightly) from within `shell.nix` (or
other nix expressions) you can use the following `shell.nix`
```nix
with import <nixpkgs> { };
let
fenix = callPackage
(fetchFromGitHub {
owner = "nix-community";
repo = "fenix";
# commit from: 2023-03-03
rev = "e2ea04982b892263c4d939f1cc3bf60a9c4deaa1";
hash = "sha256-AsOim1A8KKtMWIxG+lXh5Q4P2bhOZjoUhFWJ1EuZNNk=";
})
{ };
# Latest Nightly
with import <nixpkgs> {};
let src = fetchFromGitHub {
owner = "mozilla";
repo = "nixpkgs-mozilla";
# commit from: 2019-05-15
rev = "9f35c4b09fd44a77227e79ff0c1b4b6a69dff533";
hash = "sha256-18h0nvh55b5an4gmlgfbvwbyqj91bklf1zymis6lbdh75571qaz0=";
};
in
mkShell {
with import "${src.out}/rust-overlay.nix" pkgs pkgs;
stdenv.mkDerivation {
name = "rust-env";
nativeBuildInputs = [
# Note: to use stable, just replace `default` with `stable`
fenix.default.toolchain
# Example Build-time Additional Dependencies
pkg-config
];
buildInputs = [
# Example Run-time Additional Dependencies
openssl
# Note: to use stable, just replace `nightly` with `stable`
latest.rustChannels.nightly.rust
# Add some extra dependencies from `pkgs`
pkg-config openssl
];
# Set Environment Variables
@@ -873,66 +718,116 @@ mkShell {
}
```
Save this to `shell.nix`, then run:
Now run:
```ShellSession
$ rustc --version
rustc 1.69.0-nightly (13471d3b2 2023-03-02)
rustc 1.26.0-nightly (188e693b3 2018-03-26)
```
To see that you are using nightly.
Oxalica's Rust overlay has more complete examples of `shell.nix` (and cross compilation) under its
[`examples` directory](https://github.com/oxalica/rust-overlay/tree/e53e8853aa7b0688bc270e9e6a681d22e01cf299/examples).
## Using community Rust overlays {#using-community-rust-overlays}
### Using Rust nightly in a derivation with `buildRustPackage` {#using-rust-nightly-in-a-derivation-with-buildrustpackage}
There are two community maintained approaches to Rust toolchain management:
- [oxalica's Rust overlay](https://github.com/oxalica/rust-overlay)
- [fenix](https://github.com/nix-community/fenix)
You can also use Rust nightly to build rust packages using `makeRustPlatform`.
The below snippet demonstrates invoking `buildRustPackage` with a Rust toolchain from oxalica's overlay:
Oxalica's overlay allows you to select a particular Rust version and components.
See [their documentation](https://github.com/oxalica/rust-overlay#rust-overlay) for more
detailed usage.
Fenix is an alternative to `rustup` and can also be used as an overlay.
Both oxalica's overlay and fenix better integrate with nix and cache optimizations.
Because of this and ergonomics, either of those community projects
should be preferred to the Mozilla's Rust overlay (`nixpkgs-mozilla`).
### How to select a specific `rustc` and toolchain version {#how-to-select-a-specific-rustc-and-toolchain-version}
You can consume the oxalica overlay and use it to grab a specific Rust toolchain version.
Here is an example `shell.nix` showing how to grab the current stable toolchain:
```nix
with import <nixpkgs>
{
{ pkgs ? import <nixpkgs> {
overlays = [
(import (fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))
];
}
}:
pkgs.mkShell {
nativeBuildInputs = with pkgs; [
pkg-config
rust-bin.stable.latest.minimal
];
}
```
You can try this out by:
1. Saving that to `shell.nix`
2. Executing `nix-shell --pure --command 'rustc --version'`
As of writing, this prints out `rustc 1.56.0 (09c42c458 2021-10-18)`.
### How to use an overlay toolchain in a derivation {#how-to-use-an-overlay-toolchain-in-a-derivation}
You can also use an overlay's Rust toolchain with `buildRustPackage`.
The below snippet demonstrates invoking `buildRustPackage` with an oxalica overlay selected Rust toolchain:
```nix
with import <nixpkgs> {
overlays = [
(import (fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))
];
};
let
rustPlatform = makeRustPlatform {
cargo = rust-bin.stable.latest.minimal;
rustc = rust-bin.stable.latest.minimal;
};
in
rustPlatform.buildRustPackage rec {
pname = "ripgrep";
version = "12.1.1";
nativeBuildInputs = [
rust-bin.stable.latest.minimal
];
src = fetchFromGitHub {
owner = "BurntSushi";
repo = "ripgrep";
rev = version;
hash = "sha256-+s5RBC3XSgb8omTbUNLywZnP6jSxZBKSS1BmXOjRF8M=";
hash = "sha256-1hqps7l5qrjh9f914r5i6kmcz6f1yb951nv4lby0cjnp5l253kps=";
};
cargoHash = "sha256-l1vL2ZdtDRxSGvP0X/l3nMw8+6WF67KPutJEzUROjg8=";
doCheck = false;
cargoSha256 = "03wf9r2csi6jpa7v5sw5lpxkrk4wfzwmzx7k3991q3bdjzcwnnwp";
meta = with lib; {
description = "A fast line-oriented regex search tool, similar to ag and ack";
homepage = "https://github.com/BurntSushi/ripgrep";
license = with licenses; [ mit unlicense ];
maintainers = with maintainers; [ tailhook ];
license = licenses.unlicense;
maintainers = [ maintainers.tailhook ];
};
}
```
Follow the below steps to try that snippet.
1. create a new directory
1. save the above snippet as `default.nix` in that directory
2. cd into that directory and run `nix-build`
1. cd into that directory and run `nix-build`
Fenix also has examples with `buildRustPackage`,
[crane](https://github.com/ipetkov/crane),
[naersk](https://github.com/nix-community/naersk),
and cross compilation in its [Examples](https://github.com/nix-community/fenix#examples) section.
### Rust overlay installation {#rust-overlay-installation}
You can use this overlay by either changing your local nixpkgs configuration,
or by adding the overlay declaratively in a nix expression, e.g. in `configuration.nix`.
For more information see [the manual on installing overlays](#sec-overlays-install).
### Declarative Rust overlay installation {#declarative-rust-overlay-installation}
This snippet shows how to use oxalica's Rust overlay.
Add the following to your `configuration.nix`, `home-configuration.nix`, `shell.nix`, or similar:
```nix
{ pkgs ? import <nixpkgs> {
overlays = [
(import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))
# Further overlays go here
];
};
};
```
Note that this will fetch the latest overlay version when rebuilding your system.

View File

@@ -40,24 +40,17 @@ Since release 15.09 there is a new TeX Live packaging that lives entirely under
## Custom packages {#sec-language-texlive-custom-packages}
You may find that you need to use an external TeX package. A derivation for such package has to provide the contents of the "texmf" directory in its output and provide the appropriate `tlType` attribute (one of `"run"`, `"bin"`, `"doc"`, `"source"`). Dependencies on other TeX packages can be listed in the attribute `tlDeps`.
Such derivation must then be listed in the attribute `pkgs` of an attribute set passed to `texlive.combine`, for instance by passing `extraPkgs = { pkgs = [ custom_package ]; };`. Within Nixpkgs, `pkgs` should be part of the derivation itself, allowing users to call `texlive.combine { inherit (texlive) scheme-small; inherit some_tex_package; }`.
Here is a (very verbose) example where the attribute `pkgs` is attached to the derivation itself, which requires creating a fixed point. See also the packages `auctex`, `eukleides`, `mftrace` for more examples.
You may find that you need to use an external TeX package. A derivation for such package has to provide contents of the "texmf" directory in its output and provide the `tlType` attribute. Here is a (very verbose) example:
```nix
with import <nixpkgs> {};
let
foiltex = stdenvNoCC.mkDerivation (finalAttrs: {
foiltex_run = stdenvNoCC.mkDerivation {
pname = "latex-foiltex";
version = "2.1.4b";
passthru = {
pkgs = [ finalAttrs.finalPackage ];
tlDeps = with texlive; [ latex ];
tlType = "run";
};
passthru.tlType = "run";
srcs = [
(fetchurl {
@@ -109,7 +102,8 @@ let
maintainers = with maintainers; [ veprbl ];
platforms = platforms.all;
};
});
};
foiltex = { pkgs = [ foiltex_run ]; };
latex_with_foiltex = texlive.combine {
inherit (texlive) scheme-small;

View File

@@ -166,8 +166,8 @@ in
If your package requires building specific parts, use instead `pkgs.vimUtils.buildVimPlugin`.
### Specificities for some plugins {#vim-plugin-specificities}
#### Treesitter {#vim-plugin-treesitter}
### Specificities for some plugins
#### Treesitter
By default `nvim-treesitter` encourages you to download, compile and install
the required Treesitter grammars at run time with `:TSInstall`. This works
@@ -212,7 +212,7 @@ Note: this is not possible anymore for Neovim.
## Adding new plugins to nixpkgs {#adding-new-plugins-to-nixpkgs}
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).
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`.
After running `./update.py`, if nvim-treesitter received an update, also run [`nvim-treesitter/update.py`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/update.py) to update the tree sitter grammars for `nvim-treesitter`.
@@ -226,7 +226,7 @@ deoplete-fish = super.deoplete-fish.overrideAttrs(old: {
Sometimes plugins require an override that must be changed when the plugin is updated. This can cause issues when Vim plugins are auto-updated but the associated override isn't updated. For these plugins, the override should be written so that it specifies all information required to install the plugin, and running `./update.py` doesn't change the derivation for the plugin. Manually updating the override is required to update these types of plugins. An example of such a plugin is `LanguageClient-neovim`.
To add a new plugin, run `./update.py add "[owner]/[name]"`. **NOTE**: This script automatically commits to your git repository. Be sure to check out a fresh branch before running.
To add a new plugin, run `./update.py --add "[owner]/[name]"`. **NOTE**: This script automatically commits to your git repository. Be sure to check out a fresh branch before running.
Finally, there are some plugins that are also packaged in nodePackages because they have Javascript-related build steps, such as running webpack. Those plugins are not listed in `vim-plugin-names` or managed by `update.py` at all, and are included separately in `overrides.nix`. Currently, all these plugins are related to the `coc.nvim` ecosystem of the Language Server Protocol integration with Vim/Neovim.
@@ -244,7 +244,7 @@ Alternatively, set the number of processes to a lower count to avoid rate-limiti
./pkgs/applications/editors/vim/plugins/update.py --proc 1
```
## How to maintain an out-of-tree overlay of vim plugins ? {#vim-out-of-tree-overlays}
## How to maintain an out-of-tree overlay of vim plugins ?
You can use the updater script to generate basic packages out of a custom vim
plugin list:

View File

@@ -1,20 +1,19 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="nixpkgs-manual">
xmlns:xi="http://www.w3.org/2001/XInclude">
<info>
<title>Nixpkgs Manual</title>
<subtitle>Version <xi:include href=".version" parse="text" />
</subtitle>
</info>
<xi:include href="preface.chapter.xml" />
<part xml:id="part-using">
<part>
<title>Using Nixpkgs</title>
<xi:include href="using/configuration.chapter.xml" />
<xi:include href="using/overlays.chapter.xml" />
<xi:include href="using/overrides.chapter.xml" />
<xi:include href="functions.xml" />
</part>
<part xml:id="part-stdenv">
<part>
<title>Standard environment</title>
<xi:include href="stdenv/stdenv.chapter.xml" />
<xi:include href="stdenv/meta.chapter.xml" />
@@ -22,7 +21,7 @@
<xi:include href="stdenv/cross-compilation.chapter.xml" />
<xi:include href="stdenv/platform-notes.chapter.xml" />
</part>
<part xml:id="part-builders">
<part>
<title>Builders</title>
<xi:include href="builders/fetchers.chapter.xml" />
<xi:include href="builders/trivial-builders.chapter.xml" />
@@ -33,7 +32,7 @@
<xi:include href="languages-frameworks/index.xml" />
<xi:include href="builders/packages/index.xml" />
</part>
<part xml:id="part-contributing">
<part>
<title>Contributing to Nixpkgs</title>
<xi:include href="contributing/quick-start.chapter.xml" />
<xi:include href="contributing/coding-conventions.chapter.xml" />

View File

@@ -86,23 +86,6 @@ meta.platforms = lib.platforms.linux;
Attribute Set `lib.platforms` defines [various common lists](https://github.com/NixOS/nixpkgs/blob/master/lib/systems/doubles.nix) of platforms types.
### `badPlatforms` {#var-meta-badPlatforms}
The list of Nix [platform types](https://github.com/NixOS/nixpkgs/blob/b03ac42b0734da3e7be9bf8d94433a5195734b19/lib/meta.nix#L75-L81) on which the package is known not to be buildable.
Hydra will never create prebuilt binaries for these platform types, even if they are in [`meta.platforms`](#var-meta-platforms).
In general it is preferable to set `meta.platforms = lib.platforms.all` and then exclude any platforms on which the package is known not to build.
For example, a package which requires dynamic linking and cannot be linked statically could use this:
```nix
meta.platforms = lib.platforms.all;
meta.badPlatforms = [ lib.systems.inspect.patterns.isStatic ];
```
The [`lib.meta.availableOn`](https://github.com/NixOS/nixpkgs/blob/b03ac42b0734da3e7be9bf8d94433a5195734b19/lib/meta.nix#L95-L106) function can be used to test whether or not a package is available (i.e. buildable) on a given platform.
Some packages use this to automatically detect the maximum set of features with which they can be built.
For example, `systemd` [requires dynamic linking](https://github.com/systemd/systemd/issues/20600#issuecomment-912338965), and [has a `meta.badPlatforms` setting](https://github.com/NixOS/nixpkgs/blob/b03ac42b0734da3e7be9bf8d94433a5195734b19/pkgs/os-specific/linux/systemd/default.nix#L752) similar to the one above.
Packages which can be built with or without `systemd` support will use `lib.meta.availableOn` to detect whether or not `systemd` is available on the [`hostPlatform`](#ssec-cross-platform-parameters) for which they are being built; if it is not available (e.g. due to a statically-linked host platform like `pkgsStatic`) this support will be disabled by default.
### `tests` {#var-meta-tests}
::: {.warning}
@@ -118,7 +101,7 @@ $ cd path/to/nixpkgs
$ nix-build -A your-package.tests
```
#### Package tests {#var-meta-tests-packages}
#### Package tests
Tests that are part of the source package are often executed in the `installCheckPhase`.
@@ -130,7 +113,7 @@ Prefer `passthru.tests` for tests that are introduced in nixpkgs because:
For more on how to write and run package tests, see <xref linkend="sec-package-tests"/>.
#### NixOS tests {#var-meta-tests-nixos}
#### NixOS tests
The NixOS tests are available as `nixosTests` in parameters of derivations. For instance, the OpenSMTPD derivation includes lines similar to:
@@ -190,7 +173,7 @@ To be effective, it must be presented directly to an evaluation process that han
### `hydraPlatforms` {#var-meta-hydraPlatforms}
The list of Nix platform types for which the [Hydra](https://github.com/nixos/hydra) [instance at `hydra.nixos.org`](https://nixos.org/hydra) will build the package. (Hydra is the Nix-based continuous build system.) It defaults to the value of `meta.platforms`. Thus, the only reason to set `meta.hydraPlatforms` is if you want `hydra.nixos.org` to build the package on a subset of `meta.platforms`, or not at all, e.g.
The list of Nix platform types for which the Hydra instance at `hydra.nixos.org` will build the package. (Hydra is the Nix-based continuous build system.) It defaults to the value of `meta.platforms`. Thus, the only reason to set `meta.hydraPlatforms` is if you want `hydra.nixos.org` to build the package on a subset of `meta.platforms`, or not at all, e.g.
```nix
meta.platforms = lib.platforms.linux;
@@ -199,26 +182,7 @@ meta.hydraPlatforms = [];
### `broken` {#var-meta-broken}
If set to `true`, the package is marked as "broken", meaning that it wont show up in [search.nixos.org](https://search.nixos.org/packages), and cannot be built or installed unless the environment variable [`NIXPKGS_ALLOW_BROKEN`](#opt-allowBroken) is set.
Such unconditionally-broken packages should be removed from Nixpkgs eventually unless they are fixed.
The value of this attribute can depend on a package's arguments, including `stdenv`.
This means that `broken` can be used to express constraints, for example:
- Does not cross compile
```nix
meta.broken = !(stdenv.buildPlatform.canExecute stdenv.hostPlatform)
```
- Broken if all of a certain set of its dependencies are broken
```nix
meta.broken = lib.all (map (p: p.meta.broken) [ glibc musl ])
```
This makes `broken` strictly more powerful than `meta.badPlatforms`.
However `meta.availableOn` currently examines only `meta.platforms` and `meta.badPlatforms`, so `meta.broken` does not influence the default values for optional dependencies.
If set to `true`, the package is marked as "broken", meaning that it wont show up in `nix-env -qa`, and cannot be built or installed. Such packages should be removed from Nixpkgs eventually unless they are fixed.
## Licenses {#sec-meta-license}

View File

@@ -16,8 +16,7 @@ stdenv.mkDerivation {
}
```
(`stdenv` needs to be in scope, so if you write this in a separate Nix expression from `pkgs/all-packages.nix`, you need to pass it as a function argument.) Specifying a `name` and a `src` is the absolute minimum Nix requires. For convenience, you can also use `pname` and `version` attributes and `mkDerivation` will automatically set `name` to `"${pname}-${version}"` by default.
**Since [RFC 0035](https://github.com/NixOS/rfcs/pull/35), this is preferred for packages in Nixpkgs**, as it allows us to reuse the version easily:
(`stdenv` needs to be in scope, so if you write this in a separate Nix expression from `pkgs/all-packages.nix`, you need to pass it as a function argument.) Specifying a `name` and a `src` is the absolute minimum Nix requires. For convenience, you can also use `pname` and `version` attributes and `mkDerivation` will automatically set `name` to `"${pname}-${version}"` by default. Since [RFC 0035](https://github.com/NixOS/rfcs/pull/35), this is preferred for packages in Nixpkgs, as it allows us to reuse the version easily:
```nix
stdenv.mkDerivation rec {
@@ -34,8 +33,7 @@ Many packages have dependencies that are not provided in the standard environmen
```nix
stdenv.mkDerivation {
pname = "libfoo";
version = "1.2.3";
name = "libfoo-1.2.3";
...
buildInputs = [libbar perl ncurses];
}
@@ -47,8 +45,7 @@ Often it is necessary to override or modify some aspect of the build. To make th
```nix
stdenv.mkDerivation {
pname = "fnord";
version = "4.5";
name = "fnord-4.5";
...
buildPhase = ''
gcc foo.c -o foo
@@ -68,8 +65,7 @@ While the standard environment provides a generic builder, you can still supply
```nix
stdenv.mkDerivation {
pname = "libfoo";
version = "1.2.3";
name = "libfoo-1.2.3";
...
builder = ./builder.sh;
}
@@ -105,11 +101,11 @@ To build a `stdenv` package in a [`nix-shell`](https://nixos.org/manual/nix/unst
```bash
nix-shell '<nixpkgs>' -A some_package
eval "${unpackPhase:-unpackPhase}"
eval ${unpackPhase:-unpackPhase}
cd $sourceRoot
eval "${patchPhase:-patchPhase}"
eval "${configurePhase:-configurePhase}"
eval "${buildPhase:-buildPhase}"
eval ${patchPhase:-patchPhase}
eval ${configurePhase:-configurePhase}
eval ${buildPhase:-buildPhase}
```
To modify a [phase](#sec-stdenv-phases), first print it with
@@ -384,107 +380,39 @@ Values inside it are not passed to the builder, so you can change them without t
#### `passthru.updateScript` {#var-passthru-updateScript}
A script to be run by `maintainers/scripts/update.nix` when the package is matched. The attribute can contain one of the following:
A script to be run by `maintainers/scripts/update.nix` when the package is matched. It needs to be an executable file, either on the file system:
- []{#var-passthru-updateScript-command} an executable file, either on the file system:
```nix
passthru.updateScript = ./update.sh;
```
```nix
passthru.updateScript = ./update.sh;
```
or inside the expression itself:
or inside the expression itself:
```nix
passthru.updateScript = writeScript "update-zoom-us" ''
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p curl pcre common-updater-scripts
```nix
passthru.updateScript = writeScript "update-zoom-us" ''
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p curl pcre common-updater-scripts
set -eu -o pipefail
set -eu -o pipefail
version="$(curl -sI https://zoom.us/client/latest/zoom_x86_64.tar.xz | grep -Fi 'Location:' | pcregrep -o1 '/(([0-9]\.?)+)/')"
update-source-version zoom-us "$version"
'';
```
version="$(curl -sI https://zoom.us/client/latest/zoom_x86_64.tar.xz | grep -Fi 'Location:' | pcregrep -o1 '/(([0-9]\.?)+)/')"
update-source-version zoom-us "$version"
'';
```
The attribute can also contain a list, a script followed by arguments to be passed to it:
- a list, a script followed by arguments to be passed to it:
```nix
passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ];
```
```nix
passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ];
```
- an attribute set containing:
- [`command`]{#var-passthru-updateScript-set-command} a string or list in the [format expected by `passthru.updateScript`](#var-passthru-updateScript-command).
- [`attrPath`]{#var-passthru-updateScript-set-attrPath} (optional) a string containing the canonical attribute path for the package. If present, it will be passed to the update script instead of the attribute path on which the package was discovered during Nixpkgs traversal.
- [`supportedFeatures`]{#var-passthru-updateScript-set-supportedFeatures} (optional) a list of the [extra features](#var-passthru-updateScript-supported-features) the script supports.
```nix
passthru.updateScript = {
command = [ ../../update.sh pname ];
attrPath = pname;
supportedFeatures = [ … ];
};
```
##### How update scripts are executed? {#var-passthru-updateScript-execution}
Update scripts are to be invoked by `maintainers/scripts/update.nix` script. You can run `nix-shell maintainers/scripts/update.nix` in the root of Nixpkgs repository for information on how to use it. `update.nix` offers several modes for selecting packages to update (e.g. select by attribute path, traverse Nixpkgs and filter by maintainer, etc.), and it will execute update scripts for all matched packages that have an `updateScript` attribute.
Each update script will be passed the following environment variables:
- [`UPDATE_NIX_NAME`]{#var-passthru-updateScript-env-UPDATE_NIX_NAME} content of the `name` attribute of the updated package.
- [`UPDATE_NIX_PNAME`]{#var-passthru-updateScript-env-UPDATE_NIX_PNAME} content of the `pname` attribute of the updated package.
- [`UPDATE_NIX_OLD_VERSION`]{#var-passthru-updateScript-env-UPDATE_NIX_OLD_VERSION} content of the `version` attribute of the updated package.
- [`UPDATE_NIX_ATTR_PATH`]{#var-passthru-updateScript-env-UPDATE_NIX_ATTR_PATH} attribute path the `update.nix` discovered the package on (or the [canonical `attrPath`](#var-passthru-updateScript-set-attrPath) when available). Example: `pantheon.elementary-terminal`
The script will be run with the `UPDATE_NIX_NAME`, `UPDATE_NIX_PNAME`, `UPDATE_NIX_OLD_VERSION` and `UPDATE_NIX_ATTR_PATH` environment variables set respectively to the name, pname, old version and attribute path of the package it is supposed to update.
::: {.note}
An update script will be usually run from the root of the Nixpkgs repository but you should not rely on that. Also note that `update.nix` executes update scripts in parallel by default so you should avoid running `git commit` or any other commands that cannot handle that.
The script will be usually run from the root of the Nixpkgs repository but you should not rely on that. Also note that the update scripts will be run in parallel by default; you should avoid running `git commit` or any other commands that cannot handle that.
:::
::: {.tip}
While update scripts should not create commits themselves, `maintainers/scripts/update.nix` supports automatically creating commits when running it with `--argstr commit true`. If you need to customize commit message, you can have the update script implement [`commit`](#var-passthru-updateScript-commit) feature.
:::
##### Supported features {#var-passthru-updateScript-supported-features}
###### `commit` {#var-passthru-updateScript-commit}
This feature allows update scripts to *ask* `update.nix` to create Git commits.
When support of this feature is declared, whenever the update script exits with `0` return status, it is expected to print a JSON list containing an object described below for each updated attribute to standard output.
When `update.nix` is run with `--argstr commit true` arguments, it will create a separate commit for each of the objects. An empty list can be returned when the script did not update any files, for example, when the package is already at the latest version.
The commit object contains the following values:
- [`attrPath`]{#var-passthru-updateScript-commit-attrPath} a string containing attribute path.
- [`oldVersion`]{#var-passthru-updateScript-commit-oldVersion} a string containing old version.
- [`newVersion`]{#var-passthru-updateScript-commit-newVersion} a string containing new version.
- [`files`]{#var-passthru-updateScript-commit-files} a non-empty list of file paths (as strings) to add to the commit.
- [`commitBody`]{#var-passthru-updateScript-commit-commitBody} (optional) a string with extra content to be appended to the default commit message (useful for adding changelog links).
- [`commitMessage`]{#var-passthru-updateScript-commit-commitMessage} (optional) a string to use instead of the default commit message.
If the returned array contains exactly one object (e.g. `[{}]`), all values are optional and will be determined automatically.
```{=docbook}
<example>
<title>Standard output of an update script using commit feature</title>
```
```json
[
{
"attrPath": "volume_key",
"oldVersion": "0.3.11",
"newVersion": "0.3.12",
"files": [
"/path/to/nixpkgs/pkgs/development/libraries/volume-key/default.nix"
]
}
]
```
```{=docbook}
</example>
```
For information about how to run the updates, execute `nix-shell maintainers/scripts/update.nix`.
### Recursive attributes in `mkDerivation` {#mkderivation-recursive-attributes}
@@ -707,7 +635,7 @@ The prefix under which the package must be installed, passed via the `--prefix`
The key to use when specifying the prefix. By default, this is set to `--prefix=` as that is used by the majority of packages.
##### `dontAddStaticConfigureFlags` {#var-stdenv-dontAddStaticConfigureFlags}
##### `dontAddStaticConfigureFlags`
By default, when building statically, stdenv will try to add build system appropriate configure flags to try to enable static builds.
@@ -1099,15 +1027,15 @@ postInstall = ''
Performs string substitution on the contents of \<infile\>, writing the result to \<outfile\>. The substitutions in \<subs\> are of the following form:
#### `--replace` \<s1\> \<s2\> {#fun-substitute-replace}
#### `--replace` \<s1\> \<s2\>
Replace every occurrence of the string \<s1\> by \<s2\>.
#### `--subst-var` \<varName\> {#fun-substitute-subst-var}
#### `--subst-var` \<varName\>
Replace every occurrence of `@varName@` by the contents of the environment variable \<varName\>. This is useful for generating files from templates, using `@...@` in the template as placeholders.
#### `--subst-var-by` \<varName\> \<s\> {#fun-substitute-subst-var-by}
#### `--subst-var-by` \<varName\> \<s\>
Replace every occurrence of `@varName@` by the string \<s\>.
@@ -1248,7 +1176,7 @@ Multiple paths can be specified.
patchShebangs [--build | --host] PATH...
```
##### Flags {#patch-shebangs.sh-invocation-flags}
##### Flags
`--build`
: Look up commands available at build time
@@ -1256,7 +1184,7 @@ patchShebangs [--build | --host] PATH...
`--host`
: Look up commands available at run time
##### Examples {#patch-shebangs.sh-invocation-examples}
##### Examples
```sh
patchShebangs --host /nix/store/<hash>-hello-1.0/bin
@@ -1343,7 +1271,7 @@ Similarly, the CC Wrapper follows the Bintools Wrapper in defining standard envi
Here are some more packages that provide a setup hook. Since the list of hooks is extensible, this is not an exhaustive list. The mechanism is only to be used as a last resort, so it might cover most uses.
### Other hooks {#stdenv-other-hooks}
### Other hooks
Many other packages provide hooks, that are not part of `stdenv`. You can find
these in the [Hooks Reference](#chap-hooks).
@@ -1401,7 +1329,7 @@ bin/blib.a(bios_console.o): In function `bios_handle_cup':
Adds the `-O2 -D_FORTIFY_SOURCE=2` compiler options. During code generation the compiler knows a great deal of information about buffer sizes (where possible), and attempts to replace insecure unlimited length buffer function calls with length-limited ones. This is especially useful for old, crufty code. Additionally, format strings in writable memory that contain `%n` are blocked. If an application depends on such a format string, it will need to be worked around.
Additionally, some warnings are enabled which might trigger build failures if compiler warnings are treated as errors in the package build. In this case, set `env.NIX_CFLAGS_COMPILE` to `-Wno-error=warning-type`.
Additionally, some warnings are enabled which might trigger build failures if compiler warnings are treated as errors in the package build. In this case, set `NIX_CFLAGS_COMPILE` to `-Wno-error=warning-type`.
This needs to be turned off or fixed for errors similar to:

View File

@@ -1,7 +1,4 @@
{ "\t" = 9;
"\n" = 10;
"\r" = 13;
" " = 32;
{ " " = 32;
"!" = 33;
"\"" = 34;
"#" = 35;

View File

@@ -9,7 +9,7 @@ let
in
rec {
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs;
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr;
/* Return an attribute from nested attribute sets.
@@ -333,66 +333,6 @@ rec {
) (attrNames set)
);
/*
Like builtins.foldl' but for attribute sets.
Iterates over every name-value pair in the given attribute set.
The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`.
Attention:
There is a completely different function
`lib.foldAttrs`
which has nothing to do with this function, despite the similar name.
Example:
foldlAttrs
(acc: name: value: {
sum = acc.sum + value;
names = acc.names ++ [name];
})
{ sum = 0; names = []; }
{
foo = 1;
bar = 10;
}
->
{
sum = 11;
names = ["bar" "foo"];
}
foldlAttrs
(throw "function not needed")
123
{};
->
123
foldlAttrs
(_: _: v: v)
(throw "initial accumulator not needed")
{ z = 3; a = 2; };
->
3
The accumulator doesn't have to be an attrset.
It can be as simple as a number or string.
foldlAttrs
(acc: _: v: acc * 10 + v)
1
{ z = 1; a = 2; };
->
121
Type:
foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
*/
foldlAttrs = f: init: set:
foldl'
(acc: name: f acc name set.${name})
init
(attrNames set);
/* Apply fold functions to values grouped by key.
Example:

View File

@@ -176,7 +176,7 @@ rec {
# Only show the error for the first missing argument
error = errorForArg (lib.head missingArgs);
in if missingArgs == [] then makeOverridable f allArgs else abort error;
in if missingArgs == [] then makeOverridable f allArgs else throw error;
/* Like callPackage, but for a function that returns an attribute
@@ -213,14 +213,7 @@ rec {
outputSpecified = true;
drvPath = assert condition; drv.${outputName}.drvPath;
outPath = assert condition; drv.${outputName}.outPath;
} //
# TODO: give the derivation control over the outputs.
# `overrideAttrs` may not be the only attribute that needs
# updating when switching outputs.
lib.optionalAttrs (passthru?overrideAttrs) {
# TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
};
};
};
outputsList = map outputToAttrListElement outputs;

View File

@@ -109,8 +109,6 @@ rec {
traceSeqN 2 { a.b.c = 3; } null
trace: { a = { b = {}; }; }
=> null
Type: traceSeqN :: Int -> a -> b -> b
*/
traceSeqN = depth: x: y:
let snip = v: if isList v then noQuotes "[]" v
@@ -175,63 +173,17 @@ rec {
# -- TESTING --
/* Evaluates a set of tests.
A test is an attribute set `{expr, expected}`,
denoting an expression and its expected result.
The result is a `list` of __failed tests__, each represented as
`{name, expected, result}`,
- expected
- What was passed as `expected`
- result
- The actual `result` of the test
/* Evaluate a set of tests. A test is an attribute set `{expr,
expected}`, denoting an expression and its expected result. The
result is a list of failed tests, each represented as `{name,
expected, actual}`, denoting the attribute name of the failing
test and its expected and actual results.
Used for regression testing of the functions in lib; see
tests.nix for more examples.
tests.nix for an example. Only tests having names starting with
"test" are run.
Important: Only attributes that start with `test` are executed.
- If you want to run only a subset of the tests add the attribute `tests = ["testName"];`
Example:
runTests {
testAndOk = {
expr = lib.and true false;
expected = false;
};
testAndFail = {
expr = lib.and true false;
expected = true;
};
}
->
[
{
name = "testAndFail";
expected = true;
result = false;
}
]
Type:
runTests :: {
tests = [ String ];
${testName} :: {
expr :: a;
expected :: a;
};
}
->
[
{
name :: String;
expected :: a;
result :: a;
}
]
Add attr { tests = ["testName"]; } to run these tests only.
*/
runTests =
# Tests to run
@@ -250,4 +202,90 @@ rec {
{ testX = allTrue [ true ]; }
*/
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
# -- DEPRECATED --
traceShowVal = x: trace (showVal x) x;
traceShowValMarked = str: x: trace (str + showVal x) x;
attrNamesToStr = a:
trace ( "Warning: `attrNamesToStr` is deprecated "
+ "and will be removed in the next release. "
+ "Please use more specific concatenation "
+ "for your uses (`lib.concat(Map)StringsSep`)." )
(concatStringsSep "; " (map (x: "${x}=") (attrNames a)));
showVal =
trace ( "Warning: `showVal` is deprecated "
+ "and will be removed in the next release, "
+ "please use `traceSeqN`" )
(let
modify = v:
let pr = f: { __pretty = f; val = v; };
in if isDerivation v then pr
(drv: "<δ:${drv.name}:${concatStringsSep ","
(attrNames drv)}>")
else if [] == v then pr (const "[]")
else if isList v then pr (l: "[ ${go (head l)}, ]")
else if isAttrs v then pr
(a: "{ ${ concatStringsSep ", " (attrNames a)} }")
else v;
go = x: generators.toPretty
{ allowPrettyValues = true; }
(modify x);
in go);
traceXMLVal = x:
trace ( "Warning: `traceXMLVal` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `traceValFn builtins.toXML`." )
(trace (builtins.toXML x) x);
traceXMLValMarked = str: x:
trace ( "Warning: `traceXMLValMarked` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `traceValFn (x: str + builtins.toXML x)`." )
(trace (str + builtins.toXML x) x);
# trace the arguments passed to function and its result
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough
traceCall = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
traceValIfNot = c: x:
trace ( "Warning: `traceValIfNot` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `if/then/else` and `traceValSeq 1`.")
(if c x then true else traceSeq (showVal x) false);
addErrorContextToAttrs = attrs:
trace ( "Warning: `addErrorContextToAttrs` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `builtins.addErrorContext` directly." )
(mapAttrs (a: v: addErrorContext "while evaluating ${a}" v) attrs);
# example: (traceCallXml "myfun" id 3) will output something like
# calling myfun arg 1: 3 result: 3
# this forces deep evaluation of all arguments and the result!
# note: if result doesn't evaluate you'll get no trace at all (FIXME)
# args should be printed in any case
traceCallXml = a:
trace ( "Warning: `traceCallXml` is deprecated "
+ "and will be removed in the next release. "
+ "Please complain if you use the function regularly." )
(if !isInt a then
traceCallXml 1 "calling ${a}\n"
else
let nr = a;
in (str: expr:
if isFunction expr then
(arg:
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (builtins.seq arg arg)}" (expr arg)
)
else
let r = builtins.seq expr expr;
in trace "${str}\n result:\n${builtins.toXML r}" r
));
}

View File

@@ -78,7 +78,7 @@ let
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs
filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
mapAttrs' mapAttrsToList concatMapAttrs mapAttrsRecursive mapAttrsRecursiveCond
genAttrs isDerivation toDerivation optionalAttrs
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
@@ -100,7 +100,7 @@ let
escapeShellArg escapeShellArgs
isStorePath isStringLike
isValidPosixName toShellVar toShellVars
escapeRegex escapeURL escapeXML replaceChars lowerChars
escapeRegex escapeXML replaceChars lowerChars
upperChars toLower toUpper addContextFrom splitString
removePrefix removeSuffix versionOlder versionAtLeast
getName getVersion
@@ -145,10 +145,11 @@ let
isOptionType mkOptionType;
inherit (self.asserts)
assertMsg assertOneOf;
inherit (self.debug) traceIf traceVal traceValFn
traceSeq traceSeqN traceValSeq
traceValSeqFn traceValSeqN traceValSeqNFn traceFnSeqN
runTests testAllTrue;
inherit (self.debug) addErrorContextToAttrs traceIf traceVal traceValFn
traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq
traceValSeqFn traceValSeqN traceValSeqNFn traceFnSeqN traceShowVal
traceShowValMarked showVal traceCall traceCall2 traceCall3
traceValIfNot runTests testAllTrue traceCallXml attrNamesToStr;
inherit (self.misc) maybeEnv defaultMergeArg defaultMerge foldArgs
maybeAttrNullable maybeAttr ifEnable checkFlag getValue
checkReqs uniqList uniqListExt condConcat lazyGenericClosure

View File

@@ -422,85 +422,8 @@ ${expr "" v}
(if v then "True" else "False")
else if isFunction v then
abort "generators.toDhall: cannot convert a function to Dhall"
else if v == null then
else if isNull v then
abort "generators.toDhall: cannot convert a null to Dhall"
else
builtins.toJSON v;
/*
Translate a simple Nix expression to Lua representation with occasional
Lua-inlines that can be construted by mkLuaInline function.
Configuration:
* multiline - by default is true which results in indented block-like view.
* indent - initial indent.
Attention:
Regardless of multiline parameter there is no trailing newline.
Example:
generators.toLua {}
{
cmd = [ "typescript-language-server" "--stdio" ];
settings.workspace.library = mkLuaInline ''vim.api.nvim_get_runtime_file("", true)'';
}
->
{
["cmd"] = {
"typescript-language-server",
"--stdio"
},
["settings"] = {
["workspace"] = {
["library"] = (vim.api.nvim_get_runtime_file("", true))
}
}
}
Type:
toLua :: AttrSet -> Any -> String
*/
toLua = {
/* If this option is true, the output is indented with newlines for attribute sets and lists */
multiline ? true,
/* Initial indentation level */
indent ? ""
}@args: v:
with builtins;
let
innerIndent = "${indent} ";
introSpace = if multiline then "\n${innerIndent}" else " ";
outroSpace = if multiline then "\n${indent}" else " ";
innerArgs = args // { indent = innerIndent; };
concatItems = concatStringsSep ",${introSpace}";
isLuaInline = { _type ? null, ... }: _type == "lua-inline";
in
if v == null then
"nil"
else if isInt v || isFloat v || isString v || isBool v then
builtins.toJSON v
else if isList v then
(if v == [ ] then "{}" else
"{${introSpace}${concatItems (map (value: "${toLua innerArgs value}") v)}${outroSpace}}")
else if isAttrs v then
(
if isLuaInline v then
"(${v.expr})"
else if v == { } then
"{}"
else
"{${introSpace}${concatItems (
lib.attrsets.mapAttrsToList (key: value: "[${builtins.toJSON key}] = ${toLua innerArgs value}") v
)}${outroSpace}}"
)
else
abort "generators.toLua: type ${typeOf v} is unsupported";
/*
Mark string as Lua expression to be inlined when processed by toLua.
Type:
mkLuaInline :: String -> AttrSet
*/
mkLuaInline = expr: { _type = "lua-inline"; inherit expr; };
}

View File

@@ -81,6 +81,7 @@ in mkLicense lset) ({
apsl10 = {
spdxId = "APSL-1.0";
fullName = "Apple Public Source License 1.0";
url = "https://web.archive.org/web/20040701000000*/http://www.opensource.apple.com/apsl/1.0.txt";
};
apsl20 = {
@@ -108,11 +109,6 @@ in mkLicense lset) ({
fullName = "Apache License 2.0";
};
asl20-llvm = {
spdxId = "Apache-2.0 WITH LLVM-exception";
fullName = "Apache License 2.0 with LLVM Exceptions";
};
bitstreamVera = {
spdxId = "Bitstream-Vera";
fullName = "Bitstream Vera Font License";
@@ -224,12 +220,6 @@ in mkLicense lset) ({
fullName = "Creative Commons Zero v1.0 Universal";
};
cc-by-nc-nd-30 = {
spdxId = "CC-BY-NC-ND-3.0";
fullName = "Creative Commons Attribution Non Commercial No Derivative Works 3.0 Unported";
free = false;
};
cc-by-nc-sa-20 = {
spdxId = "CC-BY-NC-SA-2.0";
fullName = "Creative Commons Attribution Non Commercial Share Alike 2.0";
@@ -667,6 +657,11 @@ in mkLicense lset) ({
url = "https://opensource.franz.com/preamble.html";
};
llvm-exception = {
spdxId = "LLVM-exception";
fullName = "LLVM Exception"; # LLVM exceptions to the Apache 2.0 License
};
lppl12 = {
spdxId = "LPPL-1.2";
fullName = "LaTeX Project Public License v1.2";
@@ -909,13 +904,6 @@ in mkLicense lset) ({
url = "https://github.com/thestk/stk/blob/master/LICENSE";
};
tsl = {
shortName = "TSL";
fullName = "Timescale License Agreegment";
url = "https://github.com/timescale/timescaledb/blob/main/tsl/LICENSE-TIMESCALE";
unfree = true;
};
tcltk = {
spdxId = "TCL";
fullName = "TCL/TK License";

View File

@@ -21,7 +21,6 @@ let
isBool
isFunction
isList
isPath
isString
length
mapAttrs
@@ -46,9 +45,6 @@ let
showOption
unknownModule
;
inherit (lib.strings)
isConvertibleWithToString
;
showDeclPrefix = loc: decl: prefix:
" - option(s) with prefix `${showOption (loc ++ [prefix])}' in module `${decl._file}'";
@@ -407,7 +403,7 @@ rec {
key = module.key;
module = module;
modules = collectedImports.modules;
disabled = (if module.disabledModules != [] then [{ file = module._file; disabled = module.disabledModules; }] else []) ++ collectedImports.disabled;
disabled = module.disabledModules ++ collectedImports.disabled;
}) initialModules);
# filterModules :: String -> { disabled, modules } -> [ Module ]
@@ -416,30 +412,10 @@ rec {
# modules recursively. It returns the final list of unique-by-key modules
filterModules = modulesPath: { disabled, modules }:
let
moduleKey = file: m:
if isString m
then
if builtins.substring 0 1 m == "/"
then m
else toString modulesPath + "/" + m
else if isConvertibleWithToString m
then
if m?key && m.key != toString m
then
throw "Module `${file}` contains a disabledModules item that is an attribute set that can be converted to a string (${toString m}) but also has a `.key` attribute (${m.key}) with a different value. This makes it ambiguous which module should be disabled."
else
toString m
else if m?key
then
m.key
else if isAttrs m
then throw "Module `${file}` contains a disabledModules item that is an attribute set, presumably a module, that does not have a `key` attribute. This means that the module system doesn't have any means to identify the module that should be disabled. Make sure that you've put the correct value in disabledModules: a string path relative to modulesPath, a path value, or an attribute set with a `key` attribute."
else throw "Each disabledModules item must be a path, string, or a attribute set with a key attribute, or a value supported by toString. However, one of the disabledModules items in `${toString file}` is none of that, but is of type ${builtins.typeOf m}.";
disabledKeys = concatMap ({ file, disabled }: map (moduleKey file) disabled) disabled;
moduleKey = m: if isString m && (builtins.substring 0 1 m != "/")
then toString modulesPath + "/" + m
else toString m;
disabledKeys = map moduleKey disabled;
keyFilter = filter (attrs: ! elem attrs.key disabledKeys);
in map (attrs: attrs.module) (builtins.genericClosure {
startSet = keyFilter modules;
@@ -567,19 +543,15 @@ rec {
zipAttrsWith (n: concatLists)
(map (module: let subtree = module.${attr}; in
if !(builtins.isAttrs subtree) then
throw (if attr == "config" then ''
You're trying to define a value of type `${builtins.typeOf subtree}'
rather than an attribute set for the option
throw ''
You're trying to declare a value of type `${builtins.typeOf subtree}'
rather than an attribute-set for the option
`${builtins.concatStringsSep "." prefix}'!
This usually happens if `${builtins.concatStringsSep "." prefix}' has option
definitions inside that are not matched. Please check how to properly define
this option by e.g. referring to `man 5 configuration.nix'!
'' else ''
An option declaration for `${builtins.concatStringsSep "." prefix}' has type
`${builtins.typeOf subtree}' rather than an attribute set.
Did you mean to define this outside of `options'?
'')
''
else
mapAttrs (n: f module) subtree
) modules);

View File

@@ -36,9 +36,6 @@ let
inherit (lib.types)
mkOptionType
;
inherit (lib.lists)
last
;
prioritySuggestion = ''
Use `lib.mkForce value` or `lib.mkDefault value` to change the priority on any of these definitions.
'';
@@ -110,26 +107,17 @@ rec {
/* Creates an Option attribute set for an option that specifies the
package a module should use for some purpose.
The package is specified in the third argument under `default` as a list of strings
representing its attribute path in nixpkgs (or another package set).
Because of this, you need to pass nixpkgs itself (or a subset) as the first argument.
The package is specified as a list of strings representing its attribute path in nixpkgs.
The second argument may be either a string or a list of strings.
It provides the display name of the package in the description of the generated option
(using only the last element if the passed value is a list)
and serves as the fallback value for the `default` argument.
Because of this, you need to pass nixpkgs itself as the first argument.
To include extra information in the description, pass `extraDescription` to
append arbitrary text to the generated description.
You can also pass an `example` value, either a literal string or an attribute path.
The second argument is the name of the option, used in the description "The <name> package to use.".
The default argument can be omitted if the provided name is
an attribute of pkgs (if name is a string) or a
valid attribute path in pkgs (if name is a list).
You can also pass an example value, either a literal string or a package's attribute path.
If you wish to explicitly provide no default, pass `null` as `default`.
You can omit the default path if the name of the option is also attribute path in nixpkgs.
Type: mkPackageOption :: pkgs -> (string|[string]) -> { default? :: [string], example? :: null|string|[string], extraDescription? :: string } -> option
Type: mkPackageOption :: pkgs -> string -> { default :: [string]; example :: null | string | [string]; } -> option
Example:
mkPackageOption pkgs "hello" { }
@@ -141,46 +129,27 @@ rec {
example = "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
}
=> { _type = "option"; default = «derivation /nix/store/jxx55cxsjrf8kyh3fp2ya17q99w7541r-ghc-8.10.7.drv»; defaultText = { ... }; description = "The GHC package to use."; example = { ... }; type = { ... }; }
Example:
mkPackageOption pkgs [ "python39Packages" "pytorch" ] {
extraDescription = "This is an example and doesn't actually do anything.";
}
=> { _type = "option"; default = «derivation /nix/store/gvqgsnc4fif9whvwd9ppa568yxbkmvk8-python3.9-pytorch-1.10.2.drv»; defaultText = { ... }; description = "The pytorch package to use. This is an example and doesn't actually do anything."; type = { ... }; }
*/
mkPackageOption =
# Package set (a specific version of nixpkgs or a subset)
# Package set (a specific version of nixpkgs)
pkgs:
# Name for the package, shown in option description
name:
{
# The attribute path where the default package is located (may be omitted)
default ? name,
# A string or an attribute path to use as an example (may be omitted)
example ? null,
# Additional text to include in the option description (may be omitted)
extraDescription ? "",
}:
let
name' = if isList name then last name else name;
default' = if isList default then default else [ default ];
defaultPath = concatStringsSep "." default';
defaultValue = attrByPath default'
(throw "${defaultPath} cannot be found in pkgs") pkgs;
{ default ? [ name ], example ? null }:
let default' = if !isList default then [ default ] else default;
in mkOption {
defaultText = literalExpression ("pkgs." + defaultPath);
type = lib.types.package;
description = "The ${name'} package to use."
+ (if extraDescription == "" then "" else " ") + extraDescription;
${if default != null then "default" else null} = defaultValue;
description = "The ${name} package to use.";
default = attrByPath default'
(throw "${concatStringsSep "." default'} cannot be found in pkgs") pkgs;
defaultText = literalExpression ("pkgs." + concatStringsSep "." default');
${if example != null then "example" else null} = literalExpression
(if isList example then "pkgs." + concatStringsSep "." example else example);
};
/* Like mkPackageOption, but emit an mdDoc description instead of DocBook. */
mkPackageOptionMD = pkgs: name: extra:
let option = mkPackageOption pkgs name extra;
mkPackageOptionMD = args: name: extra:
let option = mkPackageOption args name extra;
in option // { description = lib.mdDoc option.description; };
/* This option accepts anything, but it does not produce any result.
@@ -368,17 +337,19 @@ rec {
# Helper functions.
/* Convert an option, described as a list of the option parts to a
human-readable version.
/* Convert an option, described as a list of the option parts in to a
safe, human readable version.
Example:
(showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
(showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
(showOption ["windowManager" "2bwm" "enable"]) == "windowManager.\"2bwm\".enable"
(showOption ["foo" "bar.baz" "tux"]) == "foo.bar.baz.tux"
Placeholders will not be quoted as they are not actual values:
(showOption ["foo" "*" "bar"]) == "foo.*.bar"
(showOption ["foo" "<name>" "bar"]) == "foo.<name>.bar"
Unlike attributes, options can also start with numbers:
(showOption ["windowManager" "2bwm" "enable"]) == "windowManager.2bwm.enable"
*/
showOption = parts: let
escapeOptionPart = part:

View File

@@ -15,9 +15,6 @@ let
last
genList
elemAt
all
concatMap
foldl'
;
inherit (lib.strings)
@@ -193,80 +190,6 @@ in /* No rec! Add dependencies on this file at the top. */ {
subpathInvalidReason value == null;
/* Join subpath strings together using `/`, returning a normalised subpath string.
Like `concatStringsSep "/"` but safer, specifically:
- All elements must be valid subpath strings, see `lib.path.subpath.isValid`
- The result gets normalised, see `lib.path.subpath.normalise`
- The edge case of an empty list gets properly handled by returning the neutral subpath `"./."`
Laws:
- Associativity:
subpath.join [ x (subpath.join [ y z ]) ] == subpath.join [ (subpath.join [ x y ]) z ]
- Identity - `"./."` is the neutral element for normalised paths:
subpath.join [ ] == "./."
subpath.join [ (subpath.normalise p) "./." ] == subpath.normalise p
subpath.join [ "./." (subpath.normalise p) ] == subpath.normalise p
- Normalisation - the result is normalised according to `lib.path.subpath.normalise`:
subpath.join ps == subpath.normalise (subpath.join ps)
- For non-empty lists, the implementation is equivalent to normalising the result of `concatStringsSep "/"`.
Note that the above laws can be derived from this one.
ps != [] -> subpath.join ps == subpath.normalise (concatStringsSep "/" ps)
Type:
subpath.join :: [ String ] -> String
Example:
subpath.join [ "foo" "bar/baz" ]
=> "./foo/bar/baz"
# normalise the result
subpath.join [ "./foo" "." "bar//./baz/" ]
=> "./foo/bar/baz"
# passing an empty list results in the current directory
subpath.join [ ]
=> "./."
# elements must be valid subpath strings
subpath.join [ /foo ]
=> <error>
subpath.join [ "" ]
=> <error>
subpath.join [ "/foo" ]
=> <error>
subpath.join [ "../foo" ]
=> <error>
*/
subpath.join =
# The list of subpaths to join together
subpaths:
# Fast in case all paths are valid
if all isValid subpaths
then joinRelPath (concatMap splitRelPath subpaths)
else
# Otherwise we take our time to gather more info for a better error message
# Strictly go through each path, throwing on the first invalid one
# Tracks the list index in the fold accumulator
foldl' (i: path:
if isValid path
then i + 1
else throw ''
lib.path.subpath.join: Element at index ${toString i} is not a valid subpath string:
${subpathInvalidReason path}''
) 0 subpaths;
/* Normalise a subpath. Throw an error if the subpath isn't valid, see
`lib.path.subpath.isValid`

View File

@@ -107,36 +107,6 @@ let
expected = true;
};
# Test examples from the lib.path.subpath.join documentation
testSubpathJoinExample1 = {
expr = subpath.join [ "foo" "bar/baz" ];
expected = "./foo/bar/baz";
};
testSubpathJoinExample2 = {
expr = subpath.join [ "./foo" "." "bar//./baz/" ];
expected = "./foo/bar/baz";
};
testSubpathJoinExample3 = {
expr = subpath.join [ ];
expected = "./.";
};
testSubpathJoinExample4 = {
expr = (builtins.tryEval (subpath.join [ /foo ])).success;
expected = false;
};
testSubpathJoinExample5 = {
expr = (builtins.tryEval (subpath.join [ "" ])).success;
expected = false;
};
testSubpathJoinExample6 = {
expr = (builtins.tryEval (subpath.join [ "/foo" ])).success;
expected = false;
};
testSubpathJoinExample7 = {
expr = (builtins.tryEval (subpath.join [ "../foo" ])).success;
expected = false;
};
# Test examples from the lib.path.subpath.normalise documentation
testSubpathNormaliseExample1 = {
expr = subpath.normalise "foo//bar";

View File

@@ -2,11 +2,7 @@
{ lib }:
let
inherit (builtins) length;
inherit (lib.trivial) warnIf;
asciiTable = import ./ascii-table.nix;
inherit (builtins) length;
in
@@ -209,20 +205,7 @@ rec {
normalizePath "/a//b///c/"
=> "/a/b/c/"
*/
normalizePath = s:
warnIf
(isPath s)
''
lib.strings.normalizePath: The argument (${toString s}) is a path value, but only strings are supported.
Path values are always normalised in Nix, so there's no need to call this function on them.
This function also copies the path to the Nix store and returns the store path, the same as "''${path}" will, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(
builtins.foldl'
(x: y: if y == "/" && hasSuffix "/" x then x else x+y)
""
(stringToCharacters s)
);
normalizePath = s: (builtins.foldl' (x: y: if y == "/" && hasSuffix "/" x then x else x+y) "" (stringToCharacters s));
/* Depending on the boolean `cond', return either the given string
or the empty string. Useful to concatenate against a bigger string.
@@ -255,17 +238,7 @@ rec {
# Prefix to check for
pref:
# Input string
str:
# Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath pref)
''
lib.strings.hasPrefix: The first argument (${toString pref}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(substring 0 (stringLength pref) str == pref);
str: substring 0 (stringLength pref) str == pref;
/* Determine whether a string has given suffix.
@@ -285,20 +258,8 @@ rec {
let
lenContent = stringLength content;
lenSuffix = stringLength suffix;
in
# Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath suffix)
''
lib.strings.hasSuffix: The first argument (${toString suffix}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(
lenContent >= lenSuffix
&& substring (lenContent - lenSuffix) lenContent content == suffix
);
in lenContent >= lenSuffix &&
substring (lenContent - lenSuffix) lenContent content == suffix;
/* Determine whether a string contains the given infix
@@ -315,16 +276,7 @@ rec {
=> false
*/
hasInfix = infix: content:
# Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath infix)
''
lib.strings.hasInfix: The first argument (${toString infix}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(builtins.match ".*${escapeRegex infix}.*" "${content}" != null);
builtins.match ".*${escapeRegex infix}.*" "${content}" != null;
/* Convert a string to a list of characters (i.e. singleton strings).
This allows you to, e.g., map a function over each character. However,
@@ -375,7 +327,9 @@ rec {
=> 40
*/
charToInt = c: builtins.getAttr c asciiTable;
charToInt = let
table = import ./ascii-table.nix;
in c: builtins.getAttr c table;
/* Escape occurrence of the elements of `list` in `string` by
prefixing it with a backslash.
@@ -401,21 +355,6 @@ rec {
*/
escapeC = list: replaceStrings list (map (c: "\\x${ toLower (lib.toHexString (charToInt c))}") list);
/* Escape the string so it can be safely placed inside a URL
query.
Type: escapeURL :: string -> string
Example:
escapeURL "foo/bar baz"
=> "foo%2Fbar%20baz"
*/
escapeURL = let
unreserved = [ "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "-" "_" "." "~" ];
toEscape = builtins.removeAttrs asciiTable unreserved;
in
replaceStrings (builtins.attrNames toEscape) (lib.mapAttrsToList (_: c: "%${fixedWidthString 2 "0" (lib.toHexString c)}") toEscape);
/* Quote string to be used safely within the Bourne shell.
Type: escapeShellArg :: string -> string
@@ -616,23 +555,14 @@ rec {
prefix:
# Input string
str:
# Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath prefix)
''
lib.strings.removePrefix: The first argument (${toString prefix}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function never removes any prefix in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(let
let
preLen = stringLength prefix;
sLen = stringLength str;
in
if substring 0 preLen str == prefix then
if hasPrefix prefix str then
substring preLen (sLen - preLen) str
else
str);
str;
/* Return a string without the specified suffix, if the suffix matches.
@@ -649,23 +579,14 @@ rec {
suffix:
# Input string
str:
# Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath suffix)
''
lib.strings.removeSuffix: The first argument (${toString suffix}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function never removes any suffix in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(let
let
sufLen = stringLength suffix;
sLen = stringLength str;
in
if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str then
substring 0 (sLen - sufLen) str
else
str);
str;
/* Return true if string v1 denotes a version older than v2.

View File

@@ -136,12 +136,10 @@ rec {
else if final.isPower then "powerpc"
else if final.isRiscV then "riscv"
else if final.isS390 then "s390"
else if final.isLoongArch64 then "loongarch"
else final.parsed.cpu.name;
qemuArch =
if final.isAarch32 then "arm"
else if final.isS390 && !final.isS390x then null
else if final.isx86_64 then "x86_64"
else if final.isx86 then "i386"
else final.uname.processor;
@@ -186,7 +184,6 @@ rec {
pulseSupport = false;
smbdSupport = false;
seccompSupport = false;
enableDocs = false;
hostCpuTargets = [ "${final.qemuArch}-linux-user" ];
};
wine = (pkgs.winePackagesFor "wine${toString final.parsed.cpu.bits}").minimal;
@@ -196,7 +193,7 @@ rec {
then "${pkgs.runtimeShell} -c '\"$@\"' --"
else if final.isWindows
then "${wine}/bin/wine${lib.optionalString (final.parsed.cpu.bits == 64) "64"}"
else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux && final.qemuArch != null
else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux
then "${qemu-user}/bin/qemu-${final.qemuArch}"
else if final.isWasi
then "${pkgs.wasmtime}/bin/wasmtime"

View File

@@ -22,11 +22,11 @@ let
"x86_64-solaris"
# JS
"javascript-ghcjs"
"js-ghcjs"
# Linux
"aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux"
"armv7l-linux" "i686-linux" "loongarch64-linux" "m68k-linux" "microblaze-linux"
"armv7l-linux" "i686-linux" "m68k-linux" "microblaze-linux"
"microblazeel-linux" "mipsel-linux" "mips64el-linux" "powerpc64-linux"
"powerpc64le-linux" "riscv32-linux" "riscv64-linux" "s390-linux"
"s390x-linux" "x86_64-linux"
@@ -86,7 +86,6 @@ in {
m68k = filterDoubles predicates.isM68k;
s390 = filterDoubles predicates.isS390;
s390x = filterDoubles predicates.isS390x;
loongarch64 = filterDoubles predicates.isLoongArch64;
js = filterDoubles predicates.isJavaScript;
bigEndian = filterDoubles predicates.isBigEndian;

View File

@@ -90,10 +90,6 @@ rec {
config = "mipsel-unknown-linux-gnu";
} // platforms.fuloong2f_n32;
loongarch64-linux = {
config = "loongarch64-unknown-linux-gnu";
};
# can execute on 32bit chip
mips-linux-gnu = { config = "mips-unknown-linux-gnu"; } // platforms.gcc_mips32r2_o32;
mipsel-linux-gnu = { config = "mipsel-unknown-linux-gnu"; } // platforms.gcc_mips32r2_o32;
@@ -333,9 +329,6 @@ rec {
# Ghcjs
ghcjs = {
# This triple is special to GHC/Cabal/GHCJS and not recognized by autotools
# See: https://gitlab.haskell.org/ghc/ghc/-/commit/6636b670233522f01d002c9b97827d00289dbf5c
# https://github.com/ghcjs/ghcjs/issues/53
config = "javascript-unknown-ghcjs";
config = "js-unknown-ghcjs";
};
}

View File

@@ -9,14 +9,6 @@ let abis = lib.mapAttrs (_: abi: builtins.removeAttrs abi [ "assertions" ]) abis
rec {
# these patterns are to be matched against {host,build,target}Platform.parsed
patterns = rec {
# The patterns below are lists in sum-of-products form.
#
# Each attribute is list of product conditions; non-list values are treated
# as a singleton list. If *any* product condition in the list matches then
# the predicate matches. Each product condition is tested by
# `lib.attrsets.matchAttrs`, which requires a match on *all* attributes of
# the product.
isi686 = { cpu = cpuTypes.i686; };
isx86_32 = { cpu = { family = "x86"; bits = 32; }; };
isx86_64 = { cpu = { family = "x86"; bits = 64; }; };
@@ -57,8 +49,7 @@ rec {
isM68k = { cpu = { family = "m68k"; }; };
isS390 = { cpu = { family = "s390"; }; };
isS390x = { cpu = { family = "s390"; bits = 64; }; };
isLoongArch64 = { cpu = { family = "loongarch"; bits = 64; }; };
isJavaScript = { cpu = cpuTypes.javascript; };
isJavaScript = { cpu = cpuTypes.js; };
is32bit = { cpu = { bits = 32; }; };
is64bit = { cpu = { bits = 64; }; };

View File

@@ -131,9 +131,7 @@ rec {
or1k = { bits = 32; significantByte = bigEndian; family = "or1k"; };
loongarch64 = { bits = 64; significantByte = littleEndian; family = "loongarch"; };
javascript = { bits = 32; significantByte = littleEndian; family = "javascript"; };
js = { bits = 32; significantByte = littleEndian; family = "js"; };
};
# GNU build systems assume that older NetBSD architectures are using a.out.
@@ -184,13 +182,24 @@ rec {
(b == armv7l && isCompatible a armv7a)
(b == armv7l && isCompatible a armv7r)
(b == armv7l && isCompatible a armv7m)
(b == armv7a && isCompatible a armv8a)
(b == armv7r && isCompatible a armv8a)
(b == armv7m && isCompatible a armv8a)
(b == armv7a && isCompatible a armv8r)
(b == armv7r && isCompatible a armv8r)
(b == armv7m && isCompatible a armv8r)
(b == armv7a && isCompatible a armv8m)
(b == armv7r && isCompatible a armv8m)
(b == armv7m && isCompatible a armv8m)
# ARMv8
(b == aarch64 && a == armv8a)
(b == armv8a && isCompatible a aarch64)
(b == armv8r && isCompatible a armv8a)
(b == armv8m && isCompatible a armv8a)
# XXX: not always true! Some arm64 cpus dont support arm32 mode.
(b == aarch64 && a == armv8a)
(b == armv8a && isCompatible a aarch64)
# PowerPC
(b == powerpc && isCompatible a powerpc64)
(b == powerpcle && isCompatible a powerpc64le)

View File

@@ -347,15 +347,6 @@ runTests {
expected = "Hello\\x20World";
};
testEscapeURL = testAllTrue [
("" == strings.escapeURL "")
("Hello" == strings.escapeURL "Hello")
("Hello%20World" == strings.escapeURL "Hello World")
("Hello%2FWorld" == strings.escapeURL "Hello/World")
("42%25" == strings.escapeURL "42%")
("%20%3F%26%3D%23%2B%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%09%3A%2F%40%24%27%28%29%2A%2C%3B" == strings.escapeURL " ?&=#+%!<>#\"{}|\\^[]`\t:/@$'()*,;")
];
testToInt = testAllTrue [
# Naive
(123 == toInt "123")
@@ -533,37 +524,6 @@ runTests {
};
};
# code from example
testFoldlAttrs = {
expr = {
example = foldlAttrs
(acc: name: value: {
sum = acc.sum + value;
names = acc.names ++ [ name ];
})
{ sum = 0; names = [ ]; }
{
foo = 1;
bar = 10;
};
# should just return the initial value
emptySet = foldlAttrs (throw "function not needed") 123 { };
# should just evaluate to the last value
accNotNeeded = foldlAttrs (_acc: _name: v: v) (throw "accumulator not needed") { z = 3; a = 2; };
# the accumulator doesnt have to be an attrset it can be as trivial as being just a number or string
trivialAcc = foldlAttrs (acc: _name: v: acc * 10 + v) 1 { z = 1; a = 2; };
};
expected = {
example = {
sum = 11;
names = [ "bar" "foo" ];
};
emptySet = 123;
accNotNeeded = 3;
trivialAcc = 121;
};
};
# code from the example
testRecursiveUpdateUntil = {
expr = recursiveUpdateUntil (path: l: r: path == ["foo"]) {
@@ -915,72 +875,6 @@ runTests {
};
testToLuaEmptyAttrSet = {
expr = generators.toLua {} {};
expected = ''{}'';
};
testToLuaEmptyList = {
expr = generators.toLua {} [];
expected = ''{}'';
};
testToLuaListOfVariousTypes = {
expr = generators.toLua {} [ null 43 3.14159 true ];
expected = ''
{
nil,
43,
3.14159,
true
}'';
};
testToLuaString = {
expr = generators.toLua {} ''double-quote (") and single quotes (')'';
expected = ''"double-quote (\") and single quotes (')"'';
};
testToLuaAttrsetWithLuaInline = {
expr = generators.toLua {} { x = generators.mkLuaInline ''"abc" .. "def"''; };
expected = ''
{
["x"] = ("abc" .. "def")
}'';
};
testToLuaAttrsetWithSpaceInKey = {
expr = generators.toLua {} { "some space and double-quote (\")" = 42; };
expected = ''
{
["some space and double-quote (\")"] = 42
}'';
};
testToLuaWithoutMultiline = {
expr = generators.toLua { multiline = false; } [ 41 43 ];
expected = ''{ 41, 43 }'';
};
testToLuaBasicExample = {
expr = generators.toLua {} {
cmd = [ "typescript-language-server" "--stdio" ];
settings.workspace.library = generators.mkLuaInline ''vim.api.nvim_get_runtime_file("", true)'';
};
expected = ''
{
["cmd"] = {
"typescript-language-server",
"--stdio"
},
["settings"] = {
["workspace"] = {
["library"] = (vim.api.nvim_get_runtime_file("", true))
}
}
}'';
};
# CLI
testToGNUCommandLine = {

View File

@@ -141,14 +141,6 @@ checkConfigError "The option .*enable.* does not exist. Definition values:\n\s*-
checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-define-enable.nix ./disable-declare-enable.nix
checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-enable-modules.nix
checkConfigOutput '^true$' 'config.positive.enable' ./disable-module-with-key.nix
checkConfigOutput '^false$' 'config.negative.enable' ./disable-module-with-key.nix
checkConfigError 'Module ..*disable-module-bad-key.nix. contains a disabledModules item that is an attribute set, presumably a module, that does not have a .key. attribute. .*' 'config.enable' ./disable-module-bad-key.nix
# Not sure if we want to keep supporting module keys that aren't strings, paths or v?key, but we shouldn't remove support accidentally.
checkConfigOutput '^true$' 'config.positive.enable' ./disable-module-with-toString-key.nix
checkConfigOutput '^false$' 'config.negative.enable' ./disable-module-with-toString-key.nix
# Check _module.args.
set -- config.enable ./declare-enable.nix ./define-enable-with-custom-arg.nix
checkConfigError 'while evaluating the module argument .*custom.* in .*define-enable-with-custom-arg.nix.*:' "$@"
@@ -189,7 +181,7 @@ checkConfigOutput '^"foo"$' config.submodule.foo ./declare-submoduleWith-special
## shorthandOnlyDefines config behaves as expected
checkConfigOutput '^true$' config.submodule.config ./declare-submoduleWith-shorthand.nix ./define-submoduleWith-shorthand.nix
checkConfigError 'is not of type `boolean' config.submodule.config ./declare-submoduleWith-shorthand.nix ./define-submoduleWith-noshorthand.nix
checkConfigError "You're trying to define a value of type \`bool'\n\s*rather than an attribute set for the option" config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-shorthand.nix
checkConfigError "You're trying to declare a value of type \`bool'\n\s*rather than an attribute-set for the option" config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-shorthand.nix
checkConfigOutput '^true$' config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-noshorthand.nix
## submoduleWith should merge all modules in one swoop
@@ -366,10 +358,6 @@ checkConfigOutput '^"The option `a\.b. defined in `.*/doRename-warnings\.nix. ha
config.result \
./doRename-warnings.nix
# Anonymous modules get deduplicated by key
checkConfigOutput '^"pear"$' config.once.raw ./merge-module-with-key.nix
checkConfigOutput '^"pear\\npear"$' config.twice.raw ./merge-module-with-key.nix
cat <<EOF
====== module tests ======
$pass Pass

View File

@@ -1,16 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
moduleWithKey = { config, ... }: {
config = {
enable = true;
};
};
in
{
imports = [
./declare-enable.nix
];
disabledModules = [ { } ];
}

View File

@@ -1,34 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
moduleWithKey = {
key = "disable-module-with-key.nix#moduleWithKey";
config = {
enable = true;
};
};
in
{
options = {
positive = mkOption {
type = types.submodule {
imports = [
./declare-enable.nix
moduleWithKey
];
};
default = {};
};
negative = mkOption {
type = types.submodule {
imports = [
./declare-enable.nix
moduleWithKey
];
disabledModules = [ moduleWithKey ];
};
default = {};
};
};
}

View File

@@ -1,34 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
moduleWithKey = {
key = 123;
config = {
enable = true;
};
};
in
{
options = {
positive = mkOption {
type = types.submodule {
imports = [
./declare-enable.nix
moduleWithKey
];
};
default = {};
};
negative = mkOption {
type = types.submodule {
imports = [
./declare-enable.nix
moduleWithKey
];
disabledModules = [ 123 ];
};
default = {};
};
};
}

View File

@@ -1,49 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
moduleWithoutKey = {
config = {
raw = "pear";
};
};
moduleWithKey = {
key = __curPos.file + "#moduleWithKey";
config = {
raw = "pear";
};
};
decl = {
options = {
raw = mkOption {
type = types.lines;
};
};
};
in
{
options = {
once = mkOption {
type = types.submodule {
imports = [
decl
moduleWithKey
moduleWithKey
];
};
default = {};
};
twice = mkOption {
type = types.submodule {
imports = [
decl
moduleWithoutKey
moduleWithoutKey
];
};
default = {};
};
};
}

View File

@@ -34,7 +34,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" "mips64el-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64-linux" "powerpc64le-linux" "m68k-linux" "s390-linux" "s390x-linux" "microblaze-linux" "microblazeel-linux" "loongarch64-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" "microblaze-linux" "microblazeel-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" ];

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
let
lib = import ../../lib;
inherit (lib)
add attrNames elemAt foldl' genList length replaceStrings sort toLower trace;
maintainers = import ../maintainer-list.nix;
simplify = replaceStrings [ "-" "_" ] [ "" "" ];
compare = a: b: simplify (toLower a) < simplify (toLower b);
namesSorted =
sort
(a: b: a.key < b.key)
(map
(n: let pos = builtins.unsafeGetAttrPos n maintainers;
in assert pos == null -> throw "maintainers entry ${n} is malformed";
{ name = n; line = pos.line; key = toLower (simplify n); })
(attrNames maintainers));
before = { name, line, key }:
foldl'
(acc: n: if n.key < key && (acc == null || n.key > acc.key) then n else acc)
null
namesSorted;
errors = foldl' add 0
(map
(i: let a = elemAt namesSorted i;
b = elemAt namesSorted (i + 1);
lim = let t = before a; in if t == null then "the initial {" else t.name;
in if a.line >= b.line
then trace
("maintainer ${a.name} (line ${toString a.line}) should be listed "
+ "after ${lim}, not after ${b.name} (line ${toString b.line})")
1
else 0)
(genList (i: i) (length namesSorted - 1)));
in
assert errors == 0; "all good!"
# generate edit commands to sort the list.
# may everything following the last current entry (closing } ff) in the wrong place
# with lib;
# concatStringsSep
# "\n"
# (let first = foldl' (acc: n: if n.line < acc then n.line else acc) 999999999 namesSorted;
# commands = map
# (i: let e = elemAt namesSorted i;
# begin = foldl'
# (acc: n: if n.line < e.line && n.line > acc then n.line else acc)
# 1
# namesSorted;
# end =
# foldl' (acc: n: if n.line > e.line && n.line < acc then n.line else acc)
# 999999999
# namesSorted;
# in "${toString e.line},${toString (end - 1)} p")
# (genList (i: i) (length namesSorted));
# in map
# (c: "sed -ne '${c}' maintainers/maintainer-list.nix")
# ([ "1,${toString (first - 1)} p" ] ++ commands))

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -I nixpkgs=. -i bash -p "import ./maintainers/scripts/convert-to-import-cargo-lock" nix-prefetch-git
convert-to-import-cargo-lock "$@"

View File

@@ -1 +0,0 @@
/target

View File

@@ -1,106 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
[[package]]
name = "basic-toml"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e819b667739967cd44d308b8c7b71305d8bb0729ac44a248aa08f33d01950b4"
dependencies = [
"serde",
]
[[package]]
name = "convert-to-import-cargo-lock"
version = "0.1.0"
dependencies = [
"anyhow",
"basic-toml",
"serde",
"serde_json",
]
[[package]]
name = "itoa"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "proc-macro2"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"

View File

@@ -1,12 +0,0 @@
[package]
name = "convert-to-import-cargo-lock"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = { version = "1.0.69" }
basic-toml = "0.1.1"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"

View File

@@ -1,16 +0,0 @@
with import ../../../. { };
rustPlatform.buildRustPackage {
name = "convert-to-import-cargo-lock";
src = lib.cleanSourceWith {
src = ./.;
filter = name: type:
let
name' = builtins.baseNameOf name;
in
name' != "default.nix" && name' != "target";
};
cargoLock.lockFile = ./Cargo.lock;
}

View File

@@ -1,5 +0,0 @@
with import ../../../. { };
mkShell {
packages = [ rustc cargo clippy rustfmt ] ++ lib.optional stdenv.isDarwin libiconv;
}

View File

@@ -1,241 +0,0 @@
#![warn(clippy::pedantic)]
#![allow(clippy::too_many_lines)]
use anyhow::anyhow;
use serde::Deserialize;
use std::{collections::HashMap, env, fs, path::PathBuf, process::Command};
#[derive(Deserialize)]
struct CargoLock<'a> {
#[serde(rename = "package", borrow)]
packages: Vec<Package<'a>>,
metadata: Option<HashMap<&'a str, &'a str>>,
}
#[derive(Deserialize)]
struct Package<'a> {
name: &'a str,
version: &'a str,
source: Option<&'a str>,
checksum: Option<&'a str>,
}
#[derive(Deserialize)]
struct PrefetchOutput {
sha256: String,
}
fn main() -> anyhow::Result<()> {
let mut hashes = HashMap::new();
let attr_count = env::args().len() - 1;
for (i, attr) in env::args().skip(1).enumerate() {
println!("converting {attr} ({}/{attr_count})", i + 1);
convert(&attr, &mut hashes)?;
}
Ok(())
}
fn convert(attr: &str, hashes: &mut HashMap<String, String>) -> anyhow::Result<()> {
let package_path = nix_eval(format!("{attr}.meta.position"))?
.and_then(|p| p.split_once(':').map(|(f, _)| PathBuf::from(f)));
if package_path.is_none() {
eprintln!("can't automatically convert {attr}: doesn't exist");
return Ok(());
}
let package_path = package_path.unwrap();
if package_path.with_file_name("Cargo.lock").exists() {
eprintln!("skipping {attr}: already has a vendored Cargo.lock");
return Ok(());
}
let mut src = PathBuf::from(
String::from_utf8(
Command::new("nix-build")
.arg("-A")
.arg(format!("{attr}.src"))
.output()?
.stdout,
)?
.trim(),
);
if !src.exists() {
eprintln!("can't automatically convert {attr}: src doesn't exist (bad attr?)");
return Ok(());
} else if !src.metadata()?.is_dir() {
eprintln!("can't automatically convert {attr}: src isn't a directory");
return Ok(());
}
if let Some(mut source_root) = nix_eval(format!("{attr}.sourceRoot"))?.map(PathBuf::from) {
source_root = source_root.components().skip(1).collect();
src.push(source_root);
}
let cargo_lock_path = src.join("Cargo.lock");
if !cargo_lock_path.exists() {
eprintln!("can't automatically convert {attr}: src doesn't contain Cargo.lock");
return Ok(());
}
let cargo_lock_content = fs::read_to_string(cargo_lock_path)?;
let cargo_lock: CargoLock = basic_toml::from_str(&cargo_lock_content)?;
let mut git_dependencies = Vec::new();
for package in cargo_lock.packages.iter().filter(|p| {
p.source.is_some()
&& p.checksum
.or_else(|| {
cargo_lock
.metadata
.as_ref()?
.get(
format!("checksum {} {} ({})", p.name, p.version, p.source.unwrap())
.as_str(),
)
.copied()
})
.is_none()
}) {
let (typ, original_url) = package
.source
.unwrap()
.split_once('+')
.expect("dependency should have well-formed source url");
if let Some(hash) = hashes.get(original_url) {
continue;
}
assert_eq!(
typ, "git",
"packages without checksums should be git dependencies"
);
let (mut url, rev) = original_url
.split_once('#')
.expect("git dependency should have commit");
// TODO: improve
if let Some((u, _)) = url.split_once('?') {
url = u;
}
let prefetch_output: PrefetchOutput = serde_json::from_slice(
&Command::new("nix-prefetch-git")
.args(["--url", url, "--rev", rev, "--quiet", "--fetch-submodules"])
.output()?
.stdout,
)?;
let output_hash = String::from_utf8(
Command::new("nix")
.args([
"--extra-experimental-features",
"nix-command",
"hash",
"to-sri",
"--type",
"sha256",
&prefetch_output.sha256,
])
.output()?
.stdout,
)?;
let hash = output_hash.trim().to_string();
git_dependencies.push((
format!("{}-{}", package.name, package.version),
output_hash.trim().to_string().clone(),
));
hashes.insert(original_url.to_string(), hash);
}
fs::write(
package_path.with_file_name("Cargo.lock"),
cargo_lock_content,
)?;
let mut package_lines: Vec<_> = fs::read_to_string(&package_path)?
.lines()
.map(String::from)
.collect();
let (cargo_deps_line_index, cargo_deps_line) = package_lines
.iter_mut()
.enumerate()
.find(|(_, l)| {
l.trim_start().starts_with("cargoHash") || l.trim_start().starts_with("cargoSha256")
})
.expect("package should contain cargoHash/cargoSha256");
let spaces = " ".repeat(cargo_deps_line.len() - cargo_deps_line.trim_start().len());
if git_dependencies.is_empty() {
*cargo_deps_line = format!("{spaces}cargoLock.lockFile = ./Cargo.lock;");
} else {
*cargo_deps_line = format!("{spaces}cargoLock = {{");
let mut index_iter = cargo_deps_line_index + 1..;
package_lines.insert(
index_iter.next().unwrap(),
format!("{spaces} lockFile = ./Cargo.lock;"),
);
package_lines.insert(
index_iter.next().unwrap(),
format!("{spaces} outputHashes = {{"),
);
for ((dep, hash), index) in git_dependencies.drain(..).zip(&mut index_iter) {
package_lines.insert(index, format!("{spaces} {dep:?} = {hash:?};"));
}
package_lines.insert(index_iter.next().unwrap(), format!("{spaces} }};"));
package_lines.insert(index_iter.next().unwrap(), format!("{spaces}}};"));
}
if package_lines.last().map(String::as_str) != Some("") {
package_lines.push(String::new());
}
fs::write(package_path, package_lines.join("\n"))?;
Ok(())
}
fn nix_eval(attr: impl AsRef<str>) -> anyhow::Result<Option<String>> {
let output = String::from_utf8(
Command::new("nix-instantiate")
.args(["--eval", "-A", attr.as_ref()])
.output()?
.stdout,
)?;
let trimmed = output.trim();
if trimmed.is_empty() || trimmed == "null" {
Ok(None)
} else {
Ok(Some(
trimmed
.strip_prefix('"')
.and_then(|p| p.strip_suffix('"'))
.ok_or_else(|| anyhow!("couldn't parse nix-instantiate output: {output:?}"))?
.to_string(),
))
}
}

View File

@@ -127,7 +127,8 @@ echo "$urllist" | xargs wget $wgetargs -nH -r -c --no-parent && {
# TODO fetch only missing tar.xz files
echo "fetching $filecount tar.xz files ..."
echo "$filelist" | xargs wget $wgetargs -nH -r -c --no-parent
urllist="$(echo "$filelist" | while read file; do echo "$BASE_URL/$file"; done)"
echo "$urllist" | xargs wget $wgetargs -nH -r -c --no-parent
echo "generating sha256 files ..."
find . -type f -name '*.tar.xz' | while read src; do

View File

@@ -3,7 +3,7 @@ let
pkgs = import ../../.. {};
inherit (pkgs) lib;
getDeps = _: pkg: {
deps = builtins.filter (x: x != null) (map (x: x.pname or null) (pkg.propagatedBuildInputs or []));
deps = builtins.filter (x: !isNull x) (map (x: x.pname or null) (pkg.propagatedBuildInputs or []));
broken = (pkg.meta.hydraPlatforms or [null]) == [];
};
in

View File

@@ -19,8 +19,6 @@ Because step 1) is quite expensive and takes roughly ~5 minutes the result is ca
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
@@ -28,13 +26,11 @@ Because step 1) is quite expensive and takes roughly ~5 minutes the result is ca
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE DataKinds #-}
import Control.Monad (forM_, (<=<))
import Control.Monad.Trans (MonadIO (liftIO))
import Data.Aeson (
FromJSON,
FromJSONKey,
ToJSON,
decodeFileStrict',
eitherDecodeStrict',
@@ -54,27 +50,21 @@ import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Text.Encoding (encodeUtf8)
import qualified Data.Text.IO as Text
import Data.Time (defaultTimeLocale, formatTime, getCurrentTime)
import Data.Time.Clock (UTCTime)
import GHC.Generics (Generic)
import Network.HTTP.Req (
GET (GET),
HttpResponse (HttpResponseBody),
NoReqBody (NoReqBody),
Option,
Req,
Scheme (Https),
bsResponse,
defaultHttpConfig,
header,
https,
jsonResponse,
req,
responseBody,
responseTimeout,
runReq,
(/:),
GET (GET),
NoReqBody (NoReqBody),
defaultHttpConfig,
header,
https,
jsonResponse,
req,
responseBody,
responseTimeout,
runReq,
(/:),
)
import System.Directory (XdgDirectory (XdgCache), getXdgDirectory)
import System.Environment (getArgs)
@@ -86,24 +76,17 @@ import Control.Exception (evaluate)
import qualified Data.IntMap.Strict as IntMap
import qualified Data.IntSet as IntSet
import Data.Bifunctor (second)
import Data.Data (Proxy)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as ByteString
import Distribution.Simple.Utils (safeLast, fromUTF8BS)
newtype JobsetEvals = JobsetEvals
{ evals :: Seq Eval
}
deriving stock (Generic, Show)
deriving anyclass (ToJSON, FromJSON)
deriving (Generic, ToJSON, FromJSON, Show)
newtype Nixpkgs = Nixpkgs {revision :: Text}
deriving stock (Generic, Show)
deriving anyclass (ToJSON, FromJSON)
deriving (Generic, ToJSON, FromJSON, Show)
newtype JobsetEvalInputs = JobsetEvalInputs {nixpkgs :: Nixpkgs}
deriving stock (Generic, Show)
deriving anyclass (ToJSON, FromJSON)
deriving (Generic, ToJSON, FromJSON, Show)
data Eval = Eval
{ id :: Int
@@ -111,42 +94,13 @@ data Eval = Eval
}
deriving (Generic, ToJSON, FromJSON, Show)
-- | Hydra job name.
--
-- Examples:
-- - @"haskellPackages.lens.x86_64-linux"@
-- - @"haskell.packages.ghc925.cabal-install.aarch64-darwin"@
-- - @"pkgsMusl.haskell.compiler.ghc90.x86_64-linux"@
-- - @"arion.aarch64-linux"@
newtype JobName = JobName { unJobName :: Text }
deriving stock (Generic, Show)
deriving newtype (Eq, FromJSONKey, FromJSON, Ord, ToJSON)
-- | Datatype representing the result of querying the build evals of the
-- haskell-updates Hydra jobset.
--
-- The URL <https://hydra.nixos.org/eval/EVAL_ID/builds> (where @EVAL_ID@ is a
-- value like 1792418) returns a list of 'Build'.
data Build = Build
{ job :: JobName
{ job :: Text
, buildstatus :: Maybe Int
-- ^ Status of the build. See 'getBuildState' for the meaning of each state.
, finished :: Int
-- ^ Whether or not the build is finished. @0@ if finished, non-zero otherwise.
, id :: Int
, nixname :: Text
-- ^ Nix name of the derivation.
--
-- Examples:
-- - @"lens-5.2.1"@
-- - @"cabal-install-3.8.0.1"@
-- - @"lens-static-x86_64-unknown-linux-musl-5.1.1"@
, system :: Text
-- ^ System
--
-- Examples:
-- - @"x86_64-linux"@
-- - @"aarch64-darwin"@
, jobsetevals :: Seq Int
}
deriving (Generic, ToJSON, FromJSON, Show)
@@ -169,31 +123,17 @@ showT = Text.pack . show
getBuildReports :: IO ()
getBuildReports = runReq defaultHttpConfig do
evalMay <- Seq.lookup 0 . evals <$> hydraJSONQuery mempty ["jobset", "nixpkgs", "haskell-updates", "evals"]
evalMay <- Seq.lookup 0 . evals <$> myReq (https "hydra.nixos.org" /: "jobset" /: "nixpkgs" /: "haskell-updates" /: "evals") mempty
eval@Eval{id} <- maybe (liftIO $ fail "No Evalution found") pure evalMay
liftIO . putStrLn $ "Fetching evaluation " <> show id <> " from Hydra. This might take a few minutes..."
buildReports :: Seq Build <- hydraJSONQuery (responseTimeout 600000000) ["eval", showT id, "builds"]
buildReports :: Seq Build <- myReq (https "hydra.nixos.org" /: "eval" /: showT id /: "builds") (responseTimeout 600000000)
liftIO do
fileName <- reportFileName
putStrLn $ "Finished fetching all builds from Hydra, saving report as " <> fileName
now <- getCurrentTime
encodeFile fileName (eval, now, buildReports)
hydraQuery :: HttpResponse a => Proxy a -> Option 'Https -> [Text] -> Req (HttpResponseBody a)
hydraQuery responseType option query =
responseBody
<$> req
GET
(foldl' (/:) (https "hydra.nixos.org") query)
NoReqBody
responseType
(header "User-Agent" "hydra-report.hs/v1 (nixpkgs;maintainers/scripts/haskell)" <> option)
hydraJSONQuery :: FromJSON a => Option 'Https -> [Text] -> Req a
hydraJSONQuery = hydraQuery jsonResponse
hydraPlainQuery :: [Text] -> Req ByteString
hydraPlainQuery = hydraQuery bsResponse mempty
where
myReq query option = responseBody <$> req GET query NoReqBody jsonResponse (header "User-Agent" "hydra-report.hs/v1 (nixpkgs;maintainers/scripts/haskell)" <> option)
hydraEvalCommand :: FilePath
hydraEvalCommand = "hydra-eval-jobs"
@@ -232,7 +172,7 @@ newtype Maintainers = Maintainers { maintainers :: Maybe Text }
--
-- Note that Hydra jobs without maintainers will have an empty string for the
-- maintainer list.
type HydraJobs = Map JobName Maintainers
type HydraJobs = Map Text Maintainers
-- | Map of email addresses to GitHub handles.
-- This is built from the file @../../maintainer-list.nix@.
@@ -257,12 +197,12 @@ type EmailToGitHubHandles = Map Text Text
-- , ("conduit.x86_64-darwin", ["snoyb", "webber"])
-- ]
-- @@
type MaintainerMap = Map JobName (NonEmpty Text)
type MaintainerMap = Map Text (NonEmpty Text)
-- | Information about a package which lists its dependencies and whether the
-- package is marked broken.
data DepInfo = DepInfo {
deps :: Set PkgName,
deps :: Set Text,
broken :: Bool
}
deriving stock (Generic, Show)
@@ -270,37 +210,23 @@ data DepInfo = DepInfo {
-- | Map from package names to their DepInfo. This is the data we get out of a
-- nix call.
type DependencyMap = Map PkgName DepInfo
type DependencyMap = Map Text DepInfo
-- | Map from package names to its broken state, number of reverse dependencies (fst) and
-- unbroken reverse dependencies (snd).
type ReverseDependencyMap = Map PkgName (Int, Int)
type ReverseDependencyMap = Map Text (Int, Int)
-- | Calculate the (unbroken) reverse dependencies of a package by transitively
-- going through all packages if its a dependency of them.
calculateReverseDependencies :: DependencyMap -> ReverseDependencyMap
calculateReverseDependencies depMap =
Map.fromDistinctAscList $ zip keys (zip (rdepMap False) (rdepMap True))
calculateReverseDependencies depMap = Map.fromDistinctAscList $ zip keys (zip (rdepMap False) (rdepMap True))
where
-- This code tries to efficiently invert the dependency map and calculate
-- its transitive closure by internally identifying every pkg with its index
-- in the package list and then using memoization.
keys :: [PkgName]
keys = Map.keys depMap
pkgToIndexMap :: Map PkgName Int
pkgToIndexMap = Map.fromDistinctAscList (zip keys [0..])
depInfos :: [DepInfo]
depInfos = Map.elems depMap
depInfoToIdx :: DepInfo -> (Bool, [Int])
depInfoToIdx DepInfo{broken,deps} =
(broken, mapMaybe (`Map.lookup` pkgToIndexMap) $ Set.toList deps)
intDeps :: [(Int, (Bool, [Int]))]
intDeps = zip [0..] (fmap depInfoToIdx depInfos)
intDeps = zip [0..] $ (\DepInfo{broken,deps} -> (broken,mapMaybe (`Map.lookup` pkgToIndexMap) $ Set.toList deps)) <$> Map.elems depMap
rdepMap onlyUnbroken = IntSet.size <$> resultList
where
resultList = go <$> [0..]
@@ -317,7 +243,7 @@ getMaintainerMap = do
handlesMap :: EmailToGitHubHandles <-
readJSONProcess nixExprCommand ("maintainers/scripts/haskell/maintainer-handles.nix":nixExprParams) "Failed to decode nix output for lookup of github handles: "
pure $ Map.mapMaybe (splitMaintainersToGitHubHandles handlesMap) hydraJobs
where
where
-- Split a comma-spearated string of Maintainers into a NonEmpty list of
-- GitHub handles.
splitMaintainersToGitHubHandles
@@ -329,10 +255,7 @@ getMaintainerMap = do
-- script ./dependencies.nix.
getDependencyMap :: IO DependencyMap
getDependencyMap =
readJSONProcess
nixExprCommand
("maintainers/scripts/haskell/dependencies.nix" : nixExprParams)
"Failed to decode nix output for lookup of dependencies: "
readJSONProcess nixExprCommand ("maintainers/scripts/haskell/dependencies.nix":nixExprParams) "Failed to decode nix output for lookup of dependencies: "
-- | Run a process that produces JSON on stdout and and decode the JSON to a
-- data type.
@@ -381,80 +304,18 @@ platformIcon (Platform x) = case x of
"x86_64-linux" -> ":penguin:"
"aarch64-linux" -> ":iphone:"
"x86_64-darwin" -> ":apple:"
"aarch64-darwin" -> ":green_apple:"
_ -> x
platformIsOS :: OS -> Platform -> Bool
platformIsOS os (Platform x) = case (os, x) of
(Linux, "x86_64-linux") -> True
(Linux, "aarch64-linux") -> True
(Darwin, "x86_64-darwin") -> True
(Darwin, "aarch64-darwin") -> True
_ -> False
-- | A package name. This is parsed from a 'JobName'.
--
-- Examples:
--
-- - The 'JobName' @"haskellPackages.lens.x86_64-linux"@ produces the 'PkgName'
-- @"lens"@.
-- - The 'JobName' @"haskell.packages.ghc925.cabal-install.aarch64-darwin"@
-- produces the 'PkgName' @"cabal-install"@.
-- - The 'JobName' @"pkgsMusl.haskell.compiler.ghc90.x86_64-linux"@ produces
-- the 'PkgName' @"ghc90"@.
-- - The 'JobName' @"arion.aarch64-linux"@ produces the 'PkgName' @"arion"@.
--
-- 'PkgName' is also used as a key in 'DependencyMap' and 'ReverseDependencyMap'.
-- In this case, 'PkgName' originally comes from attribute names in @haskellPackages@
-- in Nixpkgs.
newtype PkgName = PkgName Text
deriving stock (Generic, Show)
deriving newtype (Eq, FromJSON, FromJSONKey, Ord, ToJSON)
-- | A package set name. This is parsed from a 'JobName'.
--
-- Examples:
--
-- - The 'JobName' @"haskellPackages.lens.x86_64-linux"@ produces the 'PkgSet'
-- @"haskellPackages"@.
-- - The 'JobName' @"haskell.packages.ghc925.cabal-install.aarch64-darwin"@
-- produces the 'PkgSet' @"haskell.packages.ghc925"@.
-- - The 'JobName' @"pkgsMusl.haskell.compiler.ghc90.x86_64-linux"@ produces
-- the 'PkgSet' @"pkgsMusl.haskell.compiler"@.
-- - The 'JobName' @"arion.aarch64-linux"@ produces the 'PkgSet' @""@.
--
-- As you can see from the last example, 'PkgSet' can be empty (@""@) for
-- top-level jobs.
newtype PkgSet = PkgSet Text
deriving stock (Generic, Show)
deriving newtype (Eq, FromJSON, FromJSONKey, Ord, ToJSON)
data BuildResult = BuildResult {state :: BuildState, id :: Int} deriving (Show, Eq, Ord)
newtype Platform = Platform {platform :: Text} deriving (Show, Eq, Ord)
newtype Table row col a = Table (Map (row, col) a)
data SummaryEntry = SummaryEntry {
summaryBuilds :: Table PkgSet Platform BuildResult,
summaryBuilds :: Table Text Platform BuildResult,
summaryMaintainers :: Set Text,
summaryReverseDeps :: Int,
summaryUnbrokenReverseDeps :: Int
}
type StatusSummary = Map PkgName SummaryEntry
data OS = Linux | Darwin
newtype Table row col a = Table (Map (row, col) a)
singletonTable :: row -> col -> a -> Table row col a
singletonTable row col a = Table $ Map.singleton (row, col) a
unionTable :: (Ord row, Ord col) => Table row col a -> Table row col a -> Table row col a
unionTable (Table l) (Table r) = Table $ Map.union l r
filterWithKeyTable :: (row -> col -> a -> Bool) -> Table row col a -> Table row col a
filterWithKeyTable f (Table t) = Table $ Map.filterWithKey (\(r,c) a -> f r c a) t
nullTable :: Table row col a -> Bool
nullTable (Table t) = Map.null t
type StatusSummary = Map Text SummaryEntry
instance (Ord row, Ord col, Semigroup a) => Semigroup (Table row col a) where
Table l <> Table r = Table (Map.unionWith (<>) l r)
@@ -465,57 +326,29 @@ instance Functor (Table row col) where
instance Foldable (Table row col) where
foldMap f (Table a) = foldMap f a
getBuildState :: Build -> BuildState
getBuildState Build{finished, buildstatus} = case (finished, buildstatus) of
(0, _) -> Unfinished
(_, Just 0) -> Success
(_, Just 1) -> Failed
(_, Just 2) -> DependencyFailed
(_, Just 3) -> HydraFailure
(_, Just 4) -> Canceled
(_, Just 7) -> TimedOut
(_, Just 11) -> OutputLimitExceeded
(_, i) -> Unknown i
combineStatusSummaries :: Seq StatusSummary -> StatusSummary
combineStatusSummaries = foldl (Map.unionWith unionSummary) Map.empty
buildSummary :: MaintainerMap -> ReverseDependencyMap -> Seq Build -> StatusSummary
buildSummary maintainerMap reverseDependencyMap = foldl (Map.unionWith unionSummary) Map.empty . fmap toSummary
where
unionSummary :: SummaryEntry -> SummaryEntry -> SummaryEntry
unionSummary (SummaryEntry lb lm lr lu) (SummaryEntry rb rm rr ru) =
SummaryEntry (unionTable lb rb) (lm <> rm) (max lr rr) (max lu ru)
buildToPkgNameAndSet :: Build -> (PkgName, PkgSet)
buildToPkgNameAndSet Build{job = JobName jobName, system} = (name, set)
where
packageName :: Text
packageName = fromMaybe jobName (Text.stripSuffix ("." <> system) jobName)
splitted :: Maybe (NonEmpty Text)
splitted = nonEmpty $ Text.splitOn "." packageName
name :: PkgName
name = PkgName $ maybe packageName NonEmpty.last splitted
set :: PkgSet
set = PkgSet $ maybe "" (Text.intercalate "." . NonEmpty.init) splitted
buildToStatusSummary :: MaintainerMap -> ReverseDependencyMap -> Build -> StatusSummary
buildToStatusSummary maintainerMap reverseDependencyMap build@Build{job, id, system} =
Map.singleton pkgName summaryEntry
where
(pkgName, pkgSet) = buildToPkgNameAndSet build
maintainers :: Set Text
maintainers = maybe mempty (Set.fromList . toList) (Map.lookup job maintainerMap)
(reverseDeps, unbrokenReverseDeps) =
Map.findWithDefault (0,0) pkgName reverseDependencyMap
buildTable :: Table PkgSet Platform BuildResult
buildTable =
singletonTable pkgSet (Platform system) (BuildResult (getBuildState build) id)
summaryEntry = SummaryEntry buildTable maintainers reverseDeps unbrokenReverseDeps
unionSummary (SummaryEntry (Table lb) lm lr lu) (SummaryEntry (Table rb) rm rr ru) = SummaryEntry (Table $ Map.union lb rb) (lm <> rm) (max lr rr) (max lu ru)
toSummary Build{finished, buildstatus, job, id, system} = Map.singleton name (SummaryEntry (Table (Map.singleton (set, Platform system) (BuildResult state id))) maintainers reverseDeps unbrokenReverseDeps)
where
state :: BuildState
state = case (finished, buildstatus) of
(0, _) -> Unfinished
(_, Just 0) -> Success
(_, Just 1) -> Failed
(_, Just 2) -> DependencyFailed
(_, Just 3) -> HydraFailure
(_, Just 4) -> Canceled
(_, Just 7) -> TimedOut
(_, Just 11) -> OutputLimitExceeded
(_, i) -> Unknown i
packageName = fromMaybe job (Text.stripSuffix ("." <> system) job)
splitted = nonEmpty $ Text.splitOn "." packageName
name = maybe packageName NonEmpty.last splitted
set = maybe "" (Text.intercalate "." . NonEmpty.init) splitted
maintainers = maybe mempty (Set.fromList . toList) (Map.lookup job maintainerMap)
(reverseDeps, unbrokenReverseDeps) = Map.findWithDefault (0,0) name reverseDependencyMap
readBuildReports :: IO (Eval, UTCTime, Seq Build)
readBuildReports = do
@@ -537,36 +370,19 @@ printTable name showR showC showE (Table mapping) = joinTable <$> (name : map sh
rows = toList $ Set.fromList (fst <$> Map.keys mapping)
cols = toList $ Set.fromList (snd <$> Map.keys mapping)
printJob :: Int -> PkgName -> (Table PkgSet Platform BuildResult, Text) -> [Text]
printJob evalId (PkgName name) (Table mapping, maintainers) =
printJob :: Int -> Text -> (Table Text Platform BuildResult, Text) -> [Text]
printJob evalId name (Table mapping, maintainers) =
if length sets <= 1
then map printSingleRow sets
else ["- [ ] " <> makeJobSearchLink (PkgSet "") name <> " " <> maintainers] <> map printRow sets
else ["- [ ] " <> makeJobSearchLink "" name <> " " <> maintainers] <> map printRow sets
where
printRow :: PkgSet -> Text
printRow (PkgSet set) =
" - " <> printState (PkgSet set) <> " " <>
makeJobSearchLink (PkgSet set) (if Text.null set then "toplevel" else set)
printSingleRow set =
"- [ ] " <> printState set <> " " <>
makeJobSearchLink set (makePkgName set) <> " " <> maintainers
makePkgName :: PkgSet -> Text
makePkgName (PkgSet set) = (if Text.null set then "" else set <> ".") <> name
printState set =
Text.intercalate " " $ map (\pf -> maybe "" (label pf) $ Map.lookup (set, pf) mapping) platforms
makeJobSearchLink :: PkgSet -> Text -> Text
makeJobSearchLink set linkLabel = makeSearchLink evalId linkLabel (makePkgName set)
sets :: [PkgSet]
printRow set = " - " <> printState set <> " " <> makeJobSearchLink set (if Text.null set then "toplevel" else set)
printSingleRow set = "- [ ] " <> printState set <> " " <> makeJobSearchLink set (makePkgName set) <> " " <> maintainers
makePkgName set = (if Text.null set then "" else set <> ".") <> name
printState set = Text.intercalate " " $ map (\pf -> maybe "" (label pf) $ Map.lookup (set, pf) mapping) platforms
makeJobSearchLink set linkLabel= makeSearchLink evalId linkLabel (makePkgName set)
sets = toList $ Set.fromList (fst <$> Map.keys mapping)
platforms :: [Platform]
platforms = toList $ Set.fromList (snd <$> Map.keys mapping)
label pf (BuildResult s i) = "[[" <> platformIcon pf <> icon s <> "]](https://hydra.nixos.org/build/" <> showT i <> ")"
makeSearchLink :: Int -> Text -> Text -> Text
@@ -583,177 +399,75 @@ details summary content = ["<details><summary>" <> summary <> " </summary>", ""]
evalLine :: Eval -> UTCTime -> Text
evalLine Eval{id, jobsetevalinputs = JobsetEvalInputs{nixpkgs = Nixpkgs{revision}}} fetchTime =
"*evaluation ["
<> showT id
<> "](https://hydra.nixos.org/eval/"
<> showT id
<> ") of nixpkgs commit ["
<> Text.take 7 revision
<> "](https://github.com/NixOS/nixpkgs/commits/"
<> revision
<> ") as of "
<> Text.pack (formatTime defaultTimeLocale "%Y-%m-%d %H:%M UTC" fetchTime)
<> "*"
"*evaluation ["
<> showT id
<> "](https://hydra.nixos.org/eval/"
<> showT id
<> ") of nixpkgs commit ["
<> Text.take 7 revision
<> "](https://github.com/NixOS/nixpkgs/commits/"
<> revision
<> ") as of "
<> Text.pack (formatTime defaultTimeLocale "%Y-%m-%d %H:%M UTC" fetchTime)
<> "*"
printBuildSummary :: Eval -> UTCTime -> StatusSummary -> [(PkgName, Int)] -> Text
printBuildSummary :: Eval -> UTCTime -> StatusSummary -> [(Text, Int)] -> Text
printBuildSummary eval@Eval{id} fetchTime summary topBrokenRdeps =
Text.unlines $
headline <> [""] <> tldr <> ((" * "<>) <$> (errors <> warnings)) <> [""]
<> totals
<> optionalList "#### Maintained Linux packages with build failure" (maintainedList (fails summaryLinux))
<> optionalList "#### Maintained Linux packages with failed dependency" (maintainedList (failedDeps summaryLinux))
<> optionalList "#### Maintained Linux packages with unknown error" (maintainedList (unknownErr summaryLinux))
<> optionalHideableList "#### Maintained Darwin packages with build failure" (maintainedList (fails summaryDarwin))
<> optionalHideableList "#### Maintained Darwin packages with failed dependency" (maintainedList (failedDeps summaryDarwin))
<> optionalHideableList "#### Maintained Darwin packages with unknown error" (maintainedList (unknownErr summaryDarwin))
<> optionalHideableList "#### Unmaintained packages with build failure" (unmaintainedList (fails summary))
<> optionalHideableList "#### Unmaintained packages with failed dependency" (unmaintainedList (failedDeps summary))
<> optionalHideableList "#### Unmaintained packages with unknown error" (unmaintainedList (unknownErr summary))
<> optionalHideableList "#### Top 50 broken packages, sorted by number of reverse dependencies" (brokenLine <$> topBrokenRdeps)
<> ["","*:arrow_heading_up:: The number of packages that depend (directly or indirectly) on this package (if any). If two numbers are shown the first (lower) number considers only packages which currently have enabled hydra jobs, i.e. are not marked broken. The second (higher) number considers all packages.*",""]
<> footer
where
footer = ["*Report generated with [maintainers/scripts/haskell/hydra-report.hs](https://github.com/NixOS/nixpkgs/blob/haskell-updates/maintainers/scripts/haskell/hydra-report.hs)*"]
headline =
[ "### [haskell-updates build report from hydra](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates)"
, evalLine eval fetchTime
]
totals :: [Text]
totals =
[ "#### Build summary"
, ""
] <>
printTable
"Platform"
(\x -> makeSearchLink id (platform x <> " " <> platformIcon x) ("." <> platform x))
(\x -> showT x <> " " <> icon x)
showT
numSummary
brokenLine :: (PkgName, Int) -> Text
brokenLine (PkgName name, rdeps) =
"[" <> name <> "](https://packdeps.haskellers.com/reverse/" <> name <>
") :arrow_heading_up: " <> Text.pack (show rdeps) <> " "
numSummary = statusToNumSummary summary
summaryLinux :: StatusSummary
summaryLinux = withOS Linux summary
summaryDarwin :: StatusSummary
summaryDarwin = withOS Darwin summary
-- Remove all BuildResult from the Table that have Platform that isn't for
-- the given OS.
tableForOS :: OS -> Table PkgSet Platform BuildResult -> Table PkgSet Platform BuildResult
tableForOS os = filterWithKeyTable (\_ platform _ -> platformIsOS os platform)
-- Remove all BuildResult from the StatusSummary that have a Platform that
-- isn't for the given OS. Completely remove all PkgName from StatusSummary
-- that end up with no BuildResults.
withOS
:: OS
-> StatusSummary
-> StatusSummary
withOS os =
Map.mapMaybe
(\e@SummaryEntry{summaryBuilds} ->
let buildsForOS = tableForOS os summaryBuilds
in if nullTable buildsForOS then Nothing else Just e { summaryBuilds = buildsForOS }
)
jobsByState :: (BuildState -> Bool) -> StatusSummary -> StatusSummary
jobsByState predicate = Map.filter (predicate . worstState)
worstState :: SummaryEntry -> BuildState
worstState = foldl' min Success . fmap state . summaryBuilds
fails :: StatusSummary -> StatusSummary
fails = jobsByState (== Failed)
failedDeps :: StatusSummary -> StatusSummary
failedDeps = jobsByState (== DependencyFailed)
unknownErr :: StatusSummary -> StatusSummary
unknownErr = jobsByState (\x -> x > DependencyFailed && x < TimedOut)
withMaintainer :: StatusSummary -> Map PkgName (Table PkgSet Platform BuildResult, NonEmpty Text)
withMaintainer =
Map.mapMaybe
(\e -> (summaryBuilds e,) <$> nonEmpty (Set.toList (summaryMaintainers e)))
withoutMaintainer :: StatusSummary -> StatusSummary
withoutMaintainer = Map.mapMaybe (\e -> if Set.null (summaryMaintainers e) then Just e else Nothing)
optionalList :: Text -> [Text] -> [Text]
optionalList heading list = if null list then mempty else [heading] <> list
optionalHideableList :: Text -> [Text] -> [Text]
optionalHideableList heading list = if null list then mempty else [heading] <> details (showT (length list) <> " job(s)") list
maintainedList :: StatusSummary -> [Text]
maintainedList = showMaintainedBuild <=< Map.toList . withMaintainer
summaryEntryGetReverseDeps :: SummaryEntry -> (Int, Int)
summaryEntryGetReverseDeps sumEntry =
( negate $ summaryUnbrokenReverseDeps sumEntry
, negate $ summaryReverseDeps sumEntry
)
sortOnReverseDeps :: [(PkgName, SummaryEntry)] -> [(PkgName, SummaryEntry)]
sortOnReverseDeps = sortOn (\(_, sumEntry) -> summaryEntryGetReverseDeps sumEntry)
unmaintainedList :: StatusSummary -> [Text]
unmaintainedList = showBuild <=< sortOnReverseDeps . Map.toList . withoutMaintainer
showBuild :: (PkgName, SummaryEntry) -> [Text]
showBuild (name, entry) =
printJob
id
name
( summaryBuilds entry
, Text.pack
( if summaryReverseDeps entry > 0
then
" :arrow_heading_up: " <> show (summaryUnbrokenReverseDeps entry) <>
" | " <> show (summaryReverseDeps entry)
else ""
)
)
showMaintainedBuild
:: (PkgName, (Table PkgSet Platform BuildResult, NonEmpty Text)) -> [Text]
showMaintainedBuild (name, (table, maintainers)) =
printJob
id
name
( table
, Text.intercalate " " (fmap ("@" <>) (toList maintainers))
)
tldr = case (errors, warnings) of
([],[]) -> [":green_circle: **Ready to merge** (if there are no [evaluation errors](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates))"]
([],_) -> [":yellow_circle: **Potential issues** (and possibly [evaluation errors](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates))"]
_ -> [":red_circle: **Branch not mergeable**"]
warnings =
if' (Unfinished > maybe Success worstState maintainedJob) "`maintained` jobset failed." <>
if' (Unfinished == maybe Success worstState mergeableJob) "`mergeable` jobset is not finished." <>
if' (Unfinished == maybe Success worstState maintainedJob) "`maintained` jobset is not finished."
errors =
if' (isNothing mergeableJob) "No `mergeable` job found." <>
if' (isNothing maintainedJob) "No `maintained` job found." <>
if' (Unfinished > maybe Success worstState mergeableJob) "`mergeable` jobset failed." <>
if' (outstandingJobs (Platform "x86_64-linux") > 100) "Too many outstanding jobs on x86_64-linux." <>
if' (outstandingJobs (Platform "aarch64-linux") > 100) "Too many outstanding jobs on aarch64-linux."
if' p e = if p then [e] else mempty
outstandingJobs platform | Table m <- numSummary = Map.findWithDefault 0 (platform, Unfinished) m
maintainedJob = Map.lookup (PkgName "maintained") summary
mergeableJob = Map.lookup (PkgName "mergeable") summary
Text.unlines $
headline <> [""] <> tldr <> ((" * "<>) <$> (errors <> warnings)) <> [""]
<> totals
<> optionalList "#### Maintained packages with build failure" (maintainedList fails)
<> optionalList "#### Maintained packages with failed dependency" (maintainedList failedDeps)
<> optionalList "#### Maintained packages with unknown error" (maintainedList unknownErr)
<> optionalHideableList "#### Unmaintained packages with build failure" (unmaintainedList fails)
<> optionalHideableList "#### Unmaintained packages with failed dependency" (unmaintainedList failedDeps)
<> optionalHideableList "#### Unmaintained packages with unknown error" (unmaintainedList unknownErr)
<> optionalHideableList "#### Top 50 broken packages, sorted by number of reverse dependencies" (brokenLine <$> topBrokenRdeps)
<> ["","*:arrow_heading_up:: The number of packages that depend (directly or indirectly) on this package (if any). If two numbers are shown the first (lower) number considers only packages which currently have enabled hydra jobs, i.e. are not marked broken. The second (higher) number considers all packages.*",""]
<> footer
where
footer = ["*Report generated with [maintainers/scripts/haskell/hydra-report.hs](https://github.com/NixOS/nixpkgs/blob/haskell-updates/maintainers/scripts/haskell/hydra-report.hs)*"]
headline =
[ "### [haskell-updates build report from hydra](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates)"
, evalLine eval fetchTime ]
totals =
[ "#### Build summary"
, ""
]
<> printTable "Platform" (\x -> makeSearchLink id (platform x <> " " <> platformIcon x) ("." <> platform x)) (\x -> showT x <> " " <> icon x) showT numSummary
brokenLine (name, rdeps) = "[" <> name <> "](https://packdeps.haskellers.com/reverse/" <> name <> ") :arrow_heading_up: " <> Text.pack (show rdeps) <> " "
numSummary = statusToNumSummary summary
jobsByState predicate = Map.filter (predicate . worstState) summary
worstState = foldl' min Success . fmap state . summaryBuilds
fails = jobsByState (== Failed)
failedDeps = jobsByState (== DependencyFailed)
unknownErr = jobsByState (\x -> x > DependencyFailed && x < TimedOut)
withMaintainer = Map.mapMaybe (\e -> (summaryBuilds e,) <$> nonEmpty (Set.toList (summaryMaintainers e)))
withoutMaintainer = Map.mapMaybe (\e -> if Set.null (summaryMaintainers e) then Just e else Nothing)
optionalList heading list = if null list then mempty else [heading] <> list
optionalHideableList heading list = if null list then mempty else [heading] <> details (showT (length list) <> " job(s)") list
maintainedList = showMaintainedBuild <=< Map.toList . withMaintainer
unmaintainedList = showBuild <=< sortOn (\(snd -> x) -> (negate (summaryUnbrokenReverseDeps x), negate (summaryReverseDeps x))) . Map.toList . withoutMaintainer
showBuild (name, entry) = printJob id name (summaryBuilds entry, Text.pack (if summaryReverseDeps entry > 0 then " :arrow_heading_up: " <> show (summaryUnbrokenReverseDeps entry) <>" | "<> show (summaryReverseDeps entry) else ""))
showMaintainedBuild (name, (table, maintainers)) = printJob id name (table, Text.intercalate " " (fmap ("@" <>) (toList maintainers)))
tldr = case (errors, warnings) of
([],[]) -> [":green_circle: **Ready to merge** (if there are no [evaluation errors](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates))"]
([],_) -> [":yellow_circle: **Potential issues** (and possibly [evaluation errors](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates))"]
_ -> [":red_circle: **Branch not mergeable**"]
warnings =
if' (Unfinished > maybe Success worstState maintainedJob) "`maintained` jobset failed." <>
if' (Unfinished == maybe Success worstState mergeableJob) "`mergeable` jobset is not finished." <>
if' (Unfinished == maybe Success worstState maintainedJob) "`maintained` jobset is not finished."
errors =
if' (isNothing mergeableJob) "No `mergeable` job found." <>
if' (isNothing maintainedJob) "No `maintained` job found." <>
if' (Unfinished > maybe Success worstState mergeableJob) "`mergeable` jobset failed." <>
if' (outstandingJobs (Platform "x86_64-linux") > 100) "Too many outstanding jobs on x86_64-linux." <>
if' (outstandingJobs (Platform "aarch64-linux") > 100) "Too many outstanding jobs on aarch64-linux."
if' p e = if p then [e] else mempty
outstandingJobs platform | Table m <- numSummary = Map.findWithDefault 0 (platform, Unfinished) m
maintainedJob = Map.lookup "maintained" summary
mergeableJob = Map.lookup "mergeable" summary
printEvalInfo :: IO ()
printEvalInfo = do
@@ -768,32 +482,12 @@ printMaintainerPing = do
let tops = take 50 . sortOn (negate . snd) . fmap (second fst) . filter (\x -> maybe False broken $ Map.lookup (fst x) depMap) . Map.toList $ rdepMap
pure (rdepMap, tops)
(eval, fetchTime, buildReport) <- readBuildReports
let statusSummaries =
fmap (buildToStatusSummary maintainerMap reverseDependencyMap) buildReport
buildSum :: StatusSummary
buildSum = combineStatusSummaries statusSummaries
textBuildSummary = printBuildSummary eval fetchTime buildSum topBrokenRdeps
Text.putStrLn textBuildSummary
putStrLn (Text.unpack (printBuildSummary eval fetchTime (buildSummary maintainerMap reverseDependencyMap buildReport) topBrokenRdeps))
printMarkBrokenList :: IO ()
printMarkBrokenList = do
(_, fetchTime, buildReport) <- readBuildReports
runReq defaultHttpConfig $ forM_ buildReport \build@Build{job, id} ->
case (getBuildState build, Text.splitOn "." $ unJobName job) of
(Failed, ["haskellPackages", name, "x86_64-linux"]) -> do
-- Fetch build log from hydra to figure out the cause of the error.
build_log <- ByteString.lines <$> hydraPlainQuery ["build", showT id, "nixlog", "1", "raw"]
-- We use the last probable error cause found in the build log file.
let error_message = fromMaybe " failure " $ safeLast $ mapMaybe probableErrorCause build_log
liftIO $ putStrLn $ " - " <> Text.unpack name <> " # " <> error_message <> " in job https://hydra.nixos.org/build/" <> show id <> " at " <> formatTime defaultTimeLocale "%Y-%m-%d" fetchTime
(_, _, buildReport) <- readBuildReports
forM_ buildReport \Build{buildstatus, job} ->
case (buildstatus, Text.splitOn "." job) of
(Just 1, ["haskellPackages", name, "x86_64-linux"]) -> putStrLn $ " - " <> Text.unpack name
_ -> pure ()
{- | This function receives a line from a Nix Haskell builder build log and returns a possible error cause.
| We might need to add other causes in the future if errors happen in unusual parts of the builder.
-}
probableErrorCause :: ByteString -> Maybe String
probableErrorCause "Setup: Encountered missing or private dependencies:" = Just "dependency missing"
probableErrorCause "running tests" = Just "test failure"
probableErrorCause build_line | ByteString.isPrefixOf "Building" build_line = Just ("failure building " <> fromUTF8BS (fst $ ByteString.breakSubstring " for" $ ByteString.drop 9 build_line))
probableErrorCause build_line | ByteString.isSuffixOf "Phase" build_line = Just ("failure in " <> fromUTF8BS build_line)
probableErrorCause _ = Nothing

View File

@@ -112,8 +112,6 @@ The short version is this:
* We only do the merge if the [\`mergeable\`](https://hydra.nixos.org/job/nixpkgs/haskell-updates/mergeable) job is succeeding on hydra.
* If a [\`maintained\`](https://hydra.nixos.org/job/nixpkgs/haskell-updates/maintained) package is still broken at the time of merge, we will only merge if the maintainer has been pinged 7 days in advance. (If you care about a Haskell package, become a maintainer!)
More information about Haskell packages in nixpkgs can be found [in the nixpkgs manual](https://nixos.org/manual/nixpkgs/unstable/#haskell).
---
This is the follow-up to #${curr_haskell_updates_pr_num}. Come to [#haskell:nixos.org](https://matrix.to/#/#haskell:nixos.org) if you have any questions.

View File

@@ -11,9 +11,6 @@
# Related scripts are update-hackage.sh, for updating the snapshot of the
# Hackage database used by hackage2nix, and update-cabal2nix-unstable.sh,
# for updating the version of hackage2nix used to perform this task.
#
# Note that this script doesn't gcroot anything, so it may be broken by an
# unfortunately timed nix-store --gc.
set -euo pipefail
@@ -23,21 +20,15 @@ HACKAGE2NIX="${HACKAGE2NIX:-hackage2nix}"
# See: https://github.com/NixOS/nixpkgs/pull/122023
export LC_ALL=C.UTF-8
config_dir=pkgs/development/haskell-modules/configuration-hackage2nix
echo "Obtaining Hackage data"
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)"
echo "Generating compiler configuration"
compiler_config="$(nix-build -A haskellPackages.cabal2nix-unstable.compilerConfig --no-out-link)"
config_dir=pkgs/development/haskell-modules/configuration-hackage2nix
echo "Starting hackage2nix to regenerate pkgs/development/haskell-modules/hackage-packages.nix ..."
"$HACKAGE2NIX" \
--hackage "$unpacked_hackage" \
--preferred-versions <(for n in "$unpacked_hackage"/*/preferred-versions; do cat "$n"; echo; done) \
--nixpkgs "$PWD" \
--config "$compiler_config" \
--config "$config_dir/main.yaml" \
--config "$config_dir/stackage.yaml" \
--config "$config_dir/broken.yaml" \

View File

@@ -66,28 +66,6 @@ let
if !builtins.isList files then [ files ] else files
);
packageSetsWithVersionedHead = pkgs.haskell.packages // (
let
headSet = pkgs.haskell.packages.ghcHEAD;
# Determine the next GHC release version following GHC HEAD.
# GHC HEAD always has an uneven, tentative version number, e.g. 9.7.
# GHC releases always have even numbers, i.e. GHC 9.8 is branched off from
# GHC HEAD 9.7. Since we use the to be release number for GHC HEAD's
# configuration file, we need to calculate this here.
headVersion = lib.pipe headSet.ghc.version [
lib.versions.splitVersion
(lib.take 2)
lib.concatStrings
lib.strings.toInt
(builtins.add 1)
toString
];
in
{
"ghc${headVersion}" = headSet;
}
);
setsForFile = fileName:
let
# extract the unique part of the config's file name
@@ -99,12 +77,12 @@ let
builtins.match "ghc-([0-9]+).([0-9]+).x" configName
);
# return all package sets under haskell.packages matching the version components
setsForVersion = builtins.map (name: packageSetsWithVersionedHead.${name}) (
setsForVersion = builtins.map (name: pkgs.haskell.packages.${name}) (
builtins.filter (setName:
lib.hasPrefix "ghc${configVersion}" setName
&& (skipBinaryGHCs -> !(lib.hasInfix "Binary" setName))
) (
builtins.attrNames packageSetsWithVersionedHead
builtins.attrNames pkgs.haskell.packages
)
);

View File

@@ -40,7 +40,6 @@ sed -r \
-e 's|^constraints:||' \
-e 's|^ +| - |' \
-e 's|,$||' \
-e '/^with-compiler:/d' \
-e '/installed$/d' \
-e '/^$/d' \
< "${tmpfile}" | sort --ignore-case >"${tmpfile_new}"
@@ -58,20 +57,17 @@ sed -r \
-e '/ distribution-nixpkgs /d' \
-e '/ jailbreak-cabal /d' \
-e '/ language-nix /d' \
-e '/ hackage-db /d' \
-e '/ cabal-install /d' \
-e '/ lsp /d' \
-e '/ lsp-types /d' \
-e '/ lsp-test /d' \
-e '/ hie-bios /d' \
-e '/ ShellCheck /d' \
-e '/ Agda /d' \
< "${tmpfile_new}" >> $stackage_config
# Explanations:
# cabal2nix, distribution-nixpkgs, jailbreak-cabal, language-nix: These are our packages and we know what we are doing.
# lsp, lsp-types, lsp-test, hie-bios: These are tightly coupled to hls which is not in stackage. They have no rdeps in stackage.
# ShellCheck: latest version of command-line dev tool.
# Agda: The Agda community is fast-moving; we strive to always include the newest versions of Agda and the Agda packages in nixpkgs.
if [[ "${1:-}" == "--do-commit" ]]; then
git add $stackage_config

View File

@@ -15,29 +15,8 @@
# password-command: pass hackage.haskell.org (this can be any command, but not an arbitrary shell expression. Like cabal we only read the first output line and ignore the rest.)
# Those fields are specified under `upload` on the `cabal` man page.
if test -z "$CABAL_DIR"; then
dirs=(
"$HOME/.cabal"
"${XDG_CONFIG_HOME:-$HOME/.config}/cabal"
)
missing=true
for dir in "${dirs[@]}"; do
if test -d "$dir"; then
export CABAL_DIR="$dir"
missing=false
break
fi
done
if $missing; then
echo "Could not find the cabal configuration directory in any of: ${dirs[@]}" >&2
exit 101
fi
fi
package_list="$(nix-build -A haskell.package-list)/nixos-hackage-packages.csv"
username=$(grep "^username:" "$CABAL_DIR/config" | sed "s/^username: //")
password_command=$(grep "^password-command:" "$CABAL_DIR/config" | sed "s/^password-command: //")
username=$(grep "^username:" ~/.cabal/config | sed "s/^username: //")
password_command=$(grep "^password-command:" ~/.cabal/config | sed "s/^password-command: //")
curl -u "$username:$($password_command | head -n1)" --digest -H "Content-type: text/csv" -T "$package_list" http://hackage.haskell.org/distro/NixOS/packages.csv
echo

View File

@@ -19,7 +19,6 @@ fennel,,,,,,misterio77
fifo,,,,,,
fluent,,,,,,alerque
gitsigns.nvim,https://github.com/lewis6991/gitsigns.nvim.git,,,,5.1,
haskell-tools.nvim,,,,,,
http,,,,0.3-0,,vcunat
inspect,,,,,,
jsregexp,,,,,,
@@ -33,14 +32,13 @@ lmpfrlib,,,,,5.3,alexshpilkin
loadkit,,,,,,alerque
lpeg,,,,,,vyp
lpeg_patterns,,,,,,
lpeglabel,,,,1.6.0,,
lpeglabel,,,,,,
lpty,,,,,,
lrexlib-gnu,,,,,,
lrexlib-pcre,,,,,,vyp
lrexlib-posix,,,,,,
lua-cjson,,,,,,
lua-cmsgpack,,,,,,
lua-curl,,,,,,
lua-iconv,,,,,,
lua-lsp,,,,,,
lua-messagepack,,,,,,
@@ -83,7 +81,7 @@ luautf8,,,,,,pstn
luazip,,,,,,
lua-yajl,,,,,,pstn
luuid,,,,,,
luv,,,,1.44.2-1,,
luv,,,,1.43.0-0,,
lush.nvim,https://github.com/rktjmp/lush.nvim,,,,,teto
lyaml,,,,,,lblasc
markdown,,,,,,
@@ -104,8 +102,6 @@ std._debug,https://github.com/lua-stdlib/_debug.git,,,,,
std.normalize,https://github.com/lua-stdlib/normalize.git,,,,,
stdlib,,,,41.2.2,,vyp
teal-language-server,,,http://luarocks.org/dev,,,
telescope.nvim,,,,,5.1,
telescope-manix,,,,,,
tl,,,,,,mephistophiles
vstruct,https://github.com/ToxicFrog/vstruct.git,,,,,
vusted,,,,,,figsoda
1 name src ref server version luaversion maintainers
19 fifo
20 fluent alerque
21 gitsigns.nvim https://github.com/lewis6991/gitsigns.nvim.git 5.1
haskell-tools.nvim
22 http 0.3-0 vcunat
23 inspect
24 jsregexp
32 loadkit alerque
33 lpeg vyp
34 lpeg_patterns
35 lpeglabel 1.6.0
36 lpty
37 lrexlib-gnu
38 lrexlib-pcre vyp
39 lrexlib-posix
40 lua-cjson
41 lua-cmsgpack
lua-curl
42 lua-iconv
43 lua-lsp
44 lua-messagepack
81 luazip
82 lua-yajl pstn
83 luuid
84 luv 1.44.2-1 1.43.0-0
85 lush.nvim https://github.com/rktjmp/lush.nvim teto
86 lyaml lblasc
87 markdown
102 std.normalize https://github.com/lua-stdlib/normalize.git
103 stdlib 41.2.2 vyp
104 teal-language-server http://luarocks.org/dev
telescope.nvim 5.1
telescope-manix
105 tl mephistophiles
106 vstruct https://github.com/ToxicFrog/vstruct.git
107 vusted figsoda

View File

@@ -1,7 +1,4 @@
# python library used to update plugins:
# - pkgs/applications/editors/vim/plugins/update.py
# - pkgs/applications/editors/kakoune/plugins/update.py
# - maintainers/scripts/update-luarocks-packages
# 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
@@ -318,10 +315,10 @@ def run_nix_expr(expr):
with CleanEnvironment():
cmd = ["nix", "eval", "--extra-experimental-features",
"nix-command", "--impure", "--json", "--expr", expr]
log.debug("Running command %s", " ".join(cmd))
log.debug("Running command %s", cmd)
out = subprocess.check_output(cmd)
data = json.loads(out)
return data
data = json.loads(out)
return data
class Editor:
@@ -347,39 +344,12 @@ class Editor:
self.cache_file = cache_file or f"{name}-plugin-cache.json"
self.nixpkgs_repo = None
def add(self, args):
'''CSV spec'''
log.debug("called the 'add' command")
fetch_config = FetchConfig(args.proc, args.github_token)
editor = self
for plugin_line in args.add_plugins:
log.debug("using plugin_line", plugin_line)
pdesc = PluginDesc.load_from_string(fetch_config, plugin_line)
log.debug("loaded as pdesc", pdesc)
append = [ pdesc ]
editor.rewrite_input(fetch_config, args.input_file, editor.deprecated, append=append)
plugin, _ = prefetch_plugin(pdesc, )
autocommit = not args.no_commit
if autocommit:
commit(
editor.nixpkgs_repo,
"{drv_name}: init at {version}".format(
drv_name=editor.get_drv_name(plugin.normalized_name),
version=plugin.version
),
[args.outfile, args.input_file],
)
# Expects arguments generated by 'update' subparser
def update(self, args ):
'''CSV spec'''
print("the update member function should be overriden in subclasses")
def get_current_plugins(self) -> List[Plugin]:
"""To fill the cache"""
data = run_nix_expr(self.get_plugins)
plugins = []
for name, attr in data.items():
print("get_current_plugins: name %s" % name)
p = Plugin(name, attr["rev"], attr["submodules"], attr["sha256"])
plugins.append(p)
return plugins
@@ -388,7 +358,7 @@ class Editor:
'''CSV spec'''
return load_plugins_from_csv(config, plugin_file)
def generate_nix(self, _plugins, _outfile: str):
def generate_nix(self, plugins, outfile: str):
'''Returns nothing for now, writes directly to outfile'''
raise NotImplementedError()
@@ -425,28 +395,34 @@ class Editor:
return rewrite_input(*args, **kwargs)
def create_parser(self):
common = argparse.ArgumentParser(
add_help=False,
parser = argparse.ArgumentParser(
description=(f"""
Updates nix derivations for {self.name} plugins.\n
By default from {self.default_in} to {self.default_out}"""
)
)
common.add_argument(
parser.add_argument(
"--add",
dest="add_plugins",
default=[],
action="append",
help=f"Plugin to add to {self.attr_path} from Github in the form owner/repo",
)
parser.add_argument(
"--input-names",
"-i",
dest="input_file",
default=self.default_in,
help="A list of plugins in the form owner/repo",
)
common.add_argument(
parser.add_argument(
"--out",
"-o",
dest="outfile",
default=self.default_out,
help="Filename to save generated nix code",
)
common.add_argument(
parser.add_argument(
"--proc",
"-p",
dest="proc",
@@ -454,7 +430,7 @@ class Editor:
default=30,
help="Number of concurrent processes to spawn. Setting --github-token allows higher values.",
)
common.add_argument(
parser.add_argument(
"--github-token",
"-t",
type=str,
@@ -462,61 +438,16 @@ class Editor:
help="""Allows to set --proc to higher values.
Uses GITHUB_API_TOKEN environment variables as the default value.""",
)
common.add_argument(
parser.add_argument(
"--no-commit", "-n", action="store_true", default=False,
help="Whether to autocommit changes"
)
common.add_argument(
parser.add_argument(
"--debug", "-d", choices=LOG_LEVELS.keys(),
default=logging.getLevelName(logging.WARN),
help="Adjust log level"
)
main = argparse.ArgumentParser(
parents=[common],
description=(f"""
Updates nix derivations for {self.name} plugins.\n
By default from {self.default_in} to {self.default_out}"""
)
)
subparsers = main.add_subparsers(dest="command", required=False)
padd = subparsers.add_parser(
"add", parents=[],
description="Add new plugin",
add_help=False,
)
padd.set_defaults(func=self.add)
padd.add_argument(
"add_plugins",
default=None,
nargs="+",
help=f"Plugin to add to {self.attr_path} from Github in the form owner/repo",
)
pupdate = subparsers.add_parser(
"update",
description="Update all or a subset of existing plugins",
add_help=False,
)
pupdate.set_defaults(func=self.update)
return main
def run(self,):
'''
Convenience function
'''
parser = self.create_parser()
args = parser.parse_args()
command = args.command or "update"
log.setLevel(LOG_LEVELS[args.debug])
log.info("Chose to run command: %s", command)
if not args.no_commit:
self.nixpkgs_repo = git.Repo(self.root, search_parent_directories=True)
getattr(self, command)(args)
return parser
@@ -730,6 +661,7 @@ def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
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")
fetch_config = FetchConfig(args.proc, args.github_token)
update = editor.get_update(args.input_file, args.outfile, fetch_config)
@@ -752,3 +684,18 @@ def update_plugins(editor: Editor, args):
[args.outfile, args.input_file, editor.deprecated],
)
for plugin_line in args.add_plugins:
pdesc = PluginDesc.load_from_string(fetch_config, plugin_line)
append = [ pdesc ]
editor.rewrite_input(fetch_config, args.input_file, editor.deprecated, append=append)
update()
plugin, _ = prefetch_plugin(pdesc, )
if autocommit:
commit(
editor.nixpkgs_repo,
"{drv_name}: init at {version}".format(
drv_name=editor.get_drv_name(plugin.normalized_name),
version=plugin.version
),
[args.outfile, args.input_file],
)

View File

@@ -26,8 +26,7 @@ log = logging.getLogger()
log.addHandler(logging.StreamHandler())
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent # type: ignore
import pluginupdate
from pluginupdate import update_plugins, FetchConfig, CleanEnvironment
from pluginupdate import Editor, update_plugins, FetchConfig, CleanEnvironment
PKG_LIST="maintainers/scripts/luarocks-packages.csv"
TMP_FILE="$(mktemp)"
@@ -71,7 +70,7 @@ class LuaPlugin:
return self.name.replace(".", "-")
# rename Editor to LangUpdate/ EcosystemUpdater
class LuaEditor(pluginupdate.Editor):
class LuaEditor(Editor):
def get_current_plugins(self):
return []
@@ -88,9 +87,6 @@ class LuaEditor(pluginupdate.Editor):
luaPackages.append(plugin)
return luaPackages
def update(self, args):
update_plugins(self, args)
def generate_nix(
self,
results: List[Tuple[LuaPlugin, str]],
@@ -207,7 +203,11 @@ def main():
default_out = ROOT.joinpath(GENERATED_NIXFILE)
)
editor.run()
parser = editor.create_parser()
args = parser.parse_args()
update_plugins(editor, args)
if __name__ == "__main__":

View File

@@ -1,468 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell update-octave-shell.nix -i python3
"""
Update a Octave package expression by passing in the `.nix` file, or the directory containing it.
You can pass in multiple files or paths.
You'll likely want to use
``
$ ./update-octave-libraries ../../pkgs/development/octave-modules/**/default.nix
``
to update all non-pinned libraries in that folder.
"""
import argparse
import os
import pathlib
import re
import requests
import yaml
from concurrent.futures import ThreadPoolExecutor as Pool
from packaging.version import Version as _Version
from packaging.version import InvalidVersion
from packaging.specifiers import SpecifierSet
import collections
import subprocess
import tempfile
INDEX = "https://raw.githubusercontent.com/gnu-octave/packages/main/packages"
"""url of Octave packages' source on GitHub"""
EXTENSIONS = ['tar.gz', 'tar.bz2', 'tar', 'zip']
"""Permitted file extensions. These are evaluated from left to right and the first occurance is returned."""
PRERELEASES = False
GIT = "git"
NIXPGKS_ROOT = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode('utf-8').strip()
import logging
logging.basicConfig(level=logging.INFO)
class Version(_Version, collections.abc.Sequence):
def __init__(self, version):
super().__init__(version)
# We cannot use `str(Version(0.04.21))` because that becomes `0.4.21`
# https://github.com/avian2/unidecode/issues/13#issuecomment-354538882
self.raw_version = version
def __getitem__(self, i):
return self._version.release[i]
def __len__(self):
return len(self._version.release)
def __iter__(self):
yield from self._version.release
def _get_values(attribute, text):
"""Match attribute in text and return all matches.
:returns: List of matches.
"""
regex = '{}\s+=\s+"(.*)";'.format(attribute)
regex = re.compile(regex)
values = regex.findall(text)
return values
def _get_unique_value(attribute, text):
"""Match attribute in text and return unique match.
:returns: Single match.
"""
values = _get_values(attribute, text)
n = len(values)
if n > 1:
raise ValueError("found too many values for {}".format(attribute))
elif n == 1:
return values[0]
else:
raise ValueError("no value found for {}".format(attribute))
def _get_line_and_value(attribute, text):
"""Match attribute in text. Return the line and the value of the attribute."""
regex = '({}\s+=\s+"(.*)";)'.format(attribute)
regex = re.compile(regex)
value = regex.findall(text)
n = len(value)
if n > 1:
raise ValueError("found too many values for {}".format(attribute))
elif n == 1:
return value[0]
else:
raise ValueError("no value found for {}".format(attribute))
def _replace_value(attribute, value, text):
"""Search and replace value of attribute in text."""
old_line, old_value = _get_line_and_value(attribute, text)
new_line = old_line.replace(old_value, value)
new_text = text.replace(old_line, new_line)
return new_text
def _fetch_page(url):
r = requests.get(url)
if r.status_code == requests.codes.ok:
return list(yaml.safe_load_all(r.content))[0]
else:
raise ValueError("request for {} failed".format(url))
def _fetch_github(url):
headers = {}
token = os.environ.get('GITHUB_API_TOKEN')
if token:
headers["Authorization"] = f"token {token}"
r = requests.get(url, headers=headers)
if r.status_code == requests.codes.ok:
return r.json()
else:
raise ValueError("request for {} failed".format(url))
SEMVER = {
'major' : 0,
'minor' : 1,
'patch' : 2,
}
def _determine_latest_version(current_version, target, versions):
"""Determine latest version, given `target`, returning the more recent version.
"""
current_version = Version(current_version)
def _parse_versions(versions):
for v in versions:
try:
yield Version(v)
except InvalidVersion:
pass
versions = _parse_versions(versions)
index = SEMVER[target]
ceiling = list(current_version[0:index])
if len(ceiling) == 0:
ceiling = None
else:
ceiling[-1]+=1
ceiling = Version(".".join(map(str, ceiling)))
# We do not want prereleases
versions = SpecifierSet(prereleases=PRERELEASES).filter(versions)
if ceiling is not None:
versions = SpecifierSet(f"<{ceiling}").filter(versions)
return (max(sorted(versions))).raw_version
def _get_latest_version_octave_packages(package, extension, current_version, target):
"""Get latest version and hash from Octave Packages."""
url = "{}/{}.yaml".format(INDEX, package)
yaml = _fetch_page(url)
versions = list(map(lambda pv: pv['id'], yaml['versions']))
version = _determine_latest_version(current_version, target, versions)
try:
releases = [v if v['id'] == version else None for v in yaml['versions']]
except KeyError as e:
raise KeyError('Could not find version {} for {}'.format(version, package)) from e
for release in releases:
if release['url'].endswith(extension):
sha256 = release['sha256']
break
else:
sha256 = None
return version, sha256, None
def _get_latest_version_github(package, extension, current_version, target):
def strip_prefix(tag):
return re.sub("^[^0-9]*", "", tag)
def get_prefix(string):
matches = re.findall(r"^([^0-9]*)", string)
return next(iter(matches), "")
# when invoked as an updateScript, UPDATE_NIX_ATTR_PATH will be set
# this allows us to work with packages which live outside of octave-modules
attr_path = os.environ.get("UPDATE_NIX_ATTR_PATH", f"octavePackages.{package}")
try:
homepage = subprocess.check_output(
["nix", "eval", "-f", f"{NIXPGKS_ROOT}/default.nix", "--raw", f"{attr_path}.src.meta.homepage"])\
.decode('utf-8')
except Exception as e:
raise ValueError(f"Unable to determine homepage: {e}")
owner_repo = homepage[len("https://github.com/"):] # remove prefix
owner, repo = owner_repo.split("/")
url = f"https://api.github.com/repos/{owner}/{repo}/releases"
all_releases = _fetch_github(url)
releases = list(filter(lambda x: not x['prerelease'], all_releases))
if len(releases) == 0:
raise ValueError(f"{homepage} does not contain any stable releases")
versions = map(lambda x: strip_prefix(x['tag_name']), releases)
version = _determine_latest_version(current_version, target, versions)
release = next(filter(lambda x: strip_prefix(x['tag_name']) == version, releases))
prefix = get_prefix(release['tag_name'])
try:
sha256 = subprocess.check_output(["nix-prefetch-url", "--type", "sha256", "--unpack", f"{release['tarball_url']}"], stderr=subprocess.DEVNULL)\
.decode('utf-8').strip()
except:
# this may fail if they have both a branch and a tag of the same name, attempt tag name
tag_url = str(release['tarball_url']).replace("tarball","tarball/refs/tags")
sha256 = subprocess.check_output(["nix-prefetch-url", "--type", "sha256", "--unpack", tag_url], stderr=subprocess.DEVNULL)\
.decode('utf-8').strip()
return version, sha256, prefix
def _get_latest_version_git(package, extension, current_version, target):
"""NOTE: Unimplemented!"""
# attr_path = os.environ.get("UPDATE_NIX_ATTR_PATH", f"octavePackages.{package}")
# try:
# download_url = subprocess.check_output(
# ["nix", "--extra-experimental-features", "nix-command", "eval", "-f", f"{NIXPGKS_ROOT}/default.nix", "--raw", f"{attr_path}.src.url"])\
# .decode('utf-8')
# except Exception as e:
# raise ValueError(f"Unable to determine download link: {e}")
# with tempfile.TemporaryDirectory(prefix=attr_path) as new_clone_location:
# subprocess.run(["git", "clone", download_url, new_clone_location])
# newest_commit = subprocess.check_output(
# ["git" "rev-parse" "$(git branch -r)" "|" "tail" "-n" "1"]).decode('utf-8')
pass
FETCHERS = {
'fetchFromGitHub' : _get_latest_version_github,
'fetchurl' : _get_latest_version_octave_packages,
'fetchgit' : _get_latest_version_git,
}
DEFAULT_SETUPTOOLS_EXTENSION = 'tar.gz'
FORMATS = {
'setuptools' : DEFAULT_SETUPTOOLS_EXTENSION,
}
def _determine_fetcher(text):
# Count occurrences of fetchers.
nfetchers = sum(text.count('src = {}'.format(fetcher)) for fetcher in FETCHERS.keys())
if nfetchers == 0:
raise ValueError("no fetcher.")
elif nfetchers > 1:
raise ValueError("multiple fetchers.")
else:
# Then we check which fetcher to use.
for fetcher in FETCHERS.keys():
if 'src = {}'.format(fetcher) in text:
return fetcher
def _determine_extension(text, fetcher):
"""Determine what extension is used in the expression.
If we use:
- fetchPypi, we check if format is specified.
- fetchurl, we determine the extension from the url.
- fetchFromGitHub we simply use `.tar.gz`.
"""
if fetcher == 'fetchurl':
url = _get_unique_value('url', text)
extension = os.path.splitext(url)[1]
elif fetcher == 'fetchFromGitHub' or fetcher == 'fetchgit':
if "fetchSubmodules" in text:
raise ValueError("fetchFromGitHub fetcher doesn't support submodules")
extension = "tar.gz"
return extension
def _update_package(path, target):
# Read the expression
with open(path, 'r') as f:
text = f.read()
# Determine pname. Many files have more than one pname
pnames = _get_values('pname', text)
# Determine version.
version = _get_unique_value('version', text)
# First we check how many fetchers are mentioned.
fetcher = _determine_fetcher(text)
extension = _determine_extension(text, fetcher)
# Attempt a fetch using each pname, e.g. backports-zoneinfo vs backports.zoneinfo
successful_fetch = False
for pname in pnames:
if fetcher == "fetchgit":
logging.warning(f"You must update {pname} MANUALLY!")
return { 'path': path, 'target': target, 'pname': pname,
'old_version': version, 'new_version': version }
try:
new_version, new_sha256, prefix = FETCHERS[fetcher](pname, extension, version, target)
successful_fetch = True
break
except ValueError:
continue
if not successful_fetch:
raise ValueError(f"Unable to find correct package using these pnames: {pnames}")
if new_version == version:
logging.info("Path {}: no update available for {}.".format(path, pname))
return False
elif Version(new_version) <= Version(version):
raise ValueError("downgrade for {}.".format(pname))
if not new_sha256:
raise ValueError("no file available for {}.".format(pname))
text = _replace_value('version', new_version, text)
# hashes from pypi are 16-bit encoded sha256's, normalize it to sri to avoid merge conflicts
# sri hashes have been the default format since nix 2.4+
sri_hash = subprocess.check_output(["nix", "--extra-experimental-features", "nix-command", "hash", "to-sri", "--type", "sha256", new_sha256]).decode('utf-8').strip()
# fetchers can specify a sha256, or a sri hash
try:
text = _replace_value('sha256', sri_hash, text)
except ValueError:
text = _replace_value('hash', sri_hash, text)
if fetcher == 'fetchFromGitHub':
# in the case of fetchFromGitHub, it's common to see `rev = version;` or `rev = "v${version}";`
# in which no string value is meant to be substituted. However, we can just overwrite the previous value.
regex = '(rev\s+=\s+[^;]*;)'
regex = re.compile(regex)
matches = regex.findall(text)
n = len(matches)
if n == 0:
raise ValueError("Unable to find rev value for {}.".format(pname))
else:
# forcefully rewrite rev, incase tagging conventions changed for a release
match = matches[0]
text = text.replace(match, f'rev = "refs/tags/{prefix}${{version}}";')
# incase there's no prefix, just rewrite without interpolation
text = text.replace('"${version}";', 'version;')
with open(path, 'w') as f:
f.write(text)
logging.info("Path {}: updated {} from {} to {}".format(path, pname, version, new_version))
result = {
'path' : path,
'target': target,
'pname': pname,
'old_version' : version,
'new_version' : new_version,
#'fetcher' : fetcher,
}
return result
def _update(path, target):
# We need to read and modify a Nix expression.
if os.path.isdir(path):
path = os.path.join(path, 'default.nix')
# If a default.nix does not exist, we quit.
if not os.path.isfile(path):
logging.info("Path {}: does not exist.".format(path))
return False
# If file is not a Nix expression, we quit.
if not path.endswith(".nix"):
logging.info("Path {}: does not end with `.nix`.".format(path))
return False
try:
return _update_package(path, target)
except ValueError as e:
logging.warning("Path {}: {}".format(path, e))
return False
def _commit(path, pname, old_version, new_version, pkgs_prefix="octave: ", **kwargs):
"""Commit result.
"""
msg = f'{pkgs_prefix}{pname}: {old_version} -> {new_version}'
try:
subprocess.check_call([GIT, 'add', path])
subprocess.check_call([GIT, 'commit', '-m', msg])
except subprocess.CalledProcessError as e:
subprocess.check_call([GIT, 'checkout', path])
raise subprocess.CalledProcessError(f'Could not commit {path}') from e
return True
def main():
epilog = """
environment variables:
GITHUB_API_TOKEN\tGitHub API token used when updating github packages
"""
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, epilog=epilog)
parser.add_argument('package', type=str, nargs='+')
parser.add_argument('--target', type=str, choices=SEMVER.keys(), default='major')
parser.add_argument('--commit', action='store_true', help='Create a commit for each package update')
parser.add_argument('--use-pkgs-prefix', action='store_true', help='Use octavePackages.${pname}: instead of octave: ${pname}: when making commits')
args = parser.parse_args()
target = args.target
packages = list(map(os.path.abspath, args.package))
logging.info("Updating packages...")
# Use threads to update packages concurrently
with Pool() as p:
results = list(filter(bool, p.map(lambda pkg: _update(pkg, target), packages)))
logging.info("Finished updating packages.")
commit_options = {}
if args.use_pkgs_prefix:
logging.info("Using octavePackages. prefix for commits")
commit_options["pkgs_prefix"] = "octavePackages."
# Commits are created sequentially.
if args.commit:
logging.info("Committing updates...")
# list forces evaluation
list(map(lambda x: _commit(**x, **commit_options), results))
logging.info("Finished committing updates")
count = len(results)
logging.info("{} package(s) updated".format(count))
if __name__ == '__main__':
main()

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