diff --git a/nix-rust/Cargo.lock b/nix-rust/Cargo.lock index a2bfb03f2..6e5ecf45d 100644 --- a/nix-rust/Cargo.lock +++ b/nix-rust/Cargo.lock @@ -33,15 +33,6 @@ name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "c2-chacha" version = "0.2.3" @@ -63,63 +54,6 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-channel" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "filetime" version = "0.2.8" @@ -141,81 +75,6 @@ name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-core-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-io-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-util-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "getrandom" version = "0.1.13" @@ -226,234 +85,31 @@ dependencies = [ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "h2" -version = "0.2.0-alpha.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hermit-abi" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hex" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "http-body" -version = "0.2.0-alpha.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "httparse" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hyper" -version = "0.13.0-alpha.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-make 0.3.0-alpha.2a (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "indexmap" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lock_api" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio-uds" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "net2" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nix-rust" version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -464,75 +120,11 @@ dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num_cpus" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-project" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-utils" -version = "0.1.0-alpha.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ppv-lite86" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "proc-macro2" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proptest" version = "0.9.4" @@ -557,14 +149,6 @@ name = "quick-error" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quote" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.6.5" @@ -724,14 +308,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rusty-fork" version = "0.2.2" @@ -743,60 +319,6 @@ dependencies = [ "wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smallvec" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "string" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tar" version = "0.4.26" @@ -821,188 +343,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "time" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-macros" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-net" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.3.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tower-make" -version = "0.3.0-alpha.2a" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tower-service" -version = "0.3.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "tracing" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing-core" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "try-lock" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "wait-timeout" version = "0.2.0" @@ -1011,25 +351,11 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.3.8" @@ -1039,11 +365,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1054,15 +375,6 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "xattr" version = "0.2.2" @@ -1078,63 +390,20 @@ dependencies = [ "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" -"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" -"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" -"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" -"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" -"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" -"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" -"checksum h2 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f107db1419ef8271686187b1a5d47c6431af4a7f4d98b495e7b7fc249bb0a78" -"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -"checksum http-body 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f3aef6f3de2bd8585f5b366f3f550b5774500b4764d00cf00f903c95749eec3" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2d05aa523087ac0b9d8b93dd80d5d482a697308ed3b0dca7b0667511a7fa7cdc" -"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" -"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" -"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" -"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" -"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -1153,41 +422,12 @@ dependencies = [ "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusty-fork 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "b3196bfbffbba3e57481b6ea32249fbaf590396a52505a2615adbb79d9d826d3" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f17f5d6ab0f35c1506678b28fb1798bdf74fcb737e9843c7b17b73e426eba38" -"checksum tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9f5d22fd1e84bd4045d28813491cb7d7caae34d45c80517c2213f09a85e8787a" -"checksum tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8" -"checksum tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "112784d5543df30660b04a72ca423bfbd90e8bb32f94dcf610f15401218b22c5" -"checksum tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "86b616374bcdadd95974e1f0dfca07dc913f1163c53840c0d664aca35114964e" -"checksum tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a441682cd32f3559383112c4a7f372f5c9fa1950c5cf8c8dd05274a2ce8c2654" -"checksum tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2" -"checksum tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b97c1587fe71018eb245a4a9daa13a5a3b681bbc1f7fdadfe24720e141472c13" -"checksum tower-make 0.3.0-alpha.2a (registry+https://github.com/rust-lang/crates.io-index)" = "316d47dd40cde4ac5d88110eaf9a10a4e2a68612d9c056cd2aa24e37dcb484cd" -"checksum tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "63ff37396cd966ce43bea418bfa339f802857495f797dafa00bea5b7221ebdfa" -"checksum tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ff4e4f59e752cb3beb5b61c6d5e11191c7946231ba84faec2902c9efdd8691c5" -"checksum tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a4263b12c3d3c403274493eb805966093b53214124796552d674ca1dd5d27c2b" -"checksum tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bc913647c520c959b6d21e35ed8fa6984971deca9f0a2fcb8c51207e0c56af1d" -"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" diff --git a/nix-rust/Cargo.toml b/nix-rust/Cargo.toml index cd5c545cc..cd388bed6 100644 --- a/nix-rust/Cargo.toml +++ b/nix-rust/Cargo.toml @@ -11,12 +11,12 @@ crate-type = ["cdylib"] [dependencies] tar = "0.4" libc = "0.2" -futures-preview = { version = "=0.3.0-alpha.19" } -hyper = "0.13.0-alpha.4" -http = "0.1" -tokio = { version = "0.2.0-alpha.6", default-features = false, features = ["rt-full"] } +#futures-preview = { version = "=0.3.0-alpha.19" } +#hyper = "0.13.0-alpha.4" +#http = "0.1" +#tokio = { version = "0.2.0-alpha.6", default-features = false, features = ["rt-full"] } lazy_static = "1.4" -byteorder = "1.3" +#byteorder = "1.3" [dev-dependencies] hex = "0.3" diff --git a/nix-rust/local.mk b/nix-rust/local.mk index 51116b0b3..1e006e500 100644 --- a/nix-rust/local.mk +++ b/nix-rust/local.mk @@ -37,7 +37,9 @@ clean: clean-rust clean-rust: $(suppress) rm -rfv nix-rust/target +ifneq ($(OS), Darwin) check: rust-tests rust-tests: - cd nix-rust && CARGO_HOME=$$(if [[ -d vendor ]]; then echo vendor; fi) RUSTC_BOOTSTRAP=1 cargo test --release $$(if [[ -d vendor ]]; then echo -Z offline; fi) + cd nix-rust && CARGO_HOME=$$(if [[ -d vendor ]]; then echo vendor; fi) cargo test --release $$(if [[ -d vendor ]]; then echo --offline; fi) +endif diff --git a/nix-rust/src/c.rs b/nix-rust/src/c.rs index 42ecb9866..4c1724eb3 100644 --- a/nix-rust/src/c.rs +++ b/nix-rust/src/c.rs @@ -1,6 +1,7 @@ use super::{ error, foreign::{self, CBox}, + store::StorePath, util, }; @@ -13,43 +14,72 @@ pub extern "C" fn unpack_tarfile( } #[no_mangle] -pub extern "C" fn rust_test() { - use crate::store::{self, Store}; - use std::path::Path; - use tokio::runtime::Runtime; - - let fut = async move { - let store: Box = Box::new(store::BinaryCacheStore::new( - "http://cache.nixos.org".to_string(), - )); - - let path = store - .parse_store_path(&Path::new( - "/nix/store/7h7qgvs4kgzsn8a6rb273saxyqh4jxlz-konsole-18.12.3", - )) - .unwrap(); - - /* - let info = store.query_path_info(&path).await.unwrap(); - - eprintln!("INFO = {:?}", info); - */ - - let closure = store - .compute_path_closure(vec![path].into_iter().collect()) - .await - .unwrap(); - - eprintln!("CLOSURE = {:?}", closure.len()); - }; - - let rt = Runtime::new().unwrap(); - - rt.block_on(fut); - - /* - let file = std::fs::File::open("test.nar").unwrap(); - - crate::nar::parse(&mut std::io::BufReader::new(file)).unwrap(); - */ +pub unsafe extern "C" fn ffi_String_new(s: &str, out: *mut String) { + // FIXME: check whether 's' is valid UTF-8? + out.write(s.to_string()) +} + +#[no_mangle] +pub unsafe extern "C" fn ffi_String_drop(self_: *mut String) { + std::ptr::drop_in_place(self_); +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_new( + path: &str, + store_dir: &str, +) -> Result { + StorePath::new(std::path::Path::new(path), store_dir).map_err(|err| err.into()) +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_new2( + hash: &[u8; crate::store::path::STORE_PATH_HASH_BYTES], + name: &str, +) -> Result { + StorePath::from_parts(*hash, name).map_err(|err| err.into()) +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_fromBaseName( + base_name: &str, +) -> Result { + StorePath::new_from_base_name(base_name).map_err(|err| err.into()) +} + +#[no_mangle] +pub unsafe extern "C" fn ffi_StorePath_drop(self_: *mut StorePath) { + std::ptr::drop_in_place(self_); +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_to_string(self_: &StorePath) -> String { + format!("{}", self_) +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_less_than(a: &StorePath, b: &StorePath) -> bool { + a < b +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_eq(a: &StorePath, b: &StorePath) -> bool { + a == b +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_clone(self_: &StorePath) -> StorePath { + self_.clone() +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_name(self_: &StorePath) -> &str { + self_.name.name() +} + +#[no_mangle] +pub extern "C" fn ffi_StorePath_hash_data( + self_: &StorePath, +) -> &[u8; crate::store::path::STORE_PATH_HASH_BYTES] { + self_.hash.hash() } diff --git a/nix-rust/src/error.rs b/nix-rust/src/error.rs index 28b5c43af..c2ba5d504 100644 --- a/nix-rust/src/error.rs +++ b/nix-rust/src/error.rs @@ -19,6 +19,7 @@ pub enum Error { BadNarField(String), BadExecutableField, IOError(std::io::Error), + #[cfg(unused)] HttpError(hyper::error::Error), Misc(String), Foreign(CppException), @@ -30,6 +31,7 @@ impl From for Error { } } +#[cfg(unused)] impl From for Error { fn from(err: hyper::error::Error) -> Self { Error::HttpError(err) @@ -58,6 +60,7 @@ impl fmt::Display for Error { Error::BadNarField(s) => write!(f, "unrecognized NAR field '{}'", s), Error::BadExecutableField => write!(f, "bad 'executable' field in NAR"), Error::IOError(err) => write!(f, "I/O error: {}", err), + #[cfg(unused)] Error::HttpError(err) => write!(f, "HTTP error: {}", err), Error::Foreign(_) => write!(f, ""), // FIXME Error::Misc(s) => write!(f, "{}", s), diff --git a/nix-rust/src/lib.rs b/nix-rust/src/lib.rs index 4654d4cc3..0c3cf5276 100644 --- a/nix-rust/src/lib.rs +++ b/nix-rust/src/lib.rs @@ -12,6 +12,7 @@ extern crate proptest; mod c; mod error; mod foreign; +#[cfg(unused)] mod nar; mod store; mod util; diff --git a/nix-rust/src/store/mod.rs b/nix-rust/src/store/mod.rs index 85355b594..da972482c 100644 --- a/nix-rust/src/store/mod.rs +++ b/nix-rust/src/store/mod.rs @@ -1,9 +1,17 @@ +pub mod path; + +#[cfg(unused)] mod binary_cache_store; -mod path; +#[cfg(unused)] mod path_info; +#[cfg(unused)] mod store; -pub use binary_cache_store::BinaryCacheStore; pub use path::{StorePath, StorePathHash, StorePathName}; + +#[cfg(unused)] +pub use binary_cache_store::BinaryCacheStore; +#[cfg(unused)] pub use path_info::PathInfo; +#[cfg(unused)] pub use store::Store; diff --git a/nix-rust/src/store/path.rs b/nix-rust/src/store/path.rs index 03307ca7c..3ded5c428 100644 --- a/nix-rust/src/store/path.rs +++ b/nix-rust/src/store/path.rs @@ -23,6 +23,13 @@ impl StorePath { ) } + pub fn from_parts(hash: [u8; STORE_PATH_HASH_BYTES], name: &str) -> Result { + Ok(StorePath { + hash: StorePathHash(hash), + name: StorePathName::new(name)?, + }) + } + pub fn new_from_base_name(base_name: &str) -> Result { if base_name.len() < STORE_PATH_HASH_CHARS + 1 || base_name.as_bytes()[STORE_PATH_HASH_CHARS] != '-' as u8 @@ -43,7 +50,7 @@ impl fmt::Display for StorePath { } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub struct StorePathHash([u8; STORE_PATH_HASH_BYTES]); impl StorePathHash { @@ -55,6 +62,10 @@ impl StorePathHash { bytes.copy_from_slice(&v[0..STORE_PATH_HASH_BYTES]); Ok(Self(bytes)) } + + pub fn hash<'a>(&'a self) -> &'a [u8; STORE_PATH_HASH_BYTES] { + &self.0 + } } impl fmt::Display for StorePathHash { @@ -63,6 +74,21 @@ impl fmt::Display for StorePathHash { } } +impl Ord for StorePathHash { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + // Historically we've sorted store paths by their base32 + // serialization, but our base32 encodes bytes in reverse + // order. So compare them in reverse order as well. + self.0.iter().rev().cmp(other.0.iter().rev()) + } +} + +impl PartialOrd for StorePathHash { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct StorePathName(String); @@ -93,6 +119,10 @@ impl StorePathName { Ok(Self(s.to_string())) } + + pub fn name<'a>(&'a self) -> &'a str { + &self.0 + } } impl fmt::Display for StorePathName { diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs index ce553bb53..fefcd5ae6 100644 --- a/perl/lib/Nix/Store.xs +++ b/perl/lib/Nix/Store.xs @@ -59,7 +59,7 @@ void setVerbosity(int level) int isValidPath(char * path) CODE: try { - RETVAL = store()->isValidPath(path); + RETVAL = store()->isValidPath(store()->parseStorePath(path)); } catch (Error & e) { croak("%s", e.what()); } @@ -70,9 +70,8 @@ int isValidPath(char * path) SV * queryReferences(char * path) PPCODE: try { - PathSet paths = store()->queryPathInfo(path)->references; - for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) - XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0))); + for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->references) + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -81,7 +80,7 @@ SV * queryReferences(char * path) SV * queryPathHash(char * path) PPCODE: try { - auto s = store()->queryPathInfo(path)->narHash.to_string(); + auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); @@ -91,9 +90,9 @@ SV * queryPathHash(char * path) SV * queryDeriver(char * path) PPCODE: try { - auto deriver = store()->queryPathInfo(path)->deriver; - if (deriver == "") XSRETURN_UNDEF; - XPUSHs(sv_2mortal(newSVpv(deriver.c_str(), 0))); + auto info = store()->queryPathInfo(store()->parseStorePath(path)); + if (!info->deriver) XSRETURN_UNDEF; + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -102,18 +101,18 @@ SV * queryDeriver(char * path) SV * queryPathInfo(char * path, int base32) PPCODE: try { - auto info = store()->queryPathInfo(path); - if (info->deriver == "") + auto info = store()->queryPathInfo(store()->parseStorePath(path)); + if (info->deriver) XPUSHs(&PL_sv_undef); else - XPUSHs(sv_2mortal(newSVpv(info->deriver.c_str(), 0))); + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0))); auto s = info->narHash.to_string(base32 ? Base32 : Base16); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); mXPUSHi(info->registrationTime); mXPUSHi(info->narSize); AV * arr = newAV(); - for (PathSet::iterator i = info->references.begin(); i != info->references.end(); ++i) - av_push(arr, newSVpv(i->c_str(), 0)); + for (auto & i : info->references) + av_push(arr, newSVpv(store()->printStorePath(i).c_str(), 0)); XPUSHs(sv_2mortal(newRV((SV *) arr))); } catch (Error & e) { croak("%s", e.what()); @@ -123,8 +122,8 @@ SV * queryPathInfo(char * path, int base32) SV * queryPathFromHashPart(char * hashPart) PPCODE: try { - Path path = store()->queryPathFromHashPart(hashPart); - XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0))); + auto path = store()->queryPathFromHashPart(hashPart); + XPUSHs(sv_2mortal(newSVpv(path ? store()->printStorePath(*path).c_str() : "", 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -133,11 +132,11 @@ SV * queryPathFromHashPart(char * hashPart) SV * computeFSClosure(int flipDirection, int includeOutputs, ...) PPCODE: try { - PathSet paths; + StorePathSet paths; for (int n = 2; n < items; ++n) - store()->computeFSClosure(SvPV_nolen(ST(n)), paths, flipDirection, includeOutputs); - for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) - XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0))); + store()->computeFSClosure(store()->parseStorePath(SvPV_nolen(ST(n))), paths, flipDirection, includeOutputs); + for (auto & i : paths) + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -146,11 +145,11 @@ SV * computeFSClosure(int flipDirection, int includeOutputs, ...) SV * topoSortPaths(...) PPCODE: try { - PathSet paths; - for (int n = 0; n < items; ++n) paths.insert(SvPV_nolen(ST(n))); - Paths sorted = store()->topoSortPaths(paths); - for (Paths::iterator i = sorted.begin(); i != sorted.end(); ++i) - XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0))); + StorePathSet paths; + for (int n = 0; n < items; ++n) paths.insert(store()->parseStorePath(SvPV_nolen(ST(n)))); + auto sorted = store()->topoSortPaths(paths); + for (auto & i : sorted) + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -159,7 +158,7 @@ SV * topoSortPaths(...) SV * followLinksToStorePath(char * path) CODE: try { - RETVAL = newSVpv(store()->followLinksToStorePath(path).c_str(), 0); + RETVAL = newSVpv(store()->printStorePath(store()->followLinksToStorePath(path)).c_str(), 0); } catch (Error & e) { croak("%s", e.what()); } @@ -170,8 +169,8 @@ SV * followLinksToStorePath(char * path) void exportPaths(int fd, ...) PPCODE: try { - Paths paths; - for (int n = 1; n < items; ++n) paths.push_back(SvPV_nolen(ST(n))); + StorePathSet paths; + for (int n = 1; n < items; ++n) paths.insert(store()->parseStorePath(SvPV_nolen(ST(n)))); FdSink sink(fd); store()->exportPaths(paths, sink); } catch (Error & e) { @@ -275,8 +274,8 @@ int checkSignature(SV * publicKey_, SV * sig_, char * msg) SV * addToStore(char * srcPath, int recursive, char * algo) PPCODE: try { - Path path = store()->addToStore(baseNameOf(srcPath), srcPath, recursive, parseHashType(algo)); - XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0))); + auto path = store()->addToStore(std::string(baseNameOf(srcPath)), srcPath, recursive, parseHashType(algo)); + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -286,8 +285,8 @@ SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name) PPCODE: try { Hash h(hash, parseHashType(algo)); - Path path = store()->makeFixedOutputPath(recursive, h, name); - XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0))); + auto path = store()->makeFixedOutputPath(recursive, h, name); + XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); } @@ -298,35 +297,35 @@ SV * derivationFromPath(char * drvPath) HV *hash; CODE: try { - Derivation drv = store()->derivationFromPath(drvPath); + Derivation drv = store()->derivationFromPath(store()->parseStorePath(drvPath)); hash = newHV(); HV * outputs = newHV(); - for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) - hv_store(outputs, i->first.c_str(), i->first.size(), newSVpv(i->second.path.c_str(), 0), 0); + for (auto & i : drv.outputs) + hv_store(outputs, i.first.c_str(), i.first.size(), newSVpv(store()->printStorePath(i.second.path).c_str(), 0), 0); hv_stores(hash, "outputs", newRV((SV *) outputs)); AV * inputDrvs = newAV(); - for (DerivationInputs::iterator i = drv.inputDrvs.begin(); i != drv.inputDrvs.end(); ++i) - av_push(inputDrvs, newSVpv(i->first.c_str(), 0)); // !!! ignores i->second + for (auto & i : drv.inputDrvs) + av_push(inputDrvs, newSVpv(store()->printStorePath(i.first).c_str(), 0)); // !!! ignores i->second hv_stores(hash, "inputDrvs", newRV((SV *) inputDrvs)); AV * inputSrcs = newAV(); - for (PathSet::iterator i = drv.inputSrcs.begin(); i != drv.inputSrcs.end(); ++i) - av_push(inputSrcs, newSVpv(i->c_str(), 0)); + for (auto & i : drv.inputSrcs) + av_push(inputSrcs, newSVpv(store()->printStorePath(i).c_str(), 0)); hv_stores(hash, "inputSrcs", newRV((SV *) inputSrcs)); hv_stores(hash, "platform", newSVpv(drv.platform.c_str(), 0)); hv_stores(hash, "builder", newSVpv(drv.builder.c_str(), 0)); AV * args = newAV(); - for (Strings::iterator i = drv.args.begin(); i != drv.args.end(); ++i) - av_push(args, newSVpv(i->c_str(), 0)); + for (auto & i : drv.args) + av_push(args, newSVpv(i.c_str(), 0)); hv_stores(hash, "args", newRV((SV *) args)); HV * env = newHV(); - for (StringPairs::iterator i = drv.env.begin(); i != drv.env.end(); ++i) - hv_store(env, i->first.c_str(), i->first.size(), newSVpv(i->second.c_str(), 0), 0); + for (auto & i : drv.env) + hv_store(env, i.first.c_str(), i.first.size(), newSVpv(i.second.c_str(), 0), 0); hv_stores(hash, "env", newRV((SV *) env)); RETVAL = newRV_noinc((SV *)hash); @@ -340,7 +339,7 @@ SV * derivationFromPath(char * drvPath) void addTempRoot(char * storePath) PPCODE: try { - store()->addTempRoot(storePath); + store()->addTempRoot(store()->parseStorePath(storePath)); } catch (Error & e) { croak("%s", e.what()); } diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 27dd35784..69d1c6f7e 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -88,7 +88,7 @@ static int _main(int argc, char * * argv) return 0; } - string drvPath; + std::optional drvPath; string storeUri; while (true) { @@ -100,7 +100,7 @@ static int _main(int argc, char * * argv) auto amWilling = readInt(source); auto neededSystem = readString(source); - source >> drvPath; + drvPath = store->parseStorePath(readString(source)); auto requiredFeatures = readStrings>(source); auto canBuildLocally = amWilling @@ -236,26 +236,27 @@ connected: { Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri)); - copyPaths(store, ref(sshStore), inputs, NoRepair, NoCheckSigs, substitute); + copyPaths(store, ref(sshStore), store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute); } uploadLock = -1; - BasicDerivation drv(readDerivation(store->realStoreDir + "/" + baseNameOf(drvPath))); - drv.inputSrcs = inputs; + BasicDerivation drv(readDerivation(*store, store->realStoreDir + "/" + std::string(drvPath->to_string()))); + drv.inputSrcs = store->parseStorePathSet(inputs); - auto result = sshStore->buildDerivation(drvPath, drv); + auto result = sshStore->buildDerivation(*drvPath, drv); if (!result.success()) - throw Error("build of '%s' on '%s' failed: %s", drvPath, storeUri, result.errorMsg); + throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg); - PathSet missing; + StorePathSet missing; for (auto & path : outputs) - if (!store->isValidPath(path)) missing.insert(path); + if (!store->isValidPath(store->parseStorePath(path))) missing.insert(store->parseStorePath(path)); if (!missing.empty()) { Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri)); - store->locksHeld.insert(missing.begin(), missing.end()); /* FIXME: ugly */ + for (auto & i : missing) + store->locksHeld.insert(store->printStorePath(i)); /* FIXME: ugly */ copyPaths(ref(sshStore), store, missing, NoRepair, NoCheckSigs, NoSubstitute); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 4be4cfeea..6539a346a 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -43,6 +43,19 @@ static char * dupString(const char * s) } +static char * dupStringWithLen(const char * s, size_t size) +{ + char * t; +#if HAVE_BOEHMGC + t = GC_STRNDUP(s, size); +#else + t = strndup(s, size); +#endif + if (!t) throw std::bad_alloc(); + return t; +} + + static void printValue(std::ostream & str, std::set & active, const Value & v) { checkInterrupt(); @@ -330,10 +343,10 @@ EvalState::EvalState(const Strings & _searchPath, ref store) auto path = r.second; if (store->isInStore(r.second)) { - PathSet closure; - store->computeFSClosure(store->toStorePath(r.second), closure); + StorePathSet closure; + store->computeFSClosure(store->parseStorePath(store->toStorePath(r.second)), closure); for (auto & path : closure) - allowedPaths->insert(path); + allowedPaths->insert(store->printStorePath(path)); } else allowedPaths->insert(r.second); } @@ -550,9 +563,11 @@ void mkString(Value & v, const char * s) } -Value & mkString(Value & v, const string & s, const PathSet & context) +Value & mkString(Value & v, std::string_view s, const PathSet & context) { - mkString(v, s.c_str()); + v.type = tString; + v.string.s = dupStringWithLen(s.data(), s.size()); + v.string.context = 0; if (!context.empty()) { size_t n = 0; v.string.context = (const char * *) @@ -1639,15 +1654,16 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path) throwEvalError("file names are not allowed to end in '%1%'", drvExtension); Path dstPath; - if (srcToStore[path] != "") - dstPath = srcToStore[path]; + auto i = srcToStore.find(path); + if (i != srcToStore.end()) + dstPath = store->printStorePath(i->second); else { - dstPath = settings.readOnlyMode - ? store->computeStorePathForPath(baseNameOf(path), checkSourcePath(path)).first - : store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair); - srcToStore[path] = dstPath; - printMsg(lvlChatty, format("copied source '%1%' -> '%2%'") - % path % dstPath); + auto p = settings.readOnlyMode + ? store->computeStorePathForPath(std::string(baseNameOf(path)), checkSourcePath(path)).first + : store->addToStore(std::string(baseNameOf(path)), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair); + dstPath = store->printStorePath(p); + srcToStore.insert_or_assign(path, std::move(p)); + printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, dstPath); } context.insert(dstPath); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 85aa1ccfe..cabc92d15 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -17,6 +17,7 @@ namespace nix { class Store; class EvalState; +struct StorePath; enum RepairFlag : bool; @@ -42,14 +43,14 @@ struct Env }; -Value & mkString(Value & v, const string & s, const PathSet & context = PathSet()); +Value & mkString(Value & v, std::string_view s, const PathSet & context = PathSet()); void copyContext(const Value & v, PathSet & context); /* Cache for calls to addToStore(); maps source paths to the store paths. */ -typedef std::map SrcToStore; +typedef std::map SrcToStore; std::ostream & operator << (std::ostream & str, const Value & v); diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 4e22a1d77..a3412eab9 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -19,27 +19,27 @@ DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs) DrvInfo::DrvInfo(EvalState & state, ref store, const std::string & drvPathWithOutputs) : state(&state), attrs(nullptr), attrPath("") { - auto spec = parseDrvPathWithOutputs(drvPathWithOutputs); + auto [drvPath, selectedOutputs] = store->parseDrvPathWithOutputs(drvPathWithOutputs); - drvPath = spec.first; + this->drvPath = store->printStorePath(drvPath); auto drv = store->derivationFromPath(drvPath); - name = storePathToName(drvPath); + name = drvPath.name(); - if (spec.second.size() > 1) + if (selectedOutputs.size() > 1) throw Error("building more than one derivation output is not supported, in '%s'", drvPathWithOutputs); outputName = - spec.second.empty() - ? get(drv.env, "outputName", "out") - : *spec.second.begin(); + selectedOutputs.empty() + ? get(drv.env, "outputName").value_or("out") + : *selectedOutputs.begin(); auto i = drv.outputs.find(outputName); if (i == drv.outputs.end()) - throw Error("derivation '%s' does not have output '%s'", drvPath, outputName); + throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName); - outPath = i->second.path; + outPath = store->printStorePath(i->second.path); } diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index ccd5293e4..26b9f14ba 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -6,7 +6,7 @@ libexpr_DIR := $(d) libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc -libexpr_LIBS = libutil libstore +libexpr_LIBS = libutil libstore libnixrust libexpr_LDFLAGS = ifneq ($(OS), FreeBSD) diff --git a/src/libexpr/names.cc b/src/libexpr/names.cc index 382088c78..d1c8a6101 100644 --- a/src/libexpr/names.cc +++ b/src/libexpr/names.cc @@ -16,14 +16,14 @@ DrvName::DrvName() 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(const string & s) : hits(0) +DrvName::DrvName(std::string_view s) : hits(0) { - name = fullName = s; + name = fullName = std::string(s); for (unsigned int i = 0; i < s.size(); ++i) { /* !!! isalpha/isdigit are affected by the locale. */ if (s[i] == '-' && i + 1 < s.size() && !isalpha(s[i + 1])) { - name = string(s, 0, i); - version = string(s, i + 1); + name = s.substr(0, i); + version = s.substr(i + 1); break; } } diff --git a/src/libexpr/names.hh b/src/libexpr/names.hh index 13c3093e7..00e14b8c7 100644 --- a/src/libexpr/names.hh +++ b/src/libexpr/names.hh @@ -15,7 +15,7 @@ struct DrvName unsigned int hits; DrvName(); - DrvName(const string & s); + DrvName(std::string_view s); bool matches(DrvName & n); private: diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d693a3b20..3ef827ebc 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -44,29 +44,28 @@ std::pair decodeContext(const string & s) InvalidPathError::InvalidPathError(const Path & path) : - EvalError(format("path '%1%' is not valid") % path), path(path) {} + EvalError("path '%s' is not valid", path), path(path) {} void EvalState::realiseContext(const PathSet & context) { - PathSet drvs; + std::vector drvs; for (auto & i : context) { std::pair decoded = decodeContext(i); - Path ctx = decoded.first; - assert(store->isStorePath(ctx)); + auto ctx = store->parseStorePath(decoded.first); if (!store->isValidPath(ctx)) - throw InvalidPathError(ctx); - if (!decoded.second.empty() && nix::isDerivation(ctx)) { - drvs.insert(decoded.first + "!" + decoded.second); + throw InvalidPathError(store->printStorePath(ctx)); + if (!decoded.second.empty() && ctx.isDerivation()) { + drvs.push_back(StorePathWithOutputs{ctx.clone(), {decoded.second}}); /* Add the output of this derivation to the allowed paths. */ if (allowedPaths) { - auto drv = store->derivationFromPath(decoded.first); + auto drv = store->derivationFromPath(store->parseStorePath(decoded.first)); DerivationOutputs::iterator i = drv.outputs.find(decoded.second); if (i == drv.outputs.end()) throw Error("derivation '%s' does not have an output named '%s'", decoded.first, decoded.second); - allowedPaths->insert(i->second.path); + allowedPaths->insert(store->printStorePath(i->second.path)); } } } @@ -74,10 +73,11 @@ void EvalState::realiseContext(const PathSet & context) if (drvs.empty()) return; if (!evalSettings.enableImportFromDerivation) - throw EvalError(format("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false") % *(drvs.begin())); + throw EvalError("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false", + store->printStorePath(drvs.begin()->path)); /* For performance, prefetch all substitute info. */ - PathSet willBuild, willSubstitute, unknown; + StorePathSet willBuild, willSubstitute, unknown; unsigned long long downloadSize, narSize; store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize); store->buildPaths(drvs); @@ -100,8 +100,9 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args Path realPath = state.checkSourcePath(state.toRealPath(path, context)); - if (state.store->isStorePath(path) && state.store->isValidPath(path) && isDerivation(path)) { - Derivation drv = readDerivation(realPath); + // FIXME + if (state.store->isStorePath(path) && state.store->isValidPath(state.store->parseStorePath(path)) && isDerivation(path)) { + Derivation drv = readDerivation(*state.store, realPath); Value & w = *state.allocValue(); state.mkAttrs(w, 3 + drv.outputs.size()); Value * v2 = state.allocAttr(w, state.sDrvPath); @@ -115,7 +116,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args for (const auto & o : drv.outputs) { v2 = state.allocAttr(w, state.symbols.create(o.first)); - mkString(*v2, o.second.path, {"!" + o.first + "!" + path}); + mkString(*v2, state.store->printStorePath(o.second.path), {"!" + o.first + "!" + path}); outputsVal->listElems()[outputs_index] = state.allocValue(); mkString(*(outputsVal->listElems()[outputs_index++]), o.first); } @@ -676,24 +677,24 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * runs. */ if (path.at(0) == '=') { /* !!! This doesn't work if readOnlyMode is set. */ - PathSet refs; - state.store->computeFSClosure(string(path, 1), refs); + StorePathSet refs; + state.store->computeFSClosure(state.store->parseStorePath(std::string_view(path).substr(1)), refs); for (auto & j : refs) { - drv.inputSrcs.insert(j); - if (isDerivation(j)) - drv.inputDrvs[j] = state.store->queryDerivationOutputNames(j); + drv.inputSrcs.insert(j.clone()); + if (j.isDerivation()) + drv.inputDrvs[j.clone()] = state.store->queryDerivationOutputNames(j); } } /* Handle derivation outputs of the form ‘!!’. */ else if (path.at(0) == '!') { std::pair ctx = decodeContext(path); - drv.inputDrvs[ctx.first].insert(ctx.second); + drv.inputDrvs[state.store->parseStorePath(ctx.first)].insert(ctx.second); } /* Otherwise it's a source file. */ else - drv.inputSrcs.insert(path); + drv.inputSrcs.insert(state.store->parseStorePath(path)); } /* Do we have all required attributes? */ @@ -703,10 +704,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * throw EvalError(format("required attribute 'system' missing, at %1%") % posDrvName); /* Check whether the derivation name is valid. */ - checkStoreName(drvName); if (isDerivation(drvName)) - throw EvalError(format("derivation names are not allowed to end in '%1%', at %2%") - % drvExtension % posDrvName); + throw EvalError("derivation names are not allowed to end in '%s', at %s", drvExtension, posDrvName); if (outputHash) { /* Handle fixed-output derivations. */ @@ -716,52 +715,51 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo); Hash h(*outputHash, ht); - Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName); - if (!jsonObject) drv.env["out"] = outPath; - drv.outputs["out"] = DerivationOutput(outPath, - (outputHashRecursive ? "r:" : "") + printHashType(h.type), - h.to_string(Base16, false)); + auto outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName); + if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); + drv.outputs.insert_or_assign("out", DerivationOutput(std::move(outPath), + (outputHashRecursive ? "r:" : "") + printHashType(h.type), + h.to_string(Base16, false))); } else { - /* Construct the "masked" store derivation, which is the final - one except that in the list of outputs, the output paths - are empty, and the corresponding environment variables have - an empty value. This ensures that changes in the set of - output names do get reflected in the hash. */ + /* Compute a hash over the "masked" store derivation, which is + the final one except that in the list of outputs, the + output paths are empty strings, and the corresponding + environment variables have an empty value. This ensures + that changes in the set of output names do get reflected in + the hash. */ for (auto & i : outputs) { if (!jsonObject) drv.env[i] = ""; - drv.outputs[i] = DerivationOutput("", "", ""); } - /* Use the masked derivation expression to compute the output - path. */ - Hash h = hashDerivationModulo(*state.store, drv); + Hash h = hashDerivationModulo(*state.store, Derivation(drv), true); - for (auto & i : drv.outputs) - if (i.second.path == "") { - Path outPath = state.store->makeOutputPath(i.first, h, drvName); - if (!jsonObject) drv.env[i.first] = outPath; - i.second.path = outPath; - } + for (auto & i : outputs) { + auto outPath = state.store->makeOutputPath(i, h, drvName); + if (!jsonObject) drv.env[i] = state.store->printStorePath(outPath); + drv.outputs.insert_or_assign(i, + DerivationOutput(std::move(outPath), "", "")); + } } /* Write the resulting term into the Nix store directory. */ - Path drvPath = writeDerivation(state.store, drv, drvName, state.repair); + auto drvPath = writeDerivation(state.store, drv, drvName, state.repair); + auto drvPathS = state.store->printStorePath(drvPath); - printMsg(lvlChatty, format("instantiated '%1%' -> '%2%'") - % drvName % drvPath); + printMsg(lvlChatty, "instantiated '%1%' -> '%2%'", drvName, drvPathS); /* Optimisation, but required in read-only mode! because in that case we don't actually write store derivations, so we can't read them later. */ - drvHashes[drvPath] = hashDerivationModulo(*state.store, drv); + drvHashes.insert_or_assign(drvPath.clone(), + hashDerivationModulo(*state.store, Derivation(drv), false)); state.mkAttrs(v, 1 + drv.outputs.size()); - mkString(*state.allocAttr(v, state.sDrvPath), drvPath, {"=" + drvPath}); + mkString(*state.allocAttr(v, state.sDrvPath), drvPathS, {"=" + drvPathS}); for (auto & i : drv.outputs) { mkString(*state.allocAttr(v, state.symbols.create(i.first)), - i.second.path, {"!" + i.first + "!" + drvPath}); + state.store->printStorePath(i.second.path), {"!" + i.first + "!" + drvPathS}); } v.attrs->sort(); } @@ -814,7 +812,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V throw EvalError(format("path '%1%' is not in the Nix store, at %2%") % path % pos); Path path2 = state.store->toStorePath(path); if (!settings.readOnlyMode) - state.store->ensurePath(path2); + state.store->ensurePath(state.store->parseStorePath(path2)); context.insert(path2); mkString(v, path, context); } @@ -1010,17 +1008,17 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu string name = state.forceStringNoCtx(*args[0], pos); string contents = state.forceString(*args[1], context, pos); - PathSet refs; + StorePathSet refs; for (auto path : context) { if (path.at(0) != '/') throw EvalError(format("in 'toFile': the file '%1%' cannot refer to derivation outputs, at %2%") % name % pos); - refs.insert(path); + refs.insert(state.store->parseStorePath(path)); } - Path storePath = settings.readOnlyMode + auto storePath = state.store->printStorePath(settings.readOnlyMode ? state.store->computeStorePathForText(name, contents, refs) - : state.store->addTextToStore(name, contents, refs, state.repair); + : state.store->addTextToStore(name, contents, 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 @@ -1060,21 +1058,18 @@ static void addPath(EvalState & state, const Pos & pos, const string & name, con return state.forceBool(res, pos); }) : defaultPathFilter; - Path expectedStorePath; - if (expectedHash) { - expectedStorePath = - state.store->makeFixedOutputPath(recursive, expectedHash, name); - } + std::optional expectedStorePath; + if (expectedHash) + expectedStorePath = state.store->makeFixedOutputPath(recursive, expectedHash, name); Path dstPath; - if (!expectedHash || !state.store->isValidPath(expectedStorePath)) { - dstPath = settings.readOnlyMode + if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) { + dstPath = state.store->printStorePath(settings.readOnlyMode ? state.store->computeStorePathForPath(name, path, recursive, htSHA256, filter).first - : state.store->addToStore(name, path, recursive, htSHA256, filter, state.repair); - if (expectedHash && expectedStorePath != dstPath) { - throw Error(format("store path mismatch in (possibly filtered) path added from '%1%'") % path); - } + : state.store->addToStore(name, path, recursive, htSHA256, filter, state.repair)); + if (expectedHash && expectedStorePath != state.store->parseStorePath(dstPath)) + throw Error("store path mismatch in (possibly filtered) path added from '%s'", path); } else - dstPath = expectedStorePath; + dstPath = state.store->printStorePath(*expectedStorePath); mkString(v, dstPath, {dstPath}); } @@ -1091,7 +1086,7 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args if (args[0]->type != tLambda) throw TypeError(format("first argument in call to 'filterSource' is not a function but %1%, at %2%") % showType(*args[0]) % pos); - addPath(state, pos, baseNameOf(path), path, args[0], true, Hash(), v); + addPath(state, pos, std::string(baseNameOf(path)), path, args[0], true, Hash(), v); } static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value & v) @@ -2151,7 +2146,7 @@ void EvalState::createBaseEnv() } if (!evalSettings.pureEval) { - mkString(v, settings.thisSystem); + mkString(v, settings.thisSystem.get()); addConstant("__currentSystem", v); } diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 2d79739ea..94fa0158c 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -148,7 +148,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg if (!state.store->isStorePath(i.name)) throw EvalError("Context key '%s' is not a store path, at %s", i.name, i.pos); if (!settings.readOnlyMode) - state.store->ensurePath(i.name); + state.store->ensurePath(state.store->parseStorePath(i.name)); state.forceAttrs(*i.value, *i.pos); auto iter = i.value->attrs->find(sPath); if (iter != i.value->attrs->end()) { diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc index 9d0c64291..4aee1073e 100644 --- a/src/libexpr/primops/fetchGit.cc +++ b/src/libexpr/primops/fetchGit.cc @@ -69,7 +69,7 @@ GitInfo exportGit(ref store, const std::string & uri, return files.count(file); }; - gitInfo.storePath = store->addToStore("source", uri, true, htSHA256, filter); + gitInfo.storePath = store->printStorePath(store->addToStore("source", uri, true, htSHA256, filter)); return gitInfo; } @@ -156,7 +156,7 @@ GitInfo exportGit(ref store, const std::string & uri, gitInfo.storePath = json["storePath"]; - if (store->isValidPath(gitInfo.storePath)) { + if (store->isValidPath(store->parseStorePath(gitInfo.storePath))) { gitInfo.revCount = json["revCount"]; return gitInfo; } @@ -176,7 +176,7 @@ GitInfo exportGit(ref store, const std::string & uri, unpackTarfile(*source, tmpDir); - gitInfo.storePath = store->addToStore(name, tmpDir); + gitInfo.storePath = store->printStorePath(store->addToStore(name, tmpDir)); gitInfo.revCount = std::stoull(runProgram("git", true, { "-C", cacheDir, "rev-list", "--count", gitInfo.rev })); diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc index a907d0e1c..db274fa4f 100644 --- a/src/libexpr/primops/fetchMercurial.cc +++ b/src/libexpr/primops/fetchMercurial.cc @@ -63,7 +63,7 @@ HgInfo exportMercurial(ref store, const std::string & uri, return files.count(file); }; - hgInfo.storePath = store->addToStore("source", uri, true, htSHA256, filter); + hgInfo.storePath = store->printStorePath(store->addToStore("source", uri, true, htSHA256, filter)); return hgInfo; } @@ -134,7 +134,7 @@ HgInfo exportMercurial(ref store, const std::string & uri, hgInfo.storePath = json["storePath"]; - if (store->isValidPath(hgInfo.storePath)) { + if (store->isValidPath(store->parseStorePath(hgInfo.storePath))) { printTalkative("using cached Mercurial store path '%s'", hgInfo.storePath); return hgInfo; } @@ -150,7 +150,7 @@ HgInfo exportMercurial(ref store, const std::string & uri, deletePath(tmpDir + "/.hg_archival.txt"); - hgInfo.storePath = store->addToStore(name, tmpDir); + hgInfo.storePath = store->printStorePath(store->addToStore(name, tmpDir)); nlohmann::json json; json["storePath"] = hgInfo.storePath; diff --git a/src/libexpr/symbol-table.hh b/src/libexpr/symbol-table.hh index 91faea122..7ba5e1c14 100644 --- a/src/libexpr/symbol-table.hh +++ b/src/libexpr/symbol-table.hh @@ -38,7 +38,12 @@ public: return s < s2.s; } - operator const string & () const + operator const std::string & () const + { + return *s; + } + + operator const std::string_view () const { return *s; } diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 81fb6b05a..d41e772e9 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -33,25 +33,25 @@ void printGCWarning() } -void printMissing(ref store, const PathSet & paths, Verbosity lvl) +void printMissing(ref store, const std::vector & paths, Verbosity lvl) { unsigned long long downloadSize, narSize; - PathSet willBuild, willSubstitute, unknown; + StorePathSet willBuild, willSubstitute, unknown; store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); printMissing(store, willBuild, willSubstitute, unknown, downloadSize, narSize, lvl); } -void printMissing(ref store, const PathSet & willBuild, - const PathSet & willSubstitute, const PathSet & unknown, +void printMissing(ref store, const StorePathSet & willBuild, + const StorePathSet & willSubstitute, const StorePathSet & unknown, unsigned long long downloadSize, unsigned long long narSize, Verbosity lvl) { if (!willBuild.empty()) { printMsg(lvl, "these derivations will be built:"); - Paths sorted = store->topoSortPaths(willBuild); + auto sorted = store->topoSortPaths(willBuild); reverse(sorted.begin(), sorted.end()); for (auto & i : sorted) - printMsg(lvl, fmt(" %s", i)); + printMsg(lvl, fmt(" %s", store->printStorePath(i))); } if (!willSubstitute.empty()) { @@ -59,14 +59,14 @@ void printMissing(ref store, const PathSet & willBuild, downloadSize / (1024.0 * 1024.0), narSize / (1024.0 * 1024.0))); for (auto & i : willSubstitute) - printMsg(lvl, fmt(" %s", i)); + printMsg(lvl, fmt(" %s", store->printStorePath(i))); } if (!unknown.empty()) { printMsg(lvl, fmt("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, fmt(" %s", i)); + printMsg(lvl, fmt(" %s", store->printStorePath(i))); } } @@ -237,7 +237,7 @@ bool LegacyArgs::processArgs(const Strings & args, bool finish) void parseCmdLine(int argc, char * * argv, std::function parseArg) { - parseCmdLine(baseNameOf(argv[0]), argvToStrings(argc, argv), parseArg); + parseCmdLine(std::string(baseNameOf(argv[0])), argvToStrings(argc, argv), parseArg); } diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh index 8e4861232..b49574652 100644 --- a/src/libmain/shared.hh +++ b/src/libmain/shared.hh @@ -3,6 +3,7 @@ #include "util.hh" #include "args.hh" #include "common-args.hh" +#include "path.hh" #include @@ -37,11 +38,15 @@ void printVersion(const string & programName); void printGCWarning(); class Store; +struct StorePathWithOutputs; -void printMissing(ref store, const PathSet & paths, Verbosity lvl = lvlInfo); +void printMissing( + ref store, + const std::vector & paths, + Verbosity lvl = lvlInfo); -void printMissing(ref store, const PathSet & willBuild, - const PathSet & willSubstitute, const PathSet & unknown, +void printMissing(ref store, const StorePathSet & willBuild, + const StorePathSet & willSubstitute, const StorePathSet & unknown, unsigned long long downloadSize, unsigned long long narSize, Verbosity lvl = lvlInfo); string getArg(const string & opt, diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index 7e3e5ff88..aaacf8281 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -91,19 +91,18 @@ std::shared_ptr BinaryCacheStore::getFile(const std::string & path) return sink.s; } -Path BinaryCacheStore::narInfoFileFor(const Path & storePath) +std::string BinaryCacheStore::narInfoFileFor(const StorePath & storePath) { - assertStorePath(storePath); - return storePathToHash(storePath) + ".narinfo"; + return storePathToHash(printStorePath(storePath)) + ".narinfo"; } void BinaryCacheStore::writeNarInfo(ref narInfo) { auto narInfoFile = narInfoFileFor(narInfo->path); - upsertFile(narInfoFile, narInfo->to_string(), "text/x-nix-narinfo"); + upsertFile(narInfoFile, narInfo->to_string(*this), "text/x-nix-narinfo"); - auto hashPart = storePathToHash(narInfo->path); + auto hashPart = storePathToHash(printStorePath(narInfo->path)); { auto state_(state.lock()); @@ -126,8 +125,8 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const refcompare(0, narMagic.size(), narMagic) == 0); @@ -138,14 +137,14 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const refnarHash = hashString(htSHA256, *nar); if (info.narHash && info.narHash != narInfo->narHash) - throw Error(format("refusing to copy corrupted path '%1%' to binary cache") % info.path); + throw Error("refusing to copy corrupted path '%1%' to binary cache", printStorePath(info.path)); auto accessor_ = std::dynamic_pointer_cast(accessor); auto narAccessor = makeNarAccessor(nar); if (accessor_) - accessor_->addToCache(info.path, *nar, narAccessor); + accessor_->addToCache(printStorePath(info.path), *nar, narAccessor); /* Optionally write a JSON file containing a listing of the contents of the NAR. */ @@ -162,7 +161,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const reffileSize = narCompressed->size(); auto duration = std::chrono::duration_cast(now2 - now1).count(); - printMsg(lvlTalkative, format("copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache") - % narInfo->path % narInfo->narSize - % ((1.0 - (double) narCompressed->size() / nar->size()) * 100.0) - % duration); + printMsg(lvlTalkative, "copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache", + printStorePath(narInfo->path), narInfo->narSize, + ((1.0 - (double) narCompressed->size() / nar->size()) * 100.0), + duration); narInfo->url = "nar/" + narInfo->fileHash.to_string(Base32, false) + ".nar" + (compression == "xz" ? ".xz" : @@ -254,14 +253,14 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const refsign(*secretKey); + if (secretKey) narInfo->sign(*this, *secretKey); writeNarInfo(narInfo); stats.narInfoWrite++; } -bool BinaryCacheStore::isValidPathUncached(const Path & storePath) +bool BinaryCacheStore::isValidPathUncached(const StorePath & storePath) { // FIXME: this only checks whether a .narinfo with a matching hash // part exists. So ‘f4kb...-foo’ matches ‘f4kb...-bar’, even @@ -269,7 +268,7 @@ bool BinaryCacheStore::isValidPathUncached(const Path & storePath) return fileExists(narInfoFileFor(storePath)); } -void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink) +void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink) { auto info = queryPathInfo(storePath).cast(); @@ -295,12 +294,13 @@ void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink) stats.narReadBytes += narSize; } -void BinaryCacheStore::queryPathInfoUncached(const Path & storePath, +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'", storePath, uri), Logger::Fields{storePath, uri}); + fmt("querying info about '%s' on '%s'", storePathS, uri), Logger::Fields{storePathS, uri}); PushActivity pact(act->id); auto narInfoFile = narInfoFileFor(storePath); @@ -326,7 +326,7 @@ void BinaryCacheStore::queryPathInfoUncached(const Path & storePath, }}); } -Path BinaryCacheStore::addToStore(const string & name, const Path & srcPath, +StorePath BinaryCacheStore::addToStore(const string & name, const Path & srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) { // FIXME: some cut&paste from LocalStore::addToStore(). @@ -345,20 +345,18 @@ Path BinaryCacheStore::addToStore(const string & name, const Path & srcPath, h = hashString(hashAlgo, s); } - ValidPathInfo info; - info.path = makeFixedOutputPath(recursive, h, name); + ValidPathInfo info(makeFixedOutputPath(recursive, h, name)); addToStore(info, sink.s, repair, CheckSigs, nullptr); - return info.path; + return std::move(info.path); } -Path BinaryCacheStore::addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) +StorePath BinaryCacheStore::addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) { - ValidPathInfo info; - info.path = computeStorePathForText(name, s, references); - info.references = references; + ValidPathInfo info(computeStorePathForText(name, s, references)); + info.references = cloneStorePathSet(references); if (repair || !isValidPath(info.path)) { StringSink sink; @@ -366,7 +364,7 @@ Path BinaryCacheStore::addTextToStore(const string & name, const string & s, addToStore(info, sink.s, repair, CheckSigs, nullptr); } - return info.path; + return std::move(info.path); } ref BinaryCacheStore::getFSAccessor() @@ -374,7 +372,7 @@ ref BinaryCacheStore::getFSAccessor() return make_ref(ref(shared_from_this()), localNarCache); } -void BinaryCacheStore::addSignatures(const Path & storePath, const StringSet & sigs) +void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSet & sigs) { /* Note: this is inherently racy since there is no locking on binary caches. In particular, with S3 this unreliable, even @@ -390,24 +388,22 @@ void BinaryCacheStore::addSignatures(const Path & storePath, const StringSet & s writeNarInfo(narInfo); } -std::shared_ptr BinaryCacheStore::getBuildLog(const Path & path) +std::shared_ptr BinaryCacheStore::getBuildLog(const StorePath & path) { - Path drvPath; + auto drvPath = path.clone(); - if (isDerivation(path)) - drvPath = path; - else { + if (!path.isDerivation()) { try { auto info = queryPathInfo(path); // FIXME: add a "Log" field to .narinfo - if (info->deriver == "") return nullptr; - drvPath = info->deriver; + if (!info->deriver) return nullptr; + drvPath = info->deriver->clone(); } catch (InvalidPath &) { return nullptr; } } - auto logPath = "log/" + baseNameOf(drvPath); + auto logPath = "log/" + std::string(baseNameOf(printStorePath(drvPath))); debug("fetching build log from binary cache '%s/%s'", getUri(), logPath); diff --git a/src/libstore/binary-cache-store.hh b/src/libstore/binary-cache-store.hh index 2d7cd1947..fa2200ad8 100644 --- a/src/libstore/binary-cache-store.hh +++ b/src/libstore/binary-cache-store.hh @@ -65,18 +65,18 @@ private: std::string narMagic; - std::string narInfoFileFor(const Path & storePath); + std::string narInfoFileFor(const StorePath & storePath); void writeNarInfo(ref narInfo); public: - bool isValidPathUncached(const Path & path) override; + bool isValidPathUncached(const StorePath & path) override; - void queryPathInfoUncached(const Path & path, + void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept override; - Path queryPathFromHashPart(const string & hashPart) override + std::optional queryPathFromHashPart(const std::string & hashPart) override { unsupported("queryPathFromHashPart"); } bool wantMassQuery() override { return wantMassQuery_; } @@ -85,27 +85,27 @@ public: RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr accessor) override; - Path addToStore(const string & name, const Path & srcPath, + StorePath addToStore(const string & name, const Path & srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) override; - Path addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) override; + StorePath addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) override; - void narFromPath(const Path & path, Sink & sink) override; + void narFromPath(const StorePath & path, Sink & sink) override; - BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) override { unsupported("buildDerivation"); } - void ensurePath(const Path & path) override + void ensurePath(const StorePath & path) override { unsupported("ensurePath"); } ref getFSAccessor() override; - void addSignatures(const Path & storePath, const StringSet & sigs) override; + void addSignatures(const StorePath & storePath, const StringSet & sigs) override; - std::shared_ptr getBuildLog(const Path & path) override; + std::shared_ptr getBuildLog(const StorePath & path) override; int getPriority() override { return priority; } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 69649162e..de0ce9ae1 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -14,6 +14,7 @@ #include "parsed-derivations.hh" #include "machines.hh" #include "daemon.hh" +#include "worker-protocol.hh" #include #include @@ -98,7 +99,7 @@ typedef set Goals; typedef list WeakGoals; /* A map of paths to goals (and the other way around). */ -typedef map WeakGoalMap; +typedef std::map WeakGoalMap; @@ -253,7 +254,7 @@ private: steady_time_point lastWokenUp; /* Cache for pathContentsGood(). */ - std::map pathContentsGoodCache; + std::map pathContentsGoodCache; public: @@ -300,10 +301,10 @@ public: ~Worker(); /* Make a goal (with caching). */ - GoalPtr makeDerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, BuildMode buildMode = bmNormal); - std::shared_ptr makeBasicDerivationGoal(const Path & drvPath, + GoalPtr makeDerivationGoal(const StorePath & drvPath, const StringSet & wantedOutputs, BuildMode buildMode = bmNormal); + std::shared_ptr makeBasicDerivationGoal(StorePath && drvPath, const BasicDerivation & drv, BuildMode buildMode = bmNormal); - GoalPtr makeSubstitutionGoal(const Path & storePath, RepairFlag repair = NoRepair); + GoalPtr makeSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair); /* Remove a dead goal. */ void removeGoal(GoalPtr goal); @@ -351,9 +352,9 @@ public: /* Check whether the given valid path exists and has the right contents. */ - bool pathContentsGood(const Path & path); + bool pathContentsGood(const StorePath & path); - void markContentsGood(const Path & path); + void markContentsGood(StorePath && path); void updateProgress() { @@ -470,7 +471,10 @@ static void commonChildInit(Pipe & logPipe) close(fdDevNull); } -void handleDiffHook(uid_t uid, uid_t gid, Path tryA, Path tryB, Path drvPath, Path tmpDir) +void handleDiffHook( + uid_t uid, uid_t gid, + const Path & tryA, const Path & tryB, + const Path & drvPath, const Path & tmpDir) { auto diffHook = settings.diffHook; if (diffHook != "" && settings.runDiffHook) { @@ -662,7 +666,7 @@ HookInstance::HookInstance() throw SysError("dupping builder's stdout/stderr"); Strings args = { - baseNameOf(settings.buildHook), + std::string(baseNameOf(settings.buildHook.get())), std::to_string(verbosity), }; @@ -709,7 +713,7 @@ private: bool useDerivation; /* The path of the derivation. */ - Path drvPath; + StorePath drvPath; /* The specific outputs that we need to build. Empty means all of them. */ @@ -734,14 +738,14 @@ private: /* All input paths (that is, the union of FS closures of the immediate input paths). */ - PathSet inputPaths; + StorePathSet inputPaths; /* Outputs that are already valid. If we're repairing, these are the outputs that are valid *and* not corrupt. */ - PathSet validPaths; + StorePathSet validPaths; /* Outputs that are corrupt or not valid. */ - PathSet missingPaths; + StorePathSet missingPaths; /* User selected for running the builder. */ std::unique_ptr buildUser; @@ -821,7 +825,7 @@ private: /* Hash rewriting. */ StringMap inputRewrites, outputRewrites; - typedef map RedirectedOutputs; + typedef map RedirectedOutputs; RedirectedOutputs redirectedOutputs; BuildMode buildMode; @@ -829,7 +833,7 @@ private: /* If we're repairing without a chroot, there may be outputs that are valid but corrupt. So we redirect these outputs to temporary paths. */ - PathSet redirectedBadOutputs; + StorePathSet redirectedBadOutputs; BuildResult result; @@ -868,23 +872,23 @@ private: std::vector daemonWorkerThreads; /* Paths that were added via recursive Nix calls. */ - PathSet addedPaths; + StorePathSet addedPaths; /* Recursive Nix calls are only allowed to build or realize paths in the original input closure or added via a recursive Nix call (so e.g. you can't do 'nix-store -r /nix/store/' where /nix/store/ is some arbitrary path in a binary cache). */ - bool isAllowed(const Path & path) + bool isAllowed(const StorePath & path) { return inputPaths.count(path) || addedPaths.count(path); } - friend class RestrictedStore; + friend struct RestrictedStore; public: - DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, + DerivationGoal(StorePath && drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal); - DerivationGoal(const Path & drvPath, const BasicDerivation & drv, + DerivationGoal(StorePath && drvPath, const BasicDerivation & drv, Worker & worker, BuildMode buildMode = bmNormal); ~DerivationGoal(); @@ -899,14 +903,14 @@ public: i.e. a derivation named "aardvark" always comes before "baboon". And substitution goals always happen before derivation goals (due to "b$"). */ - return "b$" + storePathToName(drvPath) + "$" + drvPath; + return "b$" + std::string(drvPath.name()) + "$" + worker.store.printStorePath(drvPath); } void work() override; - Path getDrvPath() + StorePath getDrvPath() { - return drvPath; + return drvPath.clone(); } /* Add wanted outputs to an already existing derivation goal. */ @@ -946,7 +950,7 @@ private: /* Add 'path' to the set of paths that may be referenced by the outputs, and make it appear in the sandbox. */ - void addDependency(const Path & path); + void addDependency(const StorePath & path); /* Make a file owned by the builder. */ void chownToBuilder(const Path & path); @@ -980,15 +984,12 @@ private: void flushLine(); /* Return the set of (in)valid paths. */ - PathSet checkPathValidity(bool returnValid, bool checkHash); - - /* Abort the goal if `path' failed to build. */ - bool pathFailed(const Path & path); + StorePathSet checkPathValidity(bool returnValid, bool checkHash); /* Forcibly kill the child process, if any. */ void killChild(); - Path addHashRewrite(const Path & path); + void addHashRewrite(const StorePath & path); void repairClosure(); @@ -999,23 +1000,23 @@ private: void done(BuildResult::Status status, const string & msg = ""); - PathSet exportReferences(PathSet storePaths); + StorePathSet exportReferences(const StorePathSet & storePaths); }; const Path DerivationGoal::homeDir = "/homeless-shelter"; -DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, +DerivationGoal::DerivationGoal(StorePath && drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode) : Goal(worker) , useDerivation(true) - , drvPath(drvPath) + , drvPath(std::move(drvPath)) , wantedOutputs(wantedOutputs) , buildMode(buildMode) { state = &DerivationGoal::getDerivation; - name = (format("building of '%1%'") % drvPath).str(); + name = fmt("building of '%s'", worker.store.printStorePath(drvPath)); trace("created"); mcExpectedBuilds = std::make_unique>(worker.expectedBuilds); @@ -1023,16 +1024,16 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut } -DerivationGoal::DerivationGoal(const Path & drvPath, const BasicDerivation & drv, +DerivationGoal::DerivationGoal(StorePath && drvPath, const BasicDerivation & drv, Worker & worker, BuildMode buildMode) : Goal(worker) , useDerivation(false) - , drvPath(drvPath) + , drvPath(std::move(drvPath)) , buildMode(buildMode) { - this->drv = std::unique_ptr(new BasicDerivation(drv)); + this->drv = std::make_unique(BasicDerivation(drv)); state = &DerivationGoal::haveDerivation; - name = (format("building of %1%") % showPaths(drv.outputPaths())).str(); + name = fmt("building of %s", worker.store.showPaths(drv.outputPaths())); trace("created"); mcExpectedBuilds = std::make_unique>(worker.expectedBuilds); @@ -1142,7 +1143,7 @@ void DerivationGoal::loadDerivation() trace("loading derivation"); if (nrFailed != 0) { - printError(format("cannot build missing derivation '%1%'") % drvPath); + printError("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath)); done(BuildResult::MiscFailure); return; } @@ -1171,7 +1172,7 @@ void DerivationGoal::haveDerivation() worker.store.addTempRoot(i.second.path); /* Check what outputs paths are not already valid. */ - PathSet invalidOutputs = checkPathValidity(false, buildMode == bmRepair); + auto invalidOutputs = checkPathValidity(false, buildMode == bmRepair); /* If they are all valid, then we're done. */ if (invalidOutputs.size() == 0 && buildMode == bmNormal) { @@ -1179,7 +1180,7 @@ void DerivationGoal::haveDerivation() return; } - parsedDrv = std::make_unique(drvPath, *drv); + parsedDrv = std::make_unique(drvPath.clone(), *drv); /* We are first going to try to create the invalid output paths through substitutes. If that doesn't work, we'll build @@ -1200,7 +1201,9 @@ void DerivationGoal::outputsSubstituted() trace("all outputs substituted (maybe)"); if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback) { - done(BuildResult::TransientFailure, (format("some substitutes for the outputs of derivation '%1%' failed (usually happens due to networking issues); try '--fallback' to build derivation from source ") % drvPath).str()); + done(BuildResult::TransientFailure, + fmt("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))); return; } @@ -1227,14 +1230,15 @@ void DerivationGoal::outputsSubstituted() return; } if (buildMode == bmCheck && nrInvalid > 0) - throw Error(format("some outputs of '%1%' are not valid, so checking is not possible") % drvPath); + throw Error("some outputs of '%s' are not valid, so checking is not possible", + worker.store.printStorePath(drvPath)); /* Otherwise, at least one of the output paths could not be produced using a substitute. So we have to build instead. */ /* Make sure checkPathValidity() from now on checks all outputs. */ - wantedOutputs = PathSet(); + wantedOutputs.clear(); /* The inputs must be built before we can build this goal. */ if (useDerivation) @@ -1244,8 +1248,8 @@ void DerivationGoal::outputsSubstituted() for (auto & i : drv->inputSrcs) { if (worker.store.isValidPath(i)) continue; if (!settings.useSubstitutes) - throw Error(format("dependency '%1%' of '%2%' does not exist, and substitution is disabled") - % i % drvPath); + throw Error("dependency '%s' of '%s' does not exist, and substitution is disabled", + worker.store.printStorePath(i), worker.store.printStorePath(drvPath)); addWaitee(worker.makeSubstitutionGoal(i)); } @@ -1264,7 +1268,7 @@ void DerivationGoal::repairClosure() that produced those outputs. */ /* Get the output closure. */ - PathSet outputClosure; + StorePathSet outputClosure; for (auto & i : drv->outputs) { if (!wantOutput(i.first, wantedOutputs)) continue; worker.store.computeFSClosure(i.second.path, outputClosure); @@ -1277,26 +1281,26 @@ void DerivationGoal::repairClosure() /* Get all dependencies of this derivation so that we know which derivation is responsible for which path in the output closure. */ - PathSet inputClosure; + StorePathSet inputClosure; if (useDerivation) worker.store.computeFSClosure(drvPath, inputClosure); - std::map outputsToDrv; + std::map outputsToDrv; for (auto & i : inputClosure) - if (isDerivation(i)) { + if (i.isDerivation()) { Derivation drv = worker.store.derivationFromPath(i); for (auto & j : drv.outputs) - outputsToDrv[j.second.path] = i; + outputsToDrv.insert_or_assign(j.second.path.clone(), i.clone()); } /* Check each path (slow!). */ - PathSet broken; for (auto & i : outputClosure) { if (worker.pathContentsGood(i)) continue; - printError(format("found corrupted or missing path '%1%' in the output closure of '%2%'") % i % drvPath); - Path drvPath2 = outputsToDrv[i]; - if (drvPath2 == "") + printError("found corrupted or missing path '%s' in the output closure of '%s'", + worker.store.printStorePath(i), worker.store.printStorePath(drvPath)); + auto drvPath2 = outputsToDrv.find(i); + if (drvPath2 == outputsToDrv.end()) addWaitee(worker.makeSubstitutionGoal(i, Repair)); else - addWaitee(worker.makeDerivationGoal(drvPath2, PathSet(), bmRepair)); + addWaitee(worker.makeDerivationGoal(drvPath2->second, StringSet(), bmRepair)); } if (waitees.empty()) { @@ -1312,7 +1316,8 @@ void DerivationGoal::closureRepaired() { trace("closure repaired"); if (nrFailed > 0) - throw Error(format("some paths in the output closure of derivation '%1%' could not be repaired") % drvPath); + throw Error("some paths in the output closure of derivation '%s' could not be repaired", + worker.store.printStorePath(drvPath)); done(BuildResult::AlreadyValid); } @@ -1323,10 +1328,9 @@ void DerivationGoal::inputsRealised() if (nrFailed != 0) { if (!useDerivation) - throw Error(format("some dependencies of '%1%' are missing") % drvPath); - printError( - format("cannot build derivation '%1%': %2% dependencies couldn't be built") - % drvPath % nrFailed); + throw Error("some dependencies of '%s' are missing", worker.store.printStorePath(drvPath)); + printError("cannot build derivation '%s': %s dependencies couldn't be built", + worker.store.printStorePath(drvPath), nrFailed); done(BuildResult::DependencyFailed); return; } @@ -1349,19 +1353,21 @@ void DerivationGoal::inputsRealised() that are specified as inputs. */ assert(worker.store.isValidPath(i.first)); Derivation inDrv = worker.store.derivationFromPath(i.first); - for (auto & j : i.second) - if (inDrv.outputs.find(j) != inDrv.outputs.end()) - worker.store.computeFSClosure(inDrv.outputs[j].path, inputPaths); + for (auto & j : i.second) { + auto k = inDrv.outputs.find(j); + if (k != inDrv.outputs.end()) + worker.store.computeFSClosure(k->second.path, inputPaths); else throw Error( - format("derivation '%1%' requires non-existent output '%2%' from input derivation '%3%'") - % drvPath % j % i.first); + "derivation '%s' requires non-existent output '%s' from input derivation '%s'", + worker.store.printStorePath(drvPath), j, worker.store.printStorePath(i.first)); + } } /* Second, the input sources. */ worker.store.computeFSClosure(drv->inputSrcs, inputPaths); - debug(format("added input paths %1%") % showPaths(inputPaths)); + debug("added input paths %s", worker.store.showPaths(inputPaths)); /* Is this a fixed-output derivation? */ fixedOutput = drv->isFixedOutput(); @@ -1391,7 +1397,7 @@ void DerivationGoal::tryToBuild() few seconds and then retry this goal. */ PathSet lockFiles; for (auto & outPath : drv->outputPaths()) - lockFiles.insert(worker.store.toRealPath(outPath)); + lockFiles.insert(worker.store.toRealPath(worker.store.printStorePath(outPath))); if (!outputLocks.lockPaths(lockFiles, "", false)) { worker.waitForAWhile(shared_from_this()); @@ -1407,23 +1413,22 @@ void DerivationGoal::tryToBuild() build this derivation, so no further checks are necessary. */ validPaths = checkPathValidity(true, buildMode == bmRepair); if (buildMode != bmCheck && validPaths.size() == drv->outputs.size()) { - debug(format("skipping build of derivation '%1%', someone beat us to it") % drvPath); + debug("skipping build of derivation '%s', someone beat us to it", worker.store.printStorePath(drvPath)); outputLocks.setDeletion(true); done(BuildResult::AlreadyValid); return; } - missingPaths = drv->outputPaths(); + missingPaths = cloneStorePathSet(drv->outputPaths()); if (buildMode != bmCheck) for (auto & i : validPaths) missingPaths.erase(i); /* If any of the outputs already exist but are not valid, delete them. */ for (auto & i : drv->outputs) { - Path path = i.second.path; - if (worker.store.isValidPath(path)) continue; - debug(format("removing invalid path '%1%'") % path); - deletePath(worker.store.toRealPath(path)); + if (worker.store.isValidPath(i.second.path)) continue; + debug("removing invalid path '%s'", worker.store.printStorePath(i.second.path)); + deletePath(worker.store.toRealPath(worker.store.printStorePath(i.second.path))); } /* Don't do a remote build if the derivation has the attribute @@ -1436,11 +1441,11 @@ void DerivationGoal::tryToBuild() buildMode == bmRepair ? "repairing outputs of '%s'" : buildMode == bmCheck ? "checking outputs of '%s'" : nrRounds > 1 ? "building '%s' (round %d/%d)" : - "building '%s'", drvPath, curRound, nrRounds); - fmt("building '%s'", drvPath); + "building '%s'", worker.store.printStorePath(drvPath), curRound, nrRounds); + fmt("building '%s'", worker.store.printStorePath(drvPath)); if (hook) msg += fmt(" on '%s'", machineName); act = std::make_unique(*logger, lvlInfo, actBuild, msg, - Logger::Fields{drvPath, hook ? machineName : "", curRound, nrRounds}); + Logger::Fields{worker.store.printStorePath(drvPath), hook ? machineName : "", curRound, nrRounds}); mcRunningBuilds = std::make_unique>(worker.runningBuilds); worker.updateProgress(); }; @@ -1509,7 +1514,7 @@ void replaceValidPath(const Path & storePath, const Path tmpPath) if (pathExists(storePath)) rename(storePath.c_str(), oldPath.c_str()); if (rename(tmpPath.c_str(), storePath.c_str()) == -1) - throw SysError(format("moving '%1%' to '%2%'") % tmpPath % storePath); + throw SysError("moving '%s' to '%s'", tmpPath, storePath); deletePath(oldPath); } @@ -1534,7 +1539,7 @@ void DerivationGoal::buildDone() kill it. */ int status = hook ? hook->pid.kill() : pid.kill(); - debug(format("builder process for '%1%' finished") % drvPath); + debug("builder process for '%s' finished", worker.store.printStorePath(drvPath)); result.timesBuilt++; result.stopTime = time(0); @@ -1590,12 +1595,15 @@ void DerivationGoal::buildDone() /* Move paths out of the chroot for easier debugging of build failures. */ if (useChroot && buildMode == bmNormal) - for (auto & i : missingPaths) - if (pathExists(chrootRootDir + i)) - rename((chrootRootDir + i).c_str(), i.c_str()); + for (auto & i : missingPaths) { + auto p = worker.store.printStorePath(i); + if (pathExists(chrootRootDir + p)) + rename((chrootRootDir + p).c_str(), p.c_str()); + } - std::string msg = (format("builder for '%1%' %2%") - % drvPath % statusToString(status)).str(); + auto msg = fmt("builder for '%s' %s", + worker.store.printStorePath(drvPath), + statusToString(status)); if (!settings.verboseBuild && !logTail.empty()) { msg += (format("; last %d log lines:") % logTail.size()).str(); @@ -1616,13 +1624,13 @@ void DerivationGoal::buildDone() if (settings.postBuildHook != "") { Activity act(*logger, lvlInfo, actPostBuildHook, fmt("running post-build-hook '%s'", settings.postBuildHook), - Logger::Fields{drvPath}); + Logger::Fields{worker.store.printStorePath(drvPath)}); PushActivity pact(act.id); auto outputPaths = drv->outputPaths(); std::map hookEnvironment = getEnv(); - hookEnvironment.emplace("DRV_PATH", drvPath); - hookEnvironment.emplace("OUT_PATHS", chomp(concatStringsSep(" ", outputPaths))); + hookEnvironment.emplace("DRV_PATH", worker.store.printStorePath(drvPath)); + hookEnvironment.emplace("OUT_PATHS", chomp(concatStringsSep(" ", worker.store.printStorePathSet(outputPaths)))); RunOptions opts(settings.postBuildHook, {}); opts.environment = hookEnvironment; @@ -1675,7 +1683,7 @@ void DerivationGoal::buildDone() /* Delete unused redirected outputs (when doing hash rewriting). */ for (auto & i : redirectedOutputs) - deletePath(i.second); + deletePath(worker.store.toRealPath(worker.store.printStorePath(i.second))); /* Delete the chroot (if we were using one). */ autoDelChroot.reset(); /* this runs the destructor */ @@ -1740,7 +1748,7 @@ HookReply DerivationGoal::tryBuildHook() << "try" << (worker.getNrLocalBuilds() < settings.maxBuildJobs ? 1 : 0) << drv->platform - << drvPath + << worker.store.printStorePath(drvPath) << parsedDrv->getRequiredSystemFeatures(); worker.hook->sink.flush(); @@ -1773,7 +1781,7 @@ HookReply DerivationGoal::tryBuildHook() else if (reply == "postpone") return rpPostpone; else if (reply != "accept") - throw Error(format("bad hook reply '%1%'") % reply); + throw Error("bad hook reply '%s'", reply); } catch (SysError & e) { if (e.errNo == EPIPE) { @@ -1791,11 +1799,11 @@ HookReply DerivationGoal::tryBuildHook() /* Tell the hook all the inputs that have to be copied to the remote system. */ - hook->sink << inputPaths; + writeStorePaths(worker.store, hook->sink, inputPaths); /* Tell the hooks the missing outputs that have to be copied back from the remote system. */ - hook->sink << missingPaths; + writeStorePaths(worker.store, hook->sink, missingPaths); hook->sink = FdSink(); hook->toHook.writeSide = -1; @@ -1812,10 +1820,10 @@ HookReply DerivationGoal::tryBuildHook() } -void chmod_(const Path & path, mode_t mode) +static void chmod_(const Path & path, mode_t mode) { if (chmod(path.c_str(), mode) == -1) - throw SysError(format("setting permissions on '%1%'") % path); + throw SysError("setting permissions on '%s'", path); } @@ -1826,33 +1834,25 @@ int childEntry(void * arg) } -PathSet DerivationGoal::exportReferences(PathSet storePaths) +StorePathSet DerivationGoal::exportReferences(const StorePathSet & storePaths) { - PathSet paths; - - for (auto storePath : storePaths) { - - /* Check that the store path is valid. */ - if (!worker.store.isInStore(storePath)) - throw BuildError(format("'exportReferencesGraph' contains a non-store path '%1%'") - % storePath); - - storePath = worker.store.toStorePath(storePath); + 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", storePath); + throw BuildError("cannot export references of path '%s' because it is not in the input closure of the derivation", worker.store.printStorePath(storePath)); - worker.store.computeFSClosure(storePath, paths); + worker.store.computeFSClosure(singleton(storePath), paths); } /* If there are derivations in the graph, then include their outputs as well. This is useful if you want to do things like passing all build-time dependencies of some path to a derivation that builds a NixOS DVD image. */ - PathSet paths2(paths); + auto paths2 = cloneStorePathSet(paths); for (auto & j : paths2) { - if (isDerivation(j)) { + if (j.isDerivation()) { Derivation drv = worker.store.derivationFromPath(j); for (auto & k : drv.outputs) worker.store.computeFSClosure(k.second.path, paths); @@ -1900,7 +1900,7 @@ void DerivationGoal::startBuilder() throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}", drv->platform, concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()), - drvPath, + worker.store.printStorePath(drvPath), settings.thisSystem, concatStringsSep(", ", settings.systemFeatures)); @@ -1916,12 +1916,12 @@ void DerivationGoal::startBuilder() auto noChroot = parsedDrv->getBoolAttr("__noChroot"); if (settings.sandboxMode == smEnabled) { if (noChroot) - throw Error(format("derivation '%1%' has '__noChroot' set, " - "but that's not allowed when 'sandbox' is 'true'") % drvPath); + throw Error("derivation '%s' has '__noChroot' set, " + "but that's not allowed when 'sandbox' is 'true'", worker.store.printStorePath(drvPath)); #if __APPLE__ if (additionalSandboxProfile != "") - throw Error(format("derivation '%1%' specifies a sandbox profile, " - "but this is only allowed when 'sandbox' is 'relaxed'") % 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; } @@ -1957,14 +1957,13 @@ void DerivationGoal::startBuilder() /* Create a temporary directory where the build will take place. */ - auto drvName = storePathToName(drvPath); - tmpDir = createTempDir("", "nix-build-" + drvName, false, false, 0700); + tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700); chownToBuilder(tmpDir); /* Substitute output placeholders with the actual output paths. */ for (auto & output : drv->outputs) - inputRewrites[hashPlaceholder(output.first)] = output.second.path; + inputRewrites[hashPlaceholder(output.first)] = worker.store.printStorePath(output.second.path); /* Construct the environment passed to the builder. */ initEnv(); @@ -1980,19 +1979,22 @@ void DerivationGoal::startBuilder() temporary build directory. The text files have the format used by `nix-store --register-validity'. However, the deriver fields are left empty. */ - string s = get(drv->env, "exportReferencesGraph"); + string s = get(drv->env, "exportReferencesGraph").value_or(""); Strings ss = tokenizeString(s); if (ss.size() % 2 != 0) throw BuildError(format("odd number of tokens in 'exportReferencesGraph': '%1%'") % s); for (Strings::iterator i = ss.begin(); i != ss.end(); ) { string fileName = *i++; - checkStoreName(fileName); /* !!! abuse of this function */ - Path storePath = *i++; + static std::regex regex("[A-Za-z_][A-Za-z0-9_.]*"); + if (!std::regex_match(fileName, regex)) + throw Error("invalid file name '%s' in 'exportReferencesGraph'", fileName); + + auto storePath = worker.store.parseStorePath(*i++); /* Write closure info to . */ writeFile(tmpDir + "/" + fileName, worker.store.makeValidityRegistration( - exportReferences({storePath}), false, false)); + exportReferences(singleton(storePath)), false, false)); } } @@ -2022,17 +2024,19 @@ void DerivationGoal::startBuilder() dirsInChroot[tmpDirInSandbox] = tmpDir; /* Add the closure of store paths to the chroot. */ - PathSet closure; + StorePathSet closure; for (auto & i : dirsInChroot) try { if (worker.store.isInStore(i.second.source)) - worker.store.computeFSClosure(worker.store.toStorePath(i.second.source), closure); + worker.store.computeFSClosure(worker.store.parseStorePath(worker.store.toStorePath(i.second.source)), closure); } catch (InvalidPath & e) { } catch (Error & e) { throw Error(format("while processing 'sandbox-paths': %s") % e.what()); } - for (auto & i : closure) - dirsInChroot[i] = i; + for (auto & i : closure) { + auto p = worker.store.printStorePath(i); + dirsInChroot.insert_or_assign(p, p); + } PathSet allowedPaths = settings.allowedImpureHostPrefixes; @@ -2054,7 +2058,8 @@ void DerivationGoal::startBuilder() } } if (!found) - throw Error(format("derivation '%1%' requested impure path '%2%', but it was not in allowed-impure-host-deps") % drvPath % i); + throw Error("derivation '%s' requested impure path '%s', but it was not in allowed-impure-host-deps", + worker.store.printStorePath(drvPath), i); dirsInChroot[i] = i; } @@ -2064,7 +2069,7 @@ void DerivationGoal::startBuilder() environment using bind-mounts. We put it in the Nix store to ensure that we can create hard-links to non-directory inputs in the fake Nix store in the chroot (see below). */ - chrootRootDir = worker.store.toRealPath(drvPath) + ".chroot"; + chrootRootDir = worker.store.toRealPath(worker.store.printStorePath(drvPath)) + ".chroot"; deletePath(chrootRootDir); /* Clean up the chroot directory automatically. */ @@ -2123,14 +2128,15 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of '%1%'") % chrootStoreDir); for (auto & i : inputPaths) { - Path r = worker.store.toRealPath(i); + auto p = worker.store.printStorePath(i); + Path r = worker.store.toRealPath(p); struct stat st; if (lstat(r.c_str(), &st)) - throw SysError(format("getting attributes of path '%1%'") % i); + throw SysError("getting attributes of path '%s'", p); if (S_ISDIR(st.st_mode)) - dirsInChroot[i] = r; + dirsInChroot.insert_or_assign(p, r); else - linkOrCopy(r, chrootRootDir + i); + linkOrCopy(r, chrootRootDir + p); } /* If we're repairing, checking or rebuilding part of a @@ -2139,7 +2145,7 @@ void DerivationGoal::startBuilder() (typically the dependencies of /bin/sh). Throw them out. */ for (auto & i : drv->outputs) - dirsInChroot.erase(i.second.path); + dirsInChroot.erase(worker.store.printStorePath(i.second.path)); #elif __APPLE__ /* We don't really have any parent prep work to do (yet?) @@ -2171,17 +2177,17 @@ void DerivationGoal::startBuilder() corrupt outputs in advance. So rewrite them as well. */ if (buildMode == bmRepair) for (auto & i : missingPaths) - if (worker.store.isValidPath(i) && pathExists(i)) { + if (worker.store.isValidPath(i) && pathExists(worker.store.printStorePath(i))) { addHashRewrite(i); - redirectedBadOutputs.insert(i); + redirectedBadOutputs.insert(i.clone()); } } if (useChroot && settings.preBuildHook != "" && dynamic_cast(drv.get())) { printMsg(lvlChatty, format("executing pre-build hook '%1%'") % settings.preBuildHook); - auto args = useChroot ? Strings({drvPath, chrootRootDir}) : - Strings({ drvPath }); + auto args = useChroot ? Strings({worker.store.printStorePath(drvPath), chrootRootDir}) : + Strings({ worker.store.printStorePath(drvPath) }); enum BuildHookState { stBegin, stExtraChrootDirs @@ -2448,7 +2454,7 @@ void DerivationGoal::initTmpDir() { there is no size constraint). */ if (!parsedDrv->getStructuredAttrs()) { - StringSet passAsFile = tokenizeString(get(drv->env, "passAsFile")); + StringSet passAsFile = tokenizeString(get(drv->env, "passAsFile").value_or("")); int fileNr = 0; for (auto & i : drv->env) { if (passAsFile.find(i.first) == passAsFile.end()) { @@ -2478,6 +2484,7 @@ void DerivationGoal::initTmpDir() { env["PWD"] = tmpDirInSandbox; } + void DerivationGoal::initEnv() { env.clear(); @@ -2549,7 +2556,7 @@ void DerivationGoal::writeStructuredAttrs() /* Add an "outputs" object containing the output paths. */ nlohmann::json outputs; for (auto & i : drv->outputs) - outputs[i.first] = rewriteStrings(i.second.path, inputRewrites); + outputs[i.first] = rewriteStrings(worker.store.printStorePath(i.second.path), inputRewrites); json["outputs"] = outputs; /* Handle exportReferencesGraph. */ @@ -2559,9 +2566,9 @@ void DerivationGoal::writeStructuredAttrs() std::ostringstream str; { JSONPlaceholder jsonRoot(str, true); - PathSet storePaths; + StorePathSet storePaths; for (auto & p : *i) - storePaths.insert(p.get()); + storePaths.insert(worker.store.parseStorePath(p.get())); worker.store.pathInfoToJSON(jsonRoot, exportReferences(storePaths), false, true); } @@ -2660,22 +2667,22 @@ struct RestrictedStore : public LocalFSStore std::string getUri() override { return next->getUri(); } - PathSet queryAllValidPaths() override + StorePathSet queryAllValidPaths() override { - PathSet paths; - for (auto & p : goal.inputPaths) paths.insert(p); - for (auto & p : goal.addedPaths) paths.insert(p); + StorePathSet paths; + for (auto & p : goal.inputPaths) paths.insert(p.clone()); + for (auto & p : goal.addedPaths) paths.insert(p.clone()); return paths; } - void queryPathInfoUncached(const Path & path, + void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept override { if (goal.isAllowed(path)) { try { /* Censor impure information. */ auto info = std::make_shared(*next->queryPathInfo(path)); - info->deriver.clear(); + info->deriver.reset(); info->registrationTime = 0; info->ultimate = false; info->sigs.clear(); @@ -2687,19 +2694,19 @@ struct RestrictedStore : public LocalFSStore callback(nullptr); }; - void queryReferrers(const Path & path, PathSet & referrers) override + void queryReferrers(const StorePath & path, StorePathSet & referrers) override { } - PathSet queryDerivationOutputs(const Path & path) override + StorePathSet queryDerivationOutputs(const StorePath & path) override { throw Error("queryDerivationOutputs"); } - StringSet queryDerivationOutputNames(const Path & path) override + StringSet queryDerivationOutputNames(const StorePath & path) override { throw Error("queryDerivationOutputNames"); } - Path queryPathFromHashPart(const string & hashPart) override + std::optional queryPathFromHashPart(const std::string & hashPart) override { throw Error("queryPathFromHashPart"); } - Path addToStore(const string & name, const Path & srcPath, + StorePath addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair) override { throw Error("addToStore"); } @@ -2712,7 +2719,7 @@ struct RestrictedStore : public LocalFSStore goal.addDependency(info.path); } - Path addToStoreFromDump(const string & dump, const string & name, + StorePath addToStoreFromDump(const string & dump, const string & name, bool recursive = true, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair) override { auto path = next->addToStoreFromDump(dump, name, recursive, hashAlgo, repair); @@ -2720,89 +2727,87 @@ struct RestrictedStore : public LocalFSStore return path; } - Path addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair = NoRepair) override + StorePath addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair = NoRepair) override { auto path = next->addTextToStore(name, s, references, repair); goal.addDependency(path); return path; } - void narFromPath(const Path & path, Sink & sink) override + void narFromPath(const StorePath & path, Sink & sink) override { if (!goal.isAllowed(path)) - throw InvalidPath("cannot dump unknown path '%s' in recursive Nix", path); + throw InvalidPath("cannot dump unknown path '%s' in recursive Nix", printStorePath(path)); LocalFSStore::narFromPath(path, sink); } - void ensurePath(const Path & path) override + void ensurePath(const StorePath & path) override { if (!goal.isAllowed(path)) - throw InvalidPath("cannot substitute unknown path '%s' in recursive Nix", path); + throw InvalidPath("cannot substitute unknown path '%s' in recursive Nix", printStorePath(path)); /* Nothing to be done; 'path' must already be valid. */ } - void buildPaths(const PathSet & paths, BuildMode buildMode) override + void buildPaths(const std::vector & paths, BuildMode buildMode) override { if (buildMode != bmNormal) throw Error("unsupported build mode"); - PathSet newPaths; + StorePathSet newPaths; for (auto & path : paths) { - DrvPathWithOutputs i = parseDrvPathWithOutputs(path); - if (isDerivation(i.first)) { - if (!goal.isAllowed(i.first)) - throw InvalidPath("cannot build unknown path '%s' in recursive Nix", i.first); - auto drv = derivationFromPath(i.first); + if (path.path.isDerivation()) { + if (!goal.isAllowed(path.path)) + throw InvalidPath("cannot build unknown path '%s' in recursive Nix", printStorePath(path.path)); + auto drv = derivationFromPath(path.path); for (auto & output : drv.outputs) - if (wantOutput(output.first, i.second)) - newPaths.insert(output.second.path); - } else if (!goal.isAllowed(path)) - throw InvalidPath("cannot build unknown path '%s' in recursive Nix", path); + if (wantOutput(output.first, path.outputs)) + newPaths.insert(output.second.path.clone()); + } else if (!goal.isAllowed(path.path)) + throw InvalidPath("cannot build unknown path '%s' in recursive Nix", printStorePath(path.path)); } next->buildPaths(paths, buildMode); - PathSet closure; + StorePathSet closure; next->computeFSClosure(newPaths, closure); for (auto & path : closure) goal.addDependency(path); } - BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode = bmNormal) override { unsupported("buildDerivation"); } - void addTempRoot(const Path & path) + void addTempRoot(const StorePath & path) override { } - void addIndirectRoot(const Path & path) + void addIndirectRoot(const Path & path) override { } - Roots findRoots() + Roots findRoots(bool censor) override { return Roots(); } - void collectGarbage(const GCOptions & options, GCResults & results) + void collectGarbage(const GCOptions & options, GCResults & results) override { } - void addSignatures(const Path & storePath, const StringSet & sigs) + void addSignatures(const StorePath & storePath, const StringSet & sigs) override { unsupported("addSignatures"); } - void queryMissing(const PathSet & targets, - PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown, - unsigned long long & downloadSize, unsigned long long & narSize) + void queryMissing(const std::vector & targets, + StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, + unsigned long long & downloadSize, unsigned long long & narSize) override { /* This is slightly impure since it leaks information to the client about what paths will be built/substituted or are already present. Probably not a big deal. */ - PathSet allowed; + std::vector allowed; for (auto & path : targets) { - DrvPathWithOutputs i = parseDrvPathWithOutputs(path); - if (goal.isAllowed(i.first)) - allowed.insert(i.first); + if (goal.isAllowed(path.path)) + allowed.emplace_back(path); else - unknown.insert(i.first); + unknown.insert(path.path.clone()); } next->queryMissing(allowed, willBuild, willSubstitute, @@ -2855,7 +2860,7 @@ void DerivationGoal::startDaemon() debug("received daemon connection"); - auto workerThread = std::thread([this, store, remote{std::move(remote)}]() { + auto workerThread = std::thread([store, remote{std::move(remote)}]() { FdSource from(remote.get()); FdSink to(remote.get()); try { @@ -2893,28 +2898,26 @@ void DerivationGoal::stopDaemon() } -void DerivationGoal::addDependency(const Path & path) +void DerivationGoal::addDependency(const StorePath & path) { - worker.store.assertStorePath(path); - if (isAllowed(path)) return; - addedPaths.insert(path); + addedPaths.insert(path.clone()); /* If we're doing a sandbox build, then we have to make the path appear in the sandbox. */ if (useChroot) { - debug("materialising '%s' in the sandbox", path); + debug("materialising '%s' in the sandbox", worker.store.printStorePath(path)); #if __linux__ - Path source = worker.store.toRealPath(path); - Path target = chrootRootDir + path; + Path source = worker.store.toRealPath(worker.store.printStorePath(path)); + Path target = chrootRootDir + worker.store.printStorePath(path); debug("bind-mounting %s -> %s", target, source); if (pathExists(target)) - throw Error("store path '%s' already exists in the sandbox", path); + throw Error("store path '%s' already exists in the sandbox", worker.store.printStorePath(path)); struct stat st; if (lstat(source.c_str(), &st)) @@ -2941,13 +2944,14 @@ void DerivationGoal::addDependency(const Path & path) int status = child.wait(); if (status != 0) - throw Error("could not add path '%s' to sandbox", path); + throw Error("could not add path '%s' to sandbox", worker.store.printStorePath(path)); } else linkOrCopy(source, target); #else - throw Error("don't know how to make path '%s' (produced by a recursive Nix call) appear in the sandbox", path); + 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 } @@ -3363,8 +3367,10 @@ void DerivationGoal::runChild() } /* Add all our input paths to the chroot */ - for (auto & i : inputPaths) - dirsInChroot[i] = i; + for (auto & i : inputPaths) { + auto p = worker.store.printStorePath(i); + dirsInChroot[p] = p; + } /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ if (settings.darwinLogSandboxViolations) { @@ -3380,13 +3386,13 @@ void DerivationGoal::runChild() /* Our rwx outputs */ sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & i : missingPaths) { - sandboxProfile += (format("\t(subpath \"%1%\")\n") % i.c_str()).str(); - } + for (auto & i : missingPaths) + sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(i)); + /* Also add redirected outputs to the chroot */ - for (auto & i : redirectedOutputs) { - sandboxProfile += (format("\t(subpath \"%1%\")\n") % i.second.c_str()).str(); - } + for (auto & i : redirectedOutputs) + sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(i.second)); + sandboxProfile += ")\n"; /* Our inputs (transitive dependencies and any impurities computed above) @@ -3405,19 +3411,19 @@ void DerivationGoal::runChild() if (lstat(path.c_str(), &st)) { if (i.second.optional && errno == ENOENT) continue; - throw SysError(format("getting attributes of path '%1%'") % path); + throw SysError("getting attributes of path '%s", path); } if (S_ISDIR(st.st_mode)) - sandboxProfile += (format("\t(subpath \"%1%\")\n") % path).str(); + sandboxProfile += fmt("\t(subpath \"%s\")\n", path); else - sandboxProfile += (format("\t(literal \"%1%\")\n") % path).str(); + sandboxProfile += fmt("\t(literal \"%s\")\n", path); } sandboxProfile += ")\n"; /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ sandboxProfile += "(allow file-read*\n"; for (auto & i : ancestry) { - sandboxProfile += (format("\t(literal \"%1%\")\n") % i.c_str()).str(); + sandboxProfile += fmt("\t(literal \"%s\")\n", i); } sandboxProfile += ")\n"; @@ -3458,8 +3464,7 @@ void DerivationGoal::runChild() #endif else { builder = drv->builder.c_str(); - string builderBasename = baseNameOf(drv->builder); - args.push_back(builderBasename); + args.push_back(std::string(baseNameOf(drv->builder))); } for (auto & i : drv->args) @@ -3473,7 +3478,7 @@ void DerivationGoal::runChild() try { logger = makeJSONLogger(*logger); - BasicDerivation drv2(*drv); + BasicDerivation & drv2(*drv); for (auto & e : drv2.env) e.second = rewriteStrings(e.second, inputRewrites); @@ -3506,16 +3511,15 @@ void DerivationGoal::runChild() /* 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'). */ -PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, const Strings & paths) +StorePathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, const Strings & paths) { - PathSet result; + StorePathSet result; for (auto & i : paths) { if (store.isStorePath(i)) - result.insert(i); - else if (drv.outputs.find(i) != drv.outputs.end()) - result.insert(drv.outputs.find(i)->second.path); - else throw BuildError( - format("derivation contains an illegal reference specifier '%1%'") % i); + result.insert(store.parseStorePath(i)); + else if (drv.outputs.count(i)) + result.insert(drv.outputs.find(i)->second.path.clone()); + else throw BuildError("derivation contains an illegal reference specifier '%s'", i); } return result; } @@ -3548,19 +3552,17 @@ void DerivationGoal::registerOutputs() /* The paths that can be referenced are the input closures, the output paths, and any paths that have been built via recursive Nix calls. */ - PathSet referenceablePaths; - for (auto & p : inputPaths) referenceablePaths.insert(p); - for (auto & i : drv->outputs) referenceablePaths.insert(i.second.path); - for (auto & p : addedPaths) referenceablePaths.insert(p); + StorePathSet referenceablePaths; + for (auto & p : inputPaths) referenceablePaths.insert(p.clone()); + for (auto & i : drv->outputs) referenceablePaths.insert(i.second.path.clone()); + for (auto & p : addedPaths) referenceablePaths.insert(p.clone()); /* Check whether the output paths were created, and grep each output path to determine what other paths it references. Also make all output paths read-only. */ for (auto & i : drv->outputs) { - Path path = i.second.path; - if (missingPaths.find(path) == missingPaths.end()) continue; - - ValidPathInfo info; + auto path = worker.store.printStorePath(i.second.path); + if (!missingPaths.count(i.second.path)) continue; Path actualPath = path; if (useChroot) { @@ -3577,22 +3579,25 @@ void DerivationGoal::registerOutputs() } if (needsHashRewrite()) { - Path redirected = redirectedOutputs[path]; - if (buildMode == bmRepair - && redirectedBadOutputs.find(path) != redirectedBadOutputs.end() - && pathExists(redirected)) - replaceValidPath(path, redirected); - if (buildMode == bmCheck && redirected != "") - actualPath = redirected; + auto r = redirectedOutputs.find(i.second.path); + if (r != redirectedOutputs.end()) { + auto redirected = worker.store.toRealPath(worker.store.printStorePath(r->second)); + if (buildMode == bmRepair + && redirectedBadOutputs.count(i.second.path) + && pathExists(redirected)) + replaceValidPath(path, redirected); + if (buildMode == bmCheck) + actualPath = redirected; + } } struct stat st; if (lstat(actualPath.c_str(), &st) == -1) { if (errno == ENOENT) throw BuildError( - format("builder for '%1%' failed to produce output path '%2%'") - % drvPath % path); - throw SysError(format("getting attributes of path '%1%'") % actualPath); + "builder for '%s' failed to produce output path '%s'", + worker.store.printStorePath(drvPath), path); + throw SysError("getting attributes of path '%s'", actualPath); } #ifndef __CYGWIN__ @@ -3629,6 +3634,8 @@ void DerivationGoal::registerOutputs() /* Check that fixed-output derivations produced the right outputs (i.e., the content hash should match the specified hash). */ + std::string ca; + if (fixedOutput) { bool recursive; Hash h; @@ -3645,7 +3652,7 @@ void DerivationGoal::registerOutputs() the derivation to its content-addressed location. */ Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath); - Path dest = worker.store.makeFixedOutputPath(recursive, h2, storePathToName(path)); + auto dest = worker.store.makeFixedOutputPath(recursive, h2, i.second.path.name()); if (h != h2) { @@ -3654,9 +3661,9 @@ void DerivationGoal::registerOutputs() worker.hashMismatch = true; delayedException = std::make_exception_ptr( BuildError("hash mismatch in fixed-output derivation '%s':\n wanted: %s\n got: %s", - dest, h.to_string(SRI), h2.to_string(SRI))); + worker.store.printStorePath(dest), h.to_string(SRI), h2.to_string(SRI))); - Path actualDest = worker.store.toRealPath(dest); + Path actualDest = worker.store.toRealPath(worker.store.printStorePath(dest)); if (worker.store.isValidPath(dest)) std::rethrow_exception(delayedException); @@ -3665,16 +3672,16 @@ void DerivationGoal::registerOutputs() PathLocks outputLocks({actualDest}); deletePath(actualDest); if (rename(actualPath.c_str(), actualDest.c_str()) == -1) - throw SysError(format("moving '%1%' to '%2%'") % actualPath % dest); + throw SysError("moving '%s' to '%s'", actualPath, worker.store.printStorePath(dest)); } - path = dest; + path = worker.store.printStorePath(dest); actualPath = actualDest; } else - assert(path == dest); + assert(worker.store.parseStorePath(path) == dest); - info.ca = makeFixedOutputCA(recursive, h2); + ca = makeFixedOutputCA(recursive, h2); } /* Get rid of all weird permissions. This also checks that @@ -3688,11 +3695,11 @@ void DerivationGoal::registerOutputs() verify later on whether nobody has messed with the store. */ debug("scanning for references inside '%1%'", path); HashResult hash; - PathSet references = scanForReferences(actualPath, referenceablePaths, hash); + auto references = worker.store.parseStorePathSet(scanForReferences(actualPath, worker.store.printStorePathSet(referenceablePaths), hash)); if (buildMode == bmCheck) { - if (!worker.store.isValidPath(path)) continue; - auto info = *worker.store.queryPathInfo(path); + if (!worker.store.isValidPath(worker.store.parseStorePath(path))) continue; + ValidPathInfo info(*worker.store.queryPathInfo(worker.store.parseStorePath(path))); if (hash.first != info.narHash) { worker.checkMismatch = true; if (settings.runDiffHook || settings.keepFailed) { @@ -3704,20 +3711,22 @@ void DerivationGoal::registerOutputs() handleDiffHook( buildUser ? buildUser->getUID() : getuid(), buildUser ? buildUser->getGID() : getgid(), - path, dst, drvPath, tmpDir); + path, dst, worker.store.printStorePath(drvPath), tmpDir); - throw NotDeterministic(format("derivation '%1%' may not be deterministic: output '%2%' differs from '%3%'") - % drvPath % path % dst); + throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs from '%s'", + worker.store.printStorePath(drvPath), path, dst); } else - throw NotDeterministic(format("derivation '%1%' may not be deterministic: output '%2%' differs") - % drvPath % path); + throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs", + worker.store.printStorePath(drvPath), path); } /* Since we verified the build, it's now ultimately trusted. */ if (!info.ultimate) { info.ultimate = true; worker.store.signPathInfo(info); - worker.store.registerValidPaths({info}); + ValidPathInfos infos; + infos.push_back(std::move(info)); + worker.store.registerValidPaths(infos); } continue; @@ -3725,29 +3734,30 @@ void DerivationGoal::registerOutputs() /* For debugging, print out the referenced and unreferenced paths. */ for (auto & i : inputPaths) { - PathSet::iterator j = references.find(i); + auto j = references.find(i); if (j == references.end()) - debug(format("unreferenced input: '%1%'") % i); + debug("unreferenced input: '%1%'", worker.store.printStorePath(i)); else - debug(format("referenced input: '%1%'") % i); + debug("referenced input: '%1%'", worker.store.printStorePath(i)); } if (curRound == nrRounds) { worker.store.optimisePath(actualPath); // FIXME: combine with scanForReferences() - worker.markContentsGood(path); + worker.markContentsGood(worker.store.parseStorePath(path)); } - info.path = path; + ValidPathInfo info(worker.store.parseStorePath(path)); info.narHash = hash.first; info.narSize = hash.second; - info.references = references; - info.deriver = drvPath; + info.references = std::move(references); + info.deriver = drvPath.clone(); info.ultimate = true; + info.ca = ca; worker.store.signPathInfo(info); if (!info.references.empty()) info.ca.clear(); - infos[i.first] = info; + infos.emplace(i.first, std::move(info)); } if (buildMode == bmCheck) return; @@ -3762,16 +3772,19 @@ void DerivationGoal::registerOutputs() for (auto i = prevInfos.begin(), j = infos.begin(); i != prevInfos.end(); ++i, ++j) if (!(*i == *j)) { result.isNonDeterministic = true; - Path prev = i->second.path + checkSuffix; + Path prev = worker.store.printStorePath(i->second.path) + checkSuffix; bool prevExists = keepPreviousRound && pathExists(prev); auto msg = prevExists - ? fmt("output '%1%' of '%2%' differs from '%3%' from previous round", i->second.path, drvPath, prev) - : fmt("output '%1%' of '%2%' differs from previous round", i->second.path, drvPath); + ? fmt("output '%s' of '%s' differs from '%s' from previous round", + worker.store.printStorePath(i->second.path), worker.store.printStorePath(drvPath), prev) + : fmt("output '%s' of '%s' differs from previous round", + worker.store.printStorePath(i->second.path), worker.store.printStorePath(drvPath)); handleDiffHook( buildUser ? buildUser->getUID() : getuid(), buildUser ? buildUser->getGID() : getgid(), - prev, i->second.path, drvPath, tmpDir); + prev, worker.store.printStorePath(i->second.path), + worker.store.printStorePath(drvPath), tmpDir); if (settings.enforceDeterminism) throw NotDeterministic(msg); @@ -3784,16 +3797,17 @@ void DerivationGoal::registerOutputs() /* If this is the first round of several, then move the output out of the way. */ if (nrRounds > 1 && curRound == 1 && curRound < nrRounds && keepPreviousRound) { for (auto & i : drv->outputs) { - Path prev = i.second.path + checkSuffix; + auto path = worker.store.printStorePath(i.second.path); + Path prev = path + checkSuffix; deletePath(prev); - Path dst = i.second.path + checkSuffix; - if (rename(i.second.path.c_str(), dst.c_str())) - throw SysError(format("renaming '%1%' to '%2%'") % i.second.path % dst); + Path dst = path + checkSuffix; + if (rename(path.c_str(), dst.c_str())) + throw SysError("renaming '%s' to '%s'", path, dst); } } if (curRound < nrRounds) { - prevInfos = infos; + prevInfos = std::move(infos); return; } @@ -3801,7 +3815,7 @@ void DerivationGoal::registerOutputs() if the result was not determistic? */ if (curRound == nrRounds) { for (auto & i : drv->outputs) { - Path prev = i.second.path + checkSuffix; + Path prev = worker.store.printStorePath(i.second.path) + checkSuffix; deletePath(prev); } } @@ -3826,7 +3840,7 @@ void DerivationGoal::checkOutputs(const std::map & outputs) { std::map outputsByPath; for (auto & output : outputs) - outputsByPath.emplace(output.second.path, output.second); + outputsByPath.emplace(worker.store.printStorePath(output.second.path), output.second); for (auto & output : outputs) { auto & outputName = output.first; @@ -3842,76 +3856,77 @@ void DerivationGoal::checkOutputs(const std::map & outputs) /* Compute the closure and closure size of some output. This is slightly tricky because some of its references (namely other outputs) may not be valid yet. */ - auto getClosure = [&](const Path & path) + auto getClosure = [&](const StorePath & path) { uint64_t closureSize = 0; - PathSet pathsDone; - std::queue pathsLeft; - pathsLeft.push(path); + StorePathSet pathsDone; + std::queue pathsLeft; + pathsLeft.push(path.clone()); while (!pathsLeft.empty()) { - auto path = pathsLeft.front(); + auto path = pathsLeft.front().clone(); pathsLeft.pop(); - if (!pathsDone.insert(path).second) continue; + if (!pathsDone.insert(path.clone()).second) continue; - auto i = outputsByPath.find(path); + auto i = outputsByPath.find(worker.store.printStorePath(path)); if (i != outputsByPath.end()) { closureSize += i->second.narSize; for (auto & ref : i->second.references) - pathsLeft.push(ref); + pathsLeft.push(ref.clone()); } else { auto info = worker.store.queryPathInfo(path); closureSize += info->narSize; for (auto & ref : info->references) - pathsLeft.push(ref); + pathsLeft.push(ref.clone()); } } - return std::make_pair(pathsDone, closureSize); + return std::make_pair(std::move(pathsDone), closureSize); }; auto applyChecks = [&](const Checks & checks) { if (checks.maxSize && info.narSize > *checks.maxSize) throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes", - info.path, info.narSize, *checks.maxSize); + 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", - info.path, closureSize, *checks.maxClosureSize); + worker.store.printStorePath(info.path), closureSize, *checks.maxClosureSize); } auto checkRefs = [&](const std::optional & value, bool allowed, bool recursive) { if (!value) return; - PathSet spec = parseReferenceSpecifiers(worker.store, *drv, *value); + auto spec = parseReferenceSpecifiers(worker.store, *drv, *value); - PathSet used = recursive ? getClosure(info.path).first : info.references; + auto used = recursive ? cloneStorePathSet(getClosure(info.path).first) : cloneStorePathSet(info.references); if (recursive && checks.ignoreSelfRefs) used.erase(info.path); - PathSet badPaths; + StorePathSet badPaths; for (auto & i : used) if (allowed) { if (!spec.count(i)) - badPaths.insert(i); + badPaths.insert(i.clone()); } else { if (spec.count(i)) - badPaths.insert(i); + badPaths.insert(i.clone()); } if (!badPaths.empty()) { string badPathsStr; for (auto & i : badPaths) { badPathsStr += "\n "; - badPathsStr += i; + badPathsStr += worker.store.printStorePath(i); } - throw BuildError("output '%s' is not allowed to refer to the following paths:%s", info.path, badPathsStr); + throw BuildError("output '%s' is not allowed to refer to the following paths:%s", + worker.store.printStorePath(info.path), badPathsStr); } }; @@ -3943,7 +3958,7 @@ void DerivationGoal::checkOutputs(const std::map & outputs) 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); + throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, worker.store.printStorePath(drvPath)); res.push_back(j->get()); } checks.disallowedRequisites = res; @@ -3980,7 +3995,7 @@ Path DerivationGoal::openLogFile() if (!settings.keepLog) return ""; - string baseName = baseNameOf(drvPath); + auto baseName = std::string(baseNameOf(worker.store.printStorePath(drvPath))); /* Create a log file. */ Path dir = fmt("%s/%s/%s/", worker.store.logDir, worker.store.drvsLogDir, string(baseName, 0, 2)); @@ -4019,9 +4034,7 @@ void DerivationGoal::deleteTmpDir(bool force) /* Don't keep temporary directories for builtins because they might have privileged stuff (like a copy of netrc). */ if (settings.keepFailed && !force && !drv->isBuiltin()) { - printError( - format("note: keeping build directory '%2%'") - % drvPath % tmpDir); + printError("note: keeping build directory '%s'", tmpDir); chmod(tmpDir.c_str(), 0755); } else @@ -4100,31 +4113,31 @@ void DerivationGoal::flushLine() } -PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash) +StorePathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash) { - PathSet result; + StorePathSet result; for (auto & i : drv->outputs) { if (!wantOutput(i.first, wantedOutputs)) continue; bool good = worker.store.isValidPath(i.second.path) && (!checkHash || worker.pathContentsGood(i.second.path)); - if (good == returnValid) result.insert(i.second.path); + if (good == returnValid) result.insert(i.second.path.clone()); } return result; } -Path DerivationGoal::addHashRewrite(const Path & path) +void DerivationGoal::addHashRewrite(const StorePath & path) { - string h1 = string(path, worker.store.storeDir.size() + 1, 32); - string h2 = string(hashString(htSHA256, "rewrite:" + drvPath + ":" + path).to_string(Base32, false), 0, 32); - Path p = worker.store.storeDir + "/" + h2 + string(path, worker.store.storeDir.size() + 33); - deletePath(p); - assert(path.size() == p.size()); + auto h1 = std::string(((std::string_view) path.to_string()).substr(0, 32)); + auto p = worker.store.makeStorePath( + "rewrite:" + std::string(drvPath.to_string()) + ":" + std::string(path.to_string()), + Hash(htSHA256), path.name()); + auto h2 = std::string(((std::string_view) p.to_string()).substr(0, 32)); + deletePath(worker.store.printStorePath(p)); inputRewrites[h1] = h2; outputRewrites[h2] = h1; - redirectedOutputs[path] = p; - return p; + redirectedOutputs.insert_or_assign(path.clone(), std::move(p)); } @@ -4162,7 +4175,7 @@ class SubstitutionGoal : public Goal private: /* The store path that should be realised through a substitute. */ - Path storePath; + StorePath storePath; /* The remaining substituters. */ std::list> subs; @@ -4198,7 +4211,7 @@ private: GoalState state; public: - SubstitutionGoal(const Path & storePath, Worker & worker, RepairFlag repair = NoRepair); + SubstitutionGoal(StorePath && storePath, Worker & worker, RepairFlag repair = NoRepair); ~SubstitutionGoal(); void timedOut() override { abort(); }; @@ -4207,7 +4220,7 @@ public: { /* "a$" ensures substitution goals happen before derivation goals. */ - return "a$" + storePathToName(storePath) + "$" + storePath; + return "a$" + std::string(storePath.name()) + "$" + worker.store.printStorePath(storePath); } void work() override; @@ -4224,7 +4237,7 @@ public: void handleChildOutput(int fd, const string & data) override; void handleEOF(int fd) override; - Path getStorePath() { return storePath; } + StorePath getStorePath() { return storePath.clone(); } void amDone(ExitCode result) override { @@ -4233,13 +4246,13 @@ public: }; -SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, RepairFlag repair) +SubstitutionGoal::SubstitutionGoal(StorePath && storePath, Worker & worker, RepairFlag repair) : Goal(worker) + , storePath(std::move(storePath)) , repair(repair) { - this->storePath = storePath; state = &SubstitutionGoal::init; - name = (format("substitution of '%1%'") % storePath).str(); + name = fmt("substitution of '%s'", worker.store.printStorePath(storePath)); trace("created"); maintainExpectedSubstitutions = std::make_unique>(worker.expectedSubstitutions); } @@ -4278,7 +4291,7 @@ void SubstitutionGoal::init() } if (settings.readOnlyMode) - throw Error(format("cannot substitute path '%1%' - no write access to the Nix store") % storePath); + throw Error("cannot substitute path '%s' - no write access to the Nix store", worker.store.printStorePath(storePath)); subs = settings.useSubstitutes ? getDefaultSubstituters() : std::list>(); @@ -4293,7 +4306,7 @@ void SubstitutionGoal::tryNext() if (subs.size() == 0) { /* None left. Terminate this goal and let someone else deal with it. */ - debug(format("path '%1%' is required, but there is no substituter that can build it") % storePath); + debug("path '%s' is required, but there is no substituter that can build it", worker.store.printStorePath(storePath)); /* Hack: don't indicate failure if there were no substituters. In that case the calling derivation should just do a @@ -4357,7 +4370,7 @@ void SubstitutionGoal::tryNext() && !info->checkSignatures(worker.store, worker.store.getPublicKeys())) { printError("warning: substituter '%s' does not have a valid signature for path '%s'", - sub->getUri(), storePath); + sub->getUri(), worker.store.printStorePath(storePath)); tryNext(); return; } @@ -4380,7 +4393,7 @@ void SubstitutionGoal::referencesValid() trace("all references realised"); if (nrFailed > 0) { - debug(format("some references of path '%1%' could not be realised") % storePath); + debug("some references of path '%s' could not be realised", worker.store.printStorePath(storePath)); amDone(nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed); return; } @@ -4419,7 +4432,7 @@ void SubstitutionGoal::tryToRun() /* Wake up the worker loop when we're done. */ Finally updateStats([this]() { outPipe.writeSide = -1; }); - Activity act(*logger, actSubstitute, Logger::Fields{storePath, sub->getUri()}); + Activity act(*logger, actSubstitute, Logger::Fields{worker.store.printStorePath(storePath), sub->getUri()}); PushActivity pact(act.id); copyStorePath(ref(sub), ref(worker.store.shared_from_this()), @@ -4466,10 +4479,9 @@ void SubstitutionGoal::finished() return; } - worker.markContentsGood(storePath); + worker.markContentsGood(storePath.clone()); - printMsg(lvlChatty, - format("substitution of path '%1%' succeeded") % storePath); + printMsg(lvlChatty, "substitution of path '%s' succeeded", worker.store.printStorePath(storePath)); maintainRunningSubstitutions.reset(); @@ -4535,13 +4547,13 @@ Worker::~Worker() } -GoalPtr Worker::makeDerivationGoal(const Path & path, +GoalPtr Worker::makeDerivationGoal(const StorePath & path, const StringSet & wantedOutputs, BuildMode buildMode) { - GoalPtr goal = derivationGoals[path].lock(); + GoalPtr goal = derivationGoals[path.clone()].lock(); // FIXME if (!goal) { - goal = std::make_shared(path, wantedOutputs, *this, buildMode); - derivationGoals[path] = goal; + goal = std::make_shared(path.clone(), wantedOutputs, *this, buildMode); + derivationGoals.insert_or_assign(path.clone(), goal); wakeUp(goal); } else (dynamic_cast(goal.get()))->addWantedOutputs(wantedOutputs); @@ -4549,21 +4561,21 @@ GoalPtr Worker::makeDerivationGoal(const Path & path, } -std::shared_ptr Worker::makeBasicDerivationGoal(const Path & drvPath, +std::shared_ptr Worker::makeBasicDerivationGoal(StorePath && drvPath, const BasicDerivation & drv, BuildMode buildMode) { - auto goal = std::make_shared(drvPath, drv, *this, buildMode); + auto goal = std::make_shared(std::move(drvPath), drv, *this, buildMode); wakeUp(goal); return goal; } -GoalPtr Worker::makeSubstitutionGoal(const Path & path, RepairFlag repair) +GoalPtr Worker::makeSubstitutionGoal(const StorePath & path, RepairFlag repair) { - GoalPtr goal = substitutionGoals[path].lock(); + GoalPtr goal = substitutionGoals[path.clone()].lock(); // FIXME if (!goal) { - goal = std::make_shared(path, *this, repair); - substitutionGoals[path] = goal; + goal = std::make_shared(path.clone(), *this, repair); + substitutionGoals.insert_or_assign(path.clone(), goal); wakeUp(goal); } return goal; @@ -4902,38 +4914,38 @@ unsigned int Worker::exitStatus() } -bool Worker::pathContentsGood(const Path & path) +bool Worker::pathContentsGood(const StorePath & path) { - std::map::iterator i = pathContentsGoodCache.find(path); + auto i = pathContentsGoodCache.find(path); if (i != pathContentsGoodCache.end()) return i->second; - printInfo(format("checking path '%1%'...") % path); + printInfo("checking path '%s'...", store.printStorePath(path)); auto info = store.queryPathInfo(path); bool res; - if (!pathExists(path)) + if (!pathExists(store.printStorePath(path))) res = false; else { - HashResult current = hashPath(info->narHash.type, path); + HashResult current = hashPath(info->narHash.type, store.printStorePath(path)); Hash nullHash(htSHA256); res = info->narHash == nullHash || info->narHash == current.first; } - pathContentsGoodCache[path] = res; - if (!res) printError(format("path '%1%' is corrupted or missing!") % path); + pathContentsGoodCache.insert_or_assign(path.clone(), res); + if (!res) printError("path '%s' is corrupted or missing!", store.printStorePath(path)); return res; } -void Worker::markContentsGood(const Path & path) +void Worker::markContentsGood(StorePath && path) { - pathContentsGoodCache[path] = true; + pathContentsGoodCache.insert_or_assign(std::move(path), true); } ////////////////////////////////////////////////////////////////////// -static void primeCache(Store & store, const PathSet & paths) +static void primeCache(Store & store, const std::vector & paths) { - PathSet willBuild, willSubstitute, unknown; + StorePathSet willBuild, willSubstitute, unknown; unsigned long long downloadSize, narSize; store.queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); @@ -4944,24 +4956,23 @@ static void primeCache(Store & store, const PathSet & paths) } -void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) +void LocalStore::buildPaths(const std::vector & drvPaths, BuildMode buildMode) { Worker worker(*this); primeCache(*this, drvPaths); Goals goals; - for (auto & i : drvPaths) { - DrvPathWithOutputs i2 = parseDrvPathWithOutputs(i); - if (isDerivation(i2.first)) - goals.insert(worker.makeDerivationGoal(i2.first, i2.second, buildMode)); + for (auto & path : drvPaths) { + if (path.path.isDerivation()) + goals.insert(worker.makeDerivationGoal(path.path, path.outputs, buildMode)); else - goals.insert(worker.makeSubstitutionGoal(i, buildMode == bmRepair ? Repair : NoRepair)); + goals.insert(worker.makeSubstitutionGoal(path.path, buildMode == bmRepair ? Repair : NoRepair)); } worker.run(goals); - PathSet failed; + StorePathSet failed; for (auto & i : goals) { if (i->getExitCode() != Goal::ecSuccess) { DerivationGoal * i2 = dynamic_cast(i.get()); @@ -4975,11 +4986,11 @@ void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) } -BuildResult LocalStore::buildDerivation(const Path & drvPath, const BasicDerivation & drv, +BuildResult LocalStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) { Worker worker(*this); - auto goal = worker.makeBasicDerivationGoal(drvPath, drv, buildMode); + auto goal = worker.makeBasicDerivationGoal(drvPath.clone(), drv, buildMode); BuildResult result; @@ -4995,12 +5006,12 @@ BuildResult LocalStore::buildDerivation(const Path & drvPath, const BasicDerivat } -void LocalStore::ensurePath(const Path & path) +void LocalStore::ensurePath(const StorePath & path) { /* If the path is already valid, we're done. */ if (isValidPath(path)) return; - primeCache(*this, {path}); + primeCache(*this, {StorePathWithOutputs(path)}); Worker worker(*this); GoalPtr goal = worker.makeSubstitutionGoal(path); @@ -5009,11 +5020,11 @@ void LocalStore::ensurePath(const Path & path) worker.run(goals); if (goal->getExitCode() != Goal::ecSuccess) - throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", path); + throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path)); } -void LocalStore::repairPath(const Path & path) +void LocalStore::repairPath(const StorePath & path) { Worker worker(*this); GoalPtr goal = worker.makeSubstitutionGoal(path, Repair); @@ -5024,13 +5035,13 @@ void LocalStore::repairPath(const Path & path) if (goal->getExitCode() != Goal::ecSuccess) { /* Since substituting the path didn't work, if we have a valid deriver, then rebuild the deriver. */ - auto deriver = queryPathInfo(path)->deriver; - if (deriver != "" && isValidPath(deriver)) { + auto info = queryPathInfo(path); + if (info->deriver && isValidPath(*info->deriver)) { goals.clear(); - goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair)); + goals.insert(worker.makeDerivationGoal(*info->deriver, StringSet(), bmRepair)); worker.run(goals); } else - throw Error(worker.exitStatus(), "cannot repair path '%s'", path); + throw Error(worker.exitStatus(), "cannot repair path '%s'", printStorePath(path)); } } diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc index b1af3b4fc..f6ae5d2e6 100644 --- a/src/libstore/builtins/fetchurl.cc +++ b/src/libstore/builtins/fetchurl.cc @@ -24,7 +24,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData) Path storePath = getAttr("out"); auto mainUrl = getAttr("url"); - bool unpack = get(drv.env, "unpack", "") == "1"; + bool unpack = get(drv.env, "unpack").value_or("") == "1"; /* Note: have to use a fresh downloader here because we're in a forked process. */ diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index d3c17e772..c53dfdd56 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -260,14 +260,8 @@ static void performOp(TunnelLogger * logger, ref store, switch (op) { case wopIsValidPath: { - /* 'readStorePath' could raise an error leading to the connection - being closed. To be able to recover from an invalid path error, - call 'startWork' early, and do 'assertStorePath' afterwards so - that the 'Error' exception handler doesn't close the - connection. */ - Path path = readString(from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); - store->assertStorePath(path); bool result = store->isValidPath(path); logger->stopWork(); to << result; @@ -275,34 +269,36 @@ static void performOp(TunnelLogger * logger, ref store, } case wopQueryValidPaths: { - PathSet paths = readStorePaths(*store, from); + auto paths = readStorePaths(*store, from); logger->startWork(); - PathSet res = store->queryValidPaths(paths); + auto res = store->queryValidPaths(paths); logger->stopWork(); - to << res; + writeStorePaths(*store, to, res); break; } case wopHasSubstitutes: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); - PathSet res = store->querySubstitutablePaths({path}); + StorePathSet paths; // FIXME + paths.insert(path.clone()); + auto res = store->querySubstitutablePaths(paths); logger->stopWork(); - to << (res.find(path) != res.end()); + to << (res.count(path) != 0); break; } case wopQuerySubstitutablePaths: { - PathSet paths = readStorePaths(*store, from); + auto paths = readStorePaths(*store, from); logger->startWork(); - PathSet res = store->querySubstitutablePaths(paths); + auto res = store->querySubstitutablePaths(paths); logger->stopWork(); - to << res; + writeStorePaths(*store, to, res); break; } case wopQueryPathHash: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); auto hash = store->queryPathInfo(path)->narHash; logger->stopWork(); @@ -314,23 +310,24 @@ static void performOp(TunnelLogger * logger, ref store, case wopQueryReferrers: case wopQueryValidDerivers: case wopQueryDerivationOutputs: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); - PathSet paths; + StorePathSet paths; if (op == wopQueryReferences) - paths = store->queryPathInfo(path)->references; + for (auto & i : store->queryPathInfo(path)->references) + paths.insert(i.clone()); else if (op == wopQueryReferrers) store->queryReferrers(path, paths); else if (op == wopQueryValidDerivers) paths = store->queryValidDerivers(path); else paths = store->queryDerivationOutputs(path); logger->stopWork(); - to << paths; + writeStorePaths(*store, to, paths); break; } case wopQueryDerivationOutputNames: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); StringSet names; names = store->queryDerivationOutputNames(path); @@ -340,20 +337,20 @@ static void performOp(TunnelLogger * logger, ref store, } case wopQueryDeriver: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); - auto deriver = store->queryPathInfo(path)->deriver; + auto info = store->queryPathInfo(path); logger->stopWork(); - to << deriver; + to << (info->deriver ? store->printStorePath(*info->deriver) : ""); break; } case wopQueryPathFromHashPart: { - string hashPart = readString(from); + auto hashPart = readString(from); logger->startWork(); - Path path = store->queryPathFromHashPart(hashPart); + auto path = store->queryPathFromHashPart(hashPart); logger->stopWork(); - to << path; + to << (path ? store->printStorePath(*path) : ""); break; } @@ -383,26 +380,26 @@ static void performOp(TunnelLogger * logger, ref store, logger->startWork(); if (!savedRegular.regular) throw Error("regular file expected"); - Path path = store->addToStoreFromDump(recursive ? *savedNAR.data : savedRegular.s, baseName, recursive, hashAlgo); + auto path = store->addToStoreFromDump(recursive ? *savedNAR.data : savedRegular.s, baseName, recursive, hashAlgo); logger->stopWork(); - to << path; + to << store->printStorePath(path); break; } case wopAddTextToStore: { string suffix = readString(from); string s = readString(from); - PathSet refs = readStorePaths(*store, from); + auto refs = readStorePaths(*store, from); logger->startWork(); - Path path = store->addTextToStore(suffix, s, refs, NoRepair); + auto path = store->addTextToStore(suffix, s, refs, NoRepair); logger->stopWork(); - to << path; + to << store->printStorePath(path); break; } case wopExportPath: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); readInt(from); // obsolete logger->startWork(); TunnelSink sink(to); @@ -415,15 +412,19 @@ static void performOp(TunnelLogger * logger, ref store, case wopImportPaths: { logger->startWork(); TunnelSource source(from, to); - Paths paths = store->importPaths(source, nullptr, + auto paths = store->importPaths(source, nullptr, trusted ? NoCheckSigs : CheckSigs); logger->stopWork(); - to << paths; + Strings paths2; + for (auto & i : paths) paths2.push_back(store->printStorePath(i)); + to << paths2; break; } case wopBuildPaths: { - PathSet drvs = readStorePaths(*store, from); + std::vector drvs; + for (auto & s : readStrings(from)) + drvs.push_back(store->parseDrvPathWithOutputs(s)); BuildMode mode = bmNormal; if (GET_PROTOCOL_MINOR(clientVersion) >= 15) { mode = (BuildMode) readInt(from); @@ -441,7 +442,7 @@ static void performOp(TunnelLogger * logger, ref store, } case wopBuildDerivation: { - Path drvPath = readStorePath(*store, from); + auto drvPath = store->parseStorePath(readString(from)); BasicDerivation drv; readDerivation(from, *store, drv); BuildMode buildMode = (BuildMode) readInt(from); @@ -455,7 +456,7 @@ static void performOp(TunnelLogger * logger, ref store, } case wopEnsurePath: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); store->ensurePath(path); logger->stopWork(); @@ -464,7 +465,7 @@ static void performOp(TunnelLogger * logger, ref store, } case wopAddTempRoot: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); store->addTempRoot(path); logger->stopWork(); @@ -502,7 +503,7 @@ static void performOp(TunnelLogger * logger, ref store, for (auto & [target, links] : roots) for (auto & link : links) - to << link << target; + to << link << store->printStorePath(target); break; } @@ -510,7 +511,7 @@ static void performOp(TunnelLogger * logger, ref store, case wopCollectGarbage: { GCOptions options; options.action = (GCOptions::GCAction) readInt(from); - options.pathsToDelete = readStorePaths(*store, from); + options.pathsToDelete = readStorePaths(*store, from); from >> options.ignoreLiveness >> options.maxFreed; // obsolete fields readInt(from); @@ -568,44 +569,52 @@ static void performOp(TunnelLogger * logger, ref store, } case wopQuerySubstitutablePathInfo: { - Path path = absPath(readString(from)); + auto path = store->parseStorePath(readString(from)); logger->startWork(); SubstitutablePathInfos infos; - store->querySubstitutablePathInfos({path}, infos); + StorePathSet paths; + paths.insert(path.clone()); // FIXME + store->querySubstitutablePathInfos(paths, infos); logger->stopWork(); - SubstitutablePathInfos::iterator i = infos.find(path); + auto i = infos.find(path); if (i == infos.end()) to << 0; else { - to << 1 << i->second.deriver << i->second.references << i->second.downloadSize << i->second.narSize; + to << 1 + << (i->second.deriver ? store->printStorePath(*i->second.deriver) : ""); + writeStorePaths(*store, to, i->second.references); + to << i->second.downloadSize + << i->second.narSize; } break; } case wopQuerySubstitutablePathInfos: { - PathSet paths = readStorePaths(*store, from); + auto paths = readStorePaths(*store, from); logger->startWork(); SubstitutablePathInfos infos; store->querySubstitutablePathInfos(paths, infos); logger->stopWork(); to << infos.size(); for (auto & i : infos) { - to << i.first << i.second.deriver << i.second.references - << i.second.downloadSize << i.second.narSize; + to << store->printStorePath(i.first) + << (i.second.deriver ? store->printStorePath(*i.second.deriver) : ""); + writeStorePaths(*store, to, i.second.references); + to << i.second.downloadSize << i.second.narSize; } break; } case wopQueryAllValidPaths: { logger->startWork(); - PathSet paths = store->queryAllValidPaths(); + auto paths = store->queryAllValidPaths(); logger->stopWork(); - to << paths; + writeStorePaths(*store, to, paths); break; } case wopQueryPathInfo: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); std::shared_ptr info; logger->startWork(); try { @@ -617,8 +626,10 @@ static void performOp(TunnelLogger * logger, ref store, if (info) { if (GET_PROTOCOL_MINOR(clientVersion) >= 17) to << 1; - to << info->deriver << info->narHash.to_string(Base16, false) << info->references - << info->registrationTime << info->narSize; + to << (info->deriver ? store->printStorePath(*info->deriver) : "") + << info->narHash.to_string(Base16, false); + writeStorePaths(*store, to, info->references); + to << info->registrationTime << info->narSize; if (GET_PROTOCOL_MINOR(clientVersion) >= 16) { to << info->ultimate << info->sigs @@ -651,7 +662,7 @@ static void performOp(TunnelLogger * logger, ref store, } case wopAddSignatures: { - Path path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); StringSet sigs = readStrings(from); logger->startWork(); if (!trusted) @@ -663,22 +674,21 @@ static void performOp(TunnelLogger * logger, ref store, } case wopNarFromPath: { - auto path = readStorePath(*store, from); + auto path = store->parseStorePath(readString(from)); logger->startWork(); logger->stopWork(); - dumpPath(path, to); + dumpPath(store->printStorePath(path), to); break; } case wopAddToStoreNar: { bool repair, dontCheckSigs; - ValidPathInfo info; - info.path = readStorePath(*store, from); - from >> info.deriver; - if (!info.deriver.empty()) - store->assertStorePath(info.deriver); + ValidPathInfo info(store->parseStorePath(readString(from))); + auto deriver = readString(from); + if (deriver != "") + info.deriver = store->parseStorePath(deriver); info.narHash = Hash(readString(from), htSHA256); - info.references = readStorePaths(*store, from); + info.references = readStorePaths(*store, from); from >> info.registrationTime >> info.narSize >> info.ultimate; info.sigs = readStrings(from); from >> info.ca >> repair >> dontCheckSigs; @@ -709,13 +719,18 @@ static void performOp(TunnelLogger * logger, ref store, } case wopQueryMissing: { - PathSet targets = readStorePaths(*store, from); + std::vector targets; + for (auto & s : readStrings(from)) + targets.push_back(store->parseDrvPathWithOutputs(s)); logger->startWork(); - PathSet willBuild, willSubstitute, unknown; + StorePathSet willBuild, willSubstitute, unknown; unsigned long long downloadSize, narSize; store->queryMissing(targets, willBuild, willSubstitute, unknown, downloadSize, narSize); logger->stopWork(); - to << willBuild << willSubstitute << unknown << downloadSize << narSize; + writeStorePaths(*store, to, willBuild); + writeStorePaths(*store, to, willSubstitute); + writeStorePaths(*store, to, unknown); + to << downloadSize << narSize; break; } diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 23fcfb281..726e34479 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -21,17 +21,39 @@ void DerivationOutput::parseHashInfo(bool & recursive, Hash & hash) const HashType hashType = parseHashType(algo); if (hashType == htUnknown) - throw Error(format("unknown hash algorithm '%1%'") % algo); + throw Error("unknown hash algorithm '%s'", algo); hash = Hash(this->hash, hashType); } -Path BasicDerivation::findOutput(const string & id) const +BasicDerivation::BasicDerivation(const BasicDerivation & other) + : platform(other.platform) + , builder(other.builder) + , args(other.args) + , env(other.env) +{ + for (auto & i : other.outputs) + outputs.insert_or_assign(i.first, + DerivationOutput(i.second.path.clone(), std::string(i.second.hashAlgo), std::string(i.second.hash))); + for (auto & i : other.inputSrcs) + inputSrcs.insert(i.clone()); +} + + +Derivation::Derivation(const Derivation & other) + : BasicDerivation(other) +{ + for (auto & i : other.inputDrvs) + inputDrvs.insert_or_assign(i.first.clone(), i.second); +} + + +const StorePath & BasicDerivation::findOutput(const string & id) const { auto i = outputs.find(id); if (i == outputs.end()) - throw Error(format("derivation has no output '%1%'") % id); + throw Error("derivation has no output '%s'", id); return i->second.path; } @@ -42,18 +64,17 @@ bool BasicDerivation::isBuiltin() const } -Path writeDerivation(ref store, +StorePath writeDerivation(ref store, const Derivation & drv, const string & name, RepairFlag repair) { - PathSet references; - references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end()); + auto references = cloneStorePathSet(drv.inputSrcs); for (auto & i : drv.inputDrvs) - references.insert(i.first); + references.insert(i.first.clone()); /* Note that the outputs of a derivation are *not* references (that can be missing (of course) and should not necessarily be held during a garbage collection). */ string suffix = name + drvExtension; - string contents = drv.unparse(); + string contents = drv.unparse(*store, false); return settings.readOnlyMode ? store->computeStorePathForText(suffix, contents, references) : store->addTextToStore(suffix, contents, references, repair); @@ -121,7 +142,7 @@ static StringSet parseStrings(std::istream & str, bool arePaths) } -static Derivation parseDerivation(const string & s) +static Derivation parseDerivation(const Store & store, const string & s) { Derivation drv; istringstream_nocopy str(s); @@ -129,13 +150,12 @@ static Derivation parseDerivation(const string & s) /* Parse the list of outputs. */ while (!endOfList(str)) { - DerivationOutput out; - expect(str, "("); string id = parseString(str); - expect(str, ","); out.path = parsePath(str); - expect(str, ","); out.hashAlgo = parseString(str); - expect(str, ","); out.hash = parseString(str); + expect(str, "("); std::string id = parseString(str); + expect(str, ","); auto path = store.parseStorePath(parsePath(str)); + expect(str, ","); auto hashAlgo = parseString(str); + expect(str, ","); auto hash = parseString(str); expect(str, ")"); - drv.outputs[id] = out; + drv.outputs.emplace(id, DerivationOutput(std::move(path), std::move(hashAlgo), std::move(hash))); } /* Parse the list of input derivations. */ @@ -144,11 +164,11 @@ static Derivation parseDerivation(const string & s) expect(str, "("); Path drvPath = parsePath(str); expect(str, ",["); - drv.inputDrvs[drvPath] = parseStrings(str, false); + drv.inputDrvs.insert_or_assign(store.parseStorePath(drvPath), parseStrings(str, false)); expect(str, ")"); } - expect(str, ",["); drv.inputSrcs = parseStrings(str, true); + expect(str, ",["); drv.inputSrcs = store.parseStorePathSet(parseStrings(str, true)); expect(str, ","); drv.platform = parseString(str); expect(str, ","); drv.builder = parseString(str); @@ -171,25 +191,24 @@ static Derivation parseDerivation(const string & s) } -Derivation readDerivation(const Path & drvPath) +Derivation readDerivation(const Store & store, const Path & drvPath) { try { - return parseDerivation(readFile(drvPath)); + return parseDerivation(store, readFile(drvPath)); } catch (FormatError & e) { throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg()); } } -Derivation Store::derivationFromPath(const Path & drvPath) +Derivation Store::derivationFromPath(const StorePath & drvPath) { - assertStorePath(drvPath); ensurePath(drvPath); auto accessor = getFSAccessor(); try { - return parseDerivation(accessor->readFile(drvPath)); + return parseDerivation(*this, accessor->readFile(printStorePath(drvPath))); } catch (FormatError & e) { - throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg()); + throw Error("error parsing derivation '%s': %s", printStorePath(drvPath), e.msg()); } } @@ -220,33 +239,56 @@ static void printStrings(string & res, ForwardIterator i, ForwardIterator j) } -string Derivation::unparse() const +string Derivation::unparse(const Store & store, bool maskOutputs, + std::map * actualInputs) const { string s; s.reserve(65536); s += "Derive(["; - bool first = true; - for (auto & i : outputs) { - if (first) first = false; else s += ','; - s += '('; printString(s, i.first); - s += ','; printString(s, i.second.path); - s += ','; printString(s, i.second.hashAlgo); - s += ','; printString(s, i.second.hash); - s += ')'; + StringSet maskedOutputs; + + if (maskOutputs) { + bool first = true; + maskedOutputs = tokenizeString(get(env, "outputs").value_or("out"), " "); + for (auto & i : maskedOutputs) { + if (first) first = false; else s += ','; + s += '('; printString(s, i); + s += ",\"\",\"\",\"\")"; + } + } else { + bool first = true; + for (auto & i : outputs) { + if (first) first = false; else s += ','; + s += '('; printString(s, i.first); + s += ','; printString(s, store.printStorePath(i.second.path)); + s += ','; printString(s, i.second.hashAlgo); + s += ','; printString(s, i.second.hash); + s += ')'; + } } s += "],["; - first = true; - for (auto & i : inputDrvs) { - if (first) first = false; else s += ','; - s += '('; printString(s, i.first); - s += ','; printStrings(s, i.second.begin(), i.second.end()); - s += ')'; + bool first = true; + if (actualInputs) { + for (auto & i : *actualInputs) { + if (first) first = false; else s += ','; + s += '('; printString(s, i.first); + s += ','; printStrings(s, i.second.begin(), i.second.end()); + s += ')'; + } + } else { + for (auto & i : inputDrvs) { + if (first) first = false; else s += ','; + s += '('; printString(s, store.printStorePath(i.first)); + s += ','; printStrings(s, i.second.begin(), i.second.end()); + s += ')'; + } } s += "],"; - printStrings(s, inputSrcs.begin(), inputSrcs.end()); + auto paths = store.printStorePathSet(inputSrcs); // FIXME: slow + printStrings(s, paths.begin(), paths.end()); s += ','; printString(s, platform); s += ','; printString(s, builder); @@ -257,7 +299,7 @@ string Derivation::unparse() const for (auto & i : env) { if (first) first = false; else s += ','; s += '('; printString(s, i.first); - s += ','; printString(s, i.second); + s += ','; printString(s, maskOutputs && maskedOutputs.count(i.first) ? "" : i.second); s += ')'; } @@ -267,6 +309,7 @@ string Derivation::unparse() const } +// FIXME: remove bool isDerivation(const string & fileName) { return hasSuffix(fileName, drvExtension); @@ -304,7 +347,7 @@ DrvHashes drvHashes; paths have been replaced by the result of a recursive call to this function, and that for fixed-output derivations we return a hash of its output path. */ -Hash hashDerivationModulo(Store & store, Derivation drv) +Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutputs) { /* Return a fixed hash for fixed-output derivations. */ if (drv.isFixedOutput()) { @@ -312,42 +355,41 @@ Hash hashDerivationModulo(Store & store, Derivation drv) return hashString(htSHA256, "fixed:out:" + i->second.hashAlgo + ":" + i->second.hash + ":" - + i->second.path); + + store.printStorePath(i->second.path)); } /* For other derivations, replace the inputs paths with recursive calls to this function.*/ - DerivationInputs inputs2; + std::map inputs2; for (auto & i : drv.inputDrvs) { - Hash h = drvHashes[i.first]; - if (!h) { + auto h = drvHashes.find(i.first); + if (h == drvHashes.end()) { assert(store.isValidPath(i.first)); - Derivation drv2 = readDerivation(store.toRealPath(i.first)); - h = hashDerivationModulo(store, drv2); - drvHashes[i.first] = h; + h = drvHashes.insert_or_assign(i.first.clone(), hashDerivationModulo(store, + readDerivation(store, store.toRealPath(store.printStorePath(i.first))), false)).first; } - inputs2[h.to_string(Base16, false)] = i.second; + inputs2.insert_or_assign(h->second.to_string(Base16, false), i.second); } - drv.inputDrvs = inputs2; - return hashString(htSHA256, drv.unparse()); + return hashString(htSHA256, drv.unparse(store, maskOutputs, &inputs2)); } -DrvPathWithOutputs parseDrvPathWithOutputs(const string & s) +StorePathWithOutputs Store::parseDrvPathWithOutputs(const std::string & s) { size_t n = s.find("!"); return n == s.npos - ? DrvPathWithOutputs(s, std::set()) - : DrvPathWithOutputs(string(s, 0, n), tokenizeString >(string(s, n + 1), ",")); + ? StorePathWithOutputs{parseStorePath(s), std::set()} + : StorePathWithOutputs{parseStorePath(std::string_view(s.data(), n)), + tokenizeString>(string(s, n + 1), ",")}; } -Path makeDrvPathWithOutputs(const Path & drvPath, const std::set & outputs) +std::string StorePathWithOutputs::to_string(const Store & store) const { return outputs.empty() - ? drvPath - : drvPath + "!" + concatStringsSep(",", outputs); + ? store.printStorePath(path) + : store.printStorePath(path) + "!" + concatStringsSep(",", outputs); } @@ -357,28 +399,28 @@ bool wantOutput(const string & output, const std::set & wanted) } -PathSet BasicDerivation::outputPaths() const +StorePathSet BasicDerivation::outputPaths() const { - PathSet paths; + StorePathSet paths; for (auto & i : outputs) - paths.insert(i.second.path); + paths.insert(i.second.path.clone()); return paths; } -Source & readDerivation(Source & in, Store & store, BasicDerivation & drv) +Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv) { drv.outputs.clear(); auto nr = readNum(in); for (size_t n = 0; n < nr; n++) { auto name = readString(in); - DerivationOutput o; - in >> o.path >> o.hashAlgo >> o.hash; - store.assertStorePath(o.path); - drv.outputs[name] = o; + auto path = store.parseStorePath(readString(in)); + auto hashAlgo = readString(in); + auto hash = readString(in); + drv.outputs.emplace(name, DerivationOutput(std::move(path), std::move(hashAlgo), std::move(hash))); } - drv.inputSrcs = readStorePaths(store, in); + drv.inputSrcs = readStorePaths(store, in); in >> drv.platform >> drv.builder; drv.args = readStrings(in); @@ -393,16 +435,16 @@ Source & readDerivation(Source & in, Store & store, BasicDerivation & drv) } -Sink & operator << (Sink & out, const BasicDerivation & drv) +void writeDerivation(Sink & out, const Store & store, const BasicDerivation & drv) { out << drv.outputs.size(); for (auto & i : drv.outputs) - out << i.first << i.second.path << i.second.hashAlgo << i.second.hash; - out << drv.inputSrcs << drv.platform << drv.builder << drv.args; + out << i.first << store.printStorePath(i.second.path) << i.second.hashAlgo << i.second.hash; + writeStorePaths(store, out, drv.inputSrcs); + out << drv.platform << drv.builder << drv.args; out << drv.env.size(); for (auto & i : drv.env) out << i.first << i.second; - return out; } diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 8e02c9bc5..c2df66229 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -10,26 +10,18 @@ namespace nix { -/* Extension of derivations in the Nix store. */ -const string drvExtension = ".drv"; - - /* Abstract syntax of derivations. */ struct DerivationOutput { - Path path; - string hashAlgo; /* hash used for expected hash computation */ - string hash; /* expected hash, may be null */ - DerivationOutput() - { - } - DerivationOutput(Path path, string hashAlgo, string hash) - { - this->path = path; - this->hashAlgo = hashAlgo; - this->hash = hash; - } + StorePath path; + std::string hashAlgo; /* hash used for expected hash computation */ + std::string hash; /* expected hash, may be null */ + DerivationOutput(StorePath && path, std::string && hashAlgo, std::string && hash) + : path(std::move(path)) + , hashAlgo(std::move(hashAlgo)) + , hash(std::move(hash)) + { } void parseHashInfo(bool & recursive, Hash & hash) const; }; @@ -37,24 +29,26 @@ typedef std::map DerivationOutputs; /* For inputs that are sub-derivations, we specify exactly which output IDs we are interested in. */ -typedef std::map DerivationInputs; +typedef std::map DerivationInputs; typedef std::map StringPairs; struct BasicDerivation { DerivationOutputs outputs; /* keyed on symbolic IDs */ - PathSet inputSrcs; /* inputs that are sources */ + StorePathSet inputSrcs; /* inputs that are sources */ string platform; Path builder; Strings args; StringPairs env; + BasicDerivation() { } + explicit BasicDerivation(const BasicDerivation & other); virtual ~BasicDerivation() { }; /* Return the path corresponding to the output identifier `id' in the given derivation. */ - Path findOutput(const string & id) const; + const StorePath & findOutput(const std::string & id) const; bool isBuiltin() const; @@ -62,7 +56,7 @@ struct BasicDerivation bool isFixedOutput() const; /* Return the output paths of a derivation. */ - PathSet outputPaths() const; + StorePathSet outputPaths() const; }; @@ -71,7 +65,12 @@ struct Derivation : BasicDerivation DerivationInputs inputDrvs; /* inputs that are sub-derivations */ /* Print a derivation. */ - std::string unparse() const; + std::string unparse(const Store & store, bool maskOutputs, + std::map * actualInputs = nullptr) const; + + Derivation() { } + Derivation(Derivation && other) = default; + explicit Derivation(const Derivation & other); }; @@ -79,38 +78,29 @@ class Store; /* Write a derivation to the Nix store, and return its path. */ -Path writeDerivation(ref store, +StorePath writeDerivation(ref store, const Derivation & drv, const string & name, RepairFlag repair = NoRepair); /* Read a derivation from a file. */ -Derivation readDerivation(const Path & drvPath); +Derivation readDerivation(const Store & store, const Path & drvPath); -/* Check whether a file name ends with the extension for - derivations. */ +// FIXME: remove bool isDerivation(const string & fileName); -Hash hashDerivationModulo(Store & store, Derivation drv); +Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutputs); /* Memoisation of hashDerivationModulo(). */ -typedef std::map DrvHashes; +typedef std::map DrvHashes; extern DrvHashes drvHashes; // FIXME: global, not thread-safe -/* Split a string specifying a derivation and a set of outputs - (/nix/store/hash-foo!out1,out2,...) into the derivation path and - the outputs. */ -typedef std::pair > DrvPathWithOutputs; -DrvPathWithOutputs parseDrvPathWithOutputs(const string & s); - -Path makeDrvPathWithOutputs(const Path & drvPath, const std::set & outputs); - bool wantOutput(const string & output, const std::set & wanted); struct Source; struct Sink; -Source & readDerivation(Source & in, Store & store, BasicDerivation & drv); -Sink & operator << (Sink & out, const BasicDerivation & drv); +Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv); +void writeDerivation(Sink & out, const Store & store, const BasicDerivation & drv); std::string hashPlaceholder(const std::string & outputName); diff --git a/src/libstore/download.cc b/src/libstore/download.cc index 61e88c5c1..af058ba42 100644 --- a/src/libstore/download.cc +++ b/src/libstore/download.cc @@ -650,10 +650,10 @@ struct CurlDownloader : public Downloader #ifdef ENABLE_S3 auto [bucketName, key, params] = parseS3Uri(request.uri); - std::string profile = get(params, "profile", ""); - std::string region = get(params, "region", Aws::Region::US_EAST_1); - std::string scheme = get(params, "scheme", ""); - std::string endpoint = get(params, "endpoint", ""); + std::string profile = get(params, "profile").value_or(""); + std::string region = get(params, "region").value_or(Aws::Region::US_EAST_1); + std::string scheme = get(params, "scheme").value_or(""); + std::string endpoint = get(params, "endpoint").value_or(""); S3Helper s3Helper(profile, region, scheme, endpoint); @@ -811,13 +811,13 @@ CachedDownloadResult Downloader::downloadCached( if (p != string::npos) name = string(url, p + 1); } - Path expectedStorePath; + std::optional expectedStorePath; if (request.expectedHash) { expectedStorePath = store->makeFixedOutputPath(request.unpack, request.expectedHash, name); - if (store->isValidPath(expectedStorePath)) { + if (store->isValidPath(*expectedStorePath)) { CachedDownloadResult result; - result.storePath = expectedStorePath; - result.path = store->toRealPath(expectedStorePath); + result.storePath = store->printStorePath(*expectedStorePath); + result.path = store->toRealPath(result.storePath); return result; } } @@ -832,7 +832,7 @@ CachedDownloadResult Downloader::downloadCached( PathLocks lock({fileLink}, fmt("waiting for lock on '%1%'...", fileLink)); - Path storePath; + std::optional storePath; string expectedETag; @@ -841,9 +841,10 @@ CachedDownloadResult Downloader::downloadCached( CachedDownloadResult result; if (pathExists(fileLink) && pathExists(dataFile)) { - storePath = readLink(fileLink); - store->addTempRoot(storePath); - if (store->isValidPath(storePath)) { + storePath = store->parseStorePath(readLink(fileLink)); + // FIXME + store->addTempRoot(*storePath); + if (store->isValidPath(*storePath)) { auto ss = tokenizeString>(readFile(dataFile), "\n"); if (ss.size() >= 3 && ss[0] == url) { time_t lastChecked; @@ -857,7 +858,7 @@ CachedDownloadResult Downloader::downloadCached( } } } else - storePath = ""; + storePath.reset(); } if (!skip) { @@ -870,65 +871,65 @@ CachedDownloadResult Downloader::downloadCached( result.etag = res.etag; if (!res.cached) { - ValidPathInfo info; StringSink sink; dumpString(*res.data, sink); Hash hash = hashString(request.expectedHash ? request.expectedHash.type : htSHA256, *res.data); - info.path = store->makeFixedOutputPath(false, hash, name); + ValidPathInfo info(store->makeFixedOutputPath(false, hash, name)); info.narHash = hashString(htSHA256, *sink.s); info.narSize = sink.s->size(); info.ca = makeFixedOutputCA(false, hash); store->addToStore(info, sink.s, NoRepair, NoCheckSigs); - storePath = info.path; + storePath = info.path.clone(); } - assert(!storePath.empty()); - replaceSymlink(storePath, fileLink); + assert(storePath); + replaceSymlink(store->printStorePath(*storePath), fileLink); writeFile(dataFile, url + "\n" + res.etag + "\n" + std::to_string(time(0)) + "\n"); } catch (DownloadError & e) { - if (storePath.empty()) throw; + if (!storePath) throw; warn("warning: %s; using cached result", e.msg()); result.etag = expectedETag; } } if (request.unpack) { - Path unpackedLink = cacheDir + "/" + baseNameOf(storePath) + "-unpacked"; + Path unpackedLink = cacheDir + "/" + ((std::string) storePath->to_string()) + "-unpacked"; PathLocks lock2({unpackedLink}, fmt("waiting for lock on '%1%'...", unpackedLink)); - Path unpackedStorePath; + std::optional unpackedStorePath; if (pathExists(unpackedLink)) { - unpackedStorePath = readLink(unpackedLink); - store->addTempRoot(unpackedStorePath); - if (!store->isValidPath(unpackedStorePath)) - unpackedStorePath = ""; + unpackedStorePath = store->parseStorePath(readLink(unpackedLink)); + // FIXME + store->addTempRoot(*unpackedStorePath); + if (!store->isValidPath(*unpackedStorePath)) + unpackedStorePath.reset(); } - if (unpackedStorePath.empty()) { + if (!unpackedStorePath) { printInfo("unpacking '%s'...", url); Path tmpDir = createTempDir(); AutoDelete autoDelete(tmpDir, true); - unpackTarfile(store->toRealPath(storePath), tmpDir, baseNameOf(url)); + unpackTarfile(store->toRealPath(store->printStorePath(*storePath)), tmpDir, std::string(baseNameOf(url))); auto members = readDirectory(tmpDir); if (members.size() != 1) throw nix::Error("tarball '%s' contains an unexpected number of top-level files", url); auto topDir = tmpDir + "/" + members.begin()->name; unpackedStorePath = store->addToStore(name, topDir, true, htSHA256, defaultPathFilter, NoRepair); } - replaceSymlink(unpackedStorePath, unpackedLink); - storePath = unpackedStorePath; + replaceSymlink(store->printStorePath(*unpackedStorePath), unpackedLink); + storePath = std::move(*unpackedStorePath); } - if (expectedStorePath != "" && storePath != expectedStorePath) { + if (expectedStorePath && *storePath != *expectedStorePath) { unsigned int statusCode = 102; Hash gotHash = request.unpack - ? hashPath(request.expectedHash.type, store->toRealPath(storePath)).first - : hashFile(request.expectedHash.type, store->toRealPath(storePath)); + ? hashPath(request.expectedHash.type, store->toRealPath(store->printStorePath(*storePath))).first + : hashFile(request.expectedHash.type, store->toRealPath(store->printStorePath(*storePath))); throw nix::Error(statusCode, "hash mismatch in file downloaded from '%s':\n wanted: %s\n got: %s", url, request.expectedHash.to_string(), gotHash.to_string()); } - result.storePath = storePath; - result.path = store->toRealPath(storePath); + result.storePath = store->printStorePath(*storePath); + result.path = store->toRealPath(result.storePath); return result; } diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc index ef3fea7c8..4692d1a7b 100644 --- a/src/libstore/export-import.cc +++ b/src/libstore/export-import.cc @@ -24,9 +24,9 @@ struct HashAndWriteSink : Sink } }; -void Store::exportPaths(const Paths & paths, Sink & sink) +void Store::exportPaths(const StorePathSet & paths, Sink & sink) { - Paths sorted = topoSortPaths(PathSet(paths.begin(), paths.end())); + auto sorted = topoSortPaths(paths); std::reverse(sorted.begin(), sorted.end()); std::string doneLabel("paths exported"); @@ -42,7 +42,7 @@ void Store::exportPaths(const Paths & paths, Sink & sink) sink << 0; } -void Store::exportPath(const Path & path, Sink & sink) +void Store::exportPath(const StorePath & path, Sink & sink) { auto info = queryPathInfo(path); @@ -55,15 +55,21 @@ void Store::exportPath(const Path & path, Sink & sink) Don't complain if the stored hash is zero (unknown). */ Hash hash = hashAndWriteSink.currentHash(); if (hash != info->narHash && info->narHash != Hash(info->narHash.type)) - throw Error(format("hash of path '%1%' has changed from '%2%' to '%3%'!") % path - % info->narHash.to_string() % hash.to_string()); + throw Error("hash of path '%s' has changed from '%s' to '%s'!", + printStorePath(path), info->narHash.to_string(), hash.to_string()); - hashAndWriteSink << exportMagic << path << info->references << info->deriver << 0; + hashAndWriteSink + << exportMagic + << printStorePath(path); + writeStorePaths(*this, hashAndWriteSink, info->references); + hashAndWriteSink + << (info->deriver ? printStorePath(*info->deriver) : "") + << 0; } -Paths Store::importPaths(Source & source, std::shared_ptr accessor, CheckSigsFlag checkSigs) +StorePaths Store::importPaths(Source & source, std::shared_ptr accessor, CheckSigsFlag checkSigs) { - Paths res; + StorePaths res; while (true) { auto n = readNum(source); if (n == 0) break; @@ -77,16 +83,15 @@ Paths Store::importPaths(Source & source, std::shared_ptr accessor, if (magic != exportMagic) throw Error("Nix archive cannot be imported; wrong format"); - ValidPathInfo info; - - info.path = readStorePath(*this, source); + ValidPathInfo info(parseStorePath(readString(source))); //Activity act(*logger, lvlInfo, format("importing path '%s'") % info.path); - info.references = readStorePaths(*this, source); + info.references = readStorePaths(*this, source); - info.deriver = readString(source); - if (info.deriver != "") assertStorePath(info.deriver); + auto deriver = readString(source); + if (deriver != "") + info.deriver = parseStorePath(deriver); info.narHash = hashString(htSHA256, *tee.source.data); info.narSize = tee.source.data->size(); @@ -97,7 +102,7 @@ Paths Store::importPaths(Source & source, std::shared_ptr accessor, addToStore(info, tee.source.data, NoRepair, checkSigs, accessor); - res.push_back(info.path); + res.push_back(info.path.clone()); } return res; diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 842980fb7..ed81186af 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -85,12 +85,10 @@ void LocalStore::addIndirectRoot(const Path & path) } -Path LocalFSStore::addPermRoot(const Path & _storePath, +Path LocalFSStore::addPermRoot(const StorePath & storePath, const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir) { - Path storePath(canonPath(_storePath)); Path gcRoot(canonPath(_gcRoot)); - assertStorePath(storePath); if (isInStore(gcRoot)) throw Error(format( @@ -102,7 +100,7 @@ Path LocalFSStore::addPermRoot(const Path & _storePath, point to the Nix store. */ if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) throw Error(format("cannot create symlink '%1%'; already exists") % gcRoot); - makeSymlink(gcRoot, storePath); + makeSymlink(gcRoot, printStorePath(storePath)); addIndirectRoot(gcRoot); } @@ -117,10 +115,10 @@ Path LocalFSStore::addPermRoot(const Path & _storePath, % gcRoot % rootsDir); } - if (baseNameOf(gcRoot) == baseNameOf(storePath)) + if (baseNameOf(gcRoot) == std::string(storePath.to_string())) writeFile(gcRoot, ""); else - makeSymlink(gcRoot, storePath); + makeSymlink(gcRoot, printStorePath(storePath)); } /* Check that the root can be found by the garbage collector. @@ -129,13 +127,12 @@ Path LocalFSStore::addPermRoot(const Path & _storePath, check if the root is in a directory in or linked from the gcroots directory. */ if (settings.checkRootReachability) { - Roots roots = findRoots(false); - if (roots[storePath].count(gcRoot) == 0) + auto roots = findRoots(false); + if (roots[storePath.clone()].count(gcRoot) == 0) printError( - format( - "warning: '%1%' is not in a directory where the garbage collector looks for roots; " - "therefore, '%2%' might be removed by the garbage collector") - % gcRoot % storePath); + "warning: '%1%' is not in a directory where the garbage collector looks for roots; " + "therefore, '%2%' might be removed by the garbage collector", + gcRoot, printStorePath(storePath)); } /* Grab the global GC root, causing us to block while a GC is in @@ -147,7 +144,7 @@ Path LocalFSStore::addPermRoot(const Path & _storePath, } -void LocalStore::addTempRoot(const Path & path) +void LocalStore::addTempRoot(const StorePath & path) { auto state(_state.lock()); @@ -188,7 +185,7 @@ void LocalStore::addTempRoot(const Path & path) debug(format("acquiring write lock on '%1%'") % fnTempRoots); lockFile(state->fdTempRoots.get(), ltWrite, true); - string s = path + '\0'; + string s = printStorePath(path) + '\0'; writeFull(state->fdTempRoots.get(), s); /* Downgrade to a read lock. */ @@ -246,8 +243,7 @@ void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor) while ((end = contents.find((char) 0, pos)) != string::npos) { Path root(contents, pos, end - pos); debug("got temporary root '%s'", root); - assertStorePath(root); - tempRoots[root].emplace(censor ? censored : fmt("{temp:%d}", pid)); + tempRoots[parseStorePath(root)].emplace(censor ? censored : fmt("{temp:%d}", pid)); pos = end + 1; } @@ -260,10 +256,11 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots) { auto foundRoot = [&](const Path & path, const Path & target) { Path storePath = toStorePath(target); - if (isStorePath(storePath) && isValidPath(storePath)) - roots[storePath].emplace(path); + // FIXME + if (isStorePath(storePath) && isValidPath(parseStorePath(storePath))) + roots[parseStorePath(storePath)].emplace(path); else - printInfo(format("skipping invalid root from '%1%' to '%2%'") % path % storePath); + printInfo("skipping invalid root from '%1%' to '%2%'", path, storePath); }; try { @@ -299,9 +296,10 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots) } else if (type == DT_REG) { - Path storePath = storeDir + "/" + baseNameOf(path); - if (isStorePath(storePath) && isValidPath(storePath)) - roots[storePath].emplace(path); + Path storePath = storeDir + "/" + std::string(baseNameOf(path)); + // FIXME + if (isStorePath(storePath) && isValidPath(parseStorePath(storePath))) + roots[parseStorePath(storePath)].emplace(path); } } @@ -309,7 +307,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots) catch (SysError & e) { /* We only ignore permanent failures. */ if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR) - printInfo(format("cannot read potential root '%1%'") % path); + printInfo("cannot read potential root '%1%'", path); else throw; } @@ -340,7 +338,9 @@ Roots LocalStore::findRoots(bool censor) return roots; } -static void readProcLink(const string & file, Roots & roots) +typedef std::unordered_map> UncheckedRoots; + +static void readProcLink(const string & file, UncheckedRoots & roots) { /* 64 is the starting buffer size gnu readlink uses... */ auto bufsiz = ssize_t{64}; @@ -369,7 +369,7 @@ static string quoteRegexChars(const string & raw) return std::regex_replace(raw, specialRegex, R"(\$&)"); } -static void readFileRoots(const char * path, Roots & roots) +static void readFileRoots(const char * path, UncheckedRoots & roots) { try { roots[readFile(path)].emplace(path); @@ -381,7 +381,7 @@ static void readFileRoots(const char * path, Roots & roots) void LocalStore::findRuntimeRoots(Roots & roots, bool censor) { - Roots unchecked; + UncheckedRoots unchecked; auto procDir = AutoCloseDir{opendir("/proc")}; if (procDir) { @@ -466,16 +466,16 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor) #endif for (auto & [target, links] : unchecked) { - if (isInStore(target)) { - Path path = toStorePath(target); - if (isStorePath(path) && isValidPath(path)) { - debug(format("got additional root '%1%'") % path); - if (censor) - roots[path].insert(censored); - else - roots[path].insert(links.begin(), links.end()); - } - } + if (!isInStore(target)) continue; + Path pathS = toStorePath(target); + if (!isStorePath(pathS)) continue; + auto path = parseStorePath(pathS); + if (!isValidPath(path)) continue; + debug("got additional root '%1%'", pathS); + if (censor) + roots[path.clone()].insert(censored); + else + roots[path.clone()].insert(links.begin(), links.end()); } } @@ -485,18 +485,19 @@ struct GCLimitReached { }; struct LocalStore::GCState { - GCOptions options; + const GCOptions & options; GCResults & results; - PathSet roots; - PathSet tempRoots; - PathSet dead; - PathSet alive; + StorePathSet roots; + StorePathSet tempRoots; + StorePathSet dead; + StorePathSet alive; bool gcKeepOutputs; bool gcKeepDerivations; unsigned long long bytesInvalidated; bool moveToTrash = true; bool shouldDelete; - GCState(GCResults & results_) : results(results_), bytesInvalidated(0) { } + GCState(const GCOptions & options, GCResults & results) + : options(options), results(results), bytesInvalidated(0) { } }; @@ -504,7 +505,7 @@ bool LocalStore::isActiveTempFile(const GCState & state, const Path & path, const string & suffix) { return hasSuffix(path, suffix) - && state.tempRoots.find(string(path, 0, path.size() - suffix.size())) != state.tempRoots.end(); + && state.tempRoots.count(parseStorePath(string(path, 0, path.size() - suffix.size()))); } @@ -522,16 +523,17 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path) unsigned long long size = 0; - if (isStorePath(path) && isValidPath(path)) { - PathSet referrers; - queryReferrers(path, referrers); + // FIXME + if (isStorePath(path) && isValidPath(parseStorePath(path))) { + StorePathSet referrers; + queryReferrers(parseStorePath(path), referrers); for (auto & i : referrers) - if (i != path) deletePathRecursive(state, i); - size = queryPathInfo(path)->narSize; - invalidatePathChecked(path); + if (printStorePath(i) != path) deletePathRecursive(state, printStorePath(i)); + size = queryPathInfo(parseStorePath(path))->narSize; + invalidatePathChecked(parseStorePath(path)); } - Path realPath = realStoreDir + "/" + baseNameOf(path); + Path realPath = realStoreDir + "/" + std::string(baseNameOf(path)); struct stat st; if (lstat(realPath.c_str(), &st)) { @@ -555,7 +557,7 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path) try { if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1) throw SysError(format("making '%1%' writable") % realPath); - Path tmp = trashDir + "/" + baseNameOf(path); + Path tmp = trashDir + "/" + std::string(baseNameOf(path)); if (rename(realPath.c_str(), tmp.c_str())) throw SysError(format("unable to rename '%1%' to '%2%'") % realPath % tmp); state.bytesInvalidated += size; @@ -575,7 +577,7 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path) } -bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & path) +bool LocalStore::canReachRoot(GCState & state, StorePathSet & visited, const StorePath & path) { if (visited.count(path)) return false; @@ -584,41 +586,41 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p if (state.dead.count(path)) return false; if (state.roots.count(path)) { - debug(format("cannot delete '%1%' because it's a root") % path); - state.alive.insert(path); + debug("cannot delete '%1%' because it's a root", printStorePath(path)); + state.alive.insert(path.clone()); return true; } - visited.insert(path); + visited.insert(path.clone()); - if (!isStorePath(path) || !isValidPath(path)) return false; + //FIXME + if (!isStorePath(printStorePath(path)) || !isValidPath(path)) return false; - PathSet incoming; + StorePathSet incoming; /* Don't delete this path if any of its referrers are alive. */ queryReferrers(path, incoming); /* If keep-derivations is set and this is a derivation, then don't delete the derivation if any of the outputs are alive. */ - if (state.gcKeepDerivations && isDerivation(path)) { - PathSet outputs = queryDerivationOutputs(path); - for (auto & i : outputs) + if (state.gcKeepDerivations && path.isDerivation()) { + for (auto & i : queryDerivationOutputs(path)) if (isValidPath(i) && queryPathInfo(i)->deriver == path) - incoming.insert(i); + incoming.insert(i.clone()); } /* If keep-outputs is set, then don't delete this path if there are derivers of this path that are not garbage. */ if (state.gcKeepOutputs) { - PathSet derivers = queryValidDerivers(path); + auto derivers = queryValidDerivers(path); for (auto & i : derivers) - incoming.insert(i); + incoming.insert(i.clone()); } for (auto & i : incoming) if (i != path) if (canReachRoot(state, visited, i)) { - state.alive.insert(path); + state.alive.insert(path.clone()); return true; } @@ -630,12 +632,13 @@ void LocalStore::tryToDelete(GCState & state, const Path & path) { checkInterrupt(); - auto realPath = realStoreDir + "/" + baseNameOf(path); + auto realPath = realStoreDir + "/" + std::string(baseNameOf(path)); if (realPath == linksDir || realPath == trashDir) return; //Activity act(*logger, lvlDebug, format("considering whether to delete '%1%'") % path); - if (!isStorePath(path) || !isValidPath(path)) { + // FIXME + if (!isStorePath(path) || !isValidPath(parseStorePath(path))) { /* A lock file belonging to a path that we're building right now isn't garbage. */ if (isActiveTempFile(state, path, ".lock")) return; @@ -650,16 +653,17 @@ void LocalStore::tryToDelete(GCState & state, const Path & path) if (isActiveTempFile(state, path, ".check")) return; } - PathSet visited; + StorePathSet visited; - if (canReachRoot(state, visited, path)) { - debug(format("cannot delete '%1%' because it's still reachable") % path); + if (canReachRoot(state, visited, parseStorePath(path))) { + debug("cannot delete '%s' because it's still reachable", path); } else { /* No path we visited was a root, so everything is garbage. But we only delete ‘path’ and its referrers here so that ‘nix-store --delete’ doesn't have the unexpected effect of recursing into derivations and outputs. */ - state.dead.insert(visited.begin(), visited.end()); + for (auto & i : visited) + state.dead.insert(i.clone()); if (state.shouldDelete) deletePathRecursive(state, path); } @@ -715,8 +719,7 @@ void LocalStore::removeUnusedLinks(const GCState & state) void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) { - GCState state(results); - state.options = options; + GCState state(options, results); state.gcKeepOutputs = settings.gcKeepOutputs; state.gcKeepDerivations = settings.gcKeepDerivations; @@ -741,12 +744,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Find the roots. Since we've grabbed the GC lock, the set of permanent roots cannot increase now. */ - printError(format("finding garbage collector roots...")); + printError("finding garbage collector roots..."); Roots rootMap; if (!options.ignoreLiveness) findRootsNoTemp(rootMap, true); - for (auto & i : rootMap) state.roots.insert(i.first); + for (auto & i : rootMap) state.roots.insert(i.first.clone()); /* Read the temporary roots. This acquires read locks on all per-process temporary root files. So after this point no paths @@ -754,9 +757,10 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) FDs fds; Roots tempRoots; findTempRoots(fds, tempRoots, true); - for (auto & root : tempRoots) - state.tempRoots.insert(root.first); - state.roots.insert(state.tempRoots.begin(), state.tempRoots.end()); + for (auto & root : tempRoots) { + state.tempRoots.insert(root.first.clone()); + state.roots.insert(root.first.clone()); + } /* After this point the set of roots or temporary roots cannot increase, since we hold locks on everything. So everything @@ -768,7 +772,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) createDirs(trashDir); } catch (SysError & e) { if (e.errNo == ENOSPC) { - printInfo(format("note: can't create trash directory: %1%") % e.msg()); + printInfo("note: can't create trash directory: %s", e.msg()); state.moveToTrash = false; } } @@ -780,22 +784,21 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) if (options.action == GCOptions::gcDeleteSpecific) { for (auto & i : options.pathsToDelete) { - assertStorePath(i); - tryToDelete(state, i); + tryToDelete(state, printStorePath(i)); if (state.dead.find(i) == state.dead.end()) - throw Error(format( + throw Error( "cannot delete path '%1%' since it is still alive. " "To find out why use: " - "nix-store --query --roots" - ) % i); + "nix-store --query --roots", + printStorePath(i)); } } else if (options.maxFreed > 0) { if (state.shouldDelete) - printError(format("deleting garbage...")); + printError("deleting garbage..."); else - printError(format("determining live/dead paths...")); + printError("determining live/dead paths..."); try { @@ -815,7 +818,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) string name = dirent->d_name; if (name == "." || name == "..") continue; Path path = storeDir + "/" + name; - if (isStorePath(path) && isValidPath(path)) + // FIXME + if (isStorePath(path) && isValidPath(parseStorePath(path))) entries.push_back(path); else tryToDelete(state, path); @@ -840,12 +844,14 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } if (state.options.action == GCOptions::gcReturnLive) { - state.results.paths = state.alive; + for (auto & i : state.alive) + state.results.paths.insert(printStorePath(i)); return; } if (state.options.action == GCOptions::gcReturnDead) { - state.results.paths = state.dead; + for (auto & i : state.dead) + state.results.paths.insert(printStorePath(i)); return; } @@ -859,7 +865,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Clean up the links directory. */ if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) { - printError(format("deleting unused links...")); + printError("deleting unused links..."); removeUnusedLinks(state); } diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc index 1b8b5908c..458266be0 100644 --- a/src/libstore/legacy-ssh-store.cc +++ b/src/libstore/legacy-ssh-store.cc @@ -87,25 +87,27 @@ struct LegacySSHStore : public Store return uriScheme + host; } - void queryPathInfoUncached(const Path & path, + void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept override { try { auto conn(connections->get()); - debug("querying remote host '%s' for info on '%s'", host, path); + debug("querying remote host '%s' for info on '%s'", host, printStorePath(path)); - conn->to << cmdQueryPathInfos << PathSet{path}; + conn->to << cmdQueryPathInfos << PathSet{printStorePath(path)}; conn->to.flush(); - auto info = std::make_shared(); - conn->from >> info->path; - if (info->path.empty()) return callback(nullptr); + auto p = readString(conn->from); + if (p.empty()) return callback(nullptr); + auto info = std::make_shared(parseStorePath(p)); assert(path == info->path); PathSet references; - conn->from >> info->deriver; - info->references = readStorePaths(*this, conn->from); + auto deriver = readString(conn->from); + if (deriver != "") + info->deriver = parseStorePath(deriver); + info->references = readStorePaths(*this, conn->from); readLongLong(conn->from); // download size info->narSize = readLongLong(conn->from); @@ -127,7 +129,7 @@ struct LegacySSHStore : public Store RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr accessor) override { - debug("adding path '%s' to remote host '%s'", info.path, host); + debug("adding path '%s' to remote host '%s'", printStorePath(info.path), host); auto conn(connections->get()); @@ -135,10 +137,11 @@ struct LegacySSHStore : public Store conn->to << cmdAddToStoreNar - << info.path - << info.deriver - << info.narHash.to_string(Base16, false) - << info.references + << printStorePath(info.path) + << (info.deriver ? printStorePath(*info.deriver) : "") + << info.narHash.to_string(Base16, false); + writeStorePaths(*this, conn->to, info.references); + conn->to << info.registrationTime << info.narSize << info.ultimate @@ -165,9 +168,10 @@ struct LegacySSHStore : public Store } conn->to << exportMagic - << info.path - << info.references - << info.deriver + << printStorePath(info.path); + writeStorePaths(*this, conn->to, info.references); + conn->to + << (info.deriver ? printStorePath(*info.deriver) : "") << 0 << 0; conn->to.flush(); @@ -175,39 +179,40 @@ struct LegacySSHStore : public Store } if (readInt(conn->from) != 1) - throw Error("failed to add path '%s' to remote host '%s', info.path, host"); + throw Error("failed to add path '%s' to remote host '%s'", printStorePath(info.path), host); } - void narFromPath(const Path & path, Sink & sink) override + void narFromPath(const StorePath & path, Sink & sink) override { auto conn(connections->get()); - conn->to << cmdDumpStorePath << path; + conn->to << cmdDumpStorePath << printStorePath(path); conn->to.flush(); copyNAR(conn->from, sink); } - Path queryPathFromHashPart(const string & hashPart) override + std::optional queryPathFromHashPart(const std::string & hashPart) override { unsupported("queryPathFromHashPart"); } - Path addToStore(const string & name, const Path & srcPath, + StorePath addToStore(const string & name, const Path & srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) override { unsupported("addToStore"); } - Path addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) override + StorePath addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) override { unsupported("addTextToStore"); } - BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) override { auto conn(connections->get()); conn->to << cmdBuildDerivation - << drvPath - << drv + << printStorePath(drvPath); + writeDerivation(conn->to, *this, drv); + conn->to << settings.maxSilentTime << settings.buildTimeout; if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 2) @@ -230,11 +235,11 @@ struct LegacySSHStore : public Store return status; } - void ensurePath(const Path & path) override + void ensurePath(const StorePath & path) override { unsupported("ensurePath"); } - void computeFSClosure(const PathSet & paths, - PathSet & out, bool flipDirection = false, + void computeFSClosure(const StorePathSet & paths, + StorePathSet & out, bool flipDirection = false, bool includeOutputs = false, bool includeDerivers = false) override { if (flipDirection || includeDerivers) { @@ -246,16 +251,15 @@ struct LegacySSHStore : public Store conn->to << cmdQueryClosure - << includeOutputs - << paths; + << includeOutputs; + writeStorePaths(*this, conn->to, paths); conn->to.flush(); - auto res = readStorePaths(*this, conn->from); - - out.insert(res.begin(), res.end()); + for (auto & i : readStorePaths(*this, conn->from)) + out.insert(i.clone()); } - PathSet queryValidPaths(const PathSet & paths, + StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute) override { auto conn(connections->get()); @@ -263,11 +267,11 @@ struct LegacySSHStore : public Store conn->to << cmdQueryValidPaths << false // lock - << maybeSubstitute - << paths; + << maybeSubstitute; + writeStorePaths(*this, conn->to, paths); conn->to.flush(); - return readStorePaths(*this, conn->from); + return readStorePaths(*this, conn->from); } void connect() override diff --git a/src/libstore/local-binary-cache-store.cc b/src/libstore/local-binary-cache-store.cc index 9f99ee76d..363be1443 100644 --- a/src/libstore/local-binary-cache-store.cc +++ b/src/libstore/local-binary-cache-store.cc @@ -44,15 +44,15 @@ protected: } } - PathSet queryAllValidPaths() override + StorePathSet queryAllValidPaths() override { - PathSet paths; + StorePathSet paths; for (auto & entry : readDirectory(binaryCacheDir)) { if (entry.name.size() != 40 || !hasSuffix(entry.name, ".narinfo")) continue; - paths.insert(storeDir + "/" + entry.name.substr(0, entry.name.size() - 8)); + paths.insert(parseStorePath(storeDir + "/" + entry.name.substr(0, entry.name.size() - 8))); } return paths; diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc index 642e4070d..aa5abd835 100644 --- a/src/libstore/local-fs-store.cc +++ b/src/libstore/local-fs-store.cc @@ -21,7 +21,7 @@ struct LocalStoreAccessor : public FSAccessor Path toRealPath(const Path & path) { Path storePath = store->toStorePath(path); - if (!store->isValidPath(storePath)) + if (!store->isValidPath(store->parseStorePath(storePath))) throw InvalidPath(format("path '%1%' is not a valid store path") % storePath); return store->getRealStoreDir() + std::string(path, store->storeDir.size()); } @@ -77,34 +77,32 @@ ref LocalFSStore::getFSAccessor() std::dynamic_pointer_cast(shared_from_this()))); } -void LocalFSStore::narFromPath(const Path & path, Sink & sink) +void LocalFSStore::narFromPath(const StorePath & path, Sink & sink) { if (!isValidPath(path)) - throw Error(format("path '%s' is not valid") % path); - dumpPath(getRealStoreDir() + std::string(path, storeDir.size()), sink); + throw Error("path '%s' is not valid", printStorePath(path)); + dumpPath(getRealStoreDir() + std::string(printStorePath(path), storeDir.size()), sink); } const string LocalFSStore::drvsLogDir = "drvs"; -std::shared_ptr LocalFSStore::getBuildLog(const Path & path_) +std::shared_ptr LocalFSStore::getBuildLog(const StorePath & path_) { - auto path(path_); + auto path = path_.clone(); - assertStorePath(path); - - - if (!isDerivation(path)) { + if (!path.isDerivation()) { try { - path = queryPathInfo(path)->deriver; + auto info = queryPathInfo(path); + if (!info->deriver) return nullptr; + path = info->deriver->clone(); } catch (InvalidPath &) { return nullptr; } - if (path == "") return nullptr; } - string baseName = baseNameOf(path); + auto baseName = std::string(baseNameOf(printStorePath(path))); for (int j = 0; j < 2; j++) { diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 60e7bb7af..c1380ef09 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -541,42 +541,36 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid) } -void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & drv) +void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivation & drv) { - string drvName = storePathToName(drvPath); - assert(isDerivation(drvName)); + assert(drvPath.isDerivation()); + std::string drvName(drvPath.name()); drvName = string(drvName, 0, drvName.size() - drvExtension.size()); if (drv.isFixedOutput()) { DerivationOutputs::const_iterator out = drv.outputs.find("out"); if (out == drv.outputs.end()) - throw Error(format("derivation '%1%' does not have an output named 'out'") % drvPath); + throw Error("derivation '%s' does not have an output named 'out'", printStorePath(drvPath)); bool recursive; Hash h; out->second.parseHashInfo(recursive, h); - Path outPath = makeFixedOutputPath(recursive, h, drvName); + auto outPath = makeFixedOutputPath(recursive, h, drvName); StringPairs::const_iterator j = drv.env.find("out"); - if (out->second.path != outPath || j == drv.env.end() || j->second != outPath) - throw Error(format("derivation '%1%' has incorrect output '%2%', should be '%3%'") - % drvPath % out->second.path % outPath); + if (out->second.path != outPath || j == drv.env.end() || parseStorePath(j->second) != outPath) + throw Error("derivation '%s' has incorrect output '%s', should be '%s'", + printStorePath(drvPath), printStorePath(out->second.path), printStorePath(outPath)); } else { - Derivation drvCopy(drv); - for (auto & i : drvCopy.outputs) { - i.second.path = ""; - drvCopy.env[i.first] = ""; - } - - Hash h = hashDerivationModulo(*this, drvCopy); + Hash h = hashDerivationModulo(*this, drv, true); for (auto & i : drv.outputs) { - Path outPath = makeOutputPath(i.first, h, drvName); + auto outPath = makeOutputPath(i.first, h, drvName); StringPairs::const_iterator j = drv.env.find(i.first); - if (i.second.path != outPath || j == drv.env.end() || j->second != outPath) - throw Error(format("derivation '%1%' has incorrect output '%2%', should be '%3%'") - % drvPath % i.second.path % outPath); + if (i.second.path != outPath || j == drv.env.end() || parseStorePath(j->second) != outPath) + throw Error("derivation '%s' has incorrect output '%s', should be '%s'", + printStorePath(drvPath), printStorePath(i.second.path), printStorePath(outPath)); } } } @@ -585,16 +579,15 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs) { - checkStoreName(storePathToName(info.path)); - if (info.ca != "" && !info.isContentAddressed(*this)) - throw Error("cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't", info.path); + throw Error("cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't", + printStorePath(info.path)); state.stmtRegisterValidPath.use() - (info.path) + (printStorePath(info.path)) (info.narHash.to_string(Base16)) (info.registrationTime == 0 ? time(0) : info.registrationTime) - (info.deriver, info.deriver != "") + (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()) @@ -606,8 +599,8 @@ uint64_t LocalStore::addValidPath(State & state, the database. This is useful for the garbage collector: it can efficiently query whether a path is an output of some derivation. */ - if (isDerivation(info.path)) { - Derivation drv = readDerivation(realStoreDir + "/" + baseNameOf(info.path)); + if (info.path.isDerivation()) { + auto drv = readDerivation(*this, realStoreDir + "/" + std::string(info.path.to_string())); /* Verify that the output paths in the derivation are correct (i.e., follow the scheme for computing output paths from @@ -620,34 +613,31 @@ uint64_t LocalStore::addValidPath(State & state, state.stmtAddDerivationOutput.use() (id) (i.first) - (i.second.path) + (printStorePath(i.second.path)) .exec(); } } { auto state_(Store::state.lock()); - state_->pathInfoCache.upsert(storePathToHash(info.path), std::make_shared(info)); + state_->pathInfoCache.upsert(storePathToHash(printStorePath(info.path)), std::make_shared(info)); } return id; } -void LocalStore::queryPathInfoUncached(const Path & path, +void LocalStore::queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept { try { - auto info = std::make_shared(); - info->path = path; - - assertStorePath(path); + auto info = std::make_shared(path.clone()); callback(retrySQLite>([&]() { auto state(_state.lock()); /* Get the path info. */ - auto useQueryPathInfo(state->stmtQueryPathInfo.use()(path)); + auto useQueryPathInfo(state->stmtQueryPathInfo.use()(printStorePath(info->path))); if (!useQueryPathInfo.next()) return std::shared_ptr(); @@ -657,13 +647,13 @@ void LocalStore::queryPathInfoUncached(const Path & path, try { info->narHash = Hash(useQueryPathInfo.getStr(1)); } catch (BadHash & e) { - throw Error("in valid-path entry for '%s': %s", path, e.what()); + throw Error("in valid-path entry for '%s': %s", printStorePath(path), e.what()); } info->registrationTime = useQueryPathInfo.getInt(2); auto s = (const char *) sqlite3_column_text(state->stmtQueryPathInfo, 3); - if (s) info->deriver = s; + if (s) info->deriver = parseStorePath(s); /* Note that narSize = NULL yields 0. */ info->narSize = useQueryPathInfo.getInt(4); @@ -680,7 +670,7 @@ void LocalStore::queryPathInfoUncached(const Path & path, auto useQueryReferences(state->stmtQueryReferences.use()(info->id)); while (useQueryReferences.next()) - info->references.insert(useQueryReferences.getStr(0)); + info->references.insert(parseStorePath(useQueryReferences.getStr(0))); return info; })); @@ -698,27 +688,27 @@ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info) (info.ultimate ? 1 : 0, info.ultimate) (concatStringsSep(" ", info.sigs), !info.sigs.empty()) (info.ca, !info.ca.empty()) - (info.path) + (printStorePath(info.path)) .exec(); } -uint64_t LocalStore::queryValidPathId(State & state, const Path & path) +uint64_t LocalStore::queryValidPathId(State & state, const StorePath & path) { - auto use(state.stmtQueryPathInfo.use()(path)); + auto use(state.stmtQueryPathInfo.use()(printStorePath(path))); if (!use.next()) - throw Error(format("path '%1%' is not valid") % path); + throw Error("path '%s' is not valid", printStorePath(path)); return use.getInt(0); } -bool LocalStore::isValidPath_(State & state, const Path & path) +bool LocalStore::isValidPath_(State & state, const StorePath & path) { - return state.stmtQueryPathInfo.use()(path).next(); + return state.stmtQueryPathInfo.use()(printStorePath(path)).next(); } -bool LocalStore::isValidPathUncached(const Path & path) +bool LocalStore::isValidPathUncached(const StorePath & path) { return retrySQLite([&]() { auto state(_state.lock()); @@ -727,39 +717,38 @@ bool LocalStore::isValidPathUncached(const Path & path) } -PathSet LocalStore::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubstitute) +StorePathSet LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { - PathSet res; + StorePathSet res; for (auto & i : paths) - if (isValidPath(i)) res.insert(i); + if (isValidPath(i)) res.insert(i.clone()); return res; } -PathSet LocalStore::queryAllValidPaths() +StorePathSet LocalStore::queryAllValidPaths() { - return retrySQLite([&]() { + return retrySQLite([&]() { auto state(_state.lock()); auto use(state->stmtQueryValidPaths.use()); - PathSet res; - while (use.next()) res.insert(use.getStr(0)); + StorePathSet res; + while (use.next()) res.insert(parseStorePath(use.getStr(0))); return res; }); } -void LocalStore::queryReferrers(State & state, const Path & path, PathSet & referrers) +void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers) { - auto useQueryReferrers(state.stmtQueryReferrers.use()(path)); + auto useQueryReferrers(state.stmtQueryReferrers.use()(printStorePath(path))); while (useQueryReferrers.next()) - referrers.insert(useQueryReferrers.getStr(0)); + referrers.insert(parseStorePath(useQueryReferrers.getStr(0))); } -void LocalStore::queryReferrers(const Path & path, PathSet & referrers) +void LocalStore::queryReferrers(const StorePath & path, StorePathSet & referrers) { - assertStorePath(path); return retrySQLite([&]() { auto state(_state.lock()); queryReferrers(*state, path, referrers); @@ -767,42 +756,40 @@ void LocalStore::queryReferrers(const Path & path, PathSet & referrers) } -PathSet LocalStore::queryValidDerivers(const Path & path) +StorePathSet LocalStore::queryValidDerivers(const StorePath & path) { - assertStorePath(path); - - return retrySQLite([&]() { + return retrySQLite([&]() { auto state(_state.lock()); - auto useQueryValidDerivers(state->stmtQueryValidDerivers.use()(path)); + auto useQueryValidDerivers(state->stmtQueryValidDerivers.use()(printStorePath(path))); - PathSet derivers; + StorePathSet derivers; while (useQueryValidDerivers.next()) - derivers.insert(useQueryValidDerivers.getStr(1)); + derivers.insert(parseStorePath(useQueryValidDerivers.getStr(1))); return derivers; }); } -PathSet LocalStore::queryDerivationOutputs(const Path & path) +StorePathSet LocalStore::queryDerivationOutputs(const StorePath & path) { - return retrySQLite([&]() { + return retrySQLite([&]() { auto state(_state.lock()); auto useQueryDerivationOutputs(state->stmtQueryDerivationOutputs.use() (queryValidPathId(*state, path))); - PathSet outputs; + StorePathSet outputs; while (useQueryDerivationOutputs.next()) - outputs.insert(useQueryDerivationOutputs.getStr(1)); + outputs.insert(parseStorePath(useQueryDerivationOutputs.getStr(1))); return outputs; }); } -StringSet LocalStore::queryDerivationOutputNames(const Path & path) +StringSet LocalStore::queryDerivationOutputNames(const StorePath & path) { return retrySQLite([&]() { auto state(_state.lock()); @@ -819,31 +806,36 @@ StringSet LocalStore::queryDerivationOutputNames(const Path & path) } -Path LocalStore::queryPathFromHashPart(const string & hashPart) +std::optional LocalStore::queryPathFromHashPart(const std::string & hashPart) { if (hashPart.size() != storePathHashLen) throw Error("invalid hash part"); Path prefix = storeDir + "/" + hashPart; - return retrySQLite([&]() -> std::string { + return retrySQLite>([&]() -> std::optional { auto state(_state.lock()); auto useQueryPathFromHashPart(state->stmtQueryPathFromHashPart.use()(prefix)); - if (!useQueryPathFromHashPart.next()) return ""; + if (!useQueryPathFromHashPart.next()) return {}; const char * s = (const char *) sqlite3_column_text(state->stmtQueryPathFromHashPart, 0); - return s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0 ? s : ""; + if (s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0) + return parseStorePath(s); + return {}; }); } -PathSet LocalStore::querySubstitutablePaths(const PathSet & paths) +StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) { - if (!settings.useSubstitutes) return PathSet(); + if (!settings.useSubstitutes) return StorePathSet(); - auto remaining = paths; - PathSet res; + StorePathSet remaining; + for (auto & i : paths) + remaining.insert(i.clone()); + + StorePathSet res; for (auto & sub : getDefaultSubstituters()) { if (remaining.empty()) break; @@ -852,12 +844,12 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet & paths) auto valid = sub->queryValidPaths(remaining); - PathSet remaining2; + StorePathSet remaining2; for (auto & path : remaining) if (valid.count(path)) - res.insert(path); + res.insert(path.clone()); else - remaining2.insert(path); + remaining2.insert(path.clone()); std::swap(remaining, remaining2); } @@ -866,7 +858,7 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet & paths) } -void LocalStore::querySubstitutablePathInfos(const PathSet & paths, +void LocalStore::querySubstitutablePathInfos(const StorePathSet & paths, SubstitutablePathInfos & infos) { if (!settings.useSubstitutes) return; @@ -874,17 +866,16 @@ void LocalStore::querySubstitutablePathInfos(const PathSet & paths, if (sub->storeDir != storeDir) continue; for (auto & path : paths) { if (infos.count(path)) continue; - debug(format("checking substituter '%s' for path '%s'") - % sub->getUri() % path); + debug("checking substituter '%s' for path '%s'", sub->getUri(), printStorePath(path)); try { auto info = sub->queryPathInfo(path); auto narInfo = std::dynamic_pointer_cast( std::shared_ptr(info)); - infos[path] = SubstitutablePathInfo{ - info->deriver, - info->references, + infos.insert_or_assign(path.clone(), SubstitutablePathInfo{ + info->deriver ? info->deriver->clone() : std::optional(), + cloneStorePathSet(info->references), narInfo ? narInfo->fileSize : 0, - info->narSize}; + info->narSize}); } catch (InvalidPath &) { } catch (SubstituterDisabled &) { } catch (Error & e) { @@ -918,7 +909,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) auto state(_state.lock()); SQLiteTxn txn(state->db); - PathSet paths; + StorePathSet paths; for (auto & i : infos) { assert(i.narHash.type == htSHA256); @@ -926,7 +917,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) updatePathInfo(*state, i); else addValidPath(*state, i, false); - paths.insert(i.path); + paths.insert(i.path.clone()); } for (auto & i : infos) { @@ -939,10 +930,10 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) this in addValidPath() above, because the references might not be valid yet. */ for (auto & i : infos) - if (isDerivation(i.path)) { + if (i.path.isDerivation()) { // FIXME: inefficient; we already loaded the derivation in addValidPath(). - Derivation drv = readDerivation(realStoreDir + "/" + baseNameOf(i.path)); - checkDerivationOutputs(i.path, drv); + checkDerivationOutputs(i.path, + readDerivation(*this, realStoreDir + "/" + std::string(i.path.to_string()))); } /* Do a topological sort of the paths. This will throw an @@ -958,18 +949,18 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) /* Invalidate a path. The caller is responsible for checking that there are no referrers. */ -void LocalStore::invalidatePath(State & state, const Path & path) +void LocalStore::invalidatePath(State & state, const StorePath & path) { - debug(format("invalidating path '%1%'") % path); + debug("invalidating path '%s'", printStorePath(path)); - state.stmtInvalidatePath.use()(path).exec(); + state.stmtInvalidatePath.use()(printStorePath(path)).exec(); /* Note that the foreign key constraints on the Refs table take care of deleting the references entries for `path'. */ { auto state_(Store::state.lock()); - state_->pathInfoCache.erase(storePathToHash(path)); + state_->pathInfoCache.erase(storePathToHash(printStorePath(path))); } } @@ -987,10 +978,10 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr accessor) { if (!info.narHash) - throw Error("cannot add path '%s' because it lacks a hash", info.path); + throw Error("cannot add path '%s' because it lacks a hash", printStorePath(info.path)); if (requireSigs && checkSigs && !info.checkSignatures(*this, getPublicKeys())) - throw Error("cannot add path '%s' because it lacks a valid signature", info.path); + throw Error("cannot add path '%s' because it lacks a valid signature", printStorePath(info.path)); addTempRoot(info.path); @@ -998,12 +989,12 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, PathLocks outputLock; - Path realPath = realStoreDir + "/" + baseNameOf(info.path); + Path realPath = realStoreDir + "/" + std::string(info.path.to_string()); /* Lock the output path. But don't lock if we're being called from a build hook (whose parent process already acquired a lock on this path). */ - if (!locksHeld.count(info.path)) + if (!locksHeld.count(printStorePath(info.path))) outputLock.lockPaths({realPath}); if (repair || !isValidPath(info.path)) { @@ -1018,7 +1009,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, else { if (!info.references.empty()) settings.requireExperimentalFeature("ca-references"); - hashSink = std::make_unique(htSHA256, storePathToHash(info.path)); + hashSink = std::make_unique(htSHA256, storePathToHash(printStorePath(info.path))); } LambdaSource wrapperSource([&](unsigned char * data, size_t len) -> size_t { @@ -1033,11 +1024,11 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, if (hashResult.first != info.narHash) throw Error("hash mismatch importing path '%s';\n wanted: %s\n got: %s", - info.path, info.narHash.to_string(), hashResult.first.to_string()); + printStorePath(info.path), info.narHash.to_string(), hashResult.first.to_string()); if (hashResult.second != info.narSize) throw Error("size mismatch importing path '%s';\n wanted: %s\n got: %s", - info.path, info.narSize, hashResult.second); + printStorePath(info.path), info.narSize, hashResult.second); autoGC(); @@ -1053,12 +1044,12 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, } -Path LocalStore::addToStoreFromDump(const string & dump, const string & name, +StorePath LocalStore::addToStoreFromDump(const string & dump, const string & name, bool recursive, HashType hashAlgo, RepairFlag repair) { Hash h = hashString(hashAlgo, dump); - Path dstPath = makeFixedOutputPath(recursive, h, name); + auto dstPath = makeFixedOutputPath(recursive, h, name); addTempRoot(dstPath); @@ -1067,7 +1058,8 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, /* The first check above is an optimisation to prevent unnecessary lock acquisition. */ - Path realPath = realStoreDir + "/" + baseNameOf(dstPath); + Path realPath = realStoreDir + "/"; + realPath += dstPath.to_string(); PathLocks outputLock({realPath}); @@ -1098,8 +1090,7 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, optimisePath(realPath); // FIXME: combine with hashPath() - ValidPathInfo info; - info.path = dstPath; + ValidPathInfo info(dstPath.clone()); info.narHash = hash.first; info.narSize = hash.second; info.ca = makeFixedOutputCA(recursive, h); @@ -1113,7 +1104,7 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, } -Path LocalStore::addToStore(const string & name, const Path & _srcPath, +StorePath LocalStore::addToStore(const string & name, const Path & _srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) { Path srcPath(absPath(_srcPath)); @@ -1131,8 +1122,8 @@ Path LocalStore::addToStore(const string & name, const Path & _srcPath, } -Path LocalStore::addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) +StorePath LocalStore::addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) { auto hash = hashString(htSHA256, s); auto dstPath = makeTextPath(name, hash, references); @@ -1141,7 +1132,8 @@ Path LocalStore::addTextToStore(const string & name, const string & s, if (repair || !isValidPath(dstPath)) { - Path realPath = realStoreDir + "/" + baseNameOf(dstPath); + Path realPath = realStoreDir + "/"; + realPath += dstPath.to_string(); PathLocks outputLock({realPath}); @@ -1161,11 +1153,10 @@ Path LocalStore::addTextToStore(const string & name, const string & s, optimisePath(realPath); - ValidPathInfo info; - info.path = dstPath; + ValidPathInfo info(dstPath.clone()); info.narHash = narHash; info.narSize = sink.s->size(); - info.references = references; + info.references = cloneStorePathSet(references); info.ca = "text:" + hash.to_string(); registerValidPath(info); } @@ -1187,27 +1178,25 @@ Path LocalStore::createTempDirInStore() the GC between createTempDir() and addTempRoot(), so repeat until `tmpDir' exists. */ tmpDir = createTempDir(realStoreDir); - addTempRoot(tmpDir); + addTempRoot(parseStorePath(tmpDir)); } while (!pathExists(tmpDir)); return tmpDir; } -void LocalStore::invalidatePathChecked(const Path & path) +void LocalStore::invalidatePathChecked(const StorePath & path) { - assertStorePath(path); - retrySQLite([&]() { auto state(_state.lock()); SQLiteTxn txn(state->db); if (isValidPath_(*state, path)) { - PathSet referrers; queryReferrers(*state, path, referrers); + StorePathSet referrers; queryReferrers(*state, path, referrers); referrers.erase(path); /* ignore self-references */ if (!referrers.empty()) - throw PathInUse(format("cannot delete path '%1%' because it is in use by %2%") - % path % showPaths(referrers)); + throw PathInUse("cannot delete path '%s' because it is in use by %s", + printStorePath(path), showPaths(referrers)); invalidatePath(*state, path); } @@ -1226,18 +1215,19 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) existing and valid paths. */ AutoCloseFD fdGCLock = openGCLock(ltWrite); - PathSet store; + StringSet store; for (auto & i : readDirectory(realStoreDir)) store.insert(i.name); /* Check whether all valid paths actually exist. */ printInfo("checking path existence..."); - PathSet validPaths2 = queryAllValidPaths(), validPaths, done; + StorePathSet validPaths; + PathSet done; fdGCLock = -1; - for (auto & i : validPaths2) - verifyPath(i, store, done, validPaths, repair, errors); + for (auto & i : queryAllValidPaths()) + verifyPath(printStorePath(i), store, done, validPaths, repair, errors); /* Optionally, check the content hashes (slow). */ if (checkContents) { @@ -1272,21 +1262,20 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) auto info = std::const_pointer_cast(std::shared_ptr(queryPathInfo(i))); /* Check the content hash (optionally - slow). */ - printMsg(lvlTalkative, format("checking contents of '%1%'") % i); + printMsg(lvlTalkative, "checking contents of '%s'", printStorePath(i)); std::unique_ptr hashSink; if (info->ca == "") hashSink = std::make_unique(info->narHash.type); else - hashSink = std::make_unique(info->narHash.type, storePathToHash(info->path)); + hashSink = std::make_unique(info->narHash.type, storePathToHash(printStorePath(info->path))); - dumpPath(toRealPath(i), *hashSink); + dumpPath(toRealPath(printStorePath(i)), *hashSink); auto current = hashSink->finish(); if (info->narHash != nullHash && info->narHash != current.first) { - printError(format("path '%1%' was modified! " - "expected hash '%2%', got '%3%'") - % i % info->narHash.to_string() % current.first.to_string()); + printError("path '%s' was modified! expected hash '%s', got '%s'", + printStorePath(i), info->narHash.to_string(), current.first.to_string()); if (repair) repairPath(i); else errors = true; } else { @@ -1294,14 +1283,14 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) /* Fill in missing hashes. */ if (info->narHash == nullHash) { - printError(format("fixing missing hash on '%1%'") % i); + printError("fixing missing hash on '%s'", printStorePath(i)); info->narHash = current.first; update = true; } /* Fill in missing narSize fields (from old stores). */ if (info->narSize == 0) { - printError(format("updating size field on '%1%' to %2%") % i % current.second); + printError("updating size field on '%s' to %s", printStorePath(i), current.second); info->narSize = current.second; update = true; } @@ -1317,9 +1306,9 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) /* It's possible that the path got GC'ed, so ignore errors on invalid paths. */ if (isValidPath(i)) - printError(format("error: %1%") % e.msg()); + printError("error: %s", e.msg()); else - printError(format("warning: %1%") % e.msg()); + warn(e.msg()); errors = true; } } @@ -1329,43 +1318,43 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) } -void LocalStore::verifyPath(const Path & path, const PathSet & store, - PathSet & done, PathSet & validPaths, RepairFlag repair, bool & errors) +void LocalStore::verifyPath(const Path & pathS, const StringSet & store, + PathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors) { checkInterrupt(); - if (!done.insert(path).second) return; + if (!done.insert(pathS).second) return; - if (!isStorePath(path)) { - printError(format("path '%1%' is not in the Nix store") % path); - auto state(_state.lock()); - invalidatePath(*state, path); + if (!isStorePath(pathS)) { + printError("path '%s' is not in the Nix store", pathS); return; } - if (store.find(baseNameOf(path)) == store.end()) { + auto path = parseStorePath(pathS); + + if (!store.count(std::string(path.to_string()))) { /* Check any referrers first. If we can invalidate them first, then we can invalidate this path as well. */ bool canInvalidate = true; - PathSet referrers; queryReferrers(path, referrers); + StorePathSet referrers; queryReferrers(path, referrers); for (auto & i : referrers) if (i != path) { - verifyPath(i, store, done, validPaths, repair, errors); - if (validPaths.find(i) != validPaths.end()) + verifyPath(printStorePath(i), store, done, validPaths, repair, errors); + if (validPaths.count(i)) canInvalidate = false; } if (canInvalidate) { - printError(format("path '%1%' disappeared, removing from database...") % path); + printError("path '%s' disappeared, removing from database...", pathS); auto state(_state.lock()); invalidatePath(*state, path); } else { - printError(format("path '%1%' disappeared, but it still has valid referrers!") % path); + printError("path '%s' disappeared, but it still has valid referrers!", pathS); if (repair) try { repairPath(path); } catch (Error & e) { - printError(format("warning: %1%") % e.msg()); + warn(e.msg()); errors = true; } else errors = true; @@ -1374,7 +1363,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store, return; } - validPaths.insert(path); + validPaths.insert(std::move(path)); } @@ -1443,7 +1432,7 @@ void LocalStore::vacuumDB() } -void LocalStore::addSignatures(const Path & storePath, const StringSet & sigs) +void LocalStore::addSignatures(const StorePath & storePath, const StringSet & sigs) { retrySQLite([&]() { auto state(_state.lock()); @@ -1469,7 +1458,7 @@ void LocalStore::signPathInfo(ValidPathInfo & info) for (auto & secretKeyFile : secretKeyFiles.get()) { SecretKey secretKey(readFile(secretKeyFile)); - info.sign(secretKey); + info.sign(*this, secretKey); } } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 1d4b88898..16aeab0ad 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -119,36 +119,36 @@ public: std::string getUri() override; - bool isValidPathUncached(const Path & path) override; + bool isValidPathUncached(const StorePath & path) override; - PathSet queryValidPaths(const PathSet & paths, + StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute) override; - PathSet queryAllValidPaths() override; + StorePathSet queryAllValidPaths() override; - void queryPathInfoUncached(const Path & path, + void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept override; - void queryReferrers(const Path & path, PathSet & referrers) override; + void queryReferrers(const StorePath & path, StorePathSet & referrers) override; - PathSet queryValidDerivers(const Path & path) override; + StorePathSet queryValidDerivers(const StorePath & path) override; - PathSet queryDerivationOutputs(const Path & path) override; + StorePathSet queryDerivationOutputs(const StorePath & path) override; - StringSet queryDerivationOutputNames(const Path & path) override; + StringSet queryDerivationOutputNames(const StorePath & path) override; - Path queryPathFromHashPart(const string & hashPart) override; + std::optional queryPathFromHashPart(const std::string & hashPart) override; - PathSet querySubstitutablePaths(const PathSet & paths) override; + StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; - void querySubstitutablePathInfos(const PathSet & paths, + void querySubstitutablePathInfos(const StorePathSet & paths, SubstitutablePathInfos & infos) override; void addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr accessor) override; - Path addToStore(const string & name, const Path & srcPath, + StorePath addToStore(const string & name, const Path & srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) override; @@ -156,20 +156,22 @@ public: in `dump', which is either a NAR serialisation (if recursive == true) or simply the contents of a regular file (if recursive == false). */ - Path addToStoreFromDump(const string & dump, const string & name, + StorePath addToStoreFromDump(const string & dump, const string & name, bool recursive = true, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair) override; - Path addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) override; + StorePath addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) override; - void buildPaths(const PathSet & paths, BuildMode buildMode) override; - - BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, + void buildPaths( + const std::vector & paths, BuildMode buildMode) override; - void ensurePath(const Path & path) override; + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, + BuildMode buildMode) override; - void addTempRoot(const Path & path) override; + void ensurePath(const StorePath & path) override; + + void addTempRoot(const StorePath & path) override; void addIndirectRoot(const Path & path) override; @@ -215,9 +217,9 @@ public: /* Repair the contents of the given path by redownloading it using a substituter (if available). */ - void repairPath(const Path & path); + void repairPath(const StorePath & path); - void addSignatures(const Path & storePath, const StringSet & sigs) override; + void addSignatures(const StorePath & storePath, const StringSet & sigs) override; /* If free disk space in /nix/store if below minFree, delete garbage until it exceeds maxFree. */ @@ -231,17 +233,17 @@ private: void makeStoreWritable(); - uint64_t queryValidPathId(State & state, const Path & path); + uint64_t queryValidPathId(State & state, const StorePath & path); uint64_t addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs = true); - void invalidatePath(State & state, const Path & path); + void invalidatePath(State & state, const StorePath & path); /* Delete a path from the Nix store. */ - void invalidatePathChecked(const Path & path); + void invalidatePathChecked(const StorePath & path); - void verifyPath(const Path & path, const PathSet & store, - PathSet & done, PathSet & validPaths, RepairFlag repair, bool & errors); + void verifyPath(const Path & path, const StringSet & store, + PathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors); void updatePathInfo(State & state, const ValidPathInfo & info); @@ -256,7 +258,7 @@ private: void tryToDelete(GCState & state, const Path & path); - bool canReachRoot(GCState & state, PathSet & visited, const Path & path); + bool canReachRoot(GCState & state, StorePathSet & visited, const StorePath & path); void deletePathRecursive(GCState & state, const Path & path); @@ -275,7 +277,7 @@ private: Path createTempDirInStore(); - void checkDerivationOutputs(const Path & drvPath, const Derivation & drv); + void checkDerivationOutputs(const StorePath & drvPath, const Derivation & drv); typedef std::unordered_set InodeHash; @@ -284,8 +286,8 @@ private: void optimisePath_(Activity * act, OptimiseStats & stats, const Path & path, InodeHash & inodeHash); // Internal versions that are not wrapped in retry_sqlite. - bool isValidPath_(State & state, const Path & path); - void queryReferrers(State & state, const Path & path, PathSet & referrers); + bool isValidPath_(State & state, const StorePath & path); + void queryReferrers(State & state, const StorePath & path, StorePathSet & referrers); /* Add signatures to a ValidPathInfo using the secret keys specified by the ‘secret-key-files’ option. */ diff --git a/src/libstore/local.mk b/src/libstore/local.mk index d690fea28..d3254554d 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -6,7 +6,7 @@ libstore_DIR := $(d) libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc) -libstore_LIBS = libutil +libstore_LIBS = libutil libnixrust libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread ifneq ($(OS), FreeBSD) diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 2fceb9b9a..9c47fe524 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -9,13 +9,13 @@ namespace nix { -void Store::computeFSClosure(const PathSet & startPaths, - PathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) +void Store::computeFSClosure(const StorePathSet & startPaths, + StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) { struct State { size_t pending; - PathSet & paths; + StorePathSet & paths; std::exception_ptr exc; }; @@ -29,45 +29,47 @@ void Store::computeFSClosure(const PathSet & startPaths, { auto state(state_.lock()); if (state->exc) return; - if (!state->paths.insert(path).second) return; + if (!state->paths.insert(parseStorePath(path)).second) return; state->pending++; } - queryPathInfo(path, {[&, path](std::future> fut) { + queryPathInfo(parseStorePath(path), {[&, pathS(path)](std::future> fut) { // FIXME: calls to isValidPath() should be async try { auto info = fut.get(); + auto path = parseStorePath(pathS); + if (flipDirection) { - PathSet referrers; + StorePathSet referrers; queryReferrers(path, referrers); for (auto & ref : referrers) if (ref != path) - enqueue(ref); + enqueue(printStorePath(ref)); if (includeOutputs) for (auto & i : queryValidDerivers(path)) - enqueue(i); + enqueue(printStorePath(i)); - if (includeDerivers && isDerivation(path)) + if (includeDerivers && path.isDerivation()) for (auto & i : queryDerivationOutputs(path)) if (isValidPath(i) && queryPathInfo(i)->deriver == path) - enqueue(i); + enqueue(printStorePath(i)); } else { for (auto & ref : info->references) if (ref != path) - enqueue(ref); + enqueue(printStorePath(ref)); - if (includeOutputs && isDerivation(path)) + if (includeOutputs && path.isDerivation()) for (auto & i : queryDerivationOutputs(path)) - if (isValidPath(i)) enqueue(i); + if (isValidPath(i)) enqueue(printStorePath(i)); - if (includeDerivers && isValidPath(info->deriver)) - enqueue(info->deriver); + if (includeDerivers && info->deriver && isValidPath(*info->deriver)) + enqueue(printStorePath(*info->deriver)); } @@ -87,7 +89,7 @@ void Store::computeFSClosure(const PathSet & startPaths, }; for (auto & startPath : startPaths) - enqueue(startPath); + enqueue(printStorePath(startPath)); { auto state(state_.lock()); @@ -97,15 +99,17 @@ void Store::computeFSClosure(const PathSet & startPaths, } -void Store::computeFSClosure(const Path & startPath, - PathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) +void Store::computeFSClosure(const StorePath & startPath, + StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) { - computeFSClosure(PathSet{startPath}, paths_, flipDirection, includeOutputs, includeDerivers); + StorePathSet paths; + paths.insert(startPath.clone()); + computeFSClosure(paths, paths_, flipDirection, includeOutputs, includeDerivers); } -void Store::queryMissing(const PathSet & targets, - PathSet & willBuild_, PathSet & willSubstitute_, PathSet & unknown_, +void Store::queryMissing(const std::vector & targets, + StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_, unsigned long long & downloadSize_, unsigned long long & narSize_) { Activity act(*logger, lvlDebug, actUnknown, "querying info about missing paths"); @@ -116,8 +120,8 @@ void Store::queryMissing(const PathSet & targets, struct State { - PathSet done; - PathSet & unknown, & willSubstitute, & willBuild; + std::unordered_set done; + StorePathSet & unknown, & willSubstitute, & willBuild; unsigned long long & downloadSize; unsigned long long & narSize; }; @@ -126,31 +130,36 @@ void Store::queryMissing(const PathSet & targets, { size_t left; bool done = false; - PathSet outPaths; + StorePathSet outPaths; DrvState(size_t left) : left(left) { } }; - Sync state_(State{PathSet(), unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_}); + Sync state_(State{{}, unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_}); - std::function doPath; + std::function doPath; - auto mustBuildDrv = [&](const Path & drvPath, const Derivation & drv) { + auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) { { auto state(state_.lock()); - state->willBuild.insert(drvPath); + state->willBuild.insert(drvPath.clone()); } for (auto & i : drv.inputDrvs) - pool.enqueue(std::bind(doPath, makeDrvPathWithOutputs(i.first, i.second))); + pool.enqueue(std::bind(doPath, StorePathWithOutputs(i.first, i.second))); }; auto checkOutput = [&]( - const Path & drvPath, ref drv, const Path & outPath, ref> drvState_) + const Path & drvPathS, ref drv, const Path & outPathS, ref> drvState_) { if (drvState_->lock()->done) return; + auto drvPath = parseStorePath(drvPathS); + auto outPath = parseStorePath(outPathS); + SubstitutablePathInfos infos; - querySubstitutablePathInfos({outPath}, infos); + StorePathSet paths; // FIXME + paths.insert(outPath.clone()); + querySubstitutablePathInfos(paths, infos); if (infos.empty()) { drvState_->lock()->done = true; @@ -161,74 +170,74 @@ void Store::queryMissing(const PathSet & targets, if (drvState->done) return; assert(drvState->left); drvState->left--; - drvState->outPaths.insert(outPath); + drvState->outPaths.insert(outPath.clone()); if (!drvState->left) { for (auto & path : drvState->outPaths) - pool.enqueue(std::bind(doPath, path)); + pool.enqueue(std::bind(doPath, StorePathWithOutputs(path.clone()))); } } } }; - doPath = [&](const Path & path) { + doPath = [&](const StorePathWithOutputs & path) { { auto state(state_.lock()); - if (!state->done.insert(path).second) return; + if (!state->done.insert(path.to_string(*this)).second) return; } - DrvPathWithOutputs i2 = parseDrvPathWithOutputs(path); - - if (isDerivation(i2.first)) { - if (!isValidPath(i2.first)) { + if (path.path.isDerivation()) { + if (!isValidPath(path.path)) { // FIXME: we could try to substitute the derivation. auto state(state_.lock()); - state->unknown.insert(path); + state->unknown.insert(path.path.clone()); return; } - Derivation drv = derivationFromPath(i2.first); - ParsedDerivation parsedDrv(i2.first, drv); + auto drv = make_ref(derivationFromPath(path.path)); + ParsedDerivation parsedDrv(path.path.clone(), *drv); PathSet invalid; - for (auto & j : drv.outputs) - if (wantOutput(j.first, i2.second) + for (auto & j : drv->outputs) + if (wantOutput(j.first, path.outputs) && !isValidPath(j.second.path)) - invalid.insert(j.second.path); + invalid.insert(printStorePath(j.second.path)); if (invalid.empty()) return; if (settings.useSubstitutes && parsedDrv.substitutesAllowed()) { auto drvState = make_ref>(DrvState(invalid.size())); for (auto & output : invalid) - pool.enqueue(std::bind(checkOutput, i2.first, make_ref(drv), output, drvState)); + pool.enqueue(std::bind(checkOutput, printStorePath(path.path), drv, output, drvState)); } else - mustBuildDrv(i2.first, drv); + mustBuildDrv(path.path, *drv); } else { - if (isValidPath(path)) return; + if (isValidPath(path.path)) return; SubstitutablePathInfos infos; - querySubstitutablePathInfos({path}, infos); + StorePathSet paths; // FIXME + paths.insert(path.path.clone()); + querySubstitutablePathInfos(paths, infos); if (infos.empty()) { auto state(state_.lock()); - state->unknown.insert(path); + state->unknown.insert(path.path.clone()); return; } - auto info = infos.find(path); + auto info = infos.find(path.path); assert(info != infos.end()); { auto state(state_.lock()); - state->willSubstitute.insert(path); + state->willSubstitute.insert(path.path.clone()); state->downloadSize += info->second.downloadSize; state->narSize += info->second.narSize; } for (auto & ref : info->second.references) - pool.enqueue(std::bind(doPath, ref)); + pool.enqueue(std::bind(doPath, StorePathWithOutputs(ref))); } }; @@ -239,39 +248,42 @@ void Store::queryMissing(const PathSet & targets, } -Paths Store::topoSortPaths(const PathSet & paths) +StorePaths Store::topoSortPaths(const StorePathSet & paths) { - Paths sorted; - PathSet visited, parents; + StorePaths sorted; + StorePathSet visited, parents; - std::function dfsVisit; + std::function dfsVisit; - dfsVisit = [&](const Path & path, const Path * parent) { - if (parents.find(path) != parents.end()) - throw BuildError(format("cycle detected in the references of '%1%' from '%2%'") % path % *parent); + dfsVisit = [&](const StorePath & path, const StorePath * parent) { + if (parents.count(path)) + throw BuildError("cycle detected in the references of '%s' from '%s'", + printStorePath(path), printStorePath(*parent)); - if (!visited.insert(path).second) return; - parents.insert(path); + if (!visited.insert(path.clone()).second) return; + parents.insert(path.clone()); - PathSet references; + StorePathSet references; try { - references = queryPathInfo(path)->references; + references = cloneStorePathSet(queryPathInfo(path)->references); } catch (InvalidPath &) { } for (auto & i : references) /* Don't traverse into paths that don't exist. That can happen due to substitutes for non-existent paths. */ - if (i != path && paths.find(i) != paths.end()) + if (i != path && paths.count(i)) dfsVisit(i, &path); - sorted.push_front(path); + sorted.push_back(path.clone()); parents.erase(path); }; for (auto & i : paths) dfsVisit(i, nullptr); + std::reverse(sorted.begin(), sorted.end()); + return sorted; } diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index 5bf982195..3a2cde55f 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -193,11 +193,8 @@ public: if (!queryNAR.getInt(0)) return {oInvalid, 0}; - auto narInfo = make_ref(); - auto namePart = queryNAR.getStr(1); - narInfo->path = cache.storeDir + "/" + - hashPart + (namePart.empty() ? "" : "-" + namePart); + auto narInfo = make_ref(StorePath::fromBaseName(hashPart + "-" + namePart)); narInfo->url = queryNAR.getStr(2); narInfo->compression = queryNAR.getStr(3); if (!queryNAR.isNull(4)) @@ -206,9 +203,9 @@ public: narInfo->narHash = Hash(queryNAR.getStr(6)); narInfo->narSize = queryNAR.getInt(7); for (auto & r : tokenizeString(queryNAR.getStr(8), " ")) - narInfo->references.insert(cache.storeDir + "/" + r); + narInfo->references.insert(StorePath::fromBaseName(r)); if (!queryNAR.isNull(9)) - narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(9); + narInfo->deriver = StorePath::fromBaseName(queryNAR.getStr(9)); for (auto & sig : tokenizeString(queryNAR.getStr(10), " ")) narInfo->sigs.insert(sig); narInfo->ca = queryNAR.getStr(11); @@ -230,12 +227,12 @@ public: auto narInfo = std::dynamic_pointer_cast(info); - assert(hashPart == storePathToHash(info->path)); + //assert(hashPart == storePathToHash(info->path)); state->insertNAR.use() (cache.id) (hashPart) - (storePathToName(info->path)) + (std::string(info->path.name())) (narInfo ? narInfo->url : "", narInfo != 0) (narInfo ? narInfo->compression : "", narInfo != 0) (narInfo && narInfo->fileHash ? narInfo->fileHash.to_string() : "", narInfo && narInfo->fileHash) @@ -243,7 +240,7 @@ public: (info->narHash.to_string()) (info->narSize) (concatStringsSep(" ", info->shortRefs())) - (info->deriver != "" ? baseNameOf(info->deriver) : "", info->deriver != "") + (info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver) (concatStringsSep(" ", info->sigs)) (info->ca) (time(0)).exec(); diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index cb568ccdc..fb02cf3fd 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -4,6 +4,7 @@ namespace nix { NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence) + : ValidPathInfo(StorePath::make((unsigned char *) "xxxxxxxxxxxxxxxxxxxx", "x")) // FIXME: hack { auto corrupt = [&]() { throw Error(format("NAR info file '%1%' is corrupt") % whence); @@ -18,6 +19,8 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & } }; + bool havePath = false; + size_t pos = 0; while (pos < s.size()) { @@ -32,8 +35,8 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & std::string value(s, colon + 2, eol - colon - 2); if (name == "StorePath") { - if (!store.isStorePath(value)) corrupt(); - path = value; + path = store.parseStorePath(value); + havePath = true; } else if (name == "URL") url = value; @@ -52,18 +55,12 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & else if (name == "References") { auto refs = tokenizeString(value, " "); if (!references.empty()) corrupt(); - for (auto & r : refs) { - auto r2 = store.storeDir + "/" + r; - if (!store.isStorePath(r2)) corrupt(); - references.insert(r2); - } + for (auto & r : refs) + references.insert(StorePath::fromBaseName(r)); } else if (name == "Deriver") { - if (value != "unknown-deriver") { - auto p = store.storeDir + "/" + value; - if (!store.isStorePath(p)) corrupt(); - deriver = p; - } + if (value != "unknown-deriver") + deriver = StorePath::fromBaseName(value); } else if (name == "System") system = value; @@ -79,13 +76,13 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & if (compression == "") compression = "bzip2"; - if (path.empty() || url.empty() || narSize == 0 || !narHash) corrupt(); + if (!havePath || url.empty() || narSize == 0 || !narHash) corrupt(); } -std::string NarInfo::to_string() const +std::string NarInfo::to_string(const Store & store) const { std::string res; - res += "StorePath: " + path + "\n"; + res += "StorePath: " + store.printStorePath(path) + "\n"; res += "URL: " + url + "\n"; assert(compression != ""); res += "Compression: " + compression + "\n"; @@ -98,8 +95,8 @@ std::string NarInfo::to_string() const res += "References: " + concatStringsSep(" ", shortRefs()) + "\n"; - if (!deriver.empty()) - res += "Deriver: " + baseNameOf(deriver) + "\n"; + if (deriver) + res += "Deriver: " + std::string(deriver->to_string()) + "\n"; if (!system.empty()) res += "System: " + system + "\n"; diff --git a/src/libstore/nar-info.hh b/src/libstore/nar-info.hh index 4995061fb..373c33427 100644 --- a/src/libstore/nar-info.hh +++ b/src/libstore/nar-info.hh @@ -14,11 +14,12 @@ struct NarInfo : ValidPathInfo uint64_t fileSize = 0; std::string system; - NarInfo() { } + NarInfo() = delete; + NarInfo(StorePath && path) : ValidPathInfo(std::move(path)) { } NarInfo(const ValidPathInfo & info) : ValidPathInfo(info) { } NarInfo(const Store & store, const std::string & s, const std::string & whence); - std::string to_string() const; + std::string to_string(const Store & store) const; }; } diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 991512f21..8ac382e9d 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -254,7 +254,7 @@ void LocalStore::optimiseStore(OptimiseStats & stats) { Activity act(*logger, actOptimiseStore); - PathSet paths = queryAllValidPaths(); + auto paths = queryAllValidPaths(); InodeHash inodeHash = loadInodeHash(); act.progress(0, paths.size()); @@ -265,8 +265,8 @@ void LocalStore::optimiseStore(OptimiseStats & stats) addTempRoot(i); if (!isValidPath(i)) continue; /* path was GC'ed, probably */ { - Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", i)); - optimisePath_(&act, stats, realStoreDir + "/" + baseNameOf(i), inodeHash); + Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", printStorePath(i))); + optimisePath_(&act, stats, realStoreDir + "/" + std::string(i.to_string()), inodeHash); } done++; act.progress(done, paths.size()); diff --git a/src/libstore/parsed-derivations.cc b/src/libstore/parsed-derivations.cc index 87be8a24e..d0f289a0f 100644 --- a/src/libstore/parsed-derivations.cc +++ b/src/libstore/parsed-derivations.cc @@ -2,8 +2,8 @@ namespace nix { -ParsedDerivation::ParsedDerivation(const Path & drvPath, BasicDerivation & drv) - : drvPath(drvPath), drv(drv) +ParsedDerivation::ParsedDerivation(StorePath && drvPath, BasicDerivation & drv) + : drvPath(std::move(drvPath)), drv(drv) { /* Parse the __json attribute, if any. */ auto jsonAttr = drv.env.find("__json"); @@ -11,7 +11,7 @@ ParsedDerivation::ParsedDerivation(const Path & drvPath, BasicDerivation & drv) try { structuredAttrs = nlohmann::json::parse(jsonAttr->second); } catch (std::exception & e) { - throw Error("cannot process __json attribute of '%s': %s", drvPath, e.what()); + throw Error("cannot process __json attribute of '%s': %s", drvPath.to_string(), e.what()); } } } @@ -24,7 +24,7 @@ std::optional ParsedDerivation::getStringAttr(const std::string & n return {}; else { if (!i->is_string()) - throw Error("attribute '%s' of derivation '%s' must be a string", name, drvPath); + throw Error("attribute '%s' of derivation '%s' must be a string", name, drvPath.to_string()); return i->get(); } } else { @@ -44,7 +44,7 @@ bool ParsedDerivation::getBoolAttr(const std::string & name, bool def) const return def; else { if (!i->is_boolean()) - throw Error("attribute '%s' of derivation '%s' must be a Boolean", name, drvPath); + throw Error("attribute '%s' of derivation '%s' must be a Boolean", name, drvPath.to_string()); return i->get(); } } else { @@ -64,11 +64,11 @@ std::optional ParsedDerivation::getStringsAttr(const std::string & name return {}; else { if (!i->is_array()) - throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath); + throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath.to_string()); 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); + throw Error("attribute '%s' of derivation '%s' must be a list of strings", name, drvPath.to_string()); res.push_back(j->get()); } return res; diff --git a/src/libstore/parsed-derivations.hh b/src/libstore/parsed-derivations.hh index 9bde4b4dc..cec868754 100644 --- a/src/libstore/parsed-derivations.hh +++ b/src/libstore/parsed-derivations.hh @@ -6,13 +6,13 @@ namespace nix { class ParsedDerivation { - Path drvPath; + StorePath drvPath; BasicDerivation & drv; std::optional structuredAttrs; public: - ParsedDerivation(const Path & drvPath, BasicDerivation & drv); + ParsedDerivation(StorePath && drvPath, BasicDerivation & drv); const std::optional & getStructuredAttrs() const { diff --git a/src/libstore/path.cc b/src/libstore/path.cc new file mode 100644 index 000000000..81ae495a1 --- /dev/null +++ b/src/libstore/path.cc @@ -0,0 +1,99 @@ +#include "store-api.hh" + +namespace nix { + +extern "C" { + rust::Result ffi_StorePath_new(rust::StringSlice path, rust::StringSlice storeDir); + rust::Result ffi_StorePath_new2(unsigned char hash[20], rust::StringSlice storeDir); + rust::Result ffi_StorePath_fromBaseName(rust::StringSlice baseName); + rust::String ffi_StorePath_to_string(const StorePath & _this); + StorePath ffi_StorePath_clone(const StorePath & _this); + rust::StringSlice ffi_StorePath_name(const StorePath & _this); +} + +StorePath StorePath::make(std::string_view path, std::string_view storeDir) +{ + return ffi_StorePath_new((rust::StringSlice) path, (rust::StringSlice) storeDir).unwrap(); +} + +StorePath StorePath::make(unsigned char hash[20], std::string_view name) +{ + return ffi_StorePath_new2(hash, (rust::StringSlice) name).unwrap(); +} + +StorePath StorePath::fromBaseName(std::string_view baseName) +{ + return ffi_StorePath_fromBaseName((rust::StringSlice) baseName).unwrap(); +} + +rust::String StorePath::to_string() const +{ + return ffi_StorePath_to_string(*this); +} + +StorePath StorePath::clone() const +{ + return ffi_StorePath_clone(*this); +} + +bool StorePath::isDerivation() const +{ + return hasSuffix(name(), drvExtension); +} + +std::string_view StorePath::name() const +{ + return ffi_StorePath_name(*this); +} + +StorePath Store::parseStorePath(std::string_view path) const +{ + return StorePath::make(path, storeDir); +} + + +StorePathSet Store::parseStorePathSet(const PathSet & paths) const +{ + StorePathSet res; + for (auto & i : paths) res.insert(parseStorePath(i)); + return res; +} + +std::string Store::printStorePath(const StorePath & path) const +{ + auto s = storeDir + "/"; + s += (std::string_view) path.to_string(); + return s; +} + +PathSet Store::printStorePathSet(const StorePathSet & paths) const +{ + PathSet res; + for (auto & i : paths) res.insert(printStorePath(i)); + return res; +} + +StorePathSet cloneStorePathSet(const StorePathSet & paths) +{ + StorePathSet res; + for (auto & p : paths) + res.insert(p.clone()); + return res; +} + +StorePathSet storePathsToSet(const StorePaths & paths) +{ + StorePathSet res; + for (auto & p : paths) + res.insert(p.clone()); + return res; +} + +StorePathSet singleton(const StorePath & path) +{ + StorePathSet res; + res.insert(path.clone()); + return res; +} + +} diff --git a/src/libstore/path.hh b/src/libstore/path.hh new file mode 100644 index 000000000..273808f02 --- /dev/null +++ b/src/libstore/path.hh @@ -0,0 +1,81 @@ +#pragma once + +#include "rust-ffi.hh" + +namespace nix { + +/* See path.rs. */ +struct StorePath; + +extern "C" { + void ffi_StorePath_drop(void *); + bool ffi_StorePath_less_than(const StorePath & a, const StorePath & b); + bool ffi_StorePath_eq(const StorePath & a, const StorePath & b); + unsigned char * ffi_StorePath_hash_data(const StorePath & p); +} + +struct StorePath : rust::Value<3 * sizeof(void *) + 24, ffi_StorePath_drop> +{ + static StorePath make(std::string_view path, std::string_view storeDir); + + static StorePath make(unsigned char hash[20], std::string_view name); + + static StorePath fromBaseName(std::string_view baseName); + + rust::String to_string() const; + + bool operator < (const StorePath & other) const + { + return ffi_StorePath_less_than(*this, other); + } + + bool operator == (const StorePath & other) const + { + return ffi_StorePath_eq(*this, other); + } + + bool operator != (const StorePath & other) const + { + return !(*this == other); + } + + StorePath clone() const; + + /* Check whether a file name ends with the extension for + derivations. */ + bool isDerivation() const; + + std::string_view name() const; + + unsigned char * hashData() const + { + return ffi_StorePath_hash_data(*this); + } +}; + +typedef std::set StorePathSet; +typedef std::vector StorePaths; + +StorePathSet cloneStorePathSet(const StorePathSet & paths); +StorePathSet storePathsToSet(const StorePaths & paths); + +StorePathSet singleton(const StorePath & path); + +/* Size of the hash part of store paths, in base-32 characters. */ +const size_t storePathHashLen = 32; // i.e. 160 bits + +/* Extension of derivations in the Nix store. */ +const std::string drvExtension = ".drv"; + +} + +namespace std { + +template<> struct hash { + std::size_t operator()(const nix::StorePath & path) const noexcept + { + return * (std::size_t *) path.hashData(); + } +}; + +} diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index 4c6af567a..dae3f2d32 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -40,7 +40,7 @@ Generations findGenerations(Path profile, int & curGen) Generations gens; Path profileDir = dirOf(profile); - string profileName = baseNameOf(profile); + auto profileName = std::string(baseNameOf(profile)); for (auto & i : readDirectory(profileDir)) { int n; @@ -108,7 +108,7 @@ Path createGeneration(ref store, Path profile, Path outPath) user environment etc. we've just built. */ Path generation; makeName(profile, num + 1, generation); - store->addPermRoot(outPath, generation, false, true); + store->addPermRoot(store->parseStorePath(outPath), generation, false, true); return generation; } diff --git a/src/libstore/references.cc b/src/libstore/references.cc index 605ca9815..102e15921 100644 --- a/src/libstore/references.cc +++ b/src/libstore/references.cc @@ -89,7 +89,7 @@ PathSet scanForReferences(const string & path, hash part of the file name. (This assumes that all references have the form `HASH-bla'). */ for (auto & i : refs) { - string baseName = baseNameOf(i); + auto baseName = std::string(baseNameOf(i)); string::size_type pos = baseName.find('-'); if (pos == string::npos) throw Error(format("bad reference '%1%'") % i); diff --git a/src/libstore/remote-fs-accessor.cc b/src/libstore/remote-fs-accessor.cc index 5233fb2c2..5a2d103b9 100644 --- a/src/libstore/remote-fs-accessor.cc +++ b/src/libstore/remote-fs-accessor.cc @@ -50,7 +50,7 @@ std::pair, Path> RemoteFSAccessor::fetch(const Path & path_) auto storePath = store->toStorePath(path); std::string restPath = std::string(path, storePath.size()); - if (!store->isValidPath(storePath)) + if (!store->isValidPath(store->parseStorePath(storePath))) throw InvalidPath(format("path '%1%' is not a valid store path") % storePath); auto i = nars.find(storePath); @@ -96,7 +96,7 @@ std::pair, Path> RemoteFSAccessor::fetch(const Path & path_) } catch (SysError &) { } } - store->narFromPath(storePath, sink); + store->narFromPath(store->parseStorePath(storePath), sink); auto narAccessor = makeNarAccessor(sink.s); addToCache(storePath, *sink.s, narAccessor); return {narAccessor, restPath}; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 2a89b7c98..8c55da268 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -22,23 +22,22 @@ namespace nix { -Path readStorePath(Store & store, Source & from) +template<> StorePathSet readStorePaths(const Store & store, Source & from) { - Path path = readString(from); - store.assertStorePath(path); - return path; -} - - -template T readStorePaths(Store & store, Source & from) -{ - T paths = readStrings(from); - for (auto & i : paths) store.assertStorePath(i); + StorePathSet paths; + for (auto & i : readStrings(from)) + paths.insert(store.parseStorePath(i)); return paths; } -template PathSet readStorePaths(Store & store, Source & from); -template Paths readStorePaths(Store & store, Source & from); + +void writeStorePaths(const Store & store, Sink & out, const StorePathSet & paths) +{ + out << paths.size(); + for (auto & i : paths) + out << store.printStorePath(i); +} + /* TODO: Separate these store impls into different files, give them better names */ RemoteStore::RemoteStore(const Params & params) @@ -254,60 +253,62 @@ ConnectionHandle RemoteStore::getConnection() } -bool RemoteStore::isValidPathUncached(const Path & path) +bool RemoteStore::isValidPathUncached(const StorePath & path) { auto conn(getConnection()); - conn->to << wopIsValidPath << path; + conn->to << wopIsValidPath << printStorePath(path); conn.processStderr(); return readInt(conn->from); } -PathSet RemoteStore::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubstitute) +StorePathSet RemoteStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { auto conn(getConnection()); if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) { - PathSet res; + StorePathSet res; for (auto & i : paths) - if (isValidPath(i)) res.insert(i); + if (isValidPath(i)) res.insert(i.clone()); return res; } else { - conn->to << wopQueryValidPaths << paths; + conn->to << wopQueryValidPaths; + writeStorePaths(*this, conn->to, paths); conn.processStderr(); - return readStorePaths(*this, conn->from); + return readStorePaths(*this, conn->from); } } -PathSet RemoteStore::queryAllValidPaths() +StorePathSet RemoteStore::queryAllValidPaths() { auto conn(getConnection()); conn->to << wopQueryAllValidPaths; conn.processStderr(); - return readStorePaths(*this, conn->from); + return readStorePaths(*this, conn->from); } -PathSet RemoteStore::querySubstitutablePaths(const PathSet & paths) +StorePathSet RemoteStore::querySubstitutablePaths(const StorePathSet & paths) { auto conn(getConnection()); if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) { - PathSet res; + StorePathSet res; for (auto & i : paths) { - conn->to << wopHasSubstitutes << i; + conn->to << wopHasSubstitutes << printStorePath(i); conn.processStderr(); - if (readInt(conn->from)) res.insert(i); + if (readInt(conn->from)) res.insert(i.clone()); } return res; } else { - conn->to << wopQuerySubstitutablePaths << paths; + conn->to << wopQuerySubstitutablePaths; + writeStorePaths(*this, conn->to, paths); conn.processStderr(); - return readStorePaths(*this, conn->from); + return readStorePaths(*this, conn->from); } } -void RemoteStore::querySubstitutablePathInfos(const PathSet & paths, +void RemoteStore::querySubstitutablePathInfos(const StorePathSet & paths, SubstitutablePathInfos & infos) { if (paths.empty()) return; @@ -318,29 +319,31 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths, for (auto & i : paths) { SubstitutablePathInfo info; - conn->to << wopQuerySubstitutablePathInfo << i; + conn->to << wopQuerySubstitutablePathInfo << printStorePath(i); conn.processStderr(); unsigned int reply = readInt(conn->from); if (reply == 0) continue; - info.deriver = readString(conn->from); - if (info.deriver != "") assertStorePath(info.deriver); - info.references = readStorePaths(*this, conn->from); + auto deriver = readString(conn->from); + if (deriver != "") + info.deriver = parseStorePath(deriver); + info.references = readStorePaths(*this, conn->from); info.downloadSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from); - infos[i] = info; + infos.insert_or_assign(i.clone(), std::move(info)); } } else { - conn->to << wopQuerySubstitutablePathInfos << paths; + conn->to << wopQuerySubstitutablePathInfos; + writeStorePaths(*this, conn->to, paths); conn.processStderr(); size_t count = readNum(conn->from); for (size_t n = 0; n < count; n++) { - Path path = readStorePath(*this, conn->from); - SubstitutablePathInfo & info(infos[path]); - info.deriver = readString(conn->from); - if (info.deriver != "") assertStorePath(info.deriver); - info.references = readStorePaths(*this, conn->from); + SubstitutablePathInfo & info(infos[parseStorePath(readString(conn->from))]); + auto deriver = readString(conn->from); + if (deriver != "") + info.deriver = parseStorePath(deriver); + info.references = readStorePaths(*this, conn->from); info.downloadSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from); } @@ -349,14 +352,14 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths, } -void RemoteStore::queryPathInfoUncached(const Path & path, +void RemoteStore::queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept { try { std::shared_ptr info; { auto conn(getConnection()); - conn->to << wopQueryPathInfo << path; + conn->to << wopQueryPathInfo << printStorePath(path); try { conn.processStderr(); } catch (Error & e) { @@ -367,14 +370,13 @@ void RemoteStore::queryPathInfoUncached(const Path & path, } if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 17) { bool valid; conn->from >> valid; - if (!valid) throw InvalidPath(format("path '%s' is not valid") % path); + if (!valid) throw InvalidPath("path '%s' is not valid", printStorePath(path)); } - info = std::make_shared(); - info->path = path; - info->deriver = readString(conn->from); - if (info->deriver != "") assertStorePath(info->deriver); + info = std::make_shared(path.clone()); + auto deriver = readString(conn->from); + if (deriver != "") info->deriver = parseStorePath(deriver); info->narHash = Hash(readString(conn->from), htSHA256); - info->references = readStorePaths(*this, conn->from); + info->references = readStorePaths(*this, conn->from); conn->from >> info->registrationTime >> info->narSize; if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) { conn->from >> info->ultimate; @@ -387,52 +389,52 @@ void RemoteStore::queryPathInfoUncached(const Path & path, } -void RemoteStore::queryReferrers(const Path & path, - PathSet & referrers) +void RemoteStore::queryReferrers(const StorePath & path, + StorePathSet & referrers) { auto conn(getConnection()); - conn->to << wopQueryReferrers << path; + conn->to << wopQueryReferrers << printStorePath(path); conn.processStderr(); - PathSet referrers2 = readStorePaths(*this, conn->from); - referrers.insert(referrers2.begin(), referrers2.end()); + for (auto & i : readStorePaths(*this, conn->from)) + referrers.insert(i.clone()); } -PathSet RemoteStore::queryValidDerivers(const Path & path) +StorePathSet RemoteStore::queryValidDerivers(const StorePath & path) { auto conn(getConnection()); - conn->to << wopQueryValidDerivers << path; + conn->to << wopQueryValidDerivers << printStorePath(path); conn.processStderr(); - return readStorePaths(*this, conn->from); + return readStorePaths(*this, conn->from); } -PathSet RemoteStore::queryDerivationOutputs(const Path & path) +StorePathSet RemoteStore::queryDerivationOutputs(const StorePath & path) { auto conn(getConnection()); - conn->to << wopQueryDerivationOutputs << path; + conn->to << wopQueryDerivationOutputs << printStorePath(path); conn.processStderr(); - return readStorePaths(*this, conn->from); + return readStorePaths(*this, conn->from); } -PathSet RemoteStore::queryDerivationOutputNames(const Path & path) +PathSet RemoteStore::queryDerivationOutputNames(const StorePath & path) { auto conn(getConnection()); - conn->to << wopQueryDerivationOutputNames << path; + conn->to << wopQueryDerivationOutputNames << printStorePath(path); conn.processStderr(); return readStrings(conn->from); } -Path RemoteStore::queryPathFromHashPart(const string & hashPart) +std::optional RemoteStore::queryPathFromHashPart(const std::string & hashPart) { auto conn(getConnection()); conn->to << wopQueryPathFromHashPart << hashPart; conn.processStderr(); Path path = readString(conn->from); - if (!path.empty()) assertStorePath(path); - return path; + if (path.empty()) return {}; + return parseStorePath(path); } @@ -450,9 +452,10 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, copyNAR(source, sink); sink << exportMagic - << info.path - << info.references - << info.deriver + << printStorePath(info.path); + writeStorePaths(*this, sink, info.references); + sink + << (info.deriver ? printStorePath(*info.deriver) : "") << 0 // == no legacy signature << 0 // == no path follows ; @@ -460,14 +463,17 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, conn.processStderr(0, source2.get()); - auto importedPaths = readStorePaths(*this, conn->from); + auto importedPaths = readStorePaths(*this, conn->from); assert(importedPaths.size() <= 1); } else { conn->to << wopAddToStoreNar - << info.path << info.deriver << info.narHash.to_string(Base16, false) - << info.references << info.registrationTime << info.narSize + << printStorePath(info.path) + << (info.deriver ? printStorePath(*info.deriver) : "") + << info.narHash.to_string(Base16, false); + writeStorePaths(*this, conn->to, info.references); + conn->to << info.registrationTime << info.narSize << info.ultimate << info.sigs << info.ca << repair << !checkSigs; bool tunnel = GET_PROTOCOL_MINOR(conn->daemonVersion) >= 21; @@ -477,7 +483,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, } -Path RemoteStore::addToStore(const string & name, const Path & _srcPath, +StorePath RemoteStore::addToStore(const string & name, const Path & _srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) { if (repair) throw Error("repairing is not supported when building through the Nix daemon"); @@ -511,54 +517,52 @@ Path RemoteStore::addToStore(const string & name, const Path & _srcPath, throw; } - return readStorePath(*this, conn->from); + return parseStorePath(readString(conn->from)); } -Path RemoteStore::addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) +StorePath RemoteStore::addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) { if (repair) throw Error("repairing is not supported when building through the Nix daemon"); auto conn(getConnection()); - conn->to << wopAddTextToStore << name << s << references; + conn->to << wopAddTextToStore << name << s; + writeStorePaths(*this, conn->to, references); conn.processStderr(); - return readStorePath(*this, conn->from); + return parseStorePath(readString(conn->from)); } -void RemoteStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) +void RemoteStore::buildPaths(const std::vector & drvPaths, BuildMode buildMode) { auto conn(getConnection()); conn->to << wopBuildPaths; - if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13) { - conn->to << drvPaths; - if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15) - conn->to << buildMode; - else - /* Old daemons did not take a 'buildMode' parameter, so we - need to validate it here on the client side. */ - if (buildMode != bmNormal) - throw Error("repairing or checking is not supported when building through the Nix daemon"); - } else { - /* For backwards compatibility with old daemons, strip output - identifiers. */ - PathSet drvPaths2; - for (auto & i : drvPaths) - drvPaths2.insert(string(i, 0, i.find('!'))); - conn->to << drvPaths2; - } + assert(GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13); + Strings ss; + for (auto & p : drvPaths) + ss.push_back(p.to_string(*this)); + conn->to << ss; + if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15) + conn->to << buildMode; + else + /* Old daemons did not take a 'buildMode' parameter, so we + need to validate it here on the client side. */ + if (buildMode != bmNormal) + throw Error("repairing or checking is not supported when building through the Nix daemon"); conn.processStderr(); readInt(conn->from); } -BuildResult RemoteStore::buildDerivation(const Path & drvPath, const BasicDerivation & drv, +BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) { auto conn(getConnection()); - conn->to << wopBuildDerivation << drvPath << drv << buildMode; + conn->to << wopBuildDerivation << printStorePath(drvPath); + writeDerivation(conn->to, *this, drv); + conn->to << buildMode; conn.processStderr(); BuildResult res; unsigned int status; @@ -568,19 +572,19 @@ BuildResult RemoteStore::buildDerivation(const Path & drvPath, const BasicDeriva } -void RemoteStore::ensurePath(const Path & path) +void RemoteStore::ensurePath(const StorePath & path) { auto conn(getConnection()); - conn->to << wopEnsurePath << path; + conn->to << wopEnsurePath << printStorePath(path); conn.processStderr(); readInt(conn->from); } -void RemoteStore::addTempRoot(const Path & path) +void RemoteStore::addTempRoot(const StorePath & path) { auto conn(getConnection()); - conn->to << wopAddTempRoot << path; + conn->to << wopAddTempRoot << printStorePath(path); conn.processStderr(); readInt(conn->from); } @@ -613,8 +617,8 @@ Roots RemoteStore::findRoots(bool censor) Roots result; while (count--) { Path link = readString(conn->from); - Path target = readStorePath(*this, conn->from); - result[target].emplace(link); + auto target = parseStorePath(readString(conn->from)); + result[std::move(target)].emplace(link); } return result; } @@ -625,7 +629,9 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results) auto conn(getConnection()); conn->to - << wopCollectGarbage << options.action << options.pathsToDelete << options.ignoreLiveness + << wopCollectGarbage << options.action; + writeStorePaths(*this, conn->to, options.pathsToDelete); + conn->to << options.ignoreLiveness << options.maxFreed /* removed options */ << 0 << 0 << 0; @@ -661,17 +667,17 @@ bool RemoteStore::verifyStore(bool checkContents, RepairFlag repair) } -void RemoteStore::addSignatures(const Path & storePath, const StringSet & sigs) +void RemoteStore::addSignatures(const StorePath & storePath, const StringSet & sigs) { auto conn(getConnection()); - conn->to << wopAddSignatures << storePath << sigs; + conn->to << wopAddSignatures << printStorePath(storePath) << sigs; conn.processStderr(); readInt(conn->from); } -void RemoteStore::queryMissing(const PathSet & targets, - PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown, +void RemoteStore::queryMissing(const std::vector & targets, + StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, unsigned long long & downloadSize, unsigned long long & narSize) { { @@ -680,11 +686,15 @@ void RemoteStore::queryMissing(const PathSet & targets, // Don't hold the connection handle in the fallback case // to prevent a deadlock. goto fallback; - conn->to << wopQueryMissing << targets; + conn->to << wopQueryMissing; + Strings ss; + for (auto & p : targets) + ss.push_back(p.to_string(*this)); + conn->to << ss; conn.processStderr(); - willBuild = readStorePaths(*this, conn->from); - willSubstitute = readStorePaths(*this, conn->from); - unknown = readStorePaths(*this, conn->from); + willBuild = readStorePaths(*this, conn->from); + willSubstitute = readStorePaths(*this, conn->from); + unknown = readStorePaths(*this, conn->from); conn->from >> downloadSize >> narSize; return; } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 728df8b00..f301a97d8 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -35,50 +35,50 @@ public: /* Implementations of abstract store API methods. */ - bool isValidPathUncached(const Path & path) override; + bool isValidPathUncached(const StorePath & path) override; - PathSet queryValidPaths(const PathSet & paths, + StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute) override; - PathSet queryAllValidPaths() override; + StorePathSet queryAllValidPaths() override; - void queryPathInfoUncached(const Path & path, + void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept override; - void queryReferrers(const Path & path, PathSet & referrers) override; + void queryReferrers(const StorePath & path, StorePathSet & referrers) override; - PathSet queryValidDerivers(const Path & path) override; + StorePathSet queryValidDerivers(const StorePath & path) override; - PathSet queryDerivationOutputs(const Path & path) override; + StorePathSet queryDerivationOutputs(const StorePath & path) override; - StringSet queryDerivationOutputNames(const Path & path) override; + StringSet queryDerivationOutputNames(const StorePath & path) override; - Path queryPathFromHashPart(const string & hashPart) override; + std::optional queryPathFromHashPart(const std::string & hashPart) override; - PathSet querySubstitutablePaths(const PathSet & paths) override; + StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; - void querySubstitutablePathInfos(const PathSet & paths, + void querySubstitutablePathInfos(const StorePathSet & paths, SubstitutablePathInfos & infos) override; void addToStore(const ValidPathInfo & info, Source & nar, RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr accessor) override; - Path addToStore(const string & name, const Path & srcPath, + StorePath addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair) override; - Path addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair) override; + StorePath addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair) override; - void buildPaths(const PathSet & paths, BuildMode buildMode) override; + void buildPaths(const std::vector & paths, BuildMode buildMode) override; - BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, + BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) override; - void ensurePath(const Path & path) override; + void ensurePath(const StorePath & path) override; - void addTempRoot(const Path & path) override; + void addTempRoot(const StorePath & path) override; void addIndirectRoot(const Path & path) override; @@ -92,10 +92,10 @@ public: bool verifyStore(bool checkContents, RepairFlag repair) override; - void addSignatures(const Path & storePath, const StringSet & sigs) override; + void addSignatures(const StorePath & storePath, const StringSet & sigs) override; - void queryMissing(const PathSet & targets, - PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown, + void queryMissing(const std::vector & targets, + StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, unsigned long long & downloadSize, unsigned long long & narSize) override; void connect() override; diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index cd547a964..58966a5b7 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -222,7 +222,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore fetches the .narinfo file, rather than first checking for its existence via a HEAD request. Since .narinfos are small, doing a GET is unlikely to be slower than HEAD. */ - bool isValidPathUncached(const Path & storePath) override + bool isValidPathUncached(const StorePath & storePath) override { try { queryPathInfo(storePath); @@ -382,9 +382,9 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri()); } - PathSet queryAllValidPaths() override + StorePathSet queryAllValidPaths() override { - PathSet paths; + StorePathSet paths; std::string marker; do { @@ -405,7 +405,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore for (auto object : contents) { auto & key = object.GetKey(); if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue; - paths.insert(storeDir + "/" + key.substr(0, key.size() - 8)); + paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-unknown")); } marker = res.GetNextMarker(); diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc index b9d0c41ea..42ee06501 100644 --- a/src/libstore/ssh-store.cc +++ b/src/libstore/ssh-store.cc @@ -38,7 +38,7 @@ public: bool sameMachine() override { return false; } - void narFromPath(const Path & path, Sink & sink) override; + void narFromPath(const StorePath & path, Sink & sink) override; ref getFSAccessor() override; @@ -66,10 +66,10 @@ private: }; }; -void SSHStore::narFromPath(const Path & path, Sink & sink) +void SSHStore::narFromPath(const StorePath & path, Sink & sink) { auto conn(connections->get()); - conn->to << wopNarFromPath << path; + conn->to << wopNarFromPath << printStorePath(path); conn->processStderr(); copyNAR(conn->from, sink); } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 7e548ecd2..c98931885 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -27,13 +27,6 @@ bool Store::isStorePath(const Path & path) const } -void Store::assertStorePath(const Path & path) const -{ - if (!isStorePath(path)) - throw Error(format("path '%1%' is not in the Nix store") % path); -} - - Path Store::toStorePath(const Path & path) const { if (!isInStore(path)) @@ -60,17 +53,9 @@ Path Store::followLinksToStore(const Path & _path) const } -Path Store::followLinksToStorePath(const Path & path) const +StorePath Store::followLinksToStorePath(const Path & path) const { - return toStorePath(followLinksToStore(path)); -} - - -string storePathToName(const Path & path) -{ - auto base = baseNameOf(path); - assert(base.size() == storePathHashLen || (base.size() > storePathHashLen && base[storePathHashLen] == '-')); - return base.size() == storePathHashLen ? "" : string(base, storePathHashLen + 1); + return parseStorePath(toStorePath(followLinksToStore(path))); } @@ -82,41 +67,6 @@ string storePathToHash(const Path & path) } -void checkStoreName(const string & name) -{ - string validChars = "+-._?="; - - auto baseError = format("The path name '%2%' is invalid: %3%. " - "Path names are alphanumeric and can include the symbols %1% " - "and must not begin with a period. " - "Note: If '%2%' is a source file and you cannot rename it on " - "disk, 'builtins.path { name = ... }' can be used to give it an " - "alternative name.") % validChars % name; - - if (name.empty()) - throw Error(baseError % "it is an empty string"); - - /* Disallow names starting with a dot for possible security - reasons (e.g., "." and ".."). */ - if (name[0] == '.') - throw Error(baseError % "it is illegal to start the name with a period"); - - /* Disallow names longer than 211 characters. ext4’s max is 256, - but we need extra space for the hash and .chroot extensions. */ - if (name.length() > 211) - throw Error(baseError % "name must be less than 212 characters"); - - for (auto & i : name) - if (!((i >= 'A' && i <= 'Z') || - (i >= 'a' && i <= 'z') || - (i >= '0' && i <= '9') || - validChars.find(i) != string::npos)) - { - throw Error(baseError % (format("the '%1%' character is invalid") % i)); - } -} - - /* Store paths have the following form: /- @@ -188,43 +138,48 @@ void checkStoreName(const string & name) */ -Path Store::makeStorePath(const string & type, - const Hash & hash, const string & name) const +StorePath Store::makeStorePath(const string & type, + const Hash & hash, std::string_view name) const { /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ - string s = type + ":" + hash.to_string(Base16) + ":" + storeDir + ":" + name; - - checkStoreName(name); - - return storeDir + "/" - + compressHash(hashString(htSHA256, s), 20).to_string(Base32, false) - + "-" + name; + string s = type + ":" + hash.to_string(Base16) + ":" + storeDir + ":" + std::string(name); + auto h = compressHash(hashString(htSHA256, s), 20); + return StorePath::make(h.hash, name); } -Path Store::makeOutputPath(const string & id, - const Hash & hash, const string & name) const +StorePath Store::makeOutputPath(const string & id, + const Hash & hash, std::string_view name) const { return makeStorePath("output:" + id, hash, - name + (id == "out" ? "" : "-" + id)); + std::string(name) + (id == "out" ? "" : "-" + id)); } -static std::string makeType(string && type, const PathSet & references) +static std::string makeType( + const Store & store, + string && type, + const StorePathSet & references, + bool hasSelfReference = false) { for (auto & i : references) { type += ":"; - type += i; + type += store.printStorePath(i); } + if (hasSelfReference) type += ":self"; return std::move(type); } -Path Store::makeFixedOutputPath(bool recursive, - const Hash & hash, const string & name, const PathSet & references) const +StorePath Store::makeFixedOutputPath( + bool recursive, + const Hash & hash, + std::string_view name, + const StorePathSet & references, + bool hasSelfReference) const { if (hash.type == htSHA256 && recursive) { - return makeStorePath(makeType("source", references), hash, name); + return makeStorePath(makeType(*this, "source", references, hasSelfReference), hash, name); } else { assert(references.empty()); return makeStorePath("output:out", hashString(htSHA256, @@ -234,28 +189,27 @@ Path Store::makeFixedOutputPath(bool recursive, } -Path Store::makeTextPath(const string & name, const Hash & hash, - const PathSet & references) const +StorePath Store::makeTextPath(std::string_view name, const Hash & hash, + const StorePathSet & references) const { assert(hash.type == htSHA256); /* Stuff the references (if any) into the type. This is a bit hacky, but we can't put them in `s' since that would be ambiguous. */ - return makeStorePath(makeType("text", references), hash, name); + return makeStorePath(makeType(*this, "text", references), hash, name); } -std::pair Store::computeStorePathForPath(const string & name, +std::pair Store::computeStorePathForPath(std::string_view name, const Path & srcPath, bool recursive, HashType hashAlgo, PathFilter & filter) const { Hash h = recursive ? hashPath(hashAlgo, srcPath, filter).first : hashFile(hashAlgo, srcPath); - Path dstPath = makeFixedOutputPath(recursive, h, name); - return std::pair(dstPath, h); + return std::make_pair(makeFixedOutputPath(recursive, h, name), h); } -Path Store::computeStorePathForText(const string & name, const string & s, - const PathSet & references) const +StorePath Store::computeStorePathForText(const string & name, const string & s, + const StorePathSet & references) const { return makeTextPath(name, hashString(htSHA256, s), references); } @@ -274,11 +228,9 @@ std::string Store::getUri() } -bool Store::isValidPath(const Path & storePath) +bool Store::isValidPath(const StorePath & storePath) { - assertStorePath(storePath); - - auto hashPart = storePathToHash(storePath); + auto hashPart = storePathToHash(printStorePath(storePath)); { auto state_(state.lock()); @@ -312,7 +264,7 @@ bool Store::isValidPath(const Path & storePath) /* Default implementation for stores that only implement queryPathInfoUncached(). */ -bool Store::isValidPathUncached(const Path & path) +bool Store::isValidPathUncached(const StorePath & path) { try { queryPathInfo(path); @@ -323,7 +275,7 @@ bool Store::isValidPathUncached(const Path & path) } -ref Store::queryPathInfo(const Path & storePath) +ref Store::queryPathInfo(const StorePath & storePath) { std::promise> promise; @@ -340,22 +292,20 @@ ref Store::queryPathInfo(const Path & storePath) } -void Store::queryPathInfo(const Path & storePath, +void Store::queryPathInfo(const StorePath & storePath, Callback> callback) noexcept { std::string hashPart; try { - assertStorePath(storePath); - - hashPart = storePathToHash(storePath); + hashPart = storePathToHash(printStorePath(storePath)); { auto res = state.lock()->pathInfoCache.get(hashPart); if (res) { stats.narInfoReadAverted++; if (!*res) - throw InvalidPath(format("path '%s' is not valid") % storePath); + throw InvalidPath("path '%s' is not valid", printStorePath(storePath)); return callback(ref(*res)); } } @@ -369,8 +319,8 @@ void Store::queryPathInfo(const Path & storePath, state_->pathInfoCache.upsert(hashPart, res.first == NarInfoDiskCache::oInvalid ? 0 : res.second); if (res.first == NarInfoDiskCache::oInvalid || - (res.second->path != storePath && storePathToName(storePath) != "")) - throw InvalidPath(format("path '%s' is not valid") % storePath); + res.second->path != storePath) + throw InvalidPath("path '%s' is not valid", printStorePath(storePath)); } return callback(ref(res.second)); } @@ -381,7 +331,7 @@ void Store::queryPathInfo(const Path & storePath, auto callbackPtr = std::make_shared(std::move(callback)); queryPathInfoUncached(storePath, - {[this, storePath, hashPart, callbackPtr](std::future> fut) { + {[this, storePath{printStorePath(storePath)}, hashPart, callbackPtr](std::future> fut) { try { auto info = fut.get(); @@ -394,9 +344,7 @@ void Store::queryPathInfo(const Path & storePath, state_->pathInfoCache.upsert(hashPart, info); } - if (!info - || (info->path != storePath && storePathToName(storePath) != "")) - { + if (!info || info->path != parseStorePath(storePath)) { stats.narInfoMissing++; throw InvalidPath("path '%s' is not valid", storePath); } @@ -407,27 +355,27 @@ void Store::queryPathInfo(const Path & storePath, } -PathSet Store::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubstitute) +StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) { struct State { size_t left; - PathSet valid; + StorePathSet valid; std::exception_ptr exc; }; - Sync state_(State{paths.size(), PathSet()}); + Sync state_(State{paths.size(), StorePathSet()}); std::condition_variable wakeup; ThreadPool pool; - auto doQuery = [&](const Path & path ) { + auto doQuery = [&](const Path & path) { checkInterrupt(); - queryPathInfo(path, {[path, &state_, &wakeup](std::future> fut) { + queryPathInfo(parseStorePath(path), {[path, this, &state_, &wakeup](std::future> fut) { auto state(state_.lock()); try { auto info = fut.get(); - state->valid.insert(path); + state->valid.insert(parseStorePath(path)); } catch (InvalidPath &) { } catch (...) { state->exc = std::current_exception(); @@ -439,7 +387,7 @@ PathSet Store::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubsti }; for (auto & path : paths) - pool.enqueue(std::bind(doQuery, path)); + pool.enqueue(std::bind(doQuery, printStorePath(path))); // FIXME pool.process(); @@ -447,7 +395,7 @@ PathSet Store::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubsti auto state(state_.lock()); if (!state->left) { if (state->exc) std::rethrow_exception(state->exc); - return state->valid; + return std::move(state->valid); } state.wait(wakeup); } @@ -457,13 +405,13 @@ PathSet Store::queryValidPaths(const PathSet & paths, SubstituteFlag maybeSubsti /* 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. */ -string Store::makeValidityRegistration(const PathSet & paths, +string Store::makeValidityRegistration(const StorePathSet & paths, bool showDerivers, bool showHash) { string s = ""; for (auto & i : paths) { - s += i + "\n"; + s += printStorePath(i) + "\n"; auto info = queryPathInfo(i); @@ -472,31 +420,30 @@ string Store::makeValidityRegistration(const PathSet & paths, s += (format("%1%\n") % info->narSize).str(); } - Path deriver = showDerivers ? info->deriver : ""; + auto deriver = showDerivers && info->deriver ? printStorePath(*info->deriver) : ""; s += deriver + "\n"; s += (format("%1%\n") % info->references.size()).str(); for (auto & j : info->references) - s += j + "\n"; + s += printStorePath(j) + "\n"; } return s; } -void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths, +void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & storePaths, bool includeImpureInfo, bool showClosureSize, AllowInvalidFlag allowInvalid) { auto jsonList = jsonOut.list(); - for (auto storePath : storePaths) { + for (auto & storePath : storePaths) { auto jsonPath = jsonList.object(); - jsonPath.attr("path", storePath); + jsonPath.attr("path", printStorePath(storePath)); try { auto info = queryPathInfo(storePath); - storePath = info->path; jsonPath .attr("narHash", info->narHash.to_string()) @@ -505,7 +452,7 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths { auto jsonRefs = jsonPath.list("references"); for (auto & ref : info->references) - jsonRefs.elem(ref); + jsonRefs.elem(printStorePath(ref)); } if (info->ca != "") @@ -514,14 +461,14 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths std::pair closureSizes; if (showClosureSize) { - closureSizes = getClosureSize(storePath); + closureSizes = getClosureSize(info->path); jsonPath.attr("closureSize", closureSizes.first); } if (includeImpureInfo) { - if (info->deriver != "") - jsonPath.attr("deriver", info->deriver); + if (info->deriver) + jsonPath.attr("deriver", printStorePath(*info->deriver)); if (info->registrationTime) jsonPath.attr("registrationTime", info->registrationTime); @@ -557,10 +504,10 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths } -std::pair Store::getClosureSize(const Path & storePath) +std::pair Store::getClosureSize(const StorePath & storePath) { uint64_t totalNarSize = 0, totalDownloadSize = 0; - PathSet closure; + StorePathSet closure; computeFSClosure(storePath, closure, false, false); for (auto & p : closure) { auto info = queryPathInfo(p); @@ -584,30 +531,34 @@ const Store::Stats & Store::getStats() } -void Store::buildPaths(const PathSet & paths, BuildMode buildMode) +void Store::buildPaths(const std::vector & paths, BuildMode buildMode) { - for (auto & path : paths) - if (isDerivation(path)) - unsupported("buildPaths"); + StorePathSet paths2; - if (queryValidPaths(paths).size() != paths.size()) + for (auto & path : paths) { + if (path.path.isDerivation()) + unsupported("buildPaths"); + paths2.insert(path.path.clone()); + } + + if (queryValidPaths(paths2).size() != paths2.size()) unsupported("buildPaths"); } void copyStorePath(ref srcStore, ref dstStore, - const Path & storePath, RepairFlag repair, CheckSigsFlag checkSigs) + const StorePath & storePath, RepairFlag repair, CheckSigsFlag checkSigs) { auto srcUri = srcStore->getUri(); auto dstUri = dstStore->getUri(); Activity act(*logger, lvlInfo, actCopyPath, srcUri == "local" || srcUri == "daemon" - ? fmt("copying path '%s' to '%s'", storePath, dstUri) + ? fmt("copying path '%s' to '%s'", srcStore->printStorePath(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), - {storePath, srcUri, dstUri}); + ? fmt("copying path '%s' from '%s'", srcStore->printStorePath(storePath), srcUri) + : fmt("copying path '%s' from '%s' to '%s'", srcStore->printStorePath(storePath), srcUri, dstUri), + {srcStore->printStorePath(storePath), srcUri, dstUri}); PushActivity pact(act.id); auto info = srcStore->queryPathInfo(storePath); @@ -640,23 +591,23 @@ void copyStorePath(ref srcStore, ref dstStore, total += len; act.progress(total, info->narSize); }); - srcStore->narFromPath({storePath}, wrapperSink); + srcStore->narFromPath(storePath, wrapperSink); }, [&]() { - throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", storePath, srcStore->getUri()); + throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", srcStore->printStorePath(storePath), srcStore->getUri()); }); dstStore->addToStore(*info, *source, repair, checkSigs); } -void copyPaths(ref srcStore, ref dstStore, const PathSet & storePaths, +void copyPaths(ref srcStore, ref dstStore, const StorePathSet & storePaths, RepairFlag repair, CheckSigsFlag checkSigs, SubstituteFlag substitute) { - PathSet valid = dstStore->queryValidPaths(storePaths, substitute); + auto valid = dstStore->queryValidPaths(storePaths, substitute); PathSet missing; for (auto & path : storePaths) - if (!valid.count(path)) missing.insert(path); + if (!valid.count(path)) missing.insert(srcStore->printStorePath(path)); if (missing.empty()) return; @@ -677,23 +628,25 @@ void copyPaths(ref srcStore, ref dstStore, const PathSet & storePa PathSet(missing.begin(), missing.end()), [&](const Path & storePath) { - if (dstStore->isValidPath(storePath)) { + if (dstStore->isValidPath(dstStore->parseStorePath(storePath))) { nrDone++; showProgress(); return PathSet(); } - auto info = srcStore->queryPathInfo(storePath); + auto info = srcStore->queryPathInfo(srcStore->parseStorePath(storePath)); bytesExpected += info->narSize; act.setExpected(actCopyPath, bytesExpected); - return info->references; + return srcStore->printStorePathSet(info->references); }, - [&](const Path & storePath) { + [&](const Path & storePathS) { checkInterrupt(); + auto storePath = dstStore->parseStorePath(storePathS); + if (!dstStore->isValidPath(storePath)) { MaintainCount mc(nrRunning); showProgress(); @@ -703,7 +656,7 @@ void copyPaths(ref srcStore, ref dstStore, const PathSet & storePa nrFailed++; if (!settings.keepGoing) throw e; - logger->log(lvlError, format("could not copy %s: %s") % storePath % e.what()); + logger->log(lvlError, fmt("could not copy %s: %s", storePathS, e.what())); showProgress(); return; } @@ -716,20 +669,36 @@ void copyPaths(ref srcStore, ref dstStore, const PathSet & storePa void copyClosure(ref srcStore, ref dstStore, - const PathSet & storePaths, RepairFlag repair, CheckSigsFlag checkSigs, + const StorePathSet & storePaths, RepairFlag repair, CheckSigsFlag checkSigs, SubstituteFlag substitute) { - PathSet closure; - srcStore->computeFSClosure({storePaths}, closure); + StorePathSet closure; + srcStore->computeFSClosure(storePaths, closure); copyPaths(srcStore, dstStore, closure, repair, checkSigs, substitute); } -ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven) +ValidPathInfo::ValidPathInfo(const ValidPathInfo & other) + : path(other.path.clone()) + , deriver(other.deriver ? other.deriver->clone(): std::optional{}) + , narHash(other.narHash) + , references(cloneStorePathSet(other.references)) + , registrationTime(other.registrationTime) + , narSize(other.narSize) + , id(other.id) + , ultimate(other.ultimate) + , sigs(other.sigs) + , ca(other.ca) { - ValidPathInfo info; - getline(str, info.path); - if (str.eof()) { info.path = ""; return info; } +} + + +std::optional decodeValidPathInfo(const Store & store, std::istream & str, bool hashGiven) +{ + std::string path; + getline(str, path); + if (str.eof()) { return {}; } + ValidPathInfo info(store.parseStorePath(path)); if (hashGiven) { string s; getline(str, s); @@ -737,16 +706,29 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven) getline(str, s); if (!string2Int(s, info.narSize)) throw Error("number expected"); } - getline(str, info.deriver); + std::string deriver; + getline(str, deriver); + if (deriver != "") info.deriver = store.parseStorePath(deriver); string s; int n; getline(str, s); if (!string2Int(s, n)) throw Error("number expected"); while (n--) { getline(str, s); - info.references.insert(s); + info.references.insert(store.parseStorePath(s)); } if (!str || str.eof()) throw Error("missing input"); - return info; + return std::optional(std::move(info)); +} + + +std::string Store::showPaths(const StorePathSet & paths) +{ + std::string s; + for (auto & i : paths) { + if (s.size() != 0) s += ", "; + s += "'" + printStorePath(i) + "'"; + } + return s; } @@ -761,34 +743,34 @@ string showPaths(const PathSet & paths) } -std::string ValidPathInfo::fingerprint() const +std::string ValidPathInfo::fingerprint(const Store & store) const { if (narSize == 0 || !narHash) - throw Error(format("cannot calculate fingerprint of path '%s' because its size/hash is not known") - % path); + throw Error("cannot calculate fingerprint of path '%s' because its size/hash is not known", + store.printStorePath(path)); return - "1;" + path + ";" + "1;" + store.printStorePath(path) + ";" + narHash.to_string(Base32) + ";" + std::to_string(narSize) + ";" - + concatStringsSep(",", references); + + concatStringsSep(",", store.printStorePathSet(references)); } -void ValidPathInfo::sign(const SecretKey & secretKey) +void ValidPathInfo::sign(const Store & store, const SecretKey & secretKey) { - sigs.insert(secretKey.signDetached(fingerprint())); + sigs.insert(secretKey.signDetached(fingerprint(store))); } bool ValidPathInfo::isContentAddressed(const Store & store) const { auto warn = [&]() { - printError(format("warning: path '%s' claims to be content-addressed but isn't") % path); + printError("warning: path '%s' claims to be content-addressed but isn't", store.printStorePath(path)); }; if (hasPrefix(ca, "text:")) { Hash hash(std::string(ca, 5)); - if (store.makeTextPath(storePathToName(path), hash, references) == path) + if (store.makeTextPath(path.name(), hash, references) == path) return true; else warn(); @@ -797,9 +779,13 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const else if (hasPrefix(ca, "fixed:")) { bool recursive = ca.compare(6, 2, "r:") == 0; Hash hash(std::string(ca, recursive ? 8 : 6)); - auto refs = references; - replaceInSet(refs, path, std::string("self")); - if (store.makeFixedOutputPath(recursive, hash, storePathToName(path), refs) == path) + auto refs = cloneStorePathSet(references); + bool hasSelfReference = false; + if (refs.count(path)) { + hasSelfReference = true; + refs.erase(path); + } + if (store.makeFixedOutputPath(recursive, hash, path.name(), refs, hasSelfReference) == path) return true; else warn(); @@ -815,15 +801,15 @@ size_t ValidPathInfo::checkSignatures(const Store & store, const PublicKeys & pu size_t good = 0; for (auto & sig : sigs) - if (checkSignature(publicKeys, sig)) + if (checkSignature(store, publicKeys, sig)) good++; return good; } -bool ValidPathInfo::checkSignature(const PublicKeys & publicKeys, const std::string & sig) const +bool ValidPathInfo::checkSignature(const Store & store, const PublicKeys & publicKeys, const std::string & sig) const { - return verifyDetached(fingerprint(), sig, publicKeys); + return verifyDetached(fingerprint(store), sig, publicKeys); } @@ -831,7 +817,7 @@ Strings ValidPathInfo::shortRefs() const { Strings refs; for (auto & r : references) - refs.push_back(baseNameOf(r)); + refs.push_back(std::string(r.to_string())); return refs; } @@ -944,7 +930,7 @@ static RegisterStoreImplementation regStore([]( const std::string & uri, const Store::Params & params) -> std::shared_ptr { - switch (getStoreType(uri, get(params, "state", settings.nixStateDir))) { + switch (getStoreType(uri, get(params, "state").value_or(settings.nixStateDir))) { case tDaemon: return std::shared_ptr(std::make_shared(params)); case tLocal: { diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 8e4b133d5..552bbd67d 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -1,5 +1,6 @@ #pragma once +#include "path.hh" #include "hash.hh" #include "serialise.hh" #include "crypto.hh" @@ -42,14 +43,11 @@ enum SubstituteFlag : bool { NoSubstitute = false, Substitute = true }; enum AllowInvalidFlag : bool { DisallowInvalid = false, AllowInvalid = true }; -/* Size of the hash part of store paths, in base-32 characters. */ -const size_t storePathHashLen = 32; // i.e. 160 bits - /* Magic header of exportPath() output (obsolete). */ const uint32_t exportMagic = 0x4558494e; -typedef std::unordered_map> Roots; +typedef std::unordered_map> Roots; struct GCOptions @@ -83,7 +81,7 @@ struct GCOptions bool ignoreLiveness{false}; /* For `gcDeleteSpecific', the paths to delete. */ - PathSet pathsToDelete; + StorePathSet pathsToDelete; /* Stop after at least `maxFreed' bytes have been freed. */ unsigned long long maxFreed{std::numeric_limits::max()}; @@ -104,21 +102,21 @@ struct GCResults struct SubstitutablePathInfo { - Path deriver; - PathSet references; + std::optional deriver; + StorePathSet references; unsigned long long downloadSize; /* 0 = unknown or inapplicable */ unsigned long long narSize; /* 0 = unknown */ }; -typedef std::map SubstitutablePathInfos; +typedef std::map SubstitutablePathInfos; struct ValidPathInfo { - Path path; - Path deriver; + StorePath path; + std::optional deriver; Hash narHash; - PathSet references; + StorePathSet references; time_t registrationTime = 0; uint64_t narSize = 0; // 0 = unknown uint64_t id; // internal use only @@ -143,7 +141,7 @@ struct ValidPathInfo Ideally, the content-addressability assertion would just be a Boolean, and the store path would be computed from - ‘storePathToName(path)’, ‘narHash’ and ‘references’. However, + the name component, ‘narHash’ and ‘references’. However, 1) we've accumulated several types of content-addressed paths over the years; and 2) fixed-output derivations support multiple hash algorithms and serialisation methods (flat file @@ -171,9 +169,9 @@ struct ValidPathInfo the NAR, and the sorted references. The size field is strictly speaking superfluous, but might prevent endless/excessive data attacks. */ - std::string fingerprint() const; + std::string fingerprint(const Store & store) const; - void sign(const SecretKey & secretKey); + void sign(const Store & store, const SecretKey & secretKey); /* Return true iff the path is verifiably content-addressed. */ bool isContentAddressed(const Store & store) const; @@ -186,10 +184,13 @@ struct ValidPathInfo size_t checkSignatures(const Store & store, const PublicKeys & publicKeys) const; /* Verify a single signature. */ - bool checkSignature(const PublicKeys & publicKeys, const std::string & sig) const; + bool checkSignature(const Store & store, const PublicKeys & publicKeys, const std::string & sig) const; Strings shortRefs() const; + ValidPathInfo(StorePath && path) : path(std::move(path)) { } + explicit ValidPathInfo(const ValidPathInfo & other); + virtual ~ValidPathInfo() { } }; @@ -240,6 +241,23 @@ struct BuildResult }; +struct StorePathWithOutputs +{ + StorePath path; + std::set outputs; + + StorePathWithOutputs(const StorePath & path, const std::set & outputs = {}) + : path(path.clone()), outputs(outputs) + { } + + StorePathWithOutputs(const StorePathWithOutputs & other) + : path(other.path.clone()), outputs(other.outputs) + { } + + std::string to_string(const Store & store) const; +}; + + class Store : public std::enable_shared_from_this, public Config { public: @@ -258,6 +276,7 @@ protected: struct State { + // FIXME: fix key LRUCache> pathInfoCache; }; @@ -273,6 +292,24 @@ public: virtual std::string getUri() = 0; + StorePath parseStorePath(std::string_view path) const; + + std::string printStorePath(const StorePath & path) const; + + // FIXME: remove + StorePathSet parseStorePathSet(const PathSet & paths) const; + + PathSet printStorePathSet(const StorePathSet & path) const; + + /* Split a string specifying a derivation and a set of outputs + (/nix/store/hash-foo!out1,out2,...) into the derivation path + and the outputs. */ + StorePathWithOutputs parseDrvPathWithOutputs(const string & s); + + /* Display a set of paths in human-readable form (i.e., between quotes + and separated by commas). */ + std::string showPaths(const StorePathSet & paths); + /* Return true if ‘path’ is in the Nix store (but not the Nix store itself). */ bool isInStore(const Path & path) const; @@ -281,9 +318,6 @@ public: the Nix store. */ bool isStorePath(const Path & path) const; - /* Throw an exception if ‘path’ is not a store path. */ - void assertStorePath(const Path & path) const; - /* Chop off the parts after the top-level store name, e.g., /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */ Path toStorePath(const Path & path) const; @@ -293,26 +327,27 @@ public: /* Same as followLinksToStore(), but apply toStorePath() to the result. */ - Path followLinksToStorePath(const Path & path) const; + StorePath followLinksToStorePath(const Path & path) const; /* Constructs a unique store path name. */ - Path makeStorePath(const string & type, - const Hash & hash, const string & name) const; + StorePath makeStorePath(const string & type, + const Hash & hash, std::string_view name) const; - Path makeOutputPath(const string & id, - const Hash & hash, const string & name) const; + StorePath makeOutputPath(const string & id, + const Hash & hash, std::string_view name) const; - Path makeFixedOutputPath(bool recursive, - const Hash & hash, const string & name, - const PathSet & references = {}) const; + StorePath makeFixedOutputPath(bool recursive, + const Hash & hash, std::string_view name, + const StorePathSet & references = {}, + bool hasSelfReference = false) const; - Path makeTextPath(const string & name, const Hash & hash, - const PathSet & references) const; + StorePath makeTextPath(std::string_view name, const Hash & hash, + const StorePathSet & references) const; /* This is the preparatory part of addToStore(); it computes the store path to which srcPath is to be copied. Returns the store path and the cryptographic hash of the contents of srcPath. */ - std::pair computeStorePathForPath(const string & name, + std::pair computeStorePathForPath(std::string_view name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter) const; @@ -330,21 +365,21 @@ public: simply yield a different store path, so other users wouldn't be affected), but it has some backwards compatibility issues (the hashing scheme changes), so I'm not doing that for now. */ - Path computeStorePathForText(const string & name, const string & s, - const PathSet & references) const; + StorePath computeStorePathForText(const string & name, const string & s, + const StorePathSet & references) const; /* Check whether a path is valid. */ - bool isValidPath(const Path & path); + bool isValidPath(const StorePath & path); protected: - virtual bool isValidPathUncached(const Path & path); + virtual bool isValidPathUncached(const StorePath & path); public: /* Query which of the given paths is valid. Optionally, try to substitute missing paths. */ - virtual PathSet queryValidPaths(const PathSet & paths, + virtual StorePathSet queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute = NoSubstitute); /* Query the set of all valid paths. Note that for some store @@ -352,54 +387,54 @@ public: (i.e. you'll get /nix/store/ rather than /nix/store/-). Use queryPathInfo() to obtain the full store path. */ - virtual PathSet queryAllValidPaths() + virtual StorePathSet queryAllValidPaths() { unsupported("queryAllValidPaths"); } /* Query information about a valid path. It is permitted to omit the name part of the store path. */ - ref queryPathInfo(const Path & path); + ref queryPathInfo(const StorePath & path); /* Asynchronous version of queryPathInfo(). */ - void queryPathInfo(const Path & path, + void queryPathInfo(const StorePath & path, Callback> callback) noexcept; protected: - virtual void queryPathInfoUncached(const Path & path, + virtual void queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept = 0; public: /* Queries the set of incoming FS references for a store path. The result is not cleared. */ - virtual void queryReferrers(const Path & path, PathSet & referrers) + virtual void queryReferrers(const StorePath & path, StorePathSet & referrers) { unsupported("queryReferrers"); } /* Return all currently valid derivations that have `path' as an output. (Note that the result of `queryDeriver()' is the derivation that was actually used to produce `path', which may not exist anymore.) */ - virtual PathSet queryValidDerivers(const Path & path) { return {}; }; + virtual StorePathSet queryValidDerivers(const StorePath & path) { return {}; }; /* Query the outputs of the derivation denoted by `path'. */ - virtual PathSet queryDerivationOutputs(const Path & path) + virtual StorePathSet queryDerivationOutputs(const StorePath & path) { unsupported("queryDerivationOutputs"); } /* Query the output names of the derivation denoted by `path'. */ - virtual StringSet queryDerivationOutputNames(const Path & path) + virtual StringSet queryDerivationOutputNames(const StorePath & path) { unsupported("queryDerivationOutputNames"); } /* Query the full store path given the hash part of a valid store - path, or "" if the path doesn't exist. */ - virtual Path queryPathFromHashPart(const string & hashPart) = 0; + path, or empty if the path doesn't exist. */ + virtual std::optional queryPathFromHashPart(const std::string & hashPart) = 0; /* Query which of the given paths have substitutes. */ - virtual PathSet querySubstitutablePaths(const PathSet & paths) { return {}; }; + virtual StorePathSet querySubstitutablePaths(const StorePathSet & paths) { return {}; }; /* Query substitute info (i.e. references, derivers and download sizes) of a set of paths. If a path does not have substitute info, it's omitted from the resulting ‘infos’ map. */ - virtual void querySubstitutablePathInfos(const PathSet & paths, + virtual void querySubstitutablePathInfos(const StorePathSet & paths, SubstitutablePathInfos & infos) { return; }; virtual bool wantMassQuery() { return false; } @@ -418,12 +453,12 @@ public: validity the resulting path. The resulting path is returned. The function object `filter' can be used to exclude files (see libutil/archive.hh). */ - virtual Path addToStore(const string & name, const Path & srcPath, + virtual StorePath addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair) = 0; // FIXME: remove? - virtual Path addToStoreFromDump(const string & dump, const string & name, + virtual StorePath addToStoreFromDump(const string & dump, const string & name, bool recursive = true, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair) { throw Error("addToStoreFromDump() is not supported by this store"); @@ -431,11 +466,11 @@ public: /* Like addToStore, but the contents written to the output path is a regular file containing the given string. */ - virtual Path addTextToStore(const string & name, const string & s, - const PathSet & references, RepairFlag repair = NoRepair) = 0; + virtual StorePath addTextToStore(const string & name, const string & s, + const StorePathSet & references, RepairFlag repair = NoRepair) = 0; /* Write a NAR dump of a store path. */ - virtual void narFromPath(const Path & path, Sink & sink) = 0; + virtual void narFromPath(const StorePath & path, Sink & sink) = 0; /* For each path, if it's a derivation, build it. Building a derivation means ensuring that the output paths are valid. If @@ -445,22 +480,24 @@ public: output paths can be created by running the builder, after recursively building any sub-derivations. For inputs that are not derivations, substitute them. */ - virtual void buildPaths(const PathSet & paths, BuildMode buildMode = bmNormal); + virtual void buildPaths( + const std::vector & paths, + BuildMode buildMode = bmNormal); /* Build a single non-materialized derivation (i.e. not from an on-disk .drv file). Note that ‘drvPath’ is only used for informational purposes. */ - virtual BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, + virtual BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode = bmNormal) = 0; /* Ensure that a path is valid. If it is not currently valid, it may be made valid by running a substitute (if defined for the path). */ - virtual void ensurePath(const Path & path) = 0; + virtual void ensurePath(const StorePath & path) = 0; /* Add a store path as a temporary root of the garbage collector. The root disappears as soon as we exit. */ - virtual void addTempRoot(const Path & path) + virtual void addTempRoot(const StorePath & path) { unsupported("addTempRoot"); } /* Add an indirect root, which is merely a symlink to `path' from @@ -506,7 +543,7 @@ public: /* 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'. */ - string makeValidityRegistration(const PathSet & paths, + string makeValidityRegistration(const StorePathSet & paths, bool showDerivers, bool showHash); /* Write a JSON representation of store path metadata, such as the @@ -514,14 +551,14 @@ public: variable elements such as the registration time are included. If ‘showClosureSize’ is true, the closure size of each path is included. */ - void pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths, + void pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & storePaths, bool includeImpureInfo, bool showClosureSize, AllowInvalidFlag allowInvalid = DisallowInvalid); /* Return the size of the closure of the specified path, that is, the sum of the size of the NAR serialisation of each path in the closure. */ - std::pair getClosureSize(const Path & storePath); + std::pair getClosureSize(const StorePath & storePath); /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ @@ -537,14 +574,14 @@ public: /* Add signatures to the specified store path. The signatures are not verified. */ - virtual void addSignatures(const Path & storePath, const StringSet & sigs) + virtual void addSignatures(const StorePath & storePath, const StringSet & sigs) { unsupported("addSignatures"); } /* Utility functions. */ /* Read a derivation, after ensuring its existence through ensurePath(). */ - Derivation derivationFromPath(const Path & drvPath); + Derivation derivationFromPath(const StorePath & drvPath); /* Place in `out' the set of all store paths in the file system closure of `storePath'; that is, all paths than can be directly @@ -553,36 +590,36 @@ public: `storePath' is returned; that is, the closures under the `referrers' relation instead of the `references' relation is returned. */ - virtual void computeFSClosure(const PathSet & paths, - PathSet & out, bool flipDirection = false, + virtual void computeFSClosure(const StorePathSet & paths, + StorePathSet & out, bool flipDirection = false, bool includeOutputs = false, bool includeDerivers = false); - void computeFSClosure(const Path & path, - PathSet & out, bool flipDirection = 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 PathSet & targets, - PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown, + virtual void queryMissing(const std::vector & targets, + StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, unsigned long long & downloadSize, unsigned long long & narSize); /* Sort a set of paths topologically under the references relation. If p refers to q, then p precedes q in this list. */ - Paths topoSortPaths(const PathSet & paths); + StorePaths topoSortPaths(const StorePathSet & paths); /* Export multiple paths in the format expected by ‘nix-store --import’. */ - void exportPaths(const Paths & paths, Sink & sink); + void exportPaths(const StorePathSet & paths, Sink & sink); - void exportPath(const Path & path, Sink & sink); + void exportPath(const StorePath & path, Sink & sink); /* Import a sequence of NAR dumps created by exportPaths() into the Nix store. Optionally, the contents of the NARs are preloaded into the specified FS accessor to speed up subsequent access. */ - Paths importPaths(Source & source, std::shared_ptr accessor, + StorePaths importPaths(Source & source, std::shared_ptr accessor, CheckSigsFlag checkSigs = CheckSigs); struct Stats @@ -606,7 +643,7 @@ public: /* Return the build log of the specified store path, if available, or null otherwise. */ - virtual std::shared_ptr getBuildLog(const Path & path) + virtual std::shared_ptr getBuildLog(const StorePath & path) { return nullptr; } /* Hack to allow long-running processes like hydra-queue-runner to @@ -672,11 +709,11 @@ public: LocalFSStore(const Params & params); - void narFromPath(const Path & path, Sink & sink) override; + void narFromPath(const StorePath & path, Sink & sink) override; ref getFSAccessor() override; /* Register a permanent GC root. */ - Path addPermRoot(const Path & storePath, + Path addPermRoot(const StorePath & storePath, const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false); virtual Path getRealStoreDir() { return storeDir; } @@ -687,25 +724,17 @@ public: return getRealStoreDir() + "/" + std::string(storePath, storeDir.size() + 1); } - std::shared_ptr getBuildLog(const Path & path) override; + std::shared_ptr getBuildLog(const StorePath & path) override; }; -/* Extract the name part of the given store path. */ -string storePathToName(const Path & path); - /* Extract the hash part of the given store path. */ string storePathToHash(const Path & path); -/* Check whether ‘name’ is a valid store path name part, i.e. contains - only the characters [a-zA-Z0-9\+\-\.\_\?\=] and doesn't start with - a dot. */ -void checkStoreName(const string & name); - /* Copy a path from one store to another. */ void copyStorePath(ref srcStore, ref dstStore, - const Path & storePath, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); + const StorePath & storePath, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); /* Copy store paths from one store to another. The paths may be copied @@ -713,7 +742,7 @@ void copyStorePath(ref srcStore, ref dstStore, (i.e. if A is a reference of B, then A is copied before B), but the set of store paths is not automatically closed; use copyClosure() for that. */ -void copyPaths(ref srcStore, ref dstStore, const PathSet & storePaths, +void copyPaths(ref srcStore, ref dstStore, const StorePathSet & storePaths, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, SubstituteFlag substitute = NoSubstitute); @@ -721,7 +750,7 @@ void copyPaths(ref srcStore, ref dstStore, const PathSet & storePa /* Copy the closure of the specified paths from one store to another. */ void copyClosure(ref srcStore, ref dstStore, - const PathSet & storePaths, + const StorePathSet & storePaths, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, SubstituteFlag substitute = NoSubstitute); @@ -804,7 +833,9 @@ struct RegisterStoreImplementation string showPaths(const PathSet & paths); -ValidPathInfo decodeValidPathInfo(std::istream & str, +std::optional decodeValidPathInfo( + const Store & store, + std::istream & str, bool hashGiven = false); diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 6762b609d..857d54d99 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -65,8 +65,9 @@ typedef enum { class Store; struct Source; -Path readStorePath(Store & store, Source & from); -template T readStorePaths(Store & store, Source & from); +template T readStorePaths(const Store & store, Source & from); + +void writeStorePaths(const Store & store, Sink & out, const StorePathSet & paths); } diff --git a/src/libutil/rust-ffi.cc b/src/libutil/rust-ffi.cc index 931d29542..accc5e22b 100644 --- a/src/libutil/rust-ffi.cc +++ b/src/libutil/rust-ffi.cc @@ -1,12 +1,18 @@ #include "logging.hh" #include "rust-ffi.hh" -namespace nix { - extern "C" std::exception_ptr * make_error(rust::StringSlice s) { // FIXME: leak - return new std::exception_ptr(std::make_exception_ptr(Error(std::string(s.ptr, s.size)))); + return new std::exception_ptr(std::make_exception_ptr(nix::Error(std::string(s.ptr, s.size)))); +} + +namespace rust { + +std::ostream & operator << (std::ostream & str, const String & s) +{ + str << (std::string_view) s; + return str; } } diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh index 663758bfc..a77f83ac5 100644 --- a/src/libutil/rust-ffi.hh +++ b/src/libutil/rust-ffi.hh @@ -1,16 +1,91 @@ +#pragma once + #include "serialise.hh" +#include +#include +#include + namespace rust { -// Depending on the internal representation of Rust slices is slightly -// evil... +typedef void (*DropFun)(void *); + +/* A Rust value of N bytes. It can be moved but not copied. When it + goes out of scope, the C++ destructor will run the drop + function. */ +template +struct Value +{ +protected: + + std::array raw; + + ~Value() + { + if (!isEvacuated()) { + drop(this); + evacuate(); + } + } + + // Must not be called directly. + Value() + { } + + Value(Value && other) + : raw(other.raw) + { + other.evacuate(); + } + + void operator =(Value && other) + { + if (!isEvacuated()) + drop(this); + raw = other.raw; + other.evacuate(); + } + +private: + + /* FIXME: optimize these (ideally in such a way that the compiler + can elide most calls to evacuate() / isEvacuated(). */ + inline void evacuate() + { + for (auto & i : raw) i = 0; + } + + inline bool isEvacuated() + { + for (auto & i : raw) + if (i != 0) return false; + return true; + } +}; + +/* A Rust vector. */ +template +struct Vec : Value<3 * sizeof(void *), drop> +{ + inline size_t size() const + { + return ((const size_t *) &this->raw)[2]; + } + + const T * data() const + { + return ((const T * *) &this->raw)[0]; + } +}; + +/* A Rust slice. */ template struct Slice { - T * ptr; + const T * ptr; size_t size; - Slice(T * ptr, size_t size) : ptr(ptr), size(size) + Slice(const T * ptr, size_t size) : ptr(ptr), size(size) { assert(ptr); } @@ -18,9 +93,44 @@ struct Slice struct StringSlice : Slice { - StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {} + StringSlice(const std::string & s): Slice(s.data(), s.size()) {} + explicit StringSlice(std::string_view s): Slice(s.data(), s.size()) {} + StringSlice(const char * s): Slice(s, strlen(s)) {} + + operator std::string_view() const + { + return std::string_view(ptr, size); + } }; +/* A Rust string. */ +struct String; + +extern "C" { + void ffi_String_new(StringSlice s, String * out); + void ffi_String_drop(void * s); +} + +struct String : Vec +{ + String(std::string_view s) + { + ffi_String_new(StringSlice(s), this); + } + + String(const char * s) + : String({s, std::strlen(s)}) + { + } + + operator std::string_view() const + { + return std::string_view(data(), size()); + } +}; + +std::ostream & operator << (std::ostream & str, const String & s); + struct Source { size_t (*fun)(void * source_this, rust::Slice data); @@ -33,7 +143,7 @@ struct Source // FIXME: how to propagate exceptions? static size_t sourceWrapper(void * _this, rust::Slice data) { - auto n = ((nix::Source *) _this)->read(data.ptr, data.size); + auto n = ((nix::Source *) _this)->read((unsigned char *) data.ptr, data.size); return n; } }; @@ -49,11 +159,20 @@ struct Result std::exception_ptr * exc; }; + ~Result() + { + if (tag == 0) + data.~T(); + else if (tag == 1) + // FIXME: don't leak exc + ; + } + /* Rethrow the wrapped exception or return the wrapped value. */ T unwrap() { if (tag == 0) - return data; + return std::move(data); else if (tag == 1) std::rethrow_exception(*exc); else diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc index 2cc7793fd..262bc655f 100644 --- a/src/libutil/tarfile.cc +++ b/src/libutil/tarfile.cc @@ -17,7 +17,7 @@ void unpackTarfile(Source & source, const Path & destDir) void unpackTarfile(const Path & tarFile, const Path & destDir, std::optional baseName) { - if (!baseName) baseName = baseNameOf(tarFile); + if (!baseName) baseName = std::string(baseNameOf(tarFile)); auto source = sinkToSource([&](Sink & sink) { // FIXME: look at first few bytes to determine compression type. diff --git a/src/libutil/util.cc b/src/libutil/util.cc index b4d444a67..e67bdcdeb 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -188,22 +188,22 @@ Path dirOf(const Path & path) } -string baseNameOf(const Path & path) +std::string_view baseNameOf(std::string_view path) { if (path.empty()) return ""; - Path::size_type last = path.length() - 1; + auto last = path.size() - 1; if (path[last] == '/' && last > 0) last -= 1; - Path::size_type pos = path.rfind('/', last); + auto pos = path.rfind('/', last); if (pos == string::npos) pos = 0; else pos += 1; - return string(path, pos, last - pos + 1); + return path.substr(pos, last - pos + 1); } @@ -1302,9 +1302,10 @@ bool hasPrefix(const string & s, const string & prefix) } -bool hasSuffix(const string & s, const string & suffix) +bool hasSuffix(std::string_view s, std::string_view suffix) { - return s.size() >= suffix.size() && string(s, s.size() - suffix.size()) == suffix; + return s.size() >= suffix.size() + && s.substr(s.size() - suffix.size()) == suffix; } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a1acb49b5..abd91b81c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -62,7 +62,7 @@ Path dirOf(const Path & path); /* Return the base name of the given canonical path, i.e., everything following the final `/'. */ -string baseNameOf(const Path & path); +std::string_view baseNameOf(std::string_view path); /* Check whether 'path' is a descendant of 'dir'. */ bool isInDir(const Path & path, const Path & dir); @@ -407,7 +407,7 @@ bool hasPrefix(const string & s, const string & prefix); /* Return true iff `s' ends in `suffix'. */ -bool hasSuffix(const string & s, const string & suffix); +bool hasSuffix(std::string_view s, std::string_view suffix); /* Convert a string to lower case. */ @@ -450,10 +450,10 @@ string base64Decode(const string & s); /* Get a value for the specified key from an associate container, or a default value if the key doesn't exist. */ template -string get(const T & map, const string & key, const string & def = "") +std::optional get(const T & map, const std::string & key) { auto i = map.find(key); - return i == map.end() ? def : i->second; + return i == map.end() ? std::optional() : i->second; } diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index c506f9b0a..73e3a347b 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -317,11 +317,11 @@ static void _main(int argc, char * * argv) state->printStats(); - auto buildPaths = [&](const PathSet & paths) { + auto buildPaths = [&](const std::vector & paths) { /* Note: we do this even when !printMissing to efficiently fetch binary cache data. */ unsigned long long downloadSize, narSize; - PathSet willBuild, willSubstitute, unknown; + StorePathSet willBuild, willSubstitute, unknown; store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); @@ -337,9 +337,9 @@ static void _main(int argc, char * * argv) throw UsageError("nix-shell requires a single derivation"); auto & drvInfo = drvs.front(); - auto drv = store->derivationFromPath(drvInfo.queryDrvPath()); + auto drv = store->derivationFromPath(store->parseStorePath(drvInfo.queryDrvPath())); - PathSet pathsToBuild; + std::vector pathsToBuild; /* Figure out what bash shell to use. If $NIX_BUILD_SHELL is not set, then build bashInteractive from @@ -358,7 +358,7 @@ static void _main(int argc, char * * argv) if (!drv) throw Error("the 'bashInteractive' attribute in did not evaluate to a derivation"); - pathsToBuild.insert(drv->queryDrvPath()); + pathsToBuild.emplace_back(store->parseStorePath(drv->queryDrvPath())); shell = drv->queryOutPath() + "/bin/bash"; @@ -370,10 +370,11 @@ static void _main(int argc, char * * argv) // Build or fetch all dependencies of the derivation. for (const auto & input : drv.inputDrvs) - if (std::all_of(envExclude.cbegin(), envExclude.cend(), [&](const string & exclude) { return !std::regex_search(input.first, std::regex(exclude)); })) - pathsToBuild.insert(makeDrvPathWithOutputs(input.first, input.second)); + if (std::all_of(envExclude.cbegin(), envExclude.cend(), + [&](const string & exclude) { return !std::regex_search(store->printStorePath(input.first), std::regex(exclude)); })) + pathsToBuild.emplace_back(input.first, input.second); for (const auto & src : drv.inputSrcs) - pathsToBuild.insert(src); + pathsToBuild.emplace_back(src); buildPaths(pathsToBuild); @@ -399,7 +400,7 @@ static void _main(int argc, char * * argv) env["NIX_STORE"] = store->storeDir; env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores); - auto passAsFile = tokenizeString(get(drv.env, "passAsFile", "")); + auto passAsFile = tokenizeString(get(drv.env, "passAsFile").value_or("")); bool keepTmp = false; int fileNr = 0; @@ -468,7 +469,7 @@ static void _main(int argc, char * * argv) else { - PathSet pathsToBuild; + std::vector pathsToBuild; std::map drvPrefixes; std::map resultSymlinks; @@ -482,7 +483,7 @@ static void _main(int argc, char * * argv) if (outputName == "") throw Error("derivation '%s' lacks an 'outputName' attribute", drvPath); - pathsToBuild.insert(drvPath + "!" + outputName); + pathsToBuild.emplace_back(store->parseStorePath(drvPath), StringSet{outputName}); std::string drvPrefix; auto i = drvPrefixes.find(drvPath); @@ -508,7 +509,7 @@ static void _main(int argc, char * * argv) for (auto & symlink : resultSymlinks) if (auto store2 = store.dynamic_pointer_cast()) - store2->addPermRoot(symlink.second, absPath(symlink.first), true); + store2->addPermRoot(store->parseStorePath(symlink.second), absPath(symlink.first), true); for (auto & path : outPaths) std::cout << path << '\n'; diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc index 70aa5c966..1b337a712 100755 --- a/src/nix-channel/nix-channel.cc +++ b/src/nix-channel/nix-channel.cc @@ -27,7 +27,7 @@ static void readChannels() continue; auto split = tokenizeString>(line, " "); auto url = std::regex_replace(split[0], std::regex("/*$"), ""); - auto name = split.size() > 1 ? split[1] : baseNameOf(url); + auto name = split.size() > 1 ? split[1] : std::string(baseNameOf(url)); channels[name] = url; } } @@ -98,10 +98,9 @@ static void update(const StringSet & channelNames) // shows something useful). auto cname = name; std::smatch match; - auto urlBase = baseNameOf(url); - if (std::regex_search(urlBase, match, std::regex("(-\\d.*)$"))) { + auto urlBase = std::string(baseNameOf(url)); + if (std::regex_search(urlBase, match, std::regex("(-\\d.*)$"))) cname = cname + (string) match[1]; - } std::string extraAttrs; diff --git a/src/nix-copy-closure/nix-copy-closure.cc b/src/nix-copy-closure/nix-copy-closure.cc index fdcde8b07..f87035760 100755 --- a/src/nix-copy-closure/nix-copy-closure.cc +++ b/src/nix-copy-closure/nix-copy-closure.cc @@ -52,11 +52,11 @@ static int _main(int argc, char ** argv) auto to = toMode ? openStore(remoteUri) : openStore(); auto from = toMode ? openStore() : openStore(remoteUri); - PathSet storePaths2; + StorePathSet storePaths2; for (auto & path : storePaths) storePaths2.insert(from->followLinksToStorePath(path)); - PathSet closure; + StorePathSet closure; from->computeFSClosure(storePaths2, closure, false, includeOutputs); copyPaths(from, to, closure, NoRepair, NoCheckSigs, useSubstitutes); diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 73d1d1127..134898561 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -286,7 +286,7 @@ static int _main(int argc, char * * argv) if (chdir(socketDir.c_str()) == -1) throw SysError(format("changing to socket directory '%1%'") % socketDir); - auto socketName = baseNameOf(socketPath); + auto socketName = std::string(baseNameOf(socketPath)); auto addr = sockaddr_un{}; addr.sun_family = AF_UNIX; if (socketName.size() + 1 >= sizeof(addr.sun_path)) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index a9c743955..a40d0c7e6 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -208,10 +208,11 @@ static long comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2) // at a time. static bool isPrebuilt(EvalState & state, DrvInfo & elem) { - Path path = elem.queryOutPath(); + auto path = state.store->parseStorePath(elem.queryOutPath()); if (state.store->isValidPath(path)) return true; - PathSet ps = state.store->querySubstitutablePaths({path}); - return ps.find(path) != ps.end(); + StorePathSet paths; + paths.insert(path.clone()); // FIXME: why doesn't StorePathSet{path.clone()} work? + return state.store->querySubstitutablePaths(paths).count(path); } @@ -371,24 +372,21 @@ static void queryInstSources(EvalState & state, case srcStorePaths: { for (auto & i : args) { - Path path = state.store->followLinksToStorePath(i); + auto path = state.store->followLinksToStorePath(i); - string name = baseNameOf(path); - string::size_type dash = name.find('-'); - if (dash != string::npos) - name = string(name, dash + 1); + std::string name(path.name()); DrvInfo elem(state, "", nullptr); elem.setName(name); - if (isDerivation(path)) { - elem.setDrvPath(path); - elem.setOutPath(state.store->derivationFromPath(path).findOutput("out")); + if (path.isDerivation()) { + elem.setDrvPath(state.store->printStorePath(path)); + elem.setOutPath(state.store->printStorePath(state.store->derivationFromPath(path).findOutput("out"))); if (name.size() >= drvExtension.size() && string(name, name.size() - drvExtension.size()) == drvExtension) name = string(name, 0, name.size() - drvExtension.size()); } - else elem.setOutPath(path); + else elem.setOutPath(state.store->printStorePath(path)); elems.push_back(elem); } @@ -421,13 +419,13 @@ static void queryInstSources(EvalState & state, static void printMissing(EvalState & state, DrvInfos & elems) { - PathSet targets; + std::vector targets; for (auto & i : elems) { Path drvPath = i.queryDrvPath(); if (drvPath != "") - targets.insert(drvPath); + targets.emplace_back(state.store->parseStorePath(drvPath)); else - targets.insert(i.queryOutPath()); + targets.emplace_back(state.store->parseStorePath(i.queryOutPath())); } printMissing(state.store, targets); @@ -697,15 +695,15 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs) drv.setName(globals.forceName); if (drv.queryDrvPath() != "") { - PathSet paths = {drv.queryDrvPath()}; + std::vector paths{globals.state->store->parseStorePath(drv.queryDrvPath())}; printMissing(globals.state->store, paths); if (globals.dryRun) return; globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal); - } - else { - printMissing(globals.state->store, {drv.queryOutPath()}); + } else { + printMissing(globals.state->store, + {globals.state->store->parseStorePath(drv.queryOutPath())}); if (globals.dryRun) return; - globals.state->store->ensurePath(drv.queryOutPath()); + globals.state->store->ensurePath(globals.state->store->parseStorePath(drv.queryOutPath())); } debug(format("switching to new user environment")); @@ -729,7 +727,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors, for (auto & j : selectors) /* !!! the repeated calls to followLinksToStorePath() are expensive, should pre-compute them. */ - if ((isPath(j) && i.queryOutPath() == globals.state->store->followLinksToStorePath(j)) + if ((isPath(j) && globals.state->store->parseStorePath(i.queryOutPath()) == globals.state->store->followLinksToStorePath(j)) || DrvName(j).matches(drvName)) { printInfo("uninstalling '%s'", i.queryName()); @@ -953,12 +951,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) /* Query which paths have substitutes. */ - PathSet validPaths, substitutablePaths; + StorePathSet validPaths; + StorePathSet substitutablePaths; if (printStatus || globals.prebuiltOnly) { - PathSet paths; + StorePathSet paths; for (auto & i : elems) try { - paths.insert(i.queryOutPath()); + paths.insert(globals.state->store->parseStorePath(i.queryOutPath())); } catch (AssertionError & e) { printMsg(lvlTalkative, "skipping derivation named '%s' which gives an assertion failure", i.queryName()); i.setFailed(); @@ -989,8 +988,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) //Activity act(*logger, lvlDebug, format("outputting query result '%1%'") % i.attrPath); if (globals.prebuiltOnly && - validPaths.find(i.queryOutPath()) == validPaths.end() && - substitutablePaths.find(i.queryOutPath()) == substitutablePaths.end()) + !validPaths.count(globals.state->store->parseStorePath(i.queryOutPath())) && + !substitutablePaths.count(globals.state->store->parseStorePath(i.queryOutPath()))) continue; /* For table output. */ @@ -1001,9 +1000,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) if (printStatus) { Path outPath = i.queryOutPath(); - bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end(); + bool hasSubs = substitutablePaths.count(globals.state->store->parseStorePath(outPath)); bool isInstalled = installed.find(outPath) != installed.end(); - bool isValid = validPaths.find(outPath) != validPaths.end(); + bool isValid = validPaths.count(globals.state->store->parseStorePath(outPath)); if (xmlOutput) { attrs["installed"] = isInstalled ? "1" : "0"; attrs["valid"] = isValid ? "1" : "0"; @@ -1347,7 +1346,7 @@ static int _main(int argc, char * * argv) using LegacyArgs::LegacyArgs; }; - MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { + MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) { Operation oldOp = op; if (*arg == "--help") diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 7b9a88281..8e4ecda4e 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -32,16 +32,16 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, { /* Build the components in the user environment, if they don't exist already. */ - PathSet drvsToBuild; + std::vector drvsToBuild; for (auto & i : elems) if (i.queryDrvPath() != "") - drvsToBuild.insert(i.queryDrvPath()); + drvsToBuild.push_back({state.store->parseStorePath(i.queryDrvPath())}); debug(format("building user environment dependencies")); state.store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal); /* Construct the whole top level derivation. */ - PathSet references; + StorePathSet references; Value manifest; state.mkList(manifest, elems.size()); unsigned int n = 0; @@ -77,10 +77,10 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, /* This is only necessary when installing store paths, e.g., `nix-env -i /nix/store/abcd...-foo'. */ - state.store->addTempRoot(j.second); - state.store->ensurePath(j.second); + state.store->addTempRoot(state.store->parseStorePath(j.second)); + state.store->ensurePath(state.store->parseStorePath(j.second)); - references.insert(j.second); + references.insert(state.store->parseStorePath(j.second)); } // Copy the meta attributes. @@ -95,14 +95,14 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, vMeta.attrs->sort(); v.attrs->sort(); - if (drvPath != "") references.insert(drvPath); + if (drvPath != "") references.insert(state.store->parseStorePath(drvPath)); } /* Also write a copy of the list of user environment elements to the store; we need it for future modifications of the environment. */ - Path manifestFile = state.store->addTextToStore("env-manifest.nix", - (format("%1%") % manifest).str(), references); + auto manifestFile = state.store->addTextToStore("env-manifest.nix", + fmt("%s", manifest), references); /* Get the environment builder expression. */ Value envBuilder; @@ -113,7 +113,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, Value args, topLevel; state.mkAttrs(args, 3); mkString(*state.allocAttr(args, state.symbols.create("manifest")), - manifestFile, {manifestFile}); + state.store->printStorePath(manifestFile), {state.store->printStorePath(manifestFile)}); args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest)); args.attrs->sort(); mkApp(topLevel, envBuilder, args); @@ -123,13 +123,15 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, state.forceValue(topLevel); PathSet context; Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath)); - Path topLevelDrv = state.coerceToPath(aDrvPath.pos ? *(aDrvPath.pos) : noPos, *(aDrvPath.value), context); + auto topLevelDrv = state.store->parseStorePath(state.coerceToPath(aDrvPath.pos ? *(aDrvPath.pos) : noPos, *(aDrvPath.value), context)); Attr & aOutPath(*topLevel.attrs->find(state.sOutPath)); Path topLevelOut = state.coerceToPath(aOutPath.pos ? *(aOutPath.pos) : noPos, *(aOutPath.value), context); /* Realise the resulting store expression. */ debug("building user environment"); - state.store->buildPaths({topLevelDrv}, state.repair ? bmRepair : bmNormal); + std::vector topLevelDrvs; + topLevelDrvs.push_back(StorePathWithOutputs{topLevelDrv.clone()}); + state.store->buildPaths(topLevelDrvs, state.repair ? bmRepair : bmNormal); /* Switch the current user environment to the output path. */ auto store2 = state.store.dynamic_pointer_cast(); diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index a736caa8f..5a886d69d 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -75,9 +75,9 @@ void processExpr(EvalState & state, const Strings & attrPaths, if (++rootNr > 1) rootName += "-" + std::to_string(rootNr); auto store2 = state.store.dynamic_pointer_cast(); if (store2) - drvPath = store2->addPermRoot(drvPath, rootName, indirectRoot); + drvPath = store2->addPermRoot(store2->parseStorePath(drvPath), rootName, indirectRoot); } - std::cout << format("%1%%2%\n") % drvPath % (outputName != "out" ? "!" + outputName : ""); + std::cout << fmt("%s%s\n", drvPath, (outputName != "out" ? "!" + outputName : "")); } } } @@ -105,7 +105,7 @@ static int _main(int argc, char * * argv) using LegacyArgs::LegacyArgs; }; - MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { + MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-instantiate"); else if (*arg == "--version") diff --git a/src/nix-prefetch-url/nix-prefetch-url.cc b/src/nix-prefetch-url/nix-prefetch-url.cc index 78c883833..5040b6fb8 100644 --- a/src/nix-prefetch-url/nix-prefetch-url.cc +++ b/src/nix-prefetch-url/nix-prefetch-url.cc @@ -64,7 +64,7 @@ static int _main(int argc, char * * argv) using LegacyArgs::LegacyArgs; }; - MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { + MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-prefetch-url"); else if (*arg == "--version") @@ -156,17 +156,17 @@ static int _main(int argc, char * * argv) /* If an expected hash is given, the file may already exist in the store. */ Hash hash, expectedHash(ht); - Path storePath; + std::optional storePath; if (args.size() == 2) { expectedHash = Hash(args[1], ht); storePath = store->makeFixedOutputPath(unpack, expectedHash, name); - if (store->isValidPath(storePath)) + if (store->isValidPath(*storePath)) hash = expectedHash; else - storePath.clear(); + storePath.reset(); } - if (storePath.empty()) { + if (!storePath) { auto actualUri = resolveMirrorUri(*state, uri); @@ -193,7 +193,7 @@ static int _main(int argc, char * * argv) if (hasSuffix(baseNameOf(uri), ".zip")) runProgram("unzip", true, {"-qq", tmpFile, "-d", unpacked}); else - unpackTarfile(tmpFile, unpacked, baseNameOf(uri)); + unpackTarfile(tmpFile, unpacked, std::string(baseNameOf(uri))); /* If the archive unpacks to a single file/directory, then use that as the top-level. */ @@ -217,17 +217,17 @@ static int _main(int argc, char * * argv) into the Nix store. */ storePath = store->addToStore(name, tmpFile, unpack, ht); - assert(storePath == store->makeFixedOutputPath(unpack, hash, name)); + assert(*storePath == store->makeFixedOutputPath(unpack, hash, name)); } stopProgressBar(); if (!printPath) - printInfo(format("path is '%1%'") % storePath); + printInfo("path is '%s'", store->printStorePath(*storePath)); std::cout << printHash16or32(hash) << std::endl; if (printPath) - std::cout << storePath << std::endl; + std::cout << store->printStorePath(*storePath) << std::endl; return 0; } diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index d448654fe..a9d0dbbed 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -10,9 +10,9 @@ using std::cout; namespace nix { -static string dotQuote(const string & s) +static string dotQuote(std::string_view s) { - return "\"" + s + "\""; + return "\"" + std::string(s) + "\""; } @@ -34,7 +34,7 @@ static string makeEdge(const string & src, const string & dst) } -static string makeNode(const string & id, const string & label, +static string makeNode(const string & id, std::string_view label, const string & colour) { format f = format("%1% [label = %2%, shape = box, " @@ -44,13 +44,6 @@ static string makeNode(const string & id, const string & label, } -static string symbolicName(const string & path) -{ - string p = baseNameOf(path); - return string(p, p.find('-') + 1); -} - - #if 0 string pathLabel(const Path & nePath, const string & elemPath) { @@ -91,25 +84,24 @@ void printClosure(const Path & nePath, const StoreExpr & fs) #endif -void printDotGraph(ref store, const PathSet & roots) +void printDotGraph(ref store, StorePathSet && roots) { - PathSet workList(roots); - PathSet doneSet; + StorePathSet workList(std::move(roots)); + StorePathSet doneSet; cout << "digraph G {\n"; while (!workList.empty()) { - Path path = *(workList.begin()); - workList.erase(path); + auto path = std::move(workList.extract(workList.begin()).value()); - if (!doneSet.insert(path).second) continue; + if (!doneSet.insert(path.clone()).second) continue; - cout << makeNode(path, symbolicName(path), "#ff0000"); + cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000"); for (auto & p : store->queryPathInfo(path)->references) { if (p != path) { - workList.insert(p); - cout << makeEdge(p, path); + workList.insert(p.clone()); + cout << makeEdge(std::string(p.to_string()), std::string(p.to_string())); } } diff --git a/src/nix-store/dotgraph.hh b/src/nix-store/dotgraph.hh index e2b5fc72f..73b8d06b9 100644 --- a/src/nix-store/dotgraph.hh +++ b/src/nix-store/dotgraph.hh @@ -1,11 +1,9 @@ #pragma once -#include "types.hh" +#include "store-api.hh" namespace nix { -class Store; - -void printDotGraph(ref store, const PathSet & roots); +void printDotGraph(ref store, StorePathSet && roots); } diff --git a/src/nix-store/graphml.cc b/src/nix-store/graphml.cc index 670fbe227..347708851 100644 --- a/src/nix-store/graphml.cc +++ b/src/nix-store/graphml.cc @@ -11,7 +11,7 @@ using std::cout; namespace nix { -static inline const string & xmlQuote(const string & s) +static inline std::string_view xmlQuote(std::string_view s) { // Luckily, store paths shouldn't contain any character that needs to be // quoted. @@ -19,14 +19,13 @@ static inline const string & xmlQuote(const string & s) } -static string symbolicName(const string & path) +static string symbolicName(const std::string & p) { - string p = baseNameOf(path); return string(p, p.find('-') + 1); } -static string makeEdge(const string & src, const string & dst) +static string makeEdge(std::string_view src, std::string_view dst) { return fmt(" \n", xmlQuote(src), xmlQuote(dst)); @@ -41,18 +40,18 @@ static string makeNode(const ValidPathInfo & info) " %3%\n" " %4%\n" " \n", - info.path, + info.path.to_string(), info.narSize, - symbolicName(info.path), - (isDerivation(info.path) ? "derivation" : "output-path")); + symbolicName(std::string(info.path.name())), + (info.path.isDerivation() ? "derivation" : "output-path")); } -void printGraphML(ref store, const PathSet & roots) +void printGraphML(ref store, StorePathSet && roots) { - PathSet workList(roots); - PathSet doneSet; - std::pair ret; + StorePathSet workList(std::move(roots)); + StorePathSet doneSet; + std::pair ret; cout << "\n" << " store, const PathSet & roots) << "\n"; while (!workList.empty()) { - Path path = *(workList.begin()); - workList.erase(path); + auto path = std::move(workList.extract(workList.begin()).value()); - ret = doneSet.insert(path); + ret = doneSet.insert(path.clone()); if (ret.second == false) continue; - ValidPathInfo info = *(store->queryPathInfo(path)); - cout << makeNode(info); + auto info = store->queryPathInfo(path); + cout << makeNode(*info); - for (auto & p : store->queryPathInfo(path)->references) { + for (auto & p : info->references) { if (p != path) { - workList.insert(p); - cout << makeEdge(path, p); + workList.insert(p.clone()); + cout << makeEdge(path.to_string(), p.to_string()); } } diff --git a/src/nix-store/graphml.hh b/src/nix-store/graphml.hh index b78df1e49..78be8a367 100644 --- a/src/nix-store/graphml.hh +++ b/src/nix-store/graphml.hh @@ -1,11 +1,9 @@ #pragma once -#include "types.hh" +#include "store-api.hh" namespace nix { -class Store; - -void printGraphML(ref store, const PathSet & roots); +void printGraphML(ref store, StorePathSet && roots); } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index dfa473db5..e2e2939f4 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -47,38 +47,37 @@ ref ensureLocalStore() } -static Path useDeriver(Path path) +static StorePath useDeriver(const StorePath & path) { - if (isDerivation(path)) return path; - Path drvPath = store->queryPathInfo(path)->deriver; - if (drvPath == "") - throw Error(format("deriver of path '%1%' is not known") % path); - return drvPath; + if (path.isDerivation()) return path.clone(); + auto info = store->queryPathInfo(path); + if (!info->deriver) + throw Error("deriver of path '%s' is not known", store->printStorePath(path)); + return info->deriver->clone(); } /* Realise the given path. For a derivation that means build it; for other paths it means ensure their validity. */ -static PathSet realisePath(Path path, bool build = true) +static PathSet realisePath(StorePathWithOutputs path, bool build = true) { - DrvPathWithOutputs p = parseDrvPathWithOutputs(path); - auto store2 = std::dynamic_pointer_cast(store); - if (isDerivation(p.first)) { + if (path.path.isDerivation()) { if (build) store->buildPaths({path}); - Derivation drv = store->derivationFromPath(p.first); + Derivation drv = store->derivationFromPath(path.path); rootNr++; - if (p.second.empty()) - for (auto & i : drv.outputs) p.second.insert(i.first); + if (path.outputs.empty()) + for (auto & i : drv.outputs) path.outputs.insert(i.first); PathSet outputs; - for (auto & j : p.second) { + for (auto & j : path.outputs) { DerivationOutputs::iterator i = drv.outputs.find(j); if (i == drv.outputs.end()) - throw Error(format("derivation '%1%' does not have an output named '%2%'") % p.first % j); - Path outPath = i->second.path; + throw Error("derivation '%s' does not have an output named '%s'", + store2->printStorePath(path.path), j); + auto outPath = store2->printStorePath(i->second.path); if (store2) { if (gcRoot == "") printGCWarning(); @@ -86,7 +85,7 @@ static PathSet realisePath(Path path, bool build = true) Path rootName = gcRoot; if (rootNr > 1) rootName += "-" + std::to_string(rootNr); if (i->first != "out") rootName += "-" + i->first; - outPath = store2->addPermRoot(outPath, rootName, indirectRoot); + outPath = store2->addPermRoot(store->parseStorePath(outPath), rootName, indirectRoot); } } outputs.insert(outPath); @@ -95,8 +94,9 @@ static PathSet realisePath(Path path, bool build = true) } else { - if (build) store->ensurePath(path); - else if (!store->isValidPath(path)) throw Error(format("path '%1%' does not exist and cannot be created") % 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) { if (gcRoot == "") printGCWarning(); @@ -104,10 +104,10 @@ static PathSet realisePath(Path path, bool build = true) Path rootName = gcRoot; rootNr++; if (rootNr > 1) rootName += "-" + std::to_string(rootNr); - path = store2->addPermRoot(path, rootName, indirectRoot); + return {store2->addPermRoot(path.path, rootName, indirectRoot)}; } } - return {path}; + return {store->printStorePath(path.path)}; } } @@ -126,23 +126,20 @@ static void opRealise(Strings opFlags, Strings opArgs) else if (i == "--ignore-unknown") ignoreUnknown = true; else throw UsageError(format("unknown flag '%1%'") % i); - Paths paths; - for (auto & i : opArgs) { - DrvPathWithOutputs p = parseDrvPathWithOutputs(i); - paths.push_back(makeDrvPathWithOutputs(store->followLinksToStorePath(p.first), p.second)); - } + std::vector paths; + for (auto & i : opArgs) + paths.push_back(store->parseDrvPathWithOutputs(i)); unsigned long long downloadSize, narSize; - PathSet willBuild, willSubstitute, unknown; - store->queryMissing(PathSet(paths.begin(), paths.end()), - willBuild, willSubstitute, unknown, downloadSize, narSize); + StorePathSet willBuild, willSubstitute, unknown; + store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); if (ignoreUnknown) { - Paths paths2; + std::vector paths2; for (auto & i : paths) - if (unknown.find(i) == unknown.end()) paths2.push_back(i); - paths = paths2; - unknown = PathSet(); + if (!unknown.count(i.path)) paths2.push_back(i); + paths = std::move(paths2); + unknown = StorePathSet(); } if (settings.printMissing) @@ -151,14 +148,14 @@ static void opRealise(Strings opFlags, Strings opArgs) if (dryRun) return; /* Build all paths at the same time to exploit parallelism. */ - store->buildPaths(PathSet(paths.begin(), paths.end()), buildMode); + store->buildPaths(paths, buildMode); if (!ignoreUnknown) for (auto & i : paths) { - PathSet paths = realisePath(i, false); + auto paths2 = realisePath(i, false); if (!noOutput) - for (auto & j : paths) - cout << format("%1%\n") % j; + for (auto & j : paths2) + cout << fmt("%1%\n", j); } } @@ -169,7 +166,7 @@ static void opAdd(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); for (auto & i : opArgs) - cout << format("%1%\n") % store->addToStore(baseNameOf(i), i); + cout << fmt("%s\n", store->printStorePath(store->addToStore(std::string(baseNameOf(i)), i))); } @@ -190,7 +187,7 @@ static void opAddFixed(Strings opFlags, Strings opArgs) opArgs.pop_front(); for (auto & i : opArgs) - cout << format("%1%\n") % store->addToStore(baseNameOf(i), i, recursive, hashAlgo); + cout << fmt("%s\n", store->printStorePath(store->addToStore(std::string(baseNameOf(i)), i, recursive, hashAlgo))); } @@ -211,22 +208,21 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs) string hash = *i++; string name = *i++; - cout << format("%1%\n") % - store->makeFixedOutputPath(recursive, Hash(hash, hashAlgo), name); + cout << fmt("%s\n", store->printStorePath(store->makeFixedOutputPath(recursive, Hash(hash, hashAlgo), name))); } -static PathSet maybeUseOutputs(const Path & storePath, bool useOutput, bool forceRealise) +static StorePathSet maybeUseOutputs(const StorePath & storePath, bool useOutput, bool forceRealise) { if (forceRealise) realisePath(storePath); - if (useOutput && isDerivation(storePath)) { - Derivation drv = store->derivationFromPath(storePath); - PathSet outputs; + if (useOutput && storePath.isDerivation()) { + auto drv = store->derivationFromPath(storePath); + StorePathSet outputs; for (auto & i : drv.outputs) - outputs.insert(i.second.path); + outputs.insert(i.second.path.clone()); return outputs; } - else return {storePath}; + else return singleton(storePath.clone()); } @@ -239,23 +235,23 @@ const string treeLine = "| "; const string treeNull = " "; -static void printTree(const Path & path, - const string & firstPad, const string & tailPad, PathSet & done) +static void printTree(const StorePath & path, + const string & firstPad, const string & tailPad, StorePathSet & done) { - if (!done.insert(path).second) { - cout << format("%1%%2% [...]\n") % firstPad % path; + if (!done.insert(path.clone()).second) { + cout << fmt("%s%s [...]\n", firstPad, store->printStorePath(path)); return; } - cout << format("%1%%2%\n") % firstPad % path; + cout << fmt("%s%s\n", firstPad, store->printStorePath(path)); - auto references = store->queryPathInfo(path)->references; + auto info = store->queryPathInfo(path); /* Topologically sort under the relation A < B iff A \in closure(B). That is, if derivation A is an (possibly indirect) input of B, then A is printed first. This has the effect of flattening the tree, preventing deeply nested structures. */ - Paths sorted = store->topoSortPaths(references); + auto sorted = store->topoSortPaths(info->references); reverse(sorted.begin(), sorted.end()); for (auto i = sorted.begin(); i != sorted.end(); ++i) { @@ -318,11 +314,11 @@ static void opQuery(Strings opFlags, Strings opArgs) case qOutputs: { for (auto & i : opArgs) { - i = store->followLinksToStorePath(i); - if (forceRealise) realisePath(i); - Derivation drv = store->derivationFromPath(i); + auto i2 = store->followLinksToStorePath(i); + if (forceRealise) realisePath(i2); + Derivation drv = store->derivationFromPath(i2); for (auto & j : drv.outputs) - cout << format("%1%\n") % j.second.path; + cout << fmt("%1%\n", store->printStorePath(j.second.path)); } break; } @@ -331,51 +327,54 @@ static void opQuery(Strings opFlags, Strings opArgs) case qReferences: case qReferrers: case qReferrersClosure: { - PathSet paths; + StorePathSet paths; for (auto & i : opArgs) { - PathSet ps = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); + 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); + paths.insert(p.clone()); + } + else if (query == qReferrers) { + StorePathSet tmp; + store->queryReferrers(j, tmp); + for (auto & i : tmp) + paths.insert(i.clone()); } - else if (query == qReferrers) store->queryReferrers(j, paths); else if (query == qReferrersClosure) store->computeFSClosure(j, paths, true); } } - Paths sorted = store->topoSortPaths(paths); - for (Paths::reverse_iterator i = sorted.rbegin(); + auto sorted = store->topoSortPaths(paths); + for (StorePaths::reverse_iterator i = sorted.rbegin(); i != sorted.rend(); ++i) - cout << format("%s\n") % *i; + cout << fmt("%s\n", store->printStorePath(*i)); break; } case qDeriver: for (auto & i : opArgs) { - Path deriver = store->queryPathInfo(store->followLinksToStorePath(i))->deriver; - cout << format("%1%\n") % - (deriver == "" ? "unknown-deriver" : deriver); + auto info = store->queryPathInfo(store->followLinksToStorePath(i)); + cout << fmt("%s\n", info->deriver ? store->printStorePath(*info->deriver) : "unknown-deriver"); } break; case qBinding: for (auto & i : opArgs) { - Path path = useDeriver(store->followLinksToStorePath(i)); + 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(format("derivation '%1%' has no environment binding named '%2%'") - % path % bindingName); - cout << format("%1%\n") % j->second; + 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) { - PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); - for (auto & j : paths) { + for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) { auto info = store->queryPathInfo(j); if (query == qHash) { assert(info->narHash.type == htSHA256); @@ -387,50 +386,51 @@ static void opQuery(Strings opFlags, Strings opArgs) break; case qTree: { - PathSet done; + StorePathSet done; for (auto & i : opArgs) printTree(store->followLinksToStorePath(i), "", "", done); break; } case qGraph: { - PathSet roots; - for (auto & i : opArgs) { - PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); - roots.insert(paths.begin(), paths.end()); - } - printDotGraph(ref(store), roots); + StorePathSet roots; + for (auto & i : opArgs) + for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) + roots.insert(j.clone()); + printDotGraph(ref(store), std::move(roots)); break; } case qGraphML: { - PathSet roots; - for (auto & i : opArgs) { - PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); - roots.insert(paths.begin(), paths.end()); - } - printGraphML(ref(store), roots); + StorePathSet roots; + for (auto & i : opArgs) + for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) + roots.insert(j.clone()); + printGraphML(ref(store), std::move(roots)); break; } case qResolve: { for (auto & i : opArgs) - cout << format("%1%\n") % store->followLinksToStorePath(i); + cout << fmt("%s\n", store->printStorePath(store->followLinksToStorePath(i))); break; } case qRoots: { - PathSet referrers; - for (auto & i : opArgs) { - store->computeFSClosure( - maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise), - referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations); - } + StorePathSet args; + for (auto & i : opArgs) + for (auto & p : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) + args.insert(p.clone()); + + StorePathSet referrers; + store->computeFSClosure( + args, referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations); + Roots roots = store->findRoots(false); for (auto & [target, links] : roots) if (referrers.find(target) != referrers.end()) for (auto & link : links) - cout << format("%1% -> %2%\n") % link % target; + cout << fmt("%1% -> %2%\n", link, store->printStorePath(target)); break; } @@ -446,7 +446,7 @@ static void opPrintEnv(Strings opFlags, Strings opArgs) if (opArgs.size() != 1) throw UsageError("'--print-env' requires one derivation store path"); Path drvPath = opArgs.front(); - Derivation drv = store->derivationFromPath(drvPath); + Derivation drv = store->derivationFromPath(store->parseStorePath(drvPath)); /* Print each environment variable in the derivation in a format that can be sourced by the shell. */ @@ -476,7 +476,7 @@ static void opReadLog(Strings opFlags, Strings opArgs) auto path = store->followLinksToStorePath(i); auto log = store->getBuildLog(path); if (!log) - throw Error("build log of derivation '%s' is not available", path); + throw Error("build log of derivation '%s' is not available", store->printStorePath(path)); std::cout << *log; } } @@ -487,13 +487,10 @@ static void opDumpDB(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); if (!opArgs.empty()) { for (auto & i : opArgs) - i = store->followLinksToStorePath(i); - for (auto & i : opArgs) - cout << store->makeValidityRegistration({i}, true, true); + cout << store->makeValidityRegistration(singleton(store->followLinksToStorePath(i)), true, true); } else { - PathSet validPaths = store->queryAllValidPaths(); - for (auto & i : validPaths) - cout << store->makeValidityRegistration({i}, true, true); + for (auto & i : store->queryAllValidPaths()) + cout << store->makeValidityRegistration(singleton(i), true, true); } } @@ -503,18 +500,18 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise) ValidPathInfos infos; while (1) { - ValidPathInfo info = decodeValidPathInfo(cin, hashGiven); - if (info.path == "") break; - if (!store->isValidPath(info.path) || reregister) { + auto info = decodeValidPathInfo(*store, cin, hashGiven); + if (!info) break; + if (!store->isValidPath(info->path) || reregister) { /* !!! races */ if (canonicalise) - canonicalisePathMetaData(info.path, -1); + canonicalisePathMetaData(store->printStorePath(info->path), -1); if (!hashGiven) { - HashResult hash = hashPath(htSHA256, info.path); - info.narHash = hash.first; - info.narSize = hash.second; + HashResult hash = hashPath(htSHA256, store->printStorePath(info->path)); + info->narHash = hash.first; + info->narSize = hash.second; } - infos.push_back(info); + infos.push_back(std::move(*info)); } } @@ -556,12 +553,12 @@ static void opCheckValidity(Strings opFlags, Strings opArgs) else throw UsageError(format("unknown flag '%1%'") % i); for (auto & i : opArgs) { - Path path = store->followLinksToStorePath(i); + auto path = store->followLinksToStorePath(i); if (!store->isValidPath(path)) { if (printInvalid) - cout << format("%1%\n") % path; + cout << fmt("%s\n", store->printStorePath(path)); else - throw Error(format("path '%1%' is not valid") % path); + throw Error("path '%s' is not valid", store->printStorePath(path)); } } } @@ -591,13 +588,13 @@ static void opGC(Strings opFlags, Strings opArgs) if (printRoots) { Roots roots = store->findRoots(false); - std::set> roots2; + std::set> roots2; // Transpose and sort the roots. for (auto & [target, links] : roots) for (auto & link : links) - roots2.emplace(link, target); + roots2.emplace(link, target.clone()); for (auto & [link, target] : roots2) - std::cout << link << " -> " << target << "\n"; + std::cout << link << " -> " << store->printStorePath(target) << "\n"; } else { @@ -661,11 +658,13 @@ static void opExport(Strings opFlags, Strings opArgs) for (auto & i : opFlags) throw UsageError(format("unknown flag '%1%'") % i); + StorePathSet paths; + for (auto & i : opArgs) - i = store->followLinksToStorePath(i); + paths.insert(store->followLinksToStorePath(i)); FdSink sink(STDOUT_FILENO); - store->exportPaths(opArgs, sink); + store->exportPaths(paths, sink); sink.flush(); } @@ -678,10 +677,10 @@ static void opImport(Strings opFlags, Strings opArgs) if (!opArgs.empty()) throw UsageError("no arguments expected"); FdSource source(STDIN_FILENO); - Paths paths = store->importPaths(source, nullptr, NoCheckSigs); + auto paths = store->importPaths(source, nullptr, NoCheckSigs); for (auto & i : paths) - cout << format("%1%\n") % i << std::flush; + cout << fmt("%s\n", store->printStorePath(i)) << std::flush; } @@ -726,16 +725,16 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) int status = 0; for (auto & i : opArgs) { - Path path = store->followLinksToStorePath(i); - printMsg(lvlTalkative, format("checking path '%1%'...") % path); + auto path = store->followLinksToStorePath(i); + printMsg(lvlTalkative, "checking path '%s'...", store->printStorePath(path)); auto info = store->queryPathInfo(path); HashSink sink(info->narHash.type); store->narFromPath(path, sink); auto current = sink.finish(); if (current.first != info->narHash) { printError( - format("path '%1%' was modified! expected hash '%2%', got '%3%'") - % path % info->narHash.to_string() % current.first.to_string()); + "path '%s' was modified! expected hash '%s', got '%s'", + store->printStorePath(path), info->narHash.to_string(), current.first.to_string()); status = 1; } } @@ -751,10 +750,8 @@ static void opRepairPath(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("no flags expected"); - for (auto & i : opArgs) { - Path path = store->followLinksToStorePath(i); - ensureLocalStore()->repairPath(path); - } + for (auto & i : opArgs) + ensureLocalStore()->repairPath(store->followLinksToStorePath(i)); } /* Optimise the disk space usage of the Nix store by hard-linking @@ -818,7 +815,7 @@ static void opServe(Strings opFlags, Strings opArgs) case cmdQueryValidPaths: { bool lock = readInt(in); bool substitute = readInt(in); - PathSet paths = readStorePaths(*store, in); + auto paths = readStorePaths(*store, in); if (lock && writeAllowed) for (auto & path : paths) store->addTempRoot(path); @@ -828,34 +825,39 @@ static void opServe(Strings opFlags, Strings opArgs) flag. */ if (substitute && writeAllowed) { /* Filter out .drv files (we don't want to build anything). */ - PathSet paths2; + std::vector paths2; for (auto & path : paths) - if (!isDerivation(path)) paths2.insert(path); + if (!path.isDerivation()) + paths2.emplace_back(path.clone()); unsigned long long downloadSize, narSize; - PathSet willBuild, willSubstitute, unknown; - store->queryMissing(PathSet(paths2.begin(), paths2.end()), + StorePathSet willBuild, willSubstitute, unknown; + store->queryMissing(paths2, willBuild, willSubstitute, unknown, downloadSize, narSize); /* FIXME: should use ensurePath(), but it only does one path at a time. */ if (!willSubstitute.empty()) try { - store->buildPaths(willSubstitute); + std::vector subs; + for (auto & p : willSubstitute) subs.emplace_back(p.clone()); + store->buildPaths(subs); } catch (Error & e) { printError(format("warning: %1%") % e.msg()); } } - out << store->queryValidPaths(paths); + writeStorePaths(*store, out, store->queryValidPaths(paths)); break; } case cmdQueryPathInfos: { - PathSet paths = readStorePaths(*store, in); + auto paths = readStorePaths(*store, in); // !!! Maybe we want a queryPathInfos? for (auto & i : paths) { try { auto info = store->queryPathInfo(i); - out << info->path << info->deriver << info->references; + out << store->printStorePath(info->path) + << (info->deriver ? store->printStorePath(*info->deriver) : ""); + writeStorePaths(*store, out, info->references); // !!! Maybe we want compression? out << info->narSize // downloadSize << info->narSize; @@ -869,7 +871,7 @@ static void opServe(Strings opFlags, Strings opArgs) } case cmdDumpStorePath: - store->narFromPath(readStorePath(*store, in), out); + store->narFromPath(store->parseStorePath(readString(in)), out); break; case cmdImportPaths: { @@ -881,14 +883,17 @@ static void opServe(Strings opFlags, Strings opArgs) case cmdExportPaths: { readInt(in); // obsolete - store->exportPaths(readStorePaths(*store, in), out); + store->exportPaths(readStorePaths(*store, in), out); break; } case cmdBuildPaths: { if (!writeAllowed) throw Error("building paths is not allowed"); - PathSet paths = readStorePaths(*store, in); + + std::vector paths; + for (auto & s : readStrings(in)) + paths.emplace_back(store->parseDrvPathWithOutputs(s)); getBuildSettings(); @@ -907,7 +912,7 @@ static void opServe(Strings opFlags, Strings opArgs) if (!writeAllowed) throw Error("building paths is not allowed"); - Path drvPath = readStorePath(*store, in); // informational only + auto drvPath = store->parseStorePath(readString(in)); // informational only BasicDerivation drv; readDerivation(in, *store, drv); @@ -926,30 +931,29 @@ static void opServe(Strings opFlags, Strings opArgs) case cmdQueryClosure: { bool includeOutputs = readInt(in); - PathSet closure; - store->computeFSClosure(readStorePaths(*store, in), + StorePathSet closure; + store->computeFSClosure(readStorePaths(*store, in), closure, false, includeOutputs); - out << closure; + writeStorePaths(*store, out, closure); break; } case cmdAddToStoreNar: { if (!writeAllowed) throw Error("importing paths is not allowed"); - ValidPathInfo info; - info.path = readStorePath(*store, in); - in >> info.deriver; - if (!info.deriver.empty()) - store->assertStorePath(info.deriver); + auto path = readString(in); + ValidPathInfo info(store->parseStorePath(path)); + auto deriver = readString(in); + if (deriver != "") + info.deriver = store->parseStorePath(deriver); info.narHash = Hash(readString(in), htSHA256); - info.references = readStorePaths(*store, in); + info.references = readStorePaths(*store, in); in >> info.registrationTime >> info.narSize >> info.ultimate; info.sigs = readStrings(in); in >> info.ca; - if (info.narSize == 0) { + if (info.narSize == 0) throw Error("narInfo is too old and missing the narSize field"); - } SizedSource sizedSource(in, info.narSize); diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc index 296b2c7e4..139db3657 100644 --- a/src/nix/add-to-store.cc +++ b/src/nix/add-to-store.cc @@ -40,16 +40,17 @@ struct CmdAddToStore : MixDryRun, StoreCommand StringSink sink; dumpPath(path, sink); - ValidPathInfo info; - info.narHash = hashString(htSHA256, *sink.s); + auto narHash = hashString(htSHA256, *sink.s); + + ValidPathInfo info(store->makeFixedOutputPath(true, narHash, *namePart)); + info.narHash = narHash; info.narSize = sink.s->size(); - info.path = store->makeFixedOutputPath(true, info.narHash, *namePart); info.ca = makeFixedOutputCA(true, info.narHash); if (!dryRun) store->addToStore(info, sink.s); - std::cout << fmt("%s\n", info.path); + std::cout << fmt("%s\n", store->printStorePath(info.path)); } }; diff --git a/src/nix/command.cc b/src/nix/command.cc index 9dbc3685a..442bc6c53 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -48,28 +48,29 @@ StorePathsCommand::StorePathsCommand(bool recursive) void StorePathsCommand::run(ref store) { - Paths storePaths; + StorePaths storePaths; if (all) { if (installables.size()) throw UsageError("'--all' does not expect arguments"); for (auto & p : store->queryAllValidPaths()) - storePaths.push_back(p); + storePaths.push_back(p.clone()); } else { for (auto & p : toStorePaths(store, realiseMode, installables)) - storePaths.push_back(p); + storePaths.push_back(p.clone()); if (recursive) { - PathSet closure; - store->computeFSClosure(PathSet(storePaths.begin(), storePaths.end()), - closure, false, false); - storePaths = Paths(closure.begin(), closure.end()); + StorePathSet closure; + store->computeFSClosure(storePathsToSet(storePaths), closure, false, false); + storePaths.clear(); + for (auto & p : closure) + storePaths.push_back(p.clone()); } } - run(store, storePaths); + run(store, std::move(storePaths)); } void StorePathCommand::run(ref store) diff --git a/src/nix/command.hh b/src/nix/command.hh index 7474c5eae..00eb46903 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -2,6 +2,7 @@ #include "args.hh" #include "common-eval-args.hh" +#include "path.hh" namespace nix { @@ -28,8 +29,8 @@ private: struct Buildable { - Path drvPath; // may be empty - std::map outputs; + std::optional drvPath; + std::map outputs; }; typedef std::vector Buildables; @@ -131,7 +132,7 @@ public: using StoreCommand::run; - virtual void run(ref store, Paths storePaths) = 0; + virtual void run(ref store, std::vector storePaths) = 0; void run(ref store) override; @@ -143,7 +144,7 @@ struct StorePathCommand : public InstallablesCommand { using StoreCommand::run; - virtual void run(ref store, const Path & storePath) = 0; + virtual void run(ref store, const StorePath & storePath) = 0; void run(ref store) override; }; @@ -174,13 +175,13 @@ std::shared_ptr parseInstallable( Buildables build(ref store, RealiseMode mode, std::vector> installables); -PathSet toStorePaths(ref store, RealiseMode mode, +std::set toStorePaths(ref store, RealiseMode mode, std::vector> installables); -Path toStorePath(ref store, RealiseMode mode, +StorePath toStorePath(ref store, RealiseMode mode, std::shared_ptr installable); -PathSet toDerivations(ref store, +std::set toDerivations(ref store, std::vector> installables, bool useDeriver = false); diff --git a/src/nix/copy.cc b/src/nix/copy.cc index b1aceb15c..85c777d38 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -80,14 +80,14 @@ struct CmdCopy : StorePathsCommand return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri); } - void run(ref srcStore, Paths storePaths) override + void run(ref srcStore, StorePaths storePaths) override { if (srcUri.empty() && dstUri.empty()) throw UsageError("you must pass '--from' and/or '--to'"); ref dstStore = dstUri.empty() ? openStore() : openStore(dstUri); - copyPaths(srcStore, dstStore, PathSet(storePaths.begin(), storePaths.end()), + copyPaths(srcStore, dstStore, storePathsToSet(storePaths), NoRepair, checkSigs, substitute); } }; diff --git a/src/nix/dump-path.cc b/src/nix/dump-path.cc index 90f1552d9..bb741b572 100644 --- a/src/nix/dump-path.cc +++ b/src/nix/dump-path.cc @@ -20,7 +20,7 @@ struct CmdDumpPath : StorePathCommand }; } - void run(ref store, const Path & storePath) override + void run(ref store, const StorePath & storePath) override { FdSink sink(STDOUT_FILENO); store->narFromPath(storePath, sink); diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 0e8bba39d..8ce6bd06e 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -89,15 +89,25 @@ Buildable Installable::toBuildable() struct InstallableStorePath : Installable { - Path storePath; + ref store; + StorePath storePath; - InstallableStorePath(const Path & storePath) : storePath(storePath) { } + InstallableStorePath(ref store, const Path & storePath) + : store(store), storePath(store->parseStorePath(storePath)) { } - std::string what() override { return storePath; } + std::string what() override { return store->printStorePath(storePath); } Buildables toBuildables() override { - return {{isDerivation(storePath) ? storePath : "", {{"out", storePath}}}}; + std::map outputs; + outputs.insert_or_assign("out", storePath.clone()); + Buildable b{ + .drvPath = storePath.isDerivation() ? storePath.clone() : std::optional(), + .outputs = std::move(outputs) + }; + Buildables bs; + bs.push_back(std::move(b)); + return bs; } }; @@ -120,17 +130,17 @@ struct InstallableValue : Installable Buildables res; - PathSet drvPaths; + StorePathSet drvPaths; for (auto & drv : drvs) { - Buildable b{drv.queryDrvPath()}; - drvPaths.insert(b.drvPath); + Buildable b{.drvPath = state->store->parseStorePath(drv.queryDrvPath())}; + drvPaths.insert(b.drvPath->clone()); auto outputName = drv.queryOutputName(); if (outputName == "") - throw Error("derivation '%s' lacks an 'outputName' attribute", b.drvPath); + throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(*b.drvPath)); - b.outputs.emplace(outputName, drv.queryOutPath()); + b.outputs.emplace(outputName, state->store->parseStorePath(drv.queryOutPath())); res.push_back(std::move(b)); } @@ -138,10 +148,13 @@ struct InstallableValue : Installable // Hack to recognize .all: if all drvs have the same drvPath, // merge the buildables. if (drvPaths.size() == 1) { - Buildable b{*drvPaths.begin()}; + Buildable b{.drvPath = drvPaths.begin()->clone()}; for (auto & b2 : res) - b.outputs.insert(b2.outputs.begin(), b2.outputs.end()); - return {b}; + for (auto & output : b2.outputs) + b.outputs.insert_or_assign(output.first, output.second.clone()); + Buildables bs; + bs.push_back(std::move(b)); + return bs; } else return res; } @@ -212,7 +225,7 @@ static std::vector> parseInstallables( auto path = store->toStorePath(store->followLinksToStore(s)); if (store->isStorePath(path)) - result.push_back(std::make_shared(path)); + result.push_back(std::make_shared(store, path)); } else if (s == "" || std::regex_match(s, attrPathRegex)) @@ -242,19 +255,18 @@ Buildables build(ref store, RealiseMode mode, Buildables buildables; - PathSet pathsToBuild; + std::vector pathsToBuild; for (auto & i : installables) { for (auto & b : i->toBuildables()) { - if (b.drvPath != "") { + if (b.drvPath) { StringSet outputNames; for (auto & output : b.outputs) outputNames.insert(output.first); - pathsToBuild.insert( - b.drvPath + "!" + concatStringsSep(",", outputNames)); + pathsToBuild.push_back({*b.drvPath, outputNames}); } else for (auto & output : b.outputs) - pathsToBuild.insert(output.second); + pathsToBuild.push_back({output.second.clone()}); buildables.push_back(std::move(b)); } } @@ -267,19 +279,19 @@ Buildables build(ref store, RealiseMode mode, return buildables; } -PathSet toStorePaths(ref store, RealiseMode mode, +StorePathSet toStorePaths(ref store, RealiseMode mode, std::vector> installables) { - PathSet outPaths; + StorePathSet outPaths; for (auto & b : build(store, mode, installables)) for (auto & output : b.outputs) - outPaths.insert(output.second); + outPaths.insert(output.second.clone()); return outPaths; } -Path toStorePath(ref store, RealiseMode mode, +StorePath toStorePath(ref store, RealiseMode mode, std::shared_ptr installable) { auto paths = toStorePaths(store, mode, {installable}); @@ -287,17 +299,17 @@ Path toStorePath(ref store, RealiseMode mode, if (paths.size() != 1) throw Error("argument '%s' should evaluate to one store path", installable->what()); - return *paths.begin(); + return paths.begin()->clone(); } -PathSet toDerivations(ref store, +StorePathSet toDerivations(ref store, std::vector> installables, bool useDeriver) { - PathSet drvPaths; + StorePathSet drvPaths; for (auto & i : installables) for (auto & b : i->toBuildables()) { - if (b.drvPath.empty()) { + if (!b.drvPath) { if (!useDeriver) throw Error("argument '%s' did not evaluate to a derivation", i->what()); for (auto & output : b.outputs) { @@ -305,10 +317,10 @@ PathSet toDerivations(ref store, if (derivers.empty()) throw Error("'%s' does not have a known deriver", i->what()); // FIXME: use all derivers? - drvPaths.insert(*derivers.begin()); + drvPaths.insert(derivers.begin()->clone()); } } else - drvPaths.insert(b.drvPath); + drvPaths.insert(b.drvPath->clone()); } return drvPaths; diff --git a/src/nix/local.mk b/src/nix/local.mk index c09efd1fc..a34cca9fd 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -15,7 +15,7 @@ nix_SOURCES := \ $(wildcard src/nix-prefetch-url/*.cc) \ $(wildcard src/nix-store/*.cc) \ -nix_LIBS = libexpr libmain libstore libutil +nix_LIBS = libexpr libmain libstore libutil libnixrust nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system diff --git a/src/nix/log.cc b/src/nix/log.cc index 122a3d690..795991cb7 100644 --- a/src/nix/log.cc +++ b/src/nix/log.cc @@ -43,7 +43,7 @@ struct CmdLog : InstallableCommand RunPager pager; for (auto & sub : subs) { - auto log = b.drvPath != "" ? sub->getBuildLog(b.drvPath) : nullptr; + auto log = b.drvPath ? sub->getBuildLog(*b.drvPath) : nullptr; for (auto & output : b.outputs) { if (log) break; log = sub->getBuildLog(output.second); diff --git a/src/nix/ls.cc b/src/nix/ls.cc index 9408cc9da..3ef1f2750 100644 --- a/src/nix/ls.cc +++ b/src/nix/ls.cc @@ -67,7 +67,7 @@ struct MixLs : virtual Args, MixJSON if (st.type == FSAccessor::Type::tMissing) throw Error(format("path '%1%' does not exist") % path); doPath(st, path, - st.type == FSAccessor::Type::tDirectory ? "." : baseNameOf(path), + st.type == FSAccessor::Type::tDirectory ? "." : std::string(baseNameOf(path)), showDirectory); } diff --git a/src/nix/main.cc b/src/nix/main.cc index 5454f4b34..41d44f431 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -135,7 +135,7 @@ void mainWrapped(int argc, char * * argv) initGC(); programPath = argv[0]; - string programName = baseNameOf(programPath); + auto programName = std::string(baseNameOf(programPath)); { auto legacy = (*RegisterLegacyCommand::commands)[programName]; diff --git a/src/nix/make-content-addressable.cc b/src/nix/make-content-addressable.cc index 5b99b5084..524d467c2 100644 --- a/src/nix/make-content-addressable.cc +++ b/src/nix/make-content-addressable.cc @@ -29,34 +29,36 @@ struct CmdMakeContentAddressable : StorePathsCommand }, }; } - void run(ref store, Paths storePaths) override + void run(ref store, StorePaths storePaths) override { - auto paths = store->topoSortPaths(PathSet(storePaths.begin(), storePaths.end())); + auto paths = store->topoSortPaths(storePathsToSet(storePaths)); - paths.reverse(); + std::reverse(paths.begin(), paths.end()); - std::map remappings; + std::map remappings; for (auto & path : paths) { + auto pathS = store->printStorePath(path); auto oldInfo = store->queryPathInfo(path); - auto oldHashPart = storePathToHash(path); - auto name = storePathToName(path); + auto oldHashPart = storePathToHash(pathS); StringSink sink; store->narFromPath(path, sink); StringMap rewrites; - ValidPathInfo info; + StorePathSet references; + bool hasSelfReference = false; for (auto & ref : oldInfo->references) { if (ref == path) - info.references.insert("self"); + hasSelfReference = true; else { - auto replacement = get(remappings, ref, ref); + auto i = remappings.find(ref); + auto replacement = i != remappings.end() ? i->second.clone() : ref.clone(); // FIXME: warn about unremapped paths? - info.references.insert(replacement); if (replacement != ref) - rewrites[storePathToHash(ref)] = storePathToHash(replacement); + rewrites.insert_or_assign(store->printStorePath(ref), store->printStorePath(replacement)); + references.insert(std::move(replacement)); } } @@ -65,24 +67,26 @@ struct CmdMakeContentAddressable : StorePathsCommand HashModuloSink hashModuloSink(htSHA256, oldHashPart); hashModuloSink((unsigned char *) sink.s->data(), sink.s->size()); - info.narHash = hashModuloSink.finish().first; + auto narHash = hashModuloSink.finish().first; + + ValidPathInfo info(store->makeFixedOutputPath(true, narHash, path.name(), references, hasSelfReference)); + info.references = std::move(references); + if (hasSelfReference) info.references.insert(info.path.clone()); + info.narHash = narHash; info.narSize = sink.s->size(); - replaceInSet(info.references, path, std::string("self")); - info.path = store->makeFixedOutputPath(true, info.narHash, name, info.references); - replaceInSet(info.references, std::string("self"), info.path); info.ca = makeFixedOutputCA(true, info.narHash); - printError("rewrote '%s' to '%s'", path, info.path); + printError("rewrote '%s' to '%s'", pathS, store->printStorePath(info.path)); auto source = sinkToSource([&](Sink & nextSink) { - RewritingSink rsink2(oldHashPart, storePathToHash(info.path), nextSink); + RewritingSink rsink2(oldHashPart, storePathToHash(store->printStorePath(info.path)), nextSink); rsink2((unsigned char *) sink.s->data(), sink.s->size()); rsink2.flush(); }); store->addToStore(info, *source); - remappings[path] = info.path; + remappings.insert_or_assign(std::move(path), std::move(info.path)); } } }; diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index 2cb718f12..bffa7b356 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -78,36 +78,36 @@ struct CmdPathInfo : StorePathsCommand, MixJSON std::cout << fmt("\t%6.1f%c", res, idents.at(power)); } - void run(ref store, Paths storePaths) override + void run(ref store, StorePaths storePaths) override { size_t pathLen = 0; for (auto & storePath : storePaths) - pathLen = std::max(pathLen, storePath.size()); + pathLen = std::max(pathLen, store->printStorePath(storePath).size()); if (json) { JSONPlaceholder jsonRoot(std::cout); store->pathInfoToJSON(jsonRoot, // FIXME: preserve order? - PathSet(storePaths.begin(), storePaths.end()), + storePathsToSet(storePaths), true, showClosureSize, AllowInvalid); } else { - for (auto storePath : storePaths) { + for (auto & storePath : storePaths) { auto info = store->queryPathInfo(storePath); - storePath = info->path; // FIXME: screws up padding + auto storePathS = store->printStorePath(storePath); - std::cout << storePath; + std::cout << storePathS; if (showSize || showClosureSize || showSigs) - std::cout << std::string(std::max(0, (int) pathLen - (int) storePath.size()), ' '); + std::cout << std::string(std::max(0, (int) pathLen - (int) storePathS.size()), ' '); if (showSize) printSize(info->narSize); if (showClosureSize) - printSize(store->getClosureSize(storePath).first); + printSize(store->getClosureSize(info->path).first); if (showSigs) { std::cout << '\t'; diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index 661966733..d20c09f26 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -24,6 +24,13 @@ static uint64_t getI(const std::vector & fields, size_t n) return fields[n].i; } +static std::string_view storePathToName(std::string_view path) +{ + auto base = baseNameOf(path); + auto i = base.find('-'); + return i == std::string::npos ? base.substr(0, 0) : base.substr(i + 1); +} + class ProgressBar : public Logger { private: @@ -148,7 +155,7 @@ public: if (type == actBuild) { auto name = storePathToName(getS(fields, 0)); if (hasSuffix(name, ".drv")) - name.resize(name.size() - 4); + name = name.substr(name.size() - 4); i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name); auto machineName = getS(fields, 1); if (machineName != "") @@ -173,7 +180,7 @@ public: if (type == actPostBuildHook) { auto name = storePathToName(getS(fields, 0)); if (hasSuffix(name, ".drv")) - name.resize(name.size() - 4); + name = name.substr(name.size() - 4); i->s = fmt("post-build " ANSI_BOLD "%s" ANSI_NORMAL, name); i->name = DrvName(name).name; } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index c2b65b6ea..e6c811a7b 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -413,7 +413,7 @@ Path NixRepl::getDerivationPath(Value & v) { if (!drvInfo) throw Error("expression does not evaluate to a derivation, so I can't build it"); Path drvPath = drvInfo->queryDrvPath(); - if (drvPath == "" || !state.store->isValidPath(drvPath)) + if (drvPath == "" || !state.store->isValidPath(state.store->parseStorePath(drvPath))) throw Error("expression did not evaluate to a valid derivation"); return drvPath; } @@ -521,10 +521,10 @@ bool NixRepl::processLine(string line) but doing it in a child makes it easier to recover from problems / SIGINT. */ if (runProgram(settings.nixBinDir + "/nix", Strings{"build", "--no-link", drvPath}) == 0) { - Derivation drv = readDerivation(drvPath); + auto drv = readDerivation(*state.store, drvPath); std::cout << std::endl << "this derivation produced the following outputs:" << std::endl; for (auto & i : drv.outputs) - std::cout << format(" %1% -> %2%") % i.first % i.second.path << std::endl; + std::cout << fmt(" %s -> %s\n", i.first, state.store->printStorePath(i.second.path)); } } else if (command == ":i") { runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPath}); diff --git a/src/nix/run.cc b/src/nix/run.cc index ece4d3854..f885c5e49 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -119,24 +119,24 @@ struct CmdRun : InstallablesCommand unsetenv(var.c_str()); } - std::unordered_set done; - std::queue todo; - for (auto & path : outPaths) todo.push(path); + std::unordered_set done; + std::queue todo; + for (auto & path : outPaths) todo.push(path.clone()); auto unixPath = tokenizeString(getEnv("PATH").value_or(""), ":"); while (!todo.empty()) { - Path path = todo.front(); + auto path = todo.front().clone(); todo.pop(); - if (!done.insert(path).second) continue; + if (!done.insert(path.clone()).second) continue; if (true) - unixPath.push_front(path + "/bin"); + unixPath.push_front(store->printStorePath(path) + "/bin"); - auto propPath = path + "/nix-support/propagated-user-env-packages"; + auto propPath = store->printStorePath(path) + "/nix-support/propagated-user-env-packages"; if (accessor->stat(propPath).type == FSAccessor::tRegular) { for (auto & p : tokenizeString(readFile(propPath))) - todo.push(p); + todo.push(store->parseStorePath(p)); } } diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc index 6065adc4d..0ede7b468 100644 --- a/src/nix/show-derivation.cc +++ b/src/nix/show-derivation.cc @@ -46,9 +46,9 @@ struct CmdShowDerivation : InstallablesCommand auto drvPaths = toDerivations(store, installables, true); if (recursive) { - PathSet closure; + StorePathSet closure; store->computeFSClosure(drvPaths, closure); - drvPaths = closure; + drvPaths = std::move(closure); } { @@ -56,17 +56,19 @@ struct CmdShowDerivation : InstallablesCommand JSONObject jsonRoot(std::cout, true); for (auto & drvPath : drvPaths) { - if (!isDerivation(drvPath)) continue; + if (!drvPath.isDerivation()) continue; - auto drvObj(jsonRoot.object(drvPath)); + auto drvPathS = store->printStorePath(drvPath); - auto drv = readDerivation(drvPath); + auto drvObj(jsonRoot.object(drvPathS)); + + auto drv = readDerivation(*store, drvPathS); { auto outputsObj(drvObj.object("outputs")); for (auto & output : drv.outputs) { auto outputObj(outputsObj.object(output.first)); - outputObj.attr("path", output.second.path); + outputObj.attr("path", store->printStorePath(output.second.path)); if (output.second.hash != "") { outputObj.attr("hashAlgo", output.second.hashAlgo); outputObj.attr("hash", output.second.hash); @@ -77,13 +79,13 @@ struct CmdShowDerivation : InstallablesCommand { auto inputsList(drvObj.list("inputSrcs")); for (auto & input : drv.inputSrcs) - inputsList.elem(input); + inputsList.elem(store->printStorePath(input)); } { auto inputDrvsObj(drvObj.object("inputDrvs")); for (auto & input : drv.inputDrvs) { - auto inputList(inputDrvsObj.list(input.first)); + auto inputList(inputDrvsObj.list(store->printStorePath(input.first))); for (auto & outputId : input.second) inputList.elem(outputId); } diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 23bc83ad0..5f07448e0 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -27,7 +27,7 @@ struct CmdCopySigs : StorePathsCommand return "copy path signatures from substituters (like binary caches)"; } - void run(ref store, Paths storePaths) override + void run(ref store, StorePaths storePaths) override { if (substituterUris.empty()) throw UsageError("you must specify at least one substituter using '-s'"); @@ -44,18 +44,20 @@ struct CmdCopySigs : StorePathsCommand //logger->setExpected(doneLabel, storePaths.size()); - auto doPath = [&](const Path & storePath) { + auto doPath = [&](const Path & storePathS) { //Activity act(*logger, lvlInfo, format("getting signatures for '%s'") % storePath); checkInterrupt(); + auto storePath = store->parseStorePath(storePathS); + auto info = store->queryPathInfo(storePath); StringSet newSigs; for (auto & store2 : substituters) { try { - auto info2 = store2->queryPathInfo(storePath); + auto info2 = store2->queryPathInfo(info->path); /* Don't import signatures that don't match this binary. */ @@ -80,11 +82,11 @@ struct CmdCopySigs : StorePathsCommand }; for (auto & storePath : storePaths) - pool.enqueue(std::bind(doPath, storePath)); + pool.enqueue(std::bind(doPath, store->printStorePath(storePath))); pool.process(); - printInfo(format("imported %d signatures") % added); + printInfo("imported %d signatures", added); } }; @@ -109,7 +111,7 @@ struct CmdSignPaths : StorePathsCommand return "sign the specified paths"; } - void run(ref store, Paths storePaths) override + void run(ref store, StorePaths storePaths) override { if (secretKeyFile.empty()) throw UsageError("you must specify a secret key file using '-k'"); @@ -123,7 +125,7 @@ struct CmdSignPaths : StorePathsCommand auto info2(*info); info2.sigs.clear(); - info2.sign(secretKey); + info2.sign(*store, secretKey); assert(!info2.sigs.empty()); if (!info->sigs.count(*info2.sigs.begin())) { @@ -132,7 +134,7 @@ struct CmdSignPaths : StorePathsCommand } } - printInfo(format("added %d signatures") % added); + printInfo("added %d signatures", added); } }; diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index e6c369a7c..87f1f9d1b 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -58,13 +58,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand printInfo("upgrading Nix in profile '%s'", profileDir); - Path storePath; - { - Activity act(*logger, lvlInfo, actUnknown, "querying latest Nix version"); - storePath = getLatestNix(store); - } + auto storePath = getLatestNix(store); - auto version = DrvName(storePathToName(storePath)).version; + auto version = DrvName(storePath.name()).version; if (dryRun) { stopProgressBar(); @@ -73,13 +69,13 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand } { - Activity act(*logger, lvlInfo, actUnknown, fmt("downloading '%s'...", storePath)); + Activity act(*logger, lvlInfo, actUnknown, fmt("downloading '%s'...", store->printStorePath(storePath))); store->ensurePath(storePath); } { - Activity act(*logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", storePath)); - auto program = storePath + "/bin/nix-env"; + 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) throw Error("could not verify that '%s' works", program); @@ -88,9 +84,10 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand stopProgressBar(); { - Activity act(*logger, lvlInfo, actUnknown, fmt("installing '%s' into profile '%s'...", storePath, profileDir)); + Activity act(*logger, lvlInfo, actUnknown, + fmt("installing '%s' into profile '%s'...", store->printStorePath(storePath), profileDir)); runProgram(settings.nixBinDir + "/nix-env", false, - {"--profile", profileDir, "-i", storePath, "--no-sandbox"}); + {"--profile", profileDir, "-i", store->printStorePath(storePath), "--no-sandbox"}); } printError(ANSI_GREEN "upgrade to version %s done" ANSI_NORMAL, version); @@ -129,15 +126,17 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand !hasSuffix(userEnv, "user-environment")) throw Error("directory '%s' does not appear to be part of a Nix profile", where); - if (!store->isValidPath(userEnv)) + if (!store->isValidPath(store->parseStorePath(userEnv))) throw Error("directory '%s' is not in the Nix store", userEnv); return profileDir; } /* Return the store path of the latest stable Nix. */ - Path getLatestNix(ref store) + StorePath getLatestNix(ref store) { + Activity act(*logger, lvlInfo, actUnknown, "querying latest Nix version"); + // FIXME: use nixos.org? auto req = DownloadRequest(storePathsUrl); auto res = getDownloader()->download(req); @@ -148,7 +147,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Bindings & bindings(*state->allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v); - return state->forceString(*v2); + return store->parseStorePath(state->forceString(*v2)); } }; diff --git a/src/nix/verify.cc b/src/nix/verify.cc index fa1414196..9b0658803 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -49,7 +49,7 @@ struct CmdVerify : StorePathsCommand }; } - void run(ref store, Paths storePaths) override + void run(ref store, StorePaths storePaths) override { std::vector> substituters; for (auto & s : substituterUris) @@ -80,7 +80,7 @@ struct CmdVerify : StorePathsCommand MaintainCount> mcActive(active); update(); - auto info = store->queryPathInfo(storePath); + auto info = store->queryPathInfo(store->parseStorePath(storePath)); if (!noContents) { @@ -88,7 +88,7 @@ struct CmdVerify : StorePathsCommand if (info->ca == "") hashSink = std::make_unique(info->narHash.type); else - hashSink = std::make_unique(info->narHash.type, storePathToHash(info->path)); + hashSink = std::make_unique(info->narHash.type, storePathToHash(store->printStorePath(info->path))); store->narFromPath(info->path, *hashSink); @@ -96,10 +96,10 @@ struct CmdVerify : StorePathsCommand if (hash.first != info->narHash) { corrupted++; - act2.result(resCorruptedPath, info->path); + act2.result(resCorruptedPath, store->printStorePath(info->path)); printError( - format("path '%s' was modified! expected hash '%s', got '%s'") - % info->path % info->narHash.to_string() % hash.first.to_string()); + "path '%s' was modified! expected hash '%s', got '%s'", + store->printStorePath(info->path), info->narHash.to_string(), hash.first.to_string()); } } @@ -120,7 +120,7 @@ struct CmdVerify : StorePathsCommand auto doSigs = [&](StringSet sigs) { for (auto sig : sigs) { if (!sigsSeen.insert(sig).second) continue; - if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(publicKeys, sig)) + if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(*store, publicKeys, sig)) validSigs++; } }; @@ -147,8 +147,8 @@ struct CmdVerify : StorePathsCommand if (!good) { untrusted++; - act2.result(resUntrustedPath, info->path); - printError(format("path '%s' is untrusted") % info->path); + act2.result(resUntrustedPath, store->printStorePath(info->path)); + printError("path '%s' is untrusted", store->printStorePath(info->path)); } } @@ -164,7 +164,7 @@ struct CmdVerify : StorePathsCommand }; for (auto & storePath : storePaths) - pool.enqueue(std::bind(doPath, storePath)); + pool.enqueue(std::bind(doPath, store->printStorePath(storePath))); pool.process(); diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index fa2a903a8..8566e5851 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -73,9 +73,9 @@ struct CmdWhyDepends : SourceExprCommand auto packagePath = toStorePath(store, Build, package); auto dependency = parseInstallable(*this, store, _dependency, false); auto dependencyPath = toStorePath(store, NoBuild, dependency); - auto dependencyPathHash = storePathToHash(dependencyPath); + auto dependencyPathHash = storePathToHash(store->printStorePath(dependencyPath)); - PathSet closure; + StorePathSet closure; store->computeFSClosure({packagePath}, closure, false, false); if (!closure.count(dependencyPath)) { @@ -91,28 +91,28 @@ struct CmdWhyDepends : SourceExprCommand struct Node { - Path path; - PathSet refs; - PathSet rrefs; + StorePath path; + StorePathSet refs; + StorePathSet rrefs; size_t dist = inf; Node * prev = nullptr; bool queued = false; bool visited = false; }; - std::map graph; + std::map graph; for (auto & path : closure) - graph.emplace(path, Node{path, store->queryPathInfo(path)->references}); + graph.emplace(path.clone(), Node{path.clone(), cloneStorePathSet(store->queryPathInfo(path)->references)}); // Transpose the graph. for (auto & node : graph) for (auto & ref : node.second.refs) - graph[ref].rrefs.insert(node.first); + graph.find(ref)->second.rrefs.insert(node.first.clone()); /* Run Dijkstra's shortest path algorithm to get the distance of every path in the closure to 'dependency'. */ - graph[dependencyPath].dist = 0; + graph[dependencyPath.clone()].dist = 0; std::priority_queue queue; @@ -151,12 +151,14 @@ struct CmdWhyDepends : SourceExprCommand struct BailOut { }; printNode = [&](Node & node, const string & firstPad, const string & tailPad) { + auto pathS = store->printStorePath(node.path); + assert(node.dist != inf); std::cout << fmt("%s%s%s%s" ANSI_NORMAL "\n", firstPad, node.visited ? "\e[38;5;244m" : "", firstPad != "" ? "=> " : "", - node.path); + pathS); if (node.path == dependencyPath && !all && packagePath != dependencyPath) @@ -175,7 +177,7 @@ struct CmdWhyDepends : SourceExprCommand auto & node2 = graph.at(ref); if (node2.dist == inf) continue; refs.emplace(node2.dist, &node2); - hashes.insert(storePathToHash(node2.path)); + hashes.insert(storePathToHash(store->printStorePath(node2.path))); } /* For each reference, find the files and symlinks that @@ -187,7 +189,7 @@ struct CmdWhyDepends : SourceExprCommand visitPath = [&](const Path & p) { auto st = accessor->stat(p); - auto p2 = p == node.path ? "/" : std::string(p, node.path.size() + 1); + auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1); auto getColour = [&](const std::string & hash) { return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE; @@ -231,11 +233,11 @@ struct CmdWhyDepends : SourceExprCommand // FIXME: should use scanForReferences(). - visitPath(node.path); + visitPath(pathS); RunPager pager; for (auto & ref : refs) { - auto hash = storePathToHash(ref.second->path); + auto hash = storePathToHash(store->printStorePath(ref.second->path)); bool last = all ? ref == *refs.rbegin() : true; diff --git a/src/resolve-system-dependencies/local.mk b/src/resolve-system-dependencies/local.mk index f9db16268..bf65f7905 100644 --- a/src/resolve-system-dependencies/local.mk +++ b/src/resolve-system-dependencies/local.mk @@ -6,6 +6,6 @@ resolve-system-dependencies_DIR := $(d) resolve-system-dependencies_INSTALL_DIR := $(libexecdir)/nix -resolve-system-dependencies_LIBS := libstore libmain libutil +resolve-system-dependencies_LIBS := libstore libmain libutil libnixrust resolve-system-dependencies_SOURCES := $(d)/resolve-system-dependencies.cc diff --git a/src/resolve-system-dependencies/resolve-system-dependencies.cc b/src/resolve-system-dependencies/resolve-system-dependencies.cc index 45e8b6796..8f0c99c84 100644 --- a/src/resolve-system-dependencies/resolve-system-dependencies.cc +++ b/src/resolve-system-dependencies/resolve-system-dependencies.cc @@ -179,8 +179,8 @@ int main(int argc, char ** argv) if (std::string(argv[1]) == "--test") impurePaths.insert(argv[2]); else { - auto drv = store->derivationFromPath(Path(argv[1])); - impurePaths = tokenizeString(get(drv.env, "__impureHostDeps")); + auto drv = store->derivationFromPath(store->parseStorePath(argv[1])); + impurePaths = tokenizeString(get(drv.env, "__impureHostDeps").value_or("")); impurePaths.insert("/usr/lib/libSystem.dylib"); }