1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 22:11:15 +02:00

Merge remote-tracking branch 'upstream/master' into lfs

This commit is contained in:
Leandro Reina 2024-12-18 18:18:45 +01:00
commit 7756b2286d
207 changed files with 1354 additions and 640 deletions

View file

@ -7,9 +7,16 @@ on:
permissions: read-all
jobs:
eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v30
- run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json
tests:
needs: [check_secrets]
strategy:
fail-fast: false
matrix:
@ -26,86 +33,21 @@ jobs:
extra_nix_config: |
sandbox = true
max-jobs = 1
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v15
if: needs.check_secrets.outputs.cachix == 'true'
- uses: DeterminateSystems/magic-nix-cache-action@main
# Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user:
# https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
if: matrix.os == 'ubuntu-latest'
- run: scripts/build-checks
- run: scripts/prepare-installer-for-github-actions
- name: Upload installer tarball
uses: actions/upload-artifact@v4
with:
name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- if: matrix.os == 'ubuntu-latest'
run: |
free -h
swapon --show
swap=$(swapon --show --noheadings | head -n 1 | awk '{print $1}')
echo "Found swap: $swap"
sudo swapoff $swap
# resize it (fallocate)
sudo fallocate -l 10G $swap
sudo mkswap $swap
sudo swapon $swap
free -h
(
while sleep 60; do
free -h
done
) &
- run: nix --experimental-features 'nix-command flakes' flake check -L
- run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json
# Steps to test CI automation in your own fork.
# Cachix:
# 1. Sign-up for https://www.cachix.org/
# 2. Create a cache for $githubuser-nix-install-tests
# 3. Create a cachix auth token and save it in https://github.com/$githubuser/nix/settings/secrets/actions in "Repository secrets" as CACHIX_AUTH_TOKEN
# Dockerhub:
# 1. Sign-up for https://hub.docker.com/
# 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions)
# 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork
check_secrets:
permissions:
contents: none
name: Check Cachix and Docker secrets present for installer tests
runs-on: ubuntu-latest
outputs:
cachix: ${{ steps.secret.outputs.cachix }}
docker: ${{ steps.secret.outputs.docker }}
steps:
- name: Check for secrets
id: secret
env:
_CACHIX_SECRETS: ${{ secrets.CACHIX_SIGNING_KEY }}${{ secrets.CACHIX_AUTH_TOKEN }}
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
run: |
echo "::set-output name=cachix::${{ env._CACHIX_SECRETS != '' }}"
echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}"
installer:
needs: [tests, check_secrets]
if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true'
runs-on: ubuntu-latest
outputs:
installerURL: ${{ steps.prepare-installer.outputs.installerURL }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/install-nix-action@v30
with:
install_url: https://releases.nixos.org/nix/nix-2.20.3/install
- uses: cachix/cachix-action@v15
with:
name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
cachixArgs: '-v'
- id: prepare-installer
run: scripts/prepare-installer-for-github-actions
name: installer-${{matrix.os}}
path: out/*
installer_test:
needs: [installer, check_secrets]
if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true'
needs: [tests]
strategy:
fail-fast: false
matrix:
@ -113,11 +55,18 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- name: Download installer tarball
uses: actions/download-artifact@v4
with:
name: installer-${{matrix.os}}
path: out
- name: Serving installer
id: serving_installer
run: ./scripts/serve-installer-for-github-actions
- uses: cachix/install-nix-action@v30
with:
install_url: '${{needs.installer.outputs.installerURL}}'
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
install_url: 'http://localhost:8126/install'
install_options: "--tarball-url-prefix http://localhost:8126/"
- run: sudo apt install fish zsh
if: matrix.os == 'ubuntu-latest'
- run: brew install fish
@ -129,32 +78,50 @@ jobs:
- run: exec bash -c "nix-channel --add https://releases.nixos.org/nixos/unstable/nixos-23.05pre466020.60c1d71f2ba nixpkgs"
- run: exec bash -c "nix-channel --update && nix-env -iA nixpkgs.hello && hello"
# Steps to test CI automation in your own fork.
# 1. Sign-up for https://hub.docker.com/
# 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions)
# 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork
check_secrets:
permissions:
contents: none
name: Check Docker secrets present for installer tests
runs-on: ubuntu-latest
outputs:
docker: ${{ steps.secret.outputs.docker }}
steps:
- name: Check for secrets
id: secret
env:
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
run: |
echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}"
docker_push_image:
needs: [check_secrets, tests, vm_tests]
needs: [tests, vm_tests, check_secrets]
permissions:
contents: read
packages: write
if: >-
needs.check_secrets.outputs.docker == 'true' &&
github.event_name == 'push' &&
github.ref_name == 'master' &&
needs.check_secrets.outputs.cachix == 'true' &&
needs.check_secrets.outputs.docker == 'true'
github.ref_name == 'master'
runs-on: ubuntu-latest
steps:
- name: Check for secrets
id: secret
env:
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
run: |
echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}"
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v30
with:
install_url: https://releases.nixos.org/nix/nix-2.20.3/install
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: DeterminateSystems/magic-nix-cache-action@main
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#nix.version | tr -d \")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v15
if: needs.check_secrets.outputs.cachix == 'true'
with:
name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix --experimental-features 'nix-command flakes' build .#dockerImage -L
- run: docker load -i ./result/image.tar.gz
- run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION

122
.gitignore vendored
View file

@ -1,110 +1,12 @@
Makefile.config
perl/Makefile.config
# /
/aclocal.m4
/autom4te.cache
/precompiled-headers.h.gch
/config.*
/configure
/stamp-h1
/svn-revision
/libtool
/config/config.*
# Default meson build dir
/build
# /doc/manual/
/doc/manual/*.1
/doc/manual/*.5
/doc/manual/*.8
/doc/manual/generated/*
/doc/manual/nix.json
/doc/manual/conf-file.json
/doc/manual/language.json
/doc/manual/xp-features.json
/doc/manual/source/SUMMARY.md
/doc/manual/source/SUMMARY-rl-next.md
/doc/manual/source/store/types/*
!/doc/manual/source/store/types/index.md.in
/doc/manual/source/command-ref/new-cli
/doc/manual/source/command-ref/conf-file.md
/doc/manual/source/command-ref/experimental-features-shortlist.md
/doc/manual/source/contributing/experimental-feature-descriptions.md
/doc/manual/source/language/builtins.md
/doc/manual/source/language/builtin-constants.md
/doc/manual/source/release-notes/rl-next.md
# /scripts/
/scripts/nix-profile.sh
/scripts/nix-profile-daemon.sh
/scripts/nix-profile.fish
/scripts/nix-profile-daemon.fish
# /src/libexpr/
/src/libexpr/lexer-tab.cc
/src/libexpr/lexer-tab.hh
/src/libexpr/parser-tab.cc
/src/libexpr/parser-tab.hh
/src/libexpr/parser-tab.output
/src/libexpr/nix.tbl
/src/libexpr/tests
/src/libexpr-tests/libnixexpr-tests
# /src/libfetchers
/src/libfetchers-tests/libnixfetchers-tests
# /src/libflake
/src/libflake-tests/libnixflake-tests
# /src/libstore/
*.gen.*
/src/libstore/tests
/src/libstore-tests/libnixstore-tests
# /src/libutil/
/src/libutil/tests
/src/libutil-tests/libnixutil-tests
/src/nix/nix
/src/nix/generated-doc
# /src/nix-env/
/src/nix-env/nix-env
# /src/nix-instantiate/
/src/nix-instantiate/nix-instantiate
# /src/nix-store/
/src/nix-store/nix-store
/src/nix-prefetch-url/nix-prefetch-url
/src/nix-collect-garbage/nix-collect-garbage
# /src/nix-channel/
/src/nix-channel/nix-channel
# /src/nix-build/
/src/nix-build/nix-build
/src/nix-copy-closure/nix-copy-closure
/src/error-demo/error-demo
/src/build-remote/build-remote
# /tests/functional/
/tests/functional/test-tmp
/tests/functional/common/subst-vars.sh
/tests/functional/result*
/tests/functional/restricted-innocent
/tests/functional/shell
/tests/functional/shell.drv
/tests/functional/repl-result-out
/tests/functional/debugger-test-out
/tests/functional/test-libstoreconsumer/test-libstoreconsumer
/tests/functional/nix-shell
# /tests/functional/lang/
/tests/functional/lang/*.out
@ -112,27 +14,9 @@ perl/Makefile.config
/tests/functional/lang/*.err
/tests/functional/lang/*.ast
/perl/lib/Nix/Config.pm
/perl/lib/Nix/Store.cc
/misc/systemd/nix-daemon.service
/misc/systemd/nix-daemon.socket
/misc/systemd/nix-daemon.conf
/misc/upstart/nix-daemon.conf
outputs/
*.a
*.o
*.o.tmp
*.so
*.dylib
*.dll
*.exe
*.dep
*~
*.pc
*.plist
# GNU Global
GPATH
@ -147,8 +31,6 @@ GTAGS
compile_commands.json
*.compile_commands.json
nix-rust/target
result
result-*
@ -163,3 +45,5 @@ result-*
# Mac OS
.DS_Store
flake-regressions

View file

@ -4,8 +4,9 @@ queue_rules:
merge_conditions:
- check-success=tests (macos-latest)
- check-success=tests (ubuntu-latest)
- check-success=installer_test (macos-latest)
- check-success=installer_test (ubuntu-latest)
- check-success=vm_tests
merge_method: rebase
batch_size: 5
pull_request_rules:

View file

@ -199,6 +199,7 @@ nix3_manpages = [
'nix3-build',
'nix3-bundle',
'nix3-config',
'nix3-config-check',
'nix3-config-show',
'nix3-copy',
'nix3-daemon',
@ -206,8 +207,8 @@ nix3_manpages = [
'nix3-derivation',
'nix3-derivation-show',
'nix3-develop',
#'nix3-doctor',
'nix3-edit',
'nix3-env-shell',
'nix3-eval',
'nix3-flake-archive',
'nix3-flake-check',
@ -224,6 +225,7 @@ nix3_manpages = [
'nix3-fmt',
'nix3-hash-file',
'nix3-hash',
'nix3-hash-convert',
'nix3-hash-path',
'nix3-hash-to-base16',
'nix3-hash-to-base32',
@ -238,6 +240,7 @@ nix3_manpages = [
'nix3-nar-cat',
'nix3-nar-dump-path',
'nix3-nar-ls',
'nix3-nar-pack',
'nix3-nar',
'nix3-path-info',
'nix3-print-dev-env',
@ -260,7 +263,7 @@ nix3_manpages = [
'nix3-repl',
'nix3-run',
'nix3-search',
#'nix3-shell',
'nix3-store-add',
'nix3-store-add-file',
'nix3-store-add-path',
'nix3-store-cat',
@ -270,6 +273,7 @@ nix3_manpages = [
'nix3-store-diff-closures',
'nix3-store-dump-path',
'nix3-store-gc',
'nix3-store-info',
'nix3-store-ls',
'nix3-store-make-content-addressed',
'nix3-store',

View file

@ -0,0 +1,22 @@
---
synopsis: "Flake lock file generation now ignores local registries"
prs: [12019]
---
When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`.
This avoids accidents where users have local registry overrides that map `nixpkgs` to a `path:` flake in the local file system, which then end up in committed lock files pushed to other users.
In the future, we may remove the use of the registry during lock file generation altogether. It's better to explicitly specify the URL of a flake input. For example, instead of
```nix
{
outputs = { self, nixpkgs }: { ... };
}
```
write
```nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
outputs = { self, nixpkgs }: { ... };
}
```

View file

@ -0,0 +1,21 @@
---
synopsis: "Improved `NIX_SSHOPTS` parsing for better SSH option handling"
issues: [5181]
prs: [12020]
---
The parsing of the `NIX_SSHOPTS` environment variable has been improved to handle spaces and quotes correctly.
Previously, incorrectly split SSH options could cause failures in CLIs like `nix-copy-closure`,
especially when using complex ssh invocations such as `-o ProxyCommand="ssh -W %h:%p ..."`.
This change introduces a `shellSplitString` function to ensure
that `NIX_SSHOPTS` is parsed in a manner consistent with shell
behavior, addressing common parsing errors.
For example, the following now works as expected:
```bash
export NIX_SSHOPTS='-o ProxyCommand="ssh -W %h:%p ..."'
```
This update improves the reliability of SSH-related operations using `NIX_SSHOPTS` across Nix CLIs.

View file

@ -186,7 +186,7 @@
};
checks = forAllSystems (system: {
binaryTarball = self.hydraJobs.binaryTarball.${system};
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
installTests = self.hydraJobs.installTests.${system};
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
rl-next =
@ -201,11 +201,7 @@
# Some perl dependencies are broken on i686-linux.
# Since the support is only best-effort there, disable the perl
# bindings
# Temporarily disabled because GitHub Actions OOM issues. Once
# the old build system is gone and we are back to one build
# system, we should reenable this.
#perlBindings = self.hydraJobs.perlBindings.${system};
perlBindings = self.hydraJobs.perlBindings.${system};
}
# Add "passthru" tests
// flatMapAttrs ({
@ -237,6 +233,8 @@
inherit (nixpkgsFor.${system}.native)
changelog-d;
default = self.packages.${system}.nix;
installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system};
binaryTarball = self.hydraJobs.binaryTarball.${system};
# TODO probably should be `nix-cli`
nix = self.packages.${system}.nix-everything;
nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual;

View file

@ -12,6 +12,8 @@
hooks = {
clang-format = {
enable = true;
# https://github.com/cachix/git-hooks.nix/pull/532
package = pkgs.llvmPackages_latest.clang-tools;
excludes = [
# We don't want to format test data
# ''tests/(?!nixos/).*\.nix''

13
misc/launchd/meson.build Normal file
View file

@ -0,0 +1,13 @@
configure_file(
input : 'org.nixos.nix-daemon.plist.in',
output : 'org.nixos.nix-daemon.plist',
install : true,
install_dir : get_option('prefix') / 'Library/LaunchDaemons',
install_mode : 'rw-r--r--',
configuration : {
# TODO: unhardcode paths with something like:
# 'storedir' : store_dir,
# 'localstatedir' : localstatedir,
# 'bindir' : bindir,
},
)

View file

@ -2,4 +2,10 @@ subdir('bash')
subdir('fish')
subdir('zsh')
subdir('systemd')
if host_machine.system() == 'linux'
subdir('systemd')
endif
if host_machine.system() == 'darwin'
subdir('launchd')
endif

View file

@ -18,12 +18,8 @@ let
testNixVersions = pkgs: daemon:
pkgs.nixComponents.nix-functional-tests.override {
pname =
"nix-tests"
+ lib.optionalString
(lib.versionAtLeast daemon.version "2.4pre20211005" &&
lib.versionAtLeast pkgs.nix.version "2.4pre20211005")
"-${pkgs.nix.version}-against-${daemon.version}";
pname = "nix-daemon-compat-tests";
version = "${pkgs.nix.version}-with-daemon-${daemon.version}";
test-daemon = daemon;
};
@ -127,15 +123,10 @@ in
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf"
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
];
installerScriptForGHA = installScriptFor [
# Native
self.hydraJobs.binaryTarball."x86_64-linux"
self.hydraJobs.binaryTarball."aarch64-darwin"
# Cross
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv6l-unknown-linux-gnueabihf"
self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf"
self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu"
];
installerScriptForGHA = forAllSystems (system: nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix {
tarballs = [ self.hydraJobs.binaryTarball.${system} ];
});
# docker image with Nix inside
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);

View file

@ -65,7 +65,7 @@ runCommand "nix-binary-tarball-${version}" env ''
fn=$out/$dir.tar.xz
mkdir -p $out/nix-support
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
tar cvfJ $fn \
tar cfJ $fn \
--owner=0 --group=0 --mode=u+rw,uga+r \
--mtime='1970-01-01' \
--absolute-names \

6
scripts/build-checks Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
system=$(nix eval --raw --impure --expr builtins.currentSystem)
nix eval --json ".#checks.$system" --apply builtins.attrNames | \
jq -r '.[]' | \
xargs -P0 -I '{}' sh -c "nix build -L .#checks.$system.{} || { echo 'FAILED: \033[0;31mnix build -L .#checks.$system.{}\\033[0m'; kill 0; }"

View file

@ -463,7 +463,7 @@ EOF
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
:a
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,nosuid,noatime,owners
.
:x
EOF

View file

@ -56,6 +56,9 @@ readonly NIX_INSTALLED_CACERT="@cacert@"
#readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2"
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
# allow to override identity change command
readonly NIX_BECOME=${NIX_BECOME:-sudo}
readonly ROOT_HOME=~root
if [ -t 0 ] && [ -z "${NIX_INSTALLER_YES:-}" ]; then
@ -123,7 +126,7 @@ uninstall_directions() {
cat <<EOF
$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target
sudo mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
$NIX_BECOME mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
(after this one, you may need to re-open any terminals that were
opened while it existed.)
@ -136,7 +139,7 @@ EOF
cat <<EOF
$step. Delete the files Nix added to your system:
sudo rm -rf "/etc/nix" "$NIX_ROOT" "$ROOT_HOME/.nix-profile" "$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.local/state/nix" "$ROOT_HOME/.cache/nix" "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" "$HOME/.local/state/nix" "$HOME/.cache/nix"
$NIX_BECOME rm -rf "/etc/nix" "$NIX_ROOT" "$ROOT_HOME/.nix-profile" "$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.local/state/nix" "$ROOT_HOME/.cache/nix" "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" "$HOME/.local/state/nix" "$HOME/.cache/nix"
and that is it.
@ -343,7 +346,7 @@ __sudo() {
echo "I am executing:"
echo ""
printf " $ sudo %s\\n" "$cmd"
printf " $ $NIX_BECOME %s\\n" "$cmd"
echo ""
echo "$expl"
echo ""
@ -361,7 +364,9 @@ _sudo() {
if is_root; then
env "$@"
else
sudo "$@"
# env sets environment variables for sudo alternatives
# that don't support "VAR=value command" syntax
$NIX_BECOME env "$@"
fi
}
@ -690,7 +695,7 @@ place_channel_configuration() {
if [ -z "${NIX_INSTALLER_NO_CHANNEL_ADD:-}" ]; then
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
_sudo "to set up the default system channel (part 1)" \
install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
install -m 0644 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
fi
}
@ -964,7 +969,7 @@ $NIX_EXTRA_CONF
build-users-group = $NIX_BUILD_GROUP_NAME
EOF
_sudo "to place the default nix daemon configuration (part 2)" \
install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf
install -m 0644 "$SCRATCH/nix.conf" /etc/nix/nix.conf
}

View file

@ -9,6 +9,8 @@ self="$(dirname "$0")"
nix="@nix@"
cacert="@cacert@"
# allow to override identity change command
readonly NIX_BECOME="${NIX_BECOME:-sudo}"
if ! [ -e "$self/.reginfo" ]; then
echo "$0: incomplete installer (.reginfo is missing)" >&2
@ -63,7 +65,6 @@ while [ $# -gt 0 ]; do
exit 1
fi
INSTALL_MODE=no-daemon
# intentional tail space
ACTION=install
;;
--yes)
@ -135,8 +136,8 @@ echo "performing a single-user installation of Nix..." >&2
if ! [ -e "$dest" ]; then
cmd="mkdir -m 0755 $dest && chown $USER $dest"
echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2
if ! sudo sh -c "$cmd"; then
echo "directory $dest does not exist; creating it by running '$cmd' using $NIX_BECOME" >&2
if ! $NIX_BECOME sh -c "$cmd"; then
echo "$0: please manually run '$cmd' as root to create $dest" >&2
exit 1
fi

View file

@ -1,10 +1,11 @@
#!/usr/bin/env bash
set -e
set -euo pipefail
script=$(nix-build -A outputs.hydraJobs.installerScriptForGHA --no-out-link)
installerHash=$(echo "$script" | cut -b12-43 -)
nix build -L ".#installerScriptForGHA" ".#binaryTarball"
installerURL=https://$CACHIX_NAME.cachix.org/serve/$installerHash/install
echo "::set-output name=installerURL::$installerURL"
mkdir -p out
cp ./result/install "out/install"
name="$(basename "$(realpath ./result-1)")"
# everything before the first dash
cp -r ./result-1 "out/${name%%-*}"

View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ ! -d out ]]; then
echo "run prepare-installer-for-github-actions first"
exit 1
fi
cd out
PORT=${PORT:-8126}
nohup python -m http.server "$PORT" >/dev/null 2>&1 &
pid=$!
while ! curl -s "http://localhost:$PORT"; do
sleep 1
if ! kill -0 $pid; then
echo "Failed to start http server"
exit 1
fi
done
echo 'To install nix, run the following command:'
echo "sh <(curl http://localhost:$PORT/install) --tarball-url-prefix http://localhost:$PORT"

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-cmd', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -28,7 +28,7 @@ deps_public_maybe_subproject = [
dependency('nix-flake'),
dependency('nix-main'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
deps_public += nlohmann_json
@ -70,7 +70,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'built-path.cc',
@ -125,4 +125,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -39,8 +39,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-expr-c', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -27,7 +27,7 @@ deps_public_maybe_subproject = [
dependency('nix-util-c'),
dependency('nix-store-c'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
# TODO rename, because it will conflict with downstream projects
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
@ -53,7 +53,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'nix_api_expr.cc',
@ -72,8 +72,8 @@ headers = [config_h] + files(
# TODO move this header to libexpr, maybe don't use it in tests?
headers += files('nix_api_expr_internal.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
this_library = library(
'nixexprc',
@ -89,4 +89,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -20,8 +20,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-expr-test-support', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
deps_private_maybe_subproject = [
]
@ -26,7 +26,7 @@ deps_public_maybe_subproject = [
dependency('nix-expr'),
dependency('nix-expr-c'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
rapidcheck = dependency('rapidcheck')
deps_public += rapidcheck
@ -40,7 +40,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'tests/value/context.cc',
@ -54,8 +54,8 @@ headers = files(
'tests/value/context.hh',
)
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
this_library = library(
'nix-expr-test-support',
@ -73,4 +73,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -23,8 +23,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -691,15 +691,15 @@ namespace nix {
ASSERT_TRACE2("elemAt \"foo\" (-1)",
TypeError,
HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)),
HintFmt("while evaluating the first argument passed to builtins.elemAt"));
HintFmt("while evaluating the first argument passed to 'builtins.elemAt'"));
ASSERT_TRACE1("elemAt [] (-1)",
Error,
HintFmt("list index %d is out of bounds", -1));
HintFmt("'builtins.elemAt' called with index %d on a list of size %d", -1, 0));
ASSERT_TRACE1("elemAt [\"foo\"] 3",
Error,
HintFmt("list index %d is out of bounds", 3));
HintFmt("'builtins.elemAt' called with index %d on a list of size %d", 3, 1));
}
@ -708,11 +708,11 @@ namespace nix {
ASSERT_TRACE2("head 1",
TypeError,
HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)),
HintFmt("while evaluating the first argument passed to builtins.elemAt"));
HintFmt("while evaluating the first argument passed to 'builtins.head'"));
ASSERT_TRACE1("head []",
Error,
HintFmt("list index %d is out of bounds", 0));
HintFmt("'builtins.head' called on an empty list"));
}
@ -721,11 +721,11 @@ namespace nix {
ASSERT_TRACE2("tail 1",
TypeError,
HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)),
HintFmt("while evaluating the first argument passed to builtins.tail"));
HintFmt("while evaluating the first argument passed to 'builtins.tail'"));
ASSERT_TRACE1("tail []",
Error,
HintFmt("'tail' called on an empty list"));
HintFmt("'builtins.tail' called on an empty list"));
}

View file

@ -14,7 +14,7 @@ project('nix-expr-tests', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
deps_private_maybe_subproject = [
dependency('nix-expr'),
@ -23,10 +23,10 @@ deps_private_maybe_subproject = [
]
deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck
@ -49,7 +49,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'derived-path.cc',

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -27,8 +27,8 @@ mkMesonExecutable (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -347,6 +347,16 @@ void EvalState::allowPath(const StorePath & storePath)
rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath)));
}
void EvalState::allowClosure(const StorePath & storePath)
{
if (!rootFS.dynamic_pointer_cast<AllowListSourceAccessor>()) return;
StorePathSet closure;
store->computeFSClosure(storePath, closure);
for (auto & p : closure)
allowPath(p);
}
void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v)
{
allowPath(storePath);
@ -3099,10 +3109,7 @@ std::optional<SourcePath> EvalState::resolveLookupPathPath(const LookupPath::Pat
allowPath(path.path.abs());
if (store->isInStore(path.path.abs())) {
try {
StorePathSet closure;
store->computeFSClosure(store->toStorePath(path.path.abs()).first, closure);
for (auto & p : closure)
allowPath(p);
allowClosure(store->toStorePath(path.path.abs()).first);
} catch (InvalidPath &) { }
}
}
@ -3178,5 +3185,14 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) {
return v.print(str);
}
void forceNoNullByte(std::string_view s)
{
if (s.find('\0') != s.npos) {
using namespace std::string_view_literals;
auto str = replaceStrings(std::string(s), "\0"sv, ""sv);
throw Error("input string '%s' cannot be represented as Nix string because it contains null bytes", str);
}
}
}

View file

@ -400,6 +400,11 @@ public:
*/
void allowPath(const StorePath & storePath);
/**
* Allow access to the closure of a store path.
*/
void allowClosure(const StorePath & storePath);
/**
* Allow access to a store path and return it as a string.
*/

View file

@ -50,6 +50,7 @@ class JSONSax : nlohmann::json_sax<json> {
public:
void key(string_t & name, EvalState & state)
{
forceNoNullByte(name);
attrs.insert_or_assign(state.symbols.create(name), &value(state));
}
};
@ -122,6 +123,7 @@ public:
bool string(string_t & val) override
{
forceNoNullByte(val);
rs->value(state).mkString(val);
rs->add();
return true;

View file

@ -1,5 +1,13 @@
#pragma once
#include <cstddef>
// inluding the generated headers twice leads to errors
#ifndef BISON_HEADER
# include "lexer-tab.hh"
# include "parser-tab.hh"
#endif
namespace nix::lexer::internal {
void initLoc(YYLTYPE * loc);

View file

@ -14,7 +14,7 @@ project('nix-expr', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -25,7 +25,7 @@ deps_public_maybe_subproject = [
dependency('nix-store'),
dependency('nix-fetchers'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
boost = dependency(
'boost',
@ -77,7 +77,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
parser_tab = custom_target(
input : 'parser.y',
@ -121,7 +121,7 @@ lexer_tab = custom_target(
install_dir : get_option('includedir') / 'nix',
)
subdir('build-utils-meson/generate-header')
subdir('nix-meson-build-support/generate-header')
generated_headers = []
foreach header : [
@ -205,4 +205,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -168,7 +168,7 @@ struct ExprVar : Expr
the set stored in the environment that is `level` levels up
from the current one.*/
Level level;
Displacement displ;
Displacement displ = 0;
ExprVar(Symbol name) : name(name) { };
ExprVar(const PosIdx & pos, Symbol name) : pos(pos), name(name) { };
@ -242,7 +242,7 @@ struct ExprAttrs : Expr
Kind kind;
Expr * e;
PosIdx pos;
Displacement displ; // displacement
Displacement displ = 0; // displacement
AttrDef(Expr * e, const PosIdx & pos, Kind kind = Kind::Plain)
: kind(kind), e(e), pos(pos) { };
AttrDef() { };

View file

@ -40,8 +40,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -119,11 +119,9 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow);
if (isIFD) {
for (auto & outputPath : outputsToCopyAndAllow) {
/* Add the output of this derivations to the allowed
paths. */
allowPath(outputPath);
}
/* Allow access to the output closures of this derivation. */
for (auto & outputPath : outputsToCopyAndAllow)
allowClosure(outputPath);
}
return res;
@ -1100,7 +1098,7 @@ static RegisterPrimOp primop_warn({
.name = "__warn",
.args = {"e1", "e2"},
.doc = R"(
Evaluate *e1*, which must be a string and print iton standard error as a warning.
Evaluate *e1*, which must be a string, and print it on standard error as a warning.
Then return *e2*.
This function is useful for non-critical situations where attention is advisable.
@ -3259,23 +3257,19 @@ static RegisterPrimOp primop_isList({
.fun = prim_isList,
});
static void elemAt(EvalState & state, const PosIdx pos, Value & list, int n, Value & v)
{
state.forceList(list, pos, "while evaluating the first argument passed to builtins.elemAt");
if (n < 0 || (unsigned int) n >= list.listSize())
state.error<EvalError>(
"list index %1% is out of bounds",
n
).atPos(pos).debugThrow();
state.forceValue(*list.listElems()[n], pos);
v = *list.listElems()[n];
}
/* Return the n-1'th element of a list. */
static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
NixInt::Inner elem = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.elemAt").value;
elemAt(state, pos, *args[0], elem, v);
NixInt::Inner n = state.forceInt(*args[1], pos, "while evaluating the second argument passed to 'builtins.elemAt'").value;
state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.elemAt'");
if (n < 0 || (unsigned int) n >= args[0]->listSize())
state.error<EvalError>(
"'builtins.elemAt' called with index %d on a list of size %d",
n,
args[0]->listSize()
).atPos(pos).debugThrow();
state.forceValue(*args[0]->listElems()[n], pos);
v = *args[0]->listElems()[n];
}
static RegisterPrimOp primop_elemAt({
@ -3291,7 +3285,13 @@ static RegisterPrimOp primop_elemAt({
/* Return the first element of a list. */
static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
elemAt(state, pos, *args[0], 0, v);
state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.head'");
if (args[0]->listSize() == 0)
state.error<EvalError>(
"'builtins.head' called on an empty list"
).atPos(pos).debugThrow();
state.forceValue(*args[0]->listElems()[0], pos);
v = *args[0]->listElems()[0];
}
static RegisterPrimOp primop_head({
@ -3310,9 +3310,9 @@ static RegisterPrimOp primop_head({
don't want to use it! */
static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.tail");
state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.tail'");
if (args[0]->listSize() == 0)
state.error<EvalError>("'tail' called on an empty list").atPos(pos).debugThrow();
state.error<EvalError>("'builtins.tail' called on an empty list").atPos(pos).debugThrow();
auto list = state.buildList(args[0]->listSize() - 1);
for (const auto & [n, v] : enumerate(list))

View file

@ -28,8 +28,10 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
auto attrs = state.buildBindings(size);
for(auto & elem : table)
for(auto & elem : table) {
forceNoNullByte(elem.first);
visit(attrs.alloc(elem.first), elem.second);
}
v.mkAttrs(attrs);
}
@ -54,7 +56,11 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
v.mkFloat(toml::get<NixFloat>(t));
break;;
case toml::value_t::string:
v.mkString(toml::get<std::string>(t));
{
auto s = toml::get<std::string_view>(t);
forceNoNullByte(s);
v.mkString(s);
}
break;;
case toml::value_t::local_datetime:
case toml::value_t::offset_datetime:
@ -66,7 +72,9 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V
attrs.alloc("_type").mkString("timestamp");
std::ostringstream s;
s << t;
attrs.alloc("value").mkString(toView(s));
auto str = toView(s);
forceNoNullByte(str);
attrs.alloc("value").mkString(str);
v.mkAttrs(attrs);
} else {
throw std::runtime_error("Dates and times are not supported");

View file

@ -5,6 +5,7 @@
*/
#include <limits>
#include <stddef.h>
namespace nix {

View file

@ -510,4 +510,6 @@ typedef std::shared_ptr<Value *> RootValue;
RootValue allocRootValue(Value * v);
void forceNoNullByte(std::string_view s);
}

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-fetchers-tests', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
deps_private_maybe_subproject = [
dependency('nix-store-test-support'),
@ -22,10 +22,10 @@ deps_private_maybe_subproject = [
]
deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck
@ -42,7 +42,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'public-key.cc',

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -26,8 +26,8 @@ mkMesonExecutable (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -113,7 +113,15 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs)
std::optional<std::string> Input::getFingerprint(ref<Store> store) const
{
return scheme ? scheme->getFingerprint(store, *this) : std::nullopt;
if (!scheme) return std::nullopt;
if (cachedFingerprint) return *cachedFingerprint;
auto fingerprint = scheme->getFingerprint(store, *this);
cachedFingerprint = fingerprint;
return fingerprint;
}
ParsedURL Input::toURL() const
@ -307,7 +315,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
auto accessor = makeStorePathAccessor(store, storePath);
accessor->fingerprint = scheme->getFingerprint(store, *this);
accessor->fingerprint = getFingerprint(store);
return {accessor, *this};
} catch (Error & e) {
@ -318,7 +326,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
auto [accessor, result] = scheme->getAccessor(store, *this);
assert(!accessor->fingerprint);
accessor->fingerprint = scheme->getFingerprint(store, result);
accessor->fingerprint = result.getFingerprint(store);
return {accessor, std::move(result)};
}

View file

@ -46,6 +46,11 @@ struct Input
*/
std::optional<Path> parent;
/**
* Cached result of getFingerprint().
*/
mutable std::optional<std::optional<std::string>> cachedFingerprint;
public:
/**
* Create an `Input` from a URL.
@ -104,6 +109,11 @@ public:
bool operator ==(const Input & other) const noexcept;
bool operator <(const Input & other) const
{
return attrs < other.attrs;
}
bool contains(const Input & other) const;
/**

View file

@ -6,6 +6,7 @@
#include "signals.hh"
#include "users.hh"
#include "fs-sink.hh"
#include "sync.hh"
#include <git2/attr.h>
#include <git2/blob.h>
@ -438,7 +439,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
{
if (!(statusFlags & GIT_STATUS_INDEX_DELETED) &&
!(statusFlags & GIT_STATUS_WT_DELETED))
{
info.files.insert(CanonPath(path));
if (statusFlags != GIT_STATUS_CURRENT)
info.dirtyFiles.insert(CanonPath(path));
} else
info.deletedFiles.insert(CanonPath(path));
if (statusFlags != GIT_STATUS_CURRENT)
info.isDirty = true;
return 0;
@ -1311,4 +1317,17 @@ ref<GitRepo> getTarballCache()
return GitRepo::openRepo(repoDir, true, true);
}
GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path & path)
{
static Sync<std::map<std::filesystem::path, WorkdirInfo>> _cache;
{
auto cache(_cache.lock());
auto i = cache->find(path);
if (i != cache->end()) return i->second;
}
auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo();
_cache.lock()->emplace(path, workdirInfo);
return workdirInfo;
}
}

View file

@ -59,12 +59,20 @@ struct GitRepo
modified or added, but excluding deleted files. */
std::set<CanonPath> files;
/* All modified or added files. */
std::set<CanonPath> dirtyFiles;
/* The deleted files. */
std::set<CanonPath> deletedFiles;
/* The submodules listed in .gitmodules of this workdir. */
std::vector<Submodule> submodules;
};
virtual WorkdirInfo getWorkdirInfo() = 0;
static WorkdirInfo getCachedWorkdirInfo(const std::filesystem::path & path);
/* Get the ref that HEAD points to. */
virtual std::optional<std::string> getWorkdirRef() = 0;

View file

@ -15,6 +15,7 @@
#include "finally.hh"
#include "fetch-settings.hh"
#include "json-utils.hh"
#include "archive.hh"
#include <regex>
#include <string.h>
@ -438,7 +439,7 @@ struct GitInputScheme : InputScheme
// If this is a local directory and no ref or revision is
// given, then allow the use of an unclean working tree.
if (!input.getRef() && !input.getRev() && repoInfo.isLocal)
repoInfo.workdirInfo = GitRepo::openRepo(repoInfo.url)->getWorkdirInfo();
repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(repoInfo.url);
return repoInfo;
}
@ -803,12 +804,33 @@ struct GitInputScheme : InputScheme
std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const override
{
if (auto rev = input.getRev())
auto makeFingerprint = [&](const Hash & rev)
{
return rev->gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : "") + (getLfsAttr(input) ? ";l" : "");
}
else
return rev.gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : "") + (getLfsAttr(input) ? ";l" : "");
};
if (auto rev = input.getRev())
return makeFingerprint(*rev);
else {
auto repoInfo = getRepoInfo(input);
if (repoInfo.isLocal && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) {
/* Calculate a fingerprint that takes into account the
deleted and modified/added files. */
HashSink hashSink{HashAlgorithm::SHA512};
for (auto & file : repoInfo.workdirInfo.dirtyFiles) {
writeString("modified:", hashSink);
writeString(file.abs(), hashSink);
dumpPath(repoInfo.url + "/" + file.abs(), hashSink);
}
for (auto & file : repoInfo.workdirInfo.deletedFiles) {
writeString("deleted:", hashSink);
writeString(file.abs(), hashSink);
}
return makeFingerprint(*repoInfo.workdirInfo.headRev)
+ ";d=" + hashSink.finish().first.to_string(HashFormat::Base16, false);
}
return std::nullopt;
}
}
bool isLocked(const Input & input) const override

View file

@ -14,7 +14,7 @@ project('nix-fetchers', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -24,7 +24,7 @@ deps_public_maybe_subproject = [
dependency('nix-util'),
dependency('nix-store'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
deps_public += nlohmann_json
@ -44,7 +44,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'attrs.cc',
@ -94,4 +94,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -23,8 +23,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -178,7 +178,8 @@ Registries getRegistries(const Settings & settings, ref<Store> store)
std::pair<Input, Attrs> lookupInRegistries(
ref<Store> store,
const Input & _input)
const Input & _input,
const RegistryFilter & filter)
{
Attrs extraAttrs;
int n = 0;
@ -190,6 +191,7 @@ std::pair<Input, Attrs> lookupInRegistries(
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
for (auto & registry : getRegistries(*input.settings, store)) {
if (filter && !filter(registry->type)) continue;
// FIXME: O(n)
for (auto & entry : registry->entries) {
if (entry.exact) {

View file

@ -65,8 +65,15 @@ void overrideRegistry(
const Input & to,
const Attrs & extraAttrs);
using RegistryFilter = std::function<bool(Registry::RegistryType)>;
/**
* Rewrite a flakeref using the registries. If `filter` is set, only
* use the registries for which the filter function returns true.
*/
std::pair<Input, Attrs> lookupInRegistries(
ref<Store> store,
const Input & input);
const Input & input,
const RegistryFilter & filter = {});
}

View file

@ -1 +0,0 @@
../../build-utils-meson/

View file

@ -14,7 +14,7 @@ project('nix-flake-c', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -29,7 +29,7 @@ deps_public_maybe_subproject = [
dependency('nix-store-c'),
dependency('nix-expr-c'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
# TODO rename, because it will conflict with downstream projects
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
@ -58,7 +58,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'nix_api_flake.cc',
@ -73,8 +73,8 @@ headers = [config_h] + files(
# TODO move this header to libexpr, maybe don't use it in tests?
headers += files('nix_api_flake.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
this_library = library(
'nixflakec',
@ -90,4 +90,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -21,8 +21,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-flake-tests', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
deps_private_maybe_subproject = [
dependency('nix-expr-test-support'),
@ -23,10 +23,10 @@ deps_private_maybe_subproject = [
]
deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck
@ -43,7 +43,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'flakeref.cc',

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -27,8 +27,8 @@ mkMesonExecutable (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -21,23 +21,23 @@ using namespace flake;
namespace flake {
typedef std::pair<StorePath, FlakeRef> FetchedFlake;
typedef std::vector<std::pair<FlakeRef, FetchedFlake>> FlakeCache;
struct FetchedFlake
{
FlakeRef lockedRef;
StorePath storePath;
};
typedef std::map<FlakeRef, FetchedFlake> FlakeCache;
static std::optional<FetchedFlake> lookupInFlakeCache(
const FlakeCache & flakeCache,
const FlakeRef & flakeRef)
{
// FIXME: inefficient.
for (auto & i : flakeCache) {
if (flakeRef == i.first) {
debug("mapping '%s' to previously seen input '%s' -> '%s",
flakeRef, i.first, i.second.second);
return i.second;
}
}
return std::nullopt;
auto i = flakeCache.find(flakeRef);
if (i == flakeCache.end()) return std::nullopt;
debug("mapping '%s' to previously seen input '%s' -> '%s",
flakeRef, i->first, i->second.lockedRef);
return i->second;
}
static std::tuple<StorePath, FlakeRef, FlakeRef> fetchOrSubstituteTree(
@ -51,32 +51,39 @@ static std::tuple<StorePath, FlakeRef, FlakeRef> fetchOrSubstituteTree(
if (!fetched) {
if (originalRef.input.isDirect()) {
fetched.emplace(originalRef.fetchTree(state.store));
auto [storePath, lockedRef] = originalRef.fetchTree(state.store);
fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .storePath = storePath});
} else {
if (allowLookup) {
resolvedRef = originalRef.resolve(state.store);
auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef);
if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store));
flakeCache.push_back({resolvedRef, *fetchedResolved});
fetched.emplace(*fetchedResolved);
resolvedRef = originalRef.resolve(
state.store,
[](fetchers::Registry::RegistryType type) {
/* Only use the global registry and CLI flags
to resolve indirect flakerefs. */
return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
});
fetched = lookupInFlakeCache(flakeCache, originalRef);
if (!fetched) {
auto [storePath, lockedRef] = resolvedRef.fetchTree(state.store);
fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .storePath = storePath});
}
flakeCache.insert_or_assign(resolvedRef, *fetched);
}
else {
throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef);
}
}
flakeCache.push_back({originalRef, *fetched});
flakeCache.insert_or_assign(originalRef, *fetched);
}
auto [storePath, lockedRef] = *fetched;
debug("got tree '%s' from '%s'",
state.store->printStorePath(storePath), lockedRef);
state.store->printStorePath(fetched->storePath), fetched->lockedRef);
state.allowPath(storePath);
state.allowPath(fetched->storePath);
assert(!originalRef.input.getNarHash() || storePath == originalRef.input.computeStorePath(*state.store));
assert(!originalRef.input.getNarHash() || fetched->storePath == originalRef.input.computeStorePath(*state.store));
return {std::move(storePath), resolvedRef, lockedRef};
return {fetched->storePath, resolvedRef, fetched->lockedRef};
}
static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos)
@ -672,6 +679,8 @@ LockedFlake lockFlake(
if (lockFlags.writeLockFile) {
if (sourcePath || lockFlags.outputLockFilePath) {
if (auto unlockedInput = newLockFile.isUnlocked()) {
if (lockFlags.failOnUnlocked)
throw Error("cannot write lock file of flake '%s' because it has an unlocked input ('%s').\n", topRef, *unlockedInput);
if (state.fetchSettings.warnDirty)
warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput);
} else {

View file

@ -156,6 +156,11 @@ struct LockFlags
*/
bool writeLockFile = true;
/**
* Throw an exception when the flake has an unlocked input.
*/
bool failOnUnlocked = false;
/**
* Whether to use the registries to lookup indirect flake
* references like 'nixpkgs'.

View file

@ -3,7 +3,6 @@
#include "url.hh"
#include "url-parts.hh"
#include "fetchers.hh"
#include "registry.hh"
namespace nix {
@ -36,7 +35,9 @@ std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef)
return str;
}
FlakeRef FlakeRef::resolve(ref<Store> store) const
FlakeRef FlakeRef::resolve(
ref<Store> store,
const fetchers::RegistryFilter & filter) const
{
auto [input2, extraAttrs] = lookupInRegistries(store, input);
return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir));

View file

@ -6,6 +6,7 @@
#include "types.hh"
#include "fetchers.hh"
#include "outputs-spec.hh"
#include "registry.hh"
namespace nix {
@ -48,6 +49,11 @@ struct FlakeRef
bool operator ==(const FlakeRef & other) const = default;
bool operator <(const FlakeRef & other) const
{
return std::tie(input, subdir) < std::tie(other.input, other.subdir);
}
FlakeRef(fetchers::Input && input, const Path & subdir)
: input(std::move(input)), subdir(subdir)
{ }
@ -57,7 +63,9 @@ struct FlakeRef
fetchers::Attrs toAttrs() const;
FlakeRef resolve(ref<Store> store) const;
FlakeRef resolve(
ref<Store> store,
const fetchers::RegistryFilter & filter = {}) const;
static FlakeRef fromAttrs(
const fetchers::Settings & fetchSettings,

View file

@ -14,7 +14,7 @@ project('nix-flake', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
deps_private_maybe_subproject = [
]
@ -24,7 +24,7 @@ deps_public_maybe_subproject = [
dependency('nix-fetchers'),
dependency('nix-expr'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
deps_public += nlohmann_json
@ -39,7 +39,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'flake/config.cc',
@ -72,4 +72,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -23,8 +23,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-main-c', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -27,7 +27,7 @@ deps_public_maybe_subproject = [
dependency('nix-util-c'),
dependency('nix-store-c'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
# TODO rename, because it will conflict with downstream projects
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
@ -53,7 +53,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'nix_api_main.cc',
@ -65,8 +65,8 @@ headers = [config_h] + files(
'nix_api_main.h',
)
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
this_library = library(
'nixmainc',
@ -82,4 +82,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-main', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -24,7 +24,7 @@ deps_public_maybe_subproject = [
dependency('nix-util'),
dependency('nix-store'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
pubsetbuf_test = '''
#include <iostream>
@ -58,7 +58,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'common-args.cc',
@ -96,4 +96,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: {
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../nix-meson-build-support
./nix-meson-build-support
../../.version
./.version
./meson.build

View file

@ -1 +0,0 @@
../../build-utils-meson

View file

@ -14,7 +14,7 @@ project('nix-store-c', 'cpp',
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
subdir('nix-meson-build-support/deps-lists')
configdata = configuration_data()
@ -25,7 +25,7 @@ deps_private_maybe_subproject = [
deps_public_maybe_subproject = [
dependency('nix-util-c'),
]
subdir('build-utils-meson/subprojects')
subdir('nix-meson-build-support/subprojects')
# TODO rename, because it will conflict with downstream projects
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
@ -49,7 +49,7 @@ add_project_arguments(
language : 'cpp',
)
subdir('build-utils-meson/common')
subdir('nix-meson-build-support/common')
sources = files(
'nix_api_store.cc',
@ -64,8 +64,8 @@ headers = [config_h] + files(
# TODO don't install this once tests don't use it and/or move the header into `libstore`, non-`c`
headers += files('nix_api_store_internal.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')
this_library = library(
'nixstorec',
@ -81,4 +81,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')
subdir('nix-meson-build-support/export')

View file

@ -0,0 +1 @@
../../nix-meson-build-support

View file

@ -67,6 +67,17 @@ nix_err nix_store_get_uri(nix_c_context * context, Store * store, nix_get_string
NIXC_CATCH_ERRS
}
nix_err
nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data)
{
if (context)
context->last_err_code = NIX_OK;
try {
return call_nix_get_string_callback(store->ptr->storeDir, callback, user_data);
}
NIXC_CATCH_ERRS
}
nix_err
nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data)
{
@ -89,6 +100,18 @@ bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath *
NIXC_CATCH_ERRS_RES(false);
}
nix_err nix_store_real_path(
nix_c_context * context, Store * store, StorePath * path, nix_get_string_callback callback, void * user_data)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto res = store->ptr->toRealPath(path->path);
return call_nix_get_string_callback(res, callback, user_data);
}
NIXC_CATCH_ERRS
}
StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const char * path)
{
if (context)

View file

@ -48,12 +48,27 @@ nix_err nix_libstore_init_no_load_config(nix_c_context * context);
* Store instances may share state and resources behind the scenes.
*
* @param[out] context Optional, stores error information
* @param[in] uri URI of the Nix store, copied. See [*Store URL format* in the Nix Reference
*
* @param[in] uri @parblock
* URI of the Nix store, copied.
*
* If `NULL`, the store from the settings will be used.
* Note that `"auto"` holds a strange middle ground, reading part of the general environment, but not all of it. It
* ignores `NIX_REMOTE` and the `store` option. For this reason, `NULL` is most likely the better choice.
*
* For supported store URLs, see [*Store URL format* in the Nix Reference
* Manual](https://nixos.org/manual/nix/stable/store/types/#store-url-format).
* @param[in] params optional, null-terminated array of key-value pairs, e.g. {{"endpoint",
* "https://s3.local"}}. See [*Store Types* in the Nix Reference
* Manual](https://nixos.org/manual/nix/stable/store/types).
* @endparblock
*
* @param[in] params @parblock
* optional, null-terminated array of key-value pairs, e.g. {{"endpoint",
* "https://s3.local"}}.
*
* See [*Store Types* in the Nix Reference Manual](https://nixos.org/manual/nix/stable/store/types).
* @endparblock
*
* @return a Store pointer, NULL in case of errors
*
* @see nix_store_free
*/
Store * nix_store_open(nix_c_context * context, const char * uri, const char *** params);
@ -78,7 +93,18 @@ void nix_store_free(Store * store);
*/
nix_err nix_store_get_uri(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data);
// returns: owned StorePath*
/**
* @brief get the storeDir of a Nix store, typically `"/nix/store"`
* @param[out] context Optional, stores error information
* @param[in] store nix store reference
* @param[in] callback Called with the URI.
* @param[in] user_data optional, arbitrary data, passed to the callback when it's called.
* @see nix_get_string_callback
* @return error code, NIX_OK on success.
*/
nix_err
nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data);
/**
* @brief Parse a Nix store path into a StorePath
*
@ -123,6 +149,26 @@ void nix_store_path_free(StorePath * p);
* @return true or false, error info in context
*/
bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath * path);
/**
* @brief Get the physical location of a store path
*
* A store may reside at a different location than its `storeDir` suggests.
* This situation is called a relocated store.
* Relocated stores are used during NixOS installation, as well as in restricted computing environments that don't offer
* a writable `/nix/store`.
*
* Not all types of stores support this operation.
*
* @param[in] context Optional, stores error information
* @param[in] store nix store reference
* @param[in] path the path to get the real path from
* @param[in] callback called with the real path
* @param[in] user_data arbitrary data, passed to the callback when it's called.
*/
nix_err nix_store_real_path(
nix_c_context * context, Store * store, StorePath * path, nix_get_string_callback callback, void * user_data);
// nix_err nix_store_ensure(Store*, const char*);
// nix_err nix_store_build_paths(Store*);
/**

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