1import os
2import hashlib
3import inspect
4import re
5import zlib
6from lib import BaseTest
7
8
9def strip_processor(output):
10    return "\n".join([l for l in output.split("\n") if not l.startswith(' ') and not l.startswith('Date:')])
11
12
13def ungzip_if_required(output):
14    if output.startswith("\x1f\x8b"):
15        return zlib.decompress(output, 16+zlib.MAX_WBITS)
16
17    return output
18
19
20class PublishRepo1Test(BaseTest):
21    """
22    publish repo: default
23    """
24    fixtureCmds = [
25        "aptly repo create local-repo",
26        "aptly repo add local-repo ${files}",
27    ]
28    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo"
29    gold_processor = BaseTest.expand_environ
30
31    def check(self):
32        super(PublishRepo1Test, self).check()
33
34        self.check_exists('public/dists/maverick/InRelease')
35        self.check_exists('public/dists/maverick/Release')
36        self.check_exists('public/dists/maverick/Release.gpg')
37
38        self.check_exists('public/dists/maverick/main/binary-i386/Packages')
39        self.check_exists('public/dists/maverick/main/binary-i386/Packages.gz')
40        self.check_exists('public/dists/maverick/main/binary-i386/Packages.bz2')
41        self.check_exists('public/dists/maverick/main/Contents-i386.gz')
42        self.check_exists('public/dists/maverick/main/source/Sources')
43        self.check_exists('public/dists/maverick/main/source/Sources.gz')
44        self.check_exists('public/dists/maverick/main/source/Sources.bz2')
45
46        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
47        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
48        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
49        self.check_exists('public/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
50        self.check_exists('public/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
51
52        # verify contents except of sums
53        self.check_file_contents('public/dists/maverick/Release', 'release', match_prepare=strip_processor)
54        self.check_file_contents('public/dists/maverick/main/source/Sources', 'sources', match_prepare=lambda s: "\n".join(sorted(s.split("\n"))))
55        self.check_file_contents('public/dists/maverick/main/binary-i386/Packages', 'binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n"))))
56        self.check_file_contents('public/dists/maverick/main/Contents-i386.gz', 'contents_i386', match_prepare=ungzip_if_required)
57        self.check_file_contents('public/dists/maverick/Contents-i386.gz', 'contents_i386_legacy', match_prepare=ungzip_if_required)
58
59        # verify signatures
60        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"),
61                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')])
62        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb",  "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"),
63                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'),
64                      os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])
65
66        # verify sums
67        release = self.read_file('public/dists/maverick/Release').split("\n")
68        release = [l for l in release if l.startswith(" ")]
69        pathsSeen = set()
70        for l in release:
71            fileHash, fileSize, path = l.split()
72            if "Contents" in path and not path.endswith(".gz"):
73                # "Contents" are present in index, but not really written to disk
74                continue
75
76            pathsSeen.add(path)
77
78            fileSize = int(fileSize)
79
80            st = os.stat(os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/', path))
81            if fileSize != st.st_size:
82                raise Exception("file size doesn't match for %s: %d != %d" % (path, fileSize, st.st_size))
83
84            if len(fileHash) == 32:
85                h = hashlib.md5()
86            elif len(fileHash) == 40:
87                h = hashlib.sha1()
88            elif len(fileHash) == 64:
89                h = hashlib.sha256()
90            else:
91                h = hashlib.sha512()
92
93            h.update(self.read_file(os.path.join('public/dists/maverick', path)))
94
95            if h.hexdigest() != fileHash:
96                raise Exception("file hash doesn't match for %s: %s != %s" % (path, fileHash, h.hexdigest()))
97
98        if pathsSeen != set(['main/binary-i386/Packages', 'main/binary-i386/Packages.bz2', 'main/binary-i386/Packages.gz',
99                             'main/source/Sources', 'main/source/Sources.gz', 'main/source/Sources.bz2',
100                             'main/binary-i386/Release', 'main/source/Release', 'main/Contents-i386.gz',
101                             'Contents-i386.gz']):
102            raise Exception("path seen wrong: %r" % (pathsSeen, ))
103
104
105class PublishRepo2Test(BaseTest):
106    """
107    publish repo: different component
108    """
109    fixtureCmds = [
110        "aptly repo create local-repo",
111        "aptly repo add local-repo ${files}",
112    ]
113    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick -component=contrib local-repo"
114    gold_processor = BaseTest.expand_environ
115
116    def check(self):
117        super(PublishRepo2Test, self).check()
118
119        self.check_exists('public/dists/maverick/InRelease')
120        self.check_exists('public/dists/maverick/Release')
121        self.check_exists('public/dists/maverick/Release.gpg')
122
123        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages')
124        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.gz')
125        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.bz2')
126        self.check_exists('public/dists/maverick/contrib/Contents-i386.gz')
127        self.check_exists('public/dists/maverick/contrib/source/Sources')
128        self.check_exists('public/dists/maverick/contrib/source/Sources.gz')
129        self.check_exists('public/dists/maverick/contrib/source/Sources.bz2')
130
131        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.dsc')
132        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
133        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1.orig.tar.gz')
134        self.check_exists('public/pool/contrib/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
135        self.check_exists('public/pool/contrib/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
136
137
138class PublishRepo3Test(BaseTest):
139    """
140    publish repo: different architectures
141    """
142    fixtureCmds = [
143        "aptly repo create local-repo",
144        "aptly repo add local-repo ${files}",
145    ]
146    runCmd = "aptly -architectures=i386 publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick -component=contrib local-repo"
147    gold_processor = BaseTest.expand_environ
148
149    def check(self):
150        super(PublishRepo3Test, self).check()
151
152        self.check_exists('public/dists/maverick/InRelease')
153        self.check_exists('public/dists/maverick/Release')
154        self.check_exists('public/dists/maverick/Release.gpg')
155
156        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages')
157        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.gz')
158        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.bz2')
159        self.check_exists('public/dists/maverick/contrib/Contents-i386.gz')
160        self.check_not_exists('public/dists/maverick/contrib/source/Sources')
161        self.check_not_exists('public/dists/maverick/contrib/source/Sources.gz')
162        self.check_not_exists('public/dists/maverick/contrib/source/Sources.bz2')
163
164        self.check_not_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.dsc')
165        self.check_not_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
166        self.check_not_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1.orig.tar.gz')
167        self.check_not_exists('public/pool/contrib/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
168        self.check_exists('public/pool/contrib/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
169
170
171class PublishRepo4Test(BaseTest):
172    """
173    publish repo: under prefix
174    """
175    fixtureCmds = [
176        "aptly repo create local-repo",
177        "aptly repo add local-repo ${files}",
178    ]
179    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo ppa"
180    gold_processor = BaseTest.expand_environ
181
182    def check(self):
183        super(PublishRepo4Test, self).check()
184
185        self.check_exists('public/ppa/dists/maverick/InRelease')
186        self.check_exists('public/ppa/dists/maverick/Release')
187        self.check_exists('public/ppa/dists/maverick/Release.gpg')
188
189        self.check_exists('public/ppa/dists/maverick/main/binary-i386/Packages')
190        self.check_exists('public/ppa/dists/maverick/main/binary-i386/Packages.gz')
191        self.check_exists('public/ppa/dists/maverick/main/binary-i386/Packages.bz2')
192        self.check_exists('public/ppa/dists/maverick/main/Contents-i386.gz')
193        self.check_exists('public/ppa/dists/maverick/main/source/Sources')
194        self.check_exists('public/ppa/dists/maverick/main/source/Sources.gz')
195        self.check_exists('public/ppa/dists/maverick/main/source/Sources.bz2')
196
197        self.check_exists('public/ppa/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
198        self.check_exists('public/ppa/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
199        self.check_exists('public/ppa/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
200        self.check_exists('public/ppa/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
201        self.check_exists('public/ppa/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
202
203
204class PublishRepo5Test(BaseTest):
205    """
206    publish repo: specify distribution
207    """
208    fixtureDB = True
209    fixtureCmds = [
210        "aptly repo create local-repo",
211        "aptly repo add local-repo ${files}",
212    ]
213    runCmd = "aptly publish repo local-repo"
214    expectedCode = 1
215
216
217class PublishRepo6Test(BaseTest):
218    """
219    publish repo: double publish under root
220    """
221    fixtureDB = True
222    fixtureCmds = [
223        "aptly repo create local-repo",
224        "aptly repo add local-repo ${files}",
225        "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo",
226    ]
227    runCmd = "aptly publish repo -distribution=maverick local-repo"
228    expectedCode = 1
229
230
231class PublishRepo7Test(BaseTest):
232    """
233    publish repo: double publish under prefix
234    """
235    fixtureDB = True
236    fixtureCmds = [
237        "aptly repo create local-repo",
238        "aptly repo add local-repo ${files}",
239        "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo ./ppa",
240    ]
241    runCmd = "aptly publish repo -distribution=maverick local-repo ppa"
242    expectedCode = 1
243
244
245class PublishRepo8Test(BaseTest):
246    """
247    publish repo: wrong prefix
248    """
249    fixtureDB = True
250    fixtureCmds = [
251        "aptly repo create local-repo",
252        "aptly repo add local-repo ${files}",
253    ]
254    runCmd = "aptly publish repo -distribution=maverick local-repo ppa/dists/la"
255    expectedCode = 1
256
257
258class PublishRepo9Test(BaseTest):
259    """
260    publish repo: wrong prefix
261    """
262    fixtureDB = True
263    fixtureCmds = [
264        "aptly repo create local-repo",
265        "aptly repo add local-repo ${files}",
266    ]
267    runCmd = "aptly publish repo -distribution=maverick local-repo ppa/pool/la"
268    expectedCode = 1
269
270
271class PublishRepo10Test(BaseTest):
272    """
273    publish repo: wrong prefix
274    """
275    fixtureDB = True
276    fixtureCmds = [
277        "aptly repo create local-repo",
278        "aptly repo add local-repo ${files}",
279    ]
280    runCmd = "aptly publish repo -distribution=maverick local-repo ../la"
281    expectedCode = 1
282
283
284class PublishRepo11Test(BaseTest):
285    """
286    publish repo: no snapshot
287    """
288    runCmd = "aptly publish repo local-repo"
289    expectedCode = 1
290
291
292class PublishRepo12Test(BaseTest):
293    """
294    publish repo: -skip-signing
295    """
296    fixtureDB = True
297    fixtureCmds = [
298        "aptly repo create local-repo",
299        "aptly repo add local-repo ${files}",
300    ]
301    runCmd = "aptly publish repo -skip-signing -distribution=maverick local-repo"
302    gold_processor = BaseTest.expand_environ
303
304    def check(self):
305        super(PublishRepo12Test, self).check()
306
307        self.check_not_exists('public/dists/maverick/InRelease')
308        self.check_exists('public/dists/maverick/Release')
309        self.check_not_exists('public/dists/maverick/Release.gpg')
310
311        self.check_exists('public/dists/maverick/main/binary-i386/Packages')
312        self.check_exists('public/dists/maverick/main/binary-i386/Packages.gz')
313        self.check_exists('public/dists/maverick/main/binary-i386/Packages.bz2')
314        self.check_exists('public/dists/maverick/main/Contents-i386.gz')
315        self.check_exists('public/dists/maverick/main/source/Sources')
316        self.check_exists('public/dists/maverick/main/source/Sources.gz')
317        self.check_exists('public/dists/maverick/main/source/Sources.bz2')
318
319        # verify contents except of sums
320        self.check_file_contents('public/dists/maverick/Release', 'release', match_prepare=strip_processor)
321
322
323class PublishRepo13Test(BaseTest):
324    """
325    publish repo: empty repo is not publishable w/o architectures list
326    """
327    fixtureDB = True
328    fixtureCmds = [
329        "aptly repo create local-repo",
330    ]
331    runCmd = "aptly publish repo --distribution=mars --skip-signing local-repo"
332    expectedCode = 1
333
334
335class PublishRepo14Test(BaseTest):
336    """
337    publish repo: publishing defaults from local repo
338    """
339    fixtureCmds = [
340        "aptly repo create -distribution=maverick -component=contrib local-repo",
341        "aptly repo add local-repo ${files}",
342    ]
343    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec local-repo"
344    gold_processor = BaseTest.expand_environ
345
346    def check(self):
347        super(PublishRepo14Test, self).check()
348
349        self.check_exists('public/dists/maverick/InRelease')
350        self.check_exists('public/dists/maverick/Release')
351        self.check_exists('public/dists/maverick/Release.gpg')
352
353        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages')
354        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.gz')
355        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.bz2')
356        self.check_exists('public/dists/maverick/contrib/Contents-i386.gz')
357        self.check_exists('public/dists/maverick/contrib/source/Sources')
358        self.check_exists('public/dists/maverick/contrib/source/Sources.gz')
359        self.check_exists('public/dists/maverick/contrib/source/Sources.bz2')
360
361        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.dsc')
362        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
363        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1.orig.tar.gz')
364        self.check_exists('public/pool/contrib/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
365        self.check_exists('public/pool/contrib/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
366
367
368class PublishRepo15Test(BaseTest):
369    """
370    publish repo: custom label
371    """
372    fixtureCmds = [
373        "aptly repo create local-repo",
374        "aptly repo add local-repo ${files}",
375    ]
376    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick -component=contrib -label=label15 local-repo"
377    gold_processor = BaseTest.expand_environ
378
379    def check(self):
380        super(PublishRepo15Test, self).check()
381
382        # verify contents except of sums
383        self.check_file_contents('public/dists/maverick/Release', 'release', match_prepare=strip_processor)
384
385
386class PublishRepo16Test(BaseTest):
387    """
388    publish repo: empty repo is publishable with architectures list
389    """
390    fixtureDB = True
391    fixtureCmds = [
392        "aptly repo create local-repo",
393    ]
394    runCmd = "aptly publish repo  -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -architectures=source,i386 --distribution=maverick local-repo"
395    gold_processor = BaseTest.expand_environ
396
397    def check(self):
398        super(PublishRepo16Test, self).check()
399
400        self.check_exists('public/dists/maverick/InRelease')
401        self.check_exists('public/dists/maverick/Release')
402        self.check_exists('public/dists/maverick/Release.gpg')
403
404        self.check_exists('public/dists/maverick/main/binary-i386/Packages')
405        self.check_exists('public/dists/maverick/main/binary-i386/Packages.gz')
406        self.check_exists('public/dists/maverick/main/binary-i386/Packages.bz2')
407        self.check_exists('public/dists/maverick/main/source/Sources')
408        self.check_exists('public/dists/maverick/main/source/Sources.gz')
409        self.check_exists('public/dists/maverick/main/source/Sources.bz2')
410
411
412class PublishRepo17Test(BaseTest):
413    """
414    publish repo: multiple component
415    """
416    fixtureCmds = [
417        "aptly repo create repo1",
418        "aptly repo create repo2",
419        "aptly repo add repo1 ${files}/libboost-program-options-dev_1.49.0.1_i386.deb ${files}/pyspi_0.6.1-1.3.dsc",
420        "aptly repo add repo2 ${files}/pyspi-0.6.1-1.3.stripped.dsc",
421    ]
422    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -component=main,contrib -distribution=maverick repo1 repo2"
423    gold_processor = BaseTest.expand_environ
424
425    def check(self):
426        super(PublishRepo17Test, self).check()
427
428        self.check_exists('public/dists/maverick/InRelease')
429        self.check_exists('public/dists/maverick/Release')
430        self.check_exists('public/dists/maverick/Release.gpg')
431
432        self.check_exists('public/dists/maverick/main/binary-i386/Packages')
433        self.check_exists('public/dists/maverick/main/binary-i386/Packages.gz')
434        self.check_exists('public/dists/maverick/main/binary-i386/Packages.bz2')
435        self.check_exists('public/dists/maverick/main/source/Sources')
436        self.check_exists('public/dists/maverick/main/source/Sources.gz')
437        self.check_exists('public/dists/maverick/main/source/Sources.bz2')
438
439        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages')
440        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.gz')
441        self.check_exists('public/dists/maverick/contrib/binary-i386/Packages.bz2')
442        self.check_exists('public/dists/maverick/contrib/source/Sources')
443        self.check_exists('public/dists/maverick/contrib/source/Sources.gz')
444        self.check_exists('public/dists/maverick/contrib/source/Sources.bz2')
445
446        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
447        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
448        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
449        self.check_exists('public/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
450
451        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
452        self.check_exists('public/pool/contrib/p/pyspi/pyspi_0.6.1.orig.tar.gz')
453        self.check_exists('public/pool/contrib/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
454
455        # verify contents except of sums
456        self.check_file_contents('public/dists/maverick/Release', 'release', match_prepare=strip_processor)
457
458        # verify signatures
459        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"),
460                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')])
461        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb",  "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"),
462                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'),
463                      os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])
464
465        # verify sums
466        release = self.read_file('public/dists/maverick/Release').split("\n")
467        release = [l for l in release if l.startswith(" ")]
468        pathsSeen = set()
469        for l in release:
470            fileHash, fileSize, path = l.split()
471            if "Contents" in path and not path.endswith(".gz"):
472                # "Contents" are present in index, but not really written to disk
473                continue
474
475            pathsSeen.add(path)
476
477            fileSize = int(fileSize)
478
479            st = os.stat(os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/', path))
480            if fileSize != st.st_size:
481                raise Exception("file size doesn't match for %s: %d != %d" % (path, fileSize, st.st_size))
482
483            if len(fileHash) == 32:
484                h = hashlib.md5()
485            elif len(fileHash) == 40:
486                h = hashlib.sha1()
487            elif len(fileHash) == 64:
488                h = hashlib.sha256()
489            else:
490                h = hashlib.sha512()
491
492            h.update(self.read_file(os.path.join('public/dists/maverick', path)))
493
494            if h.hexdigest() != fileHash:
495                raise Exception("file hash doesn't match for %s: %s != %s" % (path, fileHash, h.hexdigest()))
496
497        if pathsSeen != set(['main/binary-i386/Packages', 'main/binary-i386/Packages.gz',
498                             'main/binary-i386/Packages.bz2',
499                             'main/source/Sources', 'main/source/Sources.gz', 'main/source/Sources.bz2',
500                             'contrib/binary-i386/Packages', 'contrib/binary-i386/Packages.gz',
501                             'contrib/binary-i386/Packages.bz2',
502                             'contrib/source/Sources', 'contrib/source/Sources.gz', 'contrib/source/Sources.bz2',
503                             'main/source/Release', 'contrib/source/Release',
504                             'main/binary-i386/Release', 'contrib/binary-i386/Release',
505                             'main/Contents-i386.gz', 'Contents-i386.gz']):
506            raise Exception("path seen wrong: %r" % (pathsSeen, ))
507
508
509class PublishRepo18Test(BaseTest):
510    """
511    publish repo: multiple component, guessing component names
512    """
513    fixtureCmds = [
514        "aptly repo create -distribution=squeeze -component=main repo1",
515        "aptly repo create -distribution=squeeze -component=contrib repo2",
516        "aptly repo add repo1 ${files}/libboost-program-options-dev_1.49.0.1_i386.deb ${files}/pyspi_0.6.1-1.3.dsc",
517        "aptly repo add repo2 ${files}/pyspi-0.6.1-1.3.stripped.dsc",
518    ]
519    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -component=, repo1 repo2"
520    gold_processor = BaseTest.expand_environ
521
522
523class PublishRepo19Test(BaseTest):
524    """
525    publish repo: duplicate component name (guessed)
526    """
527    fixtureCmds = [
528        "aptly repo create -distribution=squeeze -component=contrib repo1",
529        "aptly repo create -distribution=squeeze -component=contrib repo2",
530        "aptly repo add repo1 ${files}/libboost-program-options-dev_1.49.0.1_i386.deb ${files}/pyspi_0.6.1-1.3.dsc",
531        "aptly repo add repo2 ${files}/pyspi-0.6.1-1.3.stripped.dsc",
532    ]
533    runCmd = "aptly publish repo -component=, repo1 repo2"
534    expectedCode = 1
535
536
537class PublishRepo20Test(BaseTest):
538    """
539    publish repo: duplicate component name (manual)
540    """
541    fixtureCmds = [
542        "aptly repo create -distribution=squeeze -component=main repo1",
543        "aptly repo create -distribution=squeeze -component=contrib repo2",
544    ]
545    runCmd = "aptly publish repo -component=b,b repo1 repo2"
546    expectedCode = 1
547
548
549class PublishRepo21Test(BaseTest):
550    """
551    publish repo: distribution conflict
552    """
553    fixtureCmds = [
554        "aptly repo create -distribution=squeeze -component=main repo1",
555        "aptly repo create -distribution=wheezy -component=contrib repo2",
556    ]
557    runCmd = "aptly publish repo -component=, repo1 repo2"
558    expectedCode = 1
559
560
561class PublishRepo22Test(BaseTest):
562    """
563    publish reop: no such repo
564    """
565    fixtureCmds = [
566        "aptly repo create -distribution=squeeze -component=main repo1",
567    ]
568    runCmd = "aptly publish repo -component=, repo1 repo2"
569    expectedCode = 1
570
571
572class PublishRepo23Test(BaseTest):
573    """
574    publish repo: mismatch in count
575    """
576    fixtureCmds = [
577        "aptly repo create -distribution=squeeze -component=main repo1",
578    ]
579    runCmd = "aptly publish repo -component=main,contrib repo1"
580    expectedCode = 2
581
582    def outputMatchPrepare(_, s):
583        return "\n".join([l for l in s.split("\n") if l.startswith("ERROR")])
584
585
586class PublishRepo24Test(BaseTest):
587    """
588    publish repo: conflicting files in the repo
589    """
590    fixtureCmds = [
591        "aptly repo create local-repo1",
592        "aptly repo add local-repo1 ${files}",
593        "aptly repo create local-repo2",
594        "aptly repo add local-repo2 ${testfiles}",
595        "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo1",
596    ]
597    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=squeeze local-repo2"
598    expectedCode = 1
599    gold_processor = BaseTest.expand_environ
600
601
602class PublishRepo25Test(BaseTest):
603    """
604    publish repo: -force-overwrite
605    """
606    fixtureCmds = [
607        "aptly repo create local-repo1",
608        "aptly repo add local-repo1 ${files}",
609        "aptly repo create local-repo2",
610        "aptly repo add local-repo2 ${testfiles}",
611        "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo1",
612    ]
613    runCmd = "aptly publish repo -force-overwrite -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=squeeze local-repo2"
614    gold_processor = BaseTest.expand_environ
615
616    def check(self):
617        super(PublishRepo25Test, self).check()
618
619        self.check_file_contents("public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz", "file")
620
621
622class PublishRepo26Test(BaseTest):
623    """
624    publish repo: sign with passphrase
625    """
626    fixtureCmds = [
627        "aptly repo create local-repo",
628        "aptly repo add local-repo ${files}",
629    ]
630    runCmd = "aptly publish repo -keyring=${files}/aptly_passphrase.pub -secret-keyring=${files}/aptly_passphrase.sec -passphrase=verysecret -distribution=maverick local-repo"
631    gold_processor = BaseTest.expand_environ
632
633    def outputMatchPrepare(_, s):
634        return s.replace("gpg: gpg-agent is not available in this session\n", "")
635
636    def check(self):
637        super(PublishRepo26Test, self).check()
638
639        # verify signatures
640        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"),
641                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')])
642        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb",  "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"),
643                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'),
644                      os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])
645
646
647class PublishRepo27Test(BaseTest):
648    """
649    publish repo: with udebs
650    """
651    fixtureCmds = [
652        "aptly repo create local-repo",
653        "aptly repo add local-repo ${files} ${udebs}",
654    ]
655    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo"
656    gold_processor = BaseTest.expand_environ
657
658    def check(self):
659        super(PublishRepo27Test, self).check()
660
661        self.check_exists('public/dists/maverick/InRelease')
662        self.check_exists('public/dists/maverick/Release')
663        self.check_exists('public/dists/maverick/Release.gpg')
664
665        self.check_exists('public/dists/maverick/main/binary-i386/Release')
666        self.check_exists('public/dists/maverick/main/binary-i386/Packages')
667        self.check_exists('public/dists/maverick/main/binary-i386/Packages.gz')
668        self.check_exists('public/dists/maverick/main/binary-i386/Packages.bz2')
669        self.check_exists('public/dists/maverick/main/Contents-i386.gz')
670        self.check_exists('public/dists/maverick/main/debian-installer/binary-i386/Release')
671        self.check_exists('public/dists/maverick/main/debian-installer/binary-i386/Packages')
672        self.check_exists('public/dists/maverick/main/debian-installer/binary-i386/Packages.gz')
673        self.check_exists('public/dists/maverick/main/debian-installer/binary-i386/Packages.bz2')
674        self.check_exists('public/dists/maverick/main/Contents-udeb-i386.gz')
675        self.check_exists('public/dists/maverick/main/source/Release')
676        self.check_exists('public/dists/maverick/main/source/Sources')
677        self.check_exists('public/dists/maverick/main/source/Sources.gz')
678        self.check_exists('public/dists/maverick/main/source/Sources.bz2')
679
680        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
681        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
682        self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
683        self.check_exists('public/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
684        self.check_exists('public/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb')
685        self.check_exists('public/pool/main/d/dmraid/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb')
686        self.check_exists('public/pool/main/d/dmraid/dmraid-udeb_1.0.0.rc16-4.1_i386.udeb')
687
688        # verify contents except of sums
689        self.check_file_contents('public/dists/maverick/main/debian-installer/binary-i386/Packages', 'udeb_binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n"))))
690
691
692class PublishRepo28Test(BaseTest):
693    """
694    publish repo: -skip-contents
695    """
696    fixtureCmds = [
697        "aptly repo create local-repo",
698        "aptly repo add local-repo ${files} ${udebs}",
699    ]
700    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick -skip-contents local-repo"
701    gold_processor = BaseTest.expand_environ
702
703    def check(self):
704        super(PublishRepo28Test, self).check()
705
706        self.check_exists('public/dists/maverick/Release')
707
708        self.check_exists('public/dists/maverick/main/binary-i386/Release')
709        self.check_not_exists('public/dists/maverick/main/Contents-i386.gz')
710        self.check_exists('public/dists/maverick/main/debian-installer/binary-i386/Release')
711        self.check_not_exists('public/dists/maverick/main/Contents-udeb-i386.gz')
712
713
714class PublishRepo29Test(BaseTest):
715    """
716    publish repo: broken .deb file for contents
717    """
718    fixtureCmds = [
719        "aptly repo create local-repo",
720        "aptly repo add local-repo ${testfiles}",
721    ]
722    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo"
723    gold_processor = BaseTest.expand_environ
724
725
726class PublishRepo30Test(BaseTest):
727    """
728    publish repo: default (internal PGP implementation)
729    """
730    fixtureCmds = [
731        "aptly repo create local-repo",
732        "aptly repo add local-repo ${files}",
733    ]
734    runCmd = "aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=maverick local-repo"
735    gold_processor = BaseTest.expand_environ
736    configOverride = {"gpgProvider": "internal"}
737
738    def check(self):
739        super(PublishRepo30Test, self).check()
740
741        # verify signatures
742        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"),
743                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')])
744        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb",  "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"),
745                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'),
746                      os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])
747
748
749class PublishRepo31Test(BaseTest):
750    """
751    publish repo: sign with passphrase (internal PGP implementation)
752    """
753    fixtureCmds = [
754        "aptly repo create local-repo",
755        "aptly repo add local-repo ${files}",
756    ]
757    runCmd = "aptly publish repo -keyring=${files}/aptly_passphrase.pub -secret-keyring=${files}/aptly_passphrase.sec -passphrase=verysecret -distribution=maverick local-repo"
758    gold_processor = BaseTest.expand_environ
759    configOverride = {"gpgProvider": "internal"}
760
761    def outputMatchPrepare(_, s):
762        return re.sub(r' \d{4}-\d{2}-\d{2}', '', s)
763
764    def check(self):
765        super(PublishRepo31Test, self).check()
766
767        # verify signatures
768        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"),
769                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')])
770        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb",  "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"),
771                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'),
772                      os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])
773
774
775class PublishRepo32Test(BaseTest):
776    """
777    publish repo: default with gpg2
778    """
779    requiresGPG2 = True
780    fixtureCmds = [
781        "aptly repo create local-repo",
782        "aptly repo add local-repo ${files}",
783    ]
784    runCmd = "aptly publish repo -gpg-key=C5ACD2179B5231DFE842EE6121DBB89C16DB3E6D -keyring=${files}/aptly.pub -distribution=maverick local-repo"
785    gold_processor = BaseTest.expand_environ
786
787    def outputMatchPrepare(_, s):
788        return s.replace("gpg: gpg-agent is not available in this session\n", "")
789
790    def check(self):
791        super(PublishRepo32Test, self).check()
792
793        # verify signatures
794        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"),
795                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')])
796        self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb",  "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"),
797                      "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'),
798                      os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])
799