[Chore] Handle 'temp_path' as an actual 'Path' instead of 'String'

Problem: 'temp_path' and 'lock_path' are handled as 'String'.
This can be a problem when the 'temp_path' directory is a symlink
on the target system, e.g. this is the case with the default
'/tmp' and macOS, where this directory is actually a symlink to '/private/tmp'.

Solution: Handle 'temp_path' and 'lock_path' as actual Paths.
Also, canonicalize 'temp_path' to avoid canary file path mismatches when checking
filesystem events.

As a side effect, also update the 'notify' dependency to the latest stable version.
This commit is contained in:
Roman Melnikov 2023-04-19 17:46:43 +08:00
parent 8c9ea9605e
commit 784e9ee24d
No known key found for this signature in database
GPG Key ID: 8931E8ED1EE2E537
7 changed files with 177 additions and 190 deletions

294
Cargo.lock generated
View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.15" version = "0.7.15"
@ -9,12 +11,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "anymap"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -23,7 +19,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -75,7 +71,7 @@ dependencies = [
"num-integer", "num-integer",
"num-traits", "num-traits",
"time", "time",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -113,23 +109,21 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.4.4" version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [ dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils", "crossbeam-utils",
"maybe-uninit",
] ]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.7.2" version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [ dependencies = [
"autocfg", "cfg-if 1.0.0",
"cfg-if 0.1.10",
"lazy_static",
] ]
[[package]] [[package]]
@ -164,7 +158,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall", "redox_syscall",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -192,41 +186,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "fsevent"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97f347202c95c98805c216f9e1df210e8ebaec9fdb2365700a43c10797a35e63"
dependencies = [
"bitflags",
"fsevent-sys",
]
[[package]] [[package]]
name = "fsevent-sys" name = "fsevent-sys"
version = "3.0.2" version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a29c77f1ca394c3e73a9a5d24cfcabb734682d9634fc398f2204a63c994120" checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.8" version = "0.3.8"
@ -312,9 +280,9 @@ dependencies = [
[[package]] [[package]]
name = "inotify" name = "inotify"
version = "0.8.3" version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46dd0a94b393c730779ccfd2a872b67b1eb67be3fc33082e733bdb38b5fde4d4" checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"inotify-sys", "inotify-sys",
@ -330,15 +298,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.4.6" version = "0.4.6"
@ -346,13 +305,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]] [[package]]
name = "kernel32-sys" name = "kqueue"
version = "0.2.2" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [ dependencies = [
"winapi 0.2.8", "kqueue-sys",
"winapi-build", "libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags",
"libc",
] ]
[[package]] [[package]]
@ -361,17 +330,11 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.81" version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]] [[package]]
name = "log" name = "log"
@ -382,12 +345,6 @@ dependencies = [
"cfg-if 0.1.10", "cfg-if 0.1.10",
] ]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.3.4" version = "2.3.4"
@ -416,25 +373,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "mio"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
dependencies = [
"cfg-if 0.1.10",
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
"kernel32-sys",
"libc",
"log",
"miow 0.2.2",
"net2",
"slab",
"winapi 0.2.8",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.7.6" version = "0.7.6"
@ -443,33 +381,21 @@ checksum = "f33bc887064ef1fd66020c9adfc45bb9f33d75a42096c81e7c56c65b75dd1a8b"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
"miow 0.3.6", "miow",
"ntapi", "ntapi",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
name = "mio-extras" name = "mio"
version = "2.0.6" version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [ dependencies = [
"lazycell", "libc",
"log", "log",
"mio 0.6.23", "wasi 0.11.0+wasi-snapshot-preview1",
"slab", "windows-sys 0.45.0",
]
[[package]]
name = "miow"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
dependencies = [
"kernel32-sys",
"net2",
"winapi 0.2.8",
"ws2_32-sys",
] ]
[[package]] [[package]]
@ -479,38 +405,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
dependencies = [ dependencies = [
"socket2", "socket2",
"winapi 0.3.9", "winapi",
]
[[package]]
name = "net2"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
dependencies = [
"cfg-if 0.1.10",
"libc",
"winapi 0.3.9",
] ]
[[package]] [[package]]
name = "notify" name = "notify"
version = "5.0.0-pre.4" version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8b946889dfdad884379cd56367d93b6d0ce8889cc027d26a69a3a31c0a03bb5" checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9"
dependencies = [ dependencies = [
"anymap",
"bitflags", "bitflags",
"crossbeam-channel", "crossbeam-channel",
"filetime", "filetime",
"fsevent",
"fsevent-sys", "fsevent-sys",
"inotify", "inotify",
"kqueue",
"libc", "libc",
"mio 0.6.23", "mio 0.8.6",
"mio-extras",
"walkdir", "walkdir",
"winapi 0.3.9", "windows-sys 0.42.0",
] ]
[[package]] [[package]]
@ -519,7 +432,7 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [ dependencies = [
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -787,7 +700,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall", "redox_syscall",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -823,7 +736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
dependencies = [ dependencies = [
"libc", "libc",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -884,8 +797,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi 0.10.0+wasi-snapshot-preview1",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -903,7 +816,7 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"tokio-macros", "tokio-macros",
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -963,7 +876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
dependencies = [ dependencies = [
"same-file", "same-file",
"winapi 0.3.9", "winapi",
"winapi-util", "winapi-util",
] ]
@ -973,18 +886,18 @@ version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "whoami" name = "whoami"
version = "0.9.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7884773ab69074615cb8f8425d0e53f11710786158704fca70f53e71b0e05504" checksum = "7884773ab69074615cb8f8425d0e53f11710786158704fca70f53e71b0e05504"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -995,12 +908,6 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu",
] ]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]] [[package]]
name = "winapi-i686-pc-windows-gnu" name = "winapi-i686-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
@ -1013,7 +920,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [ dependencies = [
"winapi 0.3.9", "winapi",
] ]
[[package]] [[package]]
@ -1023,15 +930,86 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "ws2_32-sys" name = "windows-sys"
version = "0.2.1" version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [ dependencies = [
"winapi 0.2.8", "windows_aarch64_gnullvm",
"winapi-build", "windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
] ]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]] [[package]]
name = "yansi" name = "yansi"
version = "0.5.0" version = "0.5.0"

