mirror of
https://github.com/bootandy/dust.git
synced 2025-12-12 15:49:58 -08:00
Code changes: Removed ignore & channel crates. Using a single reciever thread to build a hashmap to prevend duplicate inodes being reported gave a severe performance penalty Using rayon crate with some hand crafted file traversal has improved performance aprox 10X Behaviour changes: Removed parameter 'limit by filesystem' - don't think this is used, and I only added it as it was easy to add with the ignore crate. Sym links will now not appear in the output tree unless using '-s' 'apparent-size' flag Change behaviour of multiple args so that it unifies them and compares them under one tree instead of treating them individually: https://github.com/bootandy/dust/issues/136
140 lines
4.2 KiB
Rust
140 lines
4.2 KiB
Rust
use assert_cmd::Command;
|
|
use std::cmp::max;
|
|
use std::fs::File;
|
|
use std::io::Write;
|
|
use std::path::PathBuf;
|
|
use std::str;
|
|
|
|
use terminal_size::{terminal_size, Height, Width};
|
|
use unicode_width::UnicodeWidthStr;
|
|
|
|
use tempfile::Builder;
|
|
use tempfile::TempDir;
|
|
|
|
// File sizes differ on both platform and on the format of the disk.
|
|
// Windows: `ln` is not usually an available command; creation of symbolic links requires special enhanced permissions
|
|
|
|
fn get_width_of_terminal() -> u16 {
|
|
if let Some((Width(w), Height(_h))) = terminal_size() {
|
|
max(w, 80)
|
|
} else {
|
|
80
|
|
}
|
|
}
|
|
|
|
// Mac test runners create tmp files with very long names, hence it may be shortened in the output
|
|
fn get_file_name(name: String) -> String {
|
|
let terminal_plus_buffer = (get_width_of_terminal() - 14) as usize;
|
|
if UnicodeWidthStr::width(&*name) > terminal_plus_buffer {
|
|
let trimmed_name = name
|
|
.chars()
|
|
.take(terminal_plus_buffer - 2)
|
|
.collect::<String>();
|
|
trimmed_name + ".."
|
|
} else {
|
|
name
|
|
}
|
|
}
|
|
|
|
fn build_temp_file(dir: &TempDir) -> PathBuf {
|
|
let file_path = dir.path().join("notes.txt");
|
|
let mut file = File::create(&file_path).unwrap();
|
|
writeln!(file, "I am a temp file").unwrap();
|
|
file_path
|
|
}
|
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
|
#[test]
|
|
pub fn test_soft_sym_link() {
|
|
let dir = Builder::new().tempdir().unwrap();
|
|
let file = build_temp_file(&dir);
|
|
let dir_s = dir.path().to_str().unwrap();
|
|
let file_path_s = file.to_str().unwrap();
|
|
|
|
let link_name = dir.path().join("the_link");
|
|
let link_name_s = link_name.to_str().unwrap();
|
|
let c = Command::new("ln")
|
|
.arg("-s")
|
|
.arg(file_path_s)
|
|
.arg(link_name_s)
|
|
.output();
|
|
assert!(c.is_ok());
|
|
|
|
let c = format!(" ├── {}", get_file_name(link_name_s.into()));
|
|
let b = format!(" ┌── {}", get_file_name(file_path_s.into()));
|
|
let a = format!("─┴ {}", dir_s);
|
|
|
|
let mut cmd = Command::cargo_bin("dust").unwrap();
|
|
let output = cmd.arg("-p").arg("-c").arg("-s").arg(dir_s).unwrap().stdout;
|
|
|
|
let output = str::from_utf8(&output).unwrap();
|
|
|
|
assert!(output.contains(a.as_str()));
|
|
assert!(output.contains(b.as_str()));
|
|
assert!(output.contains(c.as_str()));
|
|
}
|
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
|
#[test]
|
|
pub fn test_hard_sym_link() {
|
|
let dir = Builder::new().tempdir().unwrap();
|
|
let file = build_temp_file(&dir);
|
|
let dir_s = dir.path().to_str().unwrap();
|
|
let file_path_s = file.to_str().unwrap();
|
|
|
|
let link_name = dir.path().join("the_link");
|
|
let link_name_s = link_name.to_str().unwrap();
|
|
let c = Command::new("ln")
|
|
.arg(file_path_s)
|
|
.arg(link_name_s)
|
|
.output();
|
|
assert!(c.is_ok());
|
|
|
|
let link_output = format!(" ┌── {}", get_file_name(link_name_s.into()));
|
|
let file_output = format!(" ┌── {}", get_file_name(file_path_s.into()));
|
|
let dirs_output = format!("─┴ {}", dir_s);
|
|
|
|
let mut cmd = Command::cargo_bin("dust").unwrap();
|
|
let output = cmd.arg("-p").arg("-c").arg(dir_s).unwrap().stdout;
|
|
|
|
// Because this is a hard link the file and hard link look identical. Therefore
|
|
// we cannot guarantee which version will appear first.
|
|
let output = str::from_utf8(&output).unwrap();
|
|
assert!(output.contains(dirs_output.as_str()));
|
|
assert!(output.contains(link_output.as_str()) || output.contains(file_output.as_str()));
|
|
}
|
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
|
#[test]
|
|
pub fn test_recursive_sym_link() {
|
|
let dir = Builder::new().tempdir().unwrap();
|
|
let dir_s = dir.path().to_str().unwrap();
|
|
|
|
let link_name = dir.path().join("the_link");
|
|
let link_name_s = link_name.to_str().unwrap();
|
|
|
|
let c = Command::new("ln")
|
|
.arg("-s")
|
|
.arg(dir_s)
|
|
.arg(link_name_s)
|
|
.output();
|
|
assert!(c.is_ok());
|
|
|
|
let a = format!("─┬ {}", dir_s);
|
|
let b = format!(" └── {}", get_file_name(link_name_s.into()));
|
|
|
|
let mut cmd = Command::cargo_bin("dust").unwrap();
|
|
let output = cmd
|
|
.arg("-p")
|
|
.arg("-c")
|
|
.arg("-r")
|
|
.arg("-s")
|
|
.arg(dir_s)
|
|
.unwrap()
|
|
.stdout;
|
|
let output = str::from_utf8(&output).unwrap();
|
|
|
|
assert!(output.contains(a.as_str()));
|
|
assert!(output.contains(b.as_str()));
|
|
}
|