tamprolla_merge.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
---
tamprolla_merge.py (6528B)
---
1 #!/usr/bin/env python3
2 # See LICENSE file for copyright and license details.
3
4 """
5 Amprolla main module
6 """
7
8 from os.path import basename, join
9 from multiprocessing import Pool
10 from time import time
11
12
13 import lib.globalvars as globalvars
14 from lib.config import (aliases, arches, banpkgs, categories, cpunm, mergedir,
15 mergesubdir, pkgfiles, repos, repo_order, spooldir,
16 srcfiles, suites, skips)
17 from lib.lock import check_lock, free_lock
18 from lib.package import (load_packages_file, merge_packages_many,
19 write_packages)
20 from lib.release import write_release
21 from lib.log import info, die
22
23
24 def prepare_merge_dict():
25 """
26 This function will prepare a dict of lists that contain the repos
27 that need to be merged in an ordered fashion. Orders them using the
28 repo_order list found in lib.config
29 Example output:
30 {'ascii': ['ascii', None, 'stretch']},
31 """
32 merge_dict = {}
33
34 for suite in suites:
35 for i in suites[suite]:
36 merge_dict[i] = []
37
38 for suite in merge_dict:
39 for repo in repo_order:
40 tmpsuite = suite
41 if repos[repo]['aliases'] is True:
42 if tmpsuite in aliases[repos[repo]['name']]:
43 tmpsuite = aliases[repos[repo]['name']][suite]
44 elif repos[repo]['skipmissing'] is True:
45 tmpsuite = None
46 if repo == 'debian' and suite in skips:
47 tmpsuite = None
48 if tmpsuite: # make it a proper path
49 tmpsuite = join(spooldir, repos[repo]['dists'], tmpsuite)
50 merge_dict[suite].append(tmpsuite)
51
52 return merge_dict
53
54
55 def devuan_rewrite(pkg, repo_name):
56 """
57 Function to be called when including a certain package. Allows for changing
58 any attributes.
59 """
60
61 if 'Filename' in pkg and repos[repo_name]['name'] not in pkg['Filename']:
62 pkg['Filename'] = pkg['Filename'].replace('pool/', 'pool/%s/' %
63 repos[repo_name]['name'], 1)
64 if 'Directory' in pkg and repos[repo_name]['name'] not in pkg['Directory']:
65 pkg['Directory'] = pkg['Directory'].replace('pool/', 'pool/%s/' %
66 repos[repo_name]['name'], 1)
67
68 return pkg
69
70
71 def merge(packages_list):
72 """
73 Merges the Packages/Sources files given in the package list
74
75 ['path/to/devuan/Packages.gz', None, 'path/to/debian/Packages.gz']
76 """
77 all_repos = []
78 print('Loading packages: %s' % packages_list)
79
80 for i in range(len(repo_order)):
81 pkgs = load_packages_file(packages_list[i])
82 if pkgs:
83 all_repos.append({'name': repo_order[i], 'packages': pkgs})
84
85 for i in range(len(repo_order)):
86 if packages_list[i]:
87 if basename(packages_list[i]) == 'Packages.gz':
88 print('Merging packages')
89 src = False
90 new_pkgs = merge_packages_many(all_repos,
91 banned_packages=banpkgs,
92 rewriter=devuan_rewrite)
93 elif basename(packages_list[i]) == 'Sources.gz':
94 print('Merging sources')
95 src = True
96 new_pkgs = merge_packages_many(all_repos,
97 rewriter=devuan_rewrite)
98 break
99
100 print('Writing packages')
101 for i in range(len(repo_order)):
102 if packages_list[i]:
103 new_out = packages_list[i].replace(join(spooldir,
104 repos[repo_order[i]]['dists']),
105 join(mergedir, mergesubdir))
106 break
107
108 if src:
109 write_packages(new_pkgs, new_out, sources=True)
110 else:
111 write_packages(new_pkgs, new_out)
112
113
114 def gen_release(suite):
115 """
116 Generates a Release file for a given suite (jessie/ascii/unstable)
117 """
118
119 filelist = []
120 print('\nCrawling %s' % suite)
121 rootdir = join(mergedir, mergesubdir, suite)
122 for cat in categories:
123 for arch in arches:
124 if arch == 'source':
125 flist = srcfiles
126 else:
127 flist = pkgfiles
128 cont = arch.replace('binary', 'Contents')
129 cont_udeb = arch.replace('binary', 'Contents-udeb')
130 filelist.append(join(rootdir, cat, cont+'.gz'))
131 filelist.append(join(rootdir, cat, cont))
132 filelist.append(join(rootdir, cat, cont_udeb+'.gz'))
133 filelist.append(join(rootdir, cat, cont_udeb))
134
135 for i in flist:
136 filelist.append(join(rootdir, cat, arch, i))
137 if arch != 'source':
138 filelist.append(join(rootdir, cat,
139 'debian-installer', arch, i))
140
141 newrfl = join(rootdir, 'Release')
142 oldrfl = newrfl.replace(join(mergedir, mergesubdir),
143 join(spooldir, repos['devuan']['dists']))
144
145 print('Writing Release')
146 write_release(oldrfl, newrfl, filelist, rootdir)
147
148
149 def main_merge(packages_file):
150 """
151 Main function that calls the actual merge
152 """
153 to_merge = prepare_merge_dict()
154
155 for suite in to_merge:
156 globalvars.suite = suite
157 pkg_list = []
158 for rep in to_merge[suite]:
159 if rep:
160 pkg_list.append(join(rep, packages_file))
161 else:
162 pkg_list.append(None)
163
164 merge(pkg_list)
165
166
167 def main():
168 """
169 Crawls the entire directory structure and orchestrates the merge
170 in a queue using multiprocessing
171 """
172 pkg = []
173 for i in arches:
174 for j in categories:
175 if i == 'source':
176 mrgfile = 'Sources.gz'
177 else:
178 mrgfile = 'Packages.gz'
179 pkg.append(join(j, 'debian-installer', i, mrgfile))
180
181 pkg.append(join(j, i, mrgfile))
182
183 mrgpool = Pool(cpunm)
184 mrgpool.map(main_merge, pkg)
185 mrgpool.close()
186
187 rel_list = []
188 for i in suites:
189 for j in suites[i]:
190 rel_list.append(j)
191
192 relpool = Pool(cpunm)
193 relpool.map(gen_release, rel_list)
194 relpool.close()
195
196
197 if __name__ == '__main__':
198 try:
199 t1 = time()
200 check_lock()
201 main()
202 free_lock()
203 t2 = time()
204 info('Total full merge time: %s' % (t2 - t1), tofile=True)
205 except Exception as e:
206 die(e)