From 35db5ffb43fbb5a9c783a5607b5d60eccd436caf Mon Sep 17 00:00:00 2001 From: "Carl D. Roth" Date: Fri, 27 May 2016 13:06:14 -0700 Subject: [PATCH] Better implementation of 'latest' - swi file timestamp is unreliable if clock is not set correctly - extract build timestamp from manifest if available - extract timestamp-ish string from 'version' file or from swi filename --- .../loader-initrd-files/src/bin/swiget | 97 ++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) 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()