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
2021-03-21 00:57:24 +01:00
from libversion import Version
from typing import Optional
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 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
2021-03-21 00:57:24 +01:00
def odd_unstable ( version : Version , selected ) :
try :
version = version_to_list ( version . value )
except :
# Failing to parse as a list of numbers likely means the version contains a string tag like “beta”, therefore it is not a stable release.
return selected != " stable "
2017-12-25 10:46:52 +01:00
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
2021-03-21 00:57:24 +01:00
def tagged ( version : Version , selected ) :
if selected == " stable " :
return not ( " alpha " in version . value or " beta " in version . value or " rc " in version . value )
else :
return True
def no_policy ( version : Version , selected ) :
2017-12-25 10:46:52 +01:00
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 ,
2021-03-21 00:57:24 +01:00
" tagged " : tagged ,
2020-04-25 00:26:49 +02:00
" none " : no_policy ,
2017-12-25 10:46:52 +01:00
}
2020-04-25 00:26:49 +02:00
2021-03-21 00:57:24 +01:00
def make_version_policy ( version_predicate , selected , upper_bound : Optional [ Version ] ) :
2020-04-25 00:04:31 +02:00
if not upper_bound :
2021-03-21 00:57:24 +01:00
return lambda version : version_predicate ( version , selected )
2020-04-25 00:04:31 +02:00
else :
2021-03-21 00:57:24 +01:00
return lambda version : version_predicate ( version , selected ) and 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. " )
2021-03-21 00:57:24 +01:00
parser . add_argument ( " version-policy " , help = " Policy determining which versions are considered stable. GNOME packages usually denote stability by alpha/beta/rc tag in the version. For older packages, odd minor versions are unstable but there are exceptions. " , choices = version_policies . keys ( ) , nargs = " ? " , default = " tagged " )
2020-04-25 00:26:49 +02:00
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 " )
2021-03-21 00:57:24 +01:00
if upper_bound :
upper_bound = Version ( upper_bound )
2020-04-25 00:26:49 +02:00
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 )
2021-03-21 00:57:24 +01:00
versions = map ( Version , cache [ 2 ] [ package_name ] )
versions = sorted ( filter ( version_policy , versions ) )
2017-12-25 10:46:52 +01:00
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 )
2021-03-21 00:57:24 +01:00
print ( versions [ - 1 ] . value )