From: stevenknight Date: Mon, 8 Jul 2002 22:40:59 +0000 (+0000) Subject: Add a TAR Builder. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1c92facef53fb9972c6499947d54e73d2f10520e;p=scons.git Add a TAR Builder. git-svn-id: http://scons.tigris.org/svn/scons/trunk@405 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/doc/man/scons.1 b/doc/man/scons.1 index f606adb7..e6f6d0c3 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -718,6 +718,7 @@ lex nasm (if the GNU assembler is not available) pdflatex pdftex +tar tex yacc .EE @@ -739,6 +740,7 @@ masm nasm pdflatex pdftex +tar tex yacc .EE @@ -1824,6 +1826,15 @@ The linker for programs that use shared libraries. .IP SHLINKFLAGS General options passed to the linker for programs using shared libraries. +.IP TAR +The tar archiver. + +.IP TARCOM +The command line used to call the tar archiver. + +.IP TARFLAGS +General options passed to the tar archiver. + .IP TEX The TeX formatter and typesetter. diff --git a/rpm/scons.spec b/rpm/scons.spec index 6dbec214..99960501 100644 --- a/rpm/scons.spec +++ b/rpm/scons.spec @@ -132,6 +132,8 @@ rm -rf $RPM_BUILD_ROOT /usr/lib/scons/SCons/Tool/pdflatex.pyc /usr/lib/scons/SCons/Tool/pdftex.py /usr/lib/scons/SCons/Tool/pdftex.pyc +/usr/lib/scons/SCons/Tool/tar.py +/usr/lib/scons/SCons/Tool/tar.pyc /usr/lib/scons/SCons/Tool/tex.py /usr/lib/scons/SCons/Tool/tex.pyc /usr/lib/scons/SCons/Tool/yacc.py diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6779ddd1..69e70637 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -75,6 +75,8 @@ RELEASE 0.08 - which case the target(s) are deduced from the source file(s) and the Builder's specified suffix. + - Add a tar archive builder. + From Jeff Petkau: - Fix --implicit-cache if the scanner returns an empty list. diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 9a057876..0f81470b 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -41,6 +41,7 @@ SCons/Tool/msvc.py SCons/Tool/nasm.py SCons/Tool/pdflatex.py SCons/Tool/pdftex.py +SCons/Tool/tar.py SCons/Tool/tex.py SCons/Tool/yacc.py SCons/Util.py diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 7c303339..a0479031 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -355,6 +355,22 @@ class Entry(SCons.Node.Node): else: return self.srcpath + def get_contents(self): + """Fetch the contents of the entry. + + Since this should return the real contents from the file + system, we check to see into what sort of subclass we should + morph this Entry.""" + if os.path.isfile(self.abspath): + self.__class__ = File + self._morph() + return File.get_contents(self) + if os.path.isdir(self.abspath): + self.__class__ = Dir + self._morph() + return Dir.get_contents(self) + raise AttributeError + def exists(self): return os.path.exists(str(self)) @@ -477,6 +493,10 @@ class Dir(Entry): """A directory has no signature.""" pass + def get_contents(self): + """Return a fixed "contents" value of a directory.""" + return '' + def current(self): """If all of our children were up-to-date, then this directory was up-to-date, too.""" diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index ee825637..6151f2d3 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -479,7 +479,27 @@ class FSTestCase(unittest.TestCase): #XXX test root() - #XXX test get_contents() + # test Entry.get_contents() + e = fs.Entry('does_not_exist') + exc_caught = 0 + try: + e.get_contents() + except AttributeError: + exc_caught = 1 + assert exc_caught, "Should have caught an AttributError" + + test.write("file", "file\n") + e = fs.Entry('file') + c = e.get_contents() + assert c == "file\n", c + assert e.__class__ == SCons.Node.FS.File + test.unlink("file") + + test.subdir("dir") + e = fs.Entry('dir') + c = e.get_contents() + assert c == "", c + assert e.__class__ == SCons.Node.FS.Dir #XXX test get_timestamp() diff --git a/src/engine/SCons/Platform/cygwin.py b/src/engine/SCons/Platform/cygwin.py index 8858dd1b..b5a73f6f 100644 --- a/src/engine/SCons/Platform/cygwin.py +++ b/src/engine/SCons/Platform/cygwin.py @@ -44,7 +44,7 @@ def tool_list(): return ['ar', 'dvipdf', 'dvips', 'g++', 'g77', 'gcc', 'gnulink', 'latex', 'lex', - 'pdflatex', 'pdftex', 'tex', 'yacc', + 'pdflatex', 'pdftex', 'tar', 'tex', 'yacc', assembler] def generate(env): diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index 79adebd5..a45dce1d 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -44,7 +44,7 @@ def tool_list(): return ['ar', 'dvipdf', 'dvips', 'g++', 'g77', 'gcc', 'gnulink', 'latex', 'lex', - 'pdflatex', 'pdftex', 'tex', 'yacc', + 'pdflatex', 'pdftex', 'tar', 'tex', 'yacc', assembler] def generate(env): diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 957aead8..121fed66 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -43,7 +43,7 @@ def tool_list(): assembler = 'masm' return ['dvipdf', 'dvips', 'g77', 'latex', 'lex', 'lib', 'mslink', 'msvc', - 'pdflatex', 'pdftex', 'tex', 'yacc', + 'pdflatex', 'pdftex', 'tar', 'tex', 'yacc', assembler] def generate(env): diff --git a/src/engine/SCons/Tool/tar.py b/src/engine/SCons/Tool/tar.py new file mode 100644 index 00000000..fff9dff0 --- /dev/null +++ b/src/engine/SCons/Tool/tar.py @@ -0,0 +1,55 @@ +"""SCons.Tool.tar + +Tool-specific initialization for tar. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# Copyright (c) 2001, 2002 Steven Knight +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Builder +import SCons.Node.FS + +TarBuilder = SCons.Builder.Builder(action = '$TARCOM', + source_factory = SCons.Node.FS.default_fs.Entry, + suffix = '$TARSUFFIX', + multi = 1) + +def generate(env, platform): + """Add Builders and construction variables for tar to an Environment.""" + try: + bld = env['BUILDERS']['Tar'] + except KeyError: + bld = TarBuilder + env['BUILDERS']['Tar'] = bld + + env['TAR'] = 'tar' + env['TARFLAGS'] = '-c' + env['TARCOM'] = '$TAR $TARFLAGS -f $TARGET $SOURCES' + env['TARSUFFIX'] = '.tar' diff --git a/test/TAR.py b/test/TAR.py new file mode 100644 index 00000000..0327ca99 --- /dev/null +++ b/test/TAR.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002 Steven Knight +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import os.path +import string +import sys +import TestSCons + +python = sys.executable + +test = TestSCons.TestSCons() + +test.subdir('sub1') + +test.write('mytar.py', r""" +import getopt +import os +import os.path +import sys +opts, args = getopt.getopt(sys.argv[1:], 'cf:') +for opt, arg in opts: + if opt == '-f': out = arg +def process(outfile, name): + if os.path.isdir(name): + for entry in os.listdir(name): + process(outfile, os.path.join(name, entry)) + else: + outfile.write(open(name, 'rb').read()) +outfile = open(out, 'wb') +for infile in args: + process(outfile, infile) +outfile.close() +sys.exit(0) +""") + +test.write('SConstruct', """ +env = Environment(TAR = r'%s mytar.py') +env.Tar(target = 'aaa.tar', source = ['file1', 'file2']) +env.Tar(target = 'aaa.tar', source = 'file3') +env.Tar(target = 'bbb', source = 'sub1') +env.Tar(target = 'bbb', source = 'file4') +""" % python) + +test.write('file1', "file1\n") +test.write('file2', "file2\n") +test.write('file3', "file3\n") +test.write('file4', "file4\n") + +test.write(['sub1', 'file5'], "sub1/file5\n") +test.write(['sub1', 'file6'], "sub1/file6\n") + +test.run(arguments = 'aaa.tar', stderr = None) + +test.fail_test(test.read('aaa.tar') != "file1\nfile2\nfile3\n") + +test.run(arguments = 'bbb.tar', stderr = None) + +test.fail_test(test.read('bbb.tar') != "sub1/file5\nsub1/file6\nfile4\n") + + + +tar = test.where_is('tar') + +if tar: + + test.write("wrapper.py", """import os +import string +import sys +open('%s', 'wb').write("wrapper.py\\n") +os.system(string.join(sys.argv[1:], " ")) +""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\')) + + test.write('SConstruct', """ +foo = Environment() +tar = foo.Dictionary('TAR') +bar = Environment(TAR = r'%s wrapper.py ' + tar) +foo.Tar(target = 'foo.tar', source = ['file10', 'file11']) +foo.Tar(target = 'foo.tar', source = 'file12') +bar.Tar(target = 'bar.tar', source = ['file13', 'file14']) +bar.Tar(target = 'bar.tar', source = 'file15') +""" % python) + + test.write('file10', "file10\n") + test.write('file11', "file11\n") + test.write('file12', "file12\n") + test.write('file13', "file13\n") + test.write('file14', "file14\n") + test.write('file15', "file15\n") + + test.run(arguments = 'foo.tar', stderr = None) + + test.fail_test(os.path.exists(test.workpath('wrapper.out'))) + + test.fail_test(not os.path.exists(test.workpath('foo.tar'))) + + test.run(arguments = 'bar.tar', stderr = None) + + test.fail_test(not os.path.exists(test.workpath('wrapper.out'))) + + test.fail_test(not os.path.exists(test.workpath('bar.tar'))) + + test.run(program = tar, arguments = "-t -f foo.tar") + test.fail_test(test.stdout() != "file10\nfile11\nfile12\n") + + test.run(program = tar, arguments = "-t -f bar.tar") + test.fail_test(test.stdout() != "file13\nfile14\nfile15\n") + +test.pass_test() diff --git a/test/TARFLAGS.py b/test/TARFLAGS.py new file mode 100644 index 00000000..4701f35a --- /dev/null +++ b/test/TARFLAGS.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002 Steven Knight +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import os.path +import string +import sys +import TestSCons + +python = sys.executable + +test = TestSCons.TestSCons() + +test.subdir('sub1') + +test.write('mytar.py', """ +import getopt +import os +import os.path +import string +import sys +cmd_opts, args = getopt.getopt(sys.argv[1:], 'cf:x', []) +opt_string = '' +for opt, arg in cmd_opts: + if opt == '-f': out = arg + else: opt_string = opt_string + ' ' + opt +def process(outfile, name): + if os.path.isdir(name): + for entry in os.listdir(name): + process(outfile, os.path.join(name, entry)) + else: + outfile.write(open(name, 'rb').read()) +outfile = open(out, 'wb') +outfile.write('options: %s\\n' % opt_string) +for infile in args: + process(outfile, infile) +outfile.close() +sys.exit(0) +""") + +test.write('SConstruct', """ +env = Environment(TAR = r'%s mytar.py', TARFLAGS = '-x') +env.Tar(target = 'aaa.tar', source = ['file1', 'file2']) +env.Tar(target = 'aaa.tar', source = 'file3') +env.Tar(target = 'bbb', source = 'sub1') +env.Tar(target = 'bbb', source = 'file4') +""" % python) + +test.write('file1', "file1\n") +test.write('file2', "file2\n") +test.write('file3', "file3\n") +test.write('file4', "file4\n") + +test.write(['sub1', 'file5'], "sub1/file5\n") +test.write(['sub1', 'file6'], "sub1/file6\n") + +test.run(arguments = 'aaa.tar', stderr = None) + +test.fail_test(test.read('aaa.tar') != "options: -x\nfile1\nfile2\nfile3\n") + +test.run(arguments = 'bbb.tar', stderr = None) + +test.fail_test(test.read('bbb.tar') != "options: -x\nsub1/file5\nsub1/file6\nfile4\n") + + + +tar = test.where_is('tar') + +if tar: + + test.write("wrapper.py", """import os +import string +import sys +open('%s', 'wb').write("wrapper.py\\n") +os.system(string.join(sys.argv[1:], " ")) +""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\')) + + test.write('SConstruct', """ +foo = Environment() +tar = foo['TAR'] +bar = Environment(TAR = '', TARFLAGS = '%s wrapper.py ' + tar + ' -c -b 1') +foo.Tar(target = 'foo.tar', source = ['file10', 'file11']) +foo.Tar(target = 'foo.tar', source = 'file12') +bar.Tar(target = 'bar.tar', source = ['file13', 'file14']) +bar.Tar(target = 'bar.tar', source = 'file15') +""" % python) + + test.write('file10', "file10\n") + test.write('file11', "file11\n") + test.write('file12', "file12\n") + test.write('file13', "file13\n") + test.write('file14', "file14\n") + test.write('file15', "file15\n") + + test.run(arguments = 'foo.tar', stderr = None) + + test.fail_test(os.path.exists(test.workpath('wrapper.out'))) + + test.fail_test(not os.path.exists(test.workpath('foo.tar'))) + + test.run(arguments = 'bar.tar', stderr = None) + + test.fail_test(not os.path.exists(test.workpath('wrapper.out'))) + + test.fail_test(not os.path.exists(test.workpath('bar.tar'))) + + test.run(program = tar, arguments = "-t -f foo.tar") + test.fail_test(test.stdout() != "file10\nfile11\nfile12\n") + + test.run(program = tar, arguments = "-t -f bar.tar", stderr = None) + test.fail_test(test.stdout() != "file13\nfile14\nfile15\n") + +test.pass_test()