Skip to content

Commit

Permalink
feat!: use PathBuf for config path
Browse files Browse the repository at this point in the history
Use a PathBuf instead of a String to save the config path. This makes
handling paths easier on Windows.

BREAKING CHANGE: The System keyring now uses a canonical path to store
credentials. This may break credential storage. If you encounter the
error message `Could not find auth for remote <remote_name>`, you will
need to call `gritty auth <remote_name>` and supply a new token.
  • Loading branch information
benpueschel committed Aug 6, 2024
1 parent 4e94c08 commit 41cc53f
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ If not provided, the config will be searched for in the following directories:
- $HOME/.gritty.toml (~/.gritty.toml)
On Windows, the following directories will be searched:
- %LOCALAPPDATA%/gritty/config.toml (C:\\Users\\<user>\\AppData\\Local\\gritty\\config.toml)
- %LOCALAPPDATA%\\gritty\\config.toml (C:\\Users\\<user>\\AppData\\Local\\gritty\\config.toml)
- %LOCALAPPDATA%\\.gritty.toml (C:\\Users\\<user>\\AppData\\Local\\.gritty.toml)
If the config file does not exist, it will be created in the specified location,
Expand Down
6 changes: 3 additions & 3 deletions src/commands/create_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ pub async fn create_config(cfg: &Option<String>) -> Result<()> {
// Config file path

if let Some(path) = cfg {
config.path.clone_from(path);
config.path = path.into();
println!(
"Using provided config file path: {}",
&config.path.paint(Highlight::Path)
);
} else {
println!(
print!(
"Enter the path to the config file (default is {}):",
&config.path.paint(Highlight::Path)
);
let path = get_input()?;
if !path.is_empty() {
config.path = path;
config.path = path.into();
}
println!();
}
Expand Down
25 changes: 16 additions & 9 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
use crate::error::{Error, Result};
use std::{collections::BTreeMap, env, fs, path::Path};
use crate::{
error::{Error, Result},
log::{Highlight, Paint},
};
use std::{
collections::BTreeMap,
env, fs,
path::{Path, PathBuf},
};

#[cfg(feature = "keyring")]
use keyring::Entry;
Expand Down Expand Up @@ -38,7 +45,7 @@ pub struct Config {
pub secrets: Secrets,
pub colors: Option<ConfigColorMap>,
#[serde(skip)]
pub path: String,
pub path: PathBuf,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
Expand Down Expand Up @@ -74,15 +81,15 @@ impl Config {
pub fn save_default(path: &Option<String>) -> Result<()> {
let mut config = Config::default();
if let Some(path) = path {
config.path.clone_from(path);
config.path = path.into();
}
config.save()
}
pub fn save(&self) -> Result<()> {
let toml = toml::to_string(self)?;
fs::create_dir_all(Path::new(&self.path).parent().unwrap())?;
fs::write(&self.path, toml)?;
println!("Saved config to {}.", &self.path);
println!("Saved config to {}.", &self.path.paint(Highlight::Path));
Ok(())
}
pub fn load_from_file(path: Option<String>) -> Result<Self> {
Expand All @@ -106,7 +113,7 @@ impl Config {
};
let contents = fs::read_to_string(&path)?;
let mut config: Config = toml::from_str(&contents)?;
config.path = path;
config.path = path.into();
Ok(config)
}

Expand Down Expand Up @@ -135,7 +142,7 @@ impl Config {
match &mut self.secrets {
#[cfg(feature = "keyring")]
Secrets::Keyring => {
let entry = Entry::new(&self.path, name)?;
let entry = Entry::new(self.path.canonicalize()?.to_string_lossy().as_ref(), name)?;
entry.set_password(token)?;
Ok(())
}
Expand Down Expand Up @@ -216,7 +223,7 @@ impl Config {
Secrets::Keyring => {
// we get a unique secret id by combining the config path and the remote name.
// This is mainly to allow users to use multiple configs without conflicts.
let entry = Entry::new(&self.path, name)?;
let entry = Entry::new(self.path.canonicalize()?.to_string_lossy().as_ref(), name)?;
if let Ok(token) = entry.get_password() {
return Ok(Auth::Token { token });
}
Expand All @@ -237,7 +244,7 @@ impl Default for Config {
fn default() -> Self {
let config_dir = get_config_dir();
Self {
path: format!("{config_dir}/gritty/config.toml"),
path: format!("{config_dir}/gritty/config.toml").into(),
remotes: BTreeMap::new(),
colors: None,
#[cfg(feature = "keyring")]
Expand Down
12 changes: 12 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{
collections::HashMap,
fmt::{self, Display},
io::{IsTerminal, Write},
path::PathBuf,
};

use ansi_term::Style;
Expand Down Expand Up @@ -57,6 +58,17 @@ impl Paint for &str {
StyledString(self.to_string(), highlight)
}
}
impl Paint for PathBuf {
fn paint(&self, highlight: Highlight) -> StyledString {
// Windows paths use backslashes, so we need to replace any forward slashes
#[cfg(target_os = "windows")]
let str = self.to_string_lossy().to_string().replace('/', "\\");

#[cfg(not(target_os = "windows"))]
let str = self.to_string_lossy().to_string();
StyledString(str, highlight)
}
}

#[derive(Copy, Hash, Clone, PartialEq, Eq)]
pub enum Highlight {
Expand Down

0 comments on commit 41cc53f

Please sign in to comment.