diff --git a/advisors/simple-update-robot.py b/advisors/simple-update-robot.py index fff6208286abc6d35276b6fabe49a5388e1de2bd..054ddd1f961bc7655956543cfcaaf3bd0efa3b3e 100755 --- a/advisors/simple-update-robot.py +++ b/advisors/simple-update-robot.py @@ -21,6 +21,7 @@ import subprocess import os.path import re import datetime +import version_recommend def download_source_url(spec, o_ver, n_ver): """ @@ -91,7 +92,6 @@ def create_spec(repo, spec_str, o_ver, n_ver, src_fn=None): if __name__ == "__main__": pars = argparse.ArgumentParser() pars.add_argument("pkg", type=str, help="The package to be upgraded") - pars.add_argument("-o", "--old_version", type=str, help="Current upstream version of package") pars.add_argument("-n", "--new_version", type=str, help="New upstream version of package will be upgrade to") pars.add_argument("-s", "--create_spec", help="Create spec file", action="store_true") pars.add_argument("-d", "--download", help="Download upstream source code", action="store_true") @@ -101,12 +101,15 @@ if __name__ == "__main__": args = pars.parse_args() my_gitee = gitee.Gitee() + my_version = version_recommend.VersionType() spec_string= my_gitee.get_spec(args.pkg) s_spec = Spec.from_string(spec_string) + cur_ver = replace_macros(s_spec.version, s_spec) if args.fork: - my_gitee.fork_repo(args.pkg) + if not my_gitee.fork_repo(args.pkg): + print("The repo of {pkg} seems to have been forked.".format(pkg=args.pkg)) if args.clone: user=my_gitee.token["user"] @@ -114,7 +117,7 @@ if __name__ == "__main__": os.chdir(args.pkg) if args.download: - source_file = download_source_url(s_spec, args.old_version, args.new_version) + source_file = download_source_url(s_spec, cur_ver, args.new_version) if source_file: print(source_file) else: @@ -130,7 +133,11 @@ if __name__ == "__main__": print("I'm too naive to handle complicated package.") print("This package has multiple in-house patches.") sys.exit(1) - create_spec(args.pkg, spec_string, args.old_version, args.new_version) + if(my_version.compare(args.new_version, cur_ver) ==1): + create_spec(args.pkg, spec_string, cur_ver, args.new_version) + else: + print("Please check version of {pkg} will upgrade to, it's current version is {version}.".format( + pkg=args.pkg, version=cur_ver)) if args.PR: my_gitee.create_pr(my_gitee.token["user"], args.pkg) diff --git a/advisors/version_recommend.py b/advisors/version_recommend.py index c3f23414af3d133cea18b06fc2154d3e62993a50..d4b0d7c848acac74864a2bc9f4e96efe708dbf94 100755 --- a/advisors/version_recommend.py +++ b/advisors/version_recommend.py @@ -7,23 +7,84 @@ from typing import List __ALL__ = ["VersionRecommend"] +""" + +The base class of the version recommend, used to get the latest version and maintain version. + +""" + + class VersionType(object): + """Base class for version recommend""" def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ self._version_type = None def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns: None + :raises: None + """ pass def latest_version(self, version_entry): + """ + Get the latest version. + + :param version_entry: Package version list + :returns: None + :raises: None + """ version_entry.sort(reverse=True) return version_entry[0] def maintain_version(self, version_entry, current_version, pkg_type): + """ + Get the maintain version. + + :param version_entry: Package version list + :param current_version: Current version + :param pkg_type: Package type + :returns : Maintain version + :raises: None + """ _ = version_entry, pkg_type return current_version - def _max(self, z1, z2): + def compare(self, z1, z2): + """ + Get the max version. + + :param z1: The first version + :param z2: The second version + :returns 1: z1 great then z2 + :return -1: z2 great then z1 + :return 0: z1 equal then z2 + :raises: None + """ + return self._compare(self, z1, z2) + + def _compare(self, z1, z2): + """ + Get the max version. + + :param z1: The first version + :param z2: The second version + :returns 1: z1 great then z2 + :return -1: z2 great then z1 + :return 0: z1 equal then z2 + :raises: None + """ d1 = tuple(self._split(z1)) # 第一个参数版本号拆分,获取里面的数字/字母,得到序列 d2 = tuple(self._split(z2)) # 第二个参数版本号拆分,获取里面的数字/字母,得到序列 len1 = len(d1) @@ -42,14 +103,30 @@ class VersionType(object): return -1 if len1 > len2: return 1 - else: + elif len1 < len2: return -1 + else: + return 0 def get_version_mode(self): + """ + Get the version mode. + + :param: None + :returns: Version type + :raises: None + """ return self._version_type def _split(self, x): - for f, s in re.findall(r'([\d.]+)|([^\d.]+)', x): + """ + Split the input args. + + :param x: Input args + :returns: The split result + :raises: None + """ + for f, s in re.findall(r'([\d]+)|([^\d.]+)', x): if f: float(f) yield f @@ -58,8 +135,17 @@ class VersionType(object): class VersionTypeXYZW(VersionType): + """Version type Class for x.y.z.w""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 4: # 通过 '.'分割后,应该剩下4位 @@ -75,6 +161,15 @@ class VersionTypeXYZW(VersionType): return True def maintain_version(self, version_entry, current_version, pkg_type): + """ + Get the maintain version. + + :param version_entry: Package version list + :param current_version: Current version + :param pkg_type: Package type + :returns : Maintain version + :raises: None + """ if len(version_entry) == 1: # 仅一个版本,当前即为最新版本 return version_entry[0] @@ -94,13 +189,20 @@ class VersionTypeXYZW(VersionType): if len(version) <= 3: continue - if self._max(version[3], w) > 0: + if self._compare(version[3], w) > 0: w = version[3] xyz.append(w) return '.'.join(xyz) def latest_version(self, version_entry): + """ + Get latest version. + + :param version_entry: Package version list + :returns: latest version + :raises: None + """ if len(version_entry) == 1: # 仅一个版本,当前即为最新版本 return version_entry[0] version_list = [] @@ -108,7 +210,7 @@ class VersionTypeXYZW(VersionType): version_list.append(re.split(r'[._-]', version)) # 将 version 拆分为列表,方便后续比较 x = '0' for version in version_list: # 第一轮比较取出最大的第一位 - if self._max(x, version[0]) < 0: + if self._compare(x, version[0]) < 0: x = version[0] version_candidate = [] @@ -124,7 +226,7 @@ class VersionTypeXYZW(VersionType): for version in version_list: # 第二轮比较取出最大的第二位 if len(version) <= 1: # 过滤仅一位的版本号 continue - if self._max(y, version[1]) < 0: + if self._compare(y, version[1]) < 0: y = version[1] version_candidate.clear() @@ -140,7 +242,7 @@ class VersionTypeXYZW(VersionType): for version in version_list: # 第三轮比较取出最大的第三位 if len(version) <= 2: # 过滤仅二位的版本号 continue - if self._max(z, version[2]) < 0: + if self._compare(z, version[2]) < 0: z = version[2] version_candidate.clear() @@ -158,7 +260,7 @@ class VersionTypeXYZW(VersionType): for version in version_list: # 最后一位最大版本必须惟一,直接返回结果 if len(version) <= 3: # 过滤仅三位的版本号 continue - if self._max(w, version[3]) < 0: + if self._compare(w, version[3]) < 0: w = version[3] for version in version_list: # 最后一位最大版本必须惟一,直接返回结果 @@ -170,13 +272,29 @@ class VersionTypeXYZW(VersionType): return '' def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'x.y.z.w' class VersionTypeXYZ(VersionType): + """Version type Class for x.y.z""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 3: # 通过 '.'分割后,应该剩下3位 @@ -190,6 +308,15 @@ class VersionTypeXYZ(VersionType): return True def maintain_version(self, version_entry, current_version, pkg_type): + """ + Get the maintain version. + + :param version_entry: Package version list + :param current_version: Current version + :param pkg_type: Package type + :returns : Maintain version + :raises: None + """ if len(version_entry) == 1: # 仅一个版本,当前即为最新版本 return version_entry[0] @@ -209,13 +336,20 @@ class VersionTypeXYZ(VersionType): if len(version) <= 2: continue - if self._max(version[2], z) > 0: + if self._compare(version[2], z) > 0: z = version[2] xy.append(z) return '.'.join(xy) def latest_version(self, version_entry): + """ + Get latest version. + + :param version_entry: Package version list + :returns: latest version + :raises: None + """ if len(version_entry) == 1: # 仅一个版本,当前即为最新版本 return version_entry[0] version_list = [] @@ -223,7 +357,7 @@ class VersionTypeXYZ(VersionType): version_list.append(re.split(r'[._-]', version)) # 将 version 拆分为列表,方便后续比较 x = '0' for version in version_list: # 第一轮比较取出最大的第一位 - if self._max(x, version[0]) < 0: + if self._compare(x, version[0]) < 0: x = version[0] version_candidate = [] @@ -239,7 +373,7 @@ class VersionTypeXYZ(VersionType): for version in version_list: # 第二轮比较取出最大的第二位 if len(version) <= 1: # 过滤仅一位的版本号 continue - if self._max(y, version[1]) < 0: + if self._compare(y, version[1]) < 0: y = version[1] version_candidate.clear() @@ -255,7 +389,7 @@ class VersionTypeXYZ(VersionType): for version in version_list: # 第三轮比较取出最大的第三位 if len(version) <= 2: # 过滤仅二位的版本号 continue - if self._max(z, version[2]) < 0: + if self._compare(z, version[2]) < 0: z = version[2] for version in version_list: # 最后一位最大版本必须惟一,直接返回结果 @@ -267,13 +401,29 @@ class VersionTypeXYZ(VersionType): return '' def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'x.y.z' class VersionTypeXY(VersionType): + """Version type Class for x.y""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 2: # 通过 '.'分割后,应该剩下2位 @@ -285,10 +435,24 @@ class VersionTypeXY(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'x.y' def latest_version(self, version_entry): + """ + Get latest version. + + :param version_entry: Package version list + :returns: latest version + :raises: None + """ if len(version_entry) == 1: # 仅一个版本,当前即为最新版本 return version_entry[0] version_list = [] @@ -296,7 +460,7 @@ class VersionTypeXY(VersionType): version_list.append(re.split(r'[._-]', version)) # 将 version 拆分为列表,方便后续比较 x = '0' for version in version_list: # 第一轮比较取出最大的第一位 - if self._max(x, version[0]) < 0: + if self._compare(x, version[0]) < 0: x = version[0] version_candidate = [] @@ -312,7 +476,7 @@ class VersionTypeXY(VersionType): for version in version_list: # 第二轮比较取出最大的第二位 if len(version) <= 1: # 过滤仅一位的版本号 continue - if self._max(y, version[1]) < 0: + if self._compare(y, version[1]) < 0: y = version[1] version_candidate.clear() @@ -330,7 +494,7 @@ class VersionTypeXY(VersionType): for version in version_list: # 第三轮比较取出最大的第三位 if len(version) <= 2: # 过滤仅二位的版本号 continue - if self._max(z, version[2]) < 0: + if self._compare(z, version[2]) < 0: z = version[2] for version in version_list: # 最后一位最大版本必须惟一,直接返回结果 @@ -342,6 +506,15 @@ class VersionTypeXY(VersionType): return '' def maintain_version(self, version_entry, current_version, pkg_type): + """ + Get the maintain version. + + :param version_entry: Package version list + :param current_version: Current version + :param pkg_type: Package type + :returns : Maintain version + :raises: None + """ version_candidate = [] version_digital = re.split(r'[._-]', current_version) # 将版本号做拆分 x = [version_digital[0]] @@ -358,15 +531,24 @@ class VersionTypeXY(VersionType): if len(version) <= 1: continue - if self._max(version[1], y) > 0: + if self._compare(version[1], y) > 0: y = version[1] x.append(y) return '.'.join(x) class VersionTypeX(VersionType): + """Version type Class for x""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 1: # 通过 '.'分割后,应该剩下1位 @@ -376,6 +558,13 @@ class VersionTypeX(VersionType): return True def latest_version(self, version_entry): + """ + Get latest version. + + :param version_entry: Package version list + :returns: latest version + :raises: None + """ if 1 == len(version_entry): # 仅一个版本,当前即为最新版本 return version_entry[0] version_list: List[List[str]] = [] @@ -383,7 +572,7 @@ class VersionTypeX(VersionType): version_list.append(re.split(r'[._-]', version)) # 将 version 拆分为列表,方便后续比较 x = '0' for version in version_list: # 第一轮比较取出最大的第一位 - if self._max(x, version[0]) < 0: + if self._compare(x, version[0]) < 0: x = version[0] version_candidate = [] @@ -399,13 +588,22 @@ class VersionTypeX(VersionType): for version in version_list: # 第二轮比较取出最大的第二位 if len(version) <= 1: # 过滤仅一位的版本号 continue - if self._max(y, version[1]) < 0: + if self._compare(y, version[1]) < 0: y = version[1] x.append(y) return '.'.join(x) def maintain_version(self, version_entry, current_version, pkg_type): + """ + Get the maintain version. + + :param version_entry: Package version list + :param current_version: Current version + :param pkg_type: Package type + :returns : Maintain version + :raises: None + """ version_candidate = [] version_digital = re.split(r'[._-]', current_version) # 将版本号做拆分 x = [version_digital[0]] @@ -422,19 +620,35 @@ class VersionTypeX(VersionType): if len(version) <= 1: continue - if self._max(version[1], y) > 0: + if self._compare(version[1], y) > 0: y = version[1] x.append(y) return '.'.join(x) def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'x' class VersionTypeYyyyXY(VersionType): + """Version type Class for yyyy.x.y""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 3: # 通过 '.'分割后,应该剩下3位 @@ -462,13 +676,29 @@ class VersionTypeYyyyXY(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyy.x.y' class VersionTypeYyyyX(VersionType): + """Version type Class for yyyy.x""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 2: # 通过 '.'分割后,应该剩下2位 @@ -485,13 +715,29 @@ class VersionTypeYyyyX(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyy.x' class VersionTypeYyyyW(VersionType): + """Version type Class for yyyyw""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() if len(version) != 5: # 共5 位 return False @@ -505,13 +751,29 @@ class VersionTypeYyyyW(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyyw' class VersionTypeYyyyMmDd(VersionType): + """Version type Class for yyyy.mm.dd""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 3: # 通过 '.'分割后,应该剩下3位 @@ -544,17 +806,34 @@ class VersionTypeYyyyMmDd(VersionType): else: return True except ValueError as e: # 时间格式非法 + _ = e print('Time foramt failed %s.', version) return False def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyy.mm.dd' class VersionTypeYyyyMm(VersionType): + """Version type Class for yyyy.mm""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 2: # 通过 '.'分割后,应该剩下2位 @@ -576,13 +855,29 @@ class VersionTypeYyyyMm(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyy.mm' -class VersionTypeYyyyMm(VersionType): +class VersionTypeYyyymm(VersionType): + """Version type Class for yyyy.mm""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() if len(version) != 6: # 长度为6 return False @@ -608,13 +903,28 @@ class VersionTypeYyyyMm(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyymm' class VersionTypeXYymmZ(VersionType): - + """Version type Class for x.yymm.z""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() digital_list = re.split(r'[._-]', version) if len(digital_list) != 3: # 通过 '.'分割后,应该剩下3位 @@ -636,13 +946,29 @@ class VersionTypeXYymmZ(VersionType): return True def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'x.yymm.z' class VersionTypeYyyymmdd(VersionType): + """Version type Class for yyyymmdd""" def version_match(self, pkg_version): + """ + Version match. + + :param pkg_version: Package version + :returns True: Version match success + :returns False: version match fail + :raises: None + """ version = pkg_version.strip() if len(version) != 8: # 日期长度满足 8 位要求 return False @@ -666,17 +992,33 @@ class VersionTypeYyyymmdd(VersionType): else: return True except ValueError as e: # 时间格式非法 + _ = e print('Time format failed %s,', version) return False def __init__(self): + """ + Initialize. + + :param None: No parameter + :returns: None + :raises: None + """ super().__init__() self._version_type = 'yyyymmdd' class VersionRecommend(object): - + """Version recommend Class for open source""" def __init__(self, version_entry, current_version, pkg_type): + """ + Initialize. + + :param version_entry: The version list of open source + :param current_version: The current version of open source + :returns: None + :raises: None + """ self.latest_version = current_version # 提供初值,避免 current_version 为空导致后面出现异常 self.maintain_version = current_version self.version_type = self._version_match(version_entry) @@ -689,7 +1031,13 @@ class VersionRecommend(object): self.maintain_version = self._get_maintain_version(version_entry, current_version, pkg_type) def _version_match(self, version_entry): + """ + Version match function. + :param version_entry: The version list of open source + :returns: The method input version list + :raises: None + """ version_method = {VersionTypeXYZW(): 0, VersionTypeXYZ(): 0, VersionTypeXY(): 0, @@ -698,8 +1046,7 @@ class VersionRecommend(object): VersionTypeYyyyX(): 0, VersionTypeYyyyW(): 0, VersionTypeYyyyMmDd(): 0, - VersionTypeYyyyMm(): 0, - VersionTypeYyyyMm(): 0, + VersionTypeYyyymm(): 0, VersionTypeXYymmZ(): 0, VersionTypeYyyymmdd(): 0} if not version_entry: @@ -720,7 +1067,16 @@ class VersionRecommend(object): else: return method - def _version_valid(self, version): + @staticmethod + def _version_valid(version): + """ + Version valid check. + + :param version: The version of open source + :returns True: valid version + :returns False: invalid version + :raises: None + """ m = re.match("^[0-9a-zA-Z._-]*$", version) if m is None: # 版本号应该是 数字/小写字母/下划线/. 组成 return False @@ -758,10 +1114,3 @@ class VersionRecommend(object): return '' else: return self.version_type.maintain_version(version_entry, current_version, pkg_type) - - -if __name__ == '__main__': - version_recommend = VersionRecommend( - ['0.1', '0.2', '1.2.3', '1.2.4', '1.2.6', '1.3.0', '1.5-rc', '2.0-rc'], '1.2.3', 0) - print('latest_version', version_recommend.latest_version) - print('maintain_version', version_recommend.maintain_version)