Skip to content

Commit 023132d

Browse files
authored
Merge pull request #11 from santoshxshrestha/regex
fix: same item name handing
2 parents b21a3e0 + 1006cf2 commit 023132d

File tree

3 files changed

+112
-23
lines changed

3 files changed

+112
-23
lines changed

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.1.12] - 2025-09-10
11+
12+
### Changed
13+
- **Improved variable naming**: Updated variable names to be more descriptive and consistent across the codebase.
14+
15+
### Fixed
16+
17+
- **Conflicting trash items**: Updated logic to handle conflicts when recovering files with the same name.
18+
Now, if a file with the same name exists in the original location, the recovered file will be renamed with a timestamp suffix to avoid overwriting.
19+
20+
1021
## [0.1.11] - 2025-09-07
1122

1223
### Changed
@@ -17,11 +28,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1728
## [0.1.10] - 2025-09-07
1829

1930
### Fixed
31+
2032
- **Critical ignore flag bug**: Fixed issue where `-i, --ignore` flag was not functioning correctly, causing errors while trying to ingore them while using `rmxt` commands
2133

2234
### Changed
23-
- Imporved different cases handling in the ignore flag logic with match block
2435

36+
- Imporved different cases handling in the ignore flag logic with match block
2537

2638
## [0.1.9] - 2025-09-01
2739

