From 804ff6d25ac70aabcd913fe44d441799867a7dd7 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Mon, 13 Feb 2006 03:52:41 +0000 Subject: Add a NoClean() function. (Steven Johnson) --- doc/design/engine.sgml | 36 +++++++++ doc/design/scons.mod | 1 + doc/man/scons.1 | 76 +++++++++++++++++- doc/scons.mod | 1 + doc/user/MANIFEST | 2 +- doc/user/file-removal.in | 148 +++++++++++++++++++++++++++++++++++ doc/user/file-removal.sgml | 141 +++++++++++++++++++++++++++++++++ doc/user/main.in | 8 +- doc/user/main.sgml | 8 +- doc/user/precious.in | 90 --------------------- doc/user/precious.sgml | 84 -------------------- src/CHANGES.txt | 5 ++ src/engine/SCons/Environment.py | 9 +++ src/engine/SCons/EnvironmentTests.py | 23 ++++++ src/engine/SCons/Node/NodeTests.py | 9 +++ src/engine/SCons/Node/__init__.py | 5 ++ src/engine/SCons/Script/Main.py | 4 +- src/engine/SCons/Script/__init__.py | 1 + src/engine/SCons/Util.py | 18 +++-- src/engine/SCons/UtilTests.py | 6 +- test/option-c.py | 14 +++- 21 files changed, 491 insertions(+), 198 deletions(-) create mode 100644 doc/user/file-removal.in create mode 100644 doc/user/file-removal.sgml delete mode 100644 doc/user/precious.in delete mode 100644 doc/user/precious.sgml diff --git a/doc/design/engine.sgml b/doc/design/engine.sgml index 9452420..df78e3b 100644 --- a/doc/design/engine.sgml +++ b/doc/design/engine.sgml @@ -1385,7 +1385,43 @@ Comments? + +
+ Suppressing cleanup removal of build-targets + + + By default, &SCons; explicitly removes all build-targets + when invoked to perform "cleanup". Files that should not be + removed during "cleanup" can be specified via the + &NoClean; method: + + + + + env.Library(target = 'libfoo.a', source = ['aaa.c', 'bbb.c', 'ccc.c']) + env.NoClean('libfoo.a') + + + + + The NoClean operation has precedence over the Clean operation. + A target that is specified as both Clean and NoClean, will not + be removed during a clean. + + In the following example, target 'foo' will not be removed + during "cleanup": + + + env.Clean(target = 'foo') + env.NoClean('foo') + + + + + +
+
Suppressing build-target removal diff --git a/doc/design/scons.mod b/doc/design/scons.mod index 58a6576..5b246a4 100644 --- a/doc/design/scons.mod +++ b/doc/design/scons.mod @@ -155,6 +155,7 @@ ListOption"> Local"> Module"> +NoClean"> Objects"> Options"> PackageOption"> diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 3c014c6..45d7a5b 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -262,7 +262,14 @@ scons -c build export to remove target files under build and export. Additional files or directories to remove can be specified using the -Clean() function. +.BR Clean() +function. +Conversely, targets that would normally be removed by the +.B -c +invocation +can be prevented from being removed by using the +.BR NoClean () +function. A subset of a hierarchical tree may be built by remaining at the top-level directory (where the @@ -406,7 +413,12 @@ Ignored for compatibility with non-GNU versions of Clean up by removing all target files for which a construction command is specified. Also remove any files or directories associated to the construction command -using the Clean() function. +using the +.BR Clean () +function. +Will not remove any targets specified by the +.BR NoClean () +function. .TP --cache-disable, --no-cache @@ -2088,6 +2100,19 @@ will also accept the return value of any of the construction environment Builder methods. Examples: +The related +.BR NoClean () +function overrides calling +.BR Clean () +for the same target, +and any targets passed to both functions will +.I not +be removed by the +.B -c +option. + +Examples: + .ES Clean('foo', ['bar', 'baz']) Clean('dist', env.Program('hello', 'hello.c')) @@ -2757,6 +2782,53 @@ Returns a list of the target Node or Nodes. '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP +.RI NoClean( target ", ...)" +.TP +.RI env.NoClean( target ", ...)" +Specifies a list of files or directories which should +.I not +be removed whenever the targets (or their dependencies) +are specified with the +.B -c +command line option. +The specified targets may be a list +or an individual target. +Multiple calls to +.BR NoClean () +are legal, +and prevent each specified target +from being removed by calls to the +.B -c +option. + +Multiple files or directories should be specified +either as separate arguments to the +.BR NoClean () +method, or as a list. +.BR NoClean () +will also accept the return value of any of the construction environment +Builder methods. + +Calling +.BR NoClean () +for a target overrides calling +.BR Clean () +for the same target, +and any targets passed to both functions will +.I not +be removed by the +.B -c +option. + +Examples: + +.ES +NoClean('foo.elf') +NoClean(env.Program('hello', 'hello.c')) +.EE + +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP .RI env.ParseConfig( command ", [" function ", " unique ]) Calls the specified .I function diff --git a/doc/scons.mod b/doc/scons.mod index b8b64aa..975f445 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -162,6 +162,7 @@ Mkdir"> Module"> Move"> +NoClean"> Objects"> Options"> PackageOption"> diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST index 3af2c9c..04c293b 100644 --- a/doc/user/MANIFEST +++ b/doc/user/MANIFEST @@ -17,6 +17,7 @@ environments.sgml errors.sgml example.sgml factories.sgml +file-removal.sgml help.sgml hierarchy.sgml install.sgml @@ -27,7 +28,6 @@ main.sgml make.sgml nodes.sgml parseconfig.sgml -precious.sgml preface.sgml python.sgml repositories.sgml diff --git a/doc/user/file-removal.in b/doc/user/file-removal.in new file mode 100644 index 0000000..1d259bf --- /dev/null +++ b/doc/user/file-removal.in @@ -0,0 +1,148 @@ + + + + + There are two occasions when &SCons; will, + by default, remove target files. + The first is when &SCons; determines that + an target file needs to be rebuilt + and removes the existing version of the target + before executing + The second is when &SCons; is invoked with the + -c option to "clean" + a tree of its built targets. + + These behaviours can be suppressed with the + &Precious; and &NoClean; functions, respectively. + + + +
+ Preventing target removal during build: the &Precious; Function + + + + By default, &SCons; removes targets before building them. + Sometimes, however, this is not what you want. + For example, you may want to update a library incrementally, + not by having it deleted and then rebuilt from all + of the constituent object files. + In such cases, you can use the + &Precious; method to prevent + &SCons; from removing the target before it is built: + + + + + + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Precious(lib) + + + int f1() { } + + + int f2() { } + + + int f3() { } + + + + + + Although the output doesn't look any different, + &SCons; does not, in fact, + delete the target library before rebuilding it: + + + + + scons -Q + + + + + &SCons; will, however, still delete files marked as &Precious; + when the -c option is used. + + + +
+ + +
+ Preventing target removal during clean: the &NoClean; Function + + + + By default, &SCons; removes all built targets when invoked + with the -c option to clean a source tree + of built tragets. + Sometimes, however, this is not what you want. + For example, you may want to remove only intermediate generated files + (such as object files), + but leave the final targets + (the libraries) + untouched. + + In such cases, you can use the &NoClean; method to prevent &SCons; + from removing a target during a clean: + + + + + + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.NoClean(lib) + + + int f1() { } + + + int f2() { } + + + int f3() { } + + + + + + Notice that the libfoo.a + is not listed as a removed file: + + + + + scons -Q + scons -c + + +
+ diff --git a/doc/user/file-removal.sgml b/doc/user/file-removal.sgml new file mode 100644 index 0000000..76a2e01 --- /dev/null +++ b/doc/user/file-removal.sgml @@ -0,0 +1,141 @@ + + + + + There are two occasions when &SCons; will, + by default, remove target files. + The first is when &SCons; determines that + an target file needs to be rebuilt + and removes the existing version of the target + before executing + The second is when &SCons; is invoked with the + -c option to "clean" + a tree of its built targets. + + These behaviours can be suppressed with the + &Precious; and &NoClean; functions, respectively. + + + +
+ Preventing target removal during build: the &Precious; Function + + + + By default, &SCons; removes targets before building them. + Sometimes, however, this is not what you want. + For example, you may want to update a library incrementally, + not by having it deleted and then rebuilt from all + of the constituent object files. + In such cases, you can use the + &Precious; method to prevent + &SCons; from removing the target before it is built: + + + + + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Precious(lib) + + + + + Although the output doesn't look any different, + &SCons; does not, in fact, + delete the target library before rebuilding it: + + + + + % scons -Q + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o + + + + + &SCons; will, however, still delete files marked as &Precious; + when the -c option is used. + + + +
+ + +
+ Preventing target removal during clean: the &NoClean; Function + + + + By default, &SCons; removes all built targets when invoked + with the -c option to clean a source tree + of built tragets. + Sometimes, however, this is not what you want. + For example, you may want to remove only intermediate generated files + (such as object files), + but leave the final targets + (the libraries) + untouched. + + In such cases, you can use the &NoClean; method to prevent &SCons; + from removing a target during a clean: + + + + + env = Environment(RANLIBCOM='') + lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.NoClean(lib) + + + + + Notice that the libfoo.a + is not listed as a removed file: + + + + + % scons -Q + cc -o f1.o -c f1.c + cc -o f2.o -c f2.c + cc -o f3.o -c f3.c + ar rc libfoo.a f1.o f2.o f3.o + % scons -c + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Cleaning targets ... + Removed f1.o + Removed f2.o + Removed f3.o + scons: done cleaning targets. + + +
+ diff --git a/doc/user/main.in b/doc/user/main.in index a720915..af3b0ee 100644 --- a/doc/user/main.in +++ b/doc/user/main.in @@ -59,6 +59,7 @@ + @@ -68,7 +69,6 @@ - @@ -190,9 +190,9 @@ &factories; - - Preventing Removal of Targets: the &Precious; Function - &precious; + + Preventing Removal of Targets + &file-removal; diff --git a/doc/user/main.sgml b/doc/user/main.sgml index a720915..af3b0ee 100644 --- a/doc/user/main.sgml +++ b/doc/user/main.sgml @@ -59,6 +59,7 @@ + @@ -68,7 +69,6 @@ - @@ -190,9 +190,9 @@ &factories; - - Preventing Removal of Targets: the &Precious; Function - &precious; + + Preventing Removal of Targets + &file-removal; diff --git a/doc/user/precious.in b/doc/user/precious.in deleted file mode 100644 index f5e000b..0000000 --- a/doc/user/precious.in +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - By default, &SCons; removes targets before building them. - Sometimes, however, this is not what you want. - For example, you may want to update a library incrementally, - not by having it deleted and then rebuilt from all - of the constituent object files. - In such cases, you can use the - &Precious; method to prevent - &SCons; from removing the target before it is built: - - - - - - env = Environment() - lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) - env.Precious(lib) - - - int f1() { } - - - int f2() { } - - - int f3() { } - - - - - - Although the output doesn't look any different, - &SCons; does not, in fact, - delete the target library before rebuilding it: - - - - - scons -Q - - - - - &SCons; will, however, still delete files marked as &Precious; - when the -c option is used. - - diff --git a/doc/user/precious.sgml b/doc/user/precious.sgml deleted file mode 100644 index 6e80c85..0000000 --- a/doc/user/precious.sgml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - By default, &SCons; removes targets before building them. - Sometimes, however, this is not what you want. - For example, you may want to update a library incrementally, - not by having it deleted and then rebuilt from all - of the constituent object files. - In such cases, you can use the - &Precious; method to prevent - &SCons; from removing the target before it is built: - - - - - env = Environment() - lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) - env.Precious(lib) - - - - - Although the output doesn't look any different, - &SCons; does not, in fact, - delete the target library before rebuilding it: - - - - - % scons -Q - cc -c -o f1.o f1.c - cc -c -o f2.o f2.c - cc -c -o f3.o f3.c - ar r libfoo.a f1.o f2.o f3.o - ranlib libfoo.a - - - - - &SCons; will, however, still delete files marked as &Precious; - when the -c option is used. - - diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e2d5d7c..9e6cb16 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -62,6 +62,11 @@ RELEASE 0.97 - XXX - Support $MAKEINDEX, $MAKEINDEXCOM, $MAKEINDEXCOMSTR and $MAKEINDEXFLAGS for generating indices from .idx files. + From Steven Johnson: + + - Add a NoClean() Environment method and function to override removal + of targets during a -c clean, including documentation and tests. + From Steven Knight: - Check for whether files exist on disk by listing the directory diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 92b1e3d..691098d 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1285,6 +1285,15 @@ class Base(SubstitutionEnvironment): """ return apply(self.fs.Dir, (self.subst(name),) + args, kw) + def NoClean(self, *targets): + """Tags a target so that it will not be cleaned by -c""" + tlist = [] + for t in targets: + tlist.extend(self.arg2nodes(t, self.fs.Entry)) + for t in tlist: + t.set_noclean() + return tlist + def Entry(self, name, *args, **kw): """ """ diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 58c8ae8..48b258e 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -2285,6 +2285,29 @@ def generate(env): d = env.Dir('${BAR}_$BAR') assert d == 'Dir(bardir_bardir)', d + def test_NoClean(self): + """Test the NoClean() method""" + env = Environment(FOO='ggg', BAR='hhh') + env.Dir('p_hhhb') + env.File('p_d') + t = env.NoClean('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') + + assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__ + assert t[0].path == 'p_a' + assert t[0].noclean + assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__ + assert t[1].path == 'p_hhhb' + assert t[1].noclean + assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__ + assert t[2].path == 'p_c' + assert t[2].noclean + assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__ + assert t[3].path == 'p_d' + assert t[3].noclean + assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__ + assert t[4].path == 'p_ggg' + assert t[4].noclean + def test_Dump(self): """Test the Dump() method""" diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 4f7b65a..cd546cd 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -704,6 +704,15 @@ class NodeTestCase(unittest.TestCase): node.set_always_build(3) assert node.always_build == 3 + def test_set_noclean(self): + """Test setting a Node's noclean value + """ + node = SCons.Node.Node() + node.set_noclean() + assert node.noclean + node.set_noclean(7) + assert node.noclean == 7 + def test_set_precious(self): """Test setting a Node's precious value """ diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 483e88b..67a72ae 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -197,6 +197,7 @@ class Node: self.env = None self.state = no_state self.precious = None + self.noclean = None self.always_build = None self.found_includes = {} self.includes = None @@ -740,6 +741,10 @@ class Node: """Set the Node's precious value.""" self.precious = precious + def set_noclean(self, noclean = 1): + """Set the Node's noclean value.""" + self.noclean = noclean + def set_always_build(self, always_build = 1): """Set the Node's always_build value.""" self.always_build = always_build diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 8b3058a..5b35e14 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -224,7 +224,7 @@ class CleanTask(SCons.Taskmaster.Task): def show(self): target = self.targets[0] - if target.has_builder() or target.side_effect: + if (target.has_builder() or target.side_effect) and not target.noclean: for t in self.targets: if not t.isdir(): display("Removed " + str(t)) @@ -235,7 +235,7 @@ class CleanTask(SCons.Taskmaster.Task): def remove(self): target = self.targets[0] - if target.has_builder() or target.side_effect: + if (target.has_builder() or target.side_effect) and not target.noclean: for t in self.targets: try: removed = t.remove() diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 97ffdce..ce96867 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -281,6 +281,7 @@ GlobalDefaultEnvironmentFunctions = [ #The Command() method is handled separately, below. 'Depends', 'Dir', + 'NoClean', 'Entry', 'Execute', 'File', diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 37f3c06..d96f56c 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -343,14 +343,15 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): if showtags: if showtags == 2: - print ' E = exists' - print ' R = exists in repository only' - print ' b = implicit builder' - print ' B = explicit builder' - print ' S = side effect' - print ' P = precious' - print ' A = always build' - print ' C = current' + print ' E = exists' + print ' R = exists in repository only' + print ' b = implicit builder' + print ' B = explicit builder' + print ' S = side effect' + print ' P = precious' + print ' A = always build' + print ' C = current' + print ' N = no clean' print '' tags = ['['] @@ -362,6 +363,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): tags.append(' P'[IDX(root.precious)]) tags.append(' A'[IDX(root.always_build)]) tags.append(' C'[IDX(root.current())]) + tags.append(' N'[IDX(root.noclean())]) tags.append(']') else: diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 724c51d..aa93db1 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -74,6 +74,8 @@ class UtilTestCase(unittest.TestCase): return 1 def current(self): return 1 + def noclean(self): + return 1 def tree_case_1(self): """Fixture for the render_tree() and print_tree() tests.""" @@ -98,7 +100,7 @@ class UtilTestCase(unittest.TestCase): """ lines = string.split(expect, '\n')[:-1] - lines = map(lambda l: '[E BSPAC]'+l, lines) + lines = map(lambda l: '[E BSPACN]'+l, lines) withtags = string.join(lines, '\n') + '\n' return foo, expect, withtags @@ -121,7 +123,7 @@ class UtilTestCase(unittest.TestCase): """ lines = string.split(expect, '\n')[:-1] - lines = map(lambda l: '[E BSPAC]'+l, lines) + lines = map(lambda l: '[E BSPACN]'+l, lines) withtags = string.join(lines, '\n') + '\n' return blat_o, expect, withtags diff --git a/test/option-c.py b/test/option-c.py index fbad75c..8814827 100644 --- a/test/option-c.py +++ b/test/option-c.py @@ -51,6 +51,8 @@ env.B(target = 'foo1.out', source = 'foo1.in') env.B(target = 'foo2.out', source = 'foo2.xxx') env.B(target = 'foo2.xxx', source = 'foo2.in') env.B(target = 'foo3.out', source = 'foo3.in') +env.B(target = 'foo4.out', source = 'foo4.in') +env.NoClean('foo4.out') import os if hasattr(os, 'symlink'): def symlink1(env, target, source): @@ -73,12 +75,15 @@ test.write('foo2.in', "foo2.in\n") test.write('foo3.in', "foo3.in\n") -test.run(arguments = 'foo1.out foo2.out foo3.out') +test.write('foo4.in', "foo4.in\n") + +test.run(arguments = 'foo1.out foo2.out foo3.out foo4.out') test.must_match(test.workpath('foo1.out'), "foo1.in\n") test.must_match(test.workpath('foo2.xxx'), "foo2.in\n") test.must_match(test.workpath('foo2.out'), "foo2.in\n") test.must_match(test.workpath('foo3.out'), "foo3.in\n") +test.must_match(test.workpath('foo4.out'), "foo4.in\n") test.run(arguments = '-c foo1.out', stdout = test.wrap_stdout("Removed foo1.out\n", cleaning=1)) @@ -87,6 +92,7 @@ test.must_not_exist(test.workpath('foo1.out')) test.must_exist(test.workpath('foo2.xxx')) test.must_exist(test.workpath('foo2.out')) test.must_exist(test.workpath('foo3.out')) +test.must_exist(test.workpath('foo4.out')) test.run(arguments = '--clean foo2.out foo2.xxx', stdout = test.wrap_stdout("Removed foo2.xxx\nRemoved foo2.out\n", @@ -96,6 +102,7 @@ test.must_not_exist(test.workpath('foo1.out')) test.must_not_exist(test.workpath('foo2.xxx')) test.must_not_exist(test.workpath('foo2.out')) test.must_exist(test.workpath('foo3.out')) +test.must_exist(test.workpath('foo4.out')) test.run(arguments = '--remove foo3.out', stdout = test.wrap_stdout("Removed foo3.out\n", cleaning=1)) @@ -104,6 +111,7 @@ test.must_not_exist(test.workpath('foo1.out')) test.must_not_exist(test.workpath('foo2.xxx')) test.must_not_exist(test.workpath('foo2.out')) test.must_not_exist(test.workpath('foo3.out')) +test.must_exist(test.workpath('foo4.out')) test.run(arguments = '.') @@ -112,6 +120,7 @@ test.must_match(test.workpath('foo2.xxx'), "foo2.in\n") test.must_match(test.workpath('foo2.out'), "foo2.in\n") test.must_match(test.workpath('foo3.out'), "foo3.in\n") test.must_match(test.workpath('foo3.out'), "foo3.in\n") +test.must_match(test.workpath('foo4.out'), "foo4.in\n") test.must_exist(test.workpath('touch1.out')) test.must_exist(test.workpath('touch2.out')) @@ -126,6 +135,7 @@ test.must_match(test.workpath('foo1.out'), "foo1.in\n") test.must_not_exist(test.workpath('foo2.xxx')) test.must_match(test.workpath('foo2.out'), "foo2.in\n") test.must_match(test.workpath('foo3.out'), "foo3.in\n") +test.must_match(test.workpath('foo4.out'), "foo4.in\n") test.must_exist(test.workpath('touch1.out')) test.must_exist(test.workpath('touch2.out')) @@ -134,6 +144,7 @@ test.run(arguments = '-c .') test.must_not_exist(test.workpath('foo1.out')) test.must_not_exist(test.workpath('foo2.out')) test.must_not_exist(test.workpath('foo3.out')) +test.must_exist(test.workpath('foo4.out')) test.must_not_exist(test.workpath('touch1.out')) test.must_not_exist(test.workpath('touch2.out')) @@ -162,6 +173,7 @@ test.must_match(test.workpath('foo1.out'), "foo1.in\n") test.must_match(test.workpath('foo2.xxx'), "foo2.in\n") test.must_match(test.workpath('foo2.out'), "foo2.in\n") test.must_match(test.workpath('foo3.out'), "foo3.in\n") +test.must_match(test.workpath('foo4.out'), "foo4.in\n") test.must_exist(test.workpath('touch1.out')) test.must_exist(test.workpath('touch2.out')) -- cgit v0.12