diff options
author | YummyOreo <bobgim20@gmail.com> | 2024-05-12 21:35:34 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-13 09:35:34 +0700 |
commit | ce67e527722cadd4ed7341a3e5d433beb62887f6 (patch) | |
tree | 41ff5ccc9d6857d1d4173a0a61f99174b644cb9e | |
parent | 0da534d5249a9111f8e1af0ff517526e2c66cdb0 (diff) |
feat(daemon): add support for daemon on windows (#2014)weekly
* fix: gracefully exit on windows
* feat(daemon): tcp support for windows
* feat(daemon): add tcp port configuration
* fix: logging and fix compiler error
* docs: add build dependency to the readme
fix(docs): move a line up
* fix: missing field error
* docs: adds the daemon section to the default config
* fix: clippy and fmt
* feat: Update README.md
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
* refactor: changes tcp port and other stuff as per request
* fix(config): update default tcp port in example config
* fix: complier error on unix
* refactor: make the cfg stuff look better
---------
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
-rw-r--r-- | README.md | 45 | ||||
-rw-r--r-- | crates/atuin-client/config.toml | 15 | ||||
-rw-r--r-- | crates/atuin-client/src/settings.rs | 5 | ||||
-rw-r--r-- | crates/atuin-daemon/src/client.rs | 22 | ||||
-rw-r--r-- | crates/atuin-daemon/src/server.rs | 62 | ||||
-rw-r--r-- | crates/atuin/src/command/client/history.rs | 27 |
6 files changed, 131 insertions, 45 deletions
@@ -29,7 +29,7 @@ Atuin replaces your existing shell history with a SQLite database, and records additional context for your commands. Additionally, it provides optional and _fully encrypted_ synchronisation of your history between machines, via an Atuin -server. +server. @@ -90,7 +90,7 @@ I wanted to. And I **really** don't want to. - fish - nushell - xonsh - + ## Community ### Forum @@ -102,11 +102,11 @@ Atuin has a community forum, please ask here for help and support: https://forum Atuin also has a community Discord, available [here](https://discord.gg/jR3tfchVvW) # Quickstart - + ## With the default sync server - + This will sign you up for the default sync server, hosted by me. Everything is end-to-end encrypted, so your secrets are safe! - + Read more below for offline-only usage, or for hosting your own server. ``` @@ -130,10 +130,10 @@ Then restart your shell! > section below. ## Offline only (no sync) - + ``` bash <(curl https://raw.githubusercontent.com/atuinsh/atuin/main/install.sh) - + atuin import auto ``` @@ -171,25 +171,28 @@ toolchain, then you can run: ``` cargo install atuin ``` - + And then follow [the shell setup](#shell-plugin) +#### Daemon Build Dependencies +[Protoc](https://grpc.io/docs/protoc-installation/) is required to build the daemon, which is enabled by default. This is because we use protobufs for the message serialization + ### Homebrew ``` brew install atuin ``` - + And then follow [the shell setup](#shell-plugin) - + ### MacPorts -Atuin is also available in [MacPorts](https://ports.macports.org/port/atuin/) - +Atuin is also available in [MacPorts](https://ports.macports.org/port/atuin/) + ``` sudo port install atuin ``` - + And then follow [the shell setup](#shell-plugin) ### Cave @@ -223,7 +226,7 @@ Atuin is available in the Arch Linux [[extra] repository](https://archlinux.org/ ``` pacman -S atuin ``` - + And then follow [the shell setup](#shell-plugin) ### Xbps @@ -243,7 +246,7 @@ Atuin is available in the Termux package repository: ``` pkg install atuin ``` - + And then follow [the shell setup](#shell-plugin) ### From source @@ -253,7 +256,7 @@ git clone https://github.com/atuinsh/atuin.git cd atuin/crates/atuin cargo install --path . ``` - + And then follow [the shell setup](#shell-plugin) ## Shell plugin @@ -273,9 +276,9 @@ echo 'eval "$(atuin init zsh)"' >> ~/.zshrc zinit load atuinsh/atuin ``` -#### Antigen - -```sh +#### Antigen + +```sh antigen bundle atuinsh/atuin@main ``` @@ -345,7 +348,7 @@ atuin init fish | source ``` to your `is-interactive` block in your `~/.config/fish/config.fish` file - + ### Nushell Run in *Nushell*: @@ -371,7 +374,7 @@ to the end of your `~/.xonshrc` # Security -If you find any security issues, we'd appreciate it if you could alert ellie@atuin.sh +If you find any security issues, we'd appreciate it if you could alert ellie@atuin.sh # Contributors diff --git a/crates/atuin-client/config.toml b/crates/atuin-client/config.toml index 50db6952..1de7308c 100644 --- a/crates/atuin-client/config.toml +++ b/crates/atuin-client/config.toml @@ -210,3 +210,18 @@ records = true ## auto: length of the selected command. ## static: length of the longest command stored in the history. # strategy = "auto" + +[daemon] +## Enables using the daemon to sync. Requires the daemon to be running in the background. Start it with `atuin daemon` +# enabled = false + +## How often the daemon should sync in seconds +# sync_frequency = 300 + +## The path to the unix socket used by the daemon (on unix systems) +## linux/mac: ~/.local/share/atuin/atuin.sock +## windows: Not Supported +# socket_path = "~/atuin.sock" + +## The port that should be used for TCP on non unix systems +# tcp_port = 8889 diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs index ad7f95fc..ed1c0a29 100644 --- a/crates/atuin-client/src/settings.rs +++ b/crates/atuin-client/src/settings.rs @@ -353,6 +353,9 @@ pub struct Daemon { /// The path to the unix socket used by the daemon pub socket_path: String, + + /// The port that should be used for TCP on non unix systems + pub tcp_port: u64, } impl Default for Preview { @@ -369,6 +372,7 @@ impl Default for Daemon { enabled: false, sync_frequency: 300, socket_path: "".to_string(), + tcp_port: 8889, } } } @@ -706,6 +710,7 @@ impl Settings { .set_default("daemon.sync_frequency", 300)? .set_default("daemon.enabled", false)? .set_default("daemon.socket_path", socket_path.to_str())? + .set_default("daemon.tcp_port", 8889)? .set_default( "prefers_reduced_motion", std::env::var("NO_MOTION") diff --git a/crates/atuin-daemon/src/client.rs b/crates/atuin-daemon/src/client.rs index a832f9a9..f3fecdbc 100644 --- a/crates/atuin-daemon/src/client.rs +++ b/crates/atuin-daemon/src/client.rs @@ -1,8 +1,12 @@ use eyre::{eyre, Result}; -use tokio::net::UnixStream; +#[cfg(windows)] +use tokio::net::TcpStream; use tonic::transport::{Channel, Endpoint, Uri}; use tower::service_fn; +#[cfg(unix)] +use tokio::net::UnixStream; + use atuin_client::history::History; use crate::history::{ @@ -15,6 +19,7 @@ pub struct HistoryClient { // Wrap the grpc client impl HistoryClient { + #[cfg(unix)] pub async fn new(path: String) -> Result<Self> { let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -30,6 +35,21 @@ impl HistoryClient { Ok(HistoryClient { client }) } + #[cfg(not(unix))] + pub async fn new(port: u64) -> Result<Self> { + let channel = Endpoint::try_from("http://atuin_local_daemon:0")? + .connect_with_connector(service_fn(move |_: Uri| { + let url = format!("127.0.0.1:{}", port); + TcpStream::connect(url) + })) + .await + .map_err(|_| eyre!("failed to connect to local atuin daemon. Is it running?"))?; + + let client = HistoryServiceClient::new(channel); + + Ok(HistoryClient { client }) + } + pub async fn start_history(&mut self, h: History) -> Result<String> { let req = StartHistoryRequest { command: h.command, diff --git a/crates/atuin-daemon/src/server.rs b/crates/atuin-daemon/src/server.rs index 72305737..77824f60 100644 --- a/crates/atuin-daemon/src/server.rs +++ b/crates/atuin-daemon/src/server.rs @@ -13,8 +13,6 @@ use atuin_client::database::{Database, Sqlite as HistoryDatabase}; use atuin_client::history::{History, HistoryId}; use dashmap::DashMap; use eyre::Result; -use tokio::net::UnixListener; -use tokio_stream::wrappers::UnixListenerStream; use tonic::{transport::Server, Request, Response, Status}; use crate::history::history_server::{History as HistorySvc, HistoryServer}; @@ -134,6 +132,7 @@ impl HistorySvc for HistoryService { } } +#[cfg(unix)] async fn shutdown_signal(socket: PathBuf) { let mut term = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) .expect("failed to register sigterm handler"); @@ -150,6 +149,52 @@ async fn shutdown_signal(socket: PathBuf) { eprintln!("Shutting down..."); } +#[cfg(windows)] +async fn shutdown_signal() { + tokio::signal::windows::ctrl_c() + .expect("failed to register signal handler") + .recv() + .await; + eprintln!("Shutting down..."); +} + +#[cfg(unix)] +async fn start_server(settings: Settings, history: HistoryService) -> Result<()> { + use tokio::net::UnixListener; + use tokio_stream::wrappers::UnixListenerStream; + + let socket = settings.daemon.socket_path.clone(); + + let uds = UnixListener::bind(socket.clone())?; + let uds_stream = UnixListenerStream::new(uds); + + tracing::info!("listening on unix socket {:?}", socket); + Server::builder() + .add_service(HistoryServer::new(history)) + .serve_with_incoming_shutdown(uds_stream, shutdown_signal(socket.into())) + .await?; + Ok(()) +} + +#[cfg(not(unix))] +async fn start_server(settings: Settings, history: HistoryService) -> Result<()> { + use tokio::net::TcpListener; + use tokio_stream::wrappers::TcpListenerStream; + + let port = settings.daemon.tcp_port; + let url = format!("127.0.0.1:{}", port); + let tcp = TcpListener::bind(url).await?; + let tcp_stream = TcpListenerStream::new(tcp); + + tracing::info!("listening on tcp port {:?}", port); + + Server::builder() + .add_service(HistoryServer::new(history)) + .serve_with_incoming_shutdown(tcp_stream, shutdown_signal()) + .await?; + Ok(()) +} + // break the above down when we end up with multiple services /// Listen on a unix socket @@ -168,12 +213,6 @@ pub async fn listen( let history = HistoryService::new(history_store.clone(), history_db.clone()); - let socket = settings.daemon.socket_path.clone(); - let uds = UnixListener::bind(socket.clone())?; - let uds_stream = UnixListenerStream::new(uds); - - tracing::info!("listening on unix socket {:?}", socket); - // start services tokio::spawn(sync::worker( settings.clone(), @@ -182,10 +221,5 @@ pub async fn listen( history_db, )); - Server::builder() - .add_service(HistoryServer::new(history)) - .serve_with_incoming_shutdown(uds_stream, shutdown_signal(socket.into())) - .await?; - - Ok(()) + start_server(settings, history).await } diff --git a/crates/atuin/src/command/client/history.rs b/crates/atuin/src/command/client/history.rs index f966c302..9d1453fc 100644 --- a/crates/atuin/src/command/client/history.rs +++ b/crates/atuin/src/command/client/history.rs @@ -315,11 +315,15 @@ impl Cmd { } if settings.daemon.enabled { - let resp = - atuin_daemon::client::HistoryClient::new(settings.daemon.socket_path.clone()) - .await? - .start_history(h) - .await?; + let resp = atuin_daemon::client::HistoryClient::new( + #[cfg(not(unix))] + settings.daemon.tcp_port, + #[cfg(unix)] + settings.daemon.socket_path.clone(), + ) + .await? + .start_history(h) + .await?; // print the ID // we use this as the key for calling end @@ -350,10 +354,15 @@ impl Cmd { // We will need to keep the old code around for a while. // At the very least, while this is opt-in if settings.daemon.enabled { - atuin_daemon::client::HistoryClient::new(settings.daemon.socket_path.clone()) - .await? - .end_history(id.to_string(), duration.unwrap_or(0), exit) - .await?; + let resp = atuin_daemon::client::HistoryClient::new( + #[cfg(not(unix))] + settings.daemon.tcp_port, + #[cfg(unix)] + settings.daemon.socket_path.clone(), + ) + .await? + .end_history(id.to_string(), duration.unwrap_or(0), exit) + .await?; return Ok(()); } |