From 9f16385df01ee9b588e017e16363f4ff3197ad08 Mon Sep 17 00:00:00 2001 From: Dhruv Thakur <13575379+dhth@users.noreply.github.com> Date: Thu, 20 Mar 2025 23:49:42 +0100 Subject: [PATCH 1/6] feat: allow fetching bk title from remote server --- CHANGELOG.md | 6 + Cargo.lock | 1027 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 11 + src/args.rs | 22 +- src/cli/save.rs | 149 ++++-- src/errors.rs | 2 + src/handle.rs | 14 +- src/main.rs | 1 + src/service/fetch.rs | 40 ++ src/service/mod.rs | 3 + tests/save_test.rs | 110 ++++- 11 files changed, 1305 insertions(+), 80 deletions(-) create mode 100644 src/service/fetch.rs create mode 100644 src/service/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc9494..9225460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Allow fetching bookmark title from remote server + ## [v0.3.0] - Mar 10, 2025 ### Added diff --git a/Cargo.lock b/Cargo.lock index 77ed2ff..f092d2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,12 @@ dependencies = [ "num-traits", ] +[[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" @@ -222,6 +228,8 @@ dependencies = [ "pretty_assertions", "ratatui", "regex", + "reqwest", + "scraper", "select", "serde", "serde_json", @@ -245,6 +253,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + [[package]] name = "bytemuck" version = "1.22.0" @@ -299,6 +313,12 @@ 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.31" @@ -408,7 +428,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-graphics-types", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -506,6 +526,29 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.3", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.100", +] + [[package]] name = "csv" version = "1.3.1" @@ -573,6 +616,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derive_more" +version = "0.99.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "diff" version = "0.1.13" @@ -641,6 +695,27 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dtoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" + [[package]] name = "either" version = "1.15.0" @@ -650,6 +725,15 @@ dependencies = [ "serde", ] +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_home" version = "0.1.0" @@ -757,6 +841,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -764,7 +857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -778,6 +871,12 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -875,6 +974,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -895,6 +1003,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width 0.1.14", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -902,8 +1019,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -913,8 +1032,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.13.3+wasi-0.2.2", + "wasm-bindgen", "windows-targets 0.52.6", ] @@ -924,6 +1045,25 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "h2" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.15.2" @@ -991,12 +1131,137 @@ checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.11.0", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "html5ever" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +dependencies = [ + "log", + "mac", + "markup5ever 0.14.1", + "match_token", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "icu_collections" version = "1.5.0" @@ -1184,6 +1449,12 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + [[package]] name = "is-docker" version = "0.2.0" @@ -1230,6 +1501,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1328,8 +1609,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ "log", - "phf", - "phf_codegen", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf 0.11.3", + "phf_codegen 0.11.3", "string_cache", "string_cache_codegen", "tendril", @@ -1341,12 +1636,23 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9521dd6750f8e80ee6c53d65e2e4656d7de37064f3a7a5d2d11d05df93839c2" dependencies = [ - "html5ever", - "markup5ever", + "html5ever 0.26.0", + "markup5ever 0.11.0", "tendril", "xml5ever", ] +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "md-5" version = "0.10.6" @@ -1363,6 +1669,12 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "miniz_oxide" version = "0.8.5" @@ -1385,6 +1697,23 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1409,7 +1738,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "smallvec", "zeroize", ] @@ -1569,6 +1898,50 @@ dependencies = [ "pathdiff", ] +[[package]] +name = "openssl" +version = "0.10.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -1640,6 +2013,16 @@ dependencies = [ "phf_shared 0.10.0", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared 0.11.3", +] + [[package]] name = "phf_codegen" version = "0.10.0" @@ -1650,6 +2033,16 @@ dependencies = [ "phf_shared 0.10.0", ] +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + [[package]] name = "phf_generator" version = "0.10.0" @@ -1657,7 +2050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared 0.10.0", - "rand", + "rand 0.8.5", ] [[package]] @@ -1667,7 +2060,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared 0.11.3", - "rand", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.100", ] [[package]] @@ -1804,6 +2210,60 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quinn" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" +dependencies = [ + "bytes", + "getrandom 0.3.1", + "rand 0.9.0", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.39" @@ -1820,8 +2280,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "zerocopy", ] [[package]] @@ -1831,7 +2302,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1843,6 +2324,15 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.1", +] + [[package]] name = "ratatui" version = "0.29.0" @@ -1913,6 +2403,69 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "reqwest" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rsa" version = "0.9.7" @@ -1926,7 +2479,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core", + "rand_core 0.6.4", "signature", "spki", "subtle", @@ -1939,6 +2492,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "0.38.44" @@ -1965,6 +2524,49 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustls" +version = "0.23.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +dependencies = [ + "once_cell", + "ring", + "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.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +dependencies = [ + "web-time", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.20" @@ -1977,12 +2579,59 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scraper" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527e65d9d888567588db4c12da1087598d0f6f8b346cc2c5abc91f05fc2dffe2" +dependencies = [ + "cssparser", + "ego-tree", + "getopts", + "html5ever 0.29.1", + "precomputed-hash", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "select" version = "0.6.0" @@ -1990,10 +2639,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f9da09dc3f4dfdb6374cbffff7a2cffcec316874d4429899eefdc97b3b94dcd" dependencies = [ "bit-set", - "html5ever", + "html5ever 0.26.0", "markup5ever_rcdom", ] +[[package]] +name = "selectors" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8" +dependencies = [ + "bitflags 2.9.0", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.11.3", + "phf_codegen 0.11.3", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "serde" version = "1.0.219" @@ -2038,6 +2706,15 @@ dependencies = [ "serde", ] +[[package]] +name = "servo_arc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae65c4249478a2647db249fb43e23cec56a2c8974a427e7bd8cb5a1d0964921a" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2103,7 +2780,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -2285,7 +2962,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.5", "rsa", "serde", "sha1", @@ -2323,7 +3000,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand", + "rand 0.8.5", "serde", "serde_json", "sha2", @@ -2462,6 +3139,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -2473,6 +3159,27 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.18.0" @@ -2589,6 +3296,26 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -2600,6 +3327,46 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -2632,6 +3399,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "tui-input" version = "0.11.1" @@ -2704,6 +3477,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.4" @@ -2761,6 +3540,15 @@ dependencies = [ "libc", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2782,6 +3570,106 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.100", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.8" @@ -2832,6 +3720,41 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2883,13 +3806,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -2902,6 +3841,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -2914,6 +3859,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -2926,12 +3877,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -2944,6 +3907,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -2956,6 +3925,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -2968,6 +3943,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -2980,6 +3961,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winsafe" version = "0.0.19" @@ -3032,7 +4019,7 @@ checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.11.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index efd50b7..edec9dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,8 @@ once_cell = "1.20.3" open = "5.3.2" ratatui = "0.29.0" regex = "1.11.1" +reqwest = { version = "0.12.15", features = ["rustls-tls"] } +scraper = "0.23.1" select = "0.6.0" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" @@ -58,3 +60,12 @@ codegen-units = 1 # The profile that 'cargo dist' will build with [profile.dist] inherits = "release" + +[profile.release-local] +inherits = "dev" +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +incremental = false +codegen-units = 16 diff --git a/src/args.rs b/src/args.rs index 6b9b1b4..a62d5c7 100644 --- a/src/args.rs +++ b/src/args.rs @@ -108,6 +108,9 @@ pub enum BmmCommand { /// Ignore errors related to bookmark title and tags; if title is too long, it'll be trimmed, some invalid tags will be corrected #[arg(short = 'i', long = "ignore-attribute-errors")] ignore_attribute_errors: bool, + /// Whether to fetch bookmark title automatically + #[arg(short = 'F', long = "fetch")] + fetch: bool, }, /// Save/update multiple bookmarks SaveAll { @@ -294,16 +297,18 @@ ignore attribute errors : {} fail_if_uri_already_saved, reset_missing, ignore_attribute_errors, + fetch, } => format!( r#" -command : Save/update bookmark -URI : {} -title : {} -tags : {} -use editor : {} -fail if URI already saved : {} -reset missing : {} -ignore attribute errors : {} +command : Save/update bookmark +URI : {} +title : {} +tags : {} +use editor : {} +fail if URI already saved : {} +reset missing : {} +ignore attribute errors : {} +fetch details automatically : {} "#, uri, title.as_deref().unwrap_or(NOT_PROVIDED), @@ -312,6 +317,7 @@ ignore attribute errors : {} fail_if_uri_already_saved, reset_missing, ignore_attribute_errors, + fetch, ), BmmCommand::SaveAll { uris, diff --git a/src/cli/save.rs b/src/cli/save.rs index 623fb9b..e5ff5c7 100644 --- a/src/cli/save.rs +++ b/src/cli/save.rs @@ -1,8 +1,9 @@ use crate::common::{ENV_VAR_BMM_EDITOR, ENV_VAR_EDITOR}; -use crate::domain::{DraftBookmark, DraftBookmarkError, PotentialBookmark, SavedBookmark}; +use crate::domain::{DraftBookmark, DraftBookmarkError, PotentialBookmark}; use crate::persistence::{ DBError, SaveBookmarkOptions, create_or_update_bookmark, get_bookmark_with_exact_uri, }; +use crate::service::{FetchUriDetailsError, fetch_uri_details}; use regex::{Error as RegexError, Regex}; use sqlx::{Pool, Sqlite}; use std::fs::{File, OpenOptions}; @@ -27,6 +28,10 @@ pub enum SaveBookmarkError { CouldntSaveBookmark(DBError), #[error("something unexpected happened: {0}")] UnexpectedError(String), + #[error(transparent)] + CouldntFetchDetails(#[from] FetchUriDetailsError), + #[error("no details fetched from remote server")] + NoDetailsFetched, } #[derive(thiserror::Error, Debug)] @@ -59,64 +64,112 @@ pub enum ParsingTempFileContentError { InputMissing, } +pub struct SaveConfig { + pub use_editor: bool, + pub fail_if_uri_already_saved: bool, + pub reset_missing: bool, + pub ignore_attribute_errors: bool, + pub fetch: bool, +} + pub async fn save_bookmark( pool: &Pool, - potential_bookmark: PotentialBookmark, - use_editor: bool, - fail_if_uri_saved: bool, - reset_missing: bool, - ignore_attribute_errors: bool, + uri: String, + title: Option, + tags: &[String], + save_config: SaveConfig, ) -> Result<(), SaveBookmarkError> { - let maybe_existing_bookmark = get_bookmark_with_exact_uri(pool, &potential_bookmark.uri) + let maybe_existing_bookmark = get_bookmark_with_exact_uri(pool, &uri) .await .map_err(SaveBookmarkError::CouldntCheckIfBookmarkExists)?; - if fail_if_uri_saved && maybe_existing_bookmark.is_some() { + let bookmark_exists = maybe_existing_bookmark.is_some(); + + if save_config.fail_if_uri_already_saved && bookmark_exists { return Err(SaveBookmarkError::UriAlreadySaved); } if maybe_existing_bookmark.is_some() - && !use_editor - && potential_bookmark.title.is_none() - && potential_bookmark.tags.is_empty() + && !save_config.fetch + && !save_config.use_editor + && !save_config.reset_missing + && title.is_none() + && tags.is_empty() { println!("nothing to update!"); return Ok(()); } - let draft_bookmark = match use_editor { - true => match maybe_existing_bookmark { - Some(existing_bookmark) => { - let (title, tags) = get_bookmark_update_details_from_temp_file(&existing_bookmark)?; + let title_to_use = match title { + Some(t) => Some(t), + None => { + if save_config.fetch { + fetch_uri_details(&uri).await? + } else if save_config.reset_missing { + None + } else if save_config.use_editor { + maybe_existing_bookmark + .as_ref() + .and_then(|b| b.title.clone()) + } else { + None + } + } + }; - let potential_bookmark = PotentialBookmark::from(( - potential_bookmark.uri.as_str(), - title.as_deref(), - tags.as_deref(), - )); + if !save_config.use_editor && save_config.fetch && title_to_use.is_none() { + return Err(SaveBookmarkError::NoDetailsFetched); + } + + let tags_to_use = if !tags.is_empty() { + Some(tags.join(",").to_string()) + } else if save_config.reset_missing { + None + } else if save_config.use_editor { + maybe_existing_bookmark.and_then(|b| b.tags) + } else { + None + }; + + let draft_bookmark = match save_config.use_editor { + true => match bookmark_exists { + true => { + let (title, tags) = get_bookmark_update_details_from_temp_file( + uri.as_str(), + title_to_use.as_deref(), + tags_to_use.as_deref(), + )?; - DraftBookmark::try_from((potential_bookmark, ignore_attribute_errors))? - } - None => { let potential_bookmark = - get_new_bookmark_details_from_temp_file(&potential_bookmark.uri)?; + PotentialBookmark::from((uri.as_str(), title.as_deref(), tags.as_deref())); - DraftBookmark::try_from((potential_bookmark, ignore_attribute_errors))? + DraftBookmark::try_from((potential_bookmark, save_config.ignore_attribute_errors))? + } + false => { + let potential_bookmark = get_new_bookmark_details_from_temp_file( + &uri, + title_to_use.as_deref(), + tags_to_use.as_deref(), + )?; + + DraftBookmark::try_from((potential_bookmark, save_config.ignore_attribute_errors))? } }, - false => DraftBookmark::try_from((potential_bookmark, ignore_attribute_errors))?, + false => { + let potential_bookmark = + PotentialBookmark::from((uri.clone(), title_to_use, tags_to_use)); + DraftBookmark::try_from((potential_bookmark, save_config.ignore_attribute_errors))? + } }; - let reset_missing = if use_editor { true } else { reset_missing }; - let start = SystemTime::now(); let since_the_epoch = start .duration_since(UNIX_EPOCH) .map_err(|e| SaveBookmarkError::UnexpectedError(format!("system time error: {}", e)))?; let now = since_the_epoch.as_secs() as i64; let save_options = SaveBookmarkOptions { - reset_missing_attributes: reset_missing, - reset_tags: reset_missing, + reset_missing_attributes: save_config.reset_missing, + reset_tags: save_config.reset_missing, }; create_or_update_bookmark(pool, &draft_bookmark, now, save_options) .await @@ -126,7 +179,9 @@ pub async fn save_bookmark( } fn get_bookmark_update_details_from_temp_file( - bookmark: &SavedBookmark, + uri: &str, + title: Option<&str>, + tags: Option<&str>, ) -> Result<(Option, Option), CouldntGetDetailsViaEditorError> { let tmp_dir = tempdir().map_err(CouldntGetDetailsViaEditorError::CreateTempFile)?; @@ -139,7 +194,7 @@ fn get_bookmark_update_details_from_temp_file( .open(&tmp_file_path) .map_err(CouldntGetDetailsViaEditorError::OpenTempFile)?; - let file_contents = get_update_bookmark_tmp_file_contents(bookmark); + let file_contents = get_update_bookmark_tmp_file_contents(uri, title, tags); file.write_all(file_contents.as_bytes()) .map_err(CouldntGetDetailsViaEditorError::WriteToTempFile)?; @@ -166,6 +221,8 @@ fn get_bookmark_update_details_from_temp_file( fn get_new_bookmark_details_from_temp_file( uri: &str, + title: Option<&str>, + tags: Option<&str>, ) -> Result { let tmp_dir = tempdir().map_err(CouldntGetDetailsViaEditorError::CreateTempFile)?; @@ -178,7 +235,7 @@ fn get_new_bookmark_details_from_temp_file( .open(&tmp_file_path) .map_err(CouldntGetDetailsViaEditorError::OpenTempFile)?; - let file_contents = get_create_bookmark_tmp_file_contents(uri); + let file_contents = get_create_bookmark_tmp_file_contents(uri, title, tags); file.write_all(file_contents.as_bytes()) .map_err(CouldntGetDetailsViaEditorError::WriteToTempFile)?; @@ -232,7 +289,11 @@ fn get_text_editor_exe() -> Result<(String, String), CouldntGetDetailsViaEditorE Err(CouldntGetDetailsViaEditorError::NoEditorConfigured) } -fn get_update_bookmark_tmp_file_contents(bookmark: &SavedBookmark) -> String { +fn get_update_bookmark_tmp_file_contents( + uri: &str, + title: Option<&str>, + tags: Option<&str>, +) -> String { format!( r#" __ @@ -257,13 +318,17 @@ Comma separate tags: {} <<< "#, - bookmark.uri, - bookmark.title.as_deref().unwrap_or_default(), - bookmark.tags.as_deref().unwrap_or_default(), + uri, + title.unwrap_or_default(), + tags.unwrap_or_default(), ) } -fn get_create_bookmark_tmp_file_contents(uri: &str) -> String { +fn get_create_bookmark_tmp_file_contents( + uri: &str, + title: Option<&str>, + tags: Option<&str>, +) -> String { format!( r#" __ @@ -282,15 +347,17 @@ URI: Title: >>> - +{} <<< Comma separated tags: >>> - +{} <<< "#, - uri + uri, + title.unwrap_or_default(), + tags.unwrap_or_default(), ) } diff --git a/src/errors.rs b/src/errors.rs index 51311a8..fc8efd2 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -102,6 +102,8 @@ impl AppError { }, }, SaveBookmarkError::UnexpectedError(_) => Some(580), + SaveBookmarkError::CouldntFetchDetails(_) => None, + SaveBookmarkError::NoDetailsFetched => None, }, AppError::CouldntShowBookmark(e) => match e { ShowBookmarkError::CouldntGetBookmarkFromDB(_) => Some(600), diff --git a/src/handle.rs b/src/handle.rs index fd278d5..b967f8e 100644 --- a/src/handle.rs +++ b/src/handle.rs @@ -1,6 +1,5 @@ use crate::args::{Args, BmmCommand, TagsCommand}; use crate::cli::*; -use crate::domain::PotentialBookmark; use crate::errors::AppError; use crate::persistence::get_db_pool; use crate::tui::{TuiContext, run_tui}; @@ -85,18 +84,17 @@ pub async fn handle(args: Args) -> Result<(), AppError> { fail_if_uri_already_saved, reset_missing, ignore_attribute_errors, + fetch, } => { - let potential_bookmark = PotentialBookmark::from((uri, title, &tags)); - - save_bookmark( - &pool, - potential_bookmark, + let save_config = SaveConfig { use_editor, fail_if_uri_already_saved, reset_missing, ignore_attribute_errors, - ) - .await? + fetch, + }; + + save_bookmark(&pool, uri, title, &tags, save_config).await? } BmmCommand::SaveAll { diff --git a/src/main.rs b/src/main.rs index 01f6369..8c3a377 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod domain; mod errors; mod handle; mod persistence; +mod service; mod tui; mod utils; diff --git a/src/service/fetch.rs b/src/service/fetch.rs new file mode 100644 index 0000000..b33b7eb --- /dev/null +++ b/src/service/fetch.rs @@ -0,0 +1,40 @@ +use reqwest::Error as ReqwestError; +use reqwest::get; +use scraper::{Html, Selector}; +use url::{ParseError, Url}; + +#[derive(thiserror::Error, Debug)] +pub enum FetchUriDetailsError { + #[error("uri is incorrect: {0}")] + IncorrectUri(#[from] ParseError), + #[error(transparent)] + RequestUri(#[from] ReqwestError), +} + +pub async fn fetch_uri_details(uri: &str) -> Result, FetchUriDetailsError> { + Url::parse(uri)?; + let body = get(uri).await?.text().await?; + + let document = Html::parse_document(&body); + + #[allow(clippy::unwrap_used)] + let title_selector = Selector::parse("title").unwrap(); + + #[allow(clippy::unwrap_used)] + let og_title_selector = Selector::parse(r#"meta[property="og:title"]"#).unwrap(); + + let og_title = document + .select(&og_title_selector) + .next() + .and_then(|element| element.value().attr("content")) + .map(|s| s.trim().to_string()); + + let title = og_title.or_else(|| { + document + .select(&title_selector) + .next() + .map(|element| element.inner_html().trim().to_string()) + }); + + Ok(title) +} diff --git a/src/service/mod.rs b/src/service/mod.rs new file mode 100644 index 0000000..e11fb52 --- /dev/null +++ b/src/service/mod.rs @@ -0,0 +1,3 @@ +mod fetch; + +pub use fetch::*; diff --git a/tests/save_test.rs b/tests/save_test.rs index a38312b..9c8b3d4 100644 --- a/tests/save_test.rs +++ b/tests/save_test.rs @@ -51,6 +51,37 @@ fn saving_a_new_bookmark_with_title_and_tags_works() { ))); } +#[test] +fn updating_bookmarks_with_no_new_data_works() { + // GIVEN + let fixture = Fixture::new(); + let mut create_cmd = fixture.command(); + create_cmd.args([ + "save", + URI_ONE, + "--title", + "bmm's github page", + "--tags", + "tools,productivity", + ]); + create_cmd.output().expect("command should've run"); + let mut cmd = fixture.command(); + cmd.args(["save", URI_ONE]); + + // WHEN + // THEN + cmd.assert() + .success() + .stdout(contains("nothing to update!")); + + let mut list_cmd = fixture.command(); + list_cmd.args(["list", "-f", "delimited"]); + list_cmd.assert().success().stdout(contains(format!( + r#"{},bmm's github page,"productivity,tools"#, + URI_ONE + ))); +} + #[test] fn extending_tags_for_a_saved_bookmark_works() { // GIVEN @@ -81,7 +112,65 @@ fn extending_tags_for_a_saved_bookmark_works() { } #[test] -fn resetting_properties_on_bookmark_update_works() { +fn resetting_all_data_for_a_bookmark_works() { + // GIVEN + let fixture = Fixture::new(); + let mut create_cmd = fixture.command(); + create_cmd.args([ + "save", + URI_ONE, + "--title", + "bmm's github page", + "--tags", + "tools,productivity", + ]); + create_cmd.output().expect("command should've run"); + let mut cmd = fixture.command(); + cmd.args(["save", URI_ONE, "-r"]); + + // WHEN + // THEN + cmd.assert().success(); + + let mut list_cmd = fixture.command(); + list_cmd.args(["list", "-f", "delimited"]); + list_cmd + .assert() + .success() + .stdout(contains(format!("{},,", URI_ONE))); +} + +#[test] +fn resetting_title_on_bookmark_update_works() { + // GIVEN + let fixture = Fixture::new(); + let mut create_cmd = fixture.command(); + create_cmd.args([ + "save", + URI_ONE, + "--title", + "bmm's github page", + "--tags", + "tools,productivity", + ]); + create_cmd.output().expect("command should've run"); + let mut cmd = fixture.command(); + cmd.args(["save", URI_ONE, "--tags", "updated,tags", "-r"]); + + // WHEN + // THEN + cmd.assert().success(); + + let mut list_cmd = fixture.command(); + list_cmd.args(["list", "-f", "delimited"]); + list_cmd + .assert() + .success() + .stdout(contains(format!(r#"{},,"tags,updated"#, URI_ONE))); +} + +#[test] +fn resetting_tags_on_bookmark_update_works() { // GIVEN let fixture = Fixture::new(); let mut create_cmd = fixture.command(); @@ -95,7 +184,7 @@ fn resetting_properties_on_bookmark_update_works() { ]); create_cmd.output().expect("command should've run"); let mut cmd = fixture.command(); - cmd.args(["save", URI_ONE, "--tags", "cli,bookmarks", "-r"]); + cmd.args(["save", URI_ONE, "--title", "updated title", "-r"]); // WHEN // THEN @@ -106,7 +195,7 @@ fn resetting_properties_on_bookmark_update_works() { list_cmd .assert() .success() - .stdout(contains(format!(r#"{},,"bookmarks,cli"#, URI_ONE))); + .stdout(contains(format!("{},updated title,", URI_ONE))); } #[test] @@ -211,6 +300,21 @@ fn saving_a_new_bookmark_with_an_invalid_tag_fails() { )); } +#[test] +fn updating_a_bookmarks_with_no_new_details_fails_if_requested() { + // GIVEN + let fixture = Fixture::new(); + let mut create_cmd = fixture.command(); + create_cmd.args(["save", URI_ONE]); + create_cmd.output().expect("command should've run"); + let mut cmd = fixture.command(); + cmd.args(["save", URI_ONE, "-f"]); + + // WHEN + // THEN + cmd.assert().failure().stderr(contains("uri already saved")); +} + #[test] fn saving_a_new_bookmark_with_no_text_editor_configured_fails() { // GIVEN From 340fc5c0ceab64605c4dbe2364cd1a608c695f87 Mon Sep 17 00:00:00 2001 From: Dhruv Thakur <13575379+dhth@users.noreply.github.com> Date: Fri, 21 Mar 2025 00:52:51 +0100 Subject: [PATCH 2/6] test: add integration test for remote fetching --- .github/workflows/test.yml | 13 ++- src/cli/save.rs | 2 +- src/service/fetch.rs | 124 +++++++++++++++++++++++++- tests/save_test.rs | 48 ++++++++++ tests/static/local-server/simple.html | 17 ++++ 5 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 tests/static/local-server/simple.html diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 73ca8a4..6ff1521 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,11 @@ jobs: - uses: actions/checkout@v4 - name: Install toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Install miniserve + uses: jaxxstorm/action-install-gh-release@4304621e8c48d66093a8a214af5d5b5bc3b3d943 + with: + repo: svenstaro/miniserve + tag: v0.29.0 - name: Install sqlx-cli run: cargo install sqlx-cli --version=${{ env.SQLX_VERSION }} --features ${{ env.SQLX_FEATURES }} --no-default-features --locked - name: Create test database @@ -33,5 +38,11 @@ jobs: cargo sqlx database create cargo sqlx migrate run cargo sqlx prepare --check + - name: Start local http server + run: | + miniserve tests/static/local-server --index empty.html --port 8200 & + sleep 3 - name: Run tests - run: cargo test + run: cargo test -- --include-ignored + - name: Kill local server + run: pkill miniserve diff --git a/src/cli/save.rs b/src/cli/save.rs index e5ff5c7..fb1fc70 100644 --- a/src/cli/save.rs +++ b/src/cli/save.rs @@ -28,7 +28,7 @@ pub enum SaveBookmarkError { CouldntSaveBookmark(DBError), #[error("something unexpected happened: {0}")] UnexpectedError(String), - #[error(transparent)] + #[error("couldn't fetch details: {0}")] CouldntFetchDetails(#[from] FetchUriDetailsError), #[error("no details fetched from remote server")] NoDetailsFetched, diff --git a/src/service/fetch.rs b/src/service/fetch.rs index b33b7eb..0fa510f 100644 --- a/src/service/fetch.rs +++ b/src/service/fetch.rs @@ -15,7 +15,11 @@ pub async fn fetch_uri_details(uri: &str) -> Result, FetchUriDeta Url::parse(uri)?; let body = get(uri).await?.text().await?; - let document = Html::parse_document(&body); + Ok(get_title_from_html(&body)) +} + +fn get_title_from_html(html: &str) -> Option { + let document = Html::parse_document(html); #[allow(clippy::unwrap_used)] let title_selector = Selector::parse("title").unwrap(); @@ -36,5 +40,121 @@ pub async fn fetch_uri_details(uri: &str) -> Result, FetchUriDeta .map(|element| element.inner_html().trim().to_string()) }); - Ok(title) + title +} + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + + //-------------// + // SUCCESSES // + //-------------// + + #[test] + fn parsing_simple_html_works() { + // GIVEN + let html = r#" + + + + + + dhth/bmm: get to your bookmarks in a flash + + +

