mirror of
https://github.com/extrawurst/gitui.git
synced 2024-12-27 11:03:03 +03:00
parent
7a6dc2b192
commit
a6bce24d72
@ -144,6 +144,29 @@ pub fn stage_addremoved(repo_path: &str, path: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// get string from config
|
||||
pub fn get_config_string(
|
||||
repo_path: &str,
|
||||
key: &str,
|
||||
) -> Result<Option<String>> {
|
||||
let repo = repo(repo_path)?;
|
||||
let cfg = repo.config()?;
|
||||
|
||||
// this code doesnt match what the doc says regarding what
|
||||
// gets returned when but it actually works
|
||||
let entry_res = cfg.get_entry(key);
|
||||
|
||||
let entry = match entry_res {
|
||||
Ok(ent) => ent,
|
||||
Err(_) => return Ok(None),
|
||||
};
|
||||
|
||||
if !entry.has_value() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(entry.value().map(|s| s.to_string()))
|
||||
}
|
||||
}
|
||||
/// helper function
|
||||
pub(crate) fn bytes2string(bytes: &[u8]) -> Result<String> {
|
||||
Ok(String::from_utf8(bytes.to_vec())?)
|
||||
@ -177,7 +200,23 @@ mod tests {
|
||||
false
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_get_config() {
|
||||
let bad_dir_cfg =
|
||||
get_config_string("oodly_noodly", "this.doesnt.exist");
|
||||
assert!(bad_dir_cfg.is_err());
|
||||
|
||||
let (_td, repo) = repo_init().unwrap();
|
||||
let path = repo.path();
|
||||
let rpath = path.as_os_str().to_str().unwrap();
|
||||
let bad_cfg = get_config_string(rpath, "this.doesnt.exist");
|
||||
assert!(bad_cfg.is_ok());
|
||||
assert!(bad_cfg.unwrap().is_none());
|
||||
// repo init sets user.name
|
||||
let good_cfg = get_config_string(rpath, "user.name");
|
||||
assert!(good_cfg.is_ok());
|
||||
assert!(good_cfg.unwrap().is_some());
|
||||
}
|
||||
#[test]
|
||||
fn test_staging_one_file() {
|
||||
let file_path = Path::new("file1.txt");
|
||||
|
@ -8,7 +8,9 @@ use crate::{
|
||||
ui::{self, style::SharedTheme},
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use asyncgit::{sync::utils::repo_work_dir, CWD};
|
||||
use asyncgit::{
|
||||
sync::utils::get_config_string, sync::utils::repo_work_dir, CWD,
|
||||
};
|
||||
use crossterm::{
|
||||
event::Event,
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen},
|
||||
@ -66,26 +68,43 @@ impl ExternalEditorComponent {
|
||||
|
||||
let editor = env::var("GIT_EDITOR")
|
||||
.ok()
|
||||
.or_else(|| get_config_string(CWD, "core.editor").ok()?)
|
||||
.or_else(|| env::var("VISUAL").ok())
|
||||
.or_else(|| env::var("EDITOR").ok())
|
||||
.unwrap_or_else(|| String::from("vi"));
|
||||
|
||||
// TODO: proper handling arguments containing whitespaces
|
||||
// This does not do the right thing if the input is `editor --something "with spaces"`
|
||||
let mut editor = editor.split_whitespace();
|
||||
|
||||
let command = editor.next().ok_or_else(|| {
|
||||
anyhow!("unable to read editor command")
|
||||
})?;
|
||||
// deal with "editor name with spaces" p1 p2 p3
|
||||
// and with "editor_no_spaces" p1 p2 p3
|
||||
// does not address spaces in pn
|
||||
let mut echars = editor.chars().peekable();
|
||||
|
||||
let mut editor: Vec<&OsStr> =
|
||||
editor.map(|s| OsStr::new(s)).collect();
|
||||
let command: String = if *echars.peek().ok_or_else(|| {
|
||||
anyhow!("editor configuration set to empty string")
|
||||
})? == '\"'
|
||||
{
|
||||
echars
|
||||
.by_ref()
|
||||
.skip(1)
|
||||
.take_while(|c| *c != '\"')
|
||||
.collect()
|
||||
} else {
|
||||
echars.by_ref().take_while(|c| *c != ' ').collect()
|
||||
};
|
||||
|
||||
editor.push(path.as_os_str());
|
||||
let remainder_str = echars.collect::<String>();
|
||||
let remainder = remainder_str.split_whitespace();
|
||||
|
||||
Command::new(command)
|
||||
let mut args: Vec<&OsStr> =
|
||||
remainder.map(|s| OsStr::new(s)).collect();
|
||||
|
||||
args.push(path.as_os_str());
|
||||
|
||||
Command::new(command.clone())
|
||||
.current_dir(work_dir)
|
||||
.args(editor)
|
||||
.args(args)
|
||||
.status()
|
||||
.map_err(|e| anyhow!("\"{}\": {}", command, e))?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user