From 7436e4ff651b64d4019a59d04c30c414ae220403 Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Fri, 22 Apr 2022 21:14:23 +0100 Subject: [PATCH] feature-flags (#328) * use feature flags * fmt * fix features * update ci * fmt Co-authored-by: Ellie Huxtable --- .github/workflows/rust.yml | 14 +++++- Cargo.lock | 18 ++----- Cargo.toml | 19 ++++--- atuin-client/Cargo.toml | 37 +++++++++----- atuin-client/src/api_client.rs | 2 +- atuin-client/src/encryption.rs | 4 +- atuin-client/src/lib.rs | 8 ++- src/command/client.rs | 44 ++++------------ src/command/client/history.rs | 11 +++- src/command/client/sync.rs | 61 ++++++++++++++++++++--- src/command/client/{ => sync}/login.rs | 0 src/command/client/{ => sync}/logout.rs | 0 src/command/client/{ => sync}/register.rs | 0 src/command/mod.rs | 4 ++ 14 files changed, 141 insertions(+), 81 deletions(-) rename src/command/client/{ => sync}/login.rs (100%) rename src/command/client/{ => sync}/logout.rs (100%) rename src/command/client/{ => sync}/register.rs (100%) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ad81417..3c39fa2 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -63,7 +63,19 @@ jobs: key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }} - name: Run cargo test - run: ATUIN_SESSION=beepboopiamasession cargo test --workspace + run: cargo test --all-features --workspace + + - name: Run cargo check (all features) + run: cargo check --all-features --workspace + + - name: Run cargo check (no features) + run: cargo check --no-default-features --workspace + + - name: Run cargo check (sync) + run: cargo check --no-default-features --features sync --workspace + + - name: Run cargo check (server) + run: cargo check --no-default-features --features server --workspace clippy: runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 7afd0df..21c7187 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,7 +113,6 @@ dependencies = [ "log", "minspan", "parse_duration", - "rand 0.8.5", "regex", "reqwest", "rmp-serde", @@ -761,12 +760,6 @@ dependencies = [ "parking_lot 0.11.2", ] -[[package]] -name = "futures-io" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" - [[package]] name = "futures-sink" version = "0.3.21" @@ -786,10 +779,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-core", - "futures-io", "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", @@ -1804,19 +1795,20 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f55e5fa1446c4d5dd1f5daeed2a4fe193071771a2636274d0d7a3b082aa7ad6" +checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" dependencies = [ "byteorder", "num-traits", + "paste", ] [[package]] name = "rmp-serde" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3eedffbfcc6a428f230c04baf8f59bd73c1781361e4286111fe900849aaddaf" +checksum = "25786b0d276110195fa3d6f3f31299900cf71dfbd6c28450f3f58a0e7f7a347e" dependencies = [ "byteorder", "rmp", diff --git a/Cargo.toml b/Cargo.toml index 5eb3d2c..0b1bda0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,17 @@ atuin = { path = "/usr/bin/atuin" } [workspace] members = ["./atuin-client", "./atuin-server", "./atuin-common"] +[features] +# TODO(conradludgate) +# Currently, this keeps the same default built behaviour for v0.8 +# We should rethink this by the time we hit a new breaking change +default = ["sync", "server"] +sync = ["atuin-client/sync"] +server = ["atuin-server", "tracing-subscriber"] + [dependencies] -atuin-server = { path = "atuin-server", version = "0.8.1" } -atuin-client = { path = "atuin-client", version = "0.8.1" } +atuin-server = { path = "atuin-server", version = "0.8.1", optional = true } +atuin-client = { path = "atuin-client", version = "0.8.1", default-features = false } atuin-common = { path = "atuin-common", version = "0.8.1" } log = "0.4" @@ -59,7 +67,6 @@ clap_complete = "3.1.2" fs-err = "2.7" whoami = "1.1.2" - [dependencies.tracing-subscriber] version = "0.3" default-features = false @@ -69,8 +76,4 @@ features = [ "registry", "env-filter", ] - -[profile.release] -lto = "fat" -codegen-units = 1 -opt-level = 3 +optional = true diff --git a/atuin-client/Cargo.toml b/atuin-client/Cargo.toml index 49ff933..c3a567d 100644 --- a/atuin-client/Cargo.toml +++ b/atuin-client/Cargo.toml @@ -10,6 +10,17 @@ repository = "https://github.com/ellie/atuin" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["sync"] +sync = [ + "urlencoding", + "sodiumoxide", + "reqwest", + "rust-crypto", + "rmp-serde", + "base64", +] + [dependencies] atuin-common = { path = "../atuin-common", version = "0.8.1" } @@ -23,20 +34,8 @@ chrono-english = "0.1.4" config = "0.13" serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.75" -rmp-serde = "1.0.0" -sodiumoxide = "0.2.6" -reqwest = { version = "0.11", features = [ - "blocking", - "json", - "rustls-tls", -], default-features = false } -base64 = "0.13.0" parse_duration = "2.1.1" -rand = "0.8.4" -rust-crypto = "^0.2" -tokio = { version = "1", features = ["full"] } async-trait = "0.1.49" -urlencoding = "2.1.0" itertools = "0.10.3" shellexpand = "2" sqlx = { version = "0.5", features = [ @@ -48,3 +47,17 @@ sqlx = { version = "0.5", features = [ minspan = "0.1.1" regex = "1.5.4" fs-err = "2.7" + +# sync +urlencoding = { version = "2.1.0", optional = true } +sodiumoxide = { version = "0.2.6", optional = true } +reqwest = { version = "0.11", features = [ + "json", + "rustls-tls", +], default-features = false, optional = true } +rust-crypto = { version = "^0.2", optional = true } +rmp-serde = { version = "1.0.0", optional = true } +base64 = { version = "0.13.0", optional = true } + +[dev-dependencies] +tokio = { version = "1", features = ["full"] } diff --git a/atuin-client/src/api_client.rs b/atuin-client/src/api_client.rs index 171012a..d907265 100644 --- a/atuin-client/src/api_client.rs +++ b/atuin-client/src/api_client.rs @@ -38,7 +38,7 @@ pub async fn register( map.insert("password", password); let url = format!("{}/user/{}", address, username); - let resp = reqwest::blocking::get(url)?; + let resp = reqwest::get(url).await?; if resp.status().is_success() { bail!("username already in use"); diff --git a/atuin-client/src/encryption.rs b/atuin-client/src/encryption.rs index 4746c23..f805cbd 100644 --- a/atuin-client/src/encryption.rs +++ b/atuin-client/src/encryption.rs @@ -77,7 +77,7 @@ pub fn encode_key(key: secretbox::Key) -> Result { pub fn decode_key(key: String) -> Result { let buf = base64::decode(key).wrap_err("encryption key is not a valid base64 encoding")?; - let buf: secretbox::Key = rmp_serde::from_read_ref(&buf) + let buf: secretbox::Key = rmp_serde::from_slice(&buf) .wrap_err("encryption key is not a valid message pack encoding")?; Ok(buf) @@ -98,7 +98,7 @@ pub fn decrypt(encrypted_history: &EncryptedHistory, key: &secretbox::Key) -> Re let plaintext = secretbox::open(&encrypted_history.ciphertext, &encrypted_history.nonce, key) .map_err(|_| eyre!("failed to open secretbox - invalid key?"))?; - let history = rmp_serde::from_read_ref(&plaintext)?; + let history = rmp_serde::from_slice(&plaintext)?; Ok(history) } diff --git a/atuin-client/src/lib.rs b/atuin-client/src/lib.rs index 98e2f3a..497c5e7 100644 --- a/atuin-client/src/lib.rs +++ b/atuin-client/src/lib.rs @@ -3,11 +3,15 @@ #[macro_use] extern crate log; +#[cfg(feature = "sync")] pub mod api_client; -pub mod database; +#[cfg(feature = "sync")] pub mod encryption; +#[cfg(feature = "sync")] +pub mod sync; + +pub mod database; pub mod history; pub mod import; pub mod ordering; pub mod settings; -pub mod sync; diff --git a/src/command/client.rs b/src/command/client.rs index fd65345..4858e2b 100644 --- a/src/command/client.rs +++ b/src/command/client.rs @@ -8,16 +8,16 @@ use atuin_client::database::Sqlite; use atuin_client::settings::Settings; use atuin_common::utils::uuid_v4; +#[cfg(feature = "sync")] +mod sync; + mod event; mod history; mod import; mod init; -mod login; -mod logout; -mod register; mod search; mod stats; -mod sync; + use std::path::PathBuf; #[derive(Subcommand)] @@ -45,25 +45,6 @@ pub enum Cmd { /// Interactive history search Search(search::Cmd), - /// Sync with the configured server - Sync { - /// Force re-download everything - #[clap(long, short)] - force: bool, - }, - - /// Login to the configured server - Login(login::Cmd), - - /// Log out - Logout, - - /// Register with the configured server - Register(register::Cmd), - - /// Print the encryption key for transfer to another machine - Key, - /// Generate shell completions GenCompletions { /// Set the shell for generating completions @@ -74,6 +55,10 @@ pub enum Cmd { #[clap(long, short)] out_dir: Option, }, + + #[cfg(feature = "sync")] + #[clap(flatten)] + Sync(sync::Cmd), } impl Cmd { @@ -94,17 +79,6 @@ impl Cmd { Ok(()) } Self::Search(search) => search.run(&mut db, &settings).await, - Self::Sync { force } => sync::run(&settings, force, &mut db).await, - Self::Login(l) => l.run(&settings).await, - Self::Logout => logout::run(), - Self::Register(r) => r.run(&settings).await, - Self::Key => { - use atuin_client::encryption::{encode_key, load_key}; - let key = load_key(&settings).wrap_err("could not load encryption key")?; - let encode = encode_key(key).wrap_err("could not encode encryption key")?; - println!("{}", encode); - Ok(()) - } Self::Uuid => { println!("{}", uuid_v4()); Ok(()) @@ -128,6 +102,8 @@ impl Cmd { Ok(()) } + #[cfg(feature = "sync")] + Self::Sync(sync) => sync.run(settings, &mut db).await, } } } diff --git a/src/command/client/history.rs b/src/command/client/history.rs index 994cbfd..4f96c44 100644 --- a/src/command/client/history.rs +++ b/src/command/client/history.rs @@ -9,6 +9,8 @@ use tabwriter::TabWriter; use atuin_client::database::{current_context, Database}; use atuin_client::history::History; use atuin_client::settings::Settings; + +#[cfg(feature = "sync")] use atuin_client::sync; #[derive(Subcommand)] @@ -143,8 +145,13 @@ impl Cmd { db.update(&h).await?; if settings.should_sync()? { - debug!("running periodic background sync"); - sync::sync(settings, false, db).await?; + #[cfg(feature = "sync")] + { + debug!("running periodic background sync"); + sync::sync(settings, false, db).await?; + } + #[cfg(not(feature = "sync"))] + debug!("not compiled with sync support"); } else { debug!("sync disabled! not syncing"); } diff --git a/src/command/client/sync.rs b/src/command/client/sync.rs index f8bfd5e..8e80310 100644 --- a/src/command/client/sync.rs +++ b/src/command/client/sync.rs @@ -1,15 +1,64 @@ -use eyre::Result; - use atuin_client::database::Database; -use atuin_client::settings::Settings; -use atuin_client::sync; +use clap::Subcommand; +use eyre::{Result, WrapErr}; -pub async fn run( +use atuin_client::settings::Settings; + +mod login; +mod logout; +mod register; + +#[derive(Subcommand)] +#[clap(infer_subcommands = true)] +pub enum Cmd { + /// Sync with the configured server + Sync { + /// Force re-download everything + #[clap(long, short)] + force: bool, + }, + + /// Login to the configured server + Login(login::Cmd), + + /// Log out + Logout, + + /// Register with the configured server + Register(register::Cmd), + + /// Print the encryption key for transfer to another machine + Key, +} + +impl Cmd { + pub async fn run( + self, + settings: Settings, + db: &mut (impl Database + Send + Sync), + ) -> Result<()> { + match self { + Self::Sync { force } => run(&settings, force, db).await, + Self::Login(l) => l.run(&settings).await, + Self::Logout => logout::run(), + Self::Register(r) => r.run(&settings).await, + Self::Key => { + use atuin_client::encryption::{encode_key, load_key}; + let key = load_key(&settings).wrap_err("could not load encryption key")?; + let encode = encode_key(key).wrap_err("could not encode encryption key")?; + println!("{}", encode); + Ok(()) + } + } + } +} + +async fn run( settings: &Settings, force: bool, db: &mut (impl Database + Send + Sync), ) -> Result<()> { - sync::sync(settings, force, db).await?; + atuin_client::sync::sync(settings, force, db).await?; println!( "Sync complete! {} items in database, force: {}", db.history_count().await?, diff --git a/src/command/client/login.rs b/src/command/client/sync/login.rs similarity index 100% rename from src/command/client/login.rs rename to src/command/client/sync/login.rs diff --git a/src/command/client/logout.rs b/src/command/client/sync/logout.rs similarity index 100% rename from src/command/client/logout.rs rename to src/command/client/sync/logout.rs diff --git a/src/command/client/register.rs b/src/command/client/sync/register.rs similarity index 100% rename from src/command/client/register.rs rename to src/command/client/sync/register.rs diff --git a/src/command/mod.rs b/src/command/mod.rs index 3a3ed39..953b76b 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -2,6 +2,8 @@ use clap::Subcommand; use eyre::Result; mod client; + +#[cfg(feature = "server")] mod server; #[derive(Subcommand)] @@ -11,6 +13,7 @@ pub enum AtuinCmd { Client(client::Cmd), /// Start an atuin server + #[cfg(feature = "server")] #[clap(subcommand)] Server(server::Cmd), } @@ -19,6 +22,7 @@ impl AtuinCmd { pub async fn run(self) -> Result<()> { match self { Self::Client(client) => client.run().await, + #[cfg(feature = "server")] Self::Server(server) => server.run().await, } }