From 18b8748501f699a5c28ca18bf6966c96d29570b5 Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Sat, 23 Dec 2023 15:38:13 +0100 Subject: [PATCH] Prompt user for asciinema server URL when one not configured --- Cargo.lock | 248 +++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 1 + src/cmd/auth.rs | 4 +- src/cmd/upload.rs | 8 +- src/util.rs | 87 ++++++++++++++-- 5 files changed, 316 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1679ef5..dfbbc14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -62,7 +62,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -80,6 +80,7 @@ dependencies = [ "mio", "nix", "reqwest", + "rustyline", "serde", "serde_json", "signal-hook", @@ -207,6 +208,15 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "clipboard-win" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57002a5d9be777c1ef967e33674dac9ebd310d8893e4e3437b14d5f0f6372cc" +dependencies = [ + "error-code", +] + [[package]] name = "colorchoice" version = "1.0.0" @@ -247,12 +257,45 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "error-code" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "281e452d3bad4005426416cdba5ccfd4f5c1280e10099e21db27f7c1c28347fc" + +[[package]] +name = "fd-lock" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93f7a0db71c99f68398f80653ed05afb0b00e062e1a20c7ff849c4edfabbbcc" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "flate2" version = "1.0.28" @@ -380,6 +423,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "0.2.11" @@ -499,6 +551,12 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "log" version = "0.4.20" @@ -545,7 +603,16 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", ] [[package]] @@ -626,6 +693,16 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -698,7 +775,7 @@ dependencies = [ "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -707,6 +784,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rustls" version = "0.21.10" @@ -738,6 +828,28 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustyline" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + [[package]] name = "ryu" version = "1.0.15" @@ -836,6 +948,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + [[package]] name = "socket2" version = "0.5.5" @@ -843,7 +961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -930,7 +1048,7 @@ dependencies = [ "num_cpus", "pin-project-lite", "socket2", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1018,6 +1136,18 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "untrusted" version = "0.9.0" @@ -1153,13 +1283,44 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1168,13 +1329,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1183,42 +1359,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winreg" version = "0.50.0" @@ -1226,5 +1444,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index 43b78f4..7cb92cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,4 @@ signal-hook-mio = { version = "0.2.3", features = ["support-v0_8"] } signal-hook = "0.3.17" uuid = { version = "1.6.1", features = ["v4"] } reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "rustls-tls", "multipart", "gzip", "json"] } +rustyline = "13.0.0" diff --git a/src/cmd/auth.rs b/src/cmd/auth.rs index 7399945..b5c9dc1 100644 --- a/src/cmd/auth.rs +++ b/src/cmd/auth.rs @@ -6,7 +6,7 @@ use reqwest::Url; #[derive(Debug, Args)] pub struct Cli { /// asciinema server URL - server_url: String, + server_url: Option, } impl Cli { @@ -22,7 +22,7 @@ impl Cli { } fn auth_url(&self) -> Result { - let mut url = Url::parse(&self.server_url)?; + let mut url = util::get_server_url(self.server_url.as_ref())?; url.set_path(&format!("connect/{}", util::get_install_id()?)); Ok(url) diff --git a/src/cmd/upload.rs b/src/cmd/upload.rs index dbbaa8a..db8362c 100644 --- a/src/cmd/upload.rs +++ b/src/cmd/upload.rs @@ -14,7 +14,7 @@ pub struct Cli { filename: String, /// asciinema server URL - server_url: String, + server_url: Option, } #[derive(Debug, Deserialize)] @@ -59,10 +59,10 @@ impl Cli { } fn api_url(&self) -> Result { - let mut api_url = Url::parse(&self.server_url)?; - api_url.set_path("api/asciicasts"); + let mut url = util::get_server_url(self.server_url.as_ref())?; + url.set_path("api/asciicasts"); - Ok(api_url) + Ok(url) } } diff --git a/src/util.rs b/src/util.rs index e793258..fd22039 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,21 +1,36 @@ use anyhow::{anyhow, bail, Result}; +use reqwest::Url; use std::{env, fs, io::ErrorKind, path::Path, path::PathBuf}; use uuid::Uuid; -pub fn get_install_id() -> Result { - let default_path = state_home()?.join("install-id"); - let legacy_path = config_home()?.join("install-id"); +const DEFAULT_SERVER_URL: &str = "https://asciinema.org"; +const DEFAULT_SERVER_URL_FILENAME: &str = "default-server-url"; +const INSTALL_ID_FILENAME: &str = "install-id"; - if let Some(install_id) = read_install_id(&default_path)? { +pub fn get_install_id() -> Result { + if let Some(install_id) = read_install_id()? { Ok(install_id) - } else if let Some(install_id) = read_install_id(&legacy_path)? { + } else if let Some(install_id) = read_legacy_install_id()? { Ok(install_id) } else { - create_install_id(&default_path) + create_install_id() } } -fn read_install_id(path: &PathBuf) -> Result> { +fn read_install_id() -> Result> { + read_state_file(INSTALL_ID_FILENAME) +} + +fn create_install_id() -> Result { + let id = Uuid::new_v4().to_string(); + write_state_file(INSTALL_ID_FILENAME, &id)?; + + Ok(id) +} + +fn read_legacy_install_id() -> Result> { + let path = config_home()?.join(INSTALL_ID_FILENAME); + match fs::read_to_string(path) { Ok(s) => Ok(Some(s.trim().to_string())), @@ -29,16 +44,66 @@ fn read_install_id(path: &PathBuf) -> Result> { } } -fn create_install_id(path: &PathBuf) -> Result { - let id = Uuid::new_v4().to_string(); +pub fn get_server_url(server_url: Option) -> Result { + let mut url_opt = server_url + .map(|s| s.to_string()) + .or(env::var("ASCIINEMA_SERVER_URL").ok()) + .or(env::var("ASCIINEMA_API_URL").ok()); + + if url_opt.is_none() { + url_opt = read_state_file(DEFAULT_SERVER_URL_FILENAME)?; + } + + match url_opt { + Some(url) => Ok(Url::parse(&url)?), + + None => { + let url = Url::parse(&ask_for_server_url()?)?; + write_state_file(DEFAULT_SERVER_URL_FILENAME, url.as_ref())?; + + Ok(url) + } + } +} + +fn ask_for_server_url() -> Result { + println!("No asciinema server configured for this CLI."); + let mut rl = rustyline::DefaultEditor::new()?; + let url = rl.readline_with_initial( + "Enter the server URL to use by default: ", + (DEFAULT_SERVER_URL, ""), + )?; + println!(); + + Ok(url) +} + +fn read_state_file(filename: &str) -> Result> { + let path = state_home()?.join(filename); + + match fs::read_to_string(path) { + Ok(s) => Ok(Some(s.trim().to_string())), + + Err(e) => { + if e.kind() == ErrorKind::NotFound { + Ok(None) + } else { + bail!(e) + } + } + } +} + +fn write_state_file(filename: &str, contents: &str) -> Result<()> { + let path = state_home()?.join(filename); if let Some(dir) = path.parent() { fs::create_dir_all(dir)?; } - fs::write(path, &id)?; + fs::write(path, contents)?; - Ok(id) + Ok(()) } fn config_home() -> Result {