ports/lang/rust/files/rehash.py

161 lines
4.4 KiB
Python

#!/usr/bin/env python3
import re
import os
RE_splitlib = re.compile('lib([^-]+)-([0-9a-fA-F]+)\.(so|rlib)')
oldhashes = {} # list of old hashes already assigned to new value
newhashes = {} # list of libname associated to a (list of) new hashes
# split a filename in components ("libNAME-HASH.ext")
def splitlib(filename):
m = RE_splitlib.fullmatch(filename)
if m is None:
raise Exception("splitlib failed: {:s}".format(filename))
return m[1], m[2]
# register newhash inside newhashes
def register_newhashes(base_hash, args):
i = 0
for libname in args:
newhash = "{:s}{:02x}".format(base_hash, i)
i = i + 1
# add newhash in the list associated to libname
newhashes.setdefault(libname, []).append(newhash)
def getnewhash(libname, oldhash):
# check if oldhash is already assigned
if oldhash in oldhashes:
return oldhashes[oldhash]
try:
# get the new hash (and remove it from the list)
newhash = newhashes[libname].pop()
# add it in assigned oldhashes
oldhashes[oldhash] = newhash
return newhash
except KeyError:
raise Exception("unknown libname in newhashes: {:s}".format(
libname,
))
except IndexError:
raise Exception("not enough newhashes for libname: {:s}".format(
libname,
))
# generic function to walk library directory
def walk_directory(dirname, proc):
with os.scandir(dirname) as dir:
for entry in dir:
if not entry.is_file():
continue
libname, hash = splitlib(entry.name)
# call proc
proc(entry.name, libname, hash)
# register old hashes from walk a directory to assign a new hash
def register_oldhashes_directory(dirname):
def register_oldhashes_file(filename, libname, oldhash):
# construct the fullpath
fullpath = dirname + '/' + filename
# get newhash for libname
newhash = getnewhash(libname, oldhash)
# debug information
print("{:s}: {:s}".format(newhash, fullpath))
walk_directory(dirname, register_oldhashes_file)
# rehash a directory
def rehash_directory(dirname):
def rehash_file(oldfilename, libname, oldhash):
# get back newhash
newhash = getnewhash(libname, oldhash)
newfilename = oldfilename.replace(oldhash, newhash)
# get fullpath for old and new
oldpath = dirname + '/' + oldfilename
newpath = dirname + '/' + newfilename
# rename the file
os.rename(oldpath, newpath)
print("renaming files in '{:s}'".format(dirname))
walk_directory(dirname, rehash_file)
# change the hash inside all the files (libraries and binaries)
def change_hash_in_files():
from tempfile import NamedTemporaryFile
with NamedTemporaryFile() as tempfile:
# generate a sedfile from oldhash to newhash
for oldhash, newhash in oldhashes.items():
sedline = "s/{:s}/{:s}/g\n".format(
oldhash,
newhash,
)
tempfile.write(bytes(sedline, 'utf8'))
# flush to ensure the sedfile to be consistent
tempfile.flush()
# change the content of all files
sedcmd = "find . -type f -exec sed -i -f {:s} {:s} +".format(
tempfile.name,
"{}",
)
print("applying content change...")
if os.system(sedcmd) != 0:
raise Exception("sed command failed: {:s}".format(sedcmd))
if __name__ == '__main__':
from sys import argv
if len(argv) < 2:
print("usage: rehash.py triple name=hash [...]")
sys.exit(1)
triple_arch = argv[1]
base_hash = argv[2]
liblist = argv[3:]
liblist.sort()
register_newhashes(base_hash, liblist)
# list of directories containing files to rehash
dirlist = [
"lib",
"lib/rustlib/{:s}/lib".format(triple_arch),
]
# register oldhashes by walking directories
for dirname in dirlist:
register_oldhashes_directory(dirname)
# check that all new hashes are assigned
for libname, hashes in newhashes.items():
if len(hashes) != 0:
print("WARNING: unassigned hashes ({:d}) for '{:s}'".format(
len(hashes),
libname,
))
# rehash the files
for dirname in dirlist:
rehash_directory(dirname)
change_hash_in_files()