#!/usr/bin/python3 # -*- coding: utf-8 -*- import argparse import os import shutil import sys import tarfile import tempfile parser = argparse.ArgumentParser(description='APK database merge script') parser.add_argument('layers', help='Path to LXC layers to be merged', nargs=argparse.REMAINDER) if len(sys.argv) < 2: parser.print_usage() sys.exit(1) args = parser.parse_args() layers = args.layers[::-1] # /etc/apk/world world = [] for layer in layers: try: with open(os.path.join(layer, 'etc/apk/world'), 'r') as f: for line in f: if line not in world: world.append(line) except: continue os.makedirs(os.path.join(layers[-1], 'etc/apk'), 0o755, True) with open(os.path.join(layers[-1], 'etc/apk/world'), 'w') as f: f.writelines(world) os.chown(os.path.join(layers[-1], 'etc'), 100000, 100000) os.chown(os.path.join(layers[-1], 'etc/apk'), 100000, 100000) os.chown(os.path.join(layers[-1], 'etc/apk/world'), 100000, 100000) # /lib/apk/db/installed installed = [] for layer in layers: try: with open(os.path.join(layer, 'lib/apk/db/installed'), 'r') as f: buffer = [] for line in f: if line.startswith('C:'): buffer = ''.join(buffer) if buffer not in installed: installed.append(buffer) buffer = [] buffer.append(line) buffer = ''.join(buffer) if buffer not in installed: installed.append(buffer) except: continue os.makedirs(os.path.join(layers[-1], 'lib/apk/db'), 0o755, True) with open(os.path.join(layers[-1], 'lib/apk/db/installed'), 'w') as f: f.writelines(installed) os.chown(os.path.join(layers[-1], 'lib'), 100000, 100000) os.chown(os.path.join(layers[-1], 'lib/apk'), 100000, 100000) os.chown(os.path.join(layers[-1], 'lib/apk/db'), 100000, 100000) os.chown(os.path.join(layers[-1], 'lib/apk/db/installed'), 100000, 100000) # /lib/apk/db/scripts.tar tmp_tar_path = tempfile.mkstemp()[1] files_in_tar = [] with tarfile.open(tmp_tar_path, 'w:') as tmp_tar: for layer in layers: tar_path = os.path.join(layer, 'lib/apk/db/scripts.tar') if os.path.exists(tar_path): with tarfile.open(tar_path, 'r:') as tar: for member in tar.getmembers(): if member.name not in files_in_tar: buffer = tar.extractfile(member) tmp_tar.addfile(member, buffer) files_in_tar.append(member.name) if files_in_tar: shutil.move(tmp_tar_path, os.path.join(layers[-1], 'lib/apk/db/scripts.tar')) os.chown(os.path.join(layers[-1], 'lib/apk/db/scripts.tar'), 100000, 100000) else: os.unlink(tmp_tar_path) # /lib/apk/db/triggers triggers = [] for layer in layers: try: with open(os.path.join(layer, 'lib/apk/db/triggers'), 'r') as f: for line in f: if line not in triggers: triggers.append(line) except: continue with open(os.path.join(layers[-1], 'lib/apk/db/triggers'), 'w') as f: f.writelines(triggers) os.chown(os.path.join(layers[-1], 'lib/apk/db/triggers'), 100000, 100000)