feat(status): relative path of obj

This commit is contained in:
grimhilt 2024-09-11 23:36:29 +02:00
parent e66dc8d408
commit 8f636b4bf7
6 changed files with 107 additions and 24 deletions

View File

@ -106,7 +106,7 @@ fn setup_staged(obj_statuses: Arc<ObjStatuses>, indexer: &Indexer) -> ObjStaged
pub fn exec(args: StatusArgs, config: Config) {
let status = get_obj_changes(&args, &config);
print_status(&status);
print_status(&status, config.get_root_unsafe());
}
pub fn get_obj_changes(args: &StatusArgs, config: &Config) -> ObjStaged {
@ -156,7 +156,7 @@ pub fn get_obj_changes(args: &StatusArgs, config: &Config) -> ObjStaged {
}
///
fn print_status(objs: &ObjStaged) {
fn print_status(objs: &ObjStaged, root_path: &PathBuf) {
if objs.staged.len() == 0 && objs.not_staged.len() == 0 {
println!("Nothing to push, working tree clean");
return;
@ -168,7 +168,7 @@ fn print_status(objs: &ObjStaged) {
// (use "git restore --staged <file>..." to unstage)
// by alphabetical order
for obj in objs.staged.iter() {
print_object(&obj, |status: &str| status.green());
print_object(&obj, root_path, |status: &str| status.green());
}
}
// modified
@ -178,7 +178,7 @@ fn print_status(objs: &ObjStaged) {
println!("Changes not staged for push:");
println!(" (Use \"nextsync add <file>...\" to update what will be pushed)");
for obj in objs.not_staged.iter() {
print_object(&obj, |status: &str| status.red());
print_object(&obj, root_path, |status: &str| status.red());
}
// println!("Untracked files:");
@ -187,7 +187,7 @@ fn print_status(objs: &ObjStaged) {
// }
}
fn print_object(obj: &Obj, color: impl Fn(&str) -> ColoredString) {
fn print_object(obj: &Obj, root_path: &PathBuf, color: impl Fn(&str) -> ColoredString) {
println!(
" {}{}",
match obj.get_status() {
@ -201,7 +201,7 @@ fn print_object(obj: &Obj, color: impl Fn(&str) -> ColoredString) {
ObjStatus::Deleted => color("deleted: "),
_ => "unknown".red(),
},
color(&obj.cpy_path().to_string())
color(&path::to_string(&obj.get_env_relative_path(root_path)))
);
}

View File

@ -1,5 +1,6 @@
use crate::store::{structs::ObjPath, nsobject::NsObject};
use crate::store::{nsobject::NsObject, structs::ObjPath};
use crate::utils::path;
use std::env;
use std::fs;
use std::path::PathBuf;
use std::sync::OnceLock;
@ -26,7 +27,6 @@ impl From<ObjType> for u8 {
}
}
impl TryFrom<u8> for ObjType {
type Error = String;
@ -96,6 +96,32 @@ impl Obj {
&self.obj_path
}
/// Return the path of the current object relatively to the path the
/// command was executed from.
///
/// * `repo_root`: the absolute repo's root path
pub fn get_env_relative_path(&self, repo_root: &PathBuf) -> PathBuf {
let binding = env::current_dir().unwrap();
if let Ok(root_diff) = binding.strip_prefix(repo_root) {
match self.obj_path.strip_prefix(&root_diff) {
Ok(path) => path.to_path_buf(),
Err(_) => {
// if cannot strip prefix then we need to go up to the root
let mut res_path = PathBuf::new();
for _ in 0..path::get_level(&root_diff.to_path_buf()) {
res_path.push("..");
}
res_path.push(&*self.obj_path);
res_path
}
}
} else {
// if cannot strip prefix then we are at the repo's root
self.obj_path.to_path_buf()
}
}
pub fn cpy_path(&self) -> String {
path::to_string(&self.obj_path)
}

View File

@ -13,7 +13,7 @@ static REPO_ROOT: OnceLock<PathBuf> = OnceLock::new();
pub fn init(repo_root: &Option<PathBuf>) {
if tests::is_var_setup() {
REPO_ROOT_DEV.lock().unwrap()[0] = repo_root.clone().unwrap();
REPO_ROOT_DEV.lock().unwrap()[0] = repo_root.clone().expect("Tried to initialize REPO_ROOT_DEV without a proper `repo_root`");
return;
}

View File

@ -16,6 +16,15 @@ pub fn to_string(path: &PathBuf) -> String {
path.to_str().unwrap().to_string()
}
pub fn get_level(path: &PathBuf) -> i32 {
let mut level = 0;
let mut path = path.clone();
while path.pop() {
level += 1;
}
level
}
/// Improve the path to try remove and solve .. token.
/// Taken from https://stackoverflow.com/questions/68231306/stdfscanonicalize-for-files-that-dont-exist
///

View File

@ -66,6 +66,13 @@ impl ClientTest {
Config::from(Some(&self.volume))
}
pub fn new_config(&self, path: &str) -> Config {
let mut full_path = self.volume.clone();
full_path.push_str("/");
full_path.push_str(path);
Config::from(Some(&full_path))
}
pub fn ok(self) -> io::Result<()> {
fs::remove_dir_all(&self.volume)?;
Ok(())

View File

@ -15,19 +15,35 @@ fn status_expected(config: &Config, staged: Vec<&str>, not_staged: Vec<&str>) {
assert_eq!(res.not_staged.len(), not_staged.len());
for obj in staged {
assert!(res
.staged
.iter()
.position(|e| { e.get_obj_path() == &PathBuf::from(obj) })
.is_some());
assert!(
res.staged
.iter()
.position(|e| {
e.get_env_relative_path(config.get_root_unsafe()) == PathBuf::from(obj)
})
.is_some(),
"{:?}",
res.staged
.iter()
.map(|e| { e.get_env_relative_path(config.get_root_unsafe()) })
.collect::<Vec<PathBuf>>()
);
}
for obj in not_staged {
assert!(res
.not_staged
.iter()
.position(|e| { e.get_obj_path() == &PathBuf::from(obj) })
.is_some());
assert!(
res.not_staged
.iter()
.position(|e| {
e.get_env_relative_path(config.get_root_unsafe()) == PathBuf::from(obj)
})
.is_some(),
"{:?}",
res.not_staged
.iter()
.map(|e| { e.get_env_relative_path(config.get_root_unsafe()) })
.collect::<Vec<PathBuf>>()
);
}
}
@ -55,13 +71,16 @@ fn all_folder() -> io::Result<()> {
status_expected(&client.get_config(), vec![], vec!["foo", "dir"]);
client.exec_ok("add dir");
status_expected(&client.get_config(), vec!["dir/foo", "dir/bar"], vec!["foo"]);
status_expected(
&client.get_config(),
vec!["dir/foo", "dir/bar"],
vec!["foo"],
);
client.ok()
}
#[test]
#[ignore]
fn all_folder_current() -> io::Result<()> {
let mut client = ClientTest::new("status__all_folder_current").init();
@ -73,9 +92,31 @@ fn all_folder_current() -> io::Result<()> {
client.exec_ok("add dir");
status_expected(
&Config::from(Some(&String::from("./dir"))),
vec!["foor", "bar"],
vec!["../foo"],
&client.new_config("dir"),
vec!["dir/foo", "dir/bar"],
vec![],
);
client.ok()
}
#[test]
#[ignore]
fn relative_path() -> io::Result<()> {
let mut client = ClientTest::new("status__all_folder_current").init();
client.add_dir("dir")?;
client.add_file("dir/foo", "foo")?;
client.add_file("dir/bar", "bar")?;
client.add_file("foor", "foor")?;
status_expected(&client.get_config(), vec![], vec!["foor", "dir"]);
client.exec_ok("add dir");
// client.set_execution_path("dir");
status_expected(
&client.new_config("dir"),
vec!["foo", "bar"],
vec!["../foor"],
);
client.ok()