diff --git a/packages/base/all/initrds/loader-initrd-files/src/bin/swiget b/packages/base/all/initrds/loader-initrd-files/src/bin/swiget index 0e0a23f3..34615678 100755 --- a/packages/base/all/initrds/loader-initrd-files/src/bin/swiget +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/swiget @@ -12,6 +12,9 @@ import subprocess import shutil import logging import tempfile +import re +import json +import zipfile import onl.install.InstallUtils MountContext = onl.install.InstallUtils.MountContext @@ -24,6 +27,98 @@ OnlMountManager = onl.mounts.OnlMountManager import onl.network HostInfo = onl.network.HostInfo +SWI_TIMESTAMP_FMT = "%Y-%m-%d.%H:%M" + +SWI_TIMESTAMP_RE = re.compile(r""" + [0-9][0-9][0-9][0-9] [-] [0-9][0-9] [-] [0-9][0-9] + [.] + [0-9][0-9] [:] [0-9][0-9] +""", re.VERBOSE) + +SWI_FNAME_TIMESTAMP_FMT = "%Y-%m-%d.%H%M" + +SWI_FNAME_TIMESTAMP_RE = re.compile(r""" + [0-9][0-9][0-9][0-9] [-] [0-9][0-9] [-] [0-9][0-9] + [.] + [0-9][0-9] [0-9][0-9] +""", re.VERBOSE) + +def versionSortKey(vstr): + + m = SWI_TIMESTAMP_RE.search(vstr) + if m is not None: + try: + return time.mktime(time.strptime(m.group(0), SWI_TIMESTAMP_FMT)) + except ValueError: + pass + + m = SWI_FNAME_TIMESTAMP_RE.search(vstr) + if m is not None: + try: + return time.mktime(time.strptime(m.group(0), SWI_FNAME_TIMESTAMP_FMT)) + except ValueError: + pass + + return None + +def manifestSortKey(mdata): + + mdata = mdata.get('version', {}) + + vstr = mdata.get('BUILD_TIMESTAMP', None) + if vstr is not None: + try: + return time.mktime(time.strptime(vstr, SWI_TIMESTAMP_FMT)) + except ValueError: + pass + + vstr = mdata.get('FNAME_BUILD_TIMESTAMP', None) + if vstr is not None: + try: + return time.mktime(time.strptime(vstr, SWI_FNAME_TIMESTAMP_FMT)) + except ValueError: + pass + + return None + +def swiSortKey(swiPath): + + try: + zf = zipfile.ZipFile(swiPath, "r") + except zipfile.BadZipFile: + return os.path.getmtime(swiPath) + + try: + fd = zf.open("manifest.json", "r") + except KeyError: + fd = None + if fd is not None: + data = json.load(fd) + fd.close() + else: + data = {} + ts = manifestSortKey(data) + if ts is not None: return ts + + try: + fd = zf.open("version", "r") + except KeyError: + fd = None + if fd is not None: + vstr = fd.read() + fd.close() + else: + vstr = "" + ts = versionSortKey(vstr) + if ts is not None: return ts + + ts = versionSortKey(swiPath) + if ts is not None: return ts + # maybe the timestamp is embedded into the filename + + # else, use the filesytem mtime, which is less reliable + return os.path.getmtime(swiPath) + class Runner(onl.install.InstallUtils.SubprocessMixin): def __init__(self, log): @@ -188,7 +283,7 @@ class Runner(onl.install.InstallUtils.SubprocessMixin): def latest(d): l = [x for x in os.listdir(d) if x.endswith('.swi')] l = [os.path.join(d, x) for x in l] - l.sort(key=os.path.getmtime) + l.sort(key=swiSortKey) return l[-1] pm = ProcMountsParser()