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
|
#!/usr/bin/env python3
# Adélie Linux architecture package tester
# Ensure all packages are all on arches
#
# Copyright © 2018-2020 Adélie Linux team. All rights reserved.
# NCSA license.
#
import argparse
import os
import sys
from pathlib import Path
from apkkit.base.index import Index
from output import FORMATTERS, Yes, No, YES_MISSING, PARTIAL_MISSING
from version import is_older
def analyze(opts):
newest = dict()
arch_newest = {arch: dict() for arch in opts.arches}
for arch in opts.arches:
print(f"Loading {arch}...", file=sys.stderr)
url = f"{opts.url}/{opts.repo}/{arch}/APKINDEX.tar.gz"
for pkg in Index(url=url).packages:
if pkg.name != pkg.origin:
continue
new = pkg.version
for mydict in (newest, arch_newest[arch]):
curr = mydict.get(pkg.name, None)
if curr is None:
mydict[pkg.name] = new
elif is_older(curr, new):
mydict[pkg.name] = new
return newest, arch_newest
def order_arch(opts, ign):
newest, arch_newest = analyze(opts)
yield ["arch", "package", "version for arch", "newest version"]
for arch in opts.arches:
old = list()
for pkg in newest.keys():
ver = newest[pkg]
archver = arch_newest[arch].get(pkg, None)
if archver is None and pkg not in ign:
yield [arch, pkg, PARTIAL_MISSING, ver]
elif archver is not None and is_older(archver, ver):
if opts.only_missing:
continue
yield [arch, pkg, archver, ver]
def order_pkg(opts, ign):
newest, arch_newest = analyze(opts)
yield ["package", *opts.arches]
for pkg in sorted(newest.keys()):
for i in opts.arches:
archver = arch_newest[i].get(pkg, None)
if archver is None:
break
if opts.only_missing:
continue
if archver is not None and is_older(archver, newest[pkg]):
break
else:
continue
row = [pkg]
for i in opts.arches:
archver = arch_newest[i].get(pkg, None)
if archver is None and pkg in ign:
row.append(YES_MISSING)
elif archver is None:
row.append(PARTIAL_MISSING)
elif is_older(archver, newest[pkg]):
row.append(No(archver))
else:
row.append(Yes(archver))
yield row
ORDERS = {
"pkg": order_pkg,
"arch": order_arch,
}
if __name__ == "__main__":
opts = argparse.ArgumentParser(
description="""Scan the REPO/ARCH repositories under URL and
look for outdated or missing packages when comparing across
architectures. This script only examines main packages, not
subpackages.
At least two architectures must be given in order to make a
comparison."""
)
opts.add_argument(
"-f", "--format", choices=FORMATTERS.keys(),
default="pretty" if os.isatty(sys.stdout.fileno()) else "tab",
help="display format",
)
opts.add_argument(
"-m", "--only-missing", action="store_true",
help="show only missing packages",
)
opts.add_argument(
"-o", "--order", choices=ORDERS.keys(),
default="pkg",
help="display order",
)
opts.add_argument(
"url", metavar="URL",
help="base URL (no repository or arch)",
)
opts.add_argument(
"repo", metavar="REPO",
help="repository",
)
opts.add_argument(
"arches", metavar="ARCHES",
help="architectures (comma separated, at least 2)",
)
opts = opts.parse_args()
opts.arches = opts.arches.split(",")
if len(opts.arches) < 2:
print("At least two arches are required", file=sys.stderr)
sys.exit(1)
if Path(opts.repo + "-specific").is_file():
with open(opts.repo + '-specific', 'r') as ignore_file:
ign = set(pkg[:-1] for pkg in ignore_file.readlines())
else:
ign = set()
# FIXME: support multiple repos
FORMATTERS[opts.format](
opts,
ORDERS[opts.order](opts, ign),
)
|