Compare commits
203 Commits
2.22.0
...
store-refe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7c841f704 | ||
|
|
4a19f4a866 | ||
|
|
859e55d1e8 | ||
|
|
dc7615dbbb | ||
|
|
d5fdfdc592 | ||
|
|
b3ebcc5aad | ||
|
|
b59a7a14c4 | ||
|
|
c036d75f9e | ||
|
|
1d6c2316a9 | ||
|
|
bd7a074636 | ||
|
|
5f7673c7ee | ||
|
|
77cb02b739 | ||
|
|
470c0501eb | ||
|
|
b462a92b15 | ||
|
|
3a7d62528d | ||
|
|
ec2a1e4ba7 | ||
|
|
ff3f1e62f0 | ||
|
|
117dbc2c46 | ||
|
|
142222030c | ||
|
|
56afe228df | ||
|
|
041fec0b5c | ||
|
|
7577597cc4 | ||
|
|
a57abbd143 | ||
|
|
8b369f90fd | ||
|
|
40b7fb4f11 | ||
|
|
fc14378ae3 | ||
|
|
8953bdbf32 | ||
|
|
c2d4c38d24 | ||
|
|
9a2f21711d | ||
|
|
20ed0c02b8 | ||
|
|
67db9e0c64 | ||
|
|
4c91bc543c | ||
|
|
1c75af969a | ||
|
|
e4be8abe42 | ||
|
|
43dc575fd7 | ||
|
|
d48bbda2e7 | ||
|
|
b7709d14a5 | ||
|
|
927034e7ac | ||
|
|
209d75529c | ||
|
|
e0bfa6c55f | ||
|
|
7cb3c80bb5 | ||
|
|
6193737ca1 | ||
|
|
53f0c44d6c | ||
|
|
a5de384cff | ||
|
|
beb3c2bc7a | ||
|
|
1ab107b0bf | ||
|
|
d25e54d56a | ||
|
|
bcfc722f81 | ||
|
|
05bc889b89 | ||
|
|
52a16b7e59 | ||
|
|
19720d733f | ||
|
|
979a019014 | ||
|
|
a2cb90caba | ||
|
|
c9e7239e22 | ||
|
|
c66796d460 | ||
|
|
ba2911b03b | ||
|
|
02d393d619 | ||
|
|
f63292462c | ||
|
|
359043ed0d | ||
|
|
449404531d | ||
|
|
303268bb71 | ||
|
|
d50ce2df14 | ||
|
|
043135a848 | ||
|
|
3026613893 | ||
|
|
50bbe22a51 | ||
|
|
39a269657e | ||
|
|
06e13465c5 | ||
|
|
bbe780b137 | ||
|
|
45c83cd430 | ||
|
|
6907eaad4f | ||
|
|
0c2c260180 | ||
|
|
7c7aa79ebe | ||
|
|
dcc2a51bac | ||
|
|
49bd408c10 | ||
|
|
05ad4e8806 | ||
|
|
2f0031aedc | ||
|
|
52200474e1 | ||
|
|
1da18e85ba | ||
|
|
d352c52111 | ||
|
|
9a58d90c73 | ||
|
|
39f7cbdc7c | ||
|
|
1623249745 | ||
|
|
e1e041ed8f | ||
|
|
7822ecbadf | ||
|
|
33ca905cdb | ||
|
|
39e8aad446 | ||
|
|
56abd341bb | ||
|
|
62e1ea2f4b | ||
|
|
4d0777ca69 | ||
|
|
d8559cad8d | ||
|
|
6bf7edb18b | ||
|
|
8b5e8f4fba | ||
|
|
c940d11fb0 | ||
|
|
ccf94545db | ||
|
|
d3b7367c80 | ||
|
|
4537663740 | ||
|
|
1db7d1b840 | ||
|
|
87ab3c0ea4 | ||
|
|
e0ff8da9d5 | ||
|
|
0998a3ac01 | ||
|
|
cb7224a8c2 | ||
|
|
6df07f3e81 | ||
|
|
9951e14ae0 | ||
|
|
de8c3c034c | ||
|
|
b5605217ae | ||
|
|
77a406a5a6 | ||
|
|
79c7d6205c | ||
|
|
d8d20307a8 | ||
|
|
081faeda8c | ||
|
|
a5252c9979 | ||
|
|
0930058189 | ||
|
|
ddea4c6deb | ||
|
|
52ccaf7971 | ||
|
|
89f500b554 | ||
|
|
f83617f052 | ||
|
|
fcbc36cf78 | ||
|
|
9ae6455b0e | ||
|
|
72a0d4b022 | ||
|
|
a3c573950b | ||
|
|
9763eb2fcb | ||
|
|
d641e8f717 | ||
|
|
c371070580 | ||
|
|
b4950404ba | ||
|
|
da3381d51f | ||
|
|
c7216a416f | ||
|
|
1ad7b5451d | ||
|
|
36150e6fce | ||
|
|
b7eb26e362 | ||
|
|
5e189025ca | ||
|
|
ef28c7329c | ||
|
|
eab2919119 | ||
|
|
cbafa1ba2d | ||
|
|
0eababb5f7 | ||
|
|
038573279c | ||
|
|
020edac1ca | ||
|
|
2926ef0e90 | ||
|
|
79f03b794c | ||
|
|
9bd1191fcc | ||
|
|
709cd44d3e | ||
|
|
ea70878a76 | ||
|
|
27a02bc7d1 | ||
|
|
feb1d10f60 | ||
|
|
ee2fa87a7e | ||
|
|
20445dfeaf | ||
|
|
71c66de227 | ||
|
|
460d8fbaea | ||
|
|
ffc280f27a | ||
|
|
20558e0462 | ||
|
|
ba5929c7be | ||
|
|
00ca2b05b8 | ||
|
|
037c8d771d | ||
|
|
840267491e | ||
|
|
1948ec390c | ||
|
|
f34b52b521 | ||
|
|
e17aad23d6 | ||
|
|
5279e1f190 | ||
|
|
de634a54a1 | ||
|
|
1f41682217 | ||
|
|
f29a220b70 | ||
|
|
724132468a | ||
|
|
e18c3d4670 | ||
|
|
503be57bbd | ||
|
|
458441c637 | ||
|
|
4d99d07bc9 | ||
|
|
4161f3cfea | ||
|
|
e5f509ef0b | ||
|
|
2f678331d5 | ||
|
|
de51e5c335 | ||
|
|
84e0c464f1 | ||
|
|
4722b0c9e9 | ||
|
|
0353d6f79e | ||
|
|
28043fef69 | ||
|
|
1a2f88491f | ||
|
|
1ac635d600 | ||
|
|
fc1d9023a2 | ||
|
|
b406cf9b81 | ||
|
|
1c2336ff5f | ||
|
|
19cc50dcbf | ||
|
|
1c4e392c64 | ||
|
|
7e104840a9 | ||
|
|
a92eb5fc33 | ||
|
|
943a877a6a | ||
|
|
c73172e986 | ||
|
|
4ff7f5aa9c | ||
|
|
5747d244ed | ||
|
|
e3a4e40a35 | ||
|
|
26384a3187 | ||
|
|
a60a1f09b2 | ||
|
|
750bcaa330 | ||
|
|
6acf02b32a | ||
|
|
8d70db3251 | ||
|
|
ff76dd2211 | ||
|
|
ccad6e94e2 | ||
|
|
9d7dee4a8f | ||
|
|
5cc4af5231 | ||
|
|
b973cd494f | ||
|
|
3a3c205fa7 | ||
|
|
0fade05e96 | ||
|
|
dd19cce9c4 | ||
|
|
cceae30aaf | ||
|
|
aad11f4496 | ||
|
|
d084c1cb41 | ||
|
|
eff90af498 |
@@ -15,7 +15,7 @@ SpaceAfterCStyleCast: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignEscapedNewlines: Left
|
||||
ColumnLimit: 120
|
||||
BreakStringLiterals: false
|
||||
BitFieldColonSpacing: None
|
||||
@@ -30,3 +30,5 @@ BreakBeforeBinaryOperators: NonAssignment
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
IndentPPDirectives: AfterHash
|
||||
PPIndentWidth: 2
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
|
||||
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -13,7 +13,7 @@
|
||||
|
||||
"documentation":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "doc/manual/*"
|
||||
- any-glob-to-any-file: "doc/manual/**/*"
|
||||
- any-glob-to-any-file: "src/nix/**/*.md"
|
||||
|
||||
"store":
|
||||
@@ -40,4 +40,4 @@
|
||||
- any-glob-to-any-file: "src/*/tests/**/*"
|
||||
# Functional and integration tests
|
||||
- any-glob-to-any-file: "tests/functional/**/*"
|
||||
|
||||
|
||||
|
||||
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
@@ -20,12 +20,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v26
|
||||
- uses: cachix/install-nix-action@V27
|
||||
with:
|
||||
# The sandbox would otherwise be disabled by default on Darwin
|
||||
extra_nix_config: "sandbox = true"
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v14
|
||||
- uses: cachix/cachix-action@v15
|
||||
if: needs.check_secrets.outputs.cachix == 'true'
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
@@ -62,10 +62,10 @@ jobs:
|
||||
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@v26
|
||||
- uses: cachix/install-nix-action@V27
|
||||
with:
|
||||
install_url: https://releases.nixos.org/nix/nix-2.20.3/install
|
||||
- uses: cachix/cachix-action@v14
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@v26
|
||||
- uses: cachix/install-nix-action@V27
|
||||
with:
|
||||
install_url: '${{needs.installer.outputs.installerURL}}'
|
||||
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
|
||||
@@ -114,12 +114,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v26
|
||||
- uses: cachix/install-nix-action@V27
|
||||
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
|
||||
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.version | tr -d \")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v14
|
||||
- uses: cachix/cachix-action@v15
|
||||
if: needs.check_secrets.outputs.cachix == 'true'
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
|
||||
42
CITATION.cff
Normal file
42
CITATION.cff
Normal file
@@ -0,0 +1,42 @@
|
||||
cff-version: 1.2.0
|
||||
title: Nix
|
||||
message: >-
|
||||
If you use this software, please cite it using the
|
||||
metadata from this file.
|
||||
type: software
|
||||
authors:
|
||||
- given-names: Eelco
|
||||
family-names: Dolstra
|
||||
email: edolstra@gmail.com
|
||||
- name: The Nix contributors
|
||||
website: 'https://github.com/NixOS/nix'
|
||||
references:
|
||||
- title: The Purely Functional Software Deployment Model
|
||||
authors:
|
||||
- family-names: Dolstra
|
||||
given-names: Eelco
|
||||
year: 2006
|
||||
type: thesis
|
||||
thesis-type: PhD thesis
|
||||
isbn: 90-393-4130-3
|
||||
url: https://dspace.library.uu.nl/handle/1874/7540
|
||||
database-provider: Utrecht University Repository
|
||||
institution:
|
||||
name: Utrecht University
|
||||
keywords:
|
||||
- configuration management
|
||||
- software deployment
|
||||
- purely functional
|
||||
- component-based software engineering
|
||||
repository-code: 'https://github.com/NixOS/nix'
|
||||
url: 'https://nixos.org/'
|
||||
abstract: >-
|
||||
Nix, a purely functional package manager, is a powerful
|
||||
package manager for Linux and other Unix systems that
|
||||
makes package management reliable and reproducible.
|
||||
keywords:
|
||||
- reproducibility
|
||||
- open-source
|
||||
- c++
|
||||
- functional
|
||||
license: LGPL-2.1
|
||||
@@ -27,6 +27,8 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy).
|
||||
1. Search for related issues that cover what you're going to work on.
|
||||
It could help to mention there that you will work on the issue.
|
||||
|
||||
We strongly recommend first-time contributors not to propose new features but rather fix tightly-scoped problems in order to build trust and a working relationship with maintainers.
|
||||
|
||||
Issues labeled [good first issue](https://github.com/NixOS/nix/labels/good%20first%20issue) should be relatively easy to fix and are likely to get merged quickly.
|
||||
Pull requests addressing issues labeled [idea approved](https://github.com/NixOS/nix/labels/idea%20approved) or [RFC](https://github.com/NixOS/nix/labels/RFC) are especially welcomed by maintainers and will receive prioritised review.
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -98,7 +98,7 @@ ifdef HOST_WINDOWS
|
||||
GLOBAL_LDFLAGS += -Wl,--export-all-symbols
|
||||
endif
|
||||
|
||||
GLOBAL_CXXFLAGS += -g -Wall -Wimplicit-fallthrough -include $(buildprefix)config.h -std=c++2a -I src
|
||||
GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -include $(buildprefix)config.h -std=c++2a -I src
|
||||
|
||||
# Include the main lib, causing rules to be defined
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
# Solaris-specific stuff.
|
||||
AC_STRUCT_DIRENT_D_TYPE
|
||||
case "$host_os" in
|
||||
solaris*)
|
||||
# Solaris requires -lsocket -lnsl for network functions
|
||||
@@ -314,7 +313,7 @@ case "$host_os" in
|
||||
]))
|
||||
if test "x$enable_seccomp_sandboxing" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp],
|
||||
[CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"])
|
||||
[CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS" CFLAGS="$LIBSECCOMP_CFLAGS $CFLAGS"])
|
||||
have_seccomp=1
|
||||
AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.])
|
||||
AC_COMPILE_IFELSE([
|
||||
|
||||
@@ -27,7 +27,7 @@ appreciated.
|
||||
The following examples, for simplicity, don't include error handling. See the
|
||||
[Handling errors](@ref errors) section for more information.
|
||||
|
||||
# Embedding the Nix Evaluator
|
||||
# Embedding the Nix Evaluator{#nix_evaluator_example}
|
||||
|
||||
In this example we programmatically start the Nix language evaluator with a
|
||||
dummy store (that has no store paths and cannot be written to), and evaluate the
|
||||
@@ -46,9 +46,9 @@ Nix expression `builtins.nixVersion`.
|
||||
// NOTE: This example lacks all error handling. Production code must check for
|
||||
// errors, as some return values will be undefined.
|
||||
|
||||
void my_get_string_cb(const char * start, unsigned int n, char ** user_data)
|
||||
void my_get_string_cb(const char * start, unsigned int n, void * user_data)
|
||||
{
|
||||
*user_data = strdup(start);
|
||||
*((char **) user_data) = strdup(start);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -63,7 +63,7 @@ int main()
|
||||
nix_value_force(NULL, state, value);
|
||||
|
||||
char * version;
|
||||
nix_get_string(NULL, value, my_get_string_cb, version);
|
||||
nix_get_string(NULL, value, my_get_string_cb, &version);
|
||||
printf("Nix version: %s\n", version);
|
||||
|
||||
free(version);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$(docdir)/external-api/html/index.html $(docdir)/external-api/latex: $(d)/doxygen.cfg
|
||||
$(docdir)/external-api/html/index.html $(docdir)/external-api/latex: $(d)/doxygen.cfg src/lib*-c/*.h
|
||||
mkdir -p $(docdir)/external-api
|
||||
{ cat $< ; echo "OUTPUT_DIRECTORY=$(docdir)/external-api" ; } | doxygen -
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$(docdir)/internal-api/html/index.html $(docdir)/internal-api/latex: $(d)/doxygen.cfg
|
||||
$(docdir)/internal-api/html/index.html $(docdir)/internal-api/latex: $(d)/doxygen.cfg src/**/*.hh
|
||||
mkdir -p $(docdir)/internal-api
|
||||
{ cat $< ; echo "OUTPUT_DIRECTORY=$(docdir)/internal-api" ; } | doxygen -
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ additional-css = ["custom.css"]
|
||||
additional-js = ["redirects.js"]
|
||||
edit-url-template = "https://github.com/NixOS/nix/tree/master/doc/manual/{path}"
|
||||
git-repository-url = "https://github.com/NixOS/nix"
|
||||
fold.enable = true
|
||||
fold.level = 1
|
||||
|
||||
[preprocessor.anchors]
|
||||
renderers = ["html"]
|
||||
|
||||
@@ -285,15 +285,15 @@ const redirects = {
|
||||
"ch-basic-package-mgmt": "package-management/basic-package-mgmt.html",
|
||||
"ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html",
|
||||
"sec-channels": "command-ref/nix-channel.html",
|
||||
"ssec-copy-closure": "package-management/copy-closure.html",
|
||||
"ssec-copy-closure": "command-ref/nix-copy-closure.html",
|
||||
"sec-garbage-collection": "package-management/garbage-collection.html",
|
||||
"ssec-gc-roots": "package-management/garbage-collector-roots.html",
|
||||
"chap-package-management": "package-management/index.html",
|
||||
"sec-profiles": "package-management/profiles.html",
|
||||
"ssec-s3-substituter": "package-management/s3-substituter.html",
|
||||
"ssec-s3-substituter-anonymous-reads": "package-management/s3-substituter.html#anonymous-reads-to-your-s3-compatible-binary-cache",
|
||||
"ssec-s3-substituter-authenticated-reads": "package-management/s3-substituter.html#authenticated-reads-to-your-s3-binary-cache",
|
||||
"ssec-s3-substituter-authenticated-writes": "package-management/s3-substituter.html#authenticated-writes-to-your-s3-compatible-binary-cache",
|
||||
"ssec-s3-substituter": "store/types/s3-substituter.html",
|
||||
"ssec-s3-substituter-anonymous-reads": "store/types/s3-substituter.html#anonymous-reads-to-your-s3-compatible-binary-cache",
|
||||
"ssec-s3-substituter-authenticated-reads": "store/types/s3-substituter.html#authenticated-reads-to-your-s3-binary-cache",
|
||||
"ssec-s3-substituter-authenticated-writes": "store/types/s3-substituter.html#authenticated-writes-to-your-s3-compatible-binary-cache",
|
||||
"sec-sharing-packages": "package-management/sharing-packages.html",
|
||||
"ssec-ssh-substituter": "package-management/ssh-substituter.html",
|
||||
"chap-quick-start": "quick-start.html",
|
||||
|
||||
6
doc/manual/rl-next/consistent-nix-build.md
Normal file
6
doc/manual/rl-next/consistent-nix-build.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
synopsis: Show all FOD errors with `nix build --keep-going`
|
||||
---
|
||||
|
||||
`nix build --keep-going` now behaves consistently with `nix-build --keep-going`. This means
|
||||
that if e.g. multiple FODs fail to build, all hash mismatches are displayed.
|
||||
12
doc/manual/rl-next/derivation-json-change.md
Normal file
12
doc/manual/rl-next/derivation-json-change.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
synopsis: Modify `nix derivation {add,show}` JSON format
|
||||
issues: 9866
|
||||
prs: 10722
|
||||
---
|
||||
|
||||
The JSON format for derivations has been slightly revised to better conform to our [JSON guidelines](@docroot@contributing/cli-guideline#returning-future-proof-json).
|
||||
In particular, the hash algorithm and content addressing method of content-addresed derivation outputs is now separated into two fields `hashAlgo` and `method`,
|
||||
rather than one field with an arcane `:`-separated format.
|
||||
|
||||
This JSON format is only used by the experimental `nix derivation` family of commands, at this time.
|
||||
Future revisions are expected as the JSON format is still not entirely in compliance even after these changes.
|
||||
28
doc/manual/rl-next/fix-silent-unknown-options
Normal file
28
doc/manual/rl-next/fix-silent-unknown-options
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
synopsis: Warn on unknown settings anywhere in the command line
|
||||
prs: 10701
|
||||
---
|
||||
|
||||
All `nix` commands will now properly warn when an unknown option is specified anywhere in the command line.
|
||||
|
||||
Before:
|
||||
|
||||
```console
|
||||
$ nix-instantiate --option foobar baz --expr '{}'
|
||||
warning: unknown setting 'foobar'
|
||||
$ nix-instantiate '{}' --option foobar baz --expr
|
||||
$ nix eval --expr '{}' --option foobar baz
|
||||
{ }
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```console
|
||||
$ nix-instantiate --option foobar baz --expr '{}'
|
||||
warning: unknown setting 'foobar'
|
||||
$ nix-instantiate '{}' --option foobar baz --expr
|
||||
warning: unknown setting 'foobar'
|
||||
$ nix eval --expr '{}' --option foobar baz
|
||||
warning: unknown setting 'foobar'
|
||||
{ }
|
||||
```
|
||||
@@ -18,7 +18,9 @@
|
||||
- [Uninstalling Nix](installation/uninstall.md)
|
||||
- [Nix Store](store/index.md)
|
||||
- [File System Object](store/file-system-object.md)
|
||||
- [Content-Addressing File System Objects](store/file-system-object/content-address.md)
|
||||
- [Store Object](store/store-object.md)
|
||||
- [Content-Addressing Store Objects](store/store-object/content-address.md)
|
||||
- [Store Path](store/store-path.md)
|
||||
- [Store Types](store/types/index.md)
|
||||
{{#include ./store/types/SUMMARY.md}}
|
||||
@@ -27,6 +29,7 @@
|
||||
- [Language Constructs](language/constructs.md)
|
||||
- [String interpolation](language/string-interpolation.md)
|
||||
- [Lookup path](language/constructs/lookup-path.md)
|
||||
- [String context](language/string-context.md)
|
||||
- [Operators](language/operators.md)
|
||||
- [Derivations](language/derivations.md)
|
||||
- [Advanced Attributes](language/advanced-attributes.md)
|
||||
@@ -40,9 +43,7 @@
|
||||
- [Advanced Topics](advanced-topics/index.md)
|
||||
- [Sharing Packages Between Machines](package-management/sharing-packages.md)
|
||||
- [Serving a Nix store via HTTP](package-management/binary-cache-substituter.md)
|
||||
- [Copying Closures via SSH](package-management/copy-closure.md)
|
||||
- [Serving a Nix store via SSH](package-management/ssh-substituter.md)
|
||||
- [Serving a Nix store via S3](package-management/s3-substituter.md)
|
||||
- [Remote Builds](advanced-topics/distributed-builds.md)
|
||||
- [Tuning Cores and Jobs](advanced-topics/cores-vs-jobs.md)
|
||||
- [Verifying Build Reproducibility](advanced-topics/diff-hook.md)
|
||||
@@ -112,6 +113,7 @@
|
||||
- [Store Path Specification](protocols/store-path.md)
|
||||
- [Nix Archive (NAR) Format](protocols/nix-archive.md)
|
||||
- [Derivation "ATerm" file format](protocols/derivation-aterm.md)
|
||||
- [C API](c-api.md)
|
||||
- [Glossary](glossary.md)
|
||||
- [Contributing](contributing/index.md)
|
||||
- [Hacking](contributing/hacking.md)
|
||||
|
||||
@@ -39,3 +39,5 @@
|
||||
/json/* /protocols/json/:splat 301!
|
||||
|
||||
/release-notes/release-notes /release-notes 301!
|
||||
|
||||
/package-management/copy-closure /command-ref/nix-copy-closure 301!
|
||||
|
||||
@@ -12,14 +12,14 @@ machine is accessible via SSH and that it has Nix installed. You can
|
||||
test whether connecting to the remote Nix instance works, e.g.
|
||||
|
||||
```console
|
||||
$ nix store info --store ssh://mac
|
||||
$ nix store ping --store ssh://mac
|
||||
```
|
||||
|
||||
will try to connect to the machine named `mac`. It is possible to
|
||||
specify an SSH identity file as part of the remote store URI, e.g.
|
||||
|
||||
```console
|
||||
$ nix store info --store ssh://mac?ssh-key=/home/alice/my-key
|
||||
$ nix store ping --store ssh://mac?ssh-key=/home/alice/my-key
|
||||
```
|
||||
|
||||
Since builds should be non-interactive, the key should not have a
|
||||
|
||||
16
doc/manual/src/c-api.md
Normal file
16
doc/manual/src/c-api.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# C API
|
||||
|
||||
Nix provides a C API with the intent of [_becoming_](https://github.com/NixOS/nix/milestone/52) a stable API, which it is currently not.
|
||||
It is in development.
|
||||
|
||||
See:
|
||||
- C API documentation for a recent build of master
|
||||
- [Getting Started]
|
||||
- [Index]
|
||||
- [Matrix Room *Nix Bindings*](https://matrix.to/#/#nix-bindings:nixos.org) for discussion and questions.
|
||||
- [Stabilisation Milestone](https://github.com/NixOS/nix/milestone/52)
|
||||
- [Other C API PRs and issues](https://github.com/NixOS/nix/labels/c%20api)
|
||||
- [Contributing C API Documentation](contributing/documentation.md#c-api-documentation), including how to build it locally.
|
||||
|
||||
[Getting Started]: https://hydra.nixos.org/job/nix/master/external-api-docs/latest/download-by-type/doc/external-api-docs
|
||||
[Index]: https://hydra.nixos.org/job/nix/master/external-api-docs/latest/download-by-type/doc/external-api-docs/globals.html
|
||||
@@ -66,5 +66,12 @@ Configuration options can be set on the command line, overriding the values set
|
||||
|
||||
The `extra-` prefix is supported for settings that take a list of items (e.g. `--extra-trusted users alice` or `--option extra-trusted-users alice`).
|
||||
|
||||
## Integer settings
|
||||
|
||||
Settings that have an integer type support the suffixes `K`, `M`, `G`
|
||||
and `T`. These cause the specified value to be multiplied by 2^10,
|
||||
2^20, 2^30 and 2^40, respectively. For instance, `--min-free 1M` is
|
||||
equivalent to `--min-free 1048576`.
|
||||
|
||||
# Available settings
|
||||
|
||||
|
||||
@@ -74,4 +74,4 @@ $ nix-collect-garbage -d
|
||||
```
|
||||
|
||||
[profiles]: @docroot@/command-ref/files/profiles.md
|
||||
[store objects]: @docroot@/glossary.md#gloss-store-object
|
||||
[store objects]: @docroot@/store/store-object.md
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
# Name
|
||||
|
||||
`nix-copy-closure` - copy a closure to or from a remote machine via SSH
|
||||
`nix-copy-closure` - copy store objects to or from a remote machine via SSH
|
||||
|
||||
# Synopsis
|
||||
|
||||
`nix-copy-closure`
|
||||
[`--to` | `--from`]
|
||||
[`--to` | `--from` ]
|
||||
[`--gzip`]
|
||||
[`--include-outputs`]
|
||||
[`--use-substitutes` | `-s`]
|
||||
[`-v`]
|
||||
_user@machine_ _paths_
|
||||
[_user_@]_machine_[:_port_] _paths_
|
||||
|
||||
# Description
|
||||
|
||||
`nix-copy-closure` gives you an easy and efficient way to exchange
|
||||
software between machines. Given one or more Nix store _paths_ on the
|
||||
local machine, `nix-copy-closure` computes the closure of those paths
|
||||
(i.e. all their dependencies in the Nix store), and copies all paths
|
||||
in the closure to the remote machine via the `ssh` (Secure Shell)
|
||||
command. With the `--from` option, the direction is reversed: the
|
||||
closure of _paths_ on a remote machine is copied to the Nix store on
|
||||
the local machine.
|
||||
Given _paths_ from one machine, `nix-copy-closure` computes the [closure](@docroot@/glossary.md#gloss-closure) of those paths (i.e. all their dependencies in the Nix store), and copies [store objects](@docroot@/glossary.md#gloss-store-object) in that closure to another machine via SSH.
|
||||
It doesn’t copy store objects that are already present on the other machine.
|
||||
|
||||
This command is efficient because it only sends the store paths
|
||||
that are missing on the target machine.
|
||||
> **Note**
|
||||
>
|
||||
> While the Nix store to use on the local machine can be specified on the command line with the [`--store`](@docroot@/command-ref/conf-file.md#conf-store) option, the Nix store to be accessed on the remote machine can only be [configured statically](@docroot@/command-ref/conf-file.md#configuration-file) on that remote machine.
|
||||
|
||||
Since `nix-copy-closure` calls `ssh`, you may be asked to type in the
|
||||
appropriate password or passphrase. In fact, you may be asked _twice_
|
||||
because `nix-copy-closure` currently connects twice to the remote
|
||||
machine, first to get the set of paths missing on the target machine,
|
||||
and second to send the dump of those paths. When using public key
|
||||
authentication, you can avoid typing the passphrase with `ssh-agent`.
|
||||
Since `nix-copy-closure` calls `ssh`, you may need to authenticate with the remote machine.
|
||||
In fact, you may be asked for authentication _twice_ because `nix-copy-closure` currently connects twice to the remote machine: first to get the set of paths missing on the target machine, and second to send the dump of those paths.
|
||||
When using public key authentication, you can avoid typing the passphrase with `ssh-agent`.
|
||||
|
||||
# Options
|
||||
|
||||
- `--to`\
|
||||
Copy the closure of _paths_ from the local Nix store to the Nix
|
||||
store on _machine_. This is the default.
|
||||
- `--to`
|
||||
|
||||
- `--from`\
|
||||
Copy the closure of _paths_ from the Nix store on _machine_ to the
|
||||
local Nix store.
|
||||
Copy the closure of _paths_ from a Nix store accessible from the local machine to the Nix store on the remote _machine_.
|
||||
This is the default behavior.
|
||||
|
||||
- `--from`
|
||||
|
||||
Copy the closure of _paths_ from the Nix store on the remote _machine_ to the local machine's specified Nix store.
|
||||
|
||||
- `--gzip`
|
||||
|
||||
- `--gzip`\
|
||||
Enable compression of the SSH connection.
|
||||
|
||||
- `--include-outputs`\
|
||||
- `--include-outputs`
|
||||
|
||||
Also copy the outputs of [store derivation]s included in the closure.
|
||||
|
||||
[store derivation]: @docroot@/glossary.md#gloss-store-derivation
|
||||
|
||||
- `--use-substitutes` / `-s`\
|
||||
Attempt to download missing paths on the target machine using Nix’s
|
||||
substitute mechanism. Any paths that cannot be substituted on the
|
||||
target are still copied normally from the source. This is useful,
|
||||
for instance, if the connection between the source and target
|
||||
machine is slow, but the connection between the target machine and
|
||||
`nixos.org` (the default binary cache server) is
|
||||
fast.
|
||||
- `--use-substitutes` / `-s`
|
||||
|
||||
- `-v`\
|
||||
Show verbose output.
|
||||
Attempt to download missing store objects on the target from [substituters](@docroot@/command-ref/conf-file.md#conf-substituters).
|
||||
Any store objects that cannot be substituted on the target are still copied normally from the source.
|
||||
This is useful, for instance, if the connection between the source and target machine is slow, but the connection between the target machine and `cache.nixos.org` (the default binary cache server) is fast.
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
# Environment variables
|
||||
|
||||
- `NIX_SSHOPTS`\
|
||||
Additional options to be passed to `ssh` on the command
|
||||
line.
|
||||
- `NIX_SSHOPTS`
|
||||
|
||||
Additional options to be passed to `ssh` on the command line.
|
||||
|
||||
{{#include ./env-common.md}}
|
||||
|
||||
# Examples
|
||||
|
||||
Copy Firefox with all its dependencies to a remote machine:
|
||||
> **Example**
|
||||
>
|
||||
> Copy GNU Hello with all its dependencies to a remote machine:
|
||||
>
|
||||
> ```shell-session
|
||||
> $ storePath="$(nix-build '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable -A hello --no-out-link)"
|
||||
> $ nix-copy-closure --to alice@itchy.example.org "$storePath"
|
||||
> copying 5 paths...
|
||||
> copying path '/nix/store/nrwkk6ak3rgkrxbqhsscb01jpzmslf2r-xgcc-13.2.0-libgcc' to 'ssh://alice@itchy.example.org'...
|
||||
> copying path '/nix/store/gm61h1y42pqyl6178g90x8zm22n6pyy5-libunistring-1.1' to 'ssh://alice@itchy.example.org'...
|
||||
> copying path '/nix/store/ddfzjdykw67s20c35i7a6624by3iz5jv-libidn2-2.3.7' to 'ssh://alice@itchy.example.org'...
|
||||
> copying path '/nix/store/apab5i73dqa09wx0q27b6fbhd1r18ihl-glibc-2.39-31' to 'ssh://alice@itchy.example.org'...
|
||||
> copying path '/nix/store/g1n2vryg06amvcc1avb2mcq36faly0mh-hello-2.12.1' to 'ssh://alice@itchy.example.org'...
|
||||
> ```
|
||||
|
||||
```console
|
||||
$ nix-copy-closure --to alice@itchy.labs $(type -tP firefox)
|
||||
```
|
||||
|
||||
Copy Subversion from a remote machine and then install it into a user
|
||||
environment:
|
||||
|
||||
```console
|
||||
$ nix-copy-closure --from alice@itchy.labs \
|
||||
/nix/store/0dj0503hjxy5mbwlafv1rsbdiyx1gkdy-subversion-1.4.4
|
||||
$ nix-env --install /nix/store/0dj0503hjxy5mbwlafv1rsbdiyx1gkdy-subversion-1.4.4
|
||||
```
|
||||
> **Example**
|
||||
>
|
||||
> Copy GNU Hello from a remote machine using a known store path, and run it:
|
||||
>
|
||||
> ```shell-session
|
||||
> $ storePath="$(nix-instantiate --eval '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable -A hello.outPath | tr -d '"')"
|
||||
> $ nix-copy-closure --from alice@itchy.example.org "$storePath"
|
||||
> $ "$storePath"/bin/hello
|
||||
> Hello, world!
|
||||
> ```
|
||||
|
||||
@@ -47,39 +47,83 @@ These pages can be viewed offline:
|
||||
|
||||
Example: `nix-env --help --install`
|
||||
|
||||
# Package sources
|
||||
|
||||
`nix-env` can obtain packages from multiple sources:
|
||||
|
||||
- An attribute set of derivations from:
|
||||
- The [default Nix expression](@docroot@/command-ref/files/default-nix-expression.md) (by default)
|
||||
- A Nix file, specified via `--file`
|
||||
- A [profile](@docroot@/command-ref/files/profiles.md), specified via `--from-profile`
|
||||
- A Nix expression that is a function which takes default expression as argument, specified via `--from-expression`
|
||||
- A [store path](@docroot@/store/store-path.md)
|
||||
|
||||
# Selectors
|
||||
|
||||
Several commands, such as `nix-env --query ` and `nix-env --install `, take a list of
|
||||
arguments that specify the packages on which to operate. These are
|
||||
extended regular expressions that must match the entire name of the
|
||||
package. (For details on regular expressions, see **regex**(7).) The match is
|
||||
case-sensitive. The regular expression can optionally be followed by a
|
||||
dash and a version number; if omitted, any version of the package will
|
||||
match. Here are some examples:
|
||||
Several operations, such as [`nix-env --query`](./nix-env/query.md) and [`nix-env --install`](./nix-env/install.md), take a list of *arguments* that specify the packages on which to operate.
|
||||
|
||||
- `firefox`\
|
||||
Matches the package name `firefox` and any version.
|
||||
Packages are identified based on a `name` part and a `version` part of a [symbolic derivation name](@docroot@/language/derivations.md#attr-names):
|
||||
|
||||
- `firefox-32.0`\
|
||||
Matches the package name `firefox` and version `32.0`.
|
||||
- `name`: Everything up to but not including the first dash (`-`) that is *not* followed by a letter.
|
||||
- `version`: The rest, excluding the separating dash.
|
||||
|
||||
- `gtk\\+`\
|
||||
Matches the package name `gtk+`. The `+` character must be escaped
|
||||
using a backslash to prevent it from being interpreted as a
|
||||
quantifier, and the backslash must be escaped in turn with another
|
||||
backslash to ensure that the shell passes it on.
|
||||
> **Example**
|
||||
>
|
||||
> `nix-env` parses the symbolic derivation name `apache-httpd-2.0.48` as:
|
||||
>
|
||||
> ```json
|
||||
> {
|
||||
> "name": "apache-httpd",
|
||||
> "version": "2.0.48"
|
||||
> }
|
||||
> ```
|
||||
|
||||
- `.\*`\
|
||||
Matches any package name. This is the default for most commands.
|
||||
> **Example**
|
||||
>
|
||||
> `nix-env` parses the symbolic derivation name `firefox.*` as:
|
||||
>
|
||||
> ```json
|
||||
> {
|
||||
> "name": "firefox.*",
|
||||
> "version": ""
|
||||
> }
|
||||
> ```
|
||||
|
||||
- `'.*zip.*'`\
|
||||
Matches any package name containing the string `zip`. Note the dots:
|
||||
`'*zip*'` does not work, because in a regular expression, the
|
||||
character `*` is interpreted as a quantifier.
|
||||
The `name` parts of the *arguments* to `nix-env` are treated as extended regular expressions and matched against the `name` parts of derivation names in the package source.
|
||||
The match is case-sensitive.
|
||||
The regular expression can optionally be followed by a dash (`-`) and a version number; if omitted, any version of the package will match.
|
||||
For details on regular expressions, see [**regex**(7)](https://linux.die.net/man/7/regex).
|
||||
|
||||
- `'.*(firefox|chromium).*'`\
|
||||
Matches any package name containing the strings `firefox` or
|
||||
`chromium`.
|
||||
> **Example**
|
||||
>
|
||||
> Common patterns for finding package names with `nix-env`:
|
||||
>
|
||||
> - `firefox`
|
||||
>
|
||||
> Matches the package name `firefox` and any version.
|
||||
>
|
||||
> - `firefox-32.0`
|
||||
>
|
||||
> Matches the package name `firefox` and version `32.0`.
|
||||
>
|
||||
> - `gtk\\+`
|
||||
>
|
||||
> Matches the package name `gtk+`.
|
||||
> The `+` character must be escaped using a backslash (`\`) to prevent it from being interpreted as a quantifier, and the backslash must be escaped in turn with another backslash to ensure that the shell passes it on.
|
||||
>
|
||||
> - `.\*`
|
||||
>
|
||||
> Matches any package name.
|
||||
> This is the default for most commands.
|
||||
>
|
||||
> - `'.*zip.*'`
|
||||
>
|
||||
> Matches any package name containing the string `zip`.
|
||||
> Note the dots: `'*zip*'` does not work, because in a regular expression, the character `*` is interpreted as a quantifier.
|
||||
>
|
||||
> - `'.*(firefox|chromium).*'`
|
||||
>
|
||||
> Matches any package name containing the strings `firefox` or `chromium`.
|
||||
|
||||
# Files
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ Periodically deleting old generations is important to make garbage collection
|
||||
effective.
|
||||
The is because profiles are also garbage collection roots — any [store object] reachable from a profile is "alive" and ineligible for deletion.
|
||||
|
||||
[store object]: @docroot@/glossary.md#gloss-store-object
|
||||
[store object]: @docroot@/store/store-object.md
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
|
||||
# Description
|
||||
|
||||
The install operation creates a new user environment.
|
||||
The `--install` operation creates a new user environment.
|
||||
It is based on the current generation of the active [profile](@docroot@/command-ref/files/profiles.md), to which a set of [store paths] described by *args* is added.
|
||||
|
||||
[store paths]: @docroot@/glossary.md#gloss-store-path
|
||||
[store paths]: @docroot@/store/store-path.md
|
||||
|
||||
The arguments *args* map to store paths in a number of possible ways:
|
||||
|
||||
|
||||
- By default, *args* is a set of [derivation] names denoting derivations in the [default Nix expression].
|
||||
These are [realised], and the resulting output paths are installed.
|
||||
Currently installed derivations with a name equal to the name of a derivation being added are removed unless the option `--preserve-installed` is specified.
|
||||
@@ -50,7 +49,7 @@ The arguments *args* map to store paths in a number of possible ways:
|
||||
Show the attribute paths of available packages with [`nix-env --query`](./query.md):
|
||||
|
||||
```console
|
||||
nix-env --query --available --attr-path`
|
||||
nix-env --query --available --attr-path
|
||||
```
|
||||
|
||||
- If `--from-profile` *path* is given, *args* is a set of names
|
||||
|
||||
@@ -20,16 +20,21 @@ an example.
|
||||
The hash is computed over a *serialisation* of each path: a dump of
|
||||
the file system tree rooted at the path. This allows directories and
|
||||
symlinks to be hashed as well as regular files. The dump is in the
|
||||
*NAR format* produced by [`nix-store
|
||||
*[Nix Archive (NAR)][Nix Archive] format* produced by [`nix-store
|
||||
--dump`](@docroot@/command-ref/nix-store/dump.md). Thus, `nix-hash path`
|
||||
yields the same cryptographic hash as `nix-store --dump path |
|
||||
md5sum`.
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
# Options
|
||||
|
||||
- `--flat`\
|
||||
Print the cryptographic hash of the contents of each regular file
|
||||
*path*. That is, do not compute the hash over the dump of *path*.
|
||||
Print the cryptographic hash of the contents of each regular file *path*.
|
||||
That is, instead of computing
|
||||
the hash of the [Nix Archive (NAR)](@docroot@/store/file-system-object/content-address.md#serial-nix-archive) of *path*,
|
||||
just [directly hash]((@docroot@/store/file-system-object/content-address.md#serial-flat) *path* as is.
|
||||
This requires *path* to resolve to a regular file rather than directory.
|
||||
The result is identical to that produced by the GNU commands
|
||||
`md5sum` and `sha1sum`.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Name
|
||||
|
||||
`nix-store --dump` - write a single path to a Nix Archive
|
||||
`nix-store --dump` - write a single path to a [Nix Archive]
|
||||
|
||||
## Synopsis
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
## Description
|
||||
|
||||
The operation `--dump` produces a NAR (Nix ARchive) file containing the
|
||||
The operation `--dump` produces a [Nix archive](@docroot@/glossary.md#gloss-nar) (NAR) file containing the
|
||||
contents of the file system tree rooted at *path*. The archive is
|
||||
written to standard output.
|
||||
|
||||
@@ -30,8 +30,9 @@ NAR archives support filenames of unlimited length and 64-bit file
|
||||
sizes. They can contain regular files, directories, and symbolic links,
|
||||
but not other types of files (such as device nodes).
|
||||
|
||||
A Nix archive can be unpacked using `nix-store
|
||||
--restore`.
|
||||
A Nix archive can be unpacked using [`nix-store --restore`](@docroot@/command-ref/nix-store/restore.md).
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Name
|
||||
|
||||
`nix-store --export` - export store paths to a Nix Archive
|
||||
`nix-store --export` - export store paths to a [Nix Archive]
|
||||
|
||||
## Synopsis
|
||||
|
||||
@@ -8,16 +8,22 @@
|
||||
|
||||
## Description
|
||||
|
||||
The operation `--export` writes a serialisation of the specified store
|
||||
paths to standard output in a format that can be imported into another
|
||||
Nix store with `nix-store --import`. This is like `nix-store
|
||||
--dump`, except that the NAR archive produced by that command doesn’t
|
||||
contain the necessary meta-information to allow it to be imported into
|
||||
another Nix store (namely, the set of references of the path).
|
||||
The operation `--export` writes a serialisation of the given [store objects](@docroot@/glossary.md#gloss-store-object) to standard output in a format that can be imported into another [Nix store](@docroot@/store/index.md) with [`nix-store --import`](./import.md).
|
||||
|
||||
This command does not produce a *closure* of the specified paths, so if
|
||||
a store path references other store paths that are missing in the target
|
||||
Nix store, the import will fail.
|
||||
> **Warning**
|
||||
>
|
||||
> This command *does not* produce a [closure](@docroot@/glossary.md#gloss-closure) of the specified store paths.
|
||||
> Trying to import a store object that refers to store paths not available in the target Nix store will fail.
|
||||
>
|
||||
> Use [`nix-store --query`](@docroot@/command-ref/nix-store/query.md) to obtain the closure of a store path.
|
||||
|
||||
This command is different from [`nix-store --dump`](./dump.md), which produces a [Nix archive](@docroot@/glossary.md#gloss-nar) that *does not* contain the set of [references](@docroot@/glossary.md#gloss-reference) of a given store path.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> For efficient transfer of closures to remote machines over SSH, use [`nix-copy-closure`](@docroot@/command-ref/nix-copy-closure.md).
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
@@ -27,15 +33,21 @@ Nix store, the import will fail.
|
||||
|
||||
# Examples
|
||||
|
||||
To copy a whole closure, do something
|
||||
like:
|
||||
|
||||
```console
|
||||
$ nix-store --export $(nix-store --query --requisites paths) > out
|
||||
```
|
||||
|
||||
To import the whole closure again, run:
|
||||
|
||||
```console
|
||||
$ nix-store --import < out
|
||||
```
|
||||
> **Example**
|
||||
>
|
||||
> Deploy GNU Hello to an airgapped machine via USB stick.
|
||||
>
|
||||
> Write the closure to the block device on a machine with internet connection:
|
||||
>
|
||||
> ```shell-session
|
||||
> [alice@itchy]$ storePath=$(nix-build '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable -A hello --no-out-link)
|
||||
> [alice@itchy]$ nix-store --export $(nix-store --query --requisites $storePath) | sudo dd of=/dev/usb
|
||||
> ```
|
||||
>
|
||||
> Read the closure from the block device on the machine without internet connection:
|
||||
>
|
||||
> ```shell-session
|
||||
> [bob@scratchy]$ hello=$(sudo dd if=/dev/usb | nix-store --import | tail -1)
|
||||
> [bob@scratchy]$ $hello/bin/hello
|
||||
> Hello, world!
|
||||
> ```
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Name
|
||||
|
||||
`nix-store --import` - import Nix Archive into the store
|
||||
`nix-store --import` - import [Nix Archive] into the store
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
# Synopsis
|
||||
|
||||
@@ -8,14 +10,34 @@
|
||||
|
||||
# Description
|
||||
|
||||
The operation `--import` reads a serialisation of a set of store paths
|
||||
produced by `nix-store --export` from standard input and adds those
|
||||
store paths to the Nix store. Paths that already exist in the Nix store
|
||||
are ignored. If a path refers to another path that doesn’t exist in the
|
||||
Nix store, the import fails.
|
||||
The operation `--import` reads a serialisation of a set of [store objects](@docroot@/glossary.md#gloss-store-object) produced by [`nix-store --export`](./export.md) from standard input, and adds those store objects to the specified [Nix store](@docroot@/store/index.md).
|
||||
Paths that already exist in the target Nix store are ignored.
|
||||
If a path [refers](@docroot@/glossary.md#gloss-reference) to another path that doesn’t exist in the target Nix store, the import fails.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> For efficient transfer of closures to remote machines over SSH, use [`nix-copy-closure`](@docroot@/command-ref/nix-copy-closure.md).
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
{{#include ../opt-common.md}}
|
||||
|
||||
{{#include ../env-common.md}}
|
||||
|
||||
# Examples
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> Given a closure of GNU Hello as a file:
|
||||
>
|
||||
> ```shell-session
|
||||
> $ storePath="$(nix-build '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable -A hello --no-out-link)"
|
||||
> $ nix-store --export $(nix-store --query --requisites $storePath) > hello.closure
|
||||
> ```
|
||||
>
|
||||
> Import the closure into a [remote SSH store](@docroot@/store/types/ssh-store.md) using the [`--store`](@docroot@/command-ref/conf-file.md#conf-store) option:
|
||||
>
|
||||
> ```console
|
||||
> $ nix-store --import --store ssh://alice@itchy.example.org < hello.closure
|
||||
> ```
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ The operation `--optimise` reduces Nix store disk space usage by finding
|
||||
identical files in the store and hard-linking them to each other. It
|
||||
typically reduces the size of the store by something like 25-35%. Only
|
||||
regular files and symlinks are hard-linked in this manner. Files are
|
||||
considered identical when they have the same NAR archive serialisation:
|
||||
considered identical when they have the same [Nix Archive (NAR)][Nix Archive] serialisation:
|
||||
that is, regular files must have the same contents and permission
|
||||
(executable or non-executable), and symlinks must have the same
|
||||
contents.
|
||||
@@ -38,3 +38,4 @@ hashing files in `/nix/store/qhqx7l2f1kmwihc9bnxs7rc159hsxnf3-gcc-4.1.1'
|
||||
there are 114486 files with equal contents out of 215894 files in total
|
||||
```
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
@@ -25,11 +25,11 @@ Each of *paths* is processed as follows:
|
||||
|
||||
If no substitutes are available and no store derivation is given, realisation fails.
|
||||
|
||||
[store paths]: @docroot@/glossary.md#gloss-store-path
|
||||
[store paths]: @docroot@/store/store-path.md
|
||||
[valid]: @docroot@/glossary.md#gloss-validity
|
||||
[store derivation]: @docroot@/glossary.md#gloss-store-derivation
|
||||
[output paths]: @docroot@/glossary.md#gloss-output-path
|
||||
[store objects]: @docroot@/glossary.md#gloss-store-object
|
||||
[store objects]: @docroot@/store/store-object.md
|
||||
[closure]: @docroot@/glossary.md#gloss-closure
|
||||
[substituters]: @docroot@/command-ref/conf-file.md#conf-substituters
|
||||
[content-addressed derivations]: @docroot@/contributing/experimental-features.md#xp-feature-ca-derivations
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
## Description
|
||||
|
||||
The operation `--restore` unpacks a NAR archive to *path*, which must
|
||||
The operation `--restore` unpacks a [Nix Archive (NAR)][Nix Archive] to *path*, which must
|
||||
not already exist. The archive is read from standard input.
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
{{#include ../opt-common.md}}
|
||||
|
||||
@@ -147,7 +147,7 @@ Please observe these guidelines to ease reviews:
|
||||
```
|
||||
A [store object] contains a [file system object] and [references] to other store objects.
|
||||
|
||||
[store object]: @docroot@/glossary.md#gloss-store-object
|
||||
[store object]: @docroot@/store/store-object.md
|
||||
[file system object]: @docroot@/architecture/file-system-object.md
|
||||
[references]: @docroot@/glossary.md#gloss-reference
|
||||
```
|
||||
@@ -207,8 +207,9 @@ or inside `nix-shell` or `nix develop`:
|
||||
# xdg-open ./outputs/doc/share/doc/nix/internal-api/html/index.html
|
||||
```
|
||||
|
||||
## C API documentation (experimental)
|
||||
## C API documentation
|
||||
|
||||
Note that the C API is not yet stable.
|
||||
[C API documentation] is available online.
|
||||
You can also build and view it yourself:
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks.
|
||||
> ```
|
||||
|
||||
The tests for each Nix library (`libnixexpr`, `libnixstore`, etc..) live inside a directory `tests/unit/${library_name_without-nix}`.
|
||||
Given a interface (header) and implementation pair in the original library, say, `src/libexpr/value/context.{hh,cc}`, we write tests for it in `tests/unit/libexpr/tests/value/context.cc`, and (possibly) declare/define additional interfaces for testing purposes in `tests/unit/libexpr-support/tests/value/context.{hh,cc}`.
|
||||
Given an interface (header) and implementation pair in the original library, say, `src/libexpr/value/context.{hh,cc}`, we write tests for it in `tests/unit/libexpr/tests/value/context.cc`, and (possibly) declare/define additional interfaces for testing purposes in `tests/unit/libexpr-support/tests/value/context.{hh,cc}`.
|
||||
|
||||
Data for unit tests is stored in a `data` subdir of the directory for each unit test executable.
|
||||
For example, `libnixstore` code is in `src/libstore`, and its test data is in `tests/unit/libstore/data`.
|
||||
@@ -162,14 +162,14 @@ ran test tests/functional/${testName}.sh... [PASS]
|
||||
or without `make`:
|
||||
|
||||
```shell-session
|
||||
$ ./mk/run-test.sh tests/functional/${testName}.sh tests/functional/init.sh
|
||||
$ ./mk/run-test.sh tests/functional/${testName}.sh
|
||||
ran test tests/functional/${testName}.sh... [PASS]
|
||||
```
|
||||
|
||||
To see the complete output, one can also run:
|
||||
|
||||
```shell-session
|
||||
$ ./mk/debug-test.sh tests/functional/${testName}.sh tests/functional/init.sh
|
||||
$ ./mk/debug-test.sh tests/functional/${testName}.sh
|
||||
+(${testName}.sh:1) foo
|
||||
output from foo
|
||||
+(${testName}.sh:2) bar
|
||||
@@ -204,7 +204,7 @@ edit it like so:
|
||||
Then, running the test with `./mk/debug-test.sh` will drop you into GDB once the script reaches that point:
|
||||
|
||||
```shell-session
|
||||
$ ./mk/debug-test.sh tests/functional/${testName}.sh tests/functional/init.sh
|
||||
$ ./mk/debug-test.sh tests/functional/${testName}.sh
|
||||
...
|
||||
+ gdb blash blub
|
||||
GNU gdb (GDB) 12.1
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Glossary
|
||||
|
||||
- [content address]{#gloss-content-address}
|
||||
|
||||
A
|
||||
[*content address*](https://en.wikipedia.org/wiki/Content-addressable_storage)
|
||||
is a secure way to reference immutable data.
|
||||
The reference is calculated directly from the content of the data being referenced, which means the reference is
|
||||
[*tamper proof*](https://en.wikipedia.org/wiki/Tamperproofing)
|
||||
--- variations of the data should always calculate to distinct content addresses.
|
||||
|
||||
For how Nix uses content addresses, see:
|
||||
|
||||
- [Content-Addressing File System Objects](@docroot@/store/file-system-object/content-address.md)
|
||||
- [content-addressed store object](#gloss-content-addressed-store-object)
|
||||
- [content-addressed derivation](#gloss-content-addressed-derivation)
|
||||
|
||||
Software Heritage's writing on [*Intrinsic and Extrinsic identifiers*](https://www.softwareheritage.org/2020/07/09/intrinsic-vs-extrinsic-identifiers) is also a good introduction to the value of content-addressing over other referencing schemes.
|
||||
|
||||
Besides content addressing, the Nix store also uses [input addressing](#gloss-input-addressed-store-object).
|
||||
|
||||
- [derivation]{#gloss-derivation}
|
||||
|
||||
A description of a build task. The result of a derivation is a
|
||||
@@ -218,6 +237,17 @@
|
||||
- [output closure]{#gloss-output-closure}\
|
||||
The [closure] of an [output path]. It only contains what is [reachable] from the output.
|
||||
|
||||
- [deriving path]{#gloss-deriving-path}
|
||||
|
||||
Deriving paths are a way to refer to [store objects][store object] that ar not yet [realised][realise].
|
||||
This is necessary because, in general and particularly for [content-addressed derivations][content-addressed derivation], the [output path] of an [output] is not known in advance.
|
||||
There are two forms:
|
||||
|
||||
- *constant*: just a [store path]
|
||||
It can be made [valid][validity] by copying it into the store: from the evaluator, command line interface or another store.
|
||||
|
||||
- *output*: a pair of a [store path] to a [derivation] and an [output] name.
|
||||
|
||||
- [deriver]{#gloss-deriver}
|
||||
|
||||
The [store derivation] that produced an [output path].
|
||||
@@ -255,13 +285,15 @@
|
||||
|
||||
See [installables](./command-ref/new-cli/nix.md#installables) for [`nix` commands](./command-ref/new-cli/nix.md) (experimental) for details.
|
||||
|
||||
- [NAR]{#gloss-nar}
|
||||
- [Nix Archive (NAR)]{#gloss-nar}
|
||||
|
||||
A *N*ix *AR*chive. This is a serialisation of a path in the Nix
|
||||
store. It can contain regular files, directories and symbolic
|
||||
links. NARs are generated and unpacked using `nix-store --dump`
|
||||
and `nix-store --restore`.
|
||||
|
||||
See [Nix Archive](store/file-system-object/content-address.html#serial-nix-archive) for details.
|
||||
|
||||
- [`∅`]{#gloss-emtpy-set}
|
||||
|
||||
The empty set symbol. In the context of profile history, this denotes a package is not present in a particular version of the profile.
|
||||
|
||||
@@ -53,7 +53,8 @@ ssl-cert-file = /etc/ssl/my-certificate-bundle.crt
|
||||
|
||||
The Nix installer has special handling for these proxy-related
|
||||
environment variables: `http_proxy`, `https_proxy`, `ftp_proxy`,
|
||||
`no_proxy`, `HTTP_PROXY`, `HTTPS_PROXY`, `FTP_PROXY`, `NO_PROXY`.
|
||||
`all_proxy`, `no_proxy`, `HTTP_PROXY`, `HTTPS_PROXY`, `FTP_PROXY`,
|
||||
`ALL_PROXY`, `NO_PROXY`.
|
||||
|
||||
If any of these variables are set when running the Nix installer, then
|
||||
the installer will create an override file at
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
# Uninstalling Nix
|
||||
|
||||
## Single User
|
||||
|
||||
If you have a [single-user installation](./installing-binary.md#single-user-installation) of Nix, uninstall it by running:
|
||||
|
||||
```console
|
||||
$ rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile
|
||||
```
|
||||
You might also want to manually remove references to Nix from your `~/.profile`.
|
||||
|
||||
## Multi User
|
||||
|
||||
Removing a [multi-user installation](./installing-binary.md#multi-user-installation) of Nix is more involved, and depends on the operating system.
|
||||
Removing a [multi-user installation](./installing-binary.md#multi-user-installation) depends on the operating system.
|
||||
|
||||
### Linux
|
||||
|
||||
@@ -52,7 +43,15 @@ which you may remove.
|
||||
|
||||
### macOS
|
||||
|
||||
1. Edit `/etc/zshrc`, `/etc/bashrc`, and `/etc/bash.bashrc` to remove the lines sourcing `nix-daemon.sh`, which should look like this:
|
||||
1. If system-wide shell initialisation files haven't been altered since installing Nix, use the backups made by the installer:
|
||||
|
||||
```console
|
||||
sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
|
||||
sudo mv /etc/bashrc.backup-before-nix /etc/bashrc
|
||||
sudo mv /etc/bash.bashrc.backup-before-nix /etc/bash.bashrc
|
||||
```
|
||||
|
||||
Otherwise, edit `/etc/zshrc`, `/etc/bashrc`, and `/etc/bash.bashrc` to remove the lines sourcing `nix-daemon.sh`, which should look like this:
|
||||
|
||||
```bash
|
||||
# Nix
|
||||
@@ -62,18 +61,6 @@ which you may remove.
|
||||
# End Nix
|
||||
```
|
||||
|
||||
If these files haven't been altered since installing Nix you can simply put
|
||||
the backups back in place:
|
||||
|
||||
```console
|
||||
sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
|
||||
sudo mv /etc/bashrc.backup-before-nix /etc/bashrc
|
||||
sudo mv /etc/bash.bashrc.backup-before-nix /etc/bash.bashrc
|
||||
```
|
||||
|
||||
This will stop shells from sourcing the file and bringing everything you
|
||||
installed using Nix in scope.
|
||||
|
||||
2. Stop and remove the Nix daemon services:
|
||||
|
||||
```console
|
||||
@@ -83,8 +70,7 @@ which you may remove.
|
||||
sudo rm /Library/LaunchDaemons/org.nixos.darwin-store.plist
|
||||
```
|
||||
|
||||
This stops the Nix daemon and prevents it from being started next time you
|
||||
boot the system.
|
||||
This stops the Nix daemon and prevents it from being started next time you boot the system.
|
||||
|
||||
3. Remove the `nixbld` group and the `_nixbuildN` users:
|
||||
|
||||
@@ -95,25 +81,42 @@ which you may remove.
|
||||
|
||||
This will remove all the build users that no longer serve a purpose.
|
||||
|
||||
4. Edit fstab using `sudo vifs` to remove the line mounting the Nix Store
|
||||
volume on `/nix`, which looks like
|
||||
`UUID=<uuid> /nix apfs rw,noauto,nobrowse,suid,owners` or
|
||||
`LABEL=Nix\040Store /nix apfs rw,nobrowse`. This will prevent automatic
|
||||
mounting of the Nix Store volume.
|
||||
4. Edit fstab using `sudo vifs` to remove the line mounting the Nix Store volume on `/nix`, which looks like
|
||||
|
||||
5. Edit `/etc/synthetic.conf` to remove the `nix` line. If this is the only
|
||||
line in the file you can remove it entirely, `sudo rm /etc/synthetic.conf`.
|
||||
This will prevent the creation of the empty `/nix` directory to provide a
|
||||
mountpoint for the Nix Store volume.
|
||||
```
|
||||
UUID=<uuid> /nix apfs rw,noauto,nobrowse,suid,owners
|
||||
```
|
||||
or
|
||||
|
||||
6. Remove the files Nix added to your system:
|
||||
```
|
||||
LABEL=Nix\040Store /nix apfs rw,nobrowse
|
||||
```
|
||||
|
||||
by setting the cursor on the respective line using the error keys, and pressing `dd`, and then `:wq` to save the file.
|
||||
|
||||
This will prevent automatic mounting of the Nix Store volume.
|
||||
|
||||
5. Edit `/etc/synthetic.conf` to remove the `nix` line.
|
||||
If this is the only line in the file you can remove it entirely:
|
||||
|
||||
```bash
|
||||
if [ -f /etc/synthetic.conf ]; then
|
||||
if [ "$(cat /etc/synthetic.conf)" = "nix" ]; then
|
||||
sudo rm /etc/synthetic.conf
|
||||
else
|
||||
sudo vi /etc/synthetic.conf
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
This will prevent the creation of the empty `/nix` directory.
|
||||
|
||||
6. Remove the files Nix added to your system, except for the store:
|
||||
|
||||
```console
|
||||
sudo rm -rf /etc/nix /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
|
||||
```
|
||||
|
||||
This gets rid of any data Nix may have created except for the store which is
|
||||
removed next.
|
||||
|
||||
7. Remove the Nix Store volume:
|
||||
|
||||
@@ -121,29 +124,32 @@ which you may remove.
|
||||
sudo diskutil apfs deleteVolume /nix
|
||||
```
|
||||
|
||||
This will remove the Nix Store volume and everything that was added to the
|
||||
store.
|
||||
This will remove the Nix Store volume and everything that was added to the store.
|
||||
|
||||
If the output indicates that the command couldn't remove the volume, you should
|
||||
make sure you don't have an _unmounted_ Nix Store volume. Look for a
|
||||
"Nix Store" volume in the output of the following command:
|
||||
If the output indicates that the command couldn't remove the volume, you should make sure you don't have an _unmounted_ Nix Store volume.
|
||||
Look for a "Nix Store" volume in the output of the following command:
|
||||
|
||||
```console
|
||||
diskutil list
|
||||
```
|
||||
|
||||
If you _do_ see a "Nix Store" volume, delete it by re-running the diskutil
|
||||
deleteVolume command, but replace `/nix` with the store volume's `diskXsY`
|
||||
identifier.
|
||||
If you _do_ find a "Nix Store" volume, delete it by running `diskutil deleteVolume` with the store volume's `diskXsY` identifier.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> After you complete the steps here, you will still have an empty `/nix`
|
||||
> directory. This is an expected sign of a successful uninstall. The empty
|
||||
> `/nix` directory will disappear the next time you reboot.
|
||||
> After you complete the steps here, you will still have an empty `/nix` directory.
|
||||
> This is an expected sign of a successful uninstall.
|
||||
> The empty `/nix` directory will disappear the next time you reboot.
|
||||
>
|
||||
> You do not have to reboot to finish uninstalling Nix. The uninstall is
|
||||
> complete. macOS (Catalina+) directly controls root directories and its
|
||||
> read-only root will prevent you from manually deleting the empty `/nix`
|
||||
> mountpoint.
|
||||
> You do not have to reboot to finish uninstalling Nix.
|
||||
> The uninstall is complete.
|
||||
> macOS (Catalina+) directly controls root directories, and its read-only root will prevent you from manually deleting the empty `/nix` mountpoint.
|
||||
|
||||
## Single User
|
||||
|
||||
To remove a [single-user installation](./installing-binary.md#single-user-installation) of Nix, run:
|
||||
|
||||
```console
|
||||
$ rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile
|
||||
```
|
||||
You might also want to manually remove references to Nix from your `~/.profile`.
|
||||
|
||||
@@ -197,33 +197,40 @@ Derivations can declare some infrequently used optional attributes.
|
||||
`outputHashAlgo` can only be `null` when `outputHash` follows the SRI format.
|
||||
|
||||
The `outputHashMode` attribute determines how the hash is computed.
|
||||
It must be one of the following two values:
|
||||
It must be one of the following values:
|
||||
|
||||
- `"flat"`\
|
||||
The output must be a non-executable regular file. If it isn’t,
|
||||
the build fails. The hash is simply computed over the contents
|
||||
of that file (so it’s equal to what Unix commands like
|
||||
`sha256sum` or `sha1sum` produce).
|
||||
- [`"flat"`](@docroot@/store/store-object/content-address.md#method-flat)
|
||||
|
||||
This is the default.
|
||||
|
||||
- `"recursive"` or `"nar"`\
|
||||
The hash is computed over the [NAR archive](@docroot@/glossary.md#gloss-nar) dump of the output
|
||||
(i.e., the result of [`nix-store --dump`](@docroot@/command-ref/nix-store/dump.md)). In
|
||||
this case, the output can be anything, including a directory
|
||||
tree.
|
||||
- [`"recursive"` or `"nar"`](@docroot@/store/store-object/content-address.md#method-nix-archive)
|
||||
|
||||
`"recursive"` is the traditional way of indicating this,
|
||||
and is supported since 2005 (virtually the entire history of Nix).
|
||||
`"nar"` is more clear, and consistent with other parts of Nix (such as the CLI),
|
||||
however support for it is only added in Nix version 2.21.
|
||||
> **Compatibility**
|
||||
>
|
||||
> `"recursive"` is the traditional way of indicating this,
|
||||
> and is supported since 2005 (virtually the entire history of Nix).
|
||||
> `"nar"` is more clear, and consistent with other parts of Nix (such as the CLI),
|
||||
> however support for it is only added in Nix version 2.21.
|
||||
|
||||
- [`"text"`](@docroot@/store/store-object/content-address.md#method-text)
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> The use of this method for derivation outputs is part of the [`dynamic-derivations`][xp-feature-dynamic-derivations] experimental feature.
|
||||
|
||||
- [`"git"`](@docroot@/store/store-object/content-address.md#method-git)
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> This method is part of the [`git-hashing`][xp-feature-git-hashing] experimental feature.
|
||||
|
||||
- [`__contentAddressed`]{#adv-attr-__contentAddressed}
|
||||
|
||||
> **Warning**
|
||||
> This attribute is part of an [experimental feature](@docroot@/contributing/experimental-features.md).
|
||||
>
|
||||
> To use this attribute, you must enable the
|
||||
> [`ca-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-ca-derivations) experimental feature.
|
||||
> [`ca-derivations`][xp-feature-ca-derivations] experimental feature.
|
||||
> For example, in [nix.conf](../command-ref/conf-file.md) you could add:
|
||||
>
|
||||
> ```
|
||||
@@ -303,7 +310,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
[`disallowedReferences`](#adv-attr-disallowedReferences) and [`disallowedRequisites`](#adv-attr-disallowedRequisites),
|
||||
the following attributes are available:
|
||||
|
||||
- `maxSize` defines the maximum size of the resulting [store object](@docroot@/glossary.md#gloss-store-object).
|
||||
- `maxSize` defines the maximum size of the resulting [store object](@docroot@/store/store-object.md).
|
||||
- `maxClosureSize` defines the maximum size of the output's closure.
|
||||
- `ignoreSelfRefs` controls whether self-references should be considered when
|
||||
checking for allowed references/requisites.
|
||||
@@ -355,3 +362,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
```
|
||||
|
||||
ensures that the derivation can only be built on a machine with the `kvm` feature.
|
||||
|
||||
[xp-feature-ca-derivations]: @docroot@/contributing/experimental-features.md#xp-feature-ca-derivations
|
||||
[xp-feature-dynamic-derivations]: @docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations
|
||||
[xp-feature-git-hashing]: @docroot@/contributing/experimental-features.md#xp-feature-git-hashing
|
||||
|
||||
@@ -402,7 +402,85 @@ establishes the same scope as
|
||||
let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...
|
||||
```
|
||||
|
||||
Variables coming from outer `with` expressions *are* shadowed:
|
||||
|
||||
```nix
|
||||
with { a = "outer"; };
|
||||
with { a = "inner"; };
|
||||
a
|
||||
```
|
||||
|
||||
Does evaluate to `"inner"`.
|
||||
|
||||
## Comments
|
||||
|
||||
Comments can be single-line, started with a `#` character, or
|
||||
inline/multi-line, enclosed within `/* ... */`.
|
||||
- Inline comments start with `#` and run until the end of the line.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> # A number
|
||||
> 2 # Equals 1 + 1
|
||||
> ```
|
||||
>
|
||||
> ```console
|
||||
> 2
|
||||
> ```
|
||||
|
||||
- Block comments start with `/*` and run until the next occurrence of `*/`.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> /*
|
||||
> Block comments
|
||||
> can span multiple lines.
|
||||
> */ "hello"
|
||||
> ```
|
||||
>
|
||||
> ```console
|
||||
> "hello"
|
||||
> ```
|
||||
|
||||
This means that block comments cannot be nested.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> /* /* nope */ */ 1
|
||||
> ```
|
||||
>
|
||||
> ```console
|
||||
> error: syntax error, unexpected '*'
|
||||
>
|
||||
> at «string»:1:15:
|
||||
>
|
||||
> 1| /* /* nope */ *
|
||||
> | ^
|
||||
> ```
|
||||
|
||||
Consider escaping nested comments and unescaping them in post-processing.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> ```nix
|
||||
> /* /* nested *\/ */ 1
|
||||
> ```
|
||||
>
|
||||
> ```console
|
||||
> 1
|
||||
> ```
|
||||
|
||||
## Scoping rules
|
||||
|
||||
Nix is [statically scoped](https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope), but with multiple scopes and shadowing rules.
|
||||
|
||||
* primary scope --- explicitly-bound variables
|
||||
* [`let`](#let-expressions)
|
||||
* [`inherit`](#inheriting-attributes)
|
||||
* function arguments
|
||||
|
||||
* secondary scope --- implicitly-bound variables
|
||||
* [`with`](#with-expressions)
|
||||
Primary scope takes precedence over secondary scope.
|
||||
See [`with`](#with-expressions) for a detailed example.
|
||||
|
||||
@@ -17,7 +17,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||
A symbolic name for the derivation.
|
||||
It is added to the [store path] of the corresponding [store derivation] as well as to its [output paths](@docroot@/glossary.md#gloss-output-path).
|
||||
|
||||
[store path]: @docroot@/glossary.md#gloss-store-path
|
||||
[store path]: @docroot@/store/store-path.md
|
||||
|
||||
> **Example**
|
||||
>
|
||||
@@ -141,7 +141,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||
|
||||
By default, a derivation produces a single output called `out`.
|
||||
However, derivations can produce multiple outputs.
|
||||
This allows the associated [store objects](@docroot@/glossary.md#gloss-store-object) and their [closures](@docroot@/glossary.md#gloss-closure) to be copied or garbage-collected separately.
|
||||
This allows the associated [store objects](@docroot@/store/store-object.md) and their [closures](@docroot@/glossary.md#gloss-closure) to be copied or garbage-collected separately.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
The value of a Nix expression can depend on the contents of a [store object].
|
||||
|
||||
[store object]: @docroot@/glossary.md#gloss-store-object
|
||||
[store object]: @docroot@/store/store-object.md
|
||||
|
||||
Passing an expression `expr` that evaluates to a [store path](@docroot@/glossary.md#gloss-store-path) to any built-in function which reads from the filesystem constitutes Import From Derivation (IFD):
|
||||
Passing an expression `expr` that evaluates to a [store path](@docroot@/store/store-path.md) to any built-in function which reads from the filesystem constitutes Import From Derivation (IFD):
|
||||
|
||||
- [`import`](./builtins.md#builtins-import)` expr`
|
||||
- [`builtins.readFile`](./builtins.md#builtins-readFile)` expr`
|
||||
|
||||
@@ -53,7 +53,7 @@ This is an incomplete overview of language features, by example.
|
||||
<td>
|
||||
|
||||
|
||||
*Basic values*
|
||||
*Basic values ([primitives](@docroot@/language/values.md#primitives))*
|
||||
|
||||
|
||||
</td>
|
||||
@@ -71,7 +71,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A string
|
||||
A [string](@docroot@/language/values.md#type-string)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -94,6 +94,18 @@ This is an incomplete overview of language features, by example.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`# Explanation`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A [comment](@docroot@/language/constructs.md#comments).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
@@ -106,7 +118,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
String interpolation (expands to `"hello world"`, `"1 2 3"`, `"/nix/store/<hash>-bash-<version>/bin/sh"`)
|
||||
[String interpolation](@docroot@/language/string-interpolation.md) (expands to `"hello world"`, `"1 2 3"`, `"/nix/store/<hash>-bash-<version>/bin/sh"`)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -118,7 +130,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Booleans
|
||||
[Booleans](@docroot@/language/values.md#type-boolean)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -130,7 +142,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Null value
|
||||
[Null](@docroot@/language/values.md#type-null) value
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -142,7 +154,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
An integer
|
||||
An [integer](@docroot@/language/values.md#type-number)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -154,7 +166,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A floating point number
|
||||
A [floating point number](@docroot@/language/values.md#type-number)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -166,7 +178,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
An absolute path
|
||||
An absolute [path](@docroot@/language/values.md#type-path)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -178,7 +190,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A path relative to the file containing this Nix expression
|
||||
A [path](@docroot@/language/values.md#type-path) relative to the file containing this Nix expression
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -190,7 +202,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A home path. Evaluates to the `"<user's home directory>/.config"`.
|
||||
A home [path](@docroot@/language/values.md#type-path). Evaluates to the `"<user's home directory>/.config"`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -202,7 +214,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Search path for Nix files. Value determined by [`$NIX_PATH` environment variable](../command-ref/env-common.md#env-NIX_PATH).
|
||||
A [lookup path](@docroot@/language/constructs/lookup-path.md) for Nix files. Value determined by [`$NIX_PATH` environment variable](../command-ref/env-common.md#env-NIX_PATH).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -226,7 +238,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A set with attributes named `x` and `y`
|
||||
An [attribute set](@docroot@/language/values.md#attribute-set) with attributes named `x` and `y`
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -250,7 +262,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A recursive set, equivalent to `{ x = "foo"; y = "foobar"; }`
|
||||
A [recursive set](@docroot@/language/constructs.md#recursive-sets), equivalent to `{ x = "foo"; y = "foobar"; }`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -266,7 +278,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Lists with three elements.
|
||||
[Lists](@docroot@/language/values.md#list) with three elements.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -350,7 +362,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Attribute selection (evaluates to `1`)
|
||||
[Attribute selection](@docroot@/language/values.md#attribute-set) (evaluates to `1`)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -362,7 +374,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Attribute selection with default (evaluates to `3`)
|
||||
[Attribute selection](@docroot@/language/values.md#attribute-set) with default (evaluates to `3`)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -398,7 +410,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Conditional expression
|
||||
[Conditional expression](@docroot@/language/constructs.md#conditionals).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -410,7 +422,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Assertion check (evaluates to `"yes!"`).
|
||||
[Assertion](@docroot@/language/constructs.md#assertions) check (evaluates to `"yes!"`).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -422,7 +434,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Variable definition
|
||||
Variable definition. See [`let`-expressions](@docroot@/language/constructs.md#let-expressions).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -434,7 +446,9 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Add all attributes from the given set to the scope (evaluates to `1`)
|
||||
Add all attributes from the given set to the scope (evaluates to `1`).
|
||||
|
||||
See [`with`-expressions](@docroot@/language/constructs.md#with-expressions) for details and shadowing caveats.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -447,7 +461,8 @@ This is an incomplete overview of language features, by example.
|
||||
<td>
|
||||
|
||||
Adds the variables to the current scope (attribute set or `let` binding).
|
||||
Desugars to `pkgs = pkgs; src = src;`
|
||||
Desugars to `pkgs = pkgs; src = src;`.
|
||||
See [Inheriting attributes](@docroot@/language/constructs.md#inheriting-attributes).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -460,14 +475,15 @@ This is an incomplete overview of language features, by example.
|
||||
<td>
|
||||
|
||||
Adds the attributes, from the attribute set in parentheses, to the current scope (attribute set or `let` binding).
|
||||
Desugars to `lib = pkgs.lib; stdenv = pkgs.stdenv;`
|
||||
Desugars to `lib = pkgs.lib; stdenv = pkgs.stdenv;`.
|
||||
See [Inheriting attributes](@docroot@/language/constructs.md#inheriting-attributes).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
*Functions (lambdas)*
|
||||
*[Functions](@docroot@/language/constructs.md#functions) (lambdas)*
|
||||
|
||||
</td>
|
||||
<td>
|
||||
@@ -484,7 +500,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function that expects an integer and returns it increased by 1
|
||||
A [function](@docroot@/language/constructs.md#functions) that expects an integer and returns it increased by 1.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -496,7 +512,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Curried function, equivalent to `x: (y: x + y)`. Can be used like a function that takes two arguments and returns their sum.
|
||||
Curried [function](@docroot@/language/constructs.md#functions), equivalent to `x: (y: x + y)`. Can be used like a function that takes two arguments and returns their sum.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -508,7 +524,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function call (evaluates to 101)
|
||||
A [function](@docroot@/language/constructs.md#functions) call (evaluates to 101)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -520,7 +536,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function bound to a variable and subsequently called by name (evaluates to 103)
|
||||
A [function](@docroot@/language/constructs.md#functions) bound to a variable and subsequently called by name (evaluates to 103)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -532,7 +548,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function that expects a set with required attributes `x` and `y` and concatenates them
|
||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attributes `x` and `y` and concatenates them
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -544,7 +560,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y`
|
||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y`
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -556,7 +572,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function that expects a set with required attributes `x` and `y` and ignores any other attributes
|
||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attributes `x` and `y` and ignores any other attributes
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -570,7 +586,7 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
A function that expects a set with required attributes `x` and `y`, and binds the whole set to `args`
|
||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attributes `x` and `y`, and binds the whole set to `args`
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -594,7 +610,8 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Load and return Nix expression in given file
|
||||
Load and return Nix expression in given file.
|
||||
See [import](@docroot@/language/builtins.md#builtins-import).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -606,7 +623,8 @@ This is an incomplete overview of language features, by example.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Apply a function to every element of a list (evaluates to `[ 2 4 6 ]`)
|
||||
Apply a function to every element of a list (evaluates to `[ 2 4 6 ]`).
|
||||
See [`map`](@docroot@/language/builtins.md#builtins-map).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -128,7 +128,7 @@ The result is a string.
|
||||
> The file or directory at *path* must exist and is copied to the [store].
|
||||
> The path appears in the result as the corresponding [store path].
|
||||
|
||||
[store path]: @docroot@/glossary.md#gloss-store-path
|
||||
[store path]: @docroot@/store/store-path.md
|
||||
[store]: @docroot@/glossary.md#gloss-store
|
||||
|
||||
[String and path concatenation]: #string-and-path-concatenation
|
||||
|
||||
134
doc/manual/src/language/string-context.md
Normal file
134
doc/manual/src/language/string-context.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# String context
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This is an advanced topic.
|
||||
> The Nix language is designed to be used without the programmer consciously dealing with string contexts or even knowing what they are.
|
||||
|
||||
A string in the Nix language is not just a sequence of characters like strings in other languages.
|
||||
It is actually a pair of a sequence of characters and a *string context*.
|
||||
The string context is an (unordered) set of *string context elements*.
|
||||
|
||||
The purpose of string contexts is to collect non-string values attached to strings via
|
||||
[string concatenation](./operators.md#string-concatenation),
|
||||
[string interpolation](./string-interpolation.md),
|
||||
and similar operations.
|
||||
The idea is that a user can combine together values to create a build instructions for derivations without manually keeping track of where they come from.
|
||||
Then the Nix language implicitly does that bookkeeping to efficiently obtain the closure of derivation inputs.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> String contexts are *not* explicitly manipulated in idiomatic Nix language code.
|
||||
|
||||
String context elements come in different forms:
|
||||
|
||||
- [deriving path]{#string-context-element-derived-path}
|
||||
|
||||
A string context element of this type is a [deriving path](@docroot@/glossary.md#gloss-deriving-path).
|
||||
They can be either of type [constant](#string-context-constant) or [output](#string-context-output), which correspond to the types of deriving paths.
|
||||
|
||||
- [Constant string context elements]{#string-context-constant}
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> [`builtins.storePath`] creates a string with a single constant string context element:
|
||||
>
|
||||
> ```nix
|
||||
> builtins.getContext (builtins.storePath "/nix/store/wkhdf9jinag5750mqlax6z2zbwhqb76n-hello-2.10")
|
||||
> ```
|
||||
> evaluates to
|
||||
> ```nix
|
||||
> {
|
||||
> "/nix/store/wkhdf9jinag5750mqlax6z2zbwhqb76n-hello-2.10" = {
|
||||
> path = true;
|
||||
> };
|
||||
> }
|
||||
> ```
|
||||
|
||||
[deriving path]: @docroot@/glossary.md#gloss-deriving-path
|
||||
[store path]: @docroot@/glossary.md#gloss-store-path
|
||||
[`builtins.storePath`]: ./builtins.md#builtins-storePath
|
||||
|
||||
- [Output string context elements]{#string-context-output}
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> The behavior of string contexts are best demonstrated with a built-in function that is still experimental: [`builtins.outputOf`].
|
||||
> This example will *not* work with stable Nix!
|
||||
>
|
||||
> ```nix
|
||||
> builtins.getContext
|
||||
> (builtins.outputOf
|
||||
> (builtins.storePath "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv")
|
||||
> "out")
|
||||
> ```
|
||||
> evaluates to
|
||||
> ```nix
|
||||
> {
|
||||
> "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv" = {
|
||||
> outputs = [ "out" ];
|
||||
> };
|
||||
> }
|
||||
> ```
|
||||
|
||||
[`builtins.outputOf`]: ./builtins.md#builtins-outputOf
|
||||
|
||||
- [*derivation deep*]{#string-context-element-derivation-deep}
|
||||
|
||||
*derivation deep* is an advanced feature intended to be used with the
|
||||
[`exportReferencesGraph` derivation attribute](./advanced-attributes.html#adv-attr-exportReferencesGraph).
|
||||
A *derivation deep* string context element is a derivation path, and refers to both its outputs and the entire build closure of that derivation:
|
||||
all its outputs, all the other derivations the given derivation depends on, and all the outputs of those.
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> The best way to illustrate *derivation deep* string contexts is with [`builtins.addDrvOutputDependencies`].
|
||||
> Take a regular constant string context element pointing to a derivation, and transform it into a "Derivation deep" string context element.
|
||||
>
|
||||
> ```nix
|
||||
> builtins.getContext
|
||||
> (builtins.addDrvOutputDependencies
|
||||
> (builtins.storePath "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv"))
|
||||
> ```
|
||||
> evaluates to
|
||||
> ```nix
|
||||
> {
|
||||
> "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv" = {
|
||||
> allOutputs = true;
|
||||
> };
|
||||
> }
|
||||
> ```
|
||||
|
||||
[`builtins.addDrvOutputDependencies`]: ./builtins.md#builtins-addDrvOutputDependencies
|
||||
[`builtins.unsafeDiscardOutputDependency`]: ./builtins.md#builtins-unsafeDiscardOutputDependency
|
||||
|
||||
## Inspecting string contexts
|
||||
|
||||
Most basically, [`builtins.hasContext`] will tell whether a string has a non-empty context.
|
||||
|
||||
When more granular information is needed, [`builtins.getContext`] can be used.
|
||||
It creates an [attribute set] representing the string context, which can be inspected as usual.
|
||||
|
||||
[`builtins.hasContext`]: ./builtins.md#builtins-hasContext
|
||||
[`builtins.getContext`]: ./builtins.md#builtins-getContext
|
||||
[attribute set]: ./values.md#attribute-set
|
||||
|
||||
## Clearing string contexts
|
||||
|
||||
[`buitins.unsafeDiscardStringContext`](./builtins.md#builtins-unsafeDiscardStringContext) will make a copy of a string, but with an empty string context.
|
||||
The returned string can be used in more ways, e.g. by operators that require the string context to be empty.
|
||||
The requirement to explicitly discard the string context in such use cases helps ensure that string context elements are not lost by mistake.
|
||||
The "unsafe" marker is only there to remind that Nix normally guarantees that dependencies are tracked, whereas the returned string has lost them.
|
||||
|
||||
## Constructing string contexts
|
||||
|
||||
[`builtins.appendContext`] will create a copy of a string, but with additional string context elements.
|
||||
The context is specified explicitly by an [attribute set] in the format that [`builtins.hasContext`] produces.
|
||||
A string with arbitrary contexts can be made like this:
|
||||
|
||||
1. Create a string with the desired string context elements.
|
||||
(The contents of the string do not matter.)
|
||||
2. Dump its context with [`builtins.getContext`].
|
||||
3. Combine it with a base string and repeated [`builtins.appendContext`] calls.
|
||||
|
||||
[`builtins.appendContext`]: ./builtins.md#builtins-appendContext
|
||||
@@ -107,9 +107,9 @@ An expression that is interpolated must evaluate to one of the following:
|
||||
|
||||
A string interpolates to itself.
|
||||
|
||||
A path in an interpolated expression is first copied into the Nix store, and the resulting string is the [store path] of the newly created [store object](@docroot@/glossary.md#gloss-store-object).
|
||||
A path in an interpolated expression is first copied into the Nix store, and the resulting string is the [store path] of the newly created [store object](@docroot@/store/store-object.md).
|
||||
|
||||
[store path]: @docroot@/glossary.md#gloss-store-path
|
||||
[store path]: @docroot@/store/store-path.md
|
||||
|
||||
> **Example**
|
||||
>
|
||||
|
||||
@@ -92,39 +92,50 @@
|
||||
|
||||
- <a id="type-path" href="#type-path">Path</a>
|
||||
|
||||
*Paths*, e.g., `/bin/sh` or `./builder.sh`. A path must contain at
|
||||
least one slash to be recognised as such. For instance, `builder.sh`
|
||||
is not a path: it's parsed as an expression that selects the
|
||||
attribute `sh` from the variable `builder`. If the file name is
|
||||
relative, i.e., if it does not begin with a slash, it is made
|
||||
absolute at parse time relative to the [base directory](@docroot@/glossary.md#gloss-base-directory).
|
||||
For instance, if a Nix expression in
|
||||
`/foo/bar/bla.nix` refers to `../xyzzy/fnord.nix`, the absolute path
|
||||
is `/foo/xyzzy/fnord.nix`.
|
||||
*Paths* are distinct from strings and can be expressed by path literals such as `./builder.sh`.
|
||||
|
||||
If the first component of a path is a `~`, it is interpreted as if
|
||||
the rest of the path were relative to the user's home directory.
|
||||
e.g. `~/foo` would be equivalent to `/home/edolstra/foo` for a user
|
||||
whose home directory is `/home/edolstra`.
|
||||
Paths are suitable for referring to local files, and are often preferable over strings.
|
||||
- Path values do not contain trailing slashes, `.` and `..`, as they are resolved when evaluating a path literal.
|
||||
- Path literals are automatically resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
|
||||
- The files referred to by path values are automatically copied into the Nix store when used in a string interpolation or concatenation.
|
||||
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
|
||||
|
||||
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` in the base directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
|
||||
A path literal must contain at least one slash to be recognised as such.
|
||||
For instance, `builder.sh` is not a path:
|
||||
it's parsed as an expression that selects the attribute `sh` from the variable `builder`.
|
||||
|
||||
Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
|
||||
Path literals may also refer to absolute paths by starting with a slash.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Absolute paths make expressions less portable.
|
||||
> In the case where a function translates a path literal into an absolute path string for a configuration file, it is recommended to write a string literal instead.
|
||||
> This avoids some confusion about whether files at that location will be used during evaluation.
|
||||
> It also avoids unintentional situations where some function might try to copy everything at the location into the store.
|
||||
|
||||
If the first component of a path is a `~`, it is interpreted such that the rest of the path were relative to the user's home directory.
|
||||
For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`.
|
||||
Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation.
|
||||
|
||||
Paths can be used in [string interpolation] and string concatenation.
|
||||
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
|
||||
|
||||
Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
|
||||
For example, assume you used a file path in an interpolated string during a `nix repl` session.
|
||||
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents.
|
||||
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents. Use `:r` to reset the repl as needed.
|
||||
|
||||
[store path]: @docroot@/glossary.md#gloss-store-path
|
||||
[store path]: @docroot@/store/store-path.md
|
||||
|
||||
Paths can include [string interpolation] and can themselves be [interpolated in other expressions].
|
||||
Path literals can also include [string interpolation], besides being [interpolated into other expressions].
|
||||
|
||||
[interpolated in other expressions]: ./string-interpolation.md#interpolated-expressions
|
||||
[interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions
|
||||
|
||||
At least one slash (`/`) must appear *before* any interpolated expression for the result to be recognized as a path.
|
||||
|
||||
`a.${foo}/b.${bar}` is a syntactically valid division operation.
|
||||
`a.${foo}/b.${bar}` is a syntactically valid number division operation.
|
||||
`./a.${foo}/b.${bar}` is a path.
|
||||
|
||||
[Lookup paths](./constructs/lookup-path.md) such as `<nixpkgs>` resolve to path values.
|
||||
[Lookup path](./constructs/lookup-path.md) literals such as `<nixpkgs>` also resolve to path values.
|
||||
|
||||
- <a id="type-boolean" href="#type-boolean">Boolean</a>
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# Copying Closures via SSH
|
||||
|
||||
The command `nix-copy-closure` copies a Nix store path along with all
|
||||
its dependencies to or from another machine via the SSH protocol. It
|
||||
doesn’t copy store paths that are already present on the target machine.
|
||||
For example, the following command copies Firefox with all its
|
||||
dependencies:
|
||||
|
||||
$ nix-copy-closure --to alice@itchy.example.org $(type -p firefox)
|
||||
|
||||
See the [manpage for `nix-copy-closure`](../command-ref/nix-copy-closure.md) for details.
|
||||
|
||||
With `nix-store
|
||||
--export` and `nix-store --import` you can write the closure of a store
|
||||
path (that is, the path and all its dependencies) to a file, and then
|
||||
unpack that file into another Nix store. For example,
|
||||
|
||||
$ nix-store --export $(nix-store --query --requisites $(type -p firefox)) > firefox.closure
|
||||
|
||||
writes the closure of Firefox to a file. You can then copy this file to
|
||||
another machine and install the closure:
|
||||
|
||||
$ nix-store --import < firefox.closure
|
||||
|
||||
Any store paths in the closure that are already present in the target
|
||||
store are ignored. It is also possible to pipe the export into another
|
||||
command, e.g. to copy and install a closure directly to/on another
|
||||
machine:
|
||||
|
||||
$ nix-store --export $(nix-store --query --requisites $(type -p firefox)) | bzip2 | \
|
||||
ssh alice@itchy.example.org "bunzip2 | nix-store --import"
|
||||
|
||||
However, `nix-copy-closure` is generally more efficient because it only
|
||||
copies paths that are not already present in the target Nix store.
|
||||
@@ -18,10 +18,30 @@ is a JSON object with the following fields:
|
||||
Information about the output paths of the derivation.
|
||||
This is a JSON object with one member per output, where the key is the output name and the value is a JSON object with these fields:
|
||||
|
||||
* `path`: The output path.
|
||||
* `path`:
|
||||
The output path, if it is known in advanced.
|
||||
Otherwise, `null`.
|
||||
|
||||
|
||||
* `method`:
|
||||
For an output which will be [content addresed], a string representing the [method](@docroot@/store/store-object/content-address.md) of content addressing that is chosen.
|
||||
Valid method strings are:
|
||||
|
||||
- [`flat`](@docroot@/store/store-object/content-address.md#method-flat)
|
||||
- [`nar`](@docroot@/store/store-object/content-address.md#method-nix-archive)
|
||||
- [`text`](@docroot@/store/store-object/content-address.md#method-text)
|
||||
- [`git`](@docroot@/store/store-object/content-address.md#method-git)
|
||||
|
||||
Otherwise, `null`.
|
||||
|
||||
* `hashAlgo`:
|
||||
For fixed-output derivations, the hashing algorithm (e.g. `sha256`), optionally prefixed by `r:` if `hash` denotes a NAR hash rather than a flat file hash.
|
||||
For an output which will be [content addresed], the name of the hash algorithm used.
|
||||
Valid algorithm strings are:
|
||||
|
||||
- `md5`
|
||||
- `sha1`
|
||||
- `sha256`
|
||||
- `sha512`
|
||||
|
||||
* `hash`:
|
||||
For fixed-output derivations, the expected content hash in base-16.
|
||||
@@ -32,7 +52,8 @@ is a JSON object with the following fields:
|
||||
> "outputs": {
|
||||
> "out": {
|
||||
> "path": "/nix/store/2543j7c6jn75blc3drf4g5vhb1rhdq29-source",
|
||||
> "hashAlgo": "r:sha256",
|
||||
> "method": "nar",
|
||||
> "hashAlgo": "sha256",
|
||||
> "hash": "6fc80dcc62179dbc12fc0b5881275898f93444833d21b89dfe5f7fbcbb1d0d62"
|
||||
> }
|
||||
> }
|
||||
|
||||
@@ -28,9 +28,9 @@ Info about a [store object].
|
||||
|
||||
Content address of this store object's file system object, used to compute its store path.
|
||||
|
||||
[store path]: @docroot@/glossary.md#gloss-store-path
|
||||
[store path]: @docroot@/store/store-path.md
|
||||
[file system object]: @docroot@/store/file-system-object.md
|
||||
[Nix Archive]: @docroot@/glossary.md#gloss-nar
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
## Impure fields
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# Nix Archive (NAR) format
|
||||
|
||||
This is the complete specification of the Nix Archive format.
|
||||
This is the complete specification of the [Nix Archive] format.
|
||||
The Nix Archive format closely follows the abstract specification of a [file system object] tree,
|
||||
because it is designed to serialize exactly that data structure.
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#nix-archive
|
||||
[file system object]: @docroot@/store/file-system-object.md
|
||||
|
||||
The format of this specification is close to [Extended Backus–Naur form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form), with the exception of the `str(..)` function / parameterized rule, which length-prefixes and pads strings.
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# Complete Store Path Calculation
|
||||
|
||||
This is the complete specification for how store paths are calculated.
|
||||
This is the complete specification for how [store path]s are calculated.
|
||||
|
||||
The format of this specification is close to [Extended Backus–Naur form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form), but must deviate for a few things such as hash functions which we treat as bidirectional for specification purposes.
|
||||
|
||||
Regular users do *not* need to know this information --- store paths can be treated as black boxes computed from the properties of the store objects they refer to.
|
||||
But for those interested in exactly how Nix works, e.g. if they are reimplementing it, this information can be useful.
|
||||
|
||||
[store path](@docroot@/store/store-path.md)
|
||||
|
||||
## Store path proper
|
||||
|
||||
```ebnf
|
||||
@@ -34,18 +36,23 @@ where
|
||||
- `type` = one of:
|
||||
|
||||
- ```ebnf
|
||||
| "text" ( ":" store-path )*
|
||||
| "text" { ":" store-path }
|
||||
```
|
||||
|
||||
for encoded derivations written to the store.
|
||||
This is for the
|
||||
["Text"](@docroot@/store/store-object/content-address.md#method-text)
|
||||
method of content addressing store objects.
|
||||
The optional trailing store paths are the references of the store object.
|
||||
|
||||
- ```ebnf
|
||||
| "source" ( ":" store-path )*
|
||||
| "source" { ":" store-path } [ ":self" ]
|
||||
```
|
||||
|
||||
For paths copied to the store and hashed via a [Nix Archive (NAR)] and [SHA-256][sha-256].
|
||||
Just like in the text case, we can have the store objects referenced by their paths.
|
||||
This is for the
|
||||
["Nix Archive"](@docroot@/store/store-object/content-address.md#method-nix-archive)
|
||||
method of content addressing store objects,
|
||||
if the hash algorithm is [SHA-256].
|
||||
Just like in the "Text" case, we can have the store objects referenced by their paths.
|
||||
Additionally, we can have an optional `:self` label to denote self reference.
|
||||
|
||||
- ```ebnf
|
||||
@@ -53,8 +60,12 @@ where
|
||||
```
|
||||
|
||||
For either the outputs built from derivations,
|
||||
paths copied to the store hashed that area single file hashed directly, or the via a hash algorithm other than [SHA-256][sha-256].
|
||||
(in that case "source" is used; this is only necessary for compatibility).
|
||||
or content-addressed store objects that are not using one of the two above cases.
|
||||
To be explicit about the latter, that is currently these methods:
|
||||
|
||||
- ["Flat"](@docroot@/store/store-object/content-address.md#method-flat)
|
||||
- ["Git"](@docroot@/store/store-object/content-address.md#method-git)
|
||||
- ["Nix Archive"](@docroot@/store/store-object/content-address.md#method-nix-archive) if the hash algorithm is not [SHA-256].
|
||||
|
||||
`id` is the name of the output (usually, "out").
|
||||
For content-addressed store objects, `id`, is always "out".
|
||||
@@ -113,8 +124,8 @@ where
|
||||
Note that `id` = `"out"`, regardless of the name part of the store path.
|
||||
Also note that NAR + SHA-256 must not use this case, and instead must use the `type` = `"source:" ...` case.
|
||||
|
||||
[Nix Archive (NAR)]: @docroot@/glossary.md#gloss-NAR
|
||||
[sha-256]: https://en.m.wikipedia.org/wiki/SHA-256
|
||||
[Nix Archive (NAR)]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
[SHA-256]: https://en.m.wikipedia.org/wiki/SHA-256
|
||||
|
||||
### Historical Note
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Link: <flakeref>; rel="immutable"
|
||||
|
||||
*flakeref* must be a tarball flakeref. It can contain the tarball flake attributes
|
||||
`narHash`, `rev`, `revCount` and `lastModified`. If `narHash` is included, its
|
||||
value must be the NAR hash of the unpacked tarball (as computed via
|
||||
value must be the [NAR hash][Nix Archive] of the unpacked tarball (as computed via
|
||||
`nix hash path`). Nix checks the contents of the returned tarball
|
||||
against the `narHash` attribute. The `rev` and `revCount` attributes
|
||||
are useful when the tarball flake is a mirror of a fetcher type that
|
||||
@@ -40,3 +40,5 @@ Link: <https://example.org/hello/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz
|
||||
|
||||
For tarball flakes, the value of the `lastModified` flake attribute is
|
||||
defined as the timestamp of the newest file inside the tarball.
|
||||
|
||||
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
|
||||
|
||||
85
doc/manual/src/store/file-system-object/content-address.md
Normal file
85
doc/manual/src/store/file-system-object/content-address.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Content-Addressing File System Objects
|
||||
|
||||
For many operations, Nix needs to calculate [a content addresses](@docroot@/glossary.md#gloss-content-address) of [a file system object][file system object].
|
||||
Usually this is needed as part of
|
||||
[content addressing store objects](../store-object/content-address.md),
|
||||
since store objects always have a root file system object.
|
||||
But some command-line utilities also just work on "raw" file system objects, not part of any store object.
|
||||
|
||||
Every content addressing scheme Nix uses ultimately involves feeding data into a [hash function](https://en.wikipedia.org/wiki/Hash_function), and getting back an opaque fixed-size digest which is deemed a content address.
|
||||
The various *methods* of content addressing thus differ in how abstract data (in this case, a file system object and its descendents) are fed into the hash function.
|
||||
|
||||
## Serialising File System Objects { #serial }
|
||||
|
||||
The simplest method is to serialise the entire file system object tree into a single binary string, and then hash that binary string, yielding the content address.
|
||||
In this section we describe the currently-supported methods of serialising file system objects.
|
||||
|
||||
### Flat { #serial-flat }
|
||||
|
||||
A single file object can just be hashed by its contents.
|
||||
This is not enough information to encode the fact that the file system object is a file,
|
||||
but if we *already* know that the FSO is a single non-executable file by other means, it is sufficient.
|
||||
|
||||
Because the hashed data is just the raw file, as is, this choice is good for compatibility with other systems.
|
||||
For example, Unix commands like `sha256sum` or `sha1sum` will produce hashes for single files that match this.
|
||||
|
||||
### Nix Archive (NAR) { #serial-nix-archive }
|
||||
|
||||
For the other cases of [file system objects][file system object], especially directories with arbitrary descendents, we need a more complex serialisation format.
|
||||
Examples of such serialisations are the ZIP and TAR file formats.
|
||||
However, for our purposes these formats have two problems:
|
||||
|
||||
- They do not have a canonical serialisation, meaning that given an FSO, there can
|
||||
be many different serialisations.
|
||||
For instance, TAR files can have variable amounts of padding between archive members;
|
||||
and some archive formats leave the order of directory entries undefined.
|
||||
This would be bad because we use serialisation to compute cryptographic hashes over file system objects, and for those hashes to be useful as a content address or for integrity checking, uniqueness is crucial.
|
||||
Otherwise, correct hashes would report false mismatches, and the store would fail to find the content.
|
||||
|
||||
- They store more information than we have in our notion of FSOs, such as time stamps.
|
||||
This can cause FSOs that Nix should consider equal to hash to different values on different machines, just because the dates differ.
|
||||
|
||||
- As a practical consideration, the TAR format is the only truly universal format in the Unix environment.
|
||||
It has many problems, such as an inability to deal with long file names and files larger than 2^33 bytes.
|
||||
Current implementations such as GNU Tar work around these limitations in various ways.
|
||||
|
||||
For these reasons, Nix has its very own archive format—the Nix Archive (NAR) format,
|
||||
which is carefully designed to avoid the problems described above.
|
||||
|
||||
The exact specification of the Nix Archive format is in `protocols/nix-archive.md`
|
||||
|
||||
## Content addressing File System Objects beyond a single serialisation pass
|
||||
|
||||
Serialising the entire tree and then hashing that binary string is not the only option for content addressing, however.
|
||||
Another technique is that of a [Merkle graph](https://en.wikipedia.org/wiki/Merkle_tree), where previously computed hashes are included in subsequent byte strings to be hashed.
|
||||
|
||||
In particular, the Merkle graphs can match the original graph structure of file system objects:
|
||||
we can first hash (serialised) child file system objects, and then hash parent objects using the hashes of their children in the serialisation (to be hashed) of the parent file system objects.
|
||||
|
||||
Currently, there is one such Merkle DAG content addressing method supported.
|
||||
|
||||
### Git ([experimental][xp-feature-git-hashing]) { #git }
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> This method is part of the [`git-hashing`][xp-feature-git-hashing] experimental feature.
|
||||
|
||||
Git's file system model is very close to Nix's, and so Git's content addressing method is a pretty good fit.
|
||||
Just as with regular Git, files and symlinks are hashed as git "blobs", and directories are hashed as git "trees".
|
||||
|
||||
However, one difference between Nix's and Git's file system model needs special treatment.
|
||||
Plain files, executable files, and symlinks are not differentiated as distinctly addressable objects, but by their context: by the directory entry that refers to them.
|
||||
That means so long as the root object is a directory, there is no problem:
|
||||
every non-directory object is owned by a parent directory, and the entry that refers to it provides the missing information.
|
||||
However, if the root object is not a directory, then we have no way of knowing which one of an executable file, non-executable file, or symlink it is supposed to be.
|
||||
|
||||
In response to this, we have decided to treat a bare file as non-executable file.
|
||||
This is similar to do what we do with [flat serialisation](#serial-flat), which also lacks this information.
|
||||
To avoid an address collision, attempts to hash a bare executable file or symlink will result in an error (just as would happen for flat serialisation also).
|
||||
Thus, Git can encode some, but not all of Nix's "File System Objects", and this sort of content-addressing is likewise partial.
|
||||
|
||||
In the future, we may support a Git-like hash for such file system objects, or we may adopt another Merkle DAG format which is capable of representing all Nix file system objects.
|
||||
|
||||
[file system object]: ../file-system-object.md
|
||||
[store object]: ../store-object.md
|
||||
[xp-feature-git-hashing]: @docroot@/contributing/experimental-features.md#xp-feature-git-hashing
|
||||
95
doc/manual/src/store/store-object/content-address.md
Normal file
95
doc/manual/src/store/store-object/content-address.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Content-Addressing Store Objects
|
||||
|
||||
Just [like][fso-ca] [File System Objects][File System Object],
|
||||
[Store Objects][Store Object] can also be [content-addressed](@docroot@/glossary.md#gloss-content-addressed),
|
||||
unless they are [input-addressed](@docroot@/glossary.md#gloss-input-addressed-store-object).
|
||||
|
||||
For store objects, the content address we produce will take the form of a [Store Path] rather than regular hash.
|
||||
In particular, the content-addressing scheme will ensure that the digest of the store path is solely computed from the
|
||||
|
||||
- file system object graph (the root one and its children, if it has any)
|
||||
- references
|
||||
- [store directory](../store-path.md#store-directory)
|
||||
- name
|
||||
|
||||
of the store object, and not any other information, which would not be an intrinsic property of that store object.
|
||||
|
||||
For the full specification of the algorithms involved, see the [specification of store path digests][sp-spec].
|
||||
|
||||
[File System Object]: ../file-system-object.md
|
||||
[Store Object]: ../store-object.md
|
||||
[Store Path]: ../store-path.md
|
||||
|
||||
## Content addressing each part of a store object
|
||||
|
||||
### File System Objects
|
||||
|
||||
With all currently supported store object content addressing methods, the file system object is always [content-addressed][fso-ca] first, and then that hash is incorporated into content address computation for the store object.
|
||||
|
||||
### References
|
||||
|
||||
With all currently supported store object content addressing methods,
|
||||
other objects are referred to by their regular (string-encoded-) [store paths][Store Path].
|
||||
|
||||
Self-references however cannot be referred to by their path, because we are in the midst of describing how to compute that path!
|
||||
|
||||
> The alternative would require finding as hash function fixed point, i.e. the solution to an equation in the form
|
||||
> ```
|
||||
> digest = hash(..... || digest || ....)
|
||||
> ```
|
||||
> which is computationally infeasible.
|
||||
> As far as we know, this is equivalent to finding a hash collision.
|
||||
|
||||
Instead we just have a "has self reference" boolean, which will end up affecting the digest.
|
||||
|
||||
### Name and Store Directory
|
||||
|
||||
These two items affect the digest in a way that is standard for store path digest computations and not specific to content-addressing.
|
||||
Consult the [specification of store path digests][sp-spec] for further details.
|
||||
|
||||
## Content addressing Methods
|
||||
|
||||
For historical reasons, we don't support all features in all combinations.
|
||||
Each currently supported method of content addressing chooses a single method of file system object hashing, and may offer some restrictions on references.
|
||||
The names and store directories are unrestricted however.
|
||||
|
||||
### Flat { #method-flat }
|
||||
|
||||
This uses the corresponding [Flat](../file-system-object/content-address.md#serial-flat) method of file system object content addressing.
|
||||
|
||||
References are not supported: store objects with flat hashing *and* references can not be created.
|
||||
|
||||
### Text { #method-text }
|
||||
|
||||
This also uses the corresponding [Flat](../file-system-object/content-address.md#serial-flat) method of file system object content addressing.
|
||||
|
||||
References to other store objects are supported, but self references are not.
|
||||
|
||||
This is the only store-object content-addressing method that is not named identically with a corresponding file system object method.
|
||||
It is somewhat obscure, mainly used for "drv files"
|
||||
(derivations serialized as store objects in their ["ATerm" file format](@docroot@/protocols/derivation-aterm.md)).
|
||||
Prefer another method if possible.
|
||||
|
||||
### Nix Archive { #method-nix-archive }
|
||||
|
||||
This uses the corresponding [Nix Archive](../file-system-object/content-address.md#serial-nix-archive) method of file system object content addressing.
|
||||
|
||||
References (to other store objects and self references alike) are supported so long as the hash algorithm is SHA-256, but not (neither kind) otherwise.
|
||||
|
||||
### Git { #method-git }
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> This method is part of the [`git-hashing`][xp-feature-git-hashing] experimental feature.
|
||||
|
||||
This uses the corresponding [Git](../file-system-object/content-address.md#serial-git) method of file system object content addressing.
|
||||
|
||||
References are not supported.
|
||||
|
||||
Only SHA-1 is supported at this time.
|
||||
If [SHA-256-based Git](https://git-scm.com/docs/hash-function-transition)
|
||||
becomes more widespread, this restriction will be revisited.
|
||||
|
||||
[fso-ca]: ../file-system-object/content-address.md
|
||||
[sp-spec]: @docroot@/protocols/store-path.md
|
||||
[xp-feature-git-hashing]: @docroot@/contributing/experimental-features.md#xp-feature-git-hashing
|
||||
@@ -1,5 +1,11 @@
|
||||
# Store Path
|
||||
|
||||
> **Example**
|
||||
>
|
||||
> `/nix/store/a040m110amc4h71lds2jmr8qrkj2jhxd-git-2.38.1`
|
||||
>
|
||||
> A rendered store path
|
||||
|
||||
Nix implements references to [store objects](./index.md#store-object) as *store paths*.
|
||||
|
||||
Think of a store path as an [opaque], [unique identifier]:
|
||||
@@ -37,6 +43,10 @@ A store path is rendered to a file system path as the concatenation of
|
||||
> store directory digest name
|
||||
> ```
|
||||
|
||||
Exactly how the digest is calculated depends on the type of store path.
|
||||
Store path digests are *supposed* to be opaque, and so for most operations, it is not necessary to know the details.
|
||||
That said, the manual has a full [specification of store path digests](@docroot@/protocols/store-path.md).
|
||||
|
||||
## Store Directory
|
||||
|
||||
Every [Nix store](./index.md) has a store directory.
|
||||
|
||||
15
flake.nix
15
flake.nix
@@ -26,7 +26,7 @@
|
||||
inherit (nixpkgs) lib;
|
||||
inherit (lib) fileset;
|
||||
|
||||
officialRelease = true;
|
||||
officialRelease = false;
|
||||
|
||||
version = lib.fileContents ./.version + versionSuffix;
|
||||
versionSuffix =
|
||||
@@ -179,11 +179,19 @@
|
||||
];
|
||||
});
|
||||
|
||||
libseccomp-nix = final.libseccomp.overrideAttrs (_: rec {
|
||||
version = "2.5.5";
|
||||
src = final.fetchurl {
|
||||
url = "https://github.com/seccomp/libseccomp/releases/download/v${version}/libseccomp-${version}.tar.gz";
|
||||
hash = "sha256-JIosik2bmFiqa69ScSw0r+/PnJ6Ut23OAsHJqiX7M3U=";
|
||||
};
|
||||
});
|
||||
|
||||
changelog-d-nix = final.buildPackages.callPackage ./misc/changelog-d.nix { };
|
||||
|
||||
nix =
|
||||
let
|
||||
officialRelease = true;
|
||||
officialRelease = false;
|
||||
versionSuffix =
|
||||
if officialRelease
|
||||
then ""
|
||||
@@ -195,9 +203,10 @@
|
||||
stdenv
|
||||
versionSuffix
|
||||
;
|
||||
officialRelease = true;
|
||||
officialRelease = false;
|
||||
boehmgc = final.boehmgc-nix;
|
||||
libgit2 = final.libgit2-nix;
|
||||
libseccomp = final.libseccomp-nix;
|
||||
busybox-sandbox-shell = final.busybox-sandbox-shell or final.default-busybox-sandbox-shell;
|
||||
} // {
|
||||
# this is a proper separate downstream package, but put
|
||||
|
||||
@@ -36,11 +36,13 @@ We aim to achieve this by improving the contributor experience and attracting mo
|
||||
- Robert Hensing (@roberth)
|
||||
- John Ericson (@Ericson2314)
|
||||
|
||||
The team is on Github as [@NixOS/nix-team](https://github.com/orgs/NixOS/teams/nix-team).
|
||||
|
||||
## Meeting protocol
|
||||
|
||||
The team meets twice a week:
|
||||
The team meets twice a week (times are denoted in the [Europe/Amsterdam](https://en.m.wikipedia.org/wiki/Time_in_the_Netherlands) time zone):
|
||||
|
||||
- Discussion meeting: [Fridays 13:00-14:00 CET](https://calendar.google.com/calendar/event?eid=MHNtOGVuNWtrZXNpZHR2bW1sM3QyN2ZjaGNfMjAyMjExMjVUMTIwMDAwWiBiOW81MmZvYnFqYWs4b3E4bGZraGczdDBxZ0Bn)
|
||||
- Discussion meeting: [Wednesday 21:00-22:00 Europe/Amsterdam](https://www.google.com/calendar/event?eid=ZG5rZzNyajRjajducGV2NGY5aGkzYWIwdnJfMjAyNDA1MDhUMTkwMDAwWiBiOW81MmZvYnFqYWs4b3E4bGZraGczdDBxZ0Bn)
|
||||
|
||||
1. Triage issues and pull requests from the [No Status](#no-status) column (30 min)
|
||||
2. Discuss issues and pull requests from the [To discuss](#to-discuss) column (30 min).
|
||||
@@ -49,15 +51,19 @@ The team meets twice a week:
|
||||
- mark it as draft if it is blocked on the contributor
|
||||
- escalate it back to the team by moving it to To discuss, and leaving a comment as to why the issue needs to be discussed again.
|
||||
|
||||
- Work meeting: [Mondays 13:00-15:00 CET](https://calendar.google.com/calendar/event?eid=NTM1MG1wNGJnOGpmOTZhYms3bTB1bnY5cWxfMjAyMjExMjFUMTIwMDAwWiBiOW81MmZvYnFqYWs4b3E4bGZraGczdDBxZ0Bn)
|
||||
- Work meeting: [Mondays 13:00-15:00 Europe/Amsterdam](https://www.google.com/calendar/event?eid=Ym52NDdzYnRic2NzcDcybjZiNDhpNzhpa3NfMjAyNDA1MTNUMTIwMDAwWiBiOW81MmZvYnFqYWs4b3E4bGZraGczdDBxZ0Bn)
|
||||
|
||||
1. Code review on pull requests from [In review](#in-review).
|
||||
2. Other chores and tasks.
|
||||
|
||||
Meeting notes are collected on a [collaborative scratchpad](https://pad.lassul.us/Cv7FpYx-Ri-4VjUykQOLAw).
|
||||
Notes on issues and pull requests are posted as comments and linked from the meeting notes, so they are easy to find from both places.
|
||||
Notes on issues and pull requests are posted as comments and linked from the meeting notes, so they are can be found from both places.
|
||||
[All meeting notes](https://discourse.nixos.org/search?expanded=true&q=Nix%20team%20meeting%20minutes%20%23%20%23dev%3Anix%20in%3Atitle%20order%3Alatest_topic) are published on Discourse under the [Nix category](https://discourse.nixos.org/c/dev/nix/50).
|
||||
|
||||
Team meetings are generally open to anyone interested.
|
||||
We can make exceptions to discuss sensitive issues, such as security incidents or people matters.
|
||||
Contact any team member to get a calendar invite for reminders and updates.
|
||||
|
||||
## Project board protocol
|
||||
|
||||
The team uses a [GitHub project board](https://github.com/orgs/NixOS/projects/19/views/1) for tracking its work.
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
excludes = [
|
||||
# We don't want to format test data
|
||||
# ''tests/(?!nixos/).*\.nix''
|
||||
''^tests/.*''
|
||||
''^tests/functional/.*$''
|
||||
''^tests/unit/[^/]*/data/.*$''
|
||||
|
||||
# Don't format vendored code
|
||||
''^src/toml11/.*''
|
||||
@@ -113,15 +114,15 @@
|
||||
''^src/libfetchers/fetch-to-store\.cc$''
|
||||
''^src/libfetchers/fetchers\.cc$''
|
||||
''^src/libfetchers/fetchers\.hh$''
|
||||
''^src/libfetchers/filtering-input-accessor\.cc$''
|
||||
''^src/libfetchers/filtering-input-accessor\.hh$''
|
||||
''^src/libfetchers/fs-input-accessor\.cc$''
|
||||
''^src/libfetchers/fs-input-accessor\.hh$''
|
||||
''^src/libfetchers/filtering-source-accessor\.cc$''
|
||||
''^src/libfetchers/filtering-source-accessor\.hh$''
|
||||
''^src/libfetchers/fs-source-accessor\.cc$''
|
||||
''^src/libfetchers/fs-source-accessor\.hh$''
|
||||
''^src/libfetchers/git-utils\.cc$''
|
||||
''^src/libfetchers/git-utils\.hh$''
|
||||
''^src/libfetchers/github\.cc$''
|
||||
''^src/libfetchers/indirect\.cc$''
|
||||
''^src/libfetchers/memory-input-accessor\.cc$''
|
||||
''^src/libfetchers/memory-source-accessor\.cc$''
|
||||
''^src/libfetchers/path\.cc$''
|
||||
''^src/libfetchers/registry\.cc$''
|
||||
''^src/libfetchers/registry\.hh$''
|
||||
@@ -241,19 +242,19 @@
|
||||
''^src/libstore/unix/build/worker\.hh$''
|
||||
''^src/libstore/unix/builtins/fetchurl\.cc$''
|
||||
''^src/libstore/unix/builtins/unpack-channel\.cc$''
|
||||
''^src/libstore/unix/gc\.cc$''
|
||||
''^src/libstore/gc\.cc$''
|
||||
''^src/libstore/unix/local-overlay-store\.cc$''
|
||||
''^src/libstore/unix/local-overlay-store\.hh$''
|
||||
''^src/libstore/unix/local-store\.cc$''
|
||||
''^src/libstore/unix/local-store\.hh$''
|
||||
''^src/libstore/local-store\.cc$''
|
||||
''^src/libstore/local-store\.hh$''
|
||||
''^src/libstore/unix/lock\.cc$''
|
||||
''^src/libstore/unix/lock\.hh$''
|
||||
''^src/libstore/unix/optimise-store\.cc$''
|
||||
''^src/libstore/optimise-store\.cc$''
|
||||
''^src/libstore/unix/pathlocks\.cc$''
|
||||
''^src/libstore/unix/posix-fs-canonicalise\.cc$''
|
||||
''^src/libstore/unix/posix-fs-canonicalise\.hh$''
|
||||
''^src/libstore/unix/uds-remote-store\.cc$''
|
||||
''^src/libstore/unix/uds-remote-store\.hh$''
|
||||
''^src/libstore/posix-fs-canonicalise\.cc$''
|
||||
''^src/libstore/posix-fs-canonicalise\.hh$''
|
||||
''^src/libstore/uds-remote-store\.cc$''
|
||||
''^src/libstore/uds-remote-store\.hh$''
|
||||
''^src/libstore/windows/build\.cc$''
|
||||
''^src/libstore/worker-protocol-impl\.hh$''
|
||||
''^src/libstore/worker-protocol\.cc$''
|
||||
@@ -302,7 +303,7 @@
|
||||
''^src/libutil/hash\.hh$''
|
||||
''^src/libutil/hilite\.cc$''
|
||||
''^src/libutil/hilite\.hh$''
|
||||
''^src/libutil/input-accessor\.hh$''
|
||||
''^src/libutil/source-accessor\.hh$''
|
||||
''^src/libutil/json-impls\.hh$''
|
||||
''^src/libutil/json-utils\.cc$''
|
||||
''^src/libutil/json-utils\.hh$''
|
||||
@@ -350,7 +351,7 @@
|
||||
''^src/libutil/unix/processes\.cc$''
|
||||
''^src/libutil/unix/signals-impl\.hh$''
|
||||
''^src/libutil/unix/signals\.cc$''
|
||||
''^src/libutil/unix/unix-domain-socket\.cc$''
|
||||
''^src/libutil/unix-domain-socket\.cc$''
|
||||
''^src/libutil/unix/users\.cc$''
|
||||
''^src/libutil/url-parts\.hh$''
|
||||
''^src/libutil/url\.cc$''
|
||||
@@ -426,6 +427,69 @@
|
||||
''^src/nix/upgrade-nix\.cc$''
|
||||
''^src/nix/verify\.cc$''
|
||||
''^src/nix/why-depends\.cc$''
|
||||
|
||||
''^tests/nixos/ca-fd-leak/sender\.c''
|
||||
''^tests/nixos/ca-fd-leak/smuggler\.c''
|
||||
''^tests/unit/libexpr-support/tests/libexpr\.hh''
|
||||
''^tests/unit/libexpr-support/tests/value/context\.cc''
|
||||
''^tests/unit/libexpr-support/tests/value/context\.hh''
|
||||
''^tests/unit/libexpr/derived-path\.cc''
|
||||
''^tests/unit/libexpr/error_traces\.cc''
|
||||
''^tests/unit/libexpr/eval\.cc''
|
||||
''^tests/unit/libexpr/flake/flakeref\.cc''
|
||||
''^tests/unit/libexpr/flake/url-name\.cc''
|
||||
''^tests/unit/libexpr/json\.cc''
|
||||
''^tests/unit/libexpr/main\.cc''
|
||||
''^tests/unit/libexpr/primops\.cc''
|
||||
''^tests/unit/libexpr/search-path\.cc''
|
||||
''^tests/unit/libexpr/trivial\.cc''
|
||||
''^tests/unit/libexpr/value/context\.cc''
|
||||
''^tests/unit/libexpr/value/print\.cc''
|
||||
''^tests/unit/libfetchers/public-key\.cc''
|
||||
''^tests/unit/libstore-support/tests/derived-path\.cc''
|
||||
''^tests/unit/libstore-support/tests/derived-path\.hh''
|
||||
''^tests/unit/libstore-support/tests/libstore\.hh''
|
||||
''^tests/unit/libstore-support/tests/nix_api_store\.hh''
|
||||
''^tests/unit/libstore-support/tests/outputs-spec\.cc''
|
||||
''^tests/unit/libstore-support/tests/outputs-spec\.hh''
|
||||
''^tests/unit/libstore-support/tests/path\.cc''
|
||||
''^tests/unit/libstore-support/tests/path\.hh''
|
||||
''^tests/unit/libstore-support/tests/protocol\.hh''
|
||||
''^tests/unit/libstore/common-protocol\.cc''
|
||||
''^tests/unit/libstore/content-address\.cc''
|
||||
''^tests/unit/libstore/derivation\.cc''
|
||||
''^tests/unit/libstore/derived-path\.cc''
|
||||
''^tests/unit/libstore/downstream-placeholder\.cc''
|
||||
''^tests/unit/libstore/machines\.cc''
|
||||
''^tests/unit/libstore/nar-info-disk-cache\.cc''
|
||||
''^tests/unit/libstore/nar-info\.cc''
|
||||
''^tests/unit/libstore/outputs-spec\.cc''
|
||||
''^tests/unit/libstore/path-info\.cc''
|
||||
''^tests/unit/libstore/path\.cc''
|
||||
''^tests/unit/libstore/serve-protocol\.cc''
|
||||
''^tests/unit/libstore/worker-protocol\.cc''
|
||||
''^tests/unit/libutil-support/tests/characterization\.hh''
|
||||
''^tests/unit/libutil-support/tests/hash\.cc''
|
||||
''^tests/unit/libutil-support/tests/hash\.hh''
|
||||
''^tests/unit/libutil/args\.cc''
|
||||
''^tests/unit/libutil/canon-path\.cc''
|
||||
''^tests/unit/libutil/chunked-vector\.cc''
|
||||
''^tests/unit/libutil/closure\.cc''
|
||||
''^tests/unit/libutil/compression\.cc''
|
||||
''^tests/unit/libutil/config\.cc''
|
||||
''^tests/unit/libutil/file-content-address\.cc''
|
||||
''^tests/unit/libutil/git\.cc''
|
||||
''^tests/unit/libutil/hash\.cc''
|
||||
''^tests/unit/libutil/hilite\.cc''
|
||||
''^tests/unit/libutil/json-utils\.cc''
|
||||
''^tests/unit/libutil/logging\.cc''
|
||||
''^tests/unit/libutil/lru-cache\.cc''
|
||||
''^tests/unit/libutil/pool\.cc''
|
||||
''^tests/unit/libutil/references\.cc''
|
||||
''^tests/unit/libutil/suggestions\.cc''
|
||||
''^tests/unit/libutil/tests\.cc''
|
||||
''^tests/unit/libutil/url\.cc''
|
||||
''^tests/unit/libutil/xml-writer\.cc''
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
@@ -189,10 +189,7 @@ for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) {
|
||||
eval {
|
||||
downloadFile("dockerImage.$system", "1", $fn);
|
||||
};
|
||||
if ($@) {
|
||||
warn "$@" if $@;
|
||||
next;
|
||||
}
|
||||
die "$@" if $@;
|
||||
$haveDocker = 1;
|
||||
|
||||
print STDERR "loading docker image for $dockerPlatform...\n";
|
||||
|
||||
@@ -17,11 +17,3 @@ TESTS_ENVIRONMENT=(
|
||||
run () {
|
||||
cd "$(dirname $1)" && env "${TESTS_ENVIRONMENT[@]}" $BASH -x -e -u -o pipefail $(basename $1)
|
||||
}
|
||||
|
||||
init_test () {
|
||||
run "$init" 2>/dev/null > /dev/null
|
||||
}
|
||||
|
||||
run_test_proper () {
|
||||
run "$test"
|
||||
}
|
||||
|
||||
@@ -3,12 +3,8 @@
|
||||
set -eu -o pipefail
|
||||
|
||||
test=$1
|
||||
init=${2-}
|
||||
|
||||
dir="$(dirname "${BASH_SOURCE[0]}")"
|
||||
source "$dir/common-test.sh"
|
||||
|
||||
if [ -n "$init" ]; then
|
||||
(init_test)
|
||||
fi
|
||||
run_test_proper
|
||||
run "$test"
|
||||
|
||||
@@ -87,15 +87,14 @@ $(foreach script, $(bin-scripts), $(eval $(call install-program-in,$(script),$(b
|
||||
$(foreach script, $(bin-scripts), $(eval programs-list += $(script)))
|
||||
$(foreach script, $(noinst-scripts), $(eval programs-list += $(script)))
|
||||
$(foreach template, $(template-files), $(eval $(call instantiate-template,$(template))))
|
||||
install_test_init=tests/functional/init.sh
|
||||
$(foreach test, $(install-tests), \
|
||||
$(eval $(call run-test,$(test),$(install_test_init))) \
|
||||
$(eval $(call run-test,$(test))) \
|
||||
$(eval installcheck: $(test).test))
|
||||
$(foreach test-group, $(install-tests-groups), \
|
||||
$(eval $(call run-test-group,$(test-group),$(install_test_init))) \
|
||||
$(eval $(call run-test-group,$(test-group))) \
|
||||
$(eval installcheck: $(test-group).test-group) \
|
||||
$(foreach test, $($(test-group)-tests), \
|
||||
$(eval $(call run-test,$(test),$(install_test_init))) \
|
||||
$(eval $(call run-test,$(test))) \
|
||||
$(eval $(test-group).test-group: $(test).test)))
|
||||
|
||||
# Compilation database.
|
||||
|
||||
@@ -8,7 +8,6 @@ yellow=""
|
||||
normal=""
|
||||
|
||||
test=$1
|
||||
init=${2-}
|
||||
|
||||
dir="$(dirname "${BASH_SOURCE[0]}")"
|
||||
source "$dir/common-test.sh"
|
||||
@@ -22,10 +21,7 @@ if [ -t 1 ]; then
|
||||
fi
|
||||
|
||||
run_test () {
|
||||
if [ -n "$init" ]; then
|
||||
(init_test 2>/dev/null > /dev/null)
|
||||
fi
|
||||
log="$(run_test_proper 2>&1)" && status=0 || status=$?
|
||||
log="$(run "$test" 2>&1)" && status=0 || status=$?
|
||||
}
|
||||
|
||||
run_test
|
||||
|
||||
@@ -12,8 +12,8 @@ endef
|
||||
|
||||
define run-test
|
||||
|
||||
$(eval $(call run-bash,$1.test,$1 $(test-deps),mk/run-test.sh $1 $2))
|
||||
$(eval $(call run-bash,$1.test-debug,$1 $(test-deps),mk/debug-test.sh $1 $2))
|
||||
$(eval $(call run-bash,$1.test,$1 $(test-deps),mk/run-test.sh $1))
|
||||
$(eval $(call run-bash,$1.test-debug,$1 $(test-deps),mk/debug-test.sh $1))
|
||||
|
||||
endef
|
||||
|
||||
|
||||
@@ -249,13 +249,7 @@ in {
|
||||
] ++ lib.optionals buildUnitTests [
|
||||
gtest
|
||||
rapidcheck
|
||||
] ++ lib.optional stdenv.isLinux (libseccomp.overrideAttrs (_: rec {
|
||||
version = "2.5.5";
|
||||
src = fetchurl {
|
||||
url = "https://github.com/seccomp/libseccomp/releases/download/v${version}/libseccomp-${version}.tar.gz";
|
||||
hash = "sha256-JIosik2bmFiqa69ScSw0r+/PnJ6Ut23OAsHJqiX7M3U=";
|
||||
};
|
||||
}))
|
||||
] ++ lib.optional stdenv.isLinux libseccomp
|
||||
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
|
||||
# There have been issues building these dependencies
|
||||
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin))
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[test]
|
||||
-I=rel(lib/Nix)
|
||||
2
perl/.yath.rc.in
Normal file
2
perl/.yath.rc.in
Normal file
@@ -0,0 +1,2 @@
|
||||
[test]
|
||||
-I=rel(@lib_dir@)
|
||||
@@ -1,21 +0,0 @@
|
||||
makefiles = local.mk
|
||||
|
||||
GLOBAL_CXXFLAGS += -g -Wall -std=c++2a
|
||||
|
||||
# A convenience for concurrent development of Nix and its Perl bindings.
|
||||
# Not needed in a standalone build of the Perl bindings.
|
||||
ifneq ("$(wildcard ../src)", "")
|
||||
GLOBAL_CXXFLAGS += -I ../src
|
||||
endif
|
||||
|
||||
-include Makefile.config
|
||||
|
||||
OPTIMIZE = 1
|
||||
|
||||
ifeq ($(OPTIMIZE), 1)
|
||||
GLOBAL_CXXFLAGS += -O3
|
||||
else
|
||||
GLOBAL_CXXFLAGS += -O0
|
||||
endif
|
||||
|
||||
include mk/lib.mk
|
||||
@@ -1,18 +0,0 @@
|
||||
HOST_OS = @host_os@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
SODIUM_LIBS = @SODIUM_LIBS@
|
||||
NIX_CFLAGS = @NIX_CFLAGS@
|
||||
NIX_LIBS = @NIX_LIBS@
|
||||
nixbindir = @nixbindir@
|
||||
curl = @curl@
|
||||
nixlibexecdir = @nixlibexecdir@
|
||||
nixlocalstatedir = @nixlocalstatedir@
|
||||
perl = @perl@
|
||||
perllibdir = @perllibdir@
|
||||
nixstoredir = @nixstoredir@
|
||||
nixsysconfdir = @nixsysconfdir@
|
||||
@@ -1,84 +0,0 @@
|
||||
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../.version)$VERSION_SUFFIX"]))
|
||||
AC_CONFIG_SRCDIR(MANIFEST)
|
||||
AC_CONFIG_AUX_DIR(../config)
|
||||
|
||||
CFLAGS=
|
||||
CXXFLAGS=
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
# Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_DEFUN([NEED_PROG],
|
||||
[
|
||||
AC_PATH_PROG($1, $2)
|
||||
if test -z "$$1"; then
|
||||
AC_MSG_ERROR([$2 is required])
|
||||
fi
|
||||
])
|
||||
|
||||
NEED_PROG(perl, perl)
|
||||
NEED_PROG(curl, curl)
|
||||
NEED_PROG(bzip2, bzip2)
|
||||
NEED_PROG(xz, xz)
|
||||
|
||||
# Test that Perl has the open/fork feature (Perl 5.8.0 and beyond).
|
||||
AC_MSG_CHECKING([whether Perl is recent enough])
|
||||
if ! $perl -e 'open(FOO, "-|", "true"); while (<FOO>) { print; }; close FOO or die;'; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([Your Perl version is too old. Nix requires Perl 5.8.0 or newer.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
|
||||
# Figure out where to install Perl modules.
|
||||
AC_MSG_CHECKING([for the Perl installation prefix])
|
||||
perlversion=$($perl -e 'use Config; print $Config{version};')
|
||||
perlarchname=$($perl -e 'use Config; print $Config{archname};')
|
||||
AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname])
|
||||
AC_MSG_RESULT($perllibdir)
|
||||
|
||||
# Look for libsodium.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Check for the required Perl dependencies (DBI and DBD::SQLite).
|
||||
perlFlags="-I$perllibdir"
|
||||
|
||||
AC_ARG_WITH(dbi, AC_HELP_STRING([--with-dbi=PATH],
|
||||
[prefix of the Perl DBI library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_ARG_WITH(dbd-sqlite, AC_HELP_STRING([--with-dbd-sqlite=PATH],
|
||||
[prefix of the Perl DBD::SQLite library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_MSG_CHECKING([whether DBD::SQLite works])
|
||||
if ! $perl $perlFlags -e 'use DBI; use DBD::SQLite;' 2>&5; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_FAILURE([The Perl modules DBI and/or DBD::SQLite are missing.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
AC_SUBST(perlFlags)
|
||||
|
||||
PKG_CHECK_MODULES([NIX], [nix-store])
|
||||
|
||||
NEED_PROG([NIX], [nix])
|
||||
|
||||
# Expand all variables in config.status.
|
||||
test "$prefix" = NONE && prefix=$ac_default_prefix
|
||||
test "$exec_prefix" = NONE && exec_prefix='${prefix}'
|
||||
for name in $ac_subst_vars; do
|
||||
declare $name="$(eval echo "${!name}")"
|
||||
declare $name="$(eval echo "${!name}")"
|
||||
declare $name="$(eval echo "${!name}")"
|
||||
done
|
||||
|
||||
rm -f Makefile.config
|
||||
ln -sfn ../mk mk
|
||||
|
||||
AC_CONFIG_FILES([])
|
||||
AC_OUTPUT
|
||||
@@ -1,47 +1,52 @@
|
||||
{ lib, fileset
|
||||
{ lib
|
||||
, fileset
|
||||
, stdenv
|
||||
, perl, perlPackages
|
||||
, autoconf-archive, autoreconfHook, pkg-config
|
||||
, nix, curl, bzip2, xz, boost, libsodium, darwin
|
||||
, perl
|
||||
, perlPackages
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
, nix
|
||||
, curl
|
||||
, bzip2
|
||||
, xz
|
||||
, boost
|
||||
, libsodium
|
||||
, darwin
|
||||
}:
|
||||
|
||||
perl.pkgs.toPerlModule (stdenv.mkDerivation (finalAttrs: {
|
||||
name = "nix-perl-${nix.version}";
|
||||
|
||||
src = fileset.toSource {
|
||||
root = ../.;
|
||||
root = ./.;
|
||||
fileset = fileset.unions ([
|
||||
../.version
|
||||
../m4
|
||||
../mk
|
||||
./MANIFEST
|
||||
./Makefile
|
||||
./Makefile.config.in
|
||||
./configure.ac
|
||||
./lib
|
||||
./local.mk
|
||||
./meson.build
|
||||
./meson_options.txt
|
||||
] ++ lib.optionals finalAttrs.doCheck [
|
||||
./.yath.rc
|
||||
./.yath.rc.in
|
||||
./t
|
||||
]);
|
||||
};
|
||||
|
||||
nativeBuildInputs =
|
||||
[ autoconf-archive
|
||||
autoreconfHook
|
||||
pkg-config
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
buildInputs =
|
||||
[ nix
|
||||
curl
|
||||
bzip2
|
||||
xz
|
||||
perl
|
||||
boost
|
||||
]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||
buildInputs = [
|
||||
nix
|
||||
curl
|
||||
bzip2
|
||||
xz
|
||||
perl
|
||||
boost
|
||||
]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||
|
||||
# `perlPackages.Test2Harness` is marked broken for Darwin
|
||||
doCheck = !stdenv.isDarwin;
|
||||
@@ -50,12 +55,16 @@ perl.pkgs.toPerlModule (stdenv.mkDerivation (finalAttrs: {
|
||||
perlPackages.Test2Harness
|
||||
];
|
||||
|
||||
configureFlags = [
|
||||
"--with-dbi=${perlPackages.DBI}/${perl.libPrefix}"
|
||||
"--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}"
|
||||
mesonFlags = [
|
||||
(lib.mesonOption "version" (builtins.readFile ../.version))
|
||||
(lib.mesonOption "dbi_path" "${perlPackages.DBI}/${perl.libPrefix}")
|
||||
(lib.mesonOption "dbd_sqlite_path" "${perlPackages.DBDSQLite}/${perl.libPrefix}")
|
||||
(lib.mesonEnable "tests" finalAttrs.doCheck)
|
||||
];
|
||||
|
||||
mesonCheckFlags = [
|
||||
"--print-errorlogs"
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
postUnpack = "sourceRoot=$sourceRoot/perl";
|
||||
}))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "config.h"
|
||||
#include "nix/config.h"
|
||||
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
@@ -256,9 +256,8 @@ SV *
|
||||
hashPath(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
auto [accessor, canonPath] = PosixSourceAccessor::createAtRoot(path);
|
||||
Hash h = hashPath(
|
||||
accessor, canonPath,
|
||||
PosixSourceAccessor::createAtRoot(path),
|
||||
FileIngestionMethod::Recursive, parseHashAlgo(algo));
|
||||
auto s = h.to_string(base32 ? HashFormat::Nix32 : HashFormat::Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
@@ -336,10 +335,9 @@ StoreWrapper::addToStore(char * srcPath, int recursive, char * algo)
|
||||
PPCODE:
|
||||
try {
|
||||
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
|
||||
auto [accessor, canonPath] = PosixSourceAccessor::createAtRoot(srcPath);
|
||||
auto path = THIS->store->addToStore(
|
||||
std::string(baseNameOf(srcPath)),
|
||||
accessor, canonPath,
|
||||
PosixSourceAccessor::createAtRoot(srcPath),
|
||||
method, parseHashAlgo(algo));
|
||||
XPUSHs(sv_2mortal(newSVpv(THIS->store->printStorePath(path).c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
|
||||
59
perl/lib/Nix/meson.build
Normal file
59
perl/lib/Nix/meson.build
Normal file
@@ -0,0 +1,59 @@
|
||||
# Nix-Perl Scripts
|
||||
#============================================================================
|
||||
|
||||
|
||||
|
||||
# Sources
|
||||
#-------------------------------------------------
|
||||
|
||||
nix_perl_store_xs = files('Store.xs')
|
||||
|
||||
nix_perl_scripts = files(
|
||||
'CopyClosure.pm',
|
||||
'Manifest.pm',
|
||||
'SSH.pm',
|
||||
'Store.pm',
|
||||
'Utils.pm',
|
||||
)
|
||||
|
||||
foreach f : nix_perl_scripts
|
||||
fs.copyfile(f)
|
||||
endforeach
|
||||
|
||||
|
||||
# Targets
|
||||
#---------------------------------------------------
|
||||
|
||||
nix_perl_scripts += configure_file(
|
||||
output : 'Config.pm',
|
||||
input : 'Config.pm.in',
|
||||
configuration : nix_perl_conf,
|
||||
)
|
||||
|
||||
nix_perl_store_cc = custom_target(
|
||||
'Store.cc',
|
||||
output : 'Store.cc',
|
||||
input : nix_perl_store_xs,
|
||||
command : [xsubpp, '@INPUT@', '-output', '@OUTPUT@'],
|
||||
)
|
||||
|
||||
# Build Nix::Store Library
|
||||
#-------------------------------------------------
|
||||
nix_perl_store_lib = library(
|
||||
'Store',
|
||||
sources : nix_perl_store_cc,
|
||||
name_prefix : '',
|
||||
install : true,
|
||||
install_mode : 'rwxr-xr-x',
|
||||
install_dir : join_paths(nix_perl_install_dir, 'auto', 'Nix', 'Store'),
|
||||
dependencies : nix_perl_store_dep_list,
|
||||
)
|
||||
|
||||
|
||||
# Install Scripts
|
||||
#---------------------------------------------------
|
||||
install_data(
|
||||
nix_perl_scripts,
|
||||
install_mode : 'rw-r--r--',
|
||||
install_dir : join_paths(nix_perl_install_dir,'Nix'),
|
||||
)
|
||||
@@ -1,46 +0,0 @@
|
||||
nix_perl_sources := \
|
||||
lib/Nix/Store.pm \
|
||||
lib/Nix/Manifest.pm \
|
||||
lib/Nix/SSH.pm \
|
||||
lib/Nix/CopyClosure.pm \
|
||||
lib/Nix/Config.pm.in \
|
||||
lib/Nix/Utils.pm
|
||||
|
||||
nix_perl_modules := $(nix_perl_sources:.in=)
|
||||
|
||||
$(foreach x, $(nix_perl_modules), $(eval $(call install-data-in, $(x), $(perllibdir)/Nix)))
|
||||
|
||||
lib/Nix/Store.cc: lib/Nix/Store.xs
|
||||
$(trace-gen) xsubpp $^ -output $@
|
||||
|
||||
libraries += Store
|
||||
|
||||
Store_DIR := lib/Nix
|
||||
|
||||
Store_SOURCES := $(Store_DIR)/Store.cc
|
||||
|
||||
Store_CXXFLAGS = \
|
||||
$(NIX_CFLAGS) \
|
||||
-I$(shell perl -e 'use Config; print $$Config{archlibexp};')/CORE \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-Wno-unknown-warning-option -Wno-unused-variable -Wno-literal-suffix \
|
||||
-Wno-reserved-user-defined-literal -Wno-duplicate-decl-specifier -Wno-pointer-bool-conversion
|
||||
|
||||
Store_LDFLAGS := $(SODIUM_LIBS) $(NIX_LIBS)
|
||||
|
||||
ifdef HOST_CYGWIN
|
||||
archlib = $(shell perl -E 'use Config; print $$Config{archlib};')
|
||||
libperl = $(shell perl -E 'use Config; print $$Config{libperl};')
|
||||
Store_LDFLAGS += $(shell find ${archlib} -name ${libperl})
|
||||
endif
|
||||
|
||||
Store_ALLOW_UNDEFINED = 1
|
||||
|
||||
Store_FORCE_INSTALL = 1
|
||||
|
||||
Store_INSTALL_DIR = $(perllibdir)/auto/Nix/Store
|
||||
|
||||
clean-files += lib/Nix/Config.pm lib/Nix/Store.cc Makefile.config
|
||||
|
||||
check: all
|
||||
yath test
|
||||
160
perl/meson.build
Normal file
160
perl/meson.build
Normal file
@@ -0,0 +1,160 @@
|
||||
# Nix-Perl Meson build
|
||||
#============================================================================
|
||||
|
||||
|
||||
# init project
|
||||
#============================================================================
|
||||
project (
|
||||
'nix-perl',
|
||||
'cpp',
|
||||
meson_version : '>= 0.64.0',
|
||||
license : 'LGPL-2.1-or-later',
|
||||
)
|
||||
|
||||
# setup env
|
||||
#-------------------------------------------------
|
||||
fs = import('fs')
|
||||
nix_version = get_option('version')
|
||||
cpp = meson.get_compiler('cpp')
|
||||
nix_perl_conf = configuration_data()
|
||||
nix_perl_conf.set('PACKAGE_VERSION', nix_version)
|
||||
|
||||
|
||||
# set error arguments
|
||||
#-------------------------------------------------
|
||||
error_args = [
|
||||
'-Wno-pedantic',
|
||||
'-Wno-non-virtual-dtor',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-variadic-macros',
|
||||
'-Wdeprecated-declarations',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-unknown-warning-option',
|
||||
'-Wno-unused-variable',
|
||||
'-Wno-literal-suffix',
|
||||
'-Wno-reserved-user-defined-literal',
|
||||
'-Wno-duplicate-decl-specifier',
|
||||
'-Wno-pointer-bool-conversion',
|
||||
]
|
||||
|
||||
add_project_arguments(
|
||||
cpp.get_supported_arguments(error_args),
|
||||
language : 'cpp',
|
||||
)
|
||||
|
||||
|
||||
# set install directories
|
||||
#-------------------------------------------------
|
||||
prefix = get_option('prefix')
|
||||
libdir = join_paths(prefix, get_option('libdir'))
|
||||
|
||||
# Dependencies
|
||||
#============================================================================
|
||||
|
||||
# Required Programs
|
||||
#-------------------------------------------------
|
||||
xz = find_program('xz')
|
||||
xsubpp = find_program('xsubpp')
|
||||
perl = find_program('perl')
|
||||
curl = find_program('curl')
|
||||
yath = find_program('yath', required : false)
|
||||
|
||||
# Required Libraries
|
||||
#-------------------------------------------------
|
||||
bzip2_dep = dependency('bzip2')
|
||||
curl_dep = dependency('libcurl')
|
||||
libsodium_dep = dependency('libsodium')
|
||||
# nix_util_dep = dependency('nix-util')
|
||||
nix_store_dep = dependency('nix-store')
|
||||
|
||||
|
||||
# Finding Perl Headers is a pain. as they do not have
|
||||
# pkgconfig available, are not in a standard location,
|
||||
# and are installed into a version folder. Use the
|
||||
# Perl binary to give hints about perl include dir.
|
||||
#-------------------------------------------------
|
||||
perl_archname = run_command(
|
||||
perl, '-e', 'use Config; print $Config{archname};', check: true).stdout()
|
||||
perl_version = run_command(
|
||||
perl, '-e', 'use Config; print $Config{version};', check: true).stdout()
|
||||
perl_archlibexp = run_command(
|
||||
perl, '-e', 'use Config; print $Config{archlibexp};', check: true).stdout()
|
||||
perl_site_libdir = run_command(
|
||||
perl, '-e', 'use Config; print $Config{installsitearch};', check: true).stdout()
|
||||
nix_perl_install_dir = join_paths(
|
||||
libdir, 'perl5', 'site_perl', perl_version, perl_archname)
|
||||
|
||||
|
||||
# print perl hints for logs
|
||||
#-------------------------------------------------
|
||||
message('Perl archname: @0@'.format(perl_archname))
|
||||
message('Perl version: @0@'.format(perl_version))
|
||||
message('Perl archlibexp: @0@'.format(perl_archlibexp))
|
||||
message('Perl install site: @0@'.format(perl_site_libdir))
|
||||
message('Assumed Nix-Perl install dir: @0@'.format(nix_perl_install_dir))
|
||||
|
||||
# Now find perl modules
|
||||
#-------------------------------------------------
|
||||
perl_check_dbi = run_command(
|
||||
perl,
|
||||
'-e', 'use DBI; use DBD::SQLite;',
|
||||
'-I@0@'.format(get_option('dbi_path')),
|
||||
'-I@0@'.format(get_option('dbd_sqlite_path')),
|
||||
check: true
|
||||
)
|
||||
|
||||
if perl_check_dbi.returncode() == 2
|
||||
error('The Perl modules DBI and/or DBD::SQLite are missing.')
|
||||
else
|
||||
message('Found Perl Modules: DBI, DBD::SQLite.')
|
||||
endif
|
||||
|
||||
|
||||
|
||||
# declare perl dependency
|
||||
#-------------------------------------------------
|
||||
perl_dep = declare_dependency(
|
||||
dependencies : cpp.find_library(
|
||||
'perl',
|
||||
has_headers : [
|
||||
join_paths(perl_archlibexp, 'CORE', 'perl.h'),
|
||||
join_paths(perl_archlibexp, 'CORE', 'EXTERN.h')],
|
||||
dirs : [
|
||||
join_paths(perl_archlibexp, 'CORE'),
|
||||
],
|
||||
),
|
||||
include_directories : join_paths(perl_archlibexp, 'CORE'),
|
||||
)
|
||||
|
||||
# declare dependencies
|
||||
#-------------------------------------------------
|
||||
nix_perl_store_dep_list = [
|
||||
perl_dep,
|
||||
bzip2_dep,
|
||||
curl_dep,
|
||||
libsodium_dep,
|
||||
nix_store_dep,
|
||||
]
|
||||
|
||||
# # build
|
||||
# #-------------------------------------------------
|
||||
lib_dir = join_paths('lib', 'Nix')
|
||||
subdir(lib_dir)
|
||||
|
||||
if get_option('tests').enabled()
|
||||
yath_rc_conf = configuration_data()
|
||||
yath_rc_conf.set('lib_dir', lib_dir)
|
||||
yath_rc = configure_file(
|
||||
output : '.yath.rc',
|
||||
input : '.yath.rc.in',
|
||||
configuration : yath_rc_conf,
|
||||
)
|
||||
subdir('t')
|
||||
test(
|
||||
'nix-perl-test',
|
||||
yath,
|
||||
args : ['test'],
|
||||
workdir : meson.current_build_dir(),
|
||||
depends : [nix_perl_store_lib],
|
||||
)
|
||||
endif
|
||||
32
perl/meson_options.txt
Normal file
32
perl/meson_options.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
# Nix-Perl build options
|
||||
#============================================================================
|
||||
|
||||
|
||||
# compiler args
|
||||
#============================================================================
|
||||
|
||||
option(
|
||||
'version',
|
||||
type : 'string',
|
||||
description : 'nix-perl version')
|
||||
|
||||
option(
|
||||
'tests',
|
||||
type : 'feature',
|
||||
value : 'disabled',
|
||||
description : 'run nix-perl tests')
|
||||
|
||||
|
||||
# Location of Perl Modules
|
||||
#============================================================================
|
||||
option(
|
||||
'dbi_path',
|
||||
type : 'string',
|
||||
value : '/usr',
|
||||
description : 'path to perl::dbi')
|
||||
|
||||
option(
|
||||
'dbd_sqlite_path',
|
||||
type : 'string',
|
||||
value : '/usr',
|
||||
description : 'path to perl::dbd-SQLite')
|
||||
15
perl/t/meson.build
Normal file
15
perl/t/meson.build
Normal file
@@ -0,0 +1,15 @@
|
||||
# Nix-Perl Tests
|
||||
#============================================================================
|
||||
|
||||
|
||||
# src
|
||||
#---------------------------------------------------
|
||||
|
||||
nix_perl_tests = files(
|
||||
'init.t',
|
||||
)
|
||||
|
||||
|
||||
foreach f : nix_perl_tests
|
||||
fs.copyfile(f)
|
||||
endforeach
|
||||
@@ -35,7 +35,7 @@ escape_systemd_env() {
|
||||
|
||||
# Gather all non-empty proxy environment variables into a string
|
||||
create_systemd_proxy_env() {
|
||||
vars="http_proxy https_proxy ftp_proxy no_proxy HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY"
|
||||
vars="http_proxy https_proxy ftp_proxy all_proxy no_proxy HTTP_PROXY HTTPS_PROXY FTP_PROXY ALL_PROXY NO_PROXY"
|
||||
for v in $vars; do
|
||||
if [ "x${!v:-}" != "x" ]; then
|
||||
echo "Environment=${v}=$(escape_systemd_env ${!v})"
|
||||
|
||||
@@ -37,7 +37,7 @@ static std::string currentLoad;
|
||||
|
||||
static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
|
||||
{
|
||||
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
|
||||
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri.render()), slot), true);
|
||||
}
|
||||
|
||||
static bool allSupportedLocally(Store & store, const std::set<std::string>& requiredFeatures) {
|
||||
@@ -99,7 +99,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
}
|
||||
|
||||
std::optional<StorePath> drvPath;
|
||||
std::string storeUri;
|
||||
StoreReference storeUri;
|
||||
|
||||
while (true) {
|
||||
|
||||
@@ -135,7 +135,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
Machine * bestMachine = nullptr;
|
||||
uint64_t bestLoad = 0;
|
||||
for (auto & m : machines) {
|
||||
debug("considering building on remote machine '%s'", m.storeUri);
|
||||
debug("considering building on remote machine '%s'", m.storeUri.render());
|
||||
|
||||
if (m.enabled &&
|
||||
m.systemSupported(neededSystem) &&
|
||||
@@ -233,7 +233,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
|
||||
try {
|
||||
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri));
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri.render()));
|
||||
|
||||
sshStore = bestMachine->openStore();
|
||||
sshStore->connect();
|
||||
@@ -242,7 +242,7 @@ static int main_build_remote(int argc, char * * argv)
|
||||
} catch (std::exception & e) {
|
||||
auto msg = chomp(drainFD(5, false));
|
||||
printError("cannot build on '%s': %s%s",
|
||||
bestMachine->storeUri, e.what(),
|
||||
bestMachine->storeUri.render(), e.what(),
|
||||
msg.empty() ? "" : ": " + msg);
|
||||
bestMachine->enabled = false;
|
||||
continue;
|
||||
@@ -257,15 +257,15 @@ connected:
|
||||
|
||||
assert(sshStore);
|
||||
|
||||
std::cerr << "# accept\n" << storeUri << "\n";
|
||||
std::cerr << "# accept\n" << storeUri.render() << "\n";
|
||||
|
||||
auto inputs = readStrings<PathSet>(source);
|
||||
auto wantedOutputs = readStrings<StringSet>(source);
|
||||
|
||||
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri) + ".upload-lock", true);
|
||||
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri.render()) + ".upload-lock", true);
|
||||
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("waiting for the upload lock to '%s'", storeUri));
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("waiting for the upload lock to '%s'", storeUri.render()));
|
||||
|
||||
auto old = signal(SIGALRM, handleAlarm);
|
||||
alarm(15 * 60);
|
||||
@@ -278,7 +278,7 @@ connected:
|
||||
auto substitute = settings.buildersUseSubstitutes ? Substitute : NoSubstitute;
|
||||
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri));
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri.render()));
|
||||
copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute);
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ connected:
|
||||
optResult = sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv);
|
||||
auto & result = *optResult;
|
||||
if (!result.success())
|
||||
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
||||
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri.render(), result.errorMsg);
|
||||
} else {
|
||||
copyClosure(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute);
|
||||
auto res = sshStore->buildPathsWithResults({
|
||||
@@ -359,7 +359,7 @@ connected:
|
||||
}
|
||||
|
||||
if (!missingPaths.empty()) {
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri.render()));
|
||||
if (auto localStore = store.dynamic_pointer_cast<LocalStore>())
|
||||
for (auto & path : missingPaths)
|
||||
localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */
|
||||
|
||||
@@ -75,28 +75,32 @@ CopyCommand::CopyCommand()
|
||||
.longName = "from",
|
||||
.description = "URL of the source Nix store.",
|
||||
.labels = {"store-uri"},
|
||||
.handler = {&srcUri},
|
||||
.handler = {[&](std::string storeUri) {
|
||||
srcUri = StoreReference::parse(storeUri);
|
||||
}},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "to",
|
||||
.description = "URL of the destination Nix store.",
|
||||
.labels = {"store-uri"},
|
||||
.handler = {&dstUri},
|
||||
.handler = {[&](std::string storeUri) {
|
||||
dstUri = StoreReference::parse(storeUri);
|
||||
}},
|
||||
});
|
||||
}
|
||||
|
||||
ref<Store> CopyCommand::createStore()
|
||||
{
|
||||
return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri);
|
||||
return !srcUri ? StoreCommand::createStore() : openStore(*srcUri);
|
||||
}
|
||||
|
||||
ref<Store> CopyCommand::getDstStore()
|
||||
{
|
||||
if (srcUri.empty() && dstUri.empty())
|
||||
if (!srcUri && !dstUri)
|
||||
throw UsageError("you must pass '--from' and/or '--to'");
|
||||
|
||||
return dstUri.empty() ? openStore() : openStore(dstUri);
|
||||
return !dstUri ? openStore() : openStore(*dstUri);
|
||||
}
|
||||
|
||||
EvalCommand::EvalCommand()
|
||||
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
*/
|
||||
struct CopyCommand : virtual StoreCommand
|
||||
{
|
||||
std::string srcUri, dstUri;
|
||||
std::optional<StoreReference> srcUri, dstUri;
|
||||
|
||||
CopyCommand();
|
||||
|
||||
|
||||
@@ -164,7 +164,9 @@ MixEvalArgs::MixEvalArgs()
|
||||
)",
|
||||
.category = category,
|
||||
.labels = {"store-url"},
|
||||
.handler = {&evalStoreUrl},
|
||||
.handler = {[&](std::string s) {
|
||||
evalStoreUrl = StoreReference::parse(s);
|
||||
}},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "canon-path.hh"
|
||||
#include "common-args.hh"
|
||||
#include "search-path.hh"
|
||||
#include "store-reference.hh"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@@ -25,7 +26,7 @@ struct MixEvalArgs : virtual Args, virtual MixRepair
|
||||
|
||||
LookupPath lookupPath;
|
||||
|
||||
std::optional<std::string> evalStoreUrl;
|
||||
std::optional<StoreReference> evalStoreUrl;
|
||||
|
||||
private:
|
||||
struct AutoArgExpr { std::string expr; };
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "url.hh"
|
||||
#include "registry.hh"
|
||||
#include "build-result.hh"
|
||||
#include "fs-input-accessor.hh"
|
||||
|
||||
#include <regex>
|
||||
#include <queue>
|
||||
@@ -147,7 +146,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||
.category = category,
|
||||
.labels = {"flake-lock-path"},
|
||||
.handler = {[&](std::string lockFilePath) {
|
||||
lockFlags.referenceLockFilePath = getUnfilteredRootPath(CanonPath(absPath(lockFilePath)));
|
||||
lockFlags.referenceLockFilePath = {getFSSourceAccessor(), CanonPath(absPath(lockFilePath))};
|
||||
}},
|
||||
.completer = completePath
|
||||
});
|
||||
@@ -443,13 +442,10 @@ ref<eval_cache::EvalCache> openEvalCache(
|
||||
EvalState & state,
|
||||
std::shared_ptr<flake::LockedFlake> lockedFlake)
|
||||
{
|
||||
auto fingerprint = lockedFlake->getFingerprint(state.store);
|
||||
return make_ref<nix::eval_cache::EvalCache>(
|
||||
evalSettings.useEvalCache && evalSettings.pureEval
|
||||
? fingerprint
|
||||
: std::nullopt,
|
||||
state,
|
||||
[&state, lockedFlake]()
|
||||
auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval
|
||||
? lockedFlake->getFingerprint(state.store)
|
||||
: std::nullopt;
|
||||
auto rootLoader = [&state, lockedFlake]()
|
||||
{
|
||||
/* For testing whether the evaluation cache is
|
||||
complete. */
|
||||
@@ -465,7 +461,17 @@ ref<eval_cache::EvalCache> openEvalCache(
|
||||
assert(aOutputs);
|
||||
|
||||
return aOutputs->value;
|
||||
});
|
||||
};
|
||||
|
||||
if (fingerprint) {
|
||||
auto search = state.evalCaches.find(fingerprint.value());
|
||||
if (search == state.evalCaches.end()) {
|
||||
search = state.evalCaches.emplace(fingerprint.value(), make_ref<nix::eval_cache::EvalCache>(fingerprint, state, rootLoader)).first;
|
||||
}
|
||||
return search->second;
|
||||
} else {
|
||||
return make_ref<nix::eval_cache::EvalCache>(std::nullopt, state, rootLoader);
|
||||
}
|
||||
}
|
||||
|
||||
Installables SourceExprCommand::parseInstallables(
|
||||
@@ -595,6 +601,37 @@ std::vector<BuiltPathWithResult> Installable::build(
|
||||
return res;
|
||||
}
|
||||
|
||||
static void throwBuildErrors(
|
||||
std::vector<KeyedBuildResult> & buildResults,
|
||||
const Store & store)
|
||||
{
|
||||
std::vector<KeyedBuildResult> failed;
|
||||
for (auto & buildResult : buildResults) {
|
||||
if (!buildResult.success()) {
|
||||
failed.push_back(buildResult);
|
||||
}
|
||||
}
|
||||
|
||||
auto failedResult = failed.begin();
|
||||
if (failedResult != failed.end()) {
|
||||
if (failed.size() == 1) {
|
||||
failedResult->rethrow();
|
||||
} else {
|
||||
StringSet failedPaths;
|
||||
for (; failedResult != failed.end(); failedResult++) {
|
||||
if (!failedResult->errorMsg.empty()) {
|
||||
logError(ErrorInfo{
|
||||
.level = lvlError,
|
||||
.msg = failedResult->errorMsg,
|
||||
});
|
||||
}
|
||||
failedPaths.insert(failedResult->path.to_string(store));
|
||||
}
|
||||
throw Error("build of %s failed", concatStringsSep(", ", quoteStrings(failedPaths)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build2(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
@@ -656,10 +693,9 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
|
||||
if (settings.printMissing)
|
||||
printMissing(store, pathsToBuild, lvlInfo);
|
||||
|
||||
for (auto & buildResult : store->buildPathsWithResults(pathsToBuild, bMode, evalStore)) {
|
||||
if (!buildResult.success())
|
||||
buildResult.rethrow();
|
||||
|
||||
auto buildResults = store->buildPathsWithResults(pathsToBuild, bMode, evalStore);
|
||||
throwBuildErrors(buildResults, *store);
|
||||
for (auto & buildResult : buildResults) {
|
||||
for (auto & aux : backmap[buildResult.path]) {
|
||||
std::visit(overloaded {
|
||||
[&](const DerivedPath::Built & bfd) {
|
||||
|
||||
@@ -81,9 +81,15 @@ Args::Flag fileIngestionMethod(FileIngestionMethod * method)
|
||||
How to compute the hash of the input.
|
||||
One of:
|
||||
|
||||
- `nar` (the default): Serialises the input as an archive (following the [_Nix Archive Format_](https://edolstra.github.io/pubs/phd-thesis.pdf#page=101)) and passes that to the hash function.
|
||||
- `nar` (the default):
|
||||
Serialises the input as a
|
||||
[Nix Archive](@docroot@/store/file-system-object/content-address.md#serial-nix-archive)
|
||||
and passes that to the hash function.
|
||||
|
||||
- `flat`: Assumes that the input is a single file and directly passes it to the hash function;
|
||||
- `flat`:
|
||||
Assumes that the input is a single file and
|
||||
[directly passes](@docroot@/store/file-system-object/content-address.md#serial-flat)
|
||||
it to the hash function.
|
||||
)",
|
||||
.labels = {"file-ingestion-method"},
|
||||
.handler = {[method](std::string s) {
|
||||
@@ -101,15 +107,23 @@ Args::Flag contentAddressMethod(ContentAddressMethod * method)
|
||||
How to compute the content-address of the store object.
|
||||
One of:
|
||||
|
||||
- `nar` (the default): Serialises the input as an archive (following the [_Nix Archive Format_](https://edolstra.github.io/pubs/phd-thesis.pdf#page=101)) and passes that to the hash function.
|
||||
- [`nar`](@docroot@/store/store-object/content-address.md#method-nix-archive)
|
||||
(the default):
|
||||
Serialises the input as a
|
||||
[Nix Archive](@docroot@/store/file-system-object/content-address.md#serial-nix-archive)
|
||||
and passes that to the hash function.
|
||||
|
||||
- `flat`: Assumes that the input is a single file and directly passes it to the hash function;
|
||||
- [`flat`](@docroot@/store/store-object/content-address.md#method-flat):
|
||||
Assumes that the input is a single file and
|
||||
[directly passes](@docroot@/store/file-system-object/content-address.md#serial-flat)
|
||||
it to the hash function.
|
||||
|
||||
- `text`: Like `flat`, but used for
|
||||
[derivations](@docroot@/glossary.md#store-derivation) serialized in store object and
|
||||
- [`text`](@docroot@/store/store-object/content-address.md#method-text):
|
||||
Like `flat`, but used for
|
||||
[derivations](@docroot@/glossary.md#store-derivation) serialized in store object and
|
||||
[`builtins.toFile`](@docroot@/language/builtins.html#builtins-toFile).
|
||||
For advanced use-cases only;
|
||||
for regular usage prefer `nar` and `flat.
|
||||
for regular usage prefer `nar` and `flat`.
|
||||
)",
|
||||
.labels = {"content-address-method"},
|
||||
.handler = {[method](std::string s) {
|
||||
|
||||
48
src/libcmd/network-proxy.cc
Normal file
48
src/libcmd/network-proxy.cc
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "network-proxy.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "environment-variables.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
static const StringSet lowercaseVariables{"http_proxy", "https_proxy", "ftp_proxy", "all_proxy", "no_proxy"};
|
||||
|
||||
static StringSet getAllVariables()
|
||||
{
|
||||
StringSet variables = lowercaseVariables;
|
||||
for (const auto & variable : lowercaseVariables) {
|
||||
variables.insert(boost::to_upper_copy(variable));
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
|
||||
const StringSet networkProxyVariables = getAllVariables();
|
||||
|
||||
static StringSet getExcludingNoProxyVariables()
|
||||
{
|
||||
static const StringSet excludeVariables{"no_proxy", "NO_PROXY"};
|
||||
StringSet variables;
|
||||
std::set_difference(
|
||||
networkProxyVariables.begin(),
|
||||
networkProxyVariables.end(),
|
||||
excludeVariables.begin(),
|
||||
excludeVariables.end(),
|
||||
std::inserter(variables, variables.begin()));
|
||||
return variables;
|
||||
}
|
||||
|
||||
static const StringSet excludingNoProxyVariables = getExcludingNoProxyVariables();
|
||||
|
||||
bool haveNetworkProxyConnection()
|
||||
{
|
||||
for (const auto & variable : excludingNoProxyVariables) {
|
||||
if (getEnv(variable).has_value()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
22
src/libcmd/network-proxy.hh
Normal file
22
src/libcmd/network-proxy.hh
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "types.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* Environment variables relating to network proxying. These are used by
|
||||
* a few misc commands.
|
||||
*
|
||||
* See the Environment section of https://curl.se/docs/manpage.html for details.
|
||||
*/
|
||||
extern const StringSet networkProxyVariables;
|
||||
|
||||
/**
|
||||
* Heuristically check if there is a proxy connection by checking for defined
|
||||
* proxy variables.
|
||||
*/
|
||||
bool haveNetworkProxyConnection();
|
||||
|
||||
}
|
||||
@@ -259,11 +259,13 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||
try {
|
||||
auto dir = std::string(cur, 0, slash);
|
||||
auto prefix2 = std::string(cur, slash + 1);
|
||||
for (auto & entry : readDirectory(dir == "" ? "/" : dir)) {
|
||||
if (entry.name[0] != '.' && hasPrefix(entry.name, prefix2))
|
||||
completions.insert(prev + dir + "/" + entry.name);
|
||||
for (auto & entry : std::filesystem::directory_iterator{dir == "" ? "/" : dir}) {
|
||||
auto name = entry.path().filename().string();
|
||||
if (name[0] != '.' && hasPrefix(name, prefix2))
|
||||
completions.insert(prev + entry.path().string());
|
||||
}
|
||||
} catch (Error &) {
|
||||
} catch (std::filesystem::filesystem_error &) {
|
||||
}
|
||||
} else if ((dot = cur.rfind('.')) == std::string::npos) {
|
||||
/* This is a variable name; look it up in the current scope. */
|
||||
@@ -506,6 +508,10 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
auto editor = args.front();
|
||||
args.pop_front();
|
||||
|
||||
// avoid garbling the editor with the progress bar
|
||||
logger->pause();
|
||||
Finally resume([&]() { logger->resume(); });
|
||||
|
||||
// runProgram redirects stdout to a StringSink,
|
||||
// using runProgram2 to allow editors to display their UI
|
||||
runProgram2(RunOptions { .program = editor, .lookupPath = true, .args = args });
|
||||
|
||||
@@ -3,25 +3,7 @@
|
||||
/** @defgroup libexpr libexpr
|
||||
* @brief Bindings to the Nix language evaluator
|
||||
*
|
||||
* Example (without error handling):
|
||||
* @code{.c}
|
||||
* int main() {
|
||||
* nix_libexpr_init(NULL);
|
||||
*
|
||||
* Store* store = nix_store_open(NULL, "dummy", NULL);
|
||||
* EvalState* state = nix_state_create(NULL, NULL, store); // empty nix path
|
||||
* Value *value = nix_alloc_value(NULL, state);
|
||||
*
|
||||
* nix_expr_eval_from_string(NULL, state, "builtins.nixVersion", ".", value);
|
||||
* nix_value_force(NULL, state, value);
|
||||
* printf("nix version: %s\n", nix_get_string(NULL, value));
|
||||
*
|
||||
* nix_gc_decref(NULL, value);
|
||||
* nix_state_free(state);
|
||||
* nix_store_free(store);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* See *[Embedding the Nix Evaluator](@ref nix_evaluator_example)* for an example.
|
||||
* @{
|
||||
*/
|
||||
/** @file
|
||||
@@ -140,7 +122,7 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, Value *
|
||||
* @brief Create a new Nix language evaluator state.
|
||||
*
|
||||
* @param[out] context Optional, stores error information
|
||||
* @param[in] lookupPath Array of strings corresponding to entries in NIX_PATH.
|
||||
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
||||
* @param[in] store The Nix store to use.
|
||||
* @return A new Nix state or NULL on failure.
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ void nix_set_string_return(nix_string_return * str, const char * c);
|
||||
* Print to the nix_printer
|
||||
*
|
||||
* @param[out] context Optional, stores error information
|
||||
* @param printer The nix_printer to print to
|
||||
* @param[out] printer The nix_printer to print to
|
||||
* @param[in] str The string to print
|
||||
* @returns NIX_OK if everything worked
|
||||
*/
|
||||
@@ -136,7 +136,7 @@ typedef struct NixCExternalValueDesc
|
||||
* or setting it to the empty string, will make the conversion throw an error.
|
||||
*/
|
||||
void (*printValueAsJSON)(
|
||||
void * self, EvalState *, bool strict, nix_string_context * c, bool copyToStore, nix_string_return * res);
|
||||
void * self, EvalState * state, bool strict, nix_string_context * c, bool copyToStore, nix_string_return * res);
|
||||
/**
|
||||
* @brief Convert the external value to XML
|
||||
*
|
||||
@@ -155,7 +155,7 @@ typedef struct NixCExternalValueDesc
|
||||
*/
|
||||
void (*printValueAsXML)(
|
||||
void * self,
|
||||
EvalState *,
|
||||
EvalState * state,
|
||||
int strict,
|
||||
int location,
|
||||
void * doc,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
# include "gc_cpp.h"
|
||||
#endif
|
||||
|
||||
// Helper function to throw an exception if value is null
|
||||
// Internal helper functions to check [in] and [out] `Value *` parameters
|
||||
static const nix::Value & check_value_not_null(const Value * value)
|
||||
{
|
||||
if (!value) {
|
||||
@@ -37,6 +37,33 @@ static nix::Value & check_value_not_null(Value * value)
|
||||
return *((nix::Value *) value);
|
||||
}
|
||||
|
||||
static const nix::Value & check_value_in(const Value * value)
|
||||
{
|
||||
auto & v = check_value_not_null(value);
|
||||
if (!v.isValid()) {
|
||||
throw std::runtime_error("Uninitialized Value");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static nix::Value & check_value_in(Value * value)
|
||||
{
|
||||
auto & v = check_value_not_null(value);
|
||||
if (!v.isValid()) {
|
||||
throw std::runtime_error("Uninitialized Value");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static nix::Value & check_value_out(Value * value)
|
||||
{
|
||||
auto & v = check_value_not_null(value);
|
||||
if (v.isValid()) {
|
||||
throw std::runtime_error("Value already initialized. Variables are immutable");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert calls from nix into C API.
|
||||
*
|
||||
@@ -111,7 +138,7 @@ ValueType nix_get_type(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
using namespace nix;
|
||||
switch (v.type()) {
|
||||
case nThunk:
|
||||
@@ -147,7 +174,7 @@ const char * nix_get_typename(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
auto s = nix::showType(v);
|
||||
return strdup(s.c_str());
|
||||
}
|
||||
@@ -159,7 +186,7 @@ bool nix_get_bool(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nBool);
|
||||
return v.boolean();
|
||||
}
|
||||
@@ -171,7 +198,7 @@ nix_err nix_get_string(nix_c_context * context, const Value * value, nix_get_str
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nString);
|
||||
call_nix_get_string_callback(v.c_str(), callback, user_data);
|
||||
}
|
||||
@@ -183,7 +210,7 @@ const char * nix_get_path_string(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nPath);
|
||||
// NOTE (from @yorickvP)
|
||||
// v._path.path should work but may not be how Eelco intended it.
|
||||
@@ -202,7 +229,7 @@ unsigned int nix_get_list_size(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nList);
|
||||
return v.listSize();
|
||||
}
|
||||
@@ -214,7 +241,7 @@ unsigned int nix_get_attrs_size(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nAttrs);
|
||||
return v.attrs()->size();
|
||||
}
|
||||
@@ -226,7 +253,7 @@ double nix_get_float(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nFloat);
|
||||
return v.fpoint();
|
||||
}
|
||||
@@ -238,7 +265,7 @@ int64_t nix_get_int(nix_c_context * context, const Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nInt);
|
||||
return v.integer();
|
||||
}
|
||||
@@ -250,7 +277,7 @@ ExternalValue * nix_get_external(nix_c_context * context, Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
assert(v.type() == nix::nExternal);
|
||||
return (ExternalValue *) v.external();
|
||||
}
|
||||
@@ -262,7 +289,7 @@ Value * nix_get_list_byidx(nix_c_context * context, const Value * value, EvalSta
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nList);
|
||||
auto * p = v.listElems()[ix];
|
||||
nix_gc_incref(nullptr, p);
|
||||
@@ -278,7 +305,7 @@ Value * nix_get_attr_byname(nix_c_context * context, const Value * value, EvalSt
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nAttrs);
|
||||
nix::Symbol s = state->state.symbols.create(name);
|
||||
auto attr = v.attrs()->get(s);
|
||||
@@ -298,7 +325,7 @@ bool nix_has_attr_byname(nix_c_context * context, const Value * value, EvalState
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
assert(v.type() == nix::nAttrs);
|
||||
nix::Symbol s = state->state.symbols.create(name);
|
||||
auto attr = v.attrs()->get(s);
|
||||
@@ -315,7 +342,7 @@ nix_get_attr_byidx(nix_c_context * context, const Value * value, EvalState * sta
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
const nix::Attr & a = (*v.attrs())[i];
|
||||
*name = ((const std::string &) (state->state.symbols[a.name])).c_str();
|
||||
nix_gc_incref(nullptr, a.value);
|
||||
@@ -330,7 +357,7 @@ const char * nix_get_attr_name_byidx(nix_c_context * context, const Value * valu
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
const nix::Attr & a = (*v.attrs())[i];
|
||||
return ((const std::string &) (state->state.symbols[a.name])).c_str();
|
||||
}
|
||||
@@ -342,7 +369,7 @@ nix_err nix_init_bool(nix_c_context * context, Value * value, bool b)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkBool(b);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -354,7 +381,7 @@ nix_err nix_init_string(nix_c_context * context, Value * value, const char * str
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkString(std::string_view(str));
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -365,7 +392,7 @@ nix_err nix_init_path_string(nix_c_context * context, EvalState * s, Value * val
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkPath(s->state.rootPath(nix::CanonPath(str)));
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -376,7 +403,7 @@ nix_err nix_init_float(nix_c_context * context, Value * value, double d)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkFloat(d);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -387,7 +414,7 @@ nix_err nix_init_int(nix_c_context * context, Value * value, int64_t i)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkInt(i);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -398,7 +425,7 @@ nix_err nix_init_null(nix_c_context * context, Value * value)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkNull();
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -422,7 +449,7 @@ nix_err nix_init_external(nix_c_context * context, Value * value, ExternalValue
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
auto r = (nix::ExternalValueBase *) val;
|
||||
v.mkExternal(r);
|
||||
}
|
||||
@@ -469,7 +496,7 @@ nix_err nix_make_list(nix_c_context * context, ListBuilder * list_builder, Value
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkList(list_builder->builder);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -480,19 +507,19 @@ nix_err nix_init_primop(nix_c_context * context, Value * value, PrimOp * p)
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkPrimOp((nix::PrimOp *) p);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err nix_copy_value(nix_c_context * context, Value * value, Value * source)
|
||||
nix_err nix_copy_value(nix_c_context * context, Value * value, const Value * source)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & s = check_value_not_null(source);
|
||||
auto & v = check_value_out(value);
|
||||
auto & s = check_value_in(source);
|
||||
v = s;
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -503,7 +530,7 @@ nix_err nix_make_attrs(nix_c_context * context, Value * value, BindingsBuilder *
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_out(value);
|
||||
v.mkAttrs(b->builder);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
@@ -550,7 +577,7 @@ nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * st
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
auto & v = check_value_in(value);
|
||||
nix::NixStringContext stringContext;
|
||||
auto rawStr = state->state.coerceToString(nix::noPos, v, stringContext, "while realising a string").toOwned();
|
||||
nix::StorePathSet storePaths;
|
||||
|
||||
@@ -422,7 +422,7 @@ nix_err nix_init_primop(nix_c_context * context, Value * value, PrimOp * op);
|
||||
* @param[in] source value to copy from
|
||||
* @return error code, NIX_OK on success.
|
||||
*/
|
||||
nix_err nix_copy_value(nix_c_context * context, Value * value, Value * source);
|
||||
nix_err nix_copy_value(nix_c_context * context, Value * value, const Value * source);
|
||||
/**@}*/
|
||||
|
||||
/** @brief Create a bindings builder
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
#include "function-trace.hh"
|
||||
#include "profiles.hh"
|
||||
#include "print.hh"
|
||||
#include "fs-input-accessor.hh"
|
||||
#include "filtering-input-accessor.hh"
|
||||
#include "memory-input-accessor.hh"
|
||||
#include "filtering-source-accessor.hh"
|
||||
#include "memory-source-accessor.hh"
|
||||
#include "signals.hh"
|
||||
#include "gc-small-vector.hh"
|
||||
#include "url.hh"
|
||||
@@ -50,6 +49,7 @@
|
||||
|
||||
#include <gc/gc.h>
|
||||
#include <gc/gc_cpp.h>
|
||||
#include <gc/gc_allocator.h>
|
||||
|
||||
#include <boost/coroutine2/coroutine.hpp>
|
||||
#include <boost/coroutine2/protected_fixedsize_stack.hpp>
|
||||
@@ -342,6 +342,8 @@ void initGC()
|
||||
gcInitialised = true;
|
||||
}
|
||||
|
||||
static constexpr size_t BASE_ENV_SIZE = 128;
|
||||
|
||||
EvalState::EvalState(
|
||||
const LookupPath & _lookupPath,
|
||||
ref<Store> store,
|
||||
@@ -397,16 +399,16 @@ EvalState::EvalState(
|
||||
, emptyBindings(0)
|
||||
, rootFS(
|
||||
evalSettings.restrictEval || evalSettings.pureEval
|
||||
? ref<InputAccessor>(AllowListInputAccessor::create(makeFSInputAccessor(), {},
|
||||
? ref<SourceAccessor>(AllowListSourceAccessor::create(getFSSourceAccessor(), {},
|
||||
[](const CanonPath & path) -> RestrictedPathError {
|
||||
auto modeInformation = evalSettings.pureEval
|
||||
? "in pure evaluation mode (use '--impure' to override)"
|
||||
: "in restricted mode";
|
||||
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
|
||||
}))
|
||||
: makeFSInputAccessor())
|
||||
, corepkgsFS(makeMemoryInputAccessor())
|
||||
, internalFS(makeMemoryInputAccessor())
|
||||
: getFSSourceAccessor())
|
||||
, corepkgsFS(make_ref<MemorySourceAccessor>())
|
||||
, internalFS(make_ref<MemorySourceAccessor>())
|
||||
, derivationInternal{corepkgsFS->addFile(
|
||||
CanonPath("derivation-internal.nix"),
|
||||
#include "primops/derivation.nix.gen.hh"
|
||||
@@ -424,8 +426,11 @@ EvalState::EvalState(
|
||||
#if HAVE_BOEHMGC
|
||||
, valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
|
||||
, env1AllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
|
||||
, baseEnvP(std::allocate_shared<Env *>(traceable_allocator<Env *>(), &allocEnv(BASE_ENV_SIZE)))
|
||||
, baseEnv(**baseEnvP)
|
||||
#else
|
||||
, baseEnv(allocEnv(BASE_ENV_SIZE))
|
||||
#endif
|
||||
, baseEnv(allocEnv(128))
|
||||
, staticBaseEnv{std::make_shared<StaticEnv>(nullptr, nullptr)}
|
||||
{
|
||||
corepkgsFS->setPathDisplay("<nix", ">");
|
||||
@@ -455,7 +460,7 @@ EvalState::EvalState(
|
||||
}
|
||||
|
||||
/* Allow access to all paths in the search path. */
|
||||
if (rootFS.dynamic_pointer_cast<AllowListInputAccessor>())
|
||||
if (rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
|
||||
for (auto & i : lookupPath.elements)
|
||||
resolveLookupPathPath(i.path, true);
|
||||
|
||||
@@ -475,13 +480,13 @@ EvalState::~EvalState()
|
||||
|
||||
void EvalState::allowPath(const Path & path)
|
||||
{
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListInputAccessor>())
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
|
||||
rootFS2->allowPrefix(CanonPath(path));
|
||||
}
|
||||
|
||||
void EvalState::allowPath(const StorePath & storePath)
|
||||
{
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListInputAccessor>())
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
|
||||
rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath)));
|
||||
}
|
||||
|
||||
@@ -535,13 +540,13 @@ void EvalState::checkURI(const std::string & uri)
|
||||
/* If the URI is a path, then check it against allowedPaths as
|
||||
well. */
|
||||
if (hasPrefix(uri, "/")) {
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListInputAccessor>())
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
|
||||
rootFS2->checkAccess(CanonPath(uri));
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasPrefix(uri, "file://")) {
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListInputAccessor>())
|
||||
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
|
||||
rootFS2->checkAccess(CanonPath(uri.substr(7)));
|
||||
return;
|
||||
}
|
||||
@@ -2760,12 +2765,12 @@ SourcePath resolveExprPath(SourcePath path)
|
||||
if (++followCount >= maxFollow)
|
||||
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
|
||||
auto p = path.parent().resolveSymlinks() / path.baseName();
|
||||
if (p.lstat().type != InputAccessor::tSymlink) break;
|
||||
if (p.lstat().type != SourceAccessor::tSymlink) break;
|
||||
path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))};
|
||||
}
|
||||
|
||||
/* If `path' refers to a directory, append `/default.nix'. */
|
||||
if (path.resolveSymlinks().lstat().type == InputAccessor::tDirectory)
|
||||
if (path.resolveSymlinks().lstat().type == SourceAccessor::tDirectory)
|
||||
return path / "default.nix";
|
||||
|
||||
return path;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "symbol-table.hh"
|
||||
#include "config.hh"
|
||||
#include "experimental-features.hh"
|
||||
#include "input-accessor.hh"
|
||||
#include "source-accessor.hh"
|
||||
#include "search-path.hh"
|
||||
#include "repl-exit-status.hh"
|
||||
|
||||
@@ -33,7 +33,10 @@ class EvalState;
|
||||
class StorePath;
|
||||
struct SingleDerivedPath;
|
||||
enum RepairFlag : bool;
|
||||
struct MemoryInputAccessor;
|
||||
struct MemorySourceAccessor;
|
||||
namespace eval_cache {
|
||||
class EvalCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -226,18 +229,18 @@ public:
|
||||
/**
|
||||
* The accessor for the root filesystem.
|
||||
*/
|
||||
const ref<InputAccessor> rootFS;
|
||||
const ref<SourceAccessor> rootFS;
|
||||
|
||||
/**
|
||||
* The in-memory filesystem for <nix/...> paths.
|
||||
*/
|
||||
const ref<MemoryInputAccessor> corepkgsFS;
|
||||
const ref<MemorySourceAccessor> corepkgsFS;
|
||||
|
||||
/**
|
||||
* In-memory filesystem for internal, non-user-callable Nix
|
||||
* expressions like call-flake.nix.
|
||||
*/
|
||||
const ref<MemoryInputAccessor> internalFS;
|
||||
const ref<MemorySourceAccessor> internalFS;
|
||||
|
||||
const SourcePath derivationInternal;
|
||||
|
||||
@@ -282,6 +285,11 @@ public:
|
||||
return *new EvalErrorBuilder<T>(*this, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* A cache for evaluation caches, so as to reuse the same root value if possible
|
||||
*/
|
||||
std::map<const Hash, ref<eval_cache::EvalCache>> evalCaches;
|
||||
|
||||
private:
|
||||
|
||||
/* Cache for calls to addToStore(); maps source paths to the store
|
||||
@@ -539,6 +547,11 @@ public:
|
||||
*/
|
||||
SingleDerivedPath coerceToSingleDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx);
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
/** A GC root for the baseEnv reference. */
|
||||
std::shared_ptr<Env *> baseEnvP;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,11 +28,8 @@ derivation ({
|
||||
# No need to double the amount of network traffic
|
||||
preferLocalBuild = true;
|
||||
|
||||
# This attribute does nothing; it's here to avoid changing evaluation results.
|
||||
impureEnvVars = [
|
||||
# We borrow these environment variables from the caller to allow
|
||||
# easy proxy configuration. This is impure, but a fixed-output
|
||||
# derivation like fetchurl is allowed to do so since its result is
|
||||
# by definition pure.
|
||||
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
|
||||
];
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
lockFileStr:
|
||||
|
||||
# A mapping of lock file node IDs to { sourceInfo, subdir } attrsets,
|
||||
# with sourceInfo.outPath providing an InputAccessor to a previously
|
||||
# with sourceInfo.outPath providing an SourceAccessor to a previously
|
||||
# fetched tree. This is necessary for possibly unlocked inputs, in
|
||||
# particular the root input, but also --override-inputs pointing to
|
||||
# unlocked trees.
|
||||
|
||||
@@ -32,7 +32,7 @@ static void writeTrustedList(const TrustedList & trustedList)
|
||||
|
||||
void ConfigFile::apply()
|
||||
{
|
||||
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lockfile-summary"};
|
||||
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lock-file-summary", "commit-lockfile-summary"};
|
||||
|
||||
for (auto & [name, value] : settings) {
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "terminal.hh"
|
||||
#include "flake.hh"
|
||||
#include "eval.hh"
|
||||
|
||||
@@ -92,10 +92,10 @@ struct ExprString : Expr
|
||||
|
||||
struct ExprPath : Expr
|
||||
{
|
||||
ref<InputAccessor> accessor;
|
||||
ref<SourceAccessor> accessor;
|
||||
std::string s;
|
||||
Value v;
|
||||
ExprPath(ref<InputAccessor> accessor, std::string s) : accessor(accessor), s(std::move(s))
|
||||
ExprPath(ref<SourceAccessor> accessor, std::string s) : accessor(accessor), s(std::move(s))
|
||||
{
|
||||
v.mkPath(&*accessor, this->s.c_str());
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user