summaryrefslogtreecommitdiff
path: root/client/rebuild-kernel-packages.py
blob: 7e8e720622424c0e5cc5959da8b73eaecdebcd30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#!/usr/bin/python3

from __future__ import print_function

import argparse
import collections
import functools
import os
import rpm
import shlex
import subprocess
import sys

supported_kernels = ['head', '5.10', '5.4', '4.19', '4.14', '4.9']

packages = collections.OrderedDict([
    ('dahdi-linux',                           ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('ipset',                                 ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('lin_tape',                              ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('linux-gpib',                            ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('lttng-modules',                         ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('r8168',                                 ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('rtl8812au',                             ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('VirtualBox',                            ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('vpb-driver',                            ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('wl',                                    ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('xorg-driver-video-nvidia',              ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('xorg-driver-video-nvidia-legacy-390xx', ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('zfs',                                   ['head', '5.10', '5.4', '4.19', '4.14', '4.9']),
    ('xtables-addons',                        ['head', '5.10', '5.4', '4.19']),
    ('xtables-addons:XTADDONS_2',             ['4.14', '4.9']),
    ('crash',                                 ['5.4', '4.19', '4.14', '4.9']),
    ('WireGuard',                             ['5.4', '4.19', '4.14', '4.9']),
])

def get_rpmdir():
    return rpm.expandMacro("%_topdir")

def clean_pkgname(package):
    pkg = package.split(":")
    if not pkg:
        raise NameError
    spec = pkg[0]
    # ensure package ends with .spec
    if not spec.endswith(".spec"):
        spec += ".spec"
    name = spec[:-5]
    # and pkg without subdir
    name = name[name.rfind("/")+1:]
    try:
        branch = pkg[1]
    except IndexError:
        branch = "master"
    return [name, spec, branch]

def run_command(command, verbose=False, quiet=True):
    gitproc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=-1, text=True)
    gitproc.wait()
    out = gitproc.stdout.read().strip("\n'")
    if verbose:
        print(' '.join(command))
    if not quiet:
        print(out)
    if gitproc.returncode != 0:
        if quiet:
            print(out)
        print('\nError running command: \n')
        print(' '.join(command))
        return (False, None)
    return (True, out)

def get_last_tag(name, spec, branch, dist="th", kernel=None, verbose=False):
    fetch_package(name, spec, branch, verbose=verbose)
    if os.path.exists("%s/%s/%s" % (get_rpmdir(), name, spec)):
        tag = get_autotag(name, spec, branch, dist=dist, kernel=kernel, verbose=verbose)
    return tag

def get_autotag(name, spec, branch, dist="th", kernel=None, verbose=False):
    if not kernel or kernel == "head" or kernel == "master":
        ref = "auto/%s/%s-[0-9]*" % (dist, name)
    else:
        ref = "auto/%s/%s-%s-[0-9]*" % (dist, name, kernel)
    gitdir = "%s/%s" % (get_rpmdir(), name)
    tag = run_command(["/usr/bin/git", "-C", gitdir, "describe", "--tags", "--match", ref, "--abbrev=0", branch], verbose=verbose)
    return tag[1]

def fetch_package(name, spec, branch, verbose=False):
    gitdir = "%s/%s" % (get_rpmdir(), name)
    if os.path.exists("%s/.git" % gitdir):
        run_command(["/usr/bin/git", "-C", gitdir, "fetch", "origin"], verbose=verbose)
    else:
        run_command(["/usr/bin/git", "clone", "-o", "origin", "git://git.pld-linux.org/packages/" + name + ".git", gitdir], verbose=verbose)
        if not os.path.exists("%s/%s" % (gitdir, spec)):
            return None
        run_command(["/usr/bin/git", "-C", gitdir, "config", "--local", "--add", "remote.origin.fetch", "refs/notes/*:refs/notes/*"], verbose=verbose)
        run_command(["/usr/bin/git", "-C", gitdir, "remote", "set-url", "--push", "origin", "ssh://git@git.pld-linux.org/packages/" + name], verbose=verbose)
    run_command(["/usr/bin/git", "-C", gitdir, "fetch", "origin", "refs/notes/*:refs/notes/*"], verbose=verbose)
    if branch:
        if run_command(["/usr/bin/git", "-C", gitdir, "rev-parse", "--verify", "-q", branch], verbose=verbose):
            run_command(["/usr/bin/git", "-C", gitdir, "checkout", branch, "--"], verbose=verbose)
        elif run_command(["/usr/bin/git", "-C", gitdir, "rev-parse", "--verify", "-q", "refs/remotes/origin/" + branch], verbose=verbose):
            run_command(["/usr/bin/git", "-C", gitdir, "checkout", "-t", "refs/remotes/origin/" + branch], verbose=verbose)
        rev_branch = run_command(["/usr/bin/git", "-C", gitdir, "rev-parse", branch], verbose=verbose)
        rev_head = run_command(["/usr/bin/git", "-C", gitdir, "rev-parse", "HEAD"], verbose=verbose)
        if rev_branch[1] != rev_head[1]:
            print("Error: cannot checkout " + name)
            return None
        run_command(["/usr/bin/git", "-C", gitdir, "merge", "--ff-only", "@{upstream}"], verbose=verbose)

def csv_list(string):
    return string.split(',')

# TDOD: convert this to key function
# https://docs.python.org/3/library/stdtypes.html#list.sort
def kernel_cmp(x, y):
    x = x.split('.')
    y = y.split('.')
    try:
        int(x[0])
    except ValueError:
        return 1
    try:
        int(y[0])
    except ValueError:
        return -1
    majdiff = int(x[0]) - int(y[0])
    if majdiff:
        return majdiff
    mindiff = int(x[1]) - int(y[1])
    return mindiff

def main():
    parser = argparse.ArgumentParser(description='Rebuild kernel modules.')
    parser.add_argument('-d', '--dist',
            default='th',
            help='Dist name for getting auto-tags (default: %(default)s)')
    parser.add_argument('-m', '--make-request',
            default="make-request",
            metavar='SCRIPT',
            help='Name / path of the make-request script (default: %(default)s)')
    parser.add_argument('-ni', '--noinstall',
            action='store_true',
            help='skip installing new kernel packages on src builder (default: %(default)s)')
    parser.add_argument('-p', '--packages',
            type=csv_list,
            default=packages.keys(),
            metavar='PKG1[,PKG2...]',
            help='Package names to build (default: all)')
    parser.add_argument('-s', '--skip',
            type=csv_list,
            metavar='VER1[,VER2...]',
            help='Don\'t build modules specific to these kernels (default: %(default)s)')
    parser.add_argument('-k', '--kernel',
            default=supported_kernels,
            type=csv_list,
            metavar='VER1[,VER2...]',
            help='Only build modules for these kernels (default: %(default)s)')
    parser.add_argument('-t', '--test-build',
            action='store_true',
            help='Perform a test-builds')
    parser.add_argument('-bh', '--head',
            action='store_true',
            help='Perform build from head instead of last auto-tag')
    parser.add_argument('-v', '--verbose',
            action='store_true',
            help='Be verbose when running commands (default: %(default)s)')
    args = parser.parse_args()

    build_mode = '-r'
    if args.test_build:
        build_mode = '-t'

    if not args.skip:
        args.skip = []

    if not args.make_request.startswith('/'):
        for path in os.defpath.split(os.pathsep):
            if os.path.isfile('/'.join([path, args.make_request])):
                args.make_request = '/'.join([path, args.make_request])
                break

    build_kernels = supported_kernels
    if args.kernel:
        build_kernels = args.kernel

    if not args.noinstall:
        source_packages = []
        for kernel in supported_kernels:
            if kernel == 'head':
                ver = '-'
            else:
                ver = '-%s-' % kernel
            source_packages.extend(['kernel%sheaders' % ver, 'kernel%smodule-build' % ver])
        command = (('%(make_request)s -b %(dist)s-src -t -c '
                '"poldek -n %(dist)s -n %(dist)s-ready -n %(dist)s-test --up ; '
                'poldek -uvg %(source_packages)s"') %
                {'make_request': args.make_request,
                    'dist': args.dist,
                    'source_packages': ' '.join(source_packages)})
        run_command(shlex.split(command), verbose=args.verbose, quiet=False)
        input('\nPress Enter after src builder updates kernel packages...')

    print('\nCurrent kernels versions:')
    all_kernels = set()
    for kernel_list in packages.values():
        all_kernels.update(kernel_list)
    all_kernels = list(all_kernels)
    # TDOD: convert this to key function
    # https://docs.python.org/3/library/stdtypes.html#list.sort
    all_kernels.sort(key=functools.cmp_to_key(kernel_cmp), reverse=True)
    for kernel in all_kernels:
        branch = 'master'
        if kernel != 'head':
            branch = 'LINUX_%s' % kernel.replace('.','_')
        print('%s: %s' % (kernel, get_last_tag('kernel', 'kernel.spec', branch, dist=args.dist, kernel=kernel, verbose=args.verbose)))

    for pkg, kernels in packages.items():
        try:
            name, spec, branch = clean_pkgname(pkg)
        except NameError:
            continue
        if not pkg in args.packages:
            continue
        if not set(kernels).symmetric_difference(args.skip):
            continue
        selected_kernels = set(kernels).intersection(build_kernels)
        if not selected_kernels:
            continue
        if args.test_build:
            if branch:
                spec = '%s:%s' % (spec, branch)
            command = ("%s -nd %s -d %s --define 'build_kernels %s' --without userspace %s" %
                    (args.make_request, build_mode, args.dist, ','.join(selected_kernels), spec))
        else:
            if not args.head:
              tag = get_last_tag(name, spec, branch, dist=args.dist, verbose=args.verbose)
              if not tag:
                  print("Failed getching last autotag for %s!" % pkg)
                  continue
              spec = '%s:%s' % (spec, tag)
            command = ("%s -nd %s -d %s --define 'build_kernels %s' --without userspace %s" %
                    (args.make_request, build_mode, args.dist, ','.join(selected_kernels), spec))
        run_command(shlex.split(command), verbose=args.verbose, quiet=False)

if __name__ == "__main__":
    main()

# vi: encoding=utf-8 ts=8 sts=4 sw=4 et