amprolla_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)