diff --git a/doc/mkdwarfs.md b/doc/mkdwarfs.md index bb07f581..d610a3b5 100644 --- a/doc/mkdwarfs.md +++ b/doc/mkdwarfs.md @@ -255,10 +255,14 @@ Most other options are concerned with compression tuning: size of the file system. If the input only has a single group already, setting this won't make any difference. -- `--set-time=`*time*|`now`: +- `--set-time=now`|*iso-8601-string*|*unix-timestamp*: Set the time stamps for all entities to this value. This can significantly - reduce the size of the file system. You can pass either a unix time stamp - or `now`. + reduce the size of the file system. You can pass the string `now` for the + current time, an ISO 8601 string, or a unix timestamp (seconds since epoch). + The ISO 8601 string supports a space character instead of the `T` between + date and time and supports dashes as separators. Seconds or the full time + part may be omitted as long as this doesn't turn the whole string into a + single number (i.e. `2008-03-17` is supported, but `20080317` is not). - `--keep-all-times`: As of release 0.3.0, by default, `mkdwarfs` will only save the contents of diff --git a/src/mkdwarfs_main.cpp b/src/mkdwarfs_main.cpp index cd0afdf7..b61707e7 100644 --- a/src/mkdwarfs_main.cpp +++ b/src/mkdwarfs_main.cpp @@ -934,9 +934,15 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) { } else if (auto val = folly::tryTo(timestamp)) { options.timestamp = *val; } else { - iol.err << "error: argument for option '--set-time' must be numeric or " - "`now`\n"; - return 1; + try { + auto tp = parse_time_point(timestamp); + options.timestamp = std::chrono::duration_cast( + tp.time_since_epoch()) + .count(); + } catch (std::exception const& e) { + iol.err << "error: " << e.what() << "\n"; + return 1; + } } } diff --git a/test/tool_main_test.cpp b/test/tool_main_test.cpp index 8facc66e..5dca0e5e 100644 --- a/test/tool_main_test.cpp +++ b/test/tool_main_test.cpp @@ -111,6 +111,10 @@ class mkdwarfs_tester { return mkdwarfs_main(args, iol.get()); } + int run(std::initializer_list args) { + return run(std::vector(args)); + } + int run(std::string args) { return run(test::parse_args(args)); } filesystem_v2 fs_from_data(std::string data) { @@ -126,6 +130,9 @@ class mkdwarfs_tester { return fs_from_data(std::move(fsimage.value())); } + std::string out() const { return iol.out(); } + std::string err() const { return iol.err(); } + std::shared_ptr fa; std::shared_ptr os; test::test_iolayer iol; @@ -471,8 +478,8 @@ TEST(mkdwarfs_test, set_time_now) { auto t1 = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - EXPECT_EQ(reg.size(), 11); - EXPECT_EQ(opt.size(), 1); + ASSERT_EQ(reg.size(), 11); + ASSERT_EQ(opt.size(), 1); EXPECT_GE(*opt.begin(), t0); EXPECT_LE(*opt.begin(), t1); @@ -488,7 +495,29 @@ TEST(mkdwarfs_test, set_time_epoch) { auto opt = get_all_fs_times(*optfs); EXPECT_EQ(reg.size(), 11); - EXPECT_EQ(opt.size(), 1); + ASSERT_EQ(opt.size(), 1); EXPECT_EQ(*opt.begin(), 100000001); } + +TEST(mkdwarfs_test, set_time_epoch_string) { + using namespace std::chrono_literals; + using std::chrono::sys_days; + + auto optfs = build_with_args({"--set-time", "2020-01-01 01:02"}); + ASSERT_TRUE(optfs); + auto opt = get_all_fs_times(*optfs); + + ASSERT_EQ(opt.size(), 1); + + EXPECT_EQ(*opt.begin(), + std::chrono::duration_cast( + (sys_days{2020y / 1 / 1} + 1h + 2min).time_since_epoch()) + .count()); +} + +TEST(mkdwarfs_test, set_time_error) { + auto t = mkdwarfs_tester::create_empty(); + EXPECT_NE(0, t.run({"-i", "/", "-o", "-", "--set-time=InVaLiD"})); + EXPECT_THAT(t.err(), ::testing::HasSubstr("cannot parse time point")); +}