This repository has been archived by the owner on Dec 19, 2023. It is now read-only.
forked from coreos/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_out_of_date.py
executable file
·186 lines (147 loc) · 6.7 KB
/
check_out_of_date.py
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
#!/usr/bin/python2
# needs to be python2 for portage
# Prints out a list of all packages in portage-stable and how they stand relative to gentoo upstream
import argparse
import json
import os
import subprocess
import sys
import portage.versions
def split_package(p):
# split into cat/package,ver-rev
split = portage.versions.catpkgsplit(p.strip())
return (split[0] + "/" + split[1], split[2] + "-" + split[3])
def build_pkg_map(pkgs):
pkgs = map(split_package, pkgs)
package_map = dict()
for pkg, ver in pkgs:
if pkg not in package_map:
package_map[pkg] = [ver]
else:
package_map[pkg].append(ver)
return package_map
def exec_command_strict(cmd):
""" Wraps check_output splitting the input and string'ing the output"""
return bytes.decode(subprocess.check_output(cmd.split()))
def exec_command(cmd):
""" Like exec_command_strict but returns the output even if the command exited unsuccessfully"""
try:
return exec_command_strict(cmd)
except subprocess.CalledProcessError as e:
return bytes.decode(e.output)
def get_portage_tree_packages(tree_path):
""" returns a list of all packages in a portage tree/overlay in the form of cat/pkg-ver"""
pkgs = exec_command_strict("find -L {} -maxdepth 3 -type f -name *.ebuild -not -name skel.ebuild -printf %P\\n".format(tree_path))
def process_line(line):
# cat/pkg/pkg-ver.ebuild -> cat/pkg-ver
chunks = line.split("/")
end = chunks[2].replace(".ebuild", "")
return chunks[0] + "/" + end
return build_pkg_map(map(process_line, pkgs.splitlines()))
def process_emerge_output(eout):
""" transform from emerge --unordered-dispaly to cat/pkg-ver"""
def process_line(line):
return line.strip().split("] ")[1].split(":")[0]
def is_package(line):
# none of the header line have a /
return "/" in line
return map(process_line, filter(is_package, eout.splitlines()))
def get_board_packages(board):
""" gets a list of packages used by a board. valid boards are amd64-usr, sdk, and bootstrap"""
emerge_args = "--emptytree --pretend --verbose --unordered-display"
if board == "sdk":
cmd = "emerge {} @system sdk-depends sdk-extras".format(emerge_args)
elif board == "amd64-usr":
cmd = "emerge-{} {} @system board-packages".format(board, emerge_args)
elif board == "bootstrap":
pkgs = exec_command_strict("/usr/lib64/catalyst/targets/stage1/build.py")
cmd = "emerge {} {}".format(emerge_args, pkgs)
elif board == "image":
cmd = "emerge-amd64-usr {} --usepkgonly board-packages".format(emerge_args)
else:
raise "invalid board"
return build_pkg_map(process_emerge_output(exec_command(cmd)))
def print_table(report, head, line_head, line_tail, tail, joiner, pkg_joiner):
print(head)
# metapackage that acts as the header
report.insert(0, {"name": "Package",
"common": ["Common"],
"ours": ["Ours"],
"upstream": ["Upstream"],
"tag": "Tag",
"sdk": ["sdk"],
"amd64-usr": ["amd64-usr"],
"bootstrap": ["bootstrap"],
"modified": "Modified"})
for entry in report:
print(line_head + joiner.join([entry.get("name",""),
pkg_joiner.join(entry.get("common",[])),
pkg_joiner.join(entry.get("ours",[])),
pkg_joiner.join(entry.get("upstream",[])),
entry.get("tag",""),
pkg_joiner.join(entry.get("sdk", [])),
pkg_joiner.join(entry.get("amd64-usr", [])),
pkg_joiner.join(entry.get("bootstrap", [])),
entry.get("modified","")]) + line_tail)
print(tail)
def print_table_human(report):
print_table(report, "", "", "", "", "\t", " ")
def print_html_table(report):
print_table(report, "<html><body><table border=1>", "<tr><td>", "</td></tr>", "</table></body></html>", "</td><td>", "<br>")
def get_date(pkg, repo_root, fmt):
return exec_command_strict("git -C {} --no-pager log -1 --pretty=%ad --date={} {}".format(repo_root, fmt, pkg)).strip()
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--update-upstream", help="run git-pull in the gentoo mirror repo first", action="store_true")
parser.add_argument("--upstream-git", help="git uri to clone for upstream", default="https://github.com/gentoo/gentoo.git")
parser.add_argument("--upstream-path", help="path to gentoo tree", default="/mnt/host/source/src/gentoo-portage")
parser.add_argument("--portage-stable-path", help="path to portage-stable", default="/mnt/host/source/src/third_party/portage-stable")
parser.add_argument("--date-fmt", help="format for git-date to use", default="relative")
parser.add_argument("--output", help="output format, json, table, and html are accepted", default="json")
args = parser.parse_args()
if not os.path.exists(args.upstream_path):
os.makedirs(args.upstream_path)
subprocess.check_call(["git", "clone", args.upstream_git, args.upstream_path])
elif args.update_upstream:
# elif to not pull if we just cloned
subprocess.check_call(["git", "-C", args.upstream_path, "pull"])
pkg_lists = {}
sources = ["sdk", "bootstrap", "amd64-usr", "image"]
for i in sources:
pkg_lists[i] = get_board_packages(i)
gentoo_packages = get_portage_tree_packages(args.upstream_path)
packages = get_portage_tree_packages(args.portage_stable_path)
# time to make the report
report = []
for pkg, vers in packages.iteritems():
upstream = gentoo_packages.get(pkg, [])
entry = {
"name": pkg,
"common": list(set(vers).intersection(upstream)),
"ours": list(set(vers).difference(upstream)),
"upstream": list(set(upstream).difference(vers)),
"modified": get_date(pkg, args.portage_stable_path, args.date_fmt)
}
if not entry["upstream"]:
entry["tag"] = "updated"
elif entry["common"]:
entry["tag"] = "has_update"
elif pkg in gentoo_packages:
entry["tag"] = "no_ebuild_upstream"
else:
entry["tag"] = "deleted_upstream"
for src in sources:
if pkg in pkg_lists[src]:
entry[src] = pkg_lists[src][pkg]
report.append(entry)
if args.output == "json":
print(json.dumps(report))
elif args.output == "table":
print_table_human(report)
elif args.output == "html":
print_html_table(report)
else:
print("Unknown output type. Dying.")
sys.exit(2)
if __name__ == "__main__":
main()