From edea727e6e7832e49d6de7fdbd84e3eb0482b10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Nordstr=C3=B8m?= Date: Sun, 6 Oct 2024 03:49:55 +0200 Subject: [PATCH] Begin work on initial scan of project dir. Switch from tokio to smol. Update some deps. --- Cargo.lock | 618 ++++++++++++++++++++++++++----------- Cargo.toml | 28 +- src/fs/exclude.rs | 36 +++ src/fs/mod.rs | 2 + src/fs/scan_project_dir.rs | 107 +++++++ src/lib.rs | 1 + src/main.rs | 75 +++-- 7 files changed, 655 insertions(+), 212 deletions(-) create mode 100644 src/fs/exclude.rs create mode 100644 src/fs/mod.rs create mode 100644 src/fs/scan_project_dir.rs create mode 100644 src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 3f78cda..140ffb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "anstream" @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "askama" @@ -118,11 +118,125 @@ dependencies = [ "nom", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -131,15 +245,21 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -148,23 +268,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -188,6 +308,19 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bstr" version = "1.10.0" @@ -201,15 +334,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.14" +version = "1.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "e8d9e0b4957f635b8d3da819d0db5603620467ecf1f692d22a8c2717ce27e6d8" dependencies = [ "shlex", ] @@ -220,11 +353,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clap" -version = "4.5.16" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" dependencies = [ "clap_builder", "clap_derive", @@ -232,9 +371,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" dependencies = [ "anstream", "anstyle", @@ -244,9 +383,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -266,6 +405,31 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "ctrlc" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +dependencies = [ + "nix", + "windows-sys 0.59.0", +] + [[package]] name = "dbus" version = "0.9.7" @@ -283,6 +447,43 @@ 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 0.52.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + [[package]] name = "fnv" version = "1.0.7" @@ -310,24 +511,43 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -336,21 +556,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", @@ -362,9 +582,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" @@ -387,9 +607,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -403,6 +623,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "http" version = "1.1.0" @@ -446,26 +672,30 @@ dependencies = [ "async-stream", "bytes", "clap", + "ctrlc", "fsevent", "futures-util", "http-body-util", "hyper", "hyper-util", + "macro_rules_attribute", "opener", "serde", + "smol", + "smol-hyper", + "smol-macros", "thiserror", - "tokio", "tokio-stream", - "tokio-util", "tracing", "tracing-subscriber", + "trie-hard", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -505,9 +735,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -518,16 +748,15 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] [[package]] name = "indexmap" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -553,9 +782,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libdbus-sys" @@ -574,14 +803,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] -name = "lock_api" -version = "0.4.12" +name = "linux-raw-sys" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" @@ -589,6 +814,22 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "macro_rules_attribute" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a82271f7bc033d84bbca59a3ce3e4159938cb08a9c3aebbe54d215131518a13" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" + [[package]] name = "memchr" version = "2.7.4" @@ -619,11 +860,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -632,12 +873,24 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -678,18 +931,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opener" @@ -710,27 +963,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] -name = "parking_lot" -version = "0.12.3" +name = "parking" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] -name = "parking_lot_core" -version = "0.9.10" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -738,26 +980,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -770,11 +992,37 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "polling" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] [[package]] name = "proc-macro2" @@ -794,20 +1042,11 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" -dependencies = [ - "bitflags 2.6.0", -] - [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" [[package]] name = "rustc-demangle" @@ -816,31 +1055,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] -name = "ryu" -version = "1.0.18" +name = "rustix" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "ryu" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -849,9 +1095,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -898,6 +1144,49 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smol-hyper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7428a49d323867702cd12b97b08a6b0104f39ec13b49117911f101271321bc1a" +dependencies = [ + "async-executor", + "async-io", + "futures-io", + "hyper", + "pin-project-lite", +] + +[[package]] +name = "smol-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcaedb62e0475a6898988138995ec7b1e5d116167a72bb12c7b59d0649fbbc2" +dependencies = [ + "async-executor", + "async-io", + "async-lock", + "event-listener", + "futures-lite", +] + [[package]] name = "socket2" version = "0.5.7" @@ -916,9 +1205,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.76" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -927,18 +1216,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -957,38 +1246,24 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", - "tokio-macros", "windows-sys 0.52.0", ] -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -997,9 +1272,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -1008,27 +1283,6 @@ dependencies = [ "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", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - [[package]] name = "tower-service" version = "0.3.3" @@ -1092,6 +1346,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "trie-hard" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9bd82ef455bc8dc4951d95d3857abb8742a207032305df96a8dc6ed6649ac79" + [[package]] name = "try-lock" version = "0.2.5" @@ -1109,9 +1369,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "utf8parse" diff --git a/Cargo.toml b/Cargo.toml index f5f7641..280d8d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,21 +11,27 @@ keywords = ["autoreload", "html5", "css3", "js", "wasm"] edition = "2021" [dependencies] -bytes = "1.7.1" -clap = { version = "4.5.16", features = ["cargo", "derive"] } +bytes = "1.7.2" +clap = { version = "4.5.19", features = ["cargo", "derive"] } fsevent = "2.1.2" -futures-util = "0.3.30" +futures-util = "0.3.31" http-body-util = "0.1.2" hyper = { version = "1.4.1", features = ["full"] } -hyper-util = { version = "0.1.7", features = ["full"] } -thiserror = "1.0.63" -tokio = { version = "1.39.3", features = ["full"] } -tokio-util = "0.7.11" +hyper-util = { version = "0.1.9", features = ["full"] } +thiserror = "1.0.64" +#tokio = { version = "1.39.3", features = ["full"] } +#tokio-util = "0.7.11" tracing = "0.1.40" tracing-subscriber = "0.3.18" -tokio-stream = "0.1.15" -async-stream = "0.3.5" +tokio-stream = "0.1.16" +async-stream = "0.3.6" opener = "0.7.2" -anyhow = "1.0.86" +anyhow = "1.0.89" askama = { version = "0.12.1", features = ["serde-json"] } -serde = { version = "1.0.209", features = ["derive"] } +serde = { version = "1.0.210", features = ["derive"] } +smol = "2.0.2" +smol-macros = "0.1.1" +macro_rules_attribute = "0.2.0" +trie-hard = "0.1.0" +ctrlc = "3.4.5" +smol-hyper = "0.1.1" diff --git a/src/fs/exclude.rs b/src/fs/exclude.rs new file mode 100644 index 0000000..12a4d75 --- /dev/null +++ b/src/fs/exclude.rs @@ -0,0 +1,36 @@ +use std::sync::OnceLock; +use trie_hard::TrieHard; + +pub static EXCLUDE_FILES_BY_NAME: OnceLock> = OnceLock::new(); + +/// Files and directories to be excluded based on file names. +/// +/// These include metadata files of no interest, as well as files which may leak sensitive information. +pub fn exclude() -> TrieHard<'static, &'static str> { + [ + // .DS_Store meta files created by macOS are of no interest do us. We don't want to serve those. + ".DS_Store", + // If a .git directory is encountered, it is most likely because someone is serving + // directly from the root of a git repo, or from a directory that contains one or more + // git repos. + // + // In order to avoid having users accidentally leak git history which could contain + // sensitive information, we skip any file or directory named .git + // + // If the user really wants to serve .git directories, they should do so using + // another tool, rather than using http-horse for that. + // + // Of course, this simple name check will not protect you in the case of bare git repos. + // It is not meant as a bulletproof solution, but rather as a quick, simplistic protection + // against one particular kind of situation involving git repo history inside the served + // directory tree. + ".git", + // .htaccess files are intended for web servers, not to be served to clients. + // We skip any .htaccess files encountered, as they may contain sensitive information. + ".htaccess", + // .gitignore files are for .git, no point in serving those. + ".gitignore", + ] + .into_iter() + .collect::>() +} diff --git a/src/fs/mod.rs b/src/fs/mod.rs new file mode 100644 index 0000000..6679059 --- /dev/null +++ b/src/fs/mod.rs @@ -0,0 +1,2 @@ +pub mod exclude; +pub mod scan_project_dir; diff --git a/src/fs/scan_project_dir.rs b/src/fs/scan_project_dir.rs new file mode 100644 index 0000000..0ed370e --- /dev/null +++ b/src/fs/scan_project_dir.rs @@ -0,0 +1,107 @@ +//! Scan project dir + +use crate::fs::exclude::EXCLUDE_FILES_BY_NAME; +use futures_util::future::join_all; +use smol::fs::read_dir; +use smol::stream::StreamExt; +use std::fmt::Debug; +use std::os::unix::ffi::OsStrExt; +use std::path::PathBuf; +use std::sync::OnceLock; +use thiserror::Error; +use tracing::{debug, info}; +use trie_hard::TrieHard; + +#[derive(Debug, Error)] +pub enum Error { + #[error("I/O: {0}")] + IO(#[from] smol::io::Error), + #[error("Exclusion rules not initialized")] + ExcludeRulesNotInitialized, + #[error("A full re-scan of the project directory was attempted")] + FullRescanOfProjectDirWasAttempted, +} + +static I_HAVE_ALREADY_BEEN_RUN: OnceLock = OnceLock::new(); + +/// Call this function once, at program startup. +/// +/// Subsequent calls to this function should not be made. For staying up to date +/// with file system changes, file system event monitoring should be used. +pub async fn scan_project_dir(project_dir: PathBuf) -> Result<(), Error> { + let exclude = EXCLUDE_FILES_BY_NAME + .get() + .ok_or(Error::ExcludeRulesNotInitialized)?; + + // HEED THE RULES, OR SUFFER THE CONSEQUENCES! + I_HAVE_ALREADY_BEEN_RUN + .set(true) + .map_err(|_| Error::FullRescanOfProjectDirWasAttempted)?; + + scan_dir(project_dir, exclude).await +} + +async fn scan_dir(dir: PathBuf, exclude: &TrieHard<'static, &str>) -> Result<(), Error> { + info!(?dir, "Scanning directory"); + + let mut read_dir = read_dir(&dir).await?; + + //let mut files = vec![]; + + let mut subdir_futs = vec![]; + + while let Some(dir_entry) = read_dir.try_next().await? { + let file_name = dir_entry.file_name(); + debug!(?file_name, ?dir, "A dir entry was read from directory."); + if let Some(matched) = exclude.get(dir_entry.file_name().as_bytes()) { + info!( + file_name = matched, + ?dir, + "Skipping file based on exclusion rules." + ); + continue; + } + + // Symlinks are actually super useful, but because we want http-horse + // to never serve files from outside the project directory, it is + // convenient for http-horse to simply skip all symlinks for now. + // Even when they point to something else within the project directory. + // Consider raising an issue about this in our GitHub repo if your + // use-case for http-horse makes use of symlinks. + // + // In the future we may loosen this up so that symlinks pointing to + // something else within the project directory will be accepted, + // and properly treated. In that case we will have to keep track + // of which files are symlinks and when FS events affect files + // that are linked *to*, we will emit an update event for + // any symlinks pointing to that file. + // + // Further down the line after that, we may wish to loosen this up + // even further, so that if you symlink to something that is outside + // the project directory, but inside a git repo of which the project directory + // exists (and regardless of whether the project directory is tracked or git ignored), + // we would then allow, and watch, those too. Although that might be one step too far. + // + // Or, if not going as far as to allowing everything in the parent git repo to be linked to, + // we could allow symlinks that point to files in the "source directory" of the project, + // as indicated by the command line arguments provided to http-horse. + // + // TODO: ^ + let file_type = dir_entry.file_type().await?; + if file_type.is_symlink() { + info!(?file_name, ?dir, "Skipping file because it is a symlink."); + continue; + } + + if file_type.is_dir() { + let mut child_dir = dir.clone(); + child_dir.push(file_name); + subdir_futs.push(scan_dir(child_dir, exclude)); + } + } + + let res: Result, _> = join_all(subdir_futs).await.into_iter().collect(); + res?; + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d521fbd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod fs; diff --git a/src/main.rs b/src/main.rs index 8fa6c41..19bd754 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,12 @@ use askama::Template; use async_stream::stream; use bytes::Bytes; use clap::{crate_version, Parser, ValueEnum}; -use futures_util::TryStreamExt; +use futures_util::{select, FutureExt, TryStreamExt}; use http_body_util::{combinators::BoxBody, BodyExt, Either, Full, StreamBody}; +use http_horse::fs::{ + exclude::{exclude, EXCLUDE_FILES_BY_NAME}, + scan_project_dir::scan_project_dir, +}; use hyper::{ body::{Frame, Incoming}, header, @@ -13,8 +17,12 @@ use hyper::{ service::service_fn, Method, Request, Response, StatusCode, }; -use hyper_util::rt::TokioIo; +use macro_rules_attribute::apply; use serde::{Deserialize, Serialize}; +use smol::stream::StreamExt; +use smol::{fs::File, io::AsyncReadExt, net::TcpListener, Timer}; +use smol_hyper::rt::{FuturesIo, SmolExecutor, SmolTimer}; +use smol_macros::{main, Executor}; use std::{ io::ErrorKind, net::{IpAddr, SocketAddr}, @@ -24,8 +32,6 @@ use std::{ time::Duration, }; use thiserror::Error; -use tokio::{fs::File, net::TcpListener}; -use tokio_util::io::ReaderStream; use tracing::{debug, error, info, warn}; #[derive(Template)] @@ -110,11 +116,21 @@ enum ColorScheme { static PROJECT_DIR: OnceLock = OnceLock::new(); -#[tokio::main] -async fn main() -> anyhow::Result<()> { - // install global collector configured based on RUST_LOG env var. +#[apply(main!)] +async fn main(ex: &Executor<'_>) -> anyhow::Result<()> { + // Install global collector configured based on RUST_LOG env var. tracing_subscriber::fmt::init(); + // Ctrl-C handler + let (s, ctrl_c) = smol::channel::bounded(100); + ctrlc::set_handler(move || { + s.try_send(()) + .inspect_err(|e| error!(err = ?e, "Ctrl-C handler failed to send to channel.")) + .ok(); + }) + .inspect_err(|e| error!(err = ?e, "Failed to set Ctrl-C handler")) + .with_context(|| "Failed to set Ctrl-C handler.")?; + info!("Starting http-horse v{}", crate_version!()); let args = Cli::parse(); @@ -142,6 +158,13 @@ async fn main() -> anyhow::Result<()> { .inspect_err(|e| error!(existing_value = ?e, "Fatal: OnceLock has existing value.")) .map_err(|_| anyhow!("Failed to set value of OnceLock."))?; + EXCLUDE_FILES_BY_NAME + .set(exclude()) + .inspect_err(|e| error!(existing_value = ?e, "Fatal: OnceLock has existing value.")) + .map_err(|_| anyhow!("Failed to set value of OnceLock."))?; + + let project_files = ex.spawn(scan_project_dir(project_dir.clone())).await?; + // FsEvent takes strings as arguments. We always want to use the canonical path, // and because of that we have to convert back to String from PathBuf. let pdir = project_dir @@ -259,7 +282,7 @@ async fn main() -> anyhow::Result<()> { std::thread::sleep(Duration::from_millis(15)); // TODO: Create initial temp file in project dir // TODO: Start a timer so we can check how long has passed since we created initial temp file. - // TODO: Initial scan of project dir + // TODO: Integrate with initial scan of project dir 'skip_up_to_temp_file: loop { match project_out_fs_event_rx.recv() { Ok(fs_ev) => { @@ -316,7 +339,6 @@ async fn main() -> anyhow::Result<()> { let server = hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new()); let graceful = hyper_util::server::graceful::GracefulShutdown::new(); - let mut ctrl_c = pin!(tokio::signal::ctrl_c()); info!("Starting status and project servers."); // Skip printing hints if we are going to attempt to open the web browser for the user. @@ -345,9 +367,11 @@ async fn main() -> anyhow::Result<()> { } } + let mut spawned_tasks = vec![]; + // XXX: https://github.com/hyperium/hyper-util/blob/df55abac42d0cc1e1577f771d8a1fc91f4bcd0dd/examples/server_graceful.rs loop { - tokio::select! { + select! { /* * TODO: Enable TCP_NODELAY for accepted connections. * @@ -360,20 +384,21 @@ async fn main() -> anyhow::Result<()> { /* * Serving of files for the project that the user is working on. */ - project_conn = project_tcp.accept() => { + project_conn = project_tcp.accept().fuse() => { let (stream, peer_addr) = match project_conn { Ok(conn) => conn, Err(e) => { error!(err = ?e, "Accept error"); - tokio::time::sleep(Duration::from_secs(1)).await; + Timer::after(Duration::from_secs(1)).await; continue; } }; - debug!(?peer_addr, "Incoming connection accepted"); - let stream = TokioIo::new(Box::pin(stream)); + debug!(?peer_addr, "Incoming connection accepted on project_tcp"); + let stream = FuturesIo::new(stream); let conn = server.serve_connection_with_upgrades(stream, service_fn(request_handler_project)); let conn = graceful.watch(conn.into_owned()); - tokio::spawn(async move { + let task = ex.spawn(async move { + debug!("Spawned task for connection on connection from project_tcp."); if let Err(e) = conn.await { // We log this error at debug level because it is usually not interesting. // Known, uninteresting things (from error level logs perspective) @@ -393,25 +418,27 @@ async fn main() -> anyhow::Result<()> { } debug!(?peer_addr, "Connection dropped"); }); + spawned_tasks.push(task); }, /* * Serving of status pages, showing status and history. */ - status_conn = status_tcp.accept() => { + status_conn = status_tcp.accept().fuse() => { let (stream, peer_addr) = match status_conn { Ok(conn) => conn, Err(e) => { error!(err = ?e, "Accept error"); - tokio::time::sleep(Duration::from_secs(1)).await; + Timer::after(Duration::from_secs(1)).await; continue; } }; - debug!(?peer_addr, "Incoming connection accepted"); - let stream = TokioIo::new(Box::pin(stream)); + debug!(?peer_addr, "Incoming connection accepted on status_tcp"); + let stream = FuturesIo::new(stream); let conn = server.serve_connection_with_upgrades(stream, service_fn(request_handler_status)); let conn = graceful.watch(conn.into_owned()); - tokio::spawn(async move { + let task = ex.spawn(async move { + debug!("Spawned task for connection on connection from status_tcp."); if let Err(e) = conn.await { // We log this error at debug level because it is usually not interesting. // Known, uninteresting things (from error level logs perspective) @@ -431,9 +458,10 @@ async fn main() -> anyhow::Result<()> { } debug!(?peer_addr, "Connection dropped"); }); + spawned_tasks.push(task); }, - _ = ctrl_c.as_mut() => { + _ = ctrl_c.recv().fuse() => { drop(project_tcp); drop(status_tcp); info!("Ctrl-C received, starting shutdown"); @@ -461,7 +489,7 @@ fn event_stream() -> BoxBody { let mut i = 0; loop { // Sleep 250ms between each iteration so we don't overwhelm the web page with events. - tokio::time::sleep(Duration::from_millis(250)).await; + Timer::after(Duration::from_millis(250)).await; yield Ok(Bytes::from(format!("data: {{\"elem\": {i}}}\n\n"))); i += 1; } @@ -692,6 +720,8 @@ async fn handle_dir_request>( req_path_checked: P, response_builder: ResponseBuilder, ) -> HttpResult, BoxBody>>> { + // TODO: How to stream file with hyper, now that we use smol instead of tokio? + /* // 1. Try file "index.htm" if let Ok(file) = File::open(req_path_checked.as_ref().join("index.htm")).await { // Based on @@ -708,6 +738,7 @@ async fn handle_dir_request>( let boxed_body = BodyExt::boxed(stream_body); return response_builder.body(Either::Right(boxed_body)); } + */ // 3. Return a directory listing. (Note: This one needs to update itself as well.) // TODO: dir listing let (status, content_type, body) = not_found();