summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2023-10-27 18:57:08 -0500
committerToby Vincent <tobyv@tobyvin.dev>2023-10-27 18:57:50 -0500
commit539fd0f26c83064b748bbd040fdf27f302f27cb7 (patch)
tree6f1c2fd2f9b8ef14897f2c3b0f1b8b3e7aeb0816
parentc0d77c1eadc1d0304369d6bc8107ac9843be93f0 (diff)
feat: order localhost using tmux if enabled and remove historydevelop
-rw-r--r--src/config.rs13
-rw-r--r--src/history.rs77
-rw-r--r--src/lib.rs2
-rw-r--r--src/localhost.rs15
-rw-r--r--src/main.rs25
-rw-r--r--src/session.rs20
-rw-r--r--src/tmux.rs30
7 files changed, 63 insertions, 119 deletions
diff --git a/src/config.rs b/src/config.rs
index 258255b..cdef063 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,7 +1,7 @@
use clap::{Args, Parser};
use tracing::{metadata::LevelFilter, Level};
-use crate::{history, session, stdio, tmux};
+use crate::{session, stdio, tmux};
#[derive(Debug, Clone, Parser)]
pub struct Config {
@@ -15,9 +15,6 @@ pub struct Config {
pub sessions: session::Config,
#[command(flatten)]
- pub history: history::History,
-
- #[command(flatten)]
pub tmux: tmux::Tmux,
#[command(flatten)]
@@ -34,10 +31,6 @@ pub struct Flags {
#[arg(short, long)]
pub tmux: bool,
- /// Include hosts from history file
- #[arg(short = 'H', long)]
- pub history: bool,
-
/// Include hosts from the ssh `known_hosts`
#[arg(short, long)]
pub ssh: bool,
@@ -60,10 +53,6 @@ impl Flags {
self.all || self.tmux
}
- pub fn history(&self) -> bool {
- self.all || self.history
- }
-
pub fn ssh(&self) -> bool {
self.all || self.ssh
}
diff --git a/src/history.rs b/src/history.rs
deleted file mode 100644
index 0394e3d..0000000
--- a/src/history.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use std::{
- fs::File,
- io::{BufRead, BufReader, ErrorKind},
- path::PathBuf,
-};
-
-use clap::Args;
-use directories::ProjectDirs;
-
-use crate::{session::SessionWriter, Session};
-
-#[derive(Debug, Clone, Args)]
-#[group(skip)]
-pub struct History {
- /// Update the history file from the current sessions
- #[arg(short, long)]
- pub update: bool,
-
- /// path to history file [default: $XDG_DATA_HOME/sshr/history]
- #[arg(short = 'f', long = "history_file")]
- path: Option<PathBuf>,
-}
-
-impl History {
- pub fn new(History { update, path }: History) -> Self {
- Self {
- path: path.or_else(History::default_path),
- update,
- }
- }
-
- pub fn read(&self) -> Result<Vec<Session>, std::io::Error> {
- let Some(path) = &self.path() else {
- tracing::warn!(?self.path, "History file does not exist");
- return Ok(Vec::new());
- };
-
- let sessions = BufReader::new(File::open(path)?)
- .lines()
- .flatten()
- .flat_map(|item| ron::from_str(&item))
- .collect();
-
- Ok(sessions)
- }
-
- fn default_path() -> Option<PathBuf> {
- ProjectDirs::from("", "", env!("CARGO_CRATE_NAME"))?
- .state_dir()?
- .join("history")
- .into()
- }
-
- pub fn path(&self) -> Option<PathBuf> {
- self.path.clone().or_else(History::default_path)
- }
-}
-
-impl SessionWriter for History {
- type Writer = File;
- type Error = ron::Error;
-
- fn format(&self, session: &Session) -> Result<String, Self::Error> {
- ron::to_string(session)
- }
-
- fn filter(&self, session: &Session) -> bool {
- self.update && !matches!(session.state, crate::State::Discovered)
- }
-
- fn writer(&self) -> Result<Self::Writer, std::io::Error> {
- match &self.path {
- Some(path) => File::create(path),
- None => Err(std::io::Error::from(ErrorKind::NotFound)),
- }
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index ebf9c8d..2d80b54 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,5 @@
pub use crate::{
config::Config,
- history::History,
localhost::HostName,
session::{Session, Sessions, State},
ssh::KnownHosts,
@@ -10,7 +9,6 @@ pub use crate::{
};
mod config;
-mod history;
mod localhost;
mod session;
mod ssh;
diff --git a/src/localhost.rs b/src/localhost.rs
index 45b14de..2115465 100644
--- a/src/localhost.rs
+++ b/src/localhost.rs
@@ -10,16 +10,21 @@ impl HostName {
}
}
+impl From<HostName> for Session {
+ fn from(value: HostName) -> Self {
+ Session {
+ name: value.0.to_string_lossy().into(),
+ state: State::LocalHost,
+ }
+ }
+}
+
impl IntoIterator for HostName {
type Item = Session;
type IntoIter = std::option::IntoIter<Session>;
fn into_iter(self) -> Self::IntoIter {
- Some(Session {
- name: self.0.to_string_lossy().into(),
- state: State::LocalHost,
- })
- .into_iter()
+ Some(self.into()).into_iter()
}
}
diff --git a/src/main.rs b/src/main.rs
index c32c246..9eaa978 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
use anyhow::Context;
use clap::Parser;
-use sshr::{Config, HostName, Hosts, KnownHosts, Sessions, Stdout};
+use sshr::{Config, HostName, Hosts, KnownHosts, Sessions, Stdout, Tmux};
fn main() -> anyhow::Result<()> {
let mut config = Config::parse();
@@ -14,8 +14,13 @@ fn main() -> anyhow::Result<()> {
let mut sessions = Sessions::new(config.sessions);
if config.enabled.localhost() {
- let hostname = HostName::get().context("Failed to get hostname of localhost")?;
- sessions.extend(hostname);
+ if config.enabled.tmux() {
+ let local_sessions = Tmux::local_session().context("Failed to get local sessions")?;
+ sessions.extend(local_sessions);
+ } else {
+ let hostname = HostName::get().context("Failed to get hostname of localhost")?;
+ sessions.extend(hostname);
+ }
}
if config.enabled.tmux() {
@@ -38,20 +43,6 @@ fn main() -> anyhow::Result<()> {
sessions.extend(hosts);
}
- if config.enabled.history() {
- match config.history.read() {
- Ok(h) => sessions.extend(h),
- Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
- tracing::warn!("Skipping non-existant history file")
- }
- Err(err) => return Err(err).context("Failed to read history file"),
- }
- }
-
- if config.history.update {
- sessions.write_sessions(config.history)?;
- }
-
sessions
.write_sessions(Stdout::new(config.stdio))
.context("Failed to write to stdout")
diff --git a/src/session.rs b/src/session.rs
index aad299a..0118383 100644
--- a/src/session.rs
+++ b/src/session.rs
@@ -65,12 +65,12 @@ impl Sessions {
let _guard = span.enter();
match self.inner.entry(item.name) {
- Entry::Occupied(mut occupied) if &item.state > occupied.get() => {
- tracing::trace!(?occupied, new_value=?item.state, "New entry is more recent, replacing");
- occupied.insert(item.state);
+ Entry::Occupied(mut o) if item.state.is_better_than(o.get()) => {
+ tracing::trace!(prev=?o, ?item.state, "New entry is more recent or accurate, replacing");
+ o.insert(item.state);
}
- Entry::Occupied(occupied) => {
- tracing::trace!(?occupied, new_value=?item.state, "Previous entry is more recent, skipping");
+ Entry::Occupied(o) => {
+ tracing::trace!(existing=?o, ?item.state, "Existing entry is more recent or accurate, skipping");
}
Entry::Vacant(v) => {
tracing::trace!(?item.state, "No previous entry exists, inserting");
@@ -98,6 +98,16 @@ pub enum State {
LocalHost,
}
+impl State {
+ pub fn is_better_than(&self, state: &State) -> bool {
+ match (self, state) {
+ (&State::LocalHost, _) => false,
+ (_, &State::LocalHost) => true,
+ _ => self > state,
+ }
+ }
+}
+
mod epoch_timestamp {
use std::time::Duration;
diff --git a/src/tmux.rs b/src/tmux.rs
index b1f1af2..b53c172 100644
--- a/src/tmux.rs
+++ b/src/tmux.rs
@@ -55,6 +55,29 @@ impl Tmux {
.transpose()?
.ok_or(Error::NotFound)
}
+
+ pub fn local_session() -> Result<Vec<Session>, Error> {
+ let hostname = hostname::get()?;
+ let stdout = Command::new("tmux")
+ .arg("-L")
+ .arg("default")
+ .arg("list-sessions")
+ .arg("-F")
+ .arg(Self::SESSION_FORMAT)
+ .output()?
+ .stdout;
+
+ let sessions: Vec<Session> = std::str::from_utf8(&stdout)?
+ .lines()
+ .flat_map(ron::from_str)
+ .map(|mut s: Session| {
+ s.name = hostname.to_string_lossy().into();
+ s
+ })
+ .collect();
+
+ Ok(sessions)
+ }
}
#[cfg(test)]
@@ -64,7 +87,6 @@ mod tests {
const SOCKET: &str = "test";
#[test]
- #[ignore]
fn test_tmux_list() -> Result<(), Error> {
let names = Vec::from(["test_1", "test_2", "test_3", "test_4"]);
@@ -94,4 +116,10 @@ mod tests {
Ok(())
}
+
+ #[test]
+ fn test_host() -> Result<(), Error> {
+ let _local_session = Tmux::local_session()?;
+ Ok(())
+ }
}