2018-06-26 13:03:42 +04:00
import cffi
_CDEF = """
void
parseEVR ( const char * evr ,
const char * * e , const char * * v , const char * * r ) ;
int
rpmEVRcmp ( const char * const aE , const char * const aV , const char * const aR ,
const char * const aDepend ,
const char * const bE , const char * const bV , const char * const bR ,
const char * const bDepend ) ;
2021-09-02 16:33:43 +04:00
int rpmRangesOverlap ( const char * AName , const char * AEVR , int AFlags ,
const char * BName , const char * BEVR , int BFlags ) ;
2018-06-26 13:03:42 +04:00
"""
_FFI = cffi . FFI ( )
_FFI . cdef ( _CDEF )
_LIBRPM = _FFI . dlopen ( ' librpm-4.0.4.so ' )
2021-09-08 12:11:39 +04:00
_EMPTY = _FFI . new ( ' char[] ' , b ' ' )
2018-06-26 13:03:42 +04:00
def _pp_str ( p_str ) :
""" Convert FFI ' s char** to Python string.
Assumes that pointer points to a zero - terminated C - string .
Returns None if the pointer is NULL .
"""
if p_str and p_str [ 0 ] :
return _FFI . string ( p_str [ 0 ] )
return None
def parse_evr ( evr ) :
""" Returns 3-tuple (epoch, version, release) """
p_evr = _FFI . new ( ' char[] ' , evr )
e = _FFI . new ( ' char** ' )
v = _FFI . new ( ' char** ' )
r = _FFI . new ( ' char** ' )
_LIBRPM . parseEVR ( p_evr , e , v , r )
epoch = _pp_str ( e )
2021-09-08 12:11:39 +04:00
epoch = int ( epoch ) if epoch else None
2018-06-26 13:03:42 +04:00
return epoch , _pp_str ( v ) , _pp_str ( r )
2021-09-02 16:33:43 +04:00
def ranges_overlap ( aname , aevr , aflags , bname , bevr , bflags ) :
return _LIBRPM . rpmRangesOverlap (
_FFI . new ( ' char[] ' , aname ) , _FFI . new ( ' char[] ' , aevr ) , aflags ,
_FFI . new ( ' char[] ' , bname ) , _FFI . new ( ' char[] ' , bevr ) , bflags )
2021-09-08 12:11:39 +04:00
def _to_pchar ( part ) :
2021-10-02 15:20:39 +04:00
if not part :
return _FFI . NULL
if not isinstance ( part , bytes ) :
part = part . encode ( )
2021-09-08 12:11:39 +04:00
return _FFI . new ( ' char[] ' , part ) if part else _FFI . NULL
2018-06-26 13:03:42 +04:00
2021-09-08 12:11:39 +04:00
def evr_cmp ( evr1 , evr2 ) :
# Each EVR is 3-tuple 'epoch, version, release'.
# If epoch is None we replace it with '0'.
return _LIBRPM . rpmEVRcmp (
_to_pchar ( str ( evr1 [ 0 ] ) . encode ( ) if evr1 [ 0 ] else b ' 0 ' ) ,
_to_pchar ( evr1 [ 1 ] ) , _to_pchar ( evr1 [ 2 ] ) , _EMPTY ,
_to_pchar ( str ( evr2 [ 0 ] ) . encode ( ) if evr2 [ 0 ] else b ' 0 ' ) ,
_to_pchar ( evr2 [ 1 ] ) , _to_pchar ( evr2 [ 2 ] ) , _EMPTY )
2018-06-26 13:03:42 +04:00
2019-03-22 17:13:07 +04:00
def ver_cmp ( ver1 , ver2 ) :
2021-09-08 12:11:39 +04:00
return evr_cmp ( ( None , ver1 , b ' 1 ' ) , ( None , ver2 , b ' 1 ' ) )
2019-03-22 17:13:07 +04:00
2018-06-26 13:03:42 +04:00
def _tests ( ) :
2021-09-08 12:11:39 +04:00
assert parse_evr ( b ' 3:42.8.4-alt1.mips0 ' ) == ( 3 , b ' 42.8.4 ' , b ' alt1.mips0 ' )
assert parse_evr ( b ' 0:42.8.4-alt1.mips0 ' ) == ( 0 , b ' 42.8.4 ' , b ' alt1.mips0 ' )
assert parse_evr ( b ' 42.8.4-alt1.mips0 ' ) == ( None , b ' 42.8.4 ' , b ' alt1.mips0 ' )
2018-06-26 13:03:42 +04:00
2021-09-02 15:48:30 +04:00
assert parse_evr ( b ' 1.20.0-alt1_1 ' ) == ( None , b ' 1.20.0 ' , b ' alt1_1 ' )
assert parse_evr ( b ' 1:1.20.1-alt1 ' ) == ( 1 , b ' 1.20.1 ' , b ' alt1 ' )
2018-06-26 13:03:42 +04:00
2021-09-08 12:11:39 +04:00
assert evr_cmp ( ( 3 , b ' 42.8.4 ' , b ' alt1 ' ) , ( 3 , b ' 42.8.4 ' , b ' alt2 ' ) ) < 0
assert evr_cmp ( ( 3 , b ' 42.9.4 ' , b ' alt1 ' ) , ( 3 , b ' 42.8.4 ' , b ' alt2 ' ) ) > 0
assert evr_cmp ( ( 3 , b ' 42.8.4 ' , b ' alt1 ' ) , ( 3 , b ' 42.8.4 ' , b ' alt1 ' ) ) == 0
assert evr_cmp ( ( 5 , b ' 42.8.4 ' , b ' alt1 ' ) , ( 3 , b ' 42.8.4 ' , b ' alt1 ' ) ) > 0
assert evr_cmp ( ( 3 , b ' 42.9.4 ' , b ' alt1 ' ) , ( 5 , b ' 42.8.4 ' , b ' alt1 ' ) ) < 0
2021-10-02 15:20:39 +04:00
# unicode test
assert evr_cmp ( ( 3 , u ' 42.8.4 ' , u ' alt1 ' ) , ( 3 , b ' 42.8.4 ' , b ' alt1 ' ) ) == 0
2021-09-08 12:11:39 +04:00
assert evr_cmp ( ( 1 , b ' 1.2.0 ' , b ' alt1 ' ) , ( None , b ' 1.2.0 ' , b ' alt1_1 ' ) ) > 0
assert evr_cmp ( ( None , b ' 1.2.0 ' , b ' alt1_1 ' ) , ( 1 , b ' 1.2.0 ' , b ' alt1 ' ) ) < 0
2018-06-26 13:03:42 +04:00
if __name__ == ' __main__ ' :
_tests ( )