Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions aria/contents/docs/libra/command/rm/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ that.)

- `-r`, `--recursive`<br/>
Allow recursive removal when a leading directory name is given.

- `-f`, `--force`<br/>
Force removal even if the specified paths are not tracked. This skips validation checks and deletes files or directories regardless of their index status.
2 changes: 2 additions & 0 deletions libra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ tracing-subscriber = { workspace = true }
wax = { workspace = true }
url = { workspace = true }
ignore = { workspace = true }
tempfile = { workspace = true }
serial_test = { workspace = true }

[target.'cfg(unix)'.dependencies] # only on Unix
pager = { workspace = true }
Expand Down
50 changes: 38 additions & 12 deletions libra/src/command/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ use mercury::internal::index::Index;
#[derive(Parser, Debug)]
pub struct RemoveArgs {
/// file or dir to remove
pathspec: Vec<String>,
pub pathspec: Vec<String>,
/// whether to remove from index
#[clap(long)]
cached: bool,
pub cached: bool,
/// indicate recursive remove dir
#[clap(short, long)]
recursive: bool,
pub recursive: bool,
/// force removal, skip validation
#[clap(short, long)]
pub force: bool,
}

pub fn execute(args: RemoveArgs) -> Result<(), GitError> {
Expand All @@ -28,11 +31,13 @@ pub fn execute(args: RemoveArgs) -> Result<(), GitError> {
}
let idx_file = path::index();
let mut index = Index::load(&idx_file)?;
// check if pathspec is all in index
if !validate_pathspec(&args.pathspec, &index) {

// check if pathspec is all in index (skip if force is enabled)
if !args.force && !validate_pathspec(&args.pathspec, &index) {
return Ok(());
}
let dirs = get_dirs(&args.pathspec, &index);

let dirs = get_dirs(&args.pathspec, &index, args.force);
if !dirs.is_empty() && !args.recursive {
println!(
"fatal: not removing '{}' recursively without -r",
Expand All @@ -44,6 +49,7 @@ pub fn execute(args: RemoveArgs) -> Result<(), GitError> {
for path_str in args.pathspec.iter() {
let path = PathBuf::from(path_str);
let path_wd = path.to_workdir().to_string_or_panic();

if dirs.contains(path_str) {
// dir
let removed = index.remove_dir_files(&path_wd);
Expand All @@ -56,8 +62,20 @@ pub fn execute(args: RemoveArgs) -> Result<(), GitError> {
}
} else {
// file
index.remove(&path_wd, 0);
println!("rm '{}'", path_wd.bright_green());
if args.force {
// In force mode, remove from index if tracked, otherwise just delete from filesystem
if index.tracked(&path_wd, 0) {
index.remove(&path_wd, 0);
println!("rm '{}'", path_wd.bright_green());
} else {
println!("rm '{}'", path_wd.bright_yellow());
}
} else {
// Normal mode - only remove if tracked
index.remove(&path_wd, 0);
println!("rm '{}'", path_wd.bright_green());
}

if !args.cached {
fs::remove_file(&path)?;
}
Expand Down Expand Up @@ -90,14 +108,22 @@ fn validate_pathspec(pathspec: &[String], index: &Index) -> bool {
}

/// run after `validate_pathspec`
fn get_dirs(pathspec: &[String], index: &Index) -> Vec<String> {
fn get_dirs(pathspec: &[String], index: &Index, force: bool) -> Vec<String> {
let mut dirs = Vec::new();
for path_str in pathspec.iter() {
let path = PathBuf::from(path_str);
let path_wd = path.to_workdir().to_string_or_panic();
// valid but not tracked, means a dir
if !index.tracked(&path_wd, 0) {
dirs.push(path_str.clone());

if force {
// In force mode, check if the path exists and is a directory
if path.exists() && path.is_dir() {
dirs.push(path_str.clone());
}
} else {
// valid but not tracked, means a dir
if !index.tracked(&path_wd, 0) {
dirs.push(path_str.clone());
}
}
}
dirs
Expand Down
Loading
Loading