Upgrade to Rust 2021

- Fix lints
- Formatting pass
- Add Cargo.lock

Use anyhow to improve error handling

Fix errors during directory removal in Windows

Update dependencies

Switch linux build to musl

Switch to musl

Set version to 0.4.0

Allow using uid instead of mtime

Remove name duplication with runner map

Fixing typo
This commit is contained in:
Reisz 2021-12-11 13:20:14 +01:00 committed by david
parent 99a6ee6ea2
commit d9aeb582a2
13 changed files with 1226 additions and 387 deletions

4
.gitignore vendored
View File

@ -2,10 +2,6 @@
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

741
Cargo.lock generated Normal file
View File

@ -0,0 +1,741 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e67816e006b17427c9b4386915109b494fec2d929c63e3bd3561234cbf1bf1e"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "colored"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
dependencies = [
"atty",
"lazy_static",
"winapi",
]
[[package]]
name = "crc32fast"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "filetime"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi",
]
[[package]]
name = "flate2"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
dependencies = [
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itoa"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memmem"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "os_str_bytes"
version = "6.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
dependencies = [
"getrandom",
"redox_syscall",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "remove_dir_all"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "882f368737489ea543bc5c340e6f3d34a28c39980bd9a979e47322b26f60ac40"
dependencies = [
"libc",
"log",
"num_cpus",
"rayon",
"winapi",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "simple_logger"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd"
dependencies = [
"atty",
"colored",
"log",
"time",
"windows-sys",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tar"
version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand",
"remove_dir_all 0.5.3",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "time"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
"itoa",
"libc",
"num_threads",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]]
name = "time-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
dependencies = [
"time-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "uuid"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83"
dependencies = [
"getrandom",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "warp-args"
version = "0.1.0"
dependencies = [
"bincode",
"serde",
]
[[package]]
name = "warp-packer"
version = "0.4.0"
dependencies = [
"bincode",
"clap",
"flate2",
"lazy_static",
"tar",
"tempdir",
"uuid",
"warp-args",
]
[[package]]
name = "warp-runner"
version = "0.4.0"
dependencies = [
"anyhow",
"bincode",
"dirs",
"flate2",
"log",
"memmem",
"remove_dir_all 0.7.0",
"simple_logger",
"tar",
"warp-args",
]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "xattr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
dependencies = [
"libc",
]

View File

@ -1,2 +1,2 @@
[workspace]
members = ["warp-runner", "warp-packer"]
members = ["warp-args", "warp-runner", "warp-packer"]

View File

@ -2,8 +2,8 @@ all:
$(MAKE) build
build:
cargo build -p warp-runner --release --target x86_64-unknown-linux-gnu
strip target/x86_64-unknown-linux-gnu/release/warp-runner
cargo build -p warp-runner --release --target x86_64-unknown-linux-musl
strip target/x86_64-unknown-linux-musl/release/warp-runner
CC=x86_64-apple-darwin15-clang cargo build -p warp-runner --release --target x86_64-apple-darwin
x86_64-apple-darwin15-strip target/x86_64-apple-darwin/release/warp-runner
@ -11,8 +11,8 @@ build:
cargo build -p warp-runner --release --target x86_64-pc-windows-gnu
strip target/x86_64-pc-windows-gnu/release/warp-runner.exe
cargo build -p warp-packer --release --target x86_64-unknown-linux-gnu
strip target/x86_64-unknown-linux-gnu/release/warp-packer
cargo build -p warp-packer --release --target x86_64-unknown-linux-musl
strip target/x86_64-unknown-linux-musl/release/warp-packer
CC=x86_64-apple-darwin15-clang cargo build -p warp-packer --release --target x86_64-apple-darwin
x86_64-apple-darwin15-strip target/x86_64-apple-darwin/release/warp-packer

10
warp-args/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "warp-args"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bincode = "1.3"
serde = { version = "1.0", features = ["derive"] }

22
warp-args/src/lib.rs Normal file
View File

@ -0,0 +1,22 @@
use std::path::PathBuf;
use bincode::Options;
use serde::{Deserialize, Serialize};
pub const WARP_ARGS_MAGIC: &[u8] = b"DR1PWsJsM6KxNbng9Y38";
#[derive(Serialize, Deserialize, Debug)]
pub struct Args {
pub target_file_name: PathBuf,
pub prefix: Option<PathBuf>,
pub uid: Option<String>,
pub clean: bool,
}
pub fn bincode_options() -> impl bincode::Options {
bincode::DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
// Make sure bincode does not trust all size prefixes while scanning the binary
.with_limit(1_000_000)
}

View File

@ -1,13 +1,15 @@
[package]
name = "warp-packer"
version = "0.3.0"
version = "0.4.0"
authors = ["Diego Giagio <diego@giagio.com>"]
edition = "2021"
[dependencies]
clap = "2.32.0"
dirs = "1.0.4"
reqwest = "0.9.2"
tempdir = "0.3.7"
bincode = "1.3"
clap = { version = "4.0", features = ["derive"] }
flate2 = "1.0"
tar = "0.4"
lazy_static = "1.1.0"
tar = "0.4"
tempdir = "0.3.7"
uuid = { version = "1.2", features = ["v4"] }
warp-args = { path = "../warp-args" }

47
warp-packer/src/cli.rs Normal file
View File

@ -0,0 +1,47 @@
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(author, version, about)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand, Debug)]
pub enum Command {
Pack(PackArgs),
List,
}
#[derive(Args, Debug)]
pub struct PackArgs {
/// Sets the architecture. Use list subcommand to get possible options.
#[arg(short, long)]
pub arch: String,
/// Sets the input directory containing the application and dependencies
#[arg(short, long)]
pub input_dir: PathBuf,
/// Sets the application executable file name
#[arg(short, long)]
pub exec: PathBuf,
/// Sets the resulting self-contained application file name
#[arg(short, long)]
pub output: PathBuf,
/// Generate unique id for each package build
#[arg(short = 'q', long, default_value_t = false)]
pub unique_id: bool,
/// Prefix to use instead of single-file executable name
#[arg(short, long)]
pub prefix: Option<PathBuf>,
/// When using unique-id, do not look for and clean obsolete versions with the same prefix from cache
#[arg(short = 'n', long = "no-clean", action = clap::ArgAction::SetFalse)]
pub clean: bool,
}

View File

@ -1,42 +1,37 @@
extern crate clap;
extern crate dirs;
extern crate flate2;
#[macro_use]
extern crate lazy_static;
extern crate reqwest;
extern crate tar;
extern crate tempdir;
mod cli;
use clap::{App, AppSettings, Arg};
use flate2::Compression;
use bincode::Options;
use clap::Parser;
use flate2::write::GzEncoder;
use std::collections::HashMap;
use flate2::Compression;
use lazy_static::lazy_static;
use std::error::Error;
use std::fs;
use std::fs::File;
use std::io;
use std::io::copy;
use std::io::Write;
use std::io::{self, Write};
use std::path::Path;
use std::process;
use tempdir::TempDir;
use std::{collections::HashMap, io::BufWriter};
use uuid::Uuid;
use warp_args::{bincode_options, Args, WARP_ARGS_MAGIC};
const APP_NAME: &str = env!("CARGO_PKG_NAME");
const AUTHOR: &str = env!("CARGO_PKG_AUTHORS");
const VERSION: &str = env!("CARGO_PKG_VERSION");
const RUNNER_MAGIC: &[u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0";
const RUNNER_LINUX_X64: &[u8] = include_bytes!("../../target/x86_64-unknown-linux-gnu/release/warp-runner");
const RUNNER_MACOS_X64: &[u8] = include_bytes!("../../target/x86_64-apple-darwin/release/warp-runner");
const RUNNER_WINDOWS_X64: &[u8] = include_bytes!("../../target/x86_64-pc-windows-gnu/release/warp-runner.exe");
use crate::cli::Command;
lazy_static! {
static ref RUNNER_BY_ARCH: HashMap<&'static str, &'static [u8]> = {
let mut m = HashMap::new();
m.insert("linux-x64", RUNNER_LINUX_X64);
m.insert("macos-x64", RUNNER_MACOS_X64);
m.insert("windows-x64", RUNNER_WINDOWS_X64);
m.insert(
"linux-x64",
include_bytes!("../../target/x86_64-unknown-linux-musl/release/warp-runner").as_slice(),
);
m.insert(
"macos-x64",
include_bytes!("../../target/x86_64-apple-darwin/release/warp-runner").as_slice(),
);
m.insert(
"windows-x64",
include_bytes!("../../target/x86_64-pc-windows-gnu/release/warp-runner.exe").as_slice(),
);
m
};
}
@ -50,43 +45,16 @@ macro_rules! bail {
})
}
fn patch_runner(arch: &str, exec_name: &str) -> io::Result<Vec<u8>> {
// Read runner executable in memory
let runner_contents = RUNNER_BY_ARCH.get(arch).unwrap();
let mut buf = runner_contents.to_vec();
// Set the correct target executable name into the local magic buffer
let magic_len = RUNNER_MAGIC.len();
let mut new_magic = vec![0; magic_len];
new_magic[..exec_name.len()].clone_from_slice(exec_name.as_bytes());
// Find the magic buffer offset inside the runner executable
let mut offs_opt = None;
for (i, chunk) in buf.windows(magic_len).enumerate() {
if chunk == RUNNER_MAGIC {
offs_opt = Some(i);
break;
}
}
if offs_opt.is_none() {
return Err(io::Error::new(io::ErrorKind::Other, "no magic found inside runner"));
}
// Replace the magic with the new one that points to the target executable
let offs = offs_opt.unwrap();
buf[offs..offs + magic_len].clone_from_slice(&new_magic);
Ok(buf)
}
fn create_tgz(dir: &Path, out: &Path) -> io::Result<()> {
let f = fs::File::create(out)?;
fn append_tgz(f: &mut impl io::Write, dir: &Path) -> io::Result<()> {
let gz = GzEncoder::new(f, Compression::best());
let mut tar = tar::Builder::new(gz);
tar.follow_symlinks(false);
tar.append_dir_all(".", dir)?;
Ok(())
tar.append_dir_all(".", dir)
}
fn append_args(f: &mut impl io::Write, args: &Args) {
f.write_all(WARP_ARGS_MAGIC).unwrap();
bincode_options().serialize_into(f, args).unwrap();
}
#[cfg(target_family = "unix")]
@ -102,76 +70,38 @@ fn create_app_file(out: &Path) -> io::Result<File> {
#[cfg(target_family = "windows")]
fn create_app_file(out: &Path) -> io::Result<File> {
fs::OpenOptions::new()
.create(true)
.write(true)
.open(out)
fs::OpenOptions::new().create(true).write(true).open(out)
}
fn create_app(runner_buf: &Vec<u8>, tgz_path: &Path, out: &Path) -> io::Result<()> {
let mut outf = create_app_file(out)?;
let mut tgzf = fs::File::open(tgz_path)?;
outf.write_all(runner_buf)?;
copy(&mut tgzf, &mut outf)?;
Ok(())
}
fn main() -> Result<(), Box<dyn Error>> {
let args = cli::Cli::parse();
fn main() -> Result<(), Box<Error>> {
let args = App::new(APP_NAME)
.settings(&[AppSettings::ArgRequiredElseHelp, AppSettings::ColoredHelp])
.version(VERSION)
.author(AUTHOR)
.about("Create self-contained single binary application")
.arg(Arg::with_name("arch")
.short("a")
.long("arch")
.value_name("arch")
.help(&format!("Sets the architecture. Supported: {:?}", RUNNER_BY_ARCH.keys()))
.display_order(1)
.takes_value(true)
.required(true))
.arg(Arg::with_name("input_dir")
.short("i")
.long("input_dir")
.value_name("input_dir")
.help("Sets the input directory containing the application and dependencies")
.display_order(2)
.takes_value(true)
.required(true))
.arg(Arg::with_name("exec")
.short("e")
.long("exec")
.value_name("exec")
.help("Sets the application executable file name")
.display_order(3)
.takes_value(true)
.required(true))
.arg(Arg::with_name("output")
.short("o")
.long("output")
.value_name("output")
.help("Sets the resulting self-contained application file name")
.display_order(4)
.takes_value(true)
.required(true))
.get_matches();
let args = match args.command {
Command::List => {
for arch in RUNNER_BY_ARCH.keys() {
println!("{arch}");
}
return Ok(());
}
Command::Pack(args) => args,
};
let arch = args.value_of("arch").unwrap();
if !RUNNER_BY_ARCH.contains_key(&arch) {
bail!("Unknown architecture specified: {}, supported: {:?}", arch, RUNNER_BY_ARCH.keys());
if !RUNNER_BY_ARCH.contains_key(&args.arch.as_str()) {
bail!(
"Unknown architecture specified: {}, supported: {:?}",
args.arch,
RUNNER_BY_ARCH.keys()
);
}
let input_dir = Path::new(args.value_of("input_dir").unwrap());
if fs::metadata(input_dir).is_err() {
bail!("Cannot access specified input directory {:?}", input_dir);
if fs::metadata(&args.input_dir).is_err() {
bail!(
"Cannot access specified input directory {:?}",
args.input_dir
);
}
let exec_name = args.value_of("exec").unwrap();
if exec_name.len() >= RUNNER_MAGIC.len() {
bail!("Executable name is too long, please consider using a shorter name");
}
let exec_path = Path::new(input_dir).join(exec_name);
let exec_path = args.input_dir.join(&args.exec);
match fs::metadata(&exec_path) {
Err(_) => {
bail!("Cannot find file {:?}", exec_path);
@ -183,16 +113,24 @@ fn main() -> Result<(), Box<Error>> {
}
}
let runner_buf = patch_runner(&arch, &exec_name)?;
println!(
"Creating self-contained application binary {:?}...",
args.exec
);
let mut output = BufWriter::new(create_app_file(&args.output).unwrap());
output.write_all(RUNNER_BY_ARCH.get(&args.arch.as_str()).unwrap())?;
append_args(
&mut output,
&Args {
target_file_name: args.exec,
prefix: args.prefix,
uid: args.unique_id.then(|| format!("{}", Uuid::new_v4())),
clean: args.clean,
},
);
println!("Compressing input directory {:?}...", input_dir);
let tmp_dir = TempDir::new(APP_NAME)?;
let tgz_path = tmp_dir.path().join("input.tgz");
create_tgz(&input_dir, &tgz_path)?;
let exec_name = Path::new(args.value_of("output").unwrap());
println!("Creating self-contained application binary {:?}...", exec_name);
create_app(&runner_buf, &tgz_path, &exec_name)?;
println!("Compressing input directory {:?}...", args.input_dir);
append_tgz(&mut output, &args.input_dir).unwrap();
println!("All done");
Ok(())

View File

@ -1,13 +1,17 @@
[package]
name = "warp-runner"
version = "0.3.0"
version = "0.4.0"
authors = ["Diego Giagio <diego@giagio.com>"]
edition = "2021"
[dependencies]
memmem = "0.1.1"
anyhow = "1.0"
bincode = "1.3"
dirs = "4.0"
flate2 = "1.0"
tar = "0.4"
dirs = "1.0.4"
winapi = "0.3.6"
log = "0.4.5"
simple_logger = "1.0.1"
memmem = "0.1.1"
remove_dir_all = "0.7"
simple_logger = "4.0"
tar = "0.4"
warp-args = { path = "../warp-args" }

View File

@ -1,9 +1,10 @@
use log::trace;
use std::env;
use std::io;
#[cfg(target_family = "unix")]
use std::fs;
#[cfg(target_family = "unix")]
use std::fs::Permissions;
use std::io;
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
@ -36,17 +37,21 @@ fn do_execute(target: &Path, args: &[String]) -> io::Result<i32> {
.stderr(Stdio::inherit())
.spawn()?
.wait()?
.code().unwrap_or(1))
.code()
.unwrap_or(1))
}
#[cfg(target_family = "windows")]
fn is_script(target: &Path) -> bool {
const SCRIPT_EXTENSIONS: &[&str] = &["bat", "cmd"];
SCRIPT_EXTENSIONS.contains(
&target.extension()
&target
.extension()
.unwrap_or_default()
.to_string_lossy()
.to_lowercase().as_str())
.to_lowercase()
.as_str(),
)
}
#[cfg(target_family = "windows")]
@ -66,7 +71,8 @@ fn do_execute(target: &Path, args: &[String]) -> io::Result<i32> {
.stderr(Stdio::inherit())
.spawn()?
.wait()?
.code().unwrap_or(1))
.code()
.unwrap_or(1))
} else {
Ok(Command::new(target)
.args(args)
@ -75,6 +81,7 @@ fn do_execute(target: &Path, args: &[String]) -> io::Result<i32> {
.stderr(Stdio::inherit())
.spawn()?
.wait()?
.code().unwrap_or(1))
.code()
.unwrap_or(1))
}
}

View File

@ -1,14 +1,14 @@
extern crate flate2;
extern crate memmem;
extern crate tar;
use self::flate2::read::GzDecoder;
use self::memmem::{Searcher, TwoWaySearcher};
use self::tar::Archive;
use anyhow::{anyhow, Context, Result};
use bincode::Options;
use flate2::read::GzDecoder;
use log::trace;
use memmem::{Searcher, TwoWaySearcher};
use std::fs::File;
use std::io;
use std::io::{BufReader, Read, Seek, SeekFrom};
use std::path::Path;
use tar::Archive;
use warp_args::{bincode_options, Args, WARP_ARGS_MAGIC};
struct FileSearcher<'a> {
buf_reader: BufReader<File>,
@ -36,7 +36,7 @@ impl<'a> Iterator for FileSearcher<'a> {
match self.buf_reader.seek(SeekFrom::Start(self.offs as u64)) {
Ok(_) => {}
Err(e) => return Some(Err(e))
Err(e) => return Some(Err(e)),
}
loop {
@ -53,7 +53,7 @@ impl<'a> Iterator for FileSearcher<'a> {
self.offs += 1; // one past the match so we can try again if necessary
break;
}
None => self.offs += n
None => self.offs += n,
}
}
Err(e) => {
@ -68,32 +68,53 @@ impl<'a> Iterator for FileSearcher<'a> {
const GZIP_MAGIC: &[u8] = b"\x1f\x8b\x08";
pub fn extract_to(src: &Path, dst: &Path) -> io::Result<()> {
let mut found = false;
let searcher = FileSearcher::new(src, GZIP_MAGIC)?;
for result in searcher {
let offs = result?;
if extract_at_offset(src, offs, dst).is_ok() {
trace!("tarball found at offset {} was extracted successfully", offs);
found = true;
break;
}
}
if found {
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, "no tarball found inside binary"))
}
pub fn extract_to(src: &Path, dst: &Path) -> Result<()> {
FileSearcher::new(src, GZIP_MAGIC)
.context("failed searching own binary")?
.map(Result::unwrap)
.find(|offs| extract_at_offset(src, *offs, dst).unwrap())
.ok_or_else(|| anyhow!("No tarball found inside binary file {}", src.display()))
.map(|offs| {
trace!(
"tarball found at offset {} was extracted successfully",
offs
);
})
}
fn extract_at_offset(src: &Path, offs: usize, dst: &Path) -> io::Result<()> {
let mut f = File::open(src)?;
f.seek(SeekFrom::Start(offs as u64))?;
fn extract_at_offset(src: &Path, offs: usize, dst: &Path) -> Result<bool> {
let mut f = File::open(src)
.with_context(|| format!("Failed to open file to extract from: {}", src.display()))?;
f.seek(SeekFrom::Start(offs as u64))
.with_context(|| format!("Failed to read file to extract from: {}", src.display()))?;
let gz = GzDecoder::new(f);
let mut tar = Archive::new(gz);
tar.unpack(dst)?;
Ok(())
Ok(tar.unpack(dst).is_ok())
}
pub fn get_args(src: &Path) -> Result<Args> {
FileSearcher::new(src, WARP_ARGS_MAGIC)
.context("failed searching own binary")?
.map(Result::unwrap)
.find_map(|offs| {
Some((
offs,
extract_args_at_offset(src, offs + WARP_ARGS_MAGIC.len()).unwrap()?,
))
})
.ok_or_else(|| anyhow!("No arguments found inside binary file {}", src.display()))
.map(|(offs, args)| {
trace!("args found at offset {} was extracted successfully", offs);
args
})
}
fn extract_args_at_offset(src: &Path, offs: usize) -> Result<Option<Args>> {
let mut f = File::open(src)
.with_context(|| format!("Failed to open file to extract from: {}", src.display()))?;
f.seek(SeekFrom::Start(offs as u64))
.with_context(|| format!("Failed to read file to extract from: {}", src.display()))?;
Ok(bincode_options().deserialize_from(f).ok())
}

View File

@ -1,82 +1,133 @@
extern crate dirs;
#[macro_use]
extern crate log;
extern crate simple_logger;
use log::Level;
use anyhow::Context;
use anyhow::{anyhow, Result};
use log::{trace, Level};
use remove_dir_all::remove_dir_all;
use std::env;
use std::error::Error;
use std::ffi::*;
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::*;
use std::path::{Path, PathBuf};
use std::process;
use warp_args::Args;
use crate::extractor::get_args;
mod extractor;
mod executor;
mod extractor;
static TARGET_FILE_NAME_BUF: &'static [u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0";
static STATIC_SUBFOLDER_NAME: &str = "static";
fn target_file_name() -> &'static str {
let nul_pos = TARGET_FILE_NAME_BUF.iter()
.position(|elem| *elem == b'\0')
.expect("TARGET_FILE_NAME_BUF has no NUL terminator");
let slice = &TARGET_FILE_NAME_BUF[..(nul_pos + 1)];
CStr::from_bytes_with_nul(slice)
.expect("Can't convert TARGET_FILE_NAME_BUF slice to CStr")
.to_str()
.expect("Can't convert TARGET_FILE_NAME_BUF CStr to str")
}
fn cache_path(target: &str) -> PathBuf {
dirs::data_local_dir()
.expect("No data local dir found")
fn cache_path(target: &str) -> Result<PathBuf> {
Ok(dirs::data_local_dir()
.ok_or_else(|| anyhow!("No data local dir found"))?
.join("warp")
.join("packages")
.join(target)
.join(target))
}
fn extract(exe_path: &Path, cache_path: &Path) -> io::Result<()> {
fs::remove_dir_all(cache_path).ok();
extractor::extract_to(&exe_path, &cache_path)?;
fn extract(exe_path: &Path, cache_path: &Path) -> Result<()> {
if cache_path.exists() {
remove_dir_all(cache_path)
.with_context(|| format!("Failed to remove directory {}", cache_path.display()))?;
}
extractor::extract_to(exe_path, cache_path).with_context(|| {
format!(
"Failed to extract {} to {}",
exe_path.display(),
cache_path.display()
)
})
}
fn create_cache_folder(self_path: &Path, args: &Args) -> Result<PathBuf> {
let prefix = args
.prefix
.as_deref()
.unwrap_or_else(|| Path::new(self_path.file_name().unwrap()));
let cache_path = cache_path(&prefix.to_string_lossy())?;
trace!("self_path={:?}", self_path);
trace!("prefix={:?}", prefix);
trace!("cache_path={:?}", cache_path);
if cache_path.exists() && !fs::metadata(&cache_path)?.is_dir() {
return Err(anyhow!("cache at {:?} is not a directory", &cache_path));
} else {
fs::create_dir_all(&cache_path)?;
}
Ok(cache_path)
}
fn clean_cache(cache_folder: &Path, self_path: &Path, args: &Args) -> Result<()> {
if args.uid.is_none() {
let subfolder = cache_folder.join(STATIC_SUBFOLDER_NAME);
if subfolder.exists()
&& fs::metadata(&subfolder)?.modified()? < fs::metadata(self_path)?.modified()?
{
trace!("static cache older than source, removing");
remove_dir_all(subfolder)?;
}
return Ok(());
}
if !args.clean {
return Ok(());
}
let uid = OsStr::new(args.uid.as_ref().unwrap()); // Checked above
let static_folder = OsStr::new(STATIC_SUBFOLDER_NAME);
trace!("cleaning cache");
for entry in fs::read_dir(cache_folder)? {
let entry = entry?;
if entry.file_name() == static_folder {
trace!("skipped static subfolder {:?}", static_folder);
continue;
}
if entry.file_name() == uid {
trace!("skipped own uid {:?}", uid);
continue;
}
trace!("removing entry {:?}", entry);
if let Err(err) = remove_dir_all(entry.path()) {
eprintln!(
"Error while attempting to remove directory {:?}: {err}",
entry.path()
);
}
}
Ok(())
}
fn main() -> Result<(), Box<Error>> {
fn main() -> Result<()> {
if env::var("WARP_TRACE").is_ok() {
simple_logger::init_with_level(Level::Trace)?;
}
let self_path = env::current_exe()?;
let self_file_name = self_path.file_name().unwrap();
let cache_path = cache_path(&self_file_name.to_string_lossy());
let args = get_args(&self_path).unwrap();
trace!("args = {:?}", args);
trace!("self_path={:?}", self_path);
trace!("self_file_name={:?}", self_file_name);
trace!("cache_path={:?}", cache_path);
let cache_path = create_cache_folder(&self_path, &args)?;
clean_cache(&cache_path, &self_path, &args)?;
let target_file_name = target_file_name();
let target_path = cache_path.join(target_file_name);
let subfolder = args.uid.as_deref().unwrap_or(STATIC_SUBFOLDER_NAME);
let cache_path = cache_path.join(subfolder);
trace!("target_exec={:?}", target_file_name);
let target_path = cache_path.join(&args.target_file_name);
trace!("target_exec={:?}", args.target_file_name);
trace!("target_path={:?}", target_path);
match fs::metadata(&cache_path) {
Ok(cache) => {
if cache.modified()? >= fs::metadata(&self_path)?.modified()? {
trace!("cache is up-to-date");
} else {
trace!("cache is outdated");
if !cache_path.exists() {
trace!("cache empty, extracting");
extract(&self_path, &cache_path)?;
}
}
Err(_) => {
trace!("cache not found");
extract(&self_path, &cache_path)?;
}
}
let exit_code = executor::execute(&target_path)?;
process::exit(exit_code);
process::exit(executor::execute(&target_path)?);
}