View File

@ -17,7 +17,7 @@ fork = "0.1"
futures-util = "0.3.6" futures-util = "0.3.6"
log = "0.4" log = "0.4"
merge = "0.1.0" merge = "0.1.0"
notify = "5.0.0-pre.3" notify = "5.1.0"
rnix = "0.8" rnix = "0.8"
serde = { version = "1.0.104", features = [ "derive" ] } serde = { version = "1.0.104", features = [ "derive" ] }
serde_json = "1.0.48" serde_json = "1.0.48"

View File

@ -15,9 +15,9 @@ use tokio::time::timeout;
use std::time::Duration; use std::time::Duration;
use std::path::Path; use std::path::PathBuf;
use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use notify::{RecommendedWatcher, RecursiveMode, Watcher, recommended_watcher};
use thiserror::Error; use thiserror::Error;
@ -75,7 +75,7 @@ struct ActivateOpts {
/// Path for any temporary files that may be needed during activation /// Path for any temporary files that may be needed during activation
#[clap(long)] #[clap(long)]
temp_path: String, temp_path: PathBuf,
} }
/// Activate a profile /// Activate a profile
@ -86,7 +86,7 @@ struct WaitOpts {
/// Path for any temporary files that may be needed during activation /// Path for any temporary files that may be needed during activation
#[clap(long)] #[clap(long)]
temp_path: String, temp_path: PathBuf,
} }
/// Activate a profile /// Activate a profile
@ -232,7 +232,7 @@ async fn danger_zone(
pub async fn activation_confirmation( pub async fn activation_confirmation(
profile_path: String, profile_path: String,
temp_path: String, temp_path: PathBuf,
confirm_timeout: u16, confirm_timeout: u16,
closure: String, closure: String,
) -> Result<(), ActivationConfirmationError> { ) -> Result<(), ActivationConfirmationError> {
@ -240,7 +240,7 @@ pub async fn activation_confirmation(
debug!("Ensuring parent directory exists for canary file"); debug!("Ensuring parent directory exists for canary file");
if let Some(parent) = Path::new(&lock_path).parent() { if let Some(parent) = lock_path.parent() {
fs::create_dir_all(parent) fs::create_dir_all(parent)
.await .await
.map_err(ActivationConfirmationError::CreateConfirmDir)?; .map_err(ActivationConfirmationError::CreateConfirmDir)?;
@ -257,7 +257,7 @@ pub async fn activation_confirmation(
let (deleted, done) = mpsc::channel(1); let (deleted, done) = mpsc::channel(1);
let mut watcher: RecommendedWatcher = let mut watcher: RecommendedWatcher =
Watcher::new_immediate(move |res: Result<notify::event::Event, notify::Error>| { recommended_watcher(move |res: Result<notify::event::Event, notify::Error>| {
let send_result = match res { let send_result = match res {
Ok(e) if e.kind == notify::EventKind::Remove(notify::event::RemoveKind::File) => { Ok(e) if e.kind == notify::EventKind::Remove(notify::event::RemoveKind::File) => {
debug!("Got worthy removal event, sending on channel"); debug!("Got worthy removal event, sending on channel");
@ -298,7 +298,7 @@ pub enum WaitError {
#[error("Error waiting for activation: {0}")] #[error("Error waiting for activation: {0}")]
Waiting(#[from] DangerZoneError), Waiting(#[from] DangerZoneError),
} }
pub async fn wait(temp_path: String, closure: String) -> Result<(), WaitError> { pub async fn wait(temp_path: PathBuf, closure: String) -> Result<(), WaitError> {
let lock_path = deploy::make_lock_path(&temp_path, &closure); let lock_path = deploy::make_lock_path(&temp_path, &closure);
let (created, done) = mpsc::channel(1); let (created, done) = mpsc::channel(1);
@ -307,11 +307,16 @@ pub async fn wait(temp_path: String, closure: String) -> Result<(), WaitError> {
// TODO: fix wasteful clone // TODO: fix wasteful clone
let lock_path = lock_path.clone(); let lock_path = lock_path.clone();
Watcher::new_immediate(move |res: Result<notify::event::Event, notify::Error>| { recommended_watcher(move |res: Result<notify::event::Event, notify::Error>| {
let send_result = match res { let send_result = match res {
Ok(e) if e.kind == notify::EventKind::Create(notify::event::CreateKind::File) => { Ok(e) if e.kind == notify::EventKind::Create(notify::event::CreateKind::File) => {
match &e.paths[..] { match &e.paths[..] {
[x] if x == Path::new(&lock_path) => created.try_send(Ok(())), [x] => match lock_path.canonicalize() {
// 'lock_path' may not exist yet when some other files are created in 'temp_path'
// x is already supposed to be canonical path
Ok(lock_path) if x == &lock_path => created.try_send(Ok(())),
_ => Ok (())
}
_ => Ok(()), _ => Ok(()),
} }
} }
@ -363,7 +368,7 @@ pub async fn activate(
profile_path: String, profile_path: String,
closure: String, closure: String,
auto_rollback: bool, auto_rollback: bool,
temp_path: String, temp_path: PathBuf,
confirm_timeout: u16, confirm_timeout: u16,
magic_rollback: bool, magic_rollback: bool,
dry_activate: bool, dry_activate: bool,

View File

@ -14,6 +14,7 @@ use self::deploy::{DeployFlake, ParseFlakeError};
use futures_util::stream::{StreamExt, TryStreamExt}; use futures_util::stream::{StreamExt, TryStreamExt};
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use serde::Serialize; use serde::Serialize;
use std::path::PathBuf;
use std::process::Stdio; use std::process::Stdio;
use thiserror::Error; use thiserror::Error;
use tokio::process::Command; use tokio::process::Command;
@ -86,7 +87,7 @@ pub struct Opts {
confirm_timeout: Option<u16>, confirm_timeout: Option<u16>,
/// Where to store temporary files (only used by magic-rollback) /// Where to store temporary files (only used by magic-rollback)
#[clap(long)] #[clap(long)]
temp_path: Option<String>, temp_path: Option<PathBuf>,
/// Show what will be activated on the machines /// Show what will be activated on the machines
#[clap(long)] #[clap(long)]
dry_activate: bool, dry_activate: bool,

View File

@ -5,6 +5,7 @@
use merge::Merge; use merge::Merge;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Deserialize, Debug, Clone, Merge)] #[derive(Deserialize, Debug, Clone, Merge)]
pub struct GenericSettings { pub struct GenericSettings {
@ -25,7 +26,7 @@ pub struct GenericSettings {
#[serde(rename(deserialize = "confirmTimeout"))] #[serde(rename(deserialize = "confirmTimeout"))]
pub confirm_timeout: Option<u16>, pub confirm_timeout: Option<u16>,
#[serde(rename(deserialize = "tempPath"))] #[serde(rename(deserialize = "tempPath"))]
pub temp_path: Option<String>, pub temp_path: Option<PathBuf>,
#[serde(rename(deserialize = "magicRollback"))] #[serde(rename(deserialize = "magicRollback"))]
pub magic_rollback: Option<bool>, pub magic_rollback: Option<bool>,
#[serde(rename(deserialize = "sudo"))] #[serde(rename(deserialize = "sudo"))]

View File

@ -5,7 +5,7 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use log::{debug, info}; use log::{debug, info};
use std::borrow::Cow; use std::path::Path;
use thiserror::Error; use thiserror::Error;
use tokio::process::Command; use tokio::process::Command;
@ -16,7 +16,7 @@ struct ActivateCommandData<'a> {
profile_path: &'a str, profile_path: &'a str,
closure: &'a str, closure: &'a str,
auto_rollback: bool, auto_rollback: bool,
temp_path: &'a str, temp_path: &'a Path,
confirm_timeout: u16, confirm_timeout: u16,
magic_rollback: bool, magic_rollback: bool,
debug_logs: bool, debug_logs: bool,
@ -38,7 +38,7 @@ fn build_activate_command(data: &ActivateCommandData) -> String {
self_activate_command = format!( self_activate_command = format!(
"{} activate '{}' '{}' --temp-path '{}'", "{} activate '{}' '{}' --temp-path '{}'",
self_activate_command, data.closure, data.profile_path, data.temp_path self_activate_command, data.closure, data.profile_path, data.temp_path.display()
); );
self_activate_command = format!( self_activate_command = format!(
@ -77,7 +77,7 @@ fn test_activation_command_builder() {
let auto_rollback = true; let auto_rollback = true;
let dry_activate = false; let dry_activate = false;
let boot = false; let boot = false;
let temp_path = "/tmp"; let temp_path = Path::new("/tmp");
let confirm_timeout = 30; let confirm_timeout = 30;
let magic_rollback = true; let magic_rollback = true;
let debug_logs = true; let debug_logs = true;
@ -105,7 +105,7 @@ fn test_activation_command_builder() {
struct WaitCommandData<'a> { struct WaitCommandData<'a> {
sudo: &'a Option<String>, sudo: &'a Option<String>,
closure: &'a str, closure: &'a str,
temp_path: &'a str, temp_path: &'a Path,
debug_logs: bool, debug_logs: bool,
log_dir: Option<&'a str>, log_dir: Option<&'a str>,
} }
@ -123,7 +123,7 @@ fn build_wait_command(data: &WaitCommandData) -> String {
self_activate_command = format!( self_activate_command = format!(
"{} wait '{}' --temp-path '{}'", "{} wait '{}' --temp-path '{}'",
self_activate_command, data.closure, data.temp_path, self_activate_command, data.closure, data.temp_path.display(),
); );
if let Some(sudo_cmd) = &data.sudo { if let Some(sudo_cmd) = &data.sudo {
@ -137,7 +137,7 @@ fn build_wait_command(data: &WaitCommandData) -> String {
fn test_wait_command_builder() { fn test_wait_command_builder() {
let sudo = Some("sudo -u test".to_string()); let sudo = Some("sudo -u test".to_string());
let closure = "/nix/store/blah/etc"; let closure = "/nix/store/blah/etc";
let temp_path = "/tmp"; let temp_path = Path::new("/tmp");
let debug_logs = true; let debug_logs = true;
let log_dir = Some("/tmp/something.txt"); let log_dir = Some("/tmp/something.txt");
@ -216,7 +216,7 @@ pub enum ConfirmProfileError {
pub async fn confirm_profile( pub async fn confirm_profile(
deploy_data: &super::DeployData<'_>, deploy_data: &super::DeployData<'_>,
deploy_defs: &super::DeployDefs, deploy_defs: &super::DeployDefs,
temp_path: Cow<'_, str>, temp_path: &Path,
ssh_addr: &str, ssh_addr: &str,
) -> Result<(), ConfirmProfileError> { ) -> Result<(), ConfirmProfileError> {
let mut ssh_confirm_command = Command::new("ssh"); let mut ssh_confirm_command = Command::new("ssh");
@ -226,9 +226,9 @@ pub async fn confirm_profile(
ssh_confirm_command.arg(ssh_opt); ssh_confirm_command.arg(ssh_opt);
} }
let lock_path = super::make_lock_path(&temp_path, &deploy_data.profile.profile_settings.path); let lock_path = super::make_lock_path(temp_path, &deploy_data.profile.profile_settings.path);
let mut confirm_command = format!("rm {}", lock_path); let mut confirm_command = format!("rm {}", lock_path.display());
if let Some(sudo_cmd) = &deploy_defs.sudo { if let Some(sudo_cmd) = &deploy_defs.sudo {
confirm_command = format!("{} {}", sudo_cmd, confirm_command); confirm_command = format!("{} {}", sudo_cmd, confirm_command);
} }
@ -286,9 +286,9 @@ pub async fn deploy_profile(
); );
} }
let temp_path: Cow<str> = match &deploy_data.merged_settings.temp_path { let temp_path: &Path = match &deploy_data.merged_settings.temp_path {
Some(x) => x.into(), Some(x) => x,
None => "/tmp".into(), None => Path::new("/tmp"),
}; };
let confirm_timeout = deploy_data.merged_settings.confirm_timeout.unwrap_or(30); let confirm_timeout = deploy_data.merged_settings.confirm_timeout.unwrap_or(30);
@ -302,7 +302,7 @@ pub async fn deploy_profile(
profile_path: &deploy_defs.profile_path, profile_path: &deploy_defs.profile_path,
closure: &deploy_data.profile.profile_settings.path, closure: &deploy_data.profile.profile_settings.path,
auto_rollback, auto_rollback,
temp_path: &temp_path, temp_path: temp_path,
confirm_timeout, confirm_timeout,
magic_rollback, magic_rollback,
debug_logs: deploy_data.debug_logs, debug_logs: deploy_data.debug_logs,
@ -350,7 +350,7 @@ pub async fn deploy_profile(
let self_wait_command = build_wait_command(&WaitCommandData { let self_wait_command = build_wait_command(&WaitCommandData {
sudo: &deploy_defs.sudo, sudo: &deploy_defs.sudo,
closure: &deploy_data.profile.profile_settings.path, closure: &deploy_data.profile.profile_settings.path,
temp_path: &temp_path, temp_path: temp_path,
debug_logs: deploy_data.debug_logs, debug_logs: deploy_data.debug_logs,
log_dir: deploy_data.log_dir, log_dir: deploy_data.log_dir,
}); });

View File

@ -12,10 +12,12 @@ use thiserror::Error;
use flexi_logger::*; use flexi_logger::*;
pub fn make_lock_path(temp_path: &str, closure: &str) -> String { use std::path::{Path, PathBuf};
pub fn make_lock_path(temp_path: &Path, closure: &str) -> PathBuf {
let lock_hash = let lock_hash =
&closure["/nix/store/".len()..closure.find('-').unwrap_or_else(|| closure.len())]; &closure["/nix/store/".len()..closure.find('-').unwrap_or_else(|| closure.len())];
format!("{}/deploy-rs-canary-{}", temp_path, lock_hash) temp_path.join(format!("deploy-rs-canary-{}", lock_hash))
} }
const fn make_emoji(level: log::Level) -> &'static str { const fn make_emoji(level: log::Level) -> &'static str {
@ -159,7 +161,7 @@ pub struct CmdOverrides {
pub auto_rollback: Option<bool>, pub auto_rollback: Option<bool>,
pub hostname: Option<String>, pub hostname: Option<String>,
pub magic_rollback: Option<bool>, pub magic_rollback: Option<bool>,
pub temp_path: Option<String>, pub temp_path: Option<PathBuf>,
pub confirm_timeout: Option<u16>, pub confirm_timeout: Option<u16>,
pub sudo: Option<String>, pub sudo: Option<String>,
pub dry_activate: bool, pub dry_activate: bool,