mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-21 05:17:08 +08:00
builtin test: Implement -ot, -nt, -ef
These are non-POSIX extensions other test(1) utilities implement, which compares the modification time of two files as proposed for fish in #3589: testing if one file is newer than another file. -ef is a common extension to test(1) which checks if two paths refer to the same file, by comparing the dev and inode numbers.
This commit is contained in:
parent
7bdc712615
commit
8f91ee7f6b
@ -65,6 +65,10 @@ enum token_t {
|
||||
test_string_equal, // "=", true if strings are identical
|
||||
test_string_not_equal, // "!=", true if strings are not identical
|
||||
|
||||
test_file_newer, // f1 -nt f2, true if f1 exists and is newer than f2, or there is no f2
|
||||
test_file_older, // f1 -ot f2, true if f2 exists and f1 does not, or f1 is older than f2
|
||||
test_file_same, // f1 -ef f2, true if f1 and f2 exist and refer to same file
|
||||
|
||||
test_number_equal, // "-eq", true if numbers are equal
|
||||
test_number_not_equal, // "-ne", true if numbers are not equal
|
||||
test_number_greater, // "-gt", true if first number is larger than second
|
||||
@ -152,6 +156,9 @@ static const token_info_t *token_for_string(const wcstring &str) {
|
||||
{L"-z", {test_string_z, UNARY_PRIMARY}},
|
||||
{L"=", {test_string_equal, BINARY_PRIMARY}},
|
||||
{L"!=", {test_string_not_equal, BINARY_PRIMARY}},
|
||||
{L"-nt", {test_file_newer, BINARY_PRIMARY}},
|
||||
{L"-ot", {test_file_older, BINARY_PRIMARY}},
|
||||
{L"-ef", {test_file_same, BINARY_PRIMARY}},
|
||||
{L"-eq", {test_number_equal, BINARY_PRIMARY}},
|
||||
{L"-ne", {test_number_not_equal, BINARY_PRIMARY}},
|
||||
{L"-gt", {test_number_greater, BINARY_PRIMARY}},
|
||||
@ -742,6 +749,15 @@ static bool binary_primary_evaluate(test_expressions::token_t token, const wcstr
|
||||
case test_string_not_equal: {
|
||||
return left != right;
|
||||
}
|
||||
case test_file_newer: {
|
||||
return file_id_for_path(right).older_than(file_id_for_path(left));
|
||||
}
|
||||
case test_file_older: {
|
||||
return file_id_for_path(left).older_than(file_id_for_path(right));
|
||||
}
|
||||
case test_file_same: {
|
||||
return file_id_for_path(left) == file_id_for_path(right);
|
||||
}
|
||||
case test_number_equal: {
|
||||
return parse_number(left, &ln, errors) && parse_number(right, &rn, errors) &&
|
||||
ln.compare(rn) == 0;
|
||||
|
@ -868,6 +868,22 @@ static int compare(T a, T b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \return true if \param rhs has higher mtime seconds than this file_id_t.
|
||||
/// If identical, nanoseconds are compared.
|
||||
bool file_id_t::older_than(const file_id_t &rhs) const {
|
||||
int ret = compare(mod_seconds, rhs.mod_seconds);
|
||||
if (!ret) ret = compare(mod_nanoseconds, rhs.mod_nanoseconds);
|
||||
switch (ret) {
|
||||
case -1:
|
||||
return true;
|
||||
case 1:
|
||||
case 0:
|
||||
return false;
|
||||
default:
|
||||
DIE("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
int file_id_t::compare_file_id(const file_id_t &rhs) const {
|
||||
// Compare each field, stopping when we get to a non-equal field.
|
||||
int ret = 0;
|
||||
|
11
src/wutil.h
11
src/wutil.h
@ -145,9 +145,14 @@ struct file_id_t {
|
||||
dev_t device{static_cast<dev_t>(-1LL)};
|
||||
ino_t inode{static_cast<ino_t>(-1LL)};
|
||||
uint64_t size{static_cast<uint64_t>(-1LL)};
|
||||
time_t change_seconds{-1};
|
||||
/* some platforms handle negative time_t
|
||||
values to represent WW1-era dates, initialize ancient
|
||||
for the sake of comparisons.
|
||||
tv_nsec's meaningful values are REALLY [0, 999999999]
|
||||
this nanosecond component we'll initialize at 0. */
|
||||
time_t change_seconds{std::numeric_limits<time_t>::min()};
|
||||
long change_nanoseconds{-1};
|
||||
time_t mod_seconds{-1};
|
||||
time_t mod_seconds{std::numeric_limits<time_t>::min()};
|
||||
long mod_nanoseconds{-1};
|
||||
|
||||
constexpr file_id_t() = default;
|
||||
@ -159,7 +164,7 @@ struct file_id_t {
|
||||
bool operator<(const file_id_t &rhs) const;
|
||||
|
||||
static file_id_t from_stat(const struct stat &buf);
|
||||
|
||||
bool older_than(const file_id_t &rhs) const;
|
||||
wcstring dump() const;
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user