bmm

+

get to your bookmarks in a flash

+ + +"#; + + // WHEN + let title = get_title_from_html(html).expect("title should've been found"); + + // THEN + assert_eq!(title, "dhth/bmm: get to your bookmarks in a flash"); + } + + #[test] + fn parsing_html_with_og_tags_only_works() { + // GIVEN + let html = r#" +GitHub - dhth/bmm: get to your bookmarks in a flash + + + + + + + +"#; + + // WHEN + let title = get_title_from_html(html).expect("title should've been found"); + + // THEN + assert_eq!(title, "dhth/bmm: get to your bookmarks in a flash"); + } + + #[test] + fn parsing_html_with_both_title_and_og_tags_works() { + // GIVEN + let html = r#" + + + + + + dhth/bmm + + + + + + + +

bmm

+

get to your bookmarks in a flash

+ + +"#; + + // WHEN + let title = get_title_from_html(html).expect("title should've been found"); + + // THEN + assert_eq!(title, "dhth/bmm: get to your bookmarks in a flash"); + } + + #[test] + fn parsing_empty_html_works() { + // GIVEN + let html = r#" + + + +"#; + + // WHEN + let title = get_title_from_html(html); + + // THEN + assert!(title.is_none()); + } + + #[test] + fn parsing_incorrect_html_works() { + // GIVEN + let html = r#" +not:::html +"#; + + // WHEN + let title = get_title_from_html(html); + + // THEN + assert!(title.is_none()); + } } diff --git a/tests/save_test.rs b/tests/save_test.rs index 9c8b3d4..8d1b3ac 100644 --- a/tests/save_test.rs +++ b/tests/save_test.rs @@ -4,6 +4,7 @@ use predicates::prelude::PredicateBooleanExt; use predicates::str::contains; const URI_ONE: &str = "https://github.com/dhth/bmm"; +pub const LOCAL_SERVER_ADDRESS: &str = "http://127.0.0.1:8200"; //-------------// // SUCCESSES // @@ -264,6 +265,37 @@ Tags : another-invalid-tag,invalid-tag,tag1 )); } +#[test] +#[ignore = "requires a local http server"] +fn fetching_title_from_remote_server_works() { + // GIVEN + let fixture = Fixture::new(); + let mut cmd = fixture.command(); + let uri = format!("{}/simple.html", LOCAL_SERVER_ADDRESS); + cmd.args(["save", &uri, "--tags", "auto,fetch", "-F"]); + + // WHEN + // THEN + cmd.assert().success(); + + let mut show_cmd = fixture.command(); + show_cmd.args(["show", &uri]); + show_cmd.assert().success().stdout(contains( + format!( + r#" +Bookmark details +--- + +Title: dhth/bmm: get to your bookmarks in a flash +URI : {} +Tags : auto,fetch + "#, + uri, + ) + .trim(), + )); +} + //------------// // FAILURES // //------------// @@ -348,3 +380,19 @@ fn saving_a_new_bookmark_with_incorrect_text_editor_configured_fails() { .failure() .stderr(contains("cannot find binary path")); } + +#[test] +#[ignore = "sends an HTTP request to localhost"] +fn fetching_details_for_non_existent_uri_should_fail() { + // GIVEN + let fixture = Fixture::new(); + let mut cmd = fixture.command(); + let uri = "http://127.0.0.1:9999/non-existent.html"; + cmd.args(["save", uri, "-F"]); + + // WHEN + // THEN + cmd.assert() + .failure() + .stderr(contains("couldn't fetch details")); +} diff --git a/tests/static/local-server/simple.html b/tests/static/local-server/simple.html new file mode 100644 index 0000000..5b45ca9 --- /dev/null +++ b/tests/static/local-server/simple.html @@ -0,0 +1,17 @@ + + + + + + dhth/bmm + + + + + + + +

