amprolla

devuan's apt repo merger
git clone https://git.parazyd.org/amprolla
Log | Files | Refs | README | LICENSE

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)