aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-07-17 14:46:18 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-07-17 14:47:25 +0300
commit0898e65ca37686a0a06a2980acf8cc40c0e2494e (patch)
treee575f1c87bd9d3bb8dde1198389b8bd9f7b697fc
parentfe6f3ec0868185511f5acefb2729eb879798f052 (diff)
Add --after <ref-file> option for testscript touch builtin
-rw-r--r--build2/test/script/builtin.cxx54
-rw-r--r--doc/testscript.cli9
-rw-r--r--tests/in/testscript4
-rw-r--r--tests/test/script/builtin/touch.test35
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] <src-path> <dst-path>
- // mv [--no-cleanup] <src-path>... <dst-dir>/
+ // mv [--no-cleanup] [-f] <src-path> <dst-path>
+ // mv [--no-cleanup] [-f] <src-path>... <dst-dir>/
//
// 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] <file>...
+ // touch [--no-cleanup] [--after <ref-file>] <file>...
//
// 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<timestamp> 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] <file>...
+touch [--no-cleanup] [--after <ref-file>] <file>...
\
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 <ref-file>}\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 @@ $* <<EOI;
file{test}: in{test}
EOI
cat test >'FOO BAR';
-if ($cxx.target.class != 'windows')
- sleep 1
-end;
cat <'$fox$ $baz$' >=test.in;
+touch --after test test.in;
$* <<EOI;
fox = fox
baz = baz
diff --git a/tests/test/script/builtin/touch.test b/tests/test/script/builtin/touch.test
index 7188a21..04391bd 100644
--- a/tests/test/script/builtin/touch.test
+++ b/tests/test/script/builtin/touch.test
@@ -22,14 +22,14 @@ EOI
: Test that existing file touch doesn't fail.
:
$c <<EOI && $b
-cat <"" >=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 <<EOI && $b
@@ -45,14 +45,14 @@ EOI
:
: Test passing no arguments.
:
-$c <'touch 2>"touch: missing file" == 1' && $b
+$c <'touch --no-cleanup 2>"touch: missing file" != 0' && $b
: empty-path
:
: Test touching an empty path.
:
$c <<EOI && $b
-touch '' 2>"touch: invalid path ''" == 1
+touch '' 2>"touch: invalid path ''" != 0
EOI
: dir-update
@@ -61,5 +61,28 @@ EOI
:
$c <<EOI && $b
mkdir a;
-touch a 2>~"%touch: cannot create/update .+: .+%" == 1
+touch a 2>~'%touch: cannot create/update .+: .+%' != 0
EOI
+
+: after
+:
+{
+ : success
+ :
+ $c <<EOI && $b
+ touch a;
+ touch --after a b
+ EOI
+
+ : no-value
+ :
+ $c <<EOI && $b
+ touch --after 2>'touch: missing --after option value' != 0
+ EOI
+
+ : not-exists
+ :
+ $c <<EOI && $b
+ touch --after a b 2>~"%touch: cannot obtain file '.+a' modification time: .+%" != 0
+ EOI
+}