From 0898e65ca37686a0a06a2980acf8cc40c0e2494e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 17 Jul 2018 14:46:18 +0300 Subject: Add --after option for testscript touch builtin --- build2/test/script/builtin.cxx | 54 +++++++++++++++++++++++++++++------- doc/testscript.cli | 9 +++++- tests/in/testscript | 4 +-- tests/test/script/builtin/touch.test | 35 +++++++++++++++++++---- 4 files changed, 82 insertions(+), 20 deletions(-) diff --git a/build2/test/script/builtin.cxx b/build2/test/script/builtin.cxx index d0b8b38..4ab1ec3 100644 --- a/build2/test/script/builtin.cxx +++ b/build2/test/script/builtin.cxx @@ -909,8 +909,8 @@ namespace build2 return 1; } - // mv [--no-cleanup] - // mv [--no-cleanup] ... / + // mv [--no-cleanup] [-f] + // mv [--no-cleanup] [-f] ... / // // Note: can be executed synchronously. // @@ -1413,7 +1413,7 @@ namespace build2 else if (o == "-e") { // Only a single script is supported. - // + // if (subst) error () << "multiple scripts"; @@ -1490,15 +1490,15 @@ namespace build2 // path p; if (i != e) - { - if (*i != "-") + { + if (*i != "-") p = parse_path (*i, sp.wd_path); ++i; - } + } if (i != e) - error () << "unexpected argument"; + error () << "unexpected argument"; // If we edit file in place make sure that the file path is specified // and obtain a temporary file path. We will be writing to the @@ -1702,7 +1702,7 @@ namespace build2 return 2; } - // touch [--no-cleanup] ... + // touch [--no-cleanup] [--after ] ... // // Note that POSIX doesn't specify the behavior for touching an entry // other than file. @@ -1732,8 +1732,25 @@ namespace build2 in.close (); out.close (); - if (args.empty ()) - error () << "missing file"; + auto mtime = [&error] (const path& p) -> timestamp + { + try + { + timestamp t (file_mtime (p)); + + if (t == timestamp_nonexistent) + throw_generic_error (ENOENT); + + return t; + } + catch (const system_error& e) + { + error () << "cannot obtain file '" << p + << "' modification time: " << e; + } + assert (false); // Can't be here. + return timestamp (); + }; auto i (args.begin ()); auto e (args.end ()); @@ -1741,12 +1758,20 @@ namespace build2 // Process options. // bool cleanup (true); + optional after; for (; i != e; ++i) { const string& o (*i); if (o == "--no-cleanup") cleanup = false; + else if (o == "--after") + { + if (++i == e) + error () << "missing --after option value"; + + after = mtime (parse_path (*i, sp.wd_path)); + } else { if (o == "--") @@ -1756,6 +1781,9 @@ namespace build2 } } + if (i == e) + error () << "missing file"; + // Create files. // for (; i != e; ++i) @@ -1769,6 +1797,12 @@ namespace build2 // if (touch_file (p) && cleanup) sp.clean ({cleanup_type::always, p}, true); + + if (after) + { + while (mtime (p) <= *after) + touch_file (p, false /* create */); + } } catch (const system_error& e) { diff --git a/doc/testscript.cli b/doc/testscript.cli index ad5557d..b7e89f1 100644 --- a/doc/testscript.cli +++ b/doc/testscript.cli @@ -2681,13 +2681,20 @@ Note that tests dereference symbolic links. \h#builtins-touch|\c{touch}| \ -touch [--no-cleanup] ... +touch [--no-cleanup] [--after ] ... \ Change file access and modification times to the current time. Create files that do not exist. Fail if a filesystem entry other than the file exists for the specified name. +\dl| + +\li|\n\c{--after }\n + + Keep touching the file until its modification time becomes after that of the + specified reference file.|| + Unless the \c{--no-cleanup} option is specified, newly created files that are inside the script working directory are automatically registered for cleanup. diff --git a/tests/in/testscript b/tests/in/testscript index fe299d7..3e06137 100644 --- a/tests/in/testscript +++ b/tests/in/testscript @@ -62,10 +62,8 @@ $* <'FOO BAR'; -if ($cxx.target.class != 'windows') - sleep 1 -end; cat <'$fox$ $baz$' >=test.in; +touch --after test test.in; $* <=a; +cat <'' >=a; touch a EOI : no-cleanup : -: Test that touches an existing file doesn't register cleanup. If it does then -: the file would be removed while leaving the embedded scope, and so the +: Test that touching an existing file does not register cleanup. If it does +: then the file would be removed while leaving the embedded scope, and so the : cleanup registered by the first touch would fail. : $c <"touch: missing file" == 1' && $b +$c <'touch --no-cleanup 2>"touch: missing file" != 0' && $b : empty-path : : Test touching an empty path. : $c <"touch: invalid path ''" == 1 +touch '' 2>"touch: invalid path ''" != 0 EOI : dir-update @@ -61,5 +61,28 @@ EOI : $c <~"%touch: cannot create/update .+: .+%" == 1 +touch a 2>~'%touch: cannot create/update .+: .+%' != 0 EOI + +: after +: +{ + : success + : + $c <'touch: missing --after option value' != 0 + EOI + + : not-exists + : + $c <~"%touch: cannot obtain file '.+a' modification time: .+%" != 0 + EOI +} -- cgit v1.1