feature-flags (#328)

* use feature flags

* fmt

* fix features

* update ci

* fmt

Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
This commit is contained in:
Conrad Ludgate 2022-04-22 21:14:23 +01:00 committed by GitHub
parent 508d4f4761
commit 7436e4ff65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 141 additions and 81 deletions

View file

@ -63,7 +63,19 @@ jobs:
key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
- name: Run cargo test - 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: clippy:
runs-on: ubuntu-latest runs-on: ubuntu-latest

18
Cargo.lock generated
View file

@ -113,7 +113,6 @@ dependencies = [
"log", "log",
"minspan", "minspan",
"parse_duration", "parse_duration",
"rand 0.8.5",
"regex", "regex",
"reqwest", "reqwest",
"rmp-serde", "rmp-serde",
@ -761,12 +760,6 @@ dependencies = [
"parking_lot 0.11.2", "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]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.21" version = "0.3.21"
@ -786,10 +779,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-io",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab", "slab",
@ -1804,19 +1795,20 @@ dependencies = [
[[package]] [[package]]
name = "rmp" name = "rmp"
version = "0.8.10" version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f55e5fa1446c4d5dd1f5daeed2a4fe193071771a2636274d0d7a3b082aa7ad6" checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"num-traits", "num-traits",
"paste",
] ]
[[package]] [[package]]
name = "rmp-serde" name = "rmp-serde"
version = "1.0.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3eedffbfcc6a428f230c04baf8f59bd73c1781361e4286111fe900849aaddaf" checksum = "25786b0d276110195fa3d6f3f31299900cf71dfbd6c28450f3f58a0e7f7a347e"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"rmp", "rmp",

View file

@ -29,9 +29,17 @@ atuin = { path = "/usr/bin/atuin" }
[workspace] [workspace]
members = ["./atuin-client", "./atuin-server", "./atuin-common"] 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] [dependencies]
atuin-server = { path = "atuin-server", version = "0.8.1" } atuin-server = { path = "atuin-server", version = "0.8.1", optional = true }
atuin-client = { path = "atuin-client", version = "0.8.1" } atuin-client = { path = "atuin-client", version = "0.8.1", default-features = false }
atuin-common = { path = "atuin-common", version = "0.8.1" } atuin-common = { path = "atuin-common", version = "0.8.1" }
log = "0.4" log = "0.4"
@ -59,7 +67,6 @@ clap_complete = "3.1.2"
fs-err = "2.7" fs-err = "2.7"
whoami = "1.1.2" whoami = "1.1.2"
[dependencies.tracing-subscriber] [dependencies.tracing-subscriber]
version = "0.3" version = "0.3"
default-features = false default-features = false
@ -69,8 +76,4 @@ features = [
"registry", "registry",
"env-filter", "env-filter",
] ]
optional = true
[profile.release]
lto = "fat"
codegen-units = 1
opt-level = 3

View file

