Line
Link Here
|
0 |
-- vartree.py |
0 |
++ vartree.py |
Lines 1081-1086
Link Here
|
1081 |
new_contents = pkg.getcontents().copy() |
1081 |
new_contents = pkg.getcontents().copy() |
1082 |
removed = 0 |
1082 |
removed = 0 |
1083 |
|
1083 |
|
|
|
1084 |
self.startContentsRemoval(pkg.dbdir) |
1084 |
for filename in paths: |
1085 |
for filename in paths: |
1085 |
filename = _unicode_decode(filename, |
1086 |
filename = _unicode_decode(filename, |
1086 |
encoding=_encodings['content'], errors='strict') |
1087 |
encoding=_encodings['content'], errors='strict') |
Lines 1109-1114
Link Here
|
1109 |
self.removeFromContentsMeta(pkg.dbdir, index, "ATTRS_CAPS") |
1110 |
self.removeFromContentsMeta(pkg.dbdir, index, "ATTRS_CAPS") |
1110 |
removed += 1 |
1111 |
removed += 1 |
1111 |
|
1112 |
|
|
|
1113 |
self.stopContentsRemoval(pkg.dbdir) |
1112 |
if removed: |
1114 |
if removed: |
1113 |
# Also remove corresponding NEEDED lines, so that they do |
1115 |
# Also remove corresponding NEEDED lines, so that they do |
1114 |
# no corrupt LinkageMap data for preserve-libs. |
1116 |
# no corrupt LinkageMap data for preserve-libs. |
Lines 1142-1147
Link Here
|
1142 |
|
1144 |
|
1143 |
self.writeContentsToContentsFile(pkg, new_contents, new_needed=new_needed) |
1145 |
self.writeContentsToContentsFile(pkg, new_contents, new_needed=new_needed) |
1144 |
|
1146 |
|
|
|
1147 |
def startContentsRemoval(self, vdbdir): |
1148 |
contents_dir = os.path.join(vdbdir, "contents.d") |
1149 |
transaction_dir = os.path.join(vdbdir, "contents.d~") |
1150 |
manifest_file = os.path.join(contents_dir, "Manifest") |
1151 |
manifest_lines = "" |
1152 |
|
1153 |
# Clean previously unfinished transaction @TODO also: either roll-back or roll-forward |
1154 |
if os.path.isdir(transaction_dir): |
1155 |
shutil.rmtree(transaction_dir) |
1156 |
if os.path.isdir(contents_dir): |
1157 |
shutil.rmtree(contents_dir) |
1158 |
|
1159 |
# Set up transaction |
1160 |
os.mkdir(transaction_dir, 0o644) |
1161 |
files = [ |
1162 |
"CONTENTS_DIGESTS_SHA1", |
1163 |
"CONTENTS_DIGESTS_SHA256", |
1164 |
"CONTENTS_DIGESTS_SHA512", |
1165 |
"CONTENTS_MODES", |
1166 |
"CONTENTS_ATTRS_PAX", |
1167 |
"CONTENTS_ATTRS_CAPS" |
1168 |
] |
1169 |
for f in files: |
1170 |
fname_src = os.path.join(vdbdir, f) |
1171 |
fname_dest = os.path.join(transaction_dir, f) |
1172 |
|
1173 |
# Gracefully handle non-existent files |
1174 |
if os.path.isfile(fname_src): |
1175 |
shutil.copy2(fname_src, fname_dest) |
1176 |
manifest_lines += f + "\n" |
1177 |
manifest_lines += portage.checksum.perform_checksum(fname_src, "SHA1", 0)[0] + "\n" |
1178 |
|
1179 |
# Write Manifest-file of transaction |
1180 |
os.mkdir(contents_dir, 0o644) |
1181 |
with open(manifest_file,"w") as f: |
1182 |
f.write(manifest_lines) |
1183 |
|
1184 |
def stopContentsRemoval(self, vdbdir): |
1185 |
contents_dir = os.path.join(vdbdir, "contents.d") |
1186 |
transaction_dir = os.path.join(vdbdir, "contents.d~") |
1187 |
digests = [] |
1188 |
transaction_files = [] |
1189 |
all_files = [ |
1190 |
"CONTENTS_DIGESTS_SHA1", |
1191 |
"CONTENTS_DIGESTS_SHA256", |
1192 |
"CONTENTS_DIGESTS_SHA512", |
1193 |
"CONTENTS_MODES", |
1194 |
"CONTENTS_ATTRS_PAX", |
1195 |
"CONTENTS_ATTRS_CAPS" |
1196 |
] |
1197 |
|
1198 |
if not os.path.isdir(transaction_dir): |
1199 |
print("Failed creating transaction dir") |
1200 |
sys.exit(1) |
1201 |
|
1202 |
# Read Manifest-file of contents |
1203 |
manifest_file = os.path.join(contents_dir, "Manifest") |
1204 |
if os.path.isfile(manifest_file): |
1205 |
with open(manifest_file,"r") as f: |
1206 |
lines = f.read().splitlines() |
1207 |
|
1208 |
for i, line in enumerate(lines): |
1209 |
if (i%2) == 0: |
1210 |
transaction_files.append(line) |
1211 |
else: |
1212 |
digests.append(line) |
1213 |
|
1214 |
# Check transactiondir against Manifest |
1215 |
for f in transaction_files: |
1216 |
file = os.path.join(transaction_dir, f) |
1217 |
if not os.path.isfile(file): |
1218 |
print("Manifest contains non-existing file '"+file+"'") |
1219 |
sys.exit(1) |
1220 |
|
1221 |
# Setup contents_dir with links of vdbdir files |
1222 |
for i, f in enumerate(transaction_files): |
1223 |
fname_src = os.path.join(vdbdir, f) |
1224 |
fname_dest = os.path.join(contents_dir, f) |
1225 |
|
1226 |
# Gracefully handle non-existent files |
1227 |
if os.path.isfile(fname_src): |
1228 |
if portage.checksum.perform_checksum(fname_src, "SHA1", 0)[0] != digests[i]: |
1229 |
print("According to Manifest, file in vdbdir was modified '" + fname_src + "'") |
1230 |
sys.exit(1) |
1231 |
else: |
1232 |
os.link(fname_src, fname_dest) |
1233 |
else: |
1234 |
print("File in Manifest no longer found in vdbdir '"+f+"'") |
1235 |
sys.exit(1) |
1236 |
|
1237 |
# Sync contents_dir and transaction_dir to disk |
1238 |
if platform.system() == "Linux": |
1239 |
paths = [] |
1240 |
for f in os.listdir(transaction_dir): |
1241 |
paths.append(os.path.join(transaction_dir, f)) |
1242 |
for f in os.listdir(contents_dir): |
1243 |
paths.append(os.path.join(contents_dir, f)) |
1244 |
paths = tuple(paths) |
1245 |
|
1246 |
proc = SyncfsProcess(paths=paths, |
1247 |
scheduler=( |
1248 |
SchedulerInterface(portage._internal_caller and |
1249 |
global_event_loop() or EventLoop(main=False)) |
1250 |
)) |
1251 |
|
1252 |
proc.start() |
1253 |
returncode = proc.wait() |
1254 |
|
1255 |
# Link from transaction_dir |
1256 |
for f in transaction_files: |
1257 |
fname_src = os.path.join(transaction_dir, f) |
1258 |
fname_dest = os.path.join(vdbdir, f+"~") |
1259 |
|
1260 |
# Gracefully handle non-existent files |
1261 |
if os.path.isfile(fname_src): |
1262 |
os.link(fname_src, fname_dest) |
1263 |
else: |
1264 |
print("Manifest contains file that no longer exists '"+f+"'") |
1265 |
sys.exit(1) |
1266 |
|
1267 |
# Sync contents_dir and transaction_dir to disk |
1268 |
if platform.system() == "Linux": |
1269 |
paths = [] |
1270 |
for f in transaction_files: |
1271 |
# Gracefully handle non-existent files |
1272 |
if os.path.isfile(os.path.join(vdbdir, f+"~")): |
1273 |
paths.append(os.path.join(vdbdir, f+"~")) |
1274 |
else: |
1275 |
print("Manifest contains file that no longer exists '"+f+"'") |
1276 |
sys.exit(1) |
1277 |
paths = tuple(paths) |
1278 |
|
1279 |
proc = SyncfsProcess(paths=paths, |
1280 |
scheduler=( |
1281 |
SchedulerInterface(portage._internal_caller and |
1282 |
global_event_loop() or EventLoop(main=False)) |
1283 |
)) |
1284 |
|
1285 |
proc.start() |
1286 |
returncode = proc.wait() |
1287 |
|
1288 |
# Rename |
1289 |
for f in transaction_files: |
1290 |
fname_src = os.path.join(vdbdir, f+"~") |
1291 |
fname_dest = os.path.join(vdbdir, f) |
1292 |
|
1293 |
# Gracefully handle non-existent files |
1294 |
if os.path.isfile(fname_src): |
1295 |
os.rename(fname_src, fname_dest) #atomic rename, doesn't require sync |
1296 |
else: |
1297 |
print("Manifest contains file that no longer exists '"+f+"'") |
1298 |
sys.exit(1) |
1299 |
|
1300 |
shutil.rmtree(transaction_dir) |
1301 |
shutil.rmtree(contents_dir) |
1302 |
|
1145 |
def removeFromContentsMeta(self, vdbdir, index, type): |
1303 |
def removeFromContentsMeta(self, vdbdir, index, type): |
1146 |
contents_file = "" |
1304 |
contents_file = "" |
1147 |
if (type in |
1305 |
if (type in |
Lines 1151-1157
Link Here
|
1151 |
"MODES", |
1309 |
"MODES", |
1152 |
"ATTRS_PAX", |
1310 |
"ATTRS_PAX", |
1153 |
"ATTRS_CAPS"}): |
1311 |
"ATTRS_CAPS"}): |
1154 |
contents_file = os.path.join(vdbdir, "CONTENTS_"+type) |
1312 |
contents_file = os.path.join(os.path.join(vdbdir, "contents.d~"),"CONTENTS_"+type) |
1155 |
else: |
1313 |
else: |
1156 |
print("ERROR removeFromContentsMeta() got passed unexpected type "+type) |
1314 |
print("ERROR removeFromContentsMeta() got passed unexpected type "+type) |
1157 |
|
1315 |
|