2fa3921ef5682dff0e516880bd7f2f787f202d4c
[scons.git] / test / BitKeeper / BitKeeper.py
1 #!/usr/bin/env python
2 #
3 # __COPYRIGHT__
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #
24
25 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26
27 """
28 Test fetching source files from BitKeeper.
29 """
30
31 import os
32
33 import TestSCons
34
35 test = TestSCons.TestSCons()
36
37 bk = test.where_is('bk')
38 if not bk:
39     test.skip_test("Could not find 'bk'; skipping test(s).\n")
40
41 try:
42     login = os.getlogin()
43 except (AttributeError, OSError):
44     try:
45         login = os.environ['USER']
46     except KeyError:
47         login = 'USER'
48
49 host = os.uname()[1]
50
51 email = "%s@%s" % (login, host)
52
53 test.subdir('BK', 'import', ['import', 'sub'])
54
55 # Test using BitKeeper to fetch from SCCS/s.file files.
56 sccs = test.where_is('sccs')
57 if not sccs:
58     print "Could not find SCCS, skipping sub-test of BitKeeper using SCCS files."
59 else:
60     test.subdir('work1',
61                 ['work1', 'SCCS'],
62                 ['work1', 'sub'],
63                 ['work1', 'sub', 'SCCS'])
64     
65     for file in ['aaa.in', 'bbb.in', 'ccc.in']:
66         test.write(['work1', file], "work1/%s\n" % file)
67         args = "create %s" % file
68         test.run(chdir = 'work1', program = sccs, arguments = args, stderr = None)
69         test.unlink(['work1', file])
70         test.unlink(['work1', ','+file])
71     
72     test.write(['work1', 'sub', 'SConscript'], """\
73 Import("env")
74 env.Cat('ddd.out', 'ddd.in')
75 env.Cat('eee.out', 'eee.in')
76 env.Cat('fff.out', 'fff.in')
77 env.Cat('all', ['ddd.out', 'eee.out', 'fff.out'])
78 """)
79     args = "create SConscript"
80     test.run(chdir = 'work1/sub', program = sccs, arguments = args, stderr = None)
81     test.unlink(['work1', 'sub', 'SConscript'])
82     test.unlink(['work1', 'sub', ',SConscript'])
83     
84     for file in ['ddd.in', 'eee.in', 'fff.in']:
85         test.write(['work1', 'sub', file], "work1/sub/%s\n" % file)
86         args = "create %s" % file
87         test.run(chdir = 'work1/sub', program = sccs, arguments = args, stderr = None)
88         test.unlink(['work1', 'sub', file])
89         test.unlink(['work1', 'sub', ','+file])
90
91     test.write(['work1', 'SConstruct'], """
92 def cat(env, source, target):
93     target = str(target[0])
94     source = map(str, source)
95     f = open(target, "wb")
96     for src in source:
97         f.write(open(src, "rb").read())
98     f.close()
99 env = Environment(BUILDERS={'Cat':Builder(action=cat)},
100                   BITKEEPERGETFLAGS='-e')
101 env.Cat('aaa.out', 'aaa.in')
102 env.Cat('bbb.out', 'bbb.in')
103 env.Cat('ccc.out', 'ccc.in')
104 env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out'])
105 env.SourceCode('.', env.BitKeeper())
106 SConscript('sub/SConscript', "env")
107 """)
108
109     test.write(['work1', 'bbb.in'], "checked-out work1/bbb.in\n")
110
111     test.write(['work1', 'sub', 'eee.in'], "checked-out work1/sub/eee.in\n")
112
113     test.run(chdir = 'work1',
114              arguments = '.',
115              stdout = test.wrap_stdout(read_str = """\
116 bk get -e sub/SConscript
117 """,
118                                        build_str = """\
119 bk get -e aaa.in
120 cat(["aaa.out"], ["aaa.in"])
121 cat(["bbb.out"], ["bbb.in"])
122 bk get -e ccc.in
123 cat(["ccc.out"], ["ccc.in"])
124 cat(["all"], ["aaa.out", "bbb.out", "ccc.out"])
125 bk get -e sub/ddd.in
126 cat(["sub/ddd.out"], ["sub/ddd.in"])
127 cat(["sub/eee.out"], ["sub/eee.in"])
128 bk get -e sub/fff.in
129 cat(["sub/fff.out"], ["sub/fff.in"])
130 cat(["sub/all"], ["sub/ddd.out", "sub/eee.out", "sub/fff.out"])
131 """),
132              stderr = """\
133 sub/SConscript 1.1 -> 1.2: 5 lines
134 aaa.in 1.1 -> 1.2: 1 lines
135 ccc.in 1.1 -> 1.2: 1 lines
136 sub/ddd.in 1.1 -> 1.2: 1 lines
137 sub/fff.in 1.1 -> 1.2: 1 lines
138 """)
139
140     test.must_match(['work1', 'all'], "work1/aaa.in\nchecked-out work1/bbb.in\nwork1/ccc.in\n")
141
142     test.must_be_writable(test.workpath('work1', 'sub', 'SConscript'))
143     test.must_be_writable(test.workpath('work1', 'aaa.in'))
144     test.must_be_writable(test.workpath('work1', 'ccc.in'))
145     test.must_be_writable(test.workpath('work1', 'sub', 'ddd.in'))
146     test.must_be_writable(test.workpath('work1', 'sub', 'fff.in'))
147
148 # Test using BitKeeper to fetch from RCS/file,v files.
149 rcs = test.where_is('rcs')
150 ci = test.where_is('ci')
151 if not rcs:
152     print "Could not find RCS,\nskipping sub-test of BitKeeper using RCS files."
153 elif not ci:
154     print "Could not find the RCS ci command,\nskipping sub-test of BitKeeper using RCS files."
155 else:
156     test.subdir('work2',
157                 ['work2', 'RCS'],
158                 ['work2', 'sub'],
159                 ['work2', 'sub', 'RCS'])
160
161     for file in ['aaa.in', 'bbb.in', 'ccc.in']:
162         test.write(['work2', file], "work2/%s\n" % file)
163         args = "-f -t%s %s" % (file, file)
164         test.run(chdir = 'work2', program = ci, arguments = args, stderr = None)
165
166     test.write(['work2', 'sub', 'SConscript'], """\
167 Import("env")
168 env.Cat('ddd.out', 'ddd.in')
169 env.Cat('eee.out', 'eee.in')
170 env.Cat('fff.out', 'fff.in')
171 env.Cat('all', ['ddd.out', 'eee.out', 'fff.out'])
172 """)
173     args = "-f -tsub/SConscript sub/SConscript"
174     test.run(chdir = 'work2', program = ci, arguments = args, stderr = None)
175
176     for file in ['ddd.in', 'eee.in', 'fff.in']:
177         test.write(['work2', 'sub', file], "work2/sub/%s\n" % file)
178         args = "-f -tsub/%s sub/%s" % (file, file)
179         test.run(chdir = 'work2', program = ci, arguments = args, stderr = None)
180
181     test.no_result(os.path.exists(test.workpath('work2', 'aaa.in')))
182     test.no_result(os.path.exists(test.workpath('work2', 'bbb.in')))
183     test.no_result(os.path.exists(test.workpath('work2', 'ccc.in')))
184
185     test.no_result(os.path.exists(test.workpath('work2', 'sub', 'SConscript')))
186
187     test.no_result(os.path.exists(test.workpath('work2', 'sub', 'ddd.in')))
188     test.no_result(os.path.exists(test.workpath('work2', 'sub', 'eee.in')))
189     test.no_result(os.path.exists(test.workpath('work2', 'sub', 'fff.in')))
190
191     test.write(['work2', 'SConstruct'], """\
192 def cat(env, source, target):
193     target = str(target[0])
194     source = map(str, source)
195     f = open(target, "wb")
196     for src in source:
197         f.write(open(src, "rb").read())
198     f.close()
199 env = Environment(BUILDERS={'Cat':Builder(action=cat)},
200                   BITKEEPERGET='$BITKEEPER co',
201                   BITKEEPERGETFLAGS='-q')
202 env.Cat('aaa.out', 'aaa.in')
203 env.Cat('bbb.out', 'bbb.in')
204 env.Cat('ccc.out', 'ccc.in')
205 env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out'])
206 env.SourceCode('.', env.BitKeeper())
207 SConscript('sub/SConscript', "env")
208 """)
209
210     test.write(['work2', 'bbb.in'], "checked-out work2/bbb.in\n")
211
212     test.write(['work2', 'sub', 'eee.in'], "checked-out work2/sub/eee.in\n")
213
214     test.run(chdir = 'work2',
215              arguments = '.',
216              stdout = test.wrap_stdout(read_str = """\
217 bk co -q sub/SConscript
218 """,
219                                        build_str = """\
220 bk co -q aaa.in
221 cat(["aaa.out"], ["aaa.in"])
222 cat(["bbb.out"], ["bbb.in"])
223 bk co -q ccc.in
224 cat(["ccc.out"], ["ccc.in"])
225 cat(["all"], ["aaa.out", "bbb.out", "ccc.out"])
226 bk co -q sub/ddd.in
227 cat(["sub/ddd.out"], ["sub/ddd.in"])
228 cat(["sub/eee.out"], ["sub/eee.in"])
229 bk co -q sub/fff.in
230 cat(["sub/fff.out"], ["sub/fff.in"])
231 cat(["sub/all"], ["sub/ddd.out", "sub/eee.out", "sub/fff.out"])
232 """))
233
234     test.must_match(['work2', 'all'], "work2/aaa.in\nchecked-out work2/bbb.in\nwork2/ccc.in\n")
235
236     test.must_match(['work2', 'sub', 'all'], "work2/sub/ddd.in\nchecked-out work2/sub/eee.in\nwork2/sub/fff.in\n")
237
238     test.must_not_be_writable(test.workpath('work2', 'sub', 'SConscript'))
239     test.must_not_be_writable(test.workpath('work2', 'aaa.in'))
240     test.must_not_be_writable(test.workpath('work2', 'ccc.in'))
241     test.must_not_be_writable(test.workpath('work2', 'sub', 'ddd.in'))
242     test.must_not_be_writable(test.workpath('work2', 'sub', 'fff.in'))
243
244 # Set up a "pure" BitKeeper hierarchy.
245 # BitKeeper's licensing restrictions require a configuration file that
246 # specifies you're not using it multi-user.  This seems to be the
247 # minimal configuration that satisfies these requirements.
248 test.write('bk.conf', """\
249 description:test project 'foo'
250 logging:none
251 email:%s
252 single_user:%s
253 single_host:%s
254 """ % (email, login, host))
255
256 # Plus, we need to set the external environment variable that gets it to
257 # shut up and not prompt us to accept the license.
258 os.environ['BK_LICENSE'] = 'ACCEPTED'
259
260 test.write(['import', 'aaa.in'], "import/aaa.in\n")
261 test.write(['import', 'bbb.in'], "import/bbb.in\n")
262 test.write(['import', 'ccc.in'], "import/ccc.in\n")
263
264 test.write(['import', 'sub', 'SConscript'], """\
265 Import("env")
266 env.Cat('ddd.out', 'ddd.in')
267 env.Cat('eee.out', 'eee.in')
268 env.Cat('fff.out', 'fff.in')
269 env.Cat('all', ['ddd.out', 'eee.out', 'fff.out'])
270 """)
271
272 test.write(['import', 'sub', 'ddd.in'], "import/sub/ddd.in\n")
273 test.write(['import', 'sub', 'eee.in'], "import/sub/eee.in\n")
274 test.write(['import', 'sub', 'fff.in'], "import/sub/fff.in\n")
275
276 # Test transparent source file checkouts using BitKeeper, by overriding
277 # the 'SCCS' construction variable in the default Environment.
278 work3 = test.workpath('work3')
279
280 test.run(program = bk,
281          arguments = 'setup -f -c bk.conf work3')
282
283 test.run(chdir = 'import',
284          program = bk,
285          arguments = 'import -q -f -tplain . %s' % test.workpath('work3'))
286
287 test.write(['work3', 'SConstruct'], """
288 def cat(env, source, target):
289     target = str(target[0])
290     source = map(str, source)
291     f = open(target, "wb")
292     for src in source:
293         f.write(open(src, "rb").read())
294     f.close()
295 DefaultEnvironment(tools=['SCCS'])['SCCS'] = r'%s'
296 env = Environment(BUILDERS={'Cat':Builder(action=cat)})
297 env.Cat('aaa.out', 'aaa.in')
298 env.Cat('bbb.out', 'bbb.in')
299 env.Cat('ccc.out', 'ccc.in')
300 env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out'])
301 SConscript('sub/SConscript', "env")
302 """ % bk)
303
304 test.write(['work3', 'bbb.in'], "work3/bbb.in\n")
305
306 test.subdir(['work3', 'sub'])
307 test.write(['work3', 'sub', 'eee.in'], "work3/sub/eee.in\n")
308
309 test.run(chdir = 'work3',
310          arguments = '.',
311          stdout = test.wrap_stdout(read_str = """\
312 %s get sub/SConscript
313 """ % bk,
314                                    build_str = """\
315 %s get aaa.in
316 cat(["aaa.out"], ["aaa.in"])
317 cat(["bbb.out"], ["bbb.in"])
318 %s get ccc.in
319 cat(["ccc.out"], ["ccc.in"])
320 cat(["all"], ["aaa.out", "bbb.out", "ccc.out"])
321 %s get sub/ddd.in
322 cat(["sub/ddd.out"], ["sub/ddd.in"])
323 cat(["sub/eee.out"], ["sub/eee.in"])
324 %s get sub/fff.in
325 cat(["sub/fff.out"], ["sub/fff.in"])
326 cat(["sub/all"], ["sub/ddd.out", "sub/eee.out", "sub/fff.out"])
327 """ % (bk, bk, bk, bk)),
328          stderr = """\
329 sub/SConscript 1.1: 5 lines
330 aaa.in 1.1: 1 lines
331 ccc.in 1.1: 1 lines
332 sub/ddd.in 1.1: 1 lines
333 sub/fff.in 1.1: 1 lines
334 """)
335
336 test.must_match(['work3', 'all'], "import/aaa.in\nwork3/bbb.in\nimport/ccc.in\n")
337
338 test.must_match(['work3', 'sub', 'all'], "import/sub/ddd.in\nwork3/sub/eee.in\nimport/sub/fff.in\n")
339
340 test.must_not_be_writable(test.workpath('work3', 'sub', 'SConscript'))
341 test.must_not_be_writable(test.workpath('work3', 'aaa.in'))
342 test.must_not_be_writable(test.workpath('work3', 'ccc.in'))
343 test.must_not_be_writable(test.workpath('work3', 'sub', 'ddd.in'))
344 test.must_not_be_writable(test.workpath('work3', 'sub', 'fff.in'))
345
346 test.pass_test()