mirror of
https://github.com/nushell/nushell.git
synced 2024-11-26 02:13:47 +01:00
51aa66fef7
# Description This fixes #12391. nushell/nushell@87c5f6e455 accidentally introduced a bug where the path was not being properly expanded according to the cwd. This makes both 'touch' and 'mkdir' use globs just like the rest of the commands to preserve tilde behavior while still expanding the paths properly. This doesn't actually expand the globs. Should it? # User-Facing Changes - Restore behavior of `mkdir`, `touch` - Help text now says they can take globs, but they won't actually expand them, maybe this should be changed # Tests + Formatting Regression tests added. # After Submitting This is severe enough and should be included in the point release.
518 lines
15 KiB
Rust
518 lines
15 KiB
Rust
use chrono::{DateTime, Local};
|
|
use nu_test_support::fs::{files_exist_at, Stub};
|
|
use nu_test_support::nu;
|
|
use nu_test_support::playground::Playground;
|
|
use std::path::Path;
|
|
|
|
// Use 1 instead of 0 because 0 has a special meaning in Windows
|
|
const TIME_ONE: filetime::FileTime = filetime::FileTime::from_unix_time(1, 0);
|
|
|
|
#[test]
|
|
fn creates_a_file_when_it_doesnt_exist() {
|
|
Playground::setup("create_test_1", |dirs, _sandbox| {
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch i_will_be_created.txt"
|
|
);
|
|
|
|
let path = dirs.test().join("i_will_be_created.txt");
|
|
assert!(path.exists());
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn creates_two_files() {
|
|
Playground::setup("create_test_2", |dirs, _sandbox| {
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch a b"
|
|
);
|
|
|
|
let path = dirs.test().join("a");
|
|
assert!(path.exists());
|
|
|
|
let path2 = dirs.test().join("b");
|
|
assert!(path2.exists());
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_modified_time_of_file_to_today() {
|
|
Playground::setup("change_time_test_9", |dirs, sandbox| {
|
|
sandbox.with_files(vec![Stub::EmptyFile("file.txt")]);
|
|
let path = dirs.test().join("file.txt");
|
|
|
|
// Set file.txt's times to the past before the test to make sure `touch` actually changes the mtime to today
|
|
filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -m file.txt"
|
|
);
|
|
|
|
let metadata = path.metadata().unwrap();
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let mtime_day = DateTime::<Local>::from(metadata.modified().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, mtime_day);
|
|
|
|
// Check that atime remains unchanged
|
|
assert_eq!(
|
|
TIME_ONE,
|
|
filetime::FileTime::from_system_time(metadata.accessed().unwrap())
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_access_time_of_file_to_today() {
|
|
Playground::setup("change_time_test_18", |dirs, sandbox| {
|
|
sandbox.with_files(vec![Stub::EmptyFile("file.txt")]);
|
|
let path = dirs.test().join("file.txt");
|
|
|
|
// Set file.txt's times to the past before the test to make sure `touch` actually changes the atime to today
|
|
filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -a file.txt"
|
|
);
|
|
|
|
let metadata = path.metadata().unwrap();
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let atime_day = DateTime::<Local>::from(metadata.accessed().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, atime_day);
|
|
|
|
// Check that mtime remains unchanged
|
|
assert_eq!(
|
|
TIME_ONE,
|
|
filetime::FileTime::from_system_time(metadata.modified().unwrap())
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_modified_and_access_time_of_file_to_today() {
|
|
Playground::setup("change_time_test_27", |dirs, sandbox| {
|
|
sandbox.with_files(vec![Stub::EmptyFile("file.txt")]);
|
|
let path = dirs.test().join("file.txt");
|
|
|
|
filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -a -m file.txt"
|
|
);
|
|
|
|
let metadata = path.metadata().unwrap();
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let mtime_day = DateTime::<Local>::from(metadata.modified().unwrap()).date_naive();
|
|
let atime_day = DateTime::<Local>::from(metadata.accessed().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, mtime_day);
|
|
assert_eq!(today, atime_day);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn not_create_file_if_it_not_exists() {
|
|
Playground::setup("change_time_test_28", |dirs, _sandbox| {
|
|
let outcome = nu!(
|
|
cwd: dirs.test(),
|
|
"touch -c file.txt"
|
|
);
|
|
|
|
let path = dirs.test().join("file.txt");
|
|
|
|
assert!(!path.exists());
|
|
|
|
// If --no-create is improperly handled `touch` may error when trying to change the times of a nonexistent file
|
|
assert!(outcome.status.success())
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_file_times_if_exists_with_no_create() {
|
|
Playground::setup(
|
|
"change_file_times_if_exists_with_no_create",
|
|
|dirs, sandbox| {
|
|
sandbox.with_files(vec![Stub::EmptyFile("file.txt")]);
|
|
let path = dirs.test().join("file.txt");
|
|
|
|
filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -c file.txt"
|
|
);
|
|
|
|
let metadata = path.metadata().unwrap();
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let mtime_day = DateTime::<Local>::from(metadata.modified().unwrap()).date_naive();
|
|
let atime_day = DateTime::<Local>::from(metadata.accessed().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, mtime_day);
|
|
assert_eq!(today, atime_day);
|
|
},
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn creates_file_three_dots() {
|
|
Playground::setup("create_test_1", |dirs, _sandbox| {
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch file..."
|
|
);
|
|
|
|
let path = dirs.test().join("file...");
|
|
assert!(path.exists());
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn creates_file_four_dots() {
|
|
Playground::setup("create_test_1", |dirs, _sandbox| {
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch file...."
|
|
);
|
|
|
|
let path = dirs.test().join("file....");
|
|
assert!(path.exists());
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn creates_file_four_dots_quotation_marks() {
|
|
Playground::setup("create_test_1", |dirs, _sandbox| {
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch 'file....'"
|
|
);
|
|
|
|
let path = dirs.test().join("file....");
|
|
assert!(path.exists());
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_file_times_to_reference_file() {
|
|
Playground::setup("change_dir_times_to_reference_dir", |dirs, sandbox| {
|
|
sandbox.with_files(vec![
|
|
Stub::EmptyFile("reference_file"),
|
|
Stub::EmptyFile("target_file"),
|
|
]);
|
|
|
|
let reference = dirs.test().join("reference_file");
|
|
let target = dirs.test().join("target_file");
|
|
|
|
// Change the times for reference
|
|
filetime::set_file_times(
|
|
&reference,
|
|
filetime::FileTime::from_unix_time(1337, 0),
|
|
TIME_ONE,
|
|
)
|
|
.unwrap();
|
|
|
|
// target should have today's date since it was just created, but reference should be different
|
|
assert_ne!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_ne!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -r reference_file target_file"
|
|
);
|
|
|
|
assert_eq!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_eq!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_file_mtime_to_reference() {
|
|
Playground::setup("change_file_mtime_to_reference", |dirs, sandbox| {
|
|
sandbox.with_files(vec![
|
|
Stub::EmptyFile("reference_file"),
|
|
Stub::EmptyFile("target_file"),
|
|
]);
|
|
|
|
let reference = dirs.test().join("reference_file");
|
|
let target = dirs.test().join("target_file");
|
|
|
|
// Change the times for reference
|
|
filetime::set_file_times(
|
|
&reference,
|
|
TIME_ONE,
|
|
filetime::FileTime::from_unix_time(1337, 0),
|
|
)
|
|
.unwrap();
|
|
|
|
// target should have today's date since it was just created, but reference should be different
|
|
assert_ne!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_ne!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
|
|
// Save target's current atime to make sure it is preserved
|
|
let target_original_atime = target.metadata().unwrap().accessed().unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -mr reference_file target_file"
|
|
);
|
|
|
|
assert_eq!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
assert_ne!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_eq!(
|
|
target_original_atime,
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_modified_time_of_dir_to_today() {
|
|
Playground::setup("change_dir_mtime", |dirs, sandbox| {
|
|
sandbox.mkdir("test_dir");
|
|
let path = dirs.test().join("test_dir");
|
|
|
|
filetime::set_file_mtime(&path, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -m test_dir"
|
|
);
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let mtime_day =
|
|
DateTime::<Local>::from(path.metadata().unwrap().modified().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, mtime_day);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_access_time_of_dir_to_today() {
|
|
Playground::setup("change_dir_atime", |dirs, sandbox| {
|
|
sandbox.mkdir("test_dir");
|
|
let path = dirs.test().join("test_dir");
|
|
|
|
filetime::set_file_atime(&path, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -a test_dir"
|
|
);
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let atime_day =
|
|
DateTime::<Local>::from(path.metadata().unwrap().accessed().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, atime_day);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_modified_and_access_time_of_dir_to_today() {
|
|
Playground::setup("change_dir_times", |dirs, sandbox| {
|
|
sandbox.mkdir("test_dir");
|
|
let path = dirs.test().join("test_dir");
|
|
|
|
filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -a -m test_dir"
|
|
);
|
|
|
|
let metadata = path.metadata().unwrap();
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let mtime_day = DateTime::<Local>::from(metadata.modified().unwrap()).date_naive();
|
|
let atime_day = DateTime::<Local>::from(metadata.accessed().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, mtime_day);
|
|
assert_eq!(today, atime_day);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_dir_three_dots_times() {
|
|
Playground::setup("change_dir_three_dots_times", |dirs, sandbox| {
|
|
sandbox.mkdir("test_dir...");
|
|
let path = dirs.test().join("test_dir...");
|
|
|
|
filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch test_dir..."
|
|
);
|
|
|
|
let metadata = path.metadata().unwrap();
|
|
|
|
// Check only the date since the time may not match exactly
|
|
let today = Local::now().date_naive();
|
|
let mtime_day = DateTime::<Local>::from(metadata.modified().unwrap()).date_naive();
|
|
let atime_day = DateTime::<Local>::from(metadata.accessed().unwrap()).date_naive();
|
|
|
|
assert_eq!(today, mtime_day);
|
|
assert_eq!(today, atime_day);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_dir_times_to_reference_dir() {
|
|
Playground::setup("change_dir_times_to_reference_dir", |dirs, sandbox| {
|
|
sandbox.mkdir("reference_dir");
|
|
sandbox.mkdir("target_dir");
|
|
|
|
let reference = dirs.test().join("reference_dir");
|
|
let target = dirs.test().join("target_dir");
|
|
|
|
// Change the times for reference
|
|
filetime::set_file_times(
|
|
&reference,
|
|
filetime::FileTime::from_unix_time(1337, 0),
|
|
TIME_ONE,
|
|
)
|
|
.unwrap();
|
|
|
|
// target should have today's date since it was just created, but reference should be different
|
|
assert_ne!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_ne!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -r reference_dir target_dir"
|
|
);
|
|
|
|
assert_eq!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_eq!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn change_dir_atime_to_reference() {
|
|
Playground::setup("change_dir_atime_to_reference", |dirs, sandbox| {
|
|
sandbox.mkdir("reference_dir");
|
|
sandbox.mkdir("target_dir");
|
|
|
|
let reference = dirs.test().join("reference_dir");
|
|
let target = dirs.test().join("target_dir");
|
|
|
|
// Change the times for reference
|
|
filetime::set_file_times(
|
|
&reference,
|
|
filetime::FileTime::from_unix_time(1337, 0),
|
|
TIME_ONE,
|
|
)
|
|
.unwrap();
|
|
|
|
// target should have today's date since it was just created, but reference should be different
|
|
assert_ne!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_ne!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
|
|
// Save target's current mtime to make sure it is preserved
|
|
let target_original_mtime = target.metadata().unwrap().modified().unwrap();
|
|
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"touch -ar reference_dir target_dir"
|
|
);
|
|
|
|
assert_eq!(
|
|
reference.metadata().unwrap().accessed().unwrap(),
|
|
target.metadata().unwrap().accessed().unwrap()
|
|
);
|
|
assert_ne!(
|
|
reference.metadata().unwrap().modified().unwrap(),
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
assert_eq!(
|
|
target_original_mtime,
|
|
target.metadata().unwrap().modified().unwrap()
|
|
);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn create_a_file_with_tilde() {
|
|
Playground::setup("touch with tilde", |dirs, _| {
|
|
let actual = nu!(cwd: dirs.test(), "touch '~tilde'");
|
|
assert!(actual.err.is_empty());
|
|
assert!(files_exist_at(vec![Path::new("~tilde")], dirs.test()));
|
|
|
|
// pass variable
|
|
let actual = nu!(cwd: dirs.test(), "let f = '~tilde2'; touch $f");
|
|
assert!(actual.err.is_empty());
|
|
assert!(files_exist_at(vec![Path::new("~tilde2")], dirs.test()));
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn respects_cwd() {
|
|
Playground::setup("touch_respects_cwd", |dirs, _sandbox| {
|
|
nu!(
|
|
cwd: dirs.test(),
|
|
"mkdir 'dir'; cd 'dir'; touch 'i_will_be_created.txt'"
|
|
);
|
|
|
|
let path = dirs.test().join("dir/i_will_be_created.txt");
|
|
assert!(path.exists());
|
|
})
|
|
}
|