src/args.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ pub struct Args {
1111
#[command(subcommand)]
1212
pub command: Option<Commands>,
1313

14-
/// Don't put the file in trash, remove it permanently
14+
/// Don't put the item in trash, remove it permanently
1515
#[arg(short = 'p', long, global = false)]
1616
pub permanent: bool,
1717

1818
/// Remove directories and their contents recursively
1919
#[arg(short = 'r', long, global = false)]
2020
pub recursive: bool,
2121

22-
/// Force removal of files without prompt
22+
/// Force removal of item without prompt
2323
#[arg(short = 'f', long, global = false)]
2424
pub force: bool,
2525

@@ -30,15 +30,15 @@ pub struct Args {
3030

3131
#[derive(Debug, Subcommand)]
3232
pub enum Commands {
33-
/// List files in the trash directory
33+
/// List items in the trash directory
3434
#[command(name = "list")]
3535
List {
36-
/// Specify time from which to list files (in days)
36+
/// Specify time from which to list items (in days)
3737
#[arg(short = 't', long, global = false)]
3838
time: Option<i64>,
3939
},
4040

41-
/// Clean up the trash directory by removing files older than 30 days
41+
/// Clean up the trash directory by removing files/directories older than 30 days
4242
#[command(name = "tidy")]
4343
Tidy {
4444
/// Specify time to live for tidy command (in days) (default is 30 days)
@@ -49,20 +49,20 @@ pub enum Commands {
4949
/// recover all the content of the trash
5050
#[command(name = "recover-all")]
5151
RecoverAll {
52-
/// Specify time from which to recover files (in days)
52+
/// Specify time from which to recover files/directories (in days)
5353
#[arg(short = 't', long, global = false)]
5454
time: Option<i64>,
5555
},
5656

57-
/// Recover files from the trash directory
57+
/// Recover items from the trash directory
5858
#[command(name = "recover")]
5959
Recover {
60-
/// Name of the file to recover
60+
/// Name of the file/directorie to recover
6161
#[arg(help = "Name of the file to recover from trash")]
6262
name: Vec<String>,
6363
},
6464

65-
/// Purge files from the trash directory
65+
/// Purge files/directorie from the trash directory
6666
#[command(name = "purge")]
6767
Purge {
6868
/// Purge files from the trash directory
@@ -72,8 +72,8 @@ pub enum Commands {
7272
}
7373

7474
impl Args {
75-
/// Get the files to remove, handling the default case
76-
pub fn get_files(&self) -> Vec<PathBuf> {
75+
/// Get the items to remove, handling the default case
76+
pub fn get_items(&self) -> Vec<PathBuf> {
7777
match &self.command {
7878
Some(_) => Vec::new(), // No files for list/tidy/recover commands
7979
None => self.file.clone(), // Use the default file argument
@@ -113,7 +113,7 @@ impl Args {
113113
matches!(self.command, Some(Commands::Purge { .. }))
114114
}
115115

116-
/// Get the name to purge (if purge command is active)
116+
/// Get the name of the item to purge (if purge command is active)
117117
pub fn get_purge_name(&self) -> Vec<String> {
118118
match &self.command {
119119
Some(Commands::Purge { name }) => name.clone(),
@@ -143,7 +143,7 @@ impl Args {
143143
}
144144
}
145145

146-
/// Get the time from which to list files for list command
146+
/// Get the time from which to list files/directories for list command
147147
pub fn get_time_list(&self) -> i64 {
148148
match &self.command {
149149
// Default to 0 days (which will be evaluated to all the content)if not specified

src/main.rs

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use chrono::{Local, TimeZone};
22
use colored::Colorize;
3-
use tabled::{
4-
Table, Tabled,
5-
settings::{Alignment, Style, object::Columns},
6-
};
3+
use std::path::Path;
4+
use tabled::settings::object::Columns;
5+
use tabled::settings::{Alignment, Style};
6+
use tabled::{Table, Tabled};
77
use trash::os_limited::restore_all;
88
mod args;
99
use args::Args;
1010
use clap::Parser;
11-
use std::fs;
11+
use std::{fs, path::PathBuf};
1212
use trash::os_limited;
1313
use trash::{TrashItem, delete};
1414

@@ -103,12 +103,77 @@ pub fn tidy_trash(days: i64) -> Result<(), trash::Error> {
103103
}
104104
Ok(())
105105
}
106+
pub fn resolve_conflict(path: &PathBuf) -> std::io::Result<()> {
107+
let name = match path.file_name() {
108+
Some(name) => name.to_string_lossy(),
109+
None => {
110+
eprintln!("{}", "Path does not have a valid filename".red());
111+
return Ok(());
112+
}
113+
};
114+
115+
let timestamp = Local::now().format("%Y%m%d_%H%M%S");
116+
117+
let stem = path
118+
.file_stem()
119+
.map(|s| s.to_string_lossy())
120+
.unwrap_or_else(|| name.clone());
121+
122+
let extension = path
123+
.extension()
124+
.map(|ext| format!(".{}", ext.to_string_lossy()))
125+
.unwrap_or_default();
126+
127+
let new_name = format!("{}_{}{}", stem, timestamp, extension);
128+
129+
eprintln!(
130+
"{}",
131+
format!(
132+
"Conflict detected: '{}' already exists in trash. Would be renamed to: '{}'",
133+
name, new_name
134+
)
135+
.yellow()
136+
);
137+
138+
fs::rename(path, &new_name)?;
139+
140+
if let Err(e) = delete(&new_name) {
141+
eprintln!(
142+
"{}",
143+
format!("Error moving {} to trash: {e}", path.display()).red()
144+
);
145+
}
146+
147+
Ok(())
148+
}
149+
150+
pub fn check_conflict(path: &Path) -> bool {
151+
let name = match path.file_name() {
152+
Some(name) => name.to_string_lossy(),
153+
None => {
154+
eprintln!("{}", "Path does not have a valid filename".red());
155+
return false;
156+
}
157+
};
158+
159+
let trash_list = match os_limited::list() {
160+
Ok(items) => items,
161+
Err(e) => {
162+
eprintln!("{}", format!("Error listing trash items: {e}").red());
163+
return false;
164+
}
165+
};
166+
167+
trash_list
168+
.iter()
169+
.any(|item| item.name.to_string_lossy() == name)
170+
}
106171

107172
fn main() {
108173
// parsing the args
109174
let args = Args::parse();
110175

111-
let paths = args.get_files();
176+
let paths = args.get_items();
112177
let recursive = args.recursive;
113178
let force = args.force;
114179
let dir = args.dir;
@@ -286,9 +351,21 @@ All the contents from the trash more then {days} days will be deleted permanentl
286351
}
287352
}
288353
(false, _, _, _, _) => {
289-
if let Err(e) = delete(&path) {
290-
eprintln!("{}", format!("Error moving to trash: {e}").red());
291-
}
354+
match check_conflict(&path) {
355+
true => {
356+
if let Err(e) = resolve_conflict(&path) {
357+
eprintln!("{}", format!("Error resolving conflict: {e}").red());
358+
}
359+
}
360+
false => {
361+
if let Err(e) = delete(&path) {
362+
eprintln!(
363+
"{}",
364+
format!("Error moving {} to trash: {e}", path.display()).red()
365+
);
366+
}
367+
}
368+
};
292369
}
293370
_ => {}
294371
}

0 commit comments

Comments
 (0)