@ -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 # 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] [dependencies]
atuin-common = { path = "../atuin-common", version = "0.8.1" } atuin-common = { path = "../atuin-common", version = "0.8.1" }
@ -23,20 +34,8 @@ chrono-english = "0.1.4"
config = "0.13" config = "0.13"
serde = { version = "1.0.126", features = ["derive"] } serde = { version = "1.0.126", features = ["derive"] }
serde_json = "1.0.75" 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" parse_duration = "2.1.1"
rand = "0.8.4"
rust-crypto = "^0.2"
tokio = { version = "1", features = ["full"] }
async-trait = "0.1.49" async-trait = "0.1.49"
urlencoding = "2.1.0"
itertools = "0.10.3" itertools = "0.10.3"
shellexpand = "2" shellexpand = "2"
sqlx = { version = "0.5", features = [ sqlx = { version = "0.5", features = [
@ -48,3 +47,17 @@ sqlx = { version = "0.5", features = [
minspan = "0.1.1" minspan = "0.1.1"
regex = "1.5.4" regex = "1.5.4"
fs-err = "2.7" 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"] }

View file

@ -38,7 +38,7 @@ pub async fn register(
map.insert("password", password); map.insert("password", password);
let url = format!("{}/user/{}", address, username); let url = format!("{}/user/{}", address, username);
let resp = reqwest::blocking::get(url)?; let resp = reqwest::get(url).await?;
if resp.status().is_success() { if resp.status().is_success() {
bail!("username already in use"); bail!("username already in use");

View file

@ -77,7 +77,7 @@ pub fn encode_key(key: secretbox::Key) -> Result<String> {
pub fn decode_key(key: String) -> Result<secretbox::Key> { pub fn decode_key(key: String) -> Result<secretbox::Key> {
let buf = base64::decode(key).wrap_err("encryption key is not a valid base64 encoding")?; 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")?; .wrap_err("encryption key is not a valid message pack encoding")?;
Ok(buf) 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) let plaintext = secretbox::open(&encrypted_history.ciphertext, &encrypted_history.nonce, key)
.map_err(|_| eyre!("failed to open secretbox - invalid 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) Ok(history)
} }

View file

@ -3,11 +3,15 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[cfg(feature = "sync")]
pub mod api_client; pub mod api_client;
pub mod database; #[cfg(feature = "sync")]
pub mod encryption; pub mod encryption;
#[cfg(feature = "sync")]
pub mod sync;
pub mod database;
pub mod history; pub mod history;
pub mod import; pub mod import;
pub mod ordering; pub mod ordering;
pub mod settings; pub mod settings;
pub mod sync;

View file

@ -8,16 +8,16 @@ use atuin_client::database::Sqlite;
use atuin_client::settings::Settings; use atuin_client::settings::Settings;
use atuin_common::utils::uuid_v4; use atuin_common::utils::uuid_v4;
#[cfg(feature = "sync")]
mod sync;
mod event; mod event;
mod history; mod history;
mod import; mod import;
mod init; mod init;
mod login;
mod logout;
mod register;
mod search; mod search;
mod stats; mod stats;
mod sync;
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Subcommand)] #[derive(Subcommand)]
@ -45,25 +45,6 @@ pub enum Cmd {
/// Interactive history search /// Interactive history search
Search(search::Cmd), 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 /// Generate shell completions
GenCompletions { GenCompletions {
/// Set the shell for generating completions /// Set the shell for generating completions
@ -74,6 +55,10 @@ pub enum Cmd {
#[clap(long, short)] #[clap(long, short)]
out_dir: Option<String>, out_dir: Option<String>,
}, },
#[cfg(feature = "sync")]
#[clap(flatten)]
Sync(sync::Cmd),
} }
impl Cmd { impl Cmd {
@ -94,17 +79,6 @@ impl Cmd {
Ok(()) Ok(())
} }
Self::Search(search) => search.run(&mut db, &settings).await, 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 => { Self::Uuid => {
println!("{}", uuid_v4()); println!("{}", uuid_v4());
Ok(()) Ok(())
@ -128,6 +102,8 @@ impl Cmd {
Ok(()) Ok(())
} }
#[cfg(feature = "sync")]
Self::Sync(sync) => sync.run(settings, &mut db).await,
} }
} }
} }

View file

@ -9,6 +9,8 @@ use tabwriter::TabWriter;
use atuin_client::database::{current_context, Database}; use atuin_client::database::{current_context, Database};
use atuin_client::history::History; use atuin_client::history::History;
use atuin_client::settings::Settings; use atuin_client::settings::Settings;
#[cfg(feature = "sync")]
use atuin_client::sync; use atuin_client::sync;
#[derive(Subcommand)] #[derive(Subcommand)]
@ -143,8 +145,13 @@ impl Cmd {
db.update(&h).await?; db.update(&h).await?;
if settings.should_sync()? { if settings.should_sync()? {
debug!("running periodic background sync"); #[cfg(feature = "sync")]
sync::sync(settings, false, db).await?; {
debug!("running periodic background sync");
sync::sync(settings, false, db).await?;
}
#[cfg(not(feature = "sync"))]
debug!("not compiled with sync support");
} else { } else {
debug!("sync disabled! not syncing"); debug!("sync disabled! not syncing");
} }

View file

@ -1,15 +1,64 @@
use eyre::Result;
use atuin_client::database::Database; use atuin_client::database::Database;
use atuin_client::settings::Settings; use clap::Subcommand;
use atuin_client::sync; 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, settings: &Settings,
force: bool, force: bool,
db: &mut (impl Database + Send + Sync), db: &mut (impl Database + Send + Sync),
) -> Result<()> { ) -> Result<()> {
sync::sync(settings, force, db).await?; atuin_client::sync::sync(settings, force, db).await?;
println!( println!(
"Sync complete! {} items in database, force: {}", "Sync complete! {} items in database, force: {}",
db.history_count().await?, db.history_count().await?,

View file

@ -2,6 +2,8 @@ use clap::Subcommand;
use eyre::Result; use eyre::Result;
mod client; mod client;
#[cfg(feature = "server")]
mod server; mod server;
#[derive(Subcommand)] #[derive(Subcommand)]
@ -11,6 +13,7 @@ pub enum AtuinCmd {
Client(client::Cmd), Client(client::Cmd),
/// Start an atuin server /// Start an atuin server
#[cfg(feature = "server")]
#[clap(subcommand)] #[clap(subcommand)]
Server(server::Cmd), Server(server::Cmd),
} }
@ -19,6 +22,7 @@ impl AtuinCmd {
pub async fn run(self) -> Result<()> { pub async fn run(self) -> Result<()> {
match self { match self {
Self::Client(client) => client.run().await, Self::Client(client) => client.run().await,
#[cfg(feature = "server")]
Self::Server(server) => server.run().await, Self::Server(server) => server.run().await,
} }
} }