-
Notifications
You must be signed in to change notification settings - Fork 9
/
do_bulk_update.py
215 lines (172 loc) · 7 KB
/
do_bulk_update.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
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
#!/usr/bin/python3
import subprocess
import argparse
import os
import xml.etree.ElementTree as ET
# Import Crimes
import importlib.machinery
import importlib.util
loader = importlib.machinery.SourceFileLoader( 'cargo_vendor_module', './cargo_vendor' )
spec = importlib.util.spec_from_loader( 'cargo_vendor_module', loader )
cargo_vendor_module = importlib.util.module_from_spec( spec )
loader.exec_module( cargo_vendor_module )
def do_services(pkgpath):
cmd = [
"nsjail",
"--really_quiet",
"--config", "scan.cfg",
"--cwd", f"{os.getcwd()}/{pkgpath}",
"--bindmount", f"{os.getcwd()}:{os.getcwd()}",
"/usr/bin/osc", "service", "ra"
]
try:
out = subprocess.check_output(cmd, encoding='UTF-8', stderr=subprocess.STDOUT)
print(f"✅ -- services passed")
return True
except subprocess.CalledProcessError as e:
print(f"🚨 -- services failed")
print(" ".join(cmd))
print(e.stdout)
return False
def checkout_or_update(pkgname, basepath):
pkgpath = f"{basepath}:{pkgname}"
try:
if os.path.exists(pkgpath):
print(f"osc revert {pkgpath}")
# Revert/cleanup if required.
out = subprocess.check_output(["osc", "revert", "."], cwd=f"{pkgpath}")
print(f"osc clean {pkgpath}")
out = subprocess.check_output(["osc", "clean", "."], cwd=f"{pkgpath}")
print(f"osc up {pkgpath}")
out = subprocess.check_output(["osc", "up", f"{pkgpath}"])
else:
print(f"osc bco {pkgname}")
out = subprocess.check_output(["osc", "bco", f"{pkgname}"])
except subprocess.CalledProcessError as e:
print(f"Failed to checkout or update {pkgname}")
print(e.stdout)
raise e
print(f"done")
return pkgpath
def does_have_cargo_vendor(pkgpath):
service = f"{pkgpath}/_service"
has_vendor = False
has_vendor_update = False
srctar = None
srcdir = None
compression = None
if os.path.exists(service):
tree = ET.parse(service)
root_node = tree.getroot()
for tag in root_node.findall('service'):
if tag.attrib['name'] == 'cargo_audit':
root_node.remove(tag)
if tag.attrib['name'] == 'cargo_vendor':
has_vendor = True
for attr in tag:
# if attr.attrib['name'] == 'update' and attr.text == 'true':
# has_vendor_update = True
if attr.attrib['name'] == 'srctar':
srctar = attr.text
if attr.attrib['name'] == 'srcdir':
srcdir = attr.text
if attr.attrib['name'] == 'compression':
compression = attr.text
# if not has_vendor_update:
# print("Forcing update to true in _service")
# sub = ET.SubElement(tag, 'param')
# sub.set('name', 'update')
# sub.text = 'true'
root_node.remove(tag)
# Rewrite the _service to include vendor_update = true
# and to temporarily remove audit.
tree.write(service)
return (has_vendor, srctar, srcdir, compression)
def attempt_update(pkgpath, message):
print("---")
print(f"Attempting update for {pkgpath}")
(has_vendor, srctar, srcdir, compression) = does_have_cargo_vendor(pkgpath)
print(f"has_vendor: {has_vendor}, srctar: {srctar}, srcdir: {srcdir}")
if not has_vendor:
print(f"ERROR ⚠️ : {pkgpath} is not setup for cargo vendor!")
return False
print(f"Running services in {pkgpath}")
if not do_services(pkgpath):
print(f"Services reported a failure, this should be checked ...")
# return False
if srcdir and srctar is None:
# We can use srcdir to have a guess what tar we need to use.
content = os.listdir(pkgpath)
maybe_src = [
x for x in content
if x.startswith(srcdir) and '.tar' in x and 'vendor' not in x and not x.endswith('.asc')
]
if len(maybe_src) != 1:
print(f"ERROR ⚠️ : confused! Not sure what tar to use in {pkgpath} {maybe_src}")
print(f"This likely indicates a wacky package config that depends on services")
return False
srctar = maybe_src[0]
srctar = f"{pkgpath}/{srctar}"
print(f"Running vendor against {srctar} ... ")
try:
vendor_tarfile = cargo_vendor_module.do_cargo_vendor(None, srctar, outdir=pkgpath, compression=compression)
except Exception as e:
print("ERROR %s" % e)
vendor_tarfile = None
if not vendor_tarfile:
print(f"Failed to run cargo vendor 🥺 ")
return False
out = subprocess.check_output(["osc", "status"], cwd=f"{pkgpath}", encoding='UTF-8', stderr=subprocess.STDOUT)
print(out)
revert = []
changed = False
for line in out.split('\n'):
if line.startswith('M'):
if 'vendor' in line:
changed = True
elif 'cargo_config' in line:
# skipp, we don't want to revert this
pass
else:
print("Reverting %s" % line.split()[1].strip())
revert.append(line.split()[1].strip())
for item in revert:
subprocess.check_output(["osc", "revert", item], cwd=f"{pkgpath}")
return changed
def attempt_submit(pkgpath, message, yolo=False):
try:
print("---")
if not yolo:
print("You must manually run: ")
print(f"osc vc -m '{message}' {pkgpath}")
if yolo:
out = subprocess.check_output(["osc", "vc", "-m", message], cwd=f"{pkgpath}")
print(f"osc ci -m '{message}' {pkgpath}")
if yolo:
out = subprocess.check_output(["osc", "ci", "-m", message], cwd=f"{pkgpath}")
print(f"osc sr -m '{message}' {pkgpath}")
if yolo:
# out = subprocess.check_output(["osc", "sr", "-m", message], cwd=f"{pkgpath}")
pass
return f"osc sr -m '{message}' {pkgpath}"
except Exception as e:
print("ERROR %s" % e)
return None
if __name__ == '__main__':
print("Started OBS cargo vendor bulk updater ...")
basepath = "home:firstyear:branches"
parser = argparse.ArgumentParser(
description="update OBS gooderer",
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument('--yolo', action='store_true')
parser.add_argument('--message', nargs='?', default="Automatic update of vendored dependencies")
parser.add_argument('packages', nargs='+')
args = parser.parse_args()
print(args)
pkgpaths = [checkout_or_update(pkgname, basepath) for pkgname in args.packages]
submit_req = [attempt_update(pkgpath, args.message) for pkgpath in pkgpaths]
submited_req = [attempt_submit(pkgpath, args.message, args.yolo) for pkgpath in pkgpaths]
print("--- complete")
for sr in sorted(submited_req):
print(sr)