trelease.py - amprolla - devuan's apt repo merger
HTML git clone https://git.parazyd.org/amprolla
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
trelease.py (4908B)
---
1 # See LICENSE file for copyright and license details.
2
3 """
4 Release file functions and helpers
5 """
6
7 from datetime import datetime # , timedelta
8 from gzip import decompress as gzip_decomp
9 from lzma import compress as lzma_comp
10 from os.path import getsize, isfile
11 from subprocess import Popen
12
13 import lib.globalvars as globalvars
14 from lib.config import (checksums, distrolabel, gpgdir, release_aliases,
15 release_keys, signingkey, signrelease, arches)
16 from lib.log import info
17 from lib.parse import parse_release_head, parse_release
18
19
20 def rewrite_release_head(headers):
21 """
22 Rewrites the necessary headers in a Release file
23 Used to override needed values defined in config.release_aliases
24 """
25 if headers['Suite'] in release_aliases:
26 headers['Label'] = distrolabel
27 suitename = headers['Suite']
28 for var in release_aliases[suitename]:
29 headers[var] = release_aliases[suitename][var]
30
31 return headers
32
33
34 def write_release(oldrel, newrel, filelist, rmstr, rewrite=True):
35 """
36 Generates a valid Release file
37 if sign=False: do not use gnupg to sign the file
38 if rewrite=True: rewrite the Release headers as defined in the config
39
40 Arguments taken: oldrel, newrel, filelist, rmstr
41 * location of the old Release file (used to take metadata)
42 * location where to write the new Release file
43 * list of files to make checksums
44 * string to remove from the path of the hashed file
45 """
46 time1 = datetime.utcnow()
47 # time2 = datetime.utcnow() + timedelta(days=7)
48
49 prettyt1 = time1.strftime('%a, %d %b %Y %H:%M:%S UTC')
50 # prettyt2 = time2.strftime('%a, %d %b %Y %H:%M:%S UTC')
51
52 # this holds our local data in case we don't want to rehash files
53 if isfile(newrel):
54 local_rel = open(newrel).read()
55 local_rel = parse_release(local_rel)
56
57 old = open(oldrel).read()
58 new = open(newrel, 'w')
59
60 rel_cont = parse_release_head(old)
61
62 rel_cont['Date'] = prettyt1
63 # rel_cont['Valid-Until'] = prettyt2
64
65 _archlist = ''
66 for i in arches:
67 if i == 'source':
68 continue
69 if i == 'binary-all':
70 continue
71 i = i.replace('binary-', ' ')
72 _archlist += i
73 rel_cont['Architectures'] = _archlist
74
75 if rewrite:
76 rel_cont = rewrite_release_head(rel_cont)
77
78 for k in release_keys:
79 if k in rel_cont:
80 new.write('%s: %s\n' % (k, rel_cont[k]))
81
82 if globalvars.rehash:
83 rehash_release(filelist, new, rmstr)
84 else:
85 info('Reusing old checksums')
86 for csum in checksums:
87 new.write('%s:\n' % csum['name'])
88 for i, j in local_rel.items():
89 new.write(' %s %8s %s\n' % (j[0], j[1], i))
90
91 new.close()
92
93 if signrelease:
94 sign_release(newrel)
95
96
97 def rehash_release(_filelist, fdesc, rmstr):
98 """
99 Calculates checksums of a given filelist and writes them to the given
100 file descriptor. Takes rmstr as the third argument, which is a string to
101 remove from the path of the hashed file when writing it to a file.
102 """
103 info('Hashing checksums')
104 for csum in checksums:
105 fdesc.write('%s:\n' % csum['name'])
106 for i in _filelist:
107 if isfile(i):
108 cont = open(i, 'rb').read()
109 fdesc.write(' %s %8s %s\n' % (csum['f'](cont).hexdigest(),
110 getsize(i),
111 i.replace(rmstr+'/', '')))
112 elif i.endswith('.xz') and isfile(i.replace('.xz', '.gz')):
113 xzstr = lzma_comp(open(i.replace('.xz', '.gz'), 'rb').read())
114 fdesc.write(' %s %8s %s\n' % (csum['f'](xzstr).hexdigest(),
115 len(xzstr),
116 i.replace(rmstr+'/', '')))
117 elif not i.endswith('.gz') and isfile(i+'.gz'):
118 uncomp = gzip_decomp(open(i+'.gz', 'rb').read())
119 fdesc.write(' %s %8s %s\n' % (csum['f'](uncomp).hexdigest(),
120 len(uncomp),
121 i.replace(rmstr+'/', '')))
122 return
123
124
125 def sign_release(infile):
126 """
127 Signs both the clearsign and the detached signature of a Release file.
128
129 Takes a valid path to a release file as an argument.
130 """
131 args = ['gpg', '-q', '--default-key', signingkey, '--batch', '--yes',
132 '--homedir', gpgdir]
133
134 clearargs = args + ['--clearsign', '-a', '-o',
135 infile.replace('Release', 'InRelease'), infile]
136 detachargs = args + ['-sb', '-o', infile+'.gpg', infile]
137
138 info('Signing Release (clearsign)')
139 cleargpg = Popen(clearargs)
140 cleargpg.wait(timeout=5)
141
142 info('Signing Release (detached sign)')
143 detachgpg = Popen(detachargs)
144 detachgpg.wait(timeout=5)