Skip to content

Commit d32823a

Browse files
committed
mv: fix invalid numbered backup path
1 parent c315cd9 commit d32823a

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

src/uucore/src/lib/features/backup_control.rs

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -421,25 +421,29 @@ pub fn get_backup_path(
421421
}
422422

423423
fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
424-
let mut p = path.to_string_lossy().into_owned();
425-
p.push_str(suffix);
426-
PathBuf::from(p)
424+
let mut file_name = path.file_name().unwrap_or_default().to_os_string();
425+
file_name.push(suffix);
426+
path.with_file_name(file_name)
427427
}
428428

429429
fn numbered_backup_path(path: &Path) -> PathBuf {
430+
let file_name = path.file_name().unwrap_or_default();
430431
for i in 1_u64.. {
431-
let path_str = &format!("{}.~{}~", path.to_string_lossy(), i);
432-
let path = Path::new(path_str);
432+
let mut numbered_file_name = file_name.to_os_string();
433+
numbered_file_name.push(format!(".~{}~", i));
434+
let path = path.with_file_name(numbered_file_name);
433435
if !path.exists() {
434-
return path.to_path_buf();
436+
return path;
435437
}
436438
}
437439
panic!("cannot create backup")
438440
}
439441

440442
fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
441-
let test_path_str = &format!("{}.~1~", path.to_string_lossy());
442-
let test_path = Path::new(test_path_str);
443+
let file_name = path.file_name().unwrap_or_default();
444+
let mut numbered_file_name = file_name.to_os_string();
445+
numbered_file_name.push(".~1~");
446+
let test_path = path.with_file_name(numbered_file_name);
443447
if test_path.exists() {
444448
numbered_backup_path(path)
445449
} else {
@@ -660,6 +664,44 @@ mod tests {
660664
let result = determine_backup_suffix(&matches);
661665
assert_eq!(result, "-v");
662666
}
667+
668+
#[test]
669+
fn test_numbered_backup_path() {
670+
assert_eq!(numbered_backup_path(&Path::new("")), PathBuf::from(".~1~"));
671+
assert_eq!(
672+
numbered_backup_path(&Path::new("/")),
673+
PathBuf::from("/.~1~")
674+
);
675+
assert_eq!(
676+
numbered_backup_path(&Path::new("/hello/world")),
677+
PathBuf::from("/hello/world.~1~")
678+
);
679+
assert_eq!(
680+
numbered_backup_path(&Path::new("/hello/world/")),
681+
PathBuf::from("/hello/world.~1~")
682+
);
683+
}
684+
685+
#[test]
686+
fn test_simple_backup_path() {
687+
assert_eq!(
688+
simple_backup_path(&Path::new(""), ".bak"),
689+
PathBuf::from(".bak")
690+
);
691+
assert_eq!(
692+
simple_backup_path(&Path::new("/"), ".bak"),
693+
PathBuf::from("/.bak")
694+
);
695+
assert_eq!(
696+
simple_backup_path(&Path::new("/hello/world"), ".bak"),
697+
PathBuf::from("/hello/world.bak")
698+
);
699+
assert_eq!(
700+
simple_backup_path(&Path::new("/hello/world/"), ".bak"),
701+
PathBuf::from("/hello/world.bak")
702+
);
703+
}
704+
663705
#[test]
664706
fn test_source_is_target_backup() {
665707
let source = Path::new("data.txt.bak");

tests/by-util/test_mv.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,30 @@ fn test_mv_simple_backup() {
571571
assert!(at.file_exists(format!("{file_b}~")));
572572
}
573573

574+
#[test]
575+
fn test_mv_simple_backup_for_directory() {
576+
let (at, mut ucmd) = at_and_ucmd!();
577+
let dir_a = "test_mv_simple_backup_dir_a";
578+
let dir_b = "test_mv_simple_backup_dir_b";
579+
580+
at.mkdir(dir_a);
581+
at.mkdir(dir_b);
582+
at.touch(format!("{dir_a}/file_a"));
583+
at.touch(format!("{dir_b}/file_b"));
584+
ucmd.arg("-T")
585+
.arg("-b")
586+
.arg(dir_a)
587+
.arg(dir_b)
588+
.succeeds()
589+
.no_stderr();
590+
591+
assert!(!at.dir_exists(dir_a));
592+
assert!(at.dir_exists(dir_b));
593+
assert!(at.dir_exists(&format!("{dir_b}~")));
594+
assert!(at.file_exists(format!("{dir_b}/file_a")));
595+
assert!(at.file_exists(format!("{dir_b}~/file_b")));
596+
}
597+
574598
#[test]
575599
fn test_mv_simple_backup_with_file_extension() {
576600
let (at, mut ucmd) = at_and_ucmd!();

0 commit comments

Comments
 (0)