mirror of
https://github.com/tuna/mirror-web.git
synced 2025-12-25 20:32:46 +00:00
genisolist: format by black
Signed-off-by: Shengqi Chen <harry-chen@outlook.com>
This commit is contained in:
parent
6e03bff2a0
commit
cd02c4e5d2
|
|
@ -16,6 +16,7 @@ from urllib.parse import urljoin
|
|||
from configparser import ConfigParser
|
||||
from argparse import ArgumentParser, ArgumentError
|
||||
|
||||
|
||||
class Version:
|
||||
def __init__(self, vstring=None):
|
||||
if vstring:
|
||||
|
|
@ -56,11 +57,11 @@ class Version:
|
|||
|
||||
|
||||
class LooseVersion(Version):
|
||||
component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
|
||||
component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE)
|
||||
|
||||
def parse(self, vstring):
|
||||
self.vstring = vstring
|
||||
components = [x for x in self.component_re.split(vstring) if x and x != '.']
|
||||
components = [x for x in self.component_re.split(vstring) if x and x != "."]
|
||||
for i, obj in enumerate(components):
|
||||
try:
|
||||
components[i] = int(obj)
|
||||
|
|
@ -102,42 +103,45 @@ class LooseVersion(Version):
|
|||
if self_version > other_version:
|
||||
return 1
|
||||
|
||||
|
||||
parser = ArgumentParser(
|
||||
prog='iso info list generator',
|
||||
description='Generate iso info list',
|
||||
prog="iso info list generator",
|
||||
description="Generate iso info list",
|
||||
)
|
||||
parser.add_argument("-d", "--dir", default=None, help="Override root directory.")
|
||||
parser.add_argument(
|
||||
"-R",
|
||||
"--remote",
|
||||
default=None,
|
||||
help="[Remote Mode] Using rsync to get file list instead of reading from INI. Need the base of target site, for example, `mirror.tuna.tsinghua.edu.cn`.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'-d', '--dir', default=None,
|
||||
help='Override root directory.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-R', '--remote', default=None,
|
||||
help='[Remote Mode] Using rsync to get file list instead of reading from INI. Need the base of target site, for example, `mirror.nju.edu.cn`.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-T', '--test', default=None, nargs="*",
|
||||
help='Test specified `distro`s (multiple arguments input is supported) in INI. If Remote Mode is on, `distro`s must be specified in case of heavy rsync job.'
|
||||
"-T",
|
||||
"--test",
|
||||
default=None,
|
||||
nargs="*",
|
||||
help="Test specified `distro`s (multiple arguments input is supported) in INI. If Remote Mode is on, `distro`s must be specified in case of heavy rsync job.",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
CONFIG_FILE = os.path.join(os.path.dirname(__file__), 'genisolist.ini')
|
||||
CONFIG_FILE = os.path.join(os.path.dirname(__file__), "genisolist.ini")
|
||||
|
||||
|
||||
def getPlatformPriority(platform):
|
||||
platform = platform.lower()
|
||||
if platform in ['amd64', 'x86_64', '64bit']:
|
||||
if platform in ["amd64", "x86_64", "64bit"]:
|
||||
return 100
|
||||
elif platform in ['arm64', 'aarch64', 'arm64v8']:
|
||||
elif platform in ["arm64", "aarch64", "arm64v8"]:
|
||||
return 95
|
||||
elif platform in ['riscv64']:
|
||||
elif platform in ["riscv64"]:
|
||||
return 95
|
||||
elif platform in ['loongson2f', 'loongson3']:
|
||||
elif platform in ["loongson2f", "loongson3"]:
|
||||
return 95
|
||||
elif platform in ['i386', 'i486', 'i586', 'i686', 'x86', '32bit']:
|
||||
elif platform in ["i386", "i486", "i586", "i686", "x86", "32bit"]:
|
||||
return 90
|
||||
elif platform in ['arm32', 'armhf', 'armv7']:
|
||||
elif platform in ["arm32", "armhf", "armv7"]:
|
||||
return 85
|
||||
else:
|
||||
return 0
|
||||
|
|
@ -152,10 +156,10 @@ def renderTemplate(template, result):
|
|||
|
||||
def getSortKeys(template, result):
|
||||
keys = []
|
||||
for i in template.split(' '):
|
||||
for i in template.split(" "):
|
||||
if not i:
|
||||
continue
|
||||
if i[0] != '$':
|
||||
if i[0] != "$":
|
||||
keys.append(i)
|
||||
else:
|
||||
keys.append(result.group(int(i[1:])) or "")
|
||||
|
|
@ -165,8 +169,8 @@ def getSortKeys(template, result):
|
|||
def parseSection(items, rsync=False):
|
||||
items = dict(items)
|
||||
|
||||
if 'location' in items:
|
||||
locations = [items['location']]
|
||||
if "location" in items:
|
||||
locations = [items["location"]]
|
||||
else:
|
||||
locations = []
|
||||
i = 0
|
||||
|
|
@ -179,7 +183,6 @@ def parseSection(items, rsync=False):
|
|||
images = {}
|
||||
|
||||
for location in locations:
|
||||
|
||||
if rsync:
|
||||
# find last non-wildcard path
|
||||
non_regex = []
|
||||
|
|
@ -197,7 +200,8 @@ def parseSection(items, rsync=False):
|
|||
|
||||
# use fnmatch to mimic glob behavior
|
||||
image_paths = list(
|
||||
filter(lambda path: fnmatch.fnmatch(path, location), image_paths))
|
||||
filter(lambda path: fnmatch.fnmatch(path, location), image_paths)
|
||||
)
|
||||
|
||||
else:
|
||||
logger.debug("[GLOB] %s", location)
|
||||
|
|
@ -218,14 +222,17 @@ def parseSection(items, rsync=False):
|
|||
|
||||
for prop in ("version", "type", "platform", "category"):
|
||||
imageinfo[prop] = renderTemplate(items.get(prop, ""), result)
|
||||
if 'version' not in imageinfo:
|
||||
imageinfo['version'] = '0.0'
|
||||
if "version" not in imageinfo:
|
||||
imageinfo["version"] = "0.0"
|
||||
sort_by = items.get("sort_by", "")
|
||||
if not (sort_by):
|
||||
imageinfo['sort_key'] = (
|
||||
imageinfo['version'], imageinfo['platform'], imageinfo['type'])
|
||||
imageinfo["sort_key"] = (
|
||||
imageinfo["version"],
|
||||
imageinfo["platform"],
|
||||
imageinfo["type"],
|
||||
)
|
||||
else:
|
||||
imageinfo['sort_key'] = getSortKeys(sort_by, result)
|
||||
imageinfo["sort_key"] = getSortKeys(sort_by, result)
|
||||
|
||||
logger.debug("[JSON] %r", imageinfo)
|
||||
key = renderTemplate(items.get("key_by", ""), result)
|
||||
|
|
@ -234,17 +241,21 @@ def parseSection(items, rsync=False):
|
|||
images[key].append(imageinfo)
|
||||
|
||||
for image_group in images.values():
|
||||
if 'nosort' not in items:
|
||||
image_group.sort(key=lambda k: (LooseVersion(k['version']),
|
||||
getPlatformPriority(k['platform']),
|
||||
k['type']),
|
||||
reverse=True)
|
||||
if "nosort" not in items:
|
||||
image_group.sort(
|
||||
key=lambda k: (
|
||||
LooseVersion(k["version"]),
|
||||
getPlatformPriority(k["platform"]),
|
||||
k["type"],
|
||||
),
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
i = 0
|
||||
versions = set()
|
||||
listvers = int(items.get('listvers', 0xFF))
|
||||
listvers = int(items.get("listvers", 0xFF))
|
||||
for image in image_group:
|
||||
versions.add(image['version'])
|
||||
versions.add(image["version"])
|
||||
if len(versions) <= listvers:
|
||||
yield image
|
||||
else:
|
||||
|
|
@ -252,27 +263,34 @@ def parseSection(items, rsync=False):
|
|||
|
||||
|
||||
def getDetail(image_info, urlbase):
|
||||
url = urljoin(urlbase, image_info['filepath'])
|
||||
desc = "%s (%s%s)" % (
|
||||
image_info['version'],
|
||||
image_info['platform'],
|
||||
", %s" % image_info['type'] if image_info['type'] else ''
|
||||
) if image_info['platform'] != "" else image_info['version']
|
||||
url = urljoin(urlbase, image_info["filepath"])
|
||||
desc = (
|
||||
"%s (%s%s)"
|
||||
% (
|
||||
image_info["version"],
|
||||
image_info["platform"],
|
||||
", %s" % image_info["type"] if image_info["type"] else "",
|
||||
)
|
||||
if image_info["platform"] != ""
|
||||
else image_info["version"]
|
||||
)
|
||||
|
||||
category = image_info.get('category', 'os') or "os"
|
||||
category = image_info.get("category", "os") or "os"
|
||||
return (desc, url, category)
|
||||
|
||||
|
||||
def getJsonOutput(url_dict, prio={}):
|
||||
raw = []
|
||||
for distro in url_dict:
|
||||
raw.append({
|
||||
"distro": distro,
|
||||
"category": list({c for _, _, c in url_dict[distro]})[0],
|
||||
"urls": [
|
||||
{"name": name, "url": url} for name, url, _ in url_dict[distro]
|
||||
]
|
||||
})
|
||||
raw.append(
|
||||
{
|
||||
"distro": distro,
|
||||
"category": list({c for _, _, c in url_dict[distro]})[0],
|
||||
"urls": [
|
||||
{"name": name, "url": url} for name, url, _ in url_dict[distro]
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
raw.sort(key=lambda d: prio.get(d["distro"], 0xFFFF))
|
||||
|
||||
|
|
@ -285,13 +303,13 @@ def getImageList():
|
|||
raise Exception("%s not found!" % CONFIG_FILE)
|
||||
|
||||
prior = {}
|
||||
for (name, value) in ini.items("%main%"):
|
||||
for name, value in ini.items("%main%"):
|
||||
if re.match(r"d\d+$", name):
|
||||
prior[value] = int(name[1:])
|
||||
|
||||
url_dict = {}
|
||||
root = ini.get("%main%", 'root')
|
||||
urlbase = ini.get("%main%", 'urlbase')
|
||||
root = ini.get("%main%", "root")
|
||||
urlbase = ini.get("%main%", "urlbase")
|
||||
|
||||
if not args.remote:
|
||||
# Local
|
||||
|
|
@ -308,10 +326,10 @@ def getImageList():
|
|||
if section == "%main%":
|
||||
continue
|
||||
for image in parseSection(ini.items(section)):
|
||||
img_dict[image['distro']].append(image)
|
||||
img_dict[image["distro"]].append(image)
|
||||
|
||||
for distro, images in img_dict.items():
|
||||
images.sort(key=lambda x: x['sort_key'], reverse=True)
|
||||
images.sort(key=lambda x: x["sort_key"], reverse=True)
|
||||
logger.debug("[IMAGES] %r %r", distro, images)
|
||||
url_dict[distro] = [getDetail(image, urlbase) for image in images]
|
||||
|
||||
|
|
@ -320,38 +338,41 @@ def getImageList():
|
|||
else:
|
||||
# Remote
|
||||
for spec_distro in args.test:
|
||||
|
||||
img_dict = collections.defaultdict(list)
|
||||
for section in ini.sections():
|
||||
if section == "%main%":
|
||||
continue
|
||||
if ini.get(section, 'distro') != spec_distro:
|
||||
if ini.get(section, "distro") != spec_distro:
|
||||
continue
|
||||
else:
|
||||
for image in parseSection(ini.items(section), rsync=True):
|
||||
img_dict[image['distro']].append(image)
|
||||
img_dict[image["distro"]].append(image)
|
||||
|
||||
for distro, images in img_dict.items():
|
||||
images.sort(key=lambda x: x['sort_key'], reverse=True)
|
||||
images.sort(key=lambda x: x["sort_key"], reverse=True)
|
||||
logger.debug("[IMAGES] %r %r", distro, images)
|
||||
url_dict[distro] = [getDetail(image, urlbase)
|
||||
for image in images]
|
||||
url_dict[distro] = [getDetail(image, urlbase) for image in images]
|
||||
|
||||
return getJsonOutput(url_dict, prior)
|
||||
|
||||
|
||||
def rsyncQuery(url: str):
|
||||
rsync_proc = os.popen(
|
||||
"rsync -r --list-only --no-motd rsync://%s | awk '{ $1=$2=$3=$4=\"\"; print substr($0,5); }'" % url)
|
||||
"rsync -r --list-only --no-motd rsync://%s | awk '{ $1=$2=$3=$4=\"\"; print substr($0,5); }'"
|
||||
% url
|
||||
)
|
||||
return [path.rstrip() for path in rsync_proc.readlines()]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
|
||||
if args.remote:
|
||||
if not args.test:
|
||||
raise ArgumentError(
|
||||
None, 'If Remote Mode is on, images must be specified in case of heavy rsync job.')
|
||||
None,
|
||||
"If Remote Mode is on, images must be specified in case of heavy rsync job.",
|
||||
)
|
||||
|
||||
print(getImageList())
|
||||
|
|
|
|||
Loading…
Reference in New Issue