2017-12-25 10:46:52 +01:00
import argparse
2020-04-25 00:04:31 +02:00
import math
2017-12-25 10:46:52 +01:00
import json
import requests
import sys
2020-04-25 00:26:49 +02:00
2017-12-25 10:46:52 +01:00
def version_to_list ( version ) :
2020-04-25 00:26:49 +02:00
return list ( map ( int , version . split ( " . " ) ) )
2017-12-25 10:46:52 +01:00
def odd_unstable ( version_str , selected ) :
version = version_to_list ( version_str )
if len ( version ) < 2 :
return True
even = version [ 1 ] % 2 == 0
2018-11-20 21:53:55 +01:00
prerelease = ( version [ 1 ] > = 90 and version [ 1 ] < 100 ) or ( version [ 1 ] > = 900 and version [ 1 ] < 1000 )
2018-03-03 06:02:38 +01:00
stable = even and not prerelease
2020-04-25 00:26:49 +02:00
if selected == " stable " :
2018-03-03 06:02:38 +01:00
return stable
2017-12-25 10:46:52 +01:00
else :
2018-03-03 05:49:47 +01:00
return True
2017-12-25 10:46:52 +01:00
2020-04-25 00:26:49 +02:00
2017-12-25 10:46:52 +01:00
def no_policy ( version , selected ) :
return True
2020-04-25 00:26:49 +02:00
2017-12-25 10:46:52 +01:00
version_policies = {
2020-04-25 00:26:49 +02:00
" odd-unstable " : odd_unstable ,
" none " : no_policy ,
2017-12-25 10:46:52 +01:00
}
2020-04-25 00:26:49 +02:00
2020-04-25 00:04:31 +02:00
def make_version_policy ( version_predicate , selected , upper_bound ) :
if not upper_bound :
upper_bound = [ math . inf , math . inf ]
else :
upper_bound = version_to_list ( upper_bound )
return lambda version : version_predicate ( version , selected ) and version_to_list ( version ) < upper_bound
2017-12-25 10:46:52 +01:00
2020-04-25 00:26:49 +02:00
parser = argparse . ArgumentParser ( description = " Find latest version for a GNOME package by crawling their release server. " )
parser . add_argument ( " package-name " , help = " Name of the directory in https://ftp.gnome.org/pub/GNOME/sources/ containing the package. " )
parser . add_argument ( " version-policy " , help = " Policy determining which versions are considered stable. For most GNOME packages, odd minor versions are unstable but there are exceptions. " , choices = version_policies . keys ( ) , nargs = " ? " , default = " odd-unstable " )
parser . add_argument ( " requested-release " , help = " Most of the time, we will want to update to stable version but sometimes it is useful to test. " , choices = [ " stable " , " unstable " ] , nargs = " ? " , default = " stable " )
parser . add_argument ( " --upper-bound " , dest = " upper-bound " , help = " Only look for versions older than this one (useful for pinning dependencies). " )
2017-12-25 10:46:52 +01:00
2020-04-25 00:26:49 +02:00
if __name__ == " __main__ " :
2017-12-25 10:46:52 +01:00
args = parser . parse_args ( )
2020-04-25 00:26:49 +02:00
package_name = getattr ( args , " package-name " )
requested_release = getattr ( args , " requested-release " )
upper_bound = getattr ( args , " upper-bound " )
version_predicate = version_policies [ getattr ( args , " version-policy " ) ]
2020-04-25 00:04:31 +02:00
version_policy = make_version_policy ( version_predicate , requested_release , upper_bound )
2017-12-25 10:46:52 +01:00
# The structure of cache.json: https://gitlab.gnome.org/Infrastructure/sysadmin-bin/blob/master/ftpadmin#L762
2020-04-25 00:26:49 +02:00
cache = json . loads ( requests . get ( f " https://ftp.gnome.org/pub/GNOME/sources/ { package_name } /cache.json " ) . text )
2017-12-25 10:46:52 +01:00
if type ( cache ) != list or cache [ 0 ] != 4 :
2020-04-25 00:26:49 +02:00
print ( " Unknown format of cache.json file. " , file = sys . stderr )
2017-12-25 10:46:52 +01:00
sys . exit ( 1 )
versions = cache [ 2 ] [ package_name ]
versions = sorted ( filter ( version_policy , versions ) , key = version_to_list )
if len ( versions ) == 0 :
2020-04-25 00:26:49 +02:00
print ( " No versions matched. " , file = sys . stderr )
2017-12-25 10:46:52 +01:00
sys . exit ( 1 )
print ( versions [ - 1 ] )