summaryrefslogblamecommitdiff
path: root/version.py
blob: 1de0442d7a6a3a19758b8f9f51a9b945574bb489 (plain) (tree)










































































                                                                       
#!/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