1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun 6*4882a593Smuzhiyunimport os 7*4882a593Smuzhiyunimport sys 8*4882a593Smuzhiyunimport shutil 9*4882a593Smuzhiyunimport errno 10*4882a593Smuzhiyunimport time 11*4882a593Smuzhiyun 12*4882a593Smuzhiyundef mkdir(d): 13*4882a593Smuzhiyun try: 14*4882a593Smuzhiyun os.makedirs(d) 15*4882a593Smuzhiyun except OSError as e: 16*4882a593Smuzhiyun if e.errno != errno.EEXIST: 17*4882a593Smuzhiyun raise e 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun# extract the hash from past the last colon to last underscore 20*4882a593Smuzhiyundef extract_sha(filename): 21*4882a593Smuzhiyun return filename.split(':')[7].split('_')[0] 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun# get all files in a directory, extract hash and make 24*4882a593Smuzhiyun# a map from hash to list of file with that hash 25*4882a593Smuzhiyundef map_sha_to_files(dir_, prefix, sha_map): 26*4882a593Smuzhiyun sstate_prefix_path = dir_ + '/' + prefix + '/' 27*4882a593Smuzhiyun if not os.path.exists(sstate_prefix_path): 28*4882a593Smuzhiyun return 29*4882a593Smuzhiyun sstate_files = os.listdir(sstate_prefix_path) 30*4882a593Smuzhiyun for f in sstate_files: 31*4882a593Smuzhiyun try: 32*4882a593Smuzhiyun sha = extract_sha(f) 33*4882a593Smuzhiyun if sha not in sha_map: 34*4882a593Smuzhiyun sha_map[sha] = [] 35*4882a593Smuzhiyun sha_map[sha].append(sstate_prefix_path + f) 36*4882a593Smuzhiyun except IndexError: 37*4882a593Smuzhiyun continue 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun# given a prefix build a map of hash to list of files 40*4882a593Smuzhiyundef build_sha_cache(prefix): 41*4882a593Smuzhiyun sha_map = {} 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun sstate_dir = sys.argv[2] 44*4882a593Smuzhiyun map_sha_to_files(sstate_dir, prefix, sha_map) 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun native_sstate_dir = sys.argv[2] + '/' + sys.argv[4] 47*4882a593Smuzhiyun map_sha_to_files(native_sstate_dir, prefix, sha_map) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun return sha_map 50*4882a593Smuzhiyun 51*4882a593Smuzhiyunif len(sys.argv) < 5: 52*4882a593Smuzhiyun print("Incorrect number of arguments specified") 53*4882a593Smuzhiyun print("syntax: gen-lockedsig-cache <locked-sigs.inc> <input-cachedir> <output-cachedir> <nativelsbstring> [filterfile]") 54*4882a593Smuzhiyun sys.exit(1) 55*4882a593Smuzhiyun 56*4882a593Smuzhiyunfilterlist = [] 57*4882a593Smuzhiyunif len(sys.argv) > 5: 58*4882a593Smuzhiyun print('Reading filter file %s' % sys.argv[5]) 59*4882a593Smuzhiyun with open(sys.argv[5]) as f: 60*4882a593Smuzhiyun for l in f.readlines(): 61*4882a593Smuzhiyun if ":" in l: 62*4882a593Smuzhiyun filterlist.append(l.rstrip()) 63*4882a593Smuzhiyun 64*4882a593Smuzhiyunprint('Reading %s' % sys.argv[1]) 65*4882a593Smuzhiyunsigs = [] 66*4882a593Smuzhiyunwith open(sys.argv[1]) as f: 67*4882a593Smuzhiyun for l in f.readlines(): 68*4882a593Smuzhiyun if ":" in l: 69*4882a593Smuzhiyun task, sig = l.split()[0].rsplit(':', 1) 70*4882a593Smuzhiyun if filterlist and not task in filterlist: 71*4882a593Smuzhiyun print('Filtering out %s' % task) 72*4882a593Smuzhiyun else: 73*4882a593Smuzhiyun sigs.append(sig) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyunprint('Gathering file list') 76*4882a593Smuzhiyunstart_time = time.perf_counter() 77*4882a593Smuzhiyunfiles = set() 78*4882a593Smuzhiyunsstate_content_cache = {} 79*4882a593Smuzhiyunfor s in sigs: 80*4882a593Smuzhiyun prefix = s[:2] 81*4882a593Smuzhiyun prefix2 = s[2:4] 82*4882a593Smuzhiyun if prefix not in sstate_content_cache: 83*4882a593Smuzhiyun sstate_content_cache[prefix] = {} 84*4882a593Smuzhiyun if prefix2 not in sstate_content_cache[prefix]: 85*4882a593Smuzhiyun sstate_content_cache[prefix][prefix2] = build_sha_cache(prefix + "/" + prefix2) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun if s in sstate_content_cache[prefix][prefix2]: 88*4882a593Smuzhiyun for f in sstate_content_cache[prefix][prefix2][s]: 89*4882a593Smuzhiyun files.add(f) 90*4882a593Smuzhiyun 91*4882a593Smuzhiyunelapsed = time.perf_counter() - start_time 92*4882a593Smuzhiyunprint("Gathering file list took %.1fs" % elapsed) 93*4882a593Smuzhiyun 94*4882a593Smuzhiyunprint('Processing files') 95*4882a593Smuzhiyunfor f in files: 96*4882a593Smuzhiyun sys.stdout.write('Processing %s... ' % f) 97*4882a593Smuzhiyun if not f.endswith(('.tar.zst', '.siginfo', '.sig')): 98*4882a593Smuzhiyun # Most likely a temp file, skip it 99*4882a593Smuzhiyun print('skipping') 100*4882a593Smuzhiyun continue 101*4882a593Smuzhiyun dst = os.path.join(sys.argv[3], os.path.relpath(f, sys.argv[2])) 102*4882a593Smuzhiyun destdir = os.path.dirname(dst) 103*4882a593Smuzhiyun mkdir(destdir) 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun src = os.path.realpath(f) 106*4882a593Smuzhiyun if os.path.exists(dst): 107*4882a593Smuzhiyun os.remove(dst) 108*4882a593Smuzhiyun if (os.stat(src).st_dev == os.stat(destdir).st_dev): 109*4882a593Smuzhiyun print('linking') 110*4882a593Smuzhiyun try: 111*4882a593Smuzhiyun os.link(src, dst) 112*4882a593Smuzhiyun except OSError as e: 113*4882a593Smuzhiyun print('hard linking failed, copying') 114*4882a593Smuzhiyun shutil.copyfile(src, dst) 115*4882a593Smuzhiyun else: 116*4882a593Smuzhiyun print('copying') 117*4882a593Smuzhiyun shutil.copyfile(src, dst) 118*4882a593Smuzhiyun 119*4882a593Smuzhiyunprint('Done!') 120