summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@elliehuxtable.com>2024-04-23 14:45:07 +0100
committerGitHub <noreply@github.com>2024-04-23 14:45:07 +0100
commitbf88b42cec26ee2912c5e25eaadd5764b3a480f0 (patch)
tree3ddd529084a13b2c2b0ef1f1941797be4d176a63
parent8b8844887b94a4b750fbfe128317ef4c2a042485 (diff)
fix(dotfiles): unquote aliases before quoting (#1976)
* fix(dotfiles): unquote aliases before quoting * tests
-rw-r--r--crates/atuin-common/src/utils.rs26
-rw-r--r--crates/atuin-dotfiles/src/store.rs32
2 files changed, 55 insertions, 3 deletions
diff --git a/crates/atuin-common/src/utils.rs b/crates/atuin-common/src/utils.rs
index 7c533663..3815085e 100644
--- a/crates/atuin-common/src/utils.rs
+++ b/crates/atuin-common/src/utils.rs
@@ -2,6 +2,8 @@ use std::borrow::Cow;
use std::env;
use std::path::PathBuf;
+use eyre::{eyre, Result};
+
use rand::RngCore;
use uuid::Uuid;
@@ -144,6 +146,30 @@ pub trait Escapable: AsRef<str> {
}
}
+pub fn unquote(s: &str) -> Result<String> {
+ if s.chars().count() < 2 {
+ return Err(eyre!("not enough chars"));
+ }
+
+ let quote = s.chars().next().unwrap();
+
+ // not quoted, do nothing
+ if quote != '"' && quote != '\'' && quote != '`' {
+ return Ok(s.to_string());
+ }
+
+ if s.chars().last().unwrap() != quote {
+ return Err(eyre!("unexpected eof, quotes do not match"));
+ }
+
+ // removes quote characters
+ // the sanity checks performed above ensure that the quotes will be ASCII and this will not
+ // panic
+ let s = &s[1..s.len() - 1];
+
+ Ok(s.to_string())
+}
+
impl<T: AsRef<str>> Escapable for T {}
#[cfg(test)]
diff --git a/crates/atuin-dotfiles/src/store.rs b/crates/atuin-dotfiles/src/store.rs
index 425a5e1e..b7984c1c 100644
--- a/crates/atuin-dotfiles/src/store.rs
+++ b/crates/atuin-dotfiles/src/store.rs
@@ -6,6 +6,7 @@ use atuin_client::record::sqlite_store::SqliteStore;
// While we will support a range of shell config, I'd rather have a larger number of small records
// + stores, rather than one mega config store.
use atuin_common::record::{DecryptedData, Host, HostId};
+use atuin_common::utils::unquote;
use eyre::{bail, ensure, eyre, Result};
use atuin_client::record::encryption::PASETO_V4;
@@ -142,7 +143,11 @@ impl AliasStore {
let mut config = String::new();
for alias in aliases {
- config.push_str(&format!("alias {}='{}'\n", alias.name, alias.value));
+ // If it's quoted, remove the quotes. If it's not quoted, do nothing.
+ let value = unquote(alias.value.as_str()).unwrap_or(alias.value.clone());
+
+ // we're about to quote it ourselves anyway!
+ config.push_str(&format!("alias {}='{}'\n", alias.name, value));
}
Ok(config)
@@ -336,14 +341,17 @@ mod tests {
let alias = AliasStore::new(store, host_id, key);
alias.set("k", "kubectl").await.unwrap();
-
alias.set("gp", "git push").await.unwrap();
+ alias
+ .set("kgap", "'kubectl get pods --all-namespaces'")
+ .await
+ .unwrap();
let mut aliases = alias.aliases().await.unwrap();
aliases.sort_by_key(|a| a.name.clone());
- assert_eq!(aliases.len(), 2);
+ assert_eq!(aliases.len(), 3);
assert_eq!(
aliases[0],
@@ -360,5 +368,23 @@ mod tests {
value: String::from("kubectl")
}
);
+
+ assert_eq!(
+ aliases[2],
+ Alias {
+ name: String::from("kgap"),
+ value: String::from("'kubectl get pods --all-namespaces'")
+ }
+ );
+
+ let build = alias.posix().await.expect("failed to build aliases");
+
+ assert_eq!(
+ build,
+ "alias gp='git push'
+alias k='kubectl'
+alias kgap='kubectl get pods --all-namespaces'
+"
+ )
}
}