xref: /OK3568_Linux_fs/yocto/scripts/gen-lockedsig-cache (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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