bmm

+

get to your bookmarks in a flash

+ + From 8a05852198b7395746dfb061eeaa91a788cdd858 Mon Sep 17 00:00:00 2001 From: Dhruv Thakur <13575379+dhth@users.noreply.github.com> Date: Fri, 21 Mar 2025 00:54:44 +0100 Subject: [PATCH 3/6] fix: try without the v prefix --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6ff1521..826f5dd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: uses: jaxxstorm/action-install-gh-release@4304621e8c48d66093a8a214af5d5b5bc3b3d943 with: repo: svenstaro/miniserve - tag: v0.29.0 + tag: 0.29.0 - name: Install sqlx-cli run: cargo install sqlx-cli --version=${{ env.SQLX_VERSION }} --features ${{ env.SQLX_FEATURES }} --no-default-features --locked - name: Create test database From 5e5a79f7003082fdb629d4eeff2d2107965cffa5 Mon Sep 17 00:00:00 2001 From: Dhruv Thakur <13575379+dhth@users.noreply.github.com> Date: Fri, 21 Mar 2025 01:00:53 +0100 Subject: [PATCH 4/6] fix: try providing asset name --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 826f5dd..98cba36 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,6 +29,7 @@ jobs: uses: jaxxstorm/action-install-gh-release@4304621e8c48d66093a8a214af5d5b5bc3b3d943 with: repo: svenstaro/miniserve + asset-name: miniserve-0.29.0 tag: 0.29.0 - name: Install sqlx-cli run: cargo install sqlx-cli --version=${{ env.SQLX_VERSION }} --features ${{ env.SQLX_FEATURES }} --no-default-features --locked From 28ecdb12edb2e5fc20dbbdbc2f84d9e3e98b1577 Mon Sep 17 00:00:00 2001 From: Dhruv Thakur <13575379+dhth@users.noreply.github.com> Date: Fri, 21 Mar 2025 01:03:55 +0100 Subject: [PATCH 5/6] fix: try using taiki-e/install-action --- .github/workflows/test.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 98cba36..2037127 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,11 +26,9 @@ jobs: - name: Install toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install miniserve - uses: jaxxstorm/action-install-gh-release@4304621e8c48d66093a8a214af5d5b5bc3b3d943 + uses: taiki-e/install-action@351cce3d3afa3dbd66bbe6d30df1d481b1448522 with: - repo: svenstaro/miniserve - asset-name: miniserve-0.29.0 - tag: 0.29.0 + tool: miniserve - name: Install sqlx-cli run: cargo install sqlx-cli --version=${{ env.SQLX_VERSION }} --features ${{ env.SQLX_FEATURES }} --no-default-features --locked - name: Create test database From 04305297b954be59ae1026b7af6ec82db9f2b85d Mon Sep 17 00:00:00 2001 From: Dhruv Thakur <13575379+dhth@users.noreply.github.com> Date: Fri, 21 Mar 2025 01:05:42 +0100 Subject: [PATCH 6/6] ci: use correct command --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2037127..15852ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,7 @@ jobs: cargo sqlx prepare --check - name: Start local http server run: | - miniserve tests/static/local-server --index empty.html --port 8200 & + miniserve tests/static/local-server --port 8200 & sleep 3 - name: Run tests run: cargo test -- --include-ignored