#!/usr/bin/env python3 # # Copyright © 2018-2020 Adélie Linux team. All rights reserved. # NCSA license. # import ctypes import enum import functools class APK_VER(enum.IntFlag): UNKNOWN = 0 EQUAL = 1 LESS = 2 GREATER = 4 FUZZY = 8 APK_OPS = { ">=": APK_VER.GREATER | APK_VER.EQUAL, "<=": APK_VER.LESS | APK_VER.EQUAL, ">~": APK_VER.GREATER | APK_VER.EQUAL, "<~": APK_VER.LESS | APK_VER.EQUAL, ">": APK_VER.GREATER, "<": APK_VER.LESS, "=": APK_VER.EQUAL, "~": APK_VER.EQUAL, } class _apk_blob_t(ctypes.Structure): _fields_ = [ ("len", ctypes.c_long), ("ptr", ctypes.c_char_p), ] def __init__(self, s): s = s.encode("utf-8") self.len = len(s) self.ptr = ctypes.c_char_p(s) def vercmp(a, b, fuzzy=False): a = _apk_blob_t(a) b = _apk_blob_t(b) fuzzy = 1 if fuzzy else 0 return APK_VER(_LIBAPK.apk_version_compare_blob_fuzzy(a, b, fuzzy)) @functools.cmp_to_key def verkey(a, b): r = vercmp(a, b) if r == APK_VER.LESS: return -1 if r == APK_VER.EQUAL: return 0 if r == APK_VER.GREATER: return 1 return None def ver_is(a, op, b): if op not in APK_OPS: raise ValueError("Invalid op " + repr(op)) fuzzy = "~" in op return vercmp(a, b, fuzzy) & APK_OPS[op] def is_older(old, new): return vercmp(old, new) == APK_VER.LESS def is_same(old, new): return vercmp(old, new) == APK_VER.EQUAL _LIBAPK = ctypes.CDLL("libapk.so") _LIBAPK.apk_version_compare_blob_fuzzy.argtypes = [ _apk_blob_t, _apk_blob_t, ctypes.c_int, ] _LIBAPK.apk_version_compare_blob_fuzzy.restype = ctypes.c_int