mirror of
https://gitlab.redox-os.org/redox-os/redox.git
synced 2026-06-17 23:44:17 +08:00
Merge branch 'repo-bin' into 'master'
Repo.sh in Rust with TUI See merge request redox-os/cookbook!601
This commit is contained in:
commit
3710b1dab5
338
Cargo.lock
generated
338
Cargo.lock
generated
@ -52,6 +52,12 @@ dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
@ -67,6 +73,19 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi-to-tui"
|
||||
version = "7.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67555e1f1ece39d737e28c8a017721287753af3f93225e4a445b29ccb0f5912c"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"ratatui",
|
||||
"simdutf8",
|
||||
"smallvec",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
@ -128,9 +147,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "arg_parser"
|
||||
@ -374,6 +393,21 @@ version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "cassowary"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
||||
|
||||
[[package]]
|
||||
name = "castaway"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.29"
|
||||
@ -395,6 +429,12 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
@ -446,7 +486,7 @@ dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags 1.3.2",
|
||||
"strsim",
|
||||
"strsim 0.8.0",
|
||||
"textwrap",
|
||||
"unicode-width 0.1.14",
|
||||
"vec_map",
|
||||
@ -458,6 +498,20 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
|
||||
dependencies = [
|
||||
"castaway",
|
||||
"cfg-if 1.0.1",
|
||||
"itoa",
|
||||
"rustversion",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.11"
|
||||
@ -467,7 +521,7 @@ dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"unicode-width 0.2.1",
|
||||
"unicode-width 0.2.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@ -602,6 +656,41 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.11.1",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.4.0"
|
||||
@ -683,6 +772,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
|
||||
|
||||
[[package]]
|
||||
name = "dryoc"
|
||||
version = "0.6.2"
|
||||
@ -784,6 +879,17 @@ version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||
|
||||
[[package]]
|
||||
name = "filedescriptor"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"thiserror 1.0.69",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.2"
|
||||
@ -974,9 +1080,17 @@ version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
@ -1211,6 +1325,12 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.0.3"
|
||||
@ -1267,10 +1387,19 @@ dependencies = [
|
||||
"console",
|
||||
"number_prefix",
|
||||
"portable-atomic",
|
||||
"unicode-width 0.2.1",
|
||||
"unicode-width 0.2.0",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "2.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
@ -1280,6 +1409,19 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instability"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"indoc",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
@ -1379,6 +1521,15 @@ version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru-slab"
|
||||
version = "0.1.2"
|
||||
@ -1402,6 +1553,12 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
@ -1422,6 +1579,28 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if 1.0.1",
|
||||
"cfg_aliases 0.1.1",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
@ -1500,6 +1679,12 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pbr"
|
||||
version = "1.1.1"
|
||||
@ -1627,6 +1812,27 @@ version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||
|
||||
[[package]]
|
||||
name = "portable-pty"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4a596a2b3d2752d94f51fac2d4a96737b8705dddd311a32b9af47211f08671e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 1.3.2",
|
||||
"downcast-rs",
|
||||
"filedescriptor",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"nix",
|
||||
"serial2",
|
||||
"shared_library",
|
||||
"shell-words",
|
||||
"winapi",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.2"
|
||||
@ -1676,7 +1882,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.2.1",
|
||||
"pin-project-lite",
|
||||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
@ -1716,7 +1922,7 @@ version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.2.1",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2",
|
||||
@ -1804,6 +2010,27 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384c2842d4e069d5ccacf5fe1dca4ef8d07a5444329715f0fc3c61813502d4d1"
|
||||
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"indoc",
|
||||
"instability",
|
||||
"itertools",
|
||||
"lru",
|
||||
"paste",
|
||||
"strum",
|
||||
"termion",
|
||||
"unicode-segmentation",
|
||||
"unicode-truncate",
|
||||
"unicode-width 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
@ -1863,13 +2090,19 @@ dependencies = [
|
||||
name = "redox_cookbook"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ansi-to-tui",
|
||||
"anyhow",
|
||||
"blake3 1.5.3",
|
||||
"filedescriptor",
|
||||
"ignore",
|
||||
"libc",
|
||||
"object",
|
||||
"pbr",
|
||||
"pkgar 0.1.19",
|
||||
"pkgar-core 0.1.19",
|
||||
"pkgar-keys 0.1.19",
|
||||
"portable-pty",
|
||||
"ratatui",
|
||||
"redox-pkg",
|
||||
"redoxer",
|
||||
"regex",
|
||||
@ -2290,6 +2523,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial2"
|
||||
version = "0.2.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cc76fa68e25e771492ca1e3c53d447ef0be3093e05cd3b47f4b712ba10c6f3c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.1",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
@ -2301,12 +2545,34 @@ dependencies = [
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_library"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shell-words"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
@ -2356,6 +2622,34 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
@ -2723,6 +3017,23 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-truncate"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"unicode-segmentation",
|
||||
"unicode-width 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
@ -2731,9 +3042,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
|
||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
@ -3256,6 +3567,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
|
||||
12
Cargo.toml
12
Cargo.toml
@ -3,7 +3,7 @@ name = "redox_cookbook"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
edition = "2024"
|
||||
default-run = "cook"
|
||||
default-run = "repo"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -21,13 +21,16 @@ path = "src/lib.rs"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
blake3 = "=1.5.3" # 1.5.4 is incompatible with blake3 0.3 dependency from pkgar
|
||||
libc = "0.2"
|
||||
ignore = "0.4"
|
||||
object = { version = "0.36", features = ["build_core"] }
|
||||
pbr = "1.0.2"
|
||||
pkgar = { path = "pkgar/pkgar" }
|
||||
pkgar-core = { path = "pkgar/pkgar-core" }
|
||||
pkgar-keys = { path = "pkgar/pkgar-keys" }
|
||||
portable-pty = "0.9.0"
|
||||
redox-pkg = "0.2.8"
|
||||
redoxer = "0.2"
|
||||
regex = "1.11"
|
||||
@ -35,6 +38,13 @@ serde = { version = "=1.0.197", features = ["derive"] }
|
||||
termion = "4"
|
||||
toml = "0.8"
|
||||
walkdir = "2.3.1"
|
||||
filedescriptor = "0.8.3"
|
||||
ansi-to-tui = "7.0.0"
|
||||
|
||||
[dependencies.ratatui]
|
||||
version = "0.29.0"
|
||||
default-features = false
|
||||
features = ["termion"]
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
11
README.md
11
README.md
@ -29,7 +29,16 @@ Cookbook has special config to avoid repetitive args, place this file into `cook
|
||||
```toml
|
||||
# Configuration file
|
||||
# This is a configuration file to avoid repetitively spelling command args.
|
||||
# At the moment only mirrors here implemented but in future it will be expanded when scripts are rusted
|
||||
# At the moment this configures mirror and cook configuration
|
||||
|
||||
# These options has defaults set below
|
||||
# These options has higher priority than env
|
||||
#[cook]
|
||||
#jobs = <nproc>
|
||||
#nonstop = false
|
||||
#offline = false
|
||||
#tui = true
|
||||
#verbose = true
|
||||
|
||||
[mirrors]
|
||||
# see list of GNU FTP mirrors at https://www.gnu.org/prep/ftp.en.html
|
||||
|
||||
12
clean.sh
12
clean.sh
@ -1,19 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
source config.sh
|
||||
source `dirname "$0"`/config.sh
|
||||
|
||||
if [ $# = 0 ]
|
||||
then
|
||||
recipes="$(list_recipes --short)"
|
||||
recipes="--all"
|
||||
else
|
||||
recipes="$@"
|
||||
fi
|
||||
|
||||
for recipe_name in $recipes
|
||||
do
|
||||
recipe_path=`find_recipe $recipe_name`
|
||||
|
||||
echo -e "\033[01;38;5;215mcook - clean $recipe_name\033[0m"
|
||||
rm -rf "${ROOT}/$recipe_path/target/${TARGET}"
|
||||
done
|
||||
repo clean $recipes
|
||||
|
||||
@ -17,8 +17,11 @@ if [ x"${HOST}" == x"riscv64gc-unknown-redox" ] ; then
|
||||
HOST="riscv64-unknown-redox"
|
||||
fi
|
||||
|
||||
# Cookbook requires correct CWD to work
|
||||
cd `dirname "$0"`
|
||||
|
||||
# Automatic variables
|
||||
ROOT="$(cd `dirname "$0"` && pwd)"
|
||||
ROOT=`pwd`
|
||||
|
||||
export AR="${HOST}-gcc-ar"
|
||||
export AS="${HOST}-as"
|
||||
@ -60,6 +63,9 @@ function pkgar {
|
||||
function cook {
|
||||
"$ROOT/target/release/cook" "$@"
|
||||
}
|
||||
function repo {
|
||||
"$ROOT/target/release/repo" "$@"
|
||||
}
|
||||
function repo_builder {
|
||||
"$ROOT/target/release/repo_builder" "$@"
|
||||
}
|
||||
|
||||
4
fetch.sh
4
fetch.sh
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
source config.sh
|
||||
source `dirname "$0"`/config.sh
|
||||
|
||||
cook --fetch-only ${@:1}
|
||||
# Intentionally empty to allow fetch and cook running in parallel
|
||||
|
||||
12
repo.sh
12
repo.sh
@ -1,8 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
|
||||
source config.sh
|
||||
source `dirname "$0"`/config.sh
|
||||
|
||||
APPSTREAM="0"
|
||||
COOK_OPT=""
|
||||
@ -20,15 +19,12 @@ do
|
||||
COOK_OPT+=" --nonstop"
|
||||
elif [ "$arg" == "--offline" ]
|
||||
then
|
||||
COOK_OPT+=" --offline"
|
||||
export COOKBOOK_OFFLINE=true
|
||||
else
|
||||
recipes+=" $arg"
|
||||
fi
|
||||
done
|
||||
|
||||
cook $COOK_OPT $recipes
|
||||
repo cook $COOK_OPT $recipes
|
||||
|
||||
repo="$ROOT/repo/$TARGET"
|
||||
mkdir -p "$repo"
|
||||
|
||||
repo_builder "$repo" $recipes
|
||||
repo_builder "$ROOT/repo/$TARGET" $recipes
|
||||
|
||||
@ -1,36 +1,17 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::Path;
|
||||
use std::{env, process};
|
||||
|
||||
use cookbook::WALK_DEPTH;
|
||||
use cookbook::cook::fetch::{fetch, fetch_offline};
|
||||
use cookbook::cook::fs::create_target_dir;
|
||||
use cookbook::cook::package::{package, package_toml};
|
||||
use cookbook::recipe::{BuildKind, CookRecipe, Recipe};
|
||||
use cookbook::cook::package::package;
|
||||
use cookbook::recipe::{CookRecipe, Recipe};
|
||||
use pkg::PackageName;
|
||||
|
||||
use cookbook::config::init_config;
|
||||
use cookbook::cook::cook_build::build;
|
||||
use termion::{color, style};
|
||||
|
||||
fn cook_meta(
|
||||
recipe_dir: &Path,
|
||||
name: &PackageName,
|
||||
recipe: &Recipe,
|
||||
fetch_only: bool,
|
||||
) -> Result<(), String> {
|
||||
if fetch_only {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let target_dir = create_target_dir(recipe_dir)?;
|
||||
let empty_deps = BTreeSet::new();
|
||||
let _package_file = package_toml(&target_dir, name, recipe, &empty_deps)
|
||||
.map_err(|err| format!("failed to package: {}", err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cook(
|
||||
recipe_dir: &Path,
|
||||
name: &PackageName,
|
||||
@ -39,12 +20,9 @@ fn cook(
|
||||
fetch_only: bool,
|
||||
is_offline: bool,
|
||||
) -> Result<(), String> {
|
||||
if recipe.build.kind == BuildKind::None {
|
||||
return cook_meta(recipe_dir, name, recipe, fetch_only);
|
||||
}
|
||||
let source_dir = match is_offline {
|
||||
true => fetch_offline(recipe_dir, &recipe.source),
|
||||
false => fetch(recipe_dir, &recipe.source),
|
||||
true => fetch_offline(recipe_dir, recipe, &None),
|
||||
false => fetch(recipe_dir, recipe, &None),
|
||||
}
|
||||
.map_err(|err| format!("failed to fetch: {}", err))?;
|
||||
|
||||
@ -62,10 +40,11 @@ fn cook(
|
||||
recipe,
|
||||
is_offline,
|
||||
!is_deps,
|
||||
&None,
|
||||
)
|
||||
.map_err(|err| format!("failed to build: {}", err))?;
|
||||
|
||||
let _package_file = package(&stage_dir, &target_dir, name, recipe, &auto_deps)
|
||||
package(&stage_dir, &target_dir, name, recipe, &auto_deps, &None)
|
||||
.map_err(|err| format!("failed to package: {}", err))?;
|
||||
|
||||
Ok(())
|
||||
|
||||
1351
src/bin/repo.rs
Normal file
1351
src/bin/repo.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.next()
|
||||
.expect("Usage: repo_builder <REPO_DIR> <recipe1> <recipe2> ...");
|
||||
let repo_path = Path::new(&repo_dir);
|
||||
if !repo_path.is_dir() {
|
||||
fs::create_dir_all(repo_path)?;
|
||||
}
|
||||
|
||||
// Runtime dependencies include both `[package.dependencies]` and dynamically
|
||||
// linked packages discovered by auto_deps.
|
||||
|
||||
@ -1,16 +1,59 @@
|
||||
use std::{collections::HashMap, fs, sync::OnceLock};
|
||||
use std::{collections::HashMap, env, fs, str::FromStr, sync::OnceLock};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct CookConfigOpt {
|
||||
/// whether to run offline
|
||||
pub offline: Option<bool>,
|
||||
/// whether to set jobs number instead of from nproc
|
||||
pub jobs: Option<usize>,
|
||||
/// whether to use TUI to allow parallel build
|
||||
/// default value is yes if "CI" env unset and STDIN is open.
|
||||
pub tui: Option<bool>,
|
||||
/// whether to ignore build errors
|
||||
pub nonstop: Option<bool>,
|
||||
/// whether to print success recipes info and warnings
|
||||
/// build failure still be printed anyway
|
||||
pub verbose: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
|
||||
pub struct CookConfig {
|
||||
pub offline: bool,
|
||||
pub jobs: usize,
|
||||
pub tui: bool,
|
||||
pub nonstop: bool,
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
impl From<CookConfigOpt> for CookConfig {
|
||||
fn from(value: CookConfigOpt) -> Self {
|
||||
CookConfig {
|
||||
offline: value.offline.unwrap(),
|
||||
jobs: value.jobs.unwrap(),
|
||||
tui: value.tui.unwrap(),
|
||||
nonstop: value.nonstop.unwrap(),
|
||||
verbose: value.verbose.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct CookbookConfig {
|
||||
#[serde(rename = "cook")]
|
||||
cook_opt: CookConfigOpt,
|
||||
#[serde(skip)]
|
||||
pub cook: CookConfig,
|
||||
pub mirrors: HashMap<String, String>,
|
||||
}
|
||||
|
||||
static CONFIG: OnceLock<CookbookConfig> = OnceLock::new();
|
||||
|
||||
pub fn init_config() {
|
||||
let config: CookbookConfig = if fs::exists("cookbook.toml").unwrap_or(false) {
|
||||
let mut config: CookbookConfig = if fs::exists("cookbook.toml").unwrap_or(false) {
|
||||
let toml_content = fs::read_to_string("cookbook.toml")
|
||||
.map_err(|e| format!("Unable to read config: {:?}", e))
|
||||
.unwrap();
|
||||
@ -21,9 +64,44 @@ pub fn init_config() {
|
||||
CookbookConfig::default()
|
||||
};
|
||||
|
||||
if config.cook_opt.tui.is_none() {
|
||||
config.cook_opt.tui = Some(!env::var("CI").is_ok_and(|s| !s.is_empty()));
|
||||
}
|
||||
if config.cook_opt.jobs.is_none() {
|
||||
config.cook_opt.jobs = Some(extract_env(
|
||||
"COOKBOOK_MAKE_JOBS",
|
||||
std::thread::available_parallelism()
|
||||
.map(|f| usize::from(f))
|
||||
.unwrap_or(1),
|
||||
));
|
||||
}
|
||||
if config.cook_opt.offline.is_none() {
|
||||
config.cook_opt.offline = Some(extract_env("COOKBOOK_OFFLINE", false));
|
||||
}
|
||||
if config.cook_opt.verbose.is_none() {
|
||||
config.cook_opt.verbose = Some(extract_env("COOKBOOK_VERBOSE", true));
|
||||
}
|
||||
if config.cook_opt.nonstop.is_none() {
|
||||
config.cook_opt.nonstop = Some(extract_env("COOKBOOK_NONSTOP", false));
|
||||
}
|
||||
|
||||
config.cook = CookConfig::from(config.cook_opt.clone());
|
||||
|
||||
CONFIG.set(config).expect("config is initialized twice");
|
||||
}
|
||||
|
||||
fn extract_env<T: FromStr>(key: &str, default: T) -> T {
|
||||
if let Ok(e) = env::var(&key) {
|
||||
str::parse(&e).unwrap_or(default)
|
||||
} else {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_config() -> &'static CookbookConfig {
|
||||
return CONFIG.get().expect("Configuration is not initialized");
|
||||
}
|
||||
|
||||
pub fn translate_mirror(original_url: &str) -> String {
|
||||
let config = CONFIG.get().expect("Configuration is not initialized");
|
||||
|
||||
@ -75,6 +153,17 @@ mod tests {
|
||||
let _ = CONFIG.set(app_config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_cook() {
|
||||
let app_config: CookbookConfig = toml::from_str(
|
||||
"[cook]\n\
|
||||
offline = true\n",
|
||||
)
|
||||
.expect("Unable to parse test config");
|
||||
assert_eq!(app_config.cook_opt.offline, Some(true));
|
||||
assert_eq!(app_config.cook_opt.jobs, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exact_match() {
|
||||
setup_test_config();
|
||||
|
||||
@ -3,4 +3,5 @@ pub mod cook_build;
|
||||
pub mod fetch;
|
||||
pub mod fs;
|
||||
pub mod package;
|
||||
pub mod pty;
|
||||
pub mod script;
|
||||
|
||||
@ -3,6 +3,7 @@ use pkg::{Package, PackageName};
|
||||
use redoxer::target;
|
||||
|
||||
use crate::cook::fs::*;
|
||||
use crate::cook::pty::PtyOut;
|
||||
use crate::cook::script::*;
|
||||
use crate::recipe::AutoDeps;
|
||||
use crate::recipe::BuildKind;
|
||||
@ -21,9 +22,25 @@ use crate::is_redox;
|
||||
|
||||
use crate::REMOTE_PKG_SOURCE;
|
||||
|
||||
macro_rules! log_warn {
|
||||
($logger:expr, $($arg:tt)+) => {
|
||||
use std::io::Write;
|
||||
|
||||
if $logger.is_some() {
|
||||
let _ = $logger.as_ref().unwrap().1.try_clone().unwrap().write(
|
||||
format!($($arg)+)
|
||||
.as_bytes(),
|
||||
);
|
||||
} else {
|
||||
eprintln!($($arg)+);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn auto_deps(
|
||||
stage_dir: &Path,
|
||||
dep_pkgars: &BTreeSet<(PackageName, PathBuf)>,
|
||||
logger: &PtyOut,
|
||||
) -> BTreeSet<PackageName> {
|
||||
let mut paths = BTreeSet::new();
|
||||
let mut visited = BTreeSet::new();
|
||||
@ -43,7 +60,10 @@ fn auto_deps(
|
||||
};
|
||||
if visited.contains(&dir) {
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("DEBUG: auto_deps => Skipping `{dir:?}` (already visited)");
|
||||
log_warn!(
|
||||
logger,
|
||||
"DEBUG: auto_deps => Skipping `{dir:?}` (already visited)"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
assert!(
|
||||
@ -90,7 +110,7 @@ fn auto_deps(
|
||||
continue;
|
||||
};
|
||||
if let Ok(relative_path) = path.strip_prefix(stage_dir) {
|
||||
eprintln!("DEBUG: {} needs {}", relative_path.display(), name);
|
||||
log_warn!(logger, "DEBUG: {} needs {}", relative_path.display(), name);
|
||||
}
|
||||
needed.insert(name.to_string());
|
||||
}
|
||||
@ -124,7 +144,7 @@ fn auto_deps(
|
||||
continue;
|
||||
};
|
||||
if needed.contains(child_name) {
|
||||
eprintln!("DEBUG: {} provides {}", dep, child_name);
|
||||
log_warn!(logger, "DEBUG: {} provides {}", dep, child_name);
|
||||
deps.insert(dep.clone());
|
||||
missing.remove(child_name);
|
||||
}
|
||||
@ -134,7 +154,7 @@ fn auto_deps(
|
||||
}
|
||||
|
||||
for name in missing {
|
||||
eprintln!("WARN: {} missing", name);
|
||||
log_warn!(logger, "WARN: {} missing", name);
|
||||
}
|
||||
|
||||
deps
|
||||
@ -148,9 +168,14 @@ pub fn build(
|
||||
recipe: &Recipe,
|
||||
offline_mode: bool,
|
||||
check_source: bool,
|
||||
logger: &PtyOut,
|
||||
) -> Result<(PathBuf, BTreeSet<PackageName>), String> {
|
||||
let sysroot_dir = target_dir.join("sysroot");
|
||||
let stage_dir = target_dir.join("stage");
|
||||
if recipe.build.kind == BuildKind::None {
|
||||
// metapackages don't need to do anything here
|
||||
return Ok((stage_dir, BTreeSet::new()));
|
||||
}
|
||||
|
||||
let mut dep_pkgars = BTreeSet::new();
|
||||
for dependency in recipe.build.dependencies.iter() {
|
||||
@ -169,7 +194,7 @@ pub fn build(
|
||||
}
|
||||
|
||||
if stage_dir.exists() && !check_source {
|
||||
let auto_deps = build_auto_deps(target_dir, &stage_dir, dep_pkgars)?;
|
||||
let auto_deps = build_auto_deps(target_dir, &stage_dir, dep_pkgars, logger)?;
|
||||
return Ok((stage_dir, auto_deps));
|
||||
}
|
||||
|
||||
@ -185,7 +210,8 @@ pub fn build(
|
||||
if sysroot_dir.is_dir() {
|
||||
let sysroot_modified = modified_dir(&sysroot_dir)?;
|
||||
if sysroot_modified < source_modified || sysroot_modified < deps_modified {
|
||||
eprintln!(
|
||||
log_warn!(
|
||||
logger,
|
||||
"DEBUG: '{}' newer than '{}'",
|
||||
source_dir.display(),
|
||||
sysroot_dir.display()
|
||||
@ -234,7 +260,8 @@ pub fn build(
|
||||
if stage_dir.is_dir() {
|
||||
let stage_modified = modified_dir(&stage_dir)?;
|
||||
if stage_modified < source_modified || stage_modified < deps_modified {
|
||||
eprintln!(
|
||||
log_warn!(
|
||||
logger,
|
||||
"DEBUG: '{}' newer than '{}'",
|
||||
source_dir.display(),
|
||||
stage_dir.display()
|
||||
@ -292,7 +319,7 @@ pub fn build(
|
||||
flags_fn("COOKBOOK_MESON_FLAGS", mesonflags),
|
||||
),
|
||||
BuildKind::Custom { script } => script.clone(),
|
||||
BuildKind::Remote => return build_remote(target_dir, name, offline_mode),
|
||||
BuildKind::Remote => return build_remote(target_dir, name, offline_mode, logger),
|
||||
BuildKind::None => "".to_owned(),
|
||||
};
|
||||
|
||||
@ -313,7 +340,7 @@ pub fn build(
|
||||
} else {
|
||||
let cookbook_redoxer = Path::new("target/release/cookbook_redoxer")
|
||||
.canonicalize()
|
||||
.unwrap();
|
||||
.unwrap_or(PathBuf::from("/bin/false"));
|
||||
let mut command = Command::new(&cookbook_redoxer);
|
||||
command.arg("env").arg("bash").arg("-ex");
|
||||
command.env("COOKBOOK_REDOXER", &cookbook_redoxer);
|
||||
@ -337,13 +364,13 @@ pub fn build(
|
||||
"{}\n{}\n{}\n{}",
|
||||
BUILD_PRESCRIPT, SHARED_PRESCRIPT, script, BUILD_POSTSCRIPT
|
||||
);
|
||||
run_command_stdin(command, full_script.as_bytes())?;
|
||||
run_command_stdin(command, full_script.as_bytes(), logger)?;
|
||||
|
||||
// Move stage.tmp to stage atomically
|
||||
rename(&stage_dir_tmp, &stage_dir)?;
|
||||
}
|
||||
|
||||
let auto_deps = build_auto_deps(target_dir, &stage_dir, dep_pkgars)?;
|
||||
let auto_deps = build_auto_deps(target_dir, &stage_dir, dep_pkgars, logger)?;
|
||||
|
||||
Ok((stage_dir, auto_deps))
|
||||
}
|
||||
@ -353,6 +380,7 @@ fn build_auto_deps(
|
||||
target_dir: &Path,
|
||||
stage_dir: &PathBuf,
|
||||
dep_pkgars: BTreeSet<(PackageName, PathBuf)>,
|
||||
logger: &PtyOut,
|
||||
) -> Result<BTreeSet<PackageName>, String> {
|
||||
let auto_deps_path = target_dir.join("auto_deps.toml");
|
||||
if auto_deps_path.is_file() && modified(&auto_deps_path)? < modified(stage_dir)? {
|
||||
@ -366,7 +394,7 @@ fn build_auto_deps(
|
||||
toml::from_str(&toml_content).map_err(|_| "failed to deserialize cached auto_deps")?;
|
||||
wrapper.packages
|
||||
} else {
|
||||
let packages = auto_deps(stage_dir, &dep_pkgars);
|
||||
let packages = auto_deps(stage_dir, &dep_pkgars, logger);
|
||||
let wrapper = AutoDeps { packages };
|
||||
serialize_and_write(&auto_deps_path, &wrapper)?;
|
||||
wrapper.packages
|
||||
@ -385,6 +413,7 @@ pub fn build_remote(
|
||||
target_dir: &Path,
|
||||
name: &PackageName,
|
||||
offline_mode: bool,
|
||||
logger: &PtyOut,
|
||||
) -> Result<(PathBuf, BTreeSet<PackageName>), String> {
|
||||
// download straight from remote source then declare pkg dependencies as autodeps dependency
|
||||
let stage_dir = target_dir.join("stage");
|
||||
@ -394,9 +423,9 @@ pub fn build_remote(
|
||||
let source_pubkey = target_dir.join("id_ed25519.pub.toml");
|
||||
|
||||
if !offline_mode {
|
||||
download_wget(&get_remote_url(name, "pkgar"), &source_pkgar)?;
|
||||
download_wget(&get_remote_url(name, "toml"), &source_toml)?;
|
||||
download_wget(&get_pubkey_url(), &source_pubkey)?;
|
||||
download_wget(&get_remote_url(name, "pkgar"), &source_pkgar, logger)?;
|
||||
download_wget(&get_remote_url(name, "toml"), &source_toml, logger)?;
|
||||
download_wget(&get_pubkey_url(), &source_pubkey, logger)?;
|
||||
} else {
|
||||
offline_check_exists(&source_pkgar)?;
|
||||
offline_check_exists(&source_toml)?;
|
||||
@ -469,7 +498,7 @@ mod tests {
|
||||
"Expected a loop where {dir:?} points to {root:?}"
|
||||
);
|
||||
|
||||
let entries = auto_deps(root, &Default::default());
|
||||
let entries = auto_deps(root, &Default::default(), &None);
|
||||
assert!(
|
||||
entries.is_empty(),
|
||||
"auto_deps shouldn't have yielded any libraries"
|
||||
|
||||
@ -1,13 +1,30 @@
|
||||
use crate::config::translate_mirror;
|
||||
use crate::cook::fs::*;
|
||||
use crate::cook::pty::PtyOut;
|
||||
use crate::cook::script::*;
|
||||
use crate::is_redox;
|
||||
use crate::recipe::BuildKind;
|
||||
use crate::recipe::Recipe;
|
||||
use crate::{blake3, recipe::SourceRecipe};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
macro_rules! log_warn {
|
||||
($logger:expr, $($arg:tt)+) => {
|
||||
use std::io::Write;
|
||||
|
||||
if $logger.is_some() {
|
||||
let _ = $logger.as_ref().unwrap().1.try_clone().unwrap().write(
|
||||
format!($($arg)+)
|
||||
.as_bytes(),
|
||||
);
|
||||
} else {
|
||||
eprintln!($($arg)+);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn get_blake3(path: &PathBuf, show_progress: bool) -> Result<String, String> {
|
||||
if show_progress {
|
||||
blake3::blake3_progress(&path)
|
||||
@ -24,14 +41,22 @@ pub(crate) fn get_blake3(path: &PathBuf, show_progress: bool) -> Result<String,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fetch_offline(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf, String> {
|
||||
pub fn fetch_offline(
|
||||
recipe_dir: &Path,
|
||||
recipe: &Recipe,
|
||||
logger: &PtyOut,
|
||||
) -> Result<PathBuf, String> {
|
||||
let source_dir = recipe_dir.join("source");
|
||||
match source {
|
||||
if recipe.build.kind == BuildKind::None || recipe.build.kind == BuildKind::Remote {
|
||||
// the build function doesn't need source dir exists
|
||||
return Ok(source_dir);
|
||||
}
|
||||
match &recipe.source {
|
||||
Some(SourceRecipe::Path { path: _ }) | None => {
|
||||
return fetch(recipe_dir, source);
|
||||
return fetch(recipe_dir, recipe, logger);
|
||||
}
|
||||
Some(SourceRecipe::SameAs { same_as: _ }) => {
|
||||
return fetch(recipe_dir, source);
|
||||
return fetch(recipe_dir, recipe, logger);
|
||||
}
|
||||
Some(SourceRecipe::Git {
|
||||
git: _,
|
||||
@ -52,7 +77,7 @@ pub fn fetch_offline(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result
|
||||
}) => {
|
||||
if !source_dir.is_dir() {
|
||||
let source_tar = recipe_dir.join("source.tar");
|
||||
let source_tar_blake3 = get_blake3(&source_tar, true)?;
|
||||
let source_tar_blake3 = get_blake3(&source_tar, true && logger.is_none())?;
|
||||
if source_tar.exists() {
|
||||
if let Some(blake3) = blake3 {
|
||||
if source_tar_blake3 != *blake3 {
|
||||
@ -60,8 +85,8 @@ pub fn fetch_offline(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result
|
||||
"The downloaded tar blake3 '{source_tar_blake3}' is not equal to blake3 in recipe.toml."
|
||||
));
|
||||
}
|
||||
fetch_extract_tar(source_tar, &source_dir)?;
|
||||
fetch_apply_patches(recipe_dir, patches, script, &source_dir)?;
|
||||
fetch_extract_tar(source_tar, &source_dir, logger)?;
|
||||
fetch_apply_patches(recipe_dir, patches, script, &source_dir, logger)?;
|
||||
} else {
|
||||
// need to trust this tar file
|
||||
return Err(format!(
|
||||
@ -79,18 +104,28 @@ pub fn fetch_offline(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result
|
||||
Ok(source_dir)
|
||||
}
|
||||
|
||||
pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf, String> {
|
||||
pub fn fetch(recipe_dir: &Path, recipe: &Recipe, logger: &PtyOut) -> Result<PathBuf, String> {
|
||||
let source_dir = recipe_dir.join("source");
|
||||
match source {
|
||||
if recipe.build.kind == BuildKind::None || recipe.build.kind == BuildKind::Remote {
|
||||
// the build function doesn't need source dir exists
|
||||
return Ok(source_dir);
|
||||
}
|
||||
match &recipe.source {
|
||||
Some(SourceRecipe::SameAs { same_as }) => {
|
||||
let (canon_dir, recipe) = fetch_resolve_canon(recipe_dir, same_as)?;
|
||||
let (canon_dir, recipe) = fetch_resolve_canon(recipe_dir, &same_as)?;
|
||||
// recursively fetch
|
||||
fetch(&canon_dir, &recipe.source)?;
|
||||
fetch_make_symlink(&source_dir, same_as)?;
|
||||
fetch(&canon_dir, &recipe, logger)?;
|
||||
fetch_make_symlink(&source_dir, &same_as)?;
|
||||
}
|
||||
Some(SourceRecipe::Path { path }) => {
|
||||
if !source_dir.is_dir() || modified_dir(Path::new(path))? > modified_dir(&source_dir)? {
|
||||
eprintln!("[DEBUG]: {} is newer than {}", path, source_dir.display());
|
||||
if !source_dir.is_dir() || modified_dir(Path::new(&path))? > modified_dir(&source_dir)?
|
||||
{
|
||||
log_warn!(
|
||||
logger,
|
||||
"[DEBUG]: {} is newer than {}",
|
||||
path,
|
||||
source_dir.display()
|
||||
);
|
||||
copy_dir_all(path, &source_dir).map_err(|e| {
|
||||
format!(
|
||||
"Couldn't copy source from {} to {}: {}",
|
||||
@ -122,7 +157,7 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
command
|
||||
.arg("clone")
|
||||
.arg("--recursive")
|
||||
.arg(translate_mirror(git));
|
||||
.arg(translate_mirror(&git));
|
||||
if let Some(branch) = branch {
|
||||
command.arg("--branch").arg(branch);
|
||||
}
|
||||
@ -130,7 +165,7 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
command.arg("--depth").arg("1").arg("--shallow-submodules");
|
||||
}
|
||||
command.arg(&source_dir_tmp);
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
|
||||
// Move source.tmp to source atomically
|
||||
rename(&source_dir_tmp, &source_dir)?;
|
||||
@ -148,13 +183,13 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
let mut command = Command::new("git");
|
||||
command.arg("-C").arg(&source_dir);
|
||||
command.arg("remote").arg("set-url").arg("origin").arg(git);
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
|
||||
// Fetch origin
|
||||
let mut command = Command::new("git");
|
||||
command.arg("-C").arg(&source_dir);
|
||||
command.arg("fetch").arg("origin");
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
}
|
||||
|
||||
if let Some(_upstream) = upstream {
|
||||
@ -169,7 +204,7 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
let mut command = Command::new("git");
|
||||
command.arg("-C").arg(&source_dir);
|
||||
command.arg("checkout").arg(rev);
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
} else if !shallow_clone && !is_redox() {
|
||||
//TODO: complicated stuff to check and reset branch to origin
|
||||
//TODO: redox can't undestand this (got exit status 1)
|
||||
@ -179,7 +214,7 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
command.env("BRANCH", branch);
|
||||
}
|
||||
command.current_dir(&source_dir);
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
}
|
||||
|
||||
if !patches.is_empty() || script.is_some() {
|
||||
@ -187,7 +222,7 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
let mut command = Command::new("git");
|
||||
command.arg("-C").arg(&source_dir);
|
||||
command.arg("reset").arg("--hard");
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
}
|
||||
|
||||
if !shallow_clone {
|
||||
@ -195,7 +230,7 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
let mut command = Command::new("git");
|
||||
command.arg("-C").arg(&source_dir);
|
||||
command.arg("submodule").arg("sync").arg("--recursive");
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
|
||||
// Update submodules
|
||||
let mut command = Command::new("git");
|
||||
@ -205,10 +240,10 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
.arg("update")
|
||||
.arg("--init")
|
||||
.arg("--recursive");
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
}
|
||||
|
||||
fetch_apply_patches(recipe_dir, patches, script, &source_dir)?;
|
||||
fetch_apply_patches(recipe_dir, patches, script, &source_dir, logger)?;
|
||||
}
|
||||
Some(SourceRecipe::Tar {
|
||||
tar,
|
||||
@ -221,9 +256,9 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
while {
|
||||
if !source_tar.is_file() {
|
||||
tar_updated = true;
|
||||
download_wget(&tar, &source_tar)?;
|
||||
download_wget(&tar, &source_tar, logger)?;
|
||||
}
|
||||
let source_tar_blake3 = get_blake3(&source_tar, tar_updated)?;
|
||||
let source_tar_blake3 = get_blake3(&source_tar, tar_updated && logger.is_none())?;
|
||||
if let Some(blake3) = blake3 {
|
||||
if source_tar_blake3 != *blake3 {
|
||||
if tar_updated {
|
||||
@ -231,7 +266,10 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
"The downloaded tar blake3 '{source_tar_blake3}' is not equal to blake3 in recipe.toml"
|
||||
));
|
||||
} else {
|
||||
eprintln!("DEBUG: source tar blake3 is different and need redownload");
|
||||
log_warn!(
|
||||
logger,
|
||||
"DEBUG: source tar blake3 is different and need redownload"
|
||||
);
|
||||
remove_all(&source_tar)?;
|
||||
}
|
||||
true
|
||||
@ -240,7 +278,8 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
}
|
||||
} else {
|
||||
//TODO: set blake3 hash on the recipe with something like "cook fix"
|
||||
eprintln!(
|
||||
log_warn!(
|
||||
logger,
|
||||
"WARNING: set blake3 for '{}' to '{}'",
|
||||
source_tar.display(),
|
||||
source_tar_blake3
|
||||
@ -250,7 +289,10 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
} {}
|
||||
if source_dir.is_dir() {
|
||||
if tar_updated || fetch_is_patches_newer(recipe_dir, patches, &source_dir)? {
|
||||
eprintln!("DEBUG: source tar or patches is newer than the source directory");
|
||||
log_warn!(
|
||||
logger,
|
||||
"DEBUG: source tar or patches is newer than the source directory"
|
||||
);
|
||||
remove_all(&source_dir)?
|
||||
}
|
||||
}
|
||||
@ -258,8 +300,8 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
// Create source.tmp
|
||||
let source_dir_tmp = recipe_dir.join("source.tmp");
|
||||
create_dir_clean(&source_dir_tmp)?;
|
||||
fetch_extract_tar(source_tar, &source_dir_tmp)?;
|
||||
fetch_apply_patches(recipe_dir, patches, script, &source_dir_tmp)?;
|
||||
fetch_extract_tar(source_tar, &source_dir_tmp, logger)?;
|
||||
fetch_apply_patches(recipe_dir, patches, script, &source_dir_tmp, logger)?;
|
||||
|
||||
// Move source.tmp to source atomically
|
||||
rename(&source_dir_tmp, &source_dir)?;
|
||||
@ -268,8 +310,8 @@ pub fn fetch(recipe_dir: &Path, source: &Option<SourceRecipe>) -> Result<PathBuf
|
||||
// Local Sources
|
||||
None => {
|
||||
if !source_dir.is_dir() {
|
||||
//TODO: Don't print if build template is none or remote
|
||||
eprintln!(
|
||||
log_warn!(
|
||||
logger,
|
||||
"WARNING: Recipe without source section expected source dir at '{}'",
|
||||
source_dir.display(),
|
||||
);
|
||||
@ -333,6 +375,7 @@ pub(crate) fn fetch_resolve_canon(
|
||||
pub(crate) fn fetch_extract_tar(
|
||||
source_tar: PathBuf,
|
||||
source_dir_tmp: &PathBuf,
|
||||
logger: &PtyOut,
|
||||
) -> Result<(), String> {
|
||||
let mut command = Command::new("tar");
|
||||
if is_redox() {
|
||||
@ -345,7 +388,7 @@ pub(crate) fn fetch_extract_tar(
|
||||
command.arg(&source_tar);
|
||||
command.arg("--directory").arg(source_dir_tmp);
|
||||
command.arg("--strip-components").arg("1");
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -378,6 +421,7 @@ pub(crate) fn fetch_apply_patches(
|
||||
patches: &Vec<String>,
|
||||
script: &Option<String>,
|
||||
source_dir_tmp: &PathBuf,
|
||||
logger: &PtyOut,
|
||||
) -> Result<(), String> {
|
||||
for patch_name in patches {
|
||||
let patch_file = recipe_dir.join(patch_name);
|
||||
@ -400,12 +444,16 @@ pub(crate) fn fetch_apply_patches(
|
||||
let mut command = Command::new("patch");
|
||||
command.arg("--directory").arg(source_dir_tmp);
|
||||
command.arg("--strip=1");
|
||||
run_command_stdin(command, patch.as_bytes())?;
|
||||
run_command_stdin(command, patch.as_bytes(), logger)?;
|
||||
}
|
||||
Ok(if let Some(script) = script {
|
||||
let mut command = Command::new("bash");
|
||||
command.arg("-ex");
|
||||
command.current_dir(source_dir_tmp);
|
||||
run_command_stdin(command, format!("{SHARED_PRESCRIPT}\n{script}").as_bytes())?;
|
||||
run_command_stdin(
|
||||
command,
|
||||
format!("{SHARED_PRESCRIPT}\n{script}").as_bytes(),
|
||||
logger,
|
||||
)?;
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,7 +8,10 @@ use std::{
|
||||
};
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
use crate::config::translate_mirror;
|
||||
use crate::{
|
||||
config::translate_mirror,
|
||||
cook::pty::{PtyOut, spawn_to_pipe},
|
||||
};
|
||||
|
||||
//TODO: pub(crate) for all of these functions
|
||||
|
||||
@ -146,9 +149,10 @@ pub fn rename(src: &Path, dst: &Path) -> Result<(), String> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_command(mut command: process::Command) -> Result<(), String> {
|
||||
let status = command
|
||||
.status()
|
||||
pub fn run_command(mut command: process::Command, stdout_pipe: &PtyOut) -> Result<(), String> {
|
||||
let status = spawn_to_pipe(&mut command, stdout_pipe)
|
||||
.map_err(|err| format!("failed to run {:?}: {}\n{:#?}", command, err, err))?
|
||||
.wait()
|
||||
.map_err(|err| format!("failed to run {:?}: {}\n{:#?}", command, err, err))?;
|
||||
|
||||
if !status.success() {
|
||||
@ -161,11 +165,13 @@ pub fn run_command(mut command: process::Command) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_command_stdin(mut command: process::Command, stdin_data: &[u8]) -> Result<(), String> {
|
||||
pub fn run_command_stdin(
|
||||
mut command: process::Command,
|
||||
stdin_data: &[u8],
|
||||
stdout_pipe: &PtyOut,
|
||||
) -> Result<(), String> {
|
||||
command.stdin(Stdio::piped());
|
||||
|
||||
let mut child = command
|
||||
.spawn()
|
||||
let mut child = spawn_to_pipe(&mut command, stdout_pipe)
|
||||
.map_err(|err| format!("failed to spawn {:?}: {}\n{:#?}", command, err, err))?;
|
||||
|
||||
if let Some(ref mut stdin) = child.stdin {
|
||||
@ -217,13 +223,13 @@ pub fn offline_check_exists(path: &PathBuf) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn download_wget(url: &str, dest: &PathBuf) -> Result<(), String> {
|
||||
pub fn download_wget(url: &str, dest: &PathBuf, logger: &PtyOut) -> Result<(), String> {
|
||||
if !dest.is_file() {
|
||||
let dest_tmp = PathBuf::from(format!("{}.tmp", dest.display()));
|
||||
let mut command = Command::new("wget");
|
||||
command.arg(translate_mirror(url));
|
||||
command.arg("--continue").arg("-O").arg(&dest_tmp);
|
||||
run_command(command)?;
|
||||
run_command(command, logger)?;
|
||||
rename(&dest_tmp, &dest)?;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
env,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::{collections::BTreeSet, env, path::Path};
|
||||
|
||||
use pkg::{Package, PackageName};
|
||||
|
||||
use crate::{
|
||||
cook::fs::*,
|
||||
cook::{fs::*, pty::PtyOut},
|
||||
log_to_pty,
|
||||
recipe::{BuildKind, Recipe},
|
||||
};
|
||||
|
||||
@ -17,7 +14,14 @@ pub fn package(
|
||||
name: &PackageName,
|
||||
recipe: &Recipe,
|
||||
auto_deps: &BTreeSet<PackageName>,
|
||||
) -> Result<PathBuf, String> {
|
||||
logger: &PtyOut,
|
||||
) -> Result<(), String> {
|
||||
if recipe.build.kind == BuildKind::None {
|
||||
// metapackages don't have stage dir
|
||||
package_toml(target_dir, name, recipe, auto_deps)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let secret_path = "build/id_ed25519.toml";
|
||||
let public_path = "build/id_ed25519.pub.toml";
|
||||
if !Path::new(secret_path).is_file() || !Path::new(public_path).is_file() {
|
||||
@ -34,17 +38,20 @@ pub fn package(
|
||||
}
|
||||
|
||||
let package_file = target_dir.join("stage.pkgar");
|
||||
let package_meta = target_dir.join("stage.toml");
|
||||
// Rebuild package if stage is newer
|
||||
//TODO: rebuild on recipe changes
|
||||
if package_file.is_file() {
|
||||
let stage_modified = modified_dir(stage_dir)?;
|
||||
if modified(&package_file)? < stage_modified {
|
||||
eprintln!(
|
||||
log_to_pty!(
|
||||
logger,
|
||||
"DEBUG: '{}' newer than '{}'",
|
||||
stage_dir.display(),
|
||||
package_file.display()
|
||||
);
|
||||
remove_all(&package_file)?;
|
||||
remove_all(&package_meta)?;
|
||||
}
|
||||
}
|
||||
if !package_file.is_file() {
|
||||
@ -54,11 +61,13 @@ pub fn package(
|
||||
stage_dir.to_str().unwrap(),
|
||||
)
|
||||
.map_err(|err| format!("failed to create pkgar archive: {:?}", err))?;
|
||||
}
|
||||
|
||||
if !package_meta.is_file() {
|
||||
package_toml(target_dir, name, recipe, auto_deps)?;
|
||||
}
|
||||
|
||||
Ok(package_file)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn package_toml(
|
||||
@ -80,7 +89,8 @@ pub fn package_toml(
|
||||
depends,
|
||||
};
|
||||
|
||||
serialize_and_write(&target_dir.join("stage.toml"), &package)?;
|
||||
let toml_path = &target_dir.join("stage.toml");
|
||||
serialize_and_write(&toml_path, &package)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
339
src/cook/pty.rs
Normal file
339
src/cook/pty.rs
Normal file
@ -0,0 +1,339 @@
|
||||
use anyhow::{Error, bail};
|
||||
use filedescriptor::FileDescriptor;
|
||||
use libc::{self, winsize};
|
||||
use std::io::Read;
|
||||
use std::os::fd::FromRawFd;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Child;
|
||||
use std::{io, mem, ptr};
|
||||
use std::{
|
||||
io::{PipeReader, PipeWriter},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
pub use std::os::unix::io::RawFd;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_to_pty {
|
||||
($logger:expr, $($arg:tt)+) => {
|
||||
use std::io::Write;
|
||||
|
||||
if $logger.is_some() {
|
||||
let _ = $logger.as_ref().unwrap().1.try_clone().unwrap().write(
|
||||
format!($($arg)+)
|
||||
.as_bytes(),
|
||||
);
|
||||
} else {
|
||||
eprintln!($($arg)+);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub type PtyOut<'a> = Option<(&'a mut UnixSlavePty, &'a mut PipeWriter)>;
|
||||
|
||||
pub fn setup_pty() -> (
|
||||
Box<dyn Read + Send>,
|
||||
PipeReader,
|
||||
(UnixSlavePty, std::io::PipeWriter),
|
||||
) {
|
||||
let pty_system = UnixPtySystem::default();
|
||||
let pair = pty_system
|
||||
.openpty(PtySize {
|
||||
rows: 24, // Standard terminal size
|
||||
cols: 80, // Standard terminal size
|
||||
..Default::default()
|
||||
})
|
||||
.expect("Unable to open pty");
|
||||
|
||||
// TODO: There's no way to handle stdin
|
||||
let pty_reader = pair
|
||||
.master
|
||||
.try_clone_reader()
|
||||
.expect("Unable to clone pty reader");
|
||||
|
||||
let (log_reader, log_writer) = std::io::pipe().expect("Failed to create log pipe");
|
||||
let pipes = (pair.slave, log_writer);
|
||||
(pty_reader, log_reader, pipes)
|
||||
}
|
||||
|
||||
pub fn spawn_to_pipe(command: &mut Command, stdout_pipe: &PtyOut) -> Result<Child, Error> {
|
||||
match stdout_pipe {
|
||||
Some(stdout) => stdout.0.spawn_command(command.into()),
|
||||
None => Ok(command.spawn()?),
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// based on portable-pty crate
|
||||
// copied here since it isn't flexible enough
|
||||
//
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UnixPtySystem {}
|
||||
|
||||
/// Represents the size of the visible display area in the pty
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct PtySize {
|
||||
/// The number of lines of text
|
||||
pub rows: u16,
|
||||
/// The number of columns of text
|
||||
pub cols: u16,
|
||||
/// The width of a cell in pixels. Note that some systems never
|
||||
/// fill this value and ignore it.
|
||||
pub pixel_width: u16,
|
||||
/// The height of a cell in pixels. Note that some systems never
|
||||
/// fill this value and ignore it.
|
||||
pub pixel_height: u16,
|
||||
}
|
||||
|
||||
impl Default for PtySize {
|
||||
fn default() -> Self {
|
||||
PtySize {
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn openpty(size: PtySize) -> anyhow::Result<(UnixMasterPty, UnixSlavePty)> {
|
||||
let mut master: RawFd = -1;
|
||||
let mut slave: RawFd = -1;
|
||||
|
||||
let mut size = winsize {
|
||||
ws_row: size.rows,
|
||||
ws_col: size.cols,
|
||||
ws_xpixel: size.pixel_width,
|
||||
ws_ypixel: size.pixel_height,
|
||||
};
|
||||
|
||||
let result = unsafe {
|
||||
// BSDish systems may require mut pointers to some args
|
||||
#[allow(clippy::unnecessary_mut_passed)]
|
||||
libc::openpty(
|
||||
&mut master,
|
||||
&mut slave,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
&mut size,
|
||||
)
|
||||
};
|
||||
|
||||
if result != 0 {
|
||||
bail!("failed to openpty: {:?}", io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let master = UnixMasterPty {
|
||||
fd: PtyFd(unsafe { FileDescriptor::from_raw_fd(master) }),
|
||||
};
|
||||
let slave = UnixSlavePty {
|
||||
fd: PtyFd(unsafe { FileDescriptor::from_raw_fd(slave) }),
|
||||
};
|
||||
|
||||
// Ensure that these descriptors will get closed when we execute
|
||||
// the child process. This is done after constructing the Pty
|
||||
// instances so that we ensure that the Ptys get drop()'d if
|
||||
// the cloexec() functions fail (unlikely!).
|
||||
cloexec(master.fd.as_raw_fd())?;
|
||||
cloexec(slave.fd.as_raw_fd())?;
|
||||
|
||||
Ok((master, slave))
|
||||
}
|
||||
|
||||
pub struct PtyPair {
|
||||
// slave is listed first so that it is dropped first.
|
||||
// The drop order is stable and specified by rust rfc 1857
|
||||
pub slave: UnixSlavePty,
|
||||
pub master: UnixMasterPty,
|
||||
}
|
||||
|
||||
impl UnixPtySystem {
|
||||
fn openpty(&self, size: PtySize) -> anyhow::Result<PtyPair> {
|
||||
let (master, slave) = openpty(size)?;
|
||||
Ok(PtyPair {
|
||||
master: master,
|
||||
slave: slave,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct PtyFd(pub FileDescriptor);
|
||||
impl std::ops::Deref for PtyFd {
|
||||
type Target = FileDescriptor;
|
||||
fn deref(&self) -> &FileDescriptor {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl std::ops::DerefMut for PtyFd {
|
||||
fn deref_mut(&mut self) -> &mut FileDescriptor {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for PtyFd {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
||||
match self.0.read(buf) {
|
||||
Err(ref e) if e.raw_os_error() == Some(libc::EIO) => {
|
||||
// EIO indicates that the slave pty has been closed.
|
||||
// Treat this as EOF so that std::io::Read::read_to_string
|
||||
// and similar functions gracefully terminate when they
|
||||
// encounter this condition
|
||||
Ok(0)
|
||||
}
|
||||
x => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PtyFd {
|
||||
fn resize(&self, size: PtySize) -> Result<(), Error> {
|
||||
let ws_size = winsize {
|
||||
ws_row: size.rows,
|
||||
ws_col: size.cols,
|
||||
ws_xpixel: size.pixel_width,
|
||||
ws_ypixel: size.pixel_height,
|
||||
};
|
||||
|
||||
if unsafe {
|
||||
libc::ioctl(
|
||||
self.0.as_raw_fd(),
|
||||
libc::TIOCSWINSZ as _,
|
||||
&ws_size as *const _,
|
||||
)
|
||||
} != 0
|
||||
{
|
||||
bail!(
|
||||
"failed to ioctl(TIOCSWINSZ): {:?}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_size(&self) -> Result<PtySize, Error> {
|
||||
let mut size: winsize = unsafe { mem::zeroed() };
|
||||
if unsafe {
|
||||
libc::ioctl(
|
||||
self.0.as_raw_fd(),
|
||||
libc::TIOCGWINSZ as _,
|
||||
&mut size as *mut _,
|
||||
)
|
||||
} != 0
|
||||
{
|
||||
bail!(
|
||||
"failed to ioctl(TIOCGWINSZ): {:?}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
Ok(PtySize {
|
||||
rows: size.ws_row,
|
||||
cols: size.ws_col,
|
||||
pixel_width: size.ws_xpixel,
|
||||
pixel_height: size.ws_ypixel,
|
||||
})
|
||||
}
|
||||
|
||||
fn spawn_command(&self, cmd: &mut Command) -> anyhow::Result<std::process::Child> {
|
||||
unsafe {
|
||||
cmd
|
||||
// .stdin(self.as_stdio()?)
|
||||
.stdout(self.as_stdio()?)
|
||||
.stderr(self.as_stdio()?)
|
||||
.pre_exec(move || {
|
||||
// Clean up a few things before we exec the program
|
||||
// Clear out any potentially problematic signal
|
||||
// dispositions that we might have inherited
|
||||
for signo in &[
|
||||
libc::SIGCHLD,
|
||||
libc::SIGHUP,
|
||||
libc::SIGINT,
|
||||
libc::SIGQUIT,
|
||||
libc::SIGTERM,
|
||||
libc::SIGALRM,
|
||||
] {
|
||||
libc::signal(*signo, libc::SIG_DFL);
|
||||
}
|
||||
|
||||
let empty_set: libc::sigset_t = std::mem::zeroed();
|
||||
libc::sigprocmask(libc::SIG_SETMASK, &empty_set, std::ptr::null_mut());
|
||||
|
||||
// Establish ourselves as a session leader.
|
||||
if libc::setsid() == -1 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
|
||||
let mut child = cmd.spawn()?;
|
||||
|
||||
// Ensure that we close out the slave fds that Child retains;
|
||||
// they are not what we need (we need the master side to reference
|
||||
// them) and won't work in the usual way anyway.
|
||||
// In practice these are None, but it seems best to be move them
|
||||
// out in case the behavior of Command changes in the future.
|
||||
// child.stdin.take();
|
||||
child.stdout.take();
|
||||
child.stderr.take();
|
||||
|
||||
Ok(child)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the master end of a pty.
|
||||
/// The file descriptor will be closed when the Pty is dropped.
|
||||
pub struct UnixMasterPty {
|
||||
fd: PtyFd,
|
||||
}
|
||||
|
||||
/// Represents the slave end of a pty.
|
||||
/// The file descriptor will be closed when the Pty is dropped.
|
||||
pub struct UnixSlavePty {
|
||||
fd: PtyFd,
|
||||
}
|
||||
|
||||
/// Helper function to set the close-on-exec flag for a raw descriptor
|
||||
fn cloexec(fd: RawFd) -> Result<(), Error> {
|
||||
let flags = unsafe { libc::fcntl(fd, libc::F_GETFD) };
|
||||
if flags == -1 {
|
||||
bail!(
|
||||
"fcntl to read flags failed: {:?}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
let result = unsafe { libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC) };
|
||||
if result == -1 {
|
||||
bail!(
|
||||
"fcntl to set CLOEXEC failed: {:?}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl UnixSlavePty {
|
||||
fn spawn_command(&self, builder: &mut Command) -> Result<std::process::Child, Error> {
|
||||
Ok(self.fd.spawn_command(builder)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnixMasterPty {
|
||||
#[allow(unused)]
|
||||
fn resize(&self, size: PtySize) -> Result<(), Error> {
|
||||
self.fd.resize(size)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn get_size(&self) -> Result<PtySize, Error> {
|
||||
self.fd.get_size()
|
||||
}
|
||||
|
||||
fn try_clone_reader(&self) -> Result<Box<dyn Read + Send>, Error> {
|
||||
let fd = PtyFd(self.fd.try_clone()?);
|
||||
Ok(Box::new(fd))
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,9 @@
|
||||
use std::{collections::BTreeSet, convert::TryInto, fs, path::PathBuf};
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
convert::TryInto,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use pkg::{PackageName, package::PackageError, recipes};
|
||||
use regex::Regex;
|
||||
@ -10,7 +15,7 @@ use serde::{
|
||||
use crate::WALK_DEPTH;
|
||||
|
||||
/// Specifies how to download the source for a recipe
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum SourceRecipe {
|
||||
/// Reuse the source directory of another package
|
||||
@ -83,7 +88,7 @@ impl SourceRecipe {
|
||||
}
|
||||
|
||||
/// Specifies how to build a recipe
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(tag = "template")]
|
||||
pub enum BuildKind {
|
||||
/// Will not build (for meta packages)
|
||||
@ -129,7 +134,7 @@ impl Default for BuildKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BuildRecipe {
|
||||
#[serde(flatten, default)]
|
||||
pub kind: BuildKind,
|
||||
@ -137,7 +142,7 @@ pub struct BuildRecipe {
|
||||
pub dependencies: Vec<PackageName>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PackageRecipe {
|
||||
#[serde(default)]
|
||||
pub dependencies: Vec<PackageName>,
|
||||
@ -146,7 +151,7 @@ pub struct PackageRecipe {
|
||||
}
|
||||
|
||||
/// Everything required to build a Redox package
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Recipe {
|
||||
/// Specifies how to download the source for this recipe
|
||||
pub source: Option<SourceRecipe>,
|
||||
@ -158,7 +163,19 @@ pub struct Recipe {
|
||||
pub package: PackageRecipe,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
impl Recipe {
|
||||
pub fn new(file: &PathBuf) -> Result<Recipe, PackageError> {
|
||||
if !file.is_file() {
|
||||
return Err(PackageError::FileMissing(file.clone()));
|
||||
}
|
||||
let toml = fs::read_to_string(&file)
|
||||
.map_err(|err| PackageError::Parse(DeError::custom(err), Some(file.clone())))?;
|
||||
let recipe: Recipe = toml::from_str(&toml)
|
||||
.map_err(|err| PackageError::Parse(DeError::custom(err), Some(file.clone())))?;
|
||||
Ok(recipe)
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct CookRecipe {
|
||||
pub name: PackageName,
|
||||
pub dir: PathBuf,
|
||||
@ -168,24 +185,7 @@ pub struct CookRecipe {
|
||||
}
|
||||
|
||||
impl CookRecipe {
|
||||
pub fn new(
|
||||
name: impl TryInto<PackageName, Error = PackageError>,
|
||||
) -> Result<Self, PackageError> {
|
||||
let name: PackageName = name.try_into()?;
|
||||
let dir = recipes::find(name.as_str())
|
||||
.ok_or_else(|| PackageError::PackageNotFound(name.clone()))?;
|
||||
let file = dir.join("recipe.toml");
|
||||
if !file.is_file() {
|
||||
return Err(PackageError::FileMissing(file));
|
||||
}
|
||||
|
||||
let toml = fs::read_to_string(&file)
|
||||
.map_err(|err| PackageError::Parse(DeError::custom(err), Some(file.clone())))?;
|
||||
|
||||
let recipe: Recipe = toml::from_str(&toml)
|
||||
.map_err(|err| PackageError::Parse(DeError::custom(err), Some(file)))?;
|
||||
|
||||
let dir = dir.to_path_buf();
|
||||
pub fn new(name: PackageName, dir: PathBuf, recipe: Recipe) -> Result<Self, PackageError> {
|
||||
Ok(Self {
|
||||
name,
|
||||
dir,
|
||||
@ -194,6 +194,29 @@ impl CookRecipe {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_name(
|
||||
name: impl TryInto<PackageName, Error = PackageError>,
|
||||
) -> Result<Self, PackageError> {
|
||||
let name: PackageName = name.try_into()?;
|
||||
let dir = recipes::find(name.as_str())
|
||||
.ok_or_else(|| PackageError::PackageNotFound(name.clone()))?;
|
||||
let file = dir.join("recipe.toml");
|
||||
let recipe = Recipe::new(&file)?;
|
||||
Self::new(name, dir.to_path_buf(), recipe)
|
||||
}
|
||||
|
||||
pub fn from_path(dir: &Path, read_recipe: bool) -> Result<Self, PackageError> {
|
||||
let file = dir.join("recipe.toml");
|
||||
let name: PackageName = dir.file_name().unwrap().try_into()?;
|
||||
let recipe = if read_recipe {
|
||||
Recipe::new(&file)?
|
||||
} else {
|
||||
// clean/unfetch don't need to read recipe
|
||||
Recipe::default()
|
||||
};
|
||||
Self::new(name, dir.to_path_buf(), recipe)
|
||||
}
|
||||
|
||||
pub fn new_recursive(
|
||||
names: &[PackageName],
|
||||
recursion: usize,
|
||||
@ -204,7 +227,7 @@ impl CookRecipe {
|
||||
|
||||
let mut recipes = Vec::new();
|
||||
for name in names {
|
||||
let recipe = Self::new(name.as_str())?;
|
||||
let recipe = Self::from_name(name.as_str())?;
|
||||
|
||||
let dependencies =
|
||||
Self::new_recursive(&recipe.recipe.build.dependencies, recursion - 1).map_err(
|
||||
@ -253,7 +276,7 @@ impl CookRecipe {
|
||||
|
||||
let mut recipes: Vec<PackageName> = Vec::new();
|
||||
for name in names {
|
||||
let recipe = Self::new(name.as_str())?;
|
||||
let recipe = Self::from_name(name.as_str())?;
|
||||
|
||||
let dependencies = Self::get_package_deps_recursive(
|
||||
&recipe.recipe.package.dependencies,
|
||||
|
||||
13
unfetch.sh
13
unfetch.sh
@ -1,20 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
source config.sh
|
||||
source `dirname "$0"`/config.sh
|
||||
|
||||
if [ $# = 0 ]
|
||||
then
|
||||
recipes="$(list_recipes --short)"
|
||||
recipes="--all"
|
||||
else
|
||||
recipes="$@"
|
||||
fi
|
||||
|
||||
for recipe_name in $recipes
|
||||
do
|
||||
recipe_path=`find_recipe $recipe_name`
|
||||
|
||||
echo -e "\033[01;38;5;215mcook - unfetch $recipe_name\033[0m"
|
||||
rm -rfv "$recipe_path"/source "$recipe_path"/source.tar
|
||||
done
|
||||
|
||||
repo unfetch $recipes
|
||||
|
||||
Loading…
Reference in New Issue
Block a user