From ea736d88244ce1d85999d7ce6387a63c655b7000 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Mon, 14 Oct 2024 22:04:18 +0200 Subject: [PATCH] lota of progress --- Cargo.lock | 514 ++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 +- depell/Cargo.toml | 6 + depell/src/index.css | 24 +- depell/src/index.js | 66 ++++- depell/src/main.rs | 334 +++++++++++++++++------- depell/src/post-page.html | 31 ++- depell/src/schema.sql | 11 +- depell/wasm-hbc/src/lib.rs | 2 +- lang/src/parser.rs | 4 +- xtask/src/main.rs | 16 +- 11 files changed, 887 insertions(+), 123 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 017915dd..c0d5fb2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.18" @@ -41,6 +50,12 @@ version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "argon2" version = "0.5.3" @@ -64,12 +79,45 @@ dependencies = [ "syn", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "aws-lc-rs" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "axum" version = "0.7.7" @@ -98,7 +146,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -125,6 +173,30 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-server" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56bac90848f6a9393ac03c63c640925c4b7c8ca21654de40d53f55964667c7d8" +dependencies = [ + "arc-swap", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower 0.4.13", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.74" @@ -146,6 +218,29 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -191,15 +286,66 @@ version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ + "jobserver", + "libc", "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +dependencies = [ + "cc", +] + +[[package]] +name = "const_format" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "cpufeatures" version = "0.2.14" @@ -225,6 +371,8 @@ version = "0.1.0" dependencies = [ "argon2", "axum", + "axum-server", + "const_format", "getrandom", "hblang", "htmlm", @@ -256,12 +404,34 @@ dependencies = [ "subtle", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -295,6 +465,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" version = "0.3.31" @@ -310,6 +486,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + [[package]] name = "futures-task" version = "0.3.31" @@ -366,6 +548,31 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -439,6 +646,15 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + [[package]] name = "htmlm" version = "0.5.0" @@ -509,6 +725,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2", "http", "http-body", "httparse", @@ -562,12 +779,42 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "leb128" version = "0.2.5" @@ -580,6 +827,16 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -591,6 +848,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "log" version = "0.4.22" @@ -624,6 +887,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[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.0" @@ -645,6 +914,22 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + +[[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" @@ -677,12 +962,38 @@ dependencies = [ "subtle", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -707,6 +1018,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "prettyplease" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.87" @@ -743,10 +1064,54 @@ dependencies = [ "bumpalo", "hashbrown 0.14.5", "log", - "rustc-hash", + "rustc-hash 2.0.0", "smallvec", ] +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys", +] + [[package]] name = "rusqlite" version = "0.32.1" @@ -767,12 +1132,72 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustls" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -851,6 +1276,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -867,6 +1301,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -928,6 +1368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", + "bytes", "libc", "mio", "pin-project-lite", @@ -947,6 +1388,45 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.5.1" @@ -1007,6 +1487,18 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "vcpkg" version = "0.2.15" @@ -1101,6 +1593,18 @@ dependencies = [ "serde", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1201,3 +1705,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index e949af74..57882704 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ hbjit = { path = "jit" } [profile.release] lto = true -debug = true +#debug = true #strip = true codegen-units = 1 panic = "abort" diff --git a/depell/Cargo.toml b/depell/Cargo.toml index 0af1108a..16ccf2aa 100644 --- a/depell/Cargo.toml +++ b/depell/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [dependencies] argon2 = "0.5.3" axum = "0.7.7" +axum-server = { version = "0.7.1", optional = true, features = ["rustls", "tls-rustls"] } +const_format = "0.2.33" getrandom = "0.2.15" hblang.workspace = true htmlm = "0.5.0" @@ -15,3 +17,7 @@ rusqlite = { version = "0.32.1", features = ["bundled"] } serde = { version = "1.0.210", features = ["derive"] } time = "0.3.36" tokio = { version = "1.40.0", features = ["rt"] } + +[features] +#default = ["tls"] +tls = ["dep:axum-server"] diff --git a/depell/src/index.css b/depell/src/index.css index ea7c5d02..57ec65fa 100644 --- a/depell/src/index.css +++ b/depell/src/index.css @@ -28,6 +28,9 @@ body { main { margin-top: var(--small-gap); + display: flex; + flex-direction: column; + gap: var(--small-gap); } } @@ -45,8 +48,6 @@ div.preview { display: flex; gap: var(--small-gap); } - - margin: var(--small-gap) 0px; } form { @@ -119,3 +120,22 @@ div#code-editor { font-size: 12px; } } + +div#dep-list { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--small-gap); + + section { + width: 100%; + display: flex; + flex-direction: column; + text-align: center; + gap: var(--small-gap); + + div { + text-align: left; + } + } +} diff --git a/depell/src/index.js b/depell/src/index.js index db02a55f..79ce0e8b 100644 --- a/depell/src/index.js +++ b/depell/src/index.js @@ -135,14 +135,18 @@ function bufToString(mem, ptr, len) { function wireUp(target) { execApply(target); cacheInputs(target); - bindTextareaAutoResize(target); bindCodeEdit(target); + bindTextareaAutoResize(target); } const importRe = /@use\s*\(\s*"(([^"]|\\")+)"\s*\)/g; -const prevRoots = new Set(); -/** @param {string} code @param {string[]} roots @param {Post[]} buf @returns {void} */ -function loadCachedPackages(code, roots, buf) { + +/** @param {string} code + * @param {string[]} roots + * @param {Post[]} buf + * @param {Set} prevRoots + * @returns {void} */ +function loadCachedPackages(code, roots, buf, prevRoots) { buf[0].code = code; roots.length = 0; @@ -165,6 +169,8 @@ function loadCachedPackages(code, roots, buf) { } } +/**@type{Set}*/ const prevRoots = new Set(); + /** @param {HTMLElement} target */ async function bindCodeEdit(target) { const edit = target.querySelector("#code-edit"); @@ -190,6 +196,8 @@ async function bindCodeEdit(target) { let cancelation = undefined; let timeout = 0; + prevRoots.clear(); + const onInput = () => { importDiff.clear(); for (const match of edit.value.matchAll(importRe)) { @@ -215,10 +223,12 @@ async function bindCodeEdit(target) { try { const json = await e.json(); if (e.status == 200) { - for (const key in json) localStorage["package-" + key] = json[key]; + for (const [key, value] of Object.entries(json)) { + localStorage["package-" + key] = value; + } const missing = keyBuf.filter(i => json[i] === undefined); if (missing.length !== 0) { - errors.textContent = "failed to fetch: " + missing.join(", "); + errors.textContent = "deps not found: " + missing.join(", "); } else { cancelation = undefined; edit.dispatchEvent(new InputEvent("input")); @@ -236,7 +246,7 @@ async function bindCodeEdit(target) { return; } - loadCachedPackages(edit.value, keyBuf, packages); + loadCachedPackages(edit.value, keyBuf, packages, prevRoots); errors.textContent = compileCode(hbc, packages, 1); const minified_size = modifyCode(fmt, edit.value, "minify")?.length; @@ -348,7 +358,7 @@ if (window.location.hostname === 'localhost') { })() } -document.body.addEventListener('htmx:afterSettle', (ev) => { +document.body.addEventListener('htmx:afterSwap', (ev) => { if (!(ev.target instanceof HTMLElement)) never(); wireUp(ev.target); }); @@ -360,7 +370,47 @@ getFmtInstance().then(inst => { details.parameters['code'] = modifyCode(inst, details.parameters['code'], "minify"); } }); + + /** @param {string} query @param {string} target @returns {number} */ + function fuzzyCost(query, target) { + let qi = 0, bi = 0, cost = 0, matched = false; + while (qi < query.length) { + if (query.charAt(qi) === target.charAt(bi++)) { + matched = true; + qi++; + } else { + cost++; + } + if (bi === target.length) (bi = 0, qi++); + } + return cost + (matched ? 0 : 100 * target.length); + } + + let deps = undefined; + /** @param {HTMLInputElement} input @returns {void} */ + function filterCodeDeps(input) { + deps ??= document.getElementById("deps"); + if (!(deps instanceof HTMLElement)) never(); + if (input.value === "") { + deps.textContent = "results show here..."; + return; + } + deps.innerHTML = ""; + for (const root of [...prevRoots.keys()] + .sort((a, b) => fuzzyCost(input.value, a) - fuzzyCost(input.value, b))) { + const pane = document.createElement("div"); + const code = modifyCode(inst, localStorage["package-" + root], "fmt"); + pane.innerHTML = `
${root}
${code}
`; + deps.appendChild(pane); + } + if (deps.innerHTML === "") { + deps.textContent = "no results"; + } + } + + Object.assign(window, { filterCodeDeps }); }); wireUp(document.body); + diff --git a/depell/src/main.rs b/depell/src/main.rs index c57df4e0..dbc5bae7 100644 --- a/depell/src/main.rs +++ b/depell/src/main.rs @@ -3,16 +3,18 @@ use { argon2::{password_hash::SaltString, PasswordVerifier}, axum::{ body::Bytes, + extract::Path, http::{header::COOKIE, request::Parts}, response::{AppendHeaders, Html}, }, + const_format::formatcp, core::fmt, htmlm::{html, write_html}, rand_core::OsRng, serde::{Deserialize, Serialize}, std::{ collections::{HashMap, HashSet}, - fmt::Write, + fmt::{Display, Write}, net::Ipv4Addr, }, }; @@ -21,6 +23,7 @@ const MAX_NAME_LENGTH: usize = 32; const MAX_POSTNAME_LENGTH: usize = 64; const MAX_CODE_LENGTH: usize = 1024 * 4; const SESSION_DURATION_SECS: u64 = 60 * 60; +const MAX_FEED_SIZE: usize = 8 * 1024; type Redirect = AppendHeaders<[(&'static str, &'static str); COUNT]>; @@ -55,9 +58,13 @@ async fn amain() { .route("/hbfmt.wasm", static_asset!("application/wasm", "hbfmt.wasm")) .route("/hbc.wasm", static_asset!("application/wasm", "hbc.wasm")) .route("/index-view", get(Index::get)) - .route("/feed", get(Index::page)) + .route("/feed", get(Feed::page)) + .route("/feed-view", get(Feed::get)) + .route("/feed-more", post(Feed::more)) .route("/profile", get(Profile::page)) .route("/profile-view", get(Profile::get)) + .route("/profile/:name", get(Profile::get_other_page)) + .route("/profile-view/:name", get(Profile::get_other)) .route("/post", get(Post::page)) .route("/post-view", get(Post::get)) .route("/post", post(Post::post)) @@ -80,49 +87,27 @@ async fn amain() { }), ); - let socket = tokio::net::TcpListener::bind((Ipv4Addr::UNSPECIFIED, 8080)).await.unwrap(); + #[cfg(feature = "tls")] + { + let addr = + (Ipv4Addr::UNSPECIFIED, std::env::var("DEPELL_PORT").unwrap().parse::().unwrap()); + let config = axum_server::tls_rustls::RustlsConfig::from_pem_file( + std::env::var("DEPELL_CERT_PATH").unwrap(), + std::env::var("DEPELL_KEY_PATH").unwrap(), + ) + .await + .unwrap(); - axum::serve(socket, router).await.unwrap(); -} - -trait PublicPage: Default { - fn render_to_buf(self, buf: &mut String); - - fn render(self) -> String { - let mut str = String::new(); - self.render_to_buf(&mut str); - str + axum_server::bind_rustls(addr.into(), config) + .serve(router.into_make_service()) + .await + .unwrap(); } - - async fn get() -> Html { - Html(Self::default().render()) - } - - async fn page(session: Option) -> Html { - base(|s| Self::default().render_to_buf(s), session.as_ref()).await - } -} - -trait Page: Default { - fn render_to_buf(self, session: &Session, buf: &mut String); - - fn render(self, session: &Session) -> String { - let mut str = String::new(); - self.render_to_buf(session, &mut str); - str - } - - async fn get(session: Session) -> Html { - Html(Self::default().render(&session)) - } - - async fn page(session: Option) -> Result, axum::response::Redirect> { - match session { - Some(session) => { - Ok(base(|f| Self::default().render_to_buf(&session, f), Some(&session)).await) - } - None => Err(axum::response::Redirect::permanent("/login")), - } + #[cfg(not(feature = "tls"))] + { + let addr = (Ipv4Addr::UNSPECIFIED, 8080); + let socket = tokio::net::TcpListener::bind(addr).await.unwrap(); + axum::serve(socket, router).await.unwrap(); } } @@ -140,16 +125,77 @@ async fn fetch_code( r.get::<_, String>(2)?, )) }) - .inspect_err(|e| log::error!("{e}")) + .log("fetch deps query") .into_iter() .flatten() - .filter_map(|r| r.inspect_err(|e| log::error!("{e}")).ok()) + .filter_map(|r| r.log("deps row")) .collect_into(&mut deps); } }); axum::Json(deps) } +#[derive(Deserialize)] +#[serde(untagged)] +enum Feed { + Before { before_timestamp: u64 }, +} + +#[derive(Deserialize)] +struct Before { + before_timestamp: u64, +} + +impl Feed { + async fn more(session: Session, axum::Form(data): axum::Form) -> Html { + Self::Before { before_timestamp: data.before_timestamp }.render(&session) + } +} + +impl Default for Feed { + fn default() -> Self { + Self::Before { before_timestamp: now() + 3600 } + } +} + +impl Page for Feed { + fn render_to_buf(self, _: &Session, buf: &mut String) { + db::with(|db| { + let cursor = match self { + Feed::Before { before_timestamp } => db + .get_pots_before + .query_map((before_timestamp,), Post::from_row) + .log("fetch before posts query") + .into_iter() + .flatten() + .filter_map(|r| r.log("fetch before posts row")), + }; + + let base_len = buf.len(); + let mut last_timestamp = None; + for post in cursor { + write!(buf, "{}", post).unwrap(); + last_timestamp = Some(post.timestamp); + if buf.len() - base_len > MAX_FEED_SIZE { + break; + } + } + + write_html!((*buf) + if let Some(last_timestamp) = last_timestamp { +
"there might be more"
+ } else { + "no more stuff" + } + ); + }); + } +} + #[derive(Default)] struct Index; @@ -199,10 +245,30 @@ impl Page for Post { } impl Post { + pub fn from_row(r: &rusqlite::Row) -> rusqlite::Result { + Ok(Post { + author: r.get(0)?, + name: r.get(1)?, + timestamp: r.get(2)?, + code: r.get(3)?, + ..Default::default() + }) + } + async fn post( session: Session, axum::Form(mut data): axum::Form, ) -> Result> { + if data.name.len() > MAX_POSTNAME_LENGTH { + data.error = Some(formatcp!("name too long, max length is {MAX_POSTNAME_LENGTH}")); + return Err(data.render(&session)); + } + + if data.code.len() > MAX_CODE_LENGTH { + data.error = Some(formatcp!("code too long, max length is {MAX_CODE_LENGTH}")); + return Err(data.render(&session)); + } + db::with(|db| { if let Err(e) = db.create_post.insert((&data.name, &session.name, now(), &data.code)) { if let rusqlite::Error::SqliteFailure(e, _) = e { @@ -211,7 +277,7 @@ impl Post { } } data.error = data.error.or_else(|| { - log::error!("{e}"); + log::error!("create post error: {e}"); Some("internal server error") }); return; @@ -221,8 +287,12 @@ impl Post { .filter_map(|v| v.split_once('/')) .collect::>() { - if let Err(e) = db.create_import.insert((author, name, &session.name, &data.name)) { - log::error!("{e}"); + if db + .create_import + .insert((author, name, &session.name, &data.name)) + .log("create import query") + .is_none() + { data.error = Some("internal server error"); return; }; @@ -230,7 +300,7 @@ impl Post { }); if data.error.is_some() { - Err(Html(data.render(&session))) + Err(data.render(&session)) } else { Ok(redirect("/profile")) } @@ -242,7 +312,13 @@ impl fmt::Display for Post { let Self { author, name, timestamp, imports, runs, dependencies, code, .. } = self; write_html! { f
- author "/" name + + author + "/" + name + timestamp
@@ -264,26 +340,30 @@ impl fmt::Display for Post { } #[derive(Default)] -struct Profile; +struct Profile { + other: Option, +} + +impl Profile { + async fn get_other(session: Session, Path(name): Path) -> Html { + Profile { other: Some(name) }.render(&session) + } + + async fn get_other_page(session: Session, Path(name): Path) -> Html { + base(|b| Profile { other: Some(name) }.render_to_buf(&session, b), Some(&session)) + } +} impl Page for Profile { fn render_to_buf(self, session: &Session, buf: &mut String) { db::with(|db| { let iter = db .get_user_posts - .query_map((&session.name,), |r| { - Ok(Post { - author: r.get(0)?, - name: r.get(1)?, - timestamp: r.get(2)?, - code: r.get(3)?, - ..Default::default() - }) - }) - .inspect_err(|e| log::error!("{e}")) + .query_map((self.other.as_ref().unwrap_or(&session.name),), Post::from_row) + .log("get user posts query") .into_iter() .flatten() - .filter_map(|p| p.inspect_err(|e| log::error!("{e}")).ok()); + .filter_map(|p| p.log("user post row")); write_html! { (buf) for post in iter { !{post} @@ -345,9 +425,13 @@ impl Login { data.error = Some("invalid credentials"); } else { getrandom::getrandom(&mut id).unwrap(); - if let Err(e) = db.login.insert((id, &data.name, now() + SESSION_DURATION_SECS)) + if db + .login + .insert((id, &data.name, now() + SESSION_DURATION_SECS)) + .log("create session query") + .is_none() { - log::error!("{e}"); + data.error = Some("internal server error"); } } } @@ -362,7 +446,7 @@ impl Login { if data.error.is_some() { log::error!("what {:?}", data); - Err(Html(data.render())) + Err(data.render()) } else { Ok(AppendHeaders([ ("hx-location", "/feed".into()), @@ -378,7 +462,7 @@ impl Login { } async fn delete(session: Session) -> Redirect { - _ = db::with(|q| q.logout.execute((session.id,)).inspect_err(|e| log::error!("{e}"))); + _ = db::with(|q| q.logout.execute((session.id,)).log("delete session query")); redirect("/login") } } @@ -388,15 +472,18 @@ struct Signup { name: String, new_password: String, confirm_password: String, + #[serde(default)] + confirm_no_password: bool, #[serde(skip)] error: Option<&'static str>, } impl PublicPage for Signup { fn render_to_buf(self, buf: &mut String) { - let Signup { name, new_password, confirm_password, error } = self; + let Signup { name, new_password, confirm_password, confirm_no_password, error } = self; + let vals = if confirm_no_password { "{\"confirm_no_password\":true}" } else { "{}" }; write_html! { (buf) -
+ if let Some(e) = error {
e
} @@ -412,6 +499,17 @@ impl PublicPage for Signup { impl Signup { async fn post(axum::Form(mut data): axum::Form) -> Result> { + if data.name.len() > MAX_NAME_LENGTH { + data.error = Some(formatcp!("name too long, max length is {MAX_NAME_LENGTH}")); + return Err(data.render()); + } + + if !data.confirm_no_password && data.new_password.is_empty() { + data.confirm_no_password = true; + data.error = Some("Are you sure you don't want to use a password? (then submit again)"); + return Err(data.render()); + } + db::with(|db| { // TODO: hash passwords match db.register.insert((&data.name, hash_password(&data.new_password))) { @@ -422,23 +520,32 @@ impl Signup { data.error = Some("username already taken"); } Err(e) => { - log::error!("{e}"); + log::error!("create user query: {e}"); data.error = Some("internal server error"); } }; }); if data.error.is_some() { - Err(Html(data.render())) + Err(data.render()) } else { Ok(redirect("/login")) } } } -async fn base(body: impl FnOnce(&mut String), session: Option<&Session>) -> Html { +fn base(body: impl FnOnce(&mut String), session: Option<&Session>) -> Html { let username = session.map(|s| &s.name); + let nav_button = |f: &mut String, name: &str| { + write_html! {(f) + + } + }; + Html(html! { "" @@ -452,21 +559,17 @@ async fn base(body: impl FnOnce(&mut String), session: Option<&Session>) -> Html if let Some(username) = username { - + |f|{nav_button(f, "feed"); nav_button(f, "post")} } else { - - + |f|{nav_button(f, "login"); nav_button(f, "signup")} }
|f|{body(f)}
- + }) @@ -500,12 +603,11 @@ impl axum::extract::FromRequestParts for Session { let (name, expiration) = db::with(|db| { db.get_session .query_row((id,), |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?))) - .inspect_err(|e| log::error!("{e}")) - .map_err(|_| err) + .log("fetching session") + .ok_or(err) })?; if expiration < now() { - log::error!("expired"); return Err(err); } @@ -551,7 +653,7 @@ fn to_hex(src: &[u8]) -> String { } fn main() { - tokio::runtime::Builder::new_current_thread().enable_io().build().unwrap().block_on(amain()); + tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(amain()); } mod db { @@ -583,7 +685,9 @@ mod db { login: "INSERT OR REPLACE INTO session (id, username, expiration) VALUES(?, ?, ?)", logout: "DELETE FROM session WHERE id = ?", get_session: "SELECT username, expiration FROM session WHERE id = ?", - get_user_posts: "SELECT author, name, timestamp, code FROM post WHERE author = ?", + get_user_posts: "SELECT author, name, timestamp, code FROM post WHERE author = ? + ORDER BY timestamp DESC", + get_pots_before: "SELECT author, name, timestamp, code FROM post WHERE timestamp < ?", create_post: "INSERT INTO post (name, author, timestamp, code) VALUES(?, ?, ?, ?)", fetch_deps: " WITH RECURSIVE roots(name, author, code) AS ( @@ -634,6 +738,63 @@ fn redirect(to: &'static str) -> Redirect { AppendHeaders([("hx-location", to)]) } +trait PublicPage: Default { + fn render_to_buf(self, buf: &mut String); + + fn render(self) -> Html { + let mut str = String::new(); + self.render_to_buf(&mut str); + Html(str) + } + + async fn get() -> Html { + Self::default().render() + } + + async fn page(session: Option) -> Html { + base(|s| Self::default().render_to_buf(s), session.as_ref()) + } +} + +trait Page: Default { + fn render_to_buf(self, session: &Session, buf: &mut String); + + fn render(self, session: &Session) -> Html { + let mut str = String::new(); + self.render_to_buf(session, &mut str); + Html(str) + } + + async fn get(session: Session) -> Html { + Self::default().render(&session) + } + + async fn page(session: Option) -> Result, axum::response::Redirect> { + match session { + Some(session) => { + Ok(base(|f| Self::default().render_to_buf(&session, f), Some(&session))) + } + None => Err(axum::response::Redirect::permanent("/login")), + } + } +} + +trait ResultExt { + fn log(self, prefix: impl Display) -> Option; +} + +impl ResultExt for Result { + fn log(self, prefix: impl Display) -> Option { + match self { + Ok(v) => Some(v), + Err(e) => { + log::error!("{prefix}: {e}"); + None + } + } + } +} + struct Logger; impl log::Log for Logger { @@ -643,12 +804,7 @@ impl log::Log for Logger { fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) { - eprintln!( - "{} {:?} - {}", - record.module_path().unwrap_or("=="), - record.line(), - record.args() - ); + eprintln!("{} - {}", record.module_path().unwrap_or("=="), record.args()); } } diff --git a/depell/src/post-page.html b/depell/src/post-page.html index dcce9c16..cf73e356 100644 --- a/depell/src/post-page.html +++ b/depell/src/post-page.html @@ -1,12 +1,21 @@ -

About posting code

-

- If you are unfammiliar with hblang, refer to the - hblang/README.md or - vizit mlokis'es posts. Preferably don't edit the code here. -

+
+ +
+ results show here... +
+
-

Extra textarea features

-
    -
  • proper tab behaviour
  • -
  • snap to previous tab boundary on "empty" lines
  • -
+
+ +

About posting code

+

+ If you are unfammiliar with hblang, refer to the + hblang/README.md or + vizit mlokis'es posts. Preferably don't edit the code here. +

+ +

Extra textarea features

+
    +
  • proper tab behaviour
  • +
  • snap to previous tab boundary on "empty" lines
  • +
diff --git a/depell/src/schema.sql b/depell/src/schema.sql index cf9c7672..2af73464 100644 --- a/depell/src/schema.sql +++ b/depell/src/schema.sql @@ -22,17 +22,20 @@ CREATE TABLE IF NOT EXISTS post( author TEXT, timestamp INTEGER, code TEXT NOT NULL, - FOREIGN KEY (author) REFERENCES user (name) ON DELETE SET NULL, + FOREIGN KEY (author) REFERENCES user(name) ON DELETE SET NULL, PRIMARY KEY (author, name) ); +CREATE INDEX IF NOT EXISTS + post_timestamp ON post(timestamp DESC); + CREATE TABLE IF NOT EXISTS import( from_name TEXT NOT NULL, from_author TEXT, to_name TEXT NOT NULL, to_author TEXT, - FOREIGN KEY (from_name, from_author) REFERENCES post (name, author), - FOREIGN KEY (to_name, to_author) REFERENCES post (name, author) + FOREIGN KEY (from_name, from_author) REFERENCES post(name, author), + FOREIGN KEY (to_name, to_author) REFERENCES post(name, author) ); CREATE INDEX IF NOT EXISTS @@ -45,7 +48,7 @@ CREATE TABLE IF NOT EXISTS run( code_name TEXT NOT NULL, code_author TEXT NOT NULL, runner TEXT NOT NULL, - FOREIGN KEY (code_name, code_author) REFERENCES post (name, author), + FOREIGN KEY (code_name, code_author) REFERENCES post(name, author), FOREIGN KEY (runner) REFERENCES user(name), PRIMARY KEY (code_name, code_author, runner) ); diff --git a/depell/wasm-hbc/src/lib.rs b/depell/wasm-hbc/src/lib.rs index 92a2e0d9..b91df31d 100644 --- a/depell/wasm-hbc/src/lib.rs +++ b/depell/wasm-hbc/src/lib.rs @@ -83,7 +83,7 @@ unsafe fn compile_and_run(mut fuel: usize) { while fuel != 0 { match ct.vm.run() { Ok(hbvm::VmRunOk::End) => { - log::error!("exit code: {}", ct.vm.read_reg(1).0); + log::error!("exit code: {}", ct.vm.read_reg(1).0 as i64); break; } Ok(hbvm::VmRunOk::Ecall) => { diff --git a/lang/src/parser.rs b/lang/src/parser.rs index 326e6b5e..f786dcd6 100644 --- a/lang/src/parser.rs +++ b/lang/src/parser.rs @@ -570,12 +570,14 @@ impl<'a, 'b> Parser<'a, 'b> { end: TokenKind, mut f: impl FnMut(&mut Self) -> T, ) -> &'a [T] { + let mut trailing_sep = false; let mut view = self.ctx.stack.view(); while !self.advance_if(end) { let val = f(self); - self.trailing_sep = self.advance_if(delim); + trailing_sep = self.advance_if(delim); unsafe { self.ctx.stack.push(&mut view, val) }; } + self.trailing_sep = trailing_sep; self.arena.alloc_slice(unsafe { self.ctx.stack.finalize(view) }) } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index afc8a715..1c544c2a 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -83,17 +83,25 @@ fn main() -> anyhow::Result<()> { Ok(()) } "watch-depell-debug" => { - let mut c = build_cmd("cargo watch --why"); - c.arg("--exec=xtask build-depell-debug").arg("--exec=run -p depell"); + let mut c = build_cmd("cargo watch"); + c.args(["--exec=xtask build-depell-debug", "--exec=run -p depell"]); exec(c)?; Ok(()) } "watch-depell" => { - let mut c = build_cmd("cargo watch --why"); - c.arg("--exec=xtask build-depell").arg("--exec=run -p depell"); + let mut c = build_cmd("cargo watch"); + c.args(["--exec=xtask build-depell", "--exec=run -p depell --release"]); exec(c)?; Ok(()) } + "release-depell" => { + exec(build_cmd("cargo xtask build-depell"))?; + exec(build_cmd( + "cargo build -p depell --release --features tls + --target x86_64-unknown-linux-musl", + ))?; + Ok(()) + } _ => Ok(()), } }