refactor: github releases, arch name, multithreading

rewrite github downloader and configuration to store version tag in sqlite.
change 'version_tag' to 'releases_tag', 'stripped_version' to 'version'.
add 'all' arch, change 'x86_64' to 'amd64'.
add multithreading for downloader.
rename init_deb.py to init-deb.py
This commit is contained in:
wcbing 2025-02-22 21:12:33 +08:00
parent 07d25c28c7
commit 2643348df9
9 changed files with 304 additions and 228 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
data/github-local.json data/github-local.json
data/deb.db data/deb.db
deb/ deb/
__pycache__/

View File

@ -2,9 +2,16 @@
import subprocess import subprocess
import os import os
import sqlite3 import sqlite3
import sys
import logging import logging
from threading import Lock
BASE_DIR = "deb"
DB_DIR = "data"
USER_AGENT = "Debian APT-HTTP/1.3 (2.6.1)" # from Debian 12
version_lock = Lock()
base_dir = "deb"
logging.basicConfig( logging.basicConfig(
format="%(asctime)s %(message)s", format="%(asctime)s %(message)s",
datefmt="%Y/%m/%d %H:%M:%S", datefmt="%Y/%m/%d %H:%M:%S",
@ -13,68 +20,58 @@ logging.basicConfig(
def download(url): def download(url):
file_dir = os.path.join(base_dir, os.path.dirname(url)) """Download file using curl with APT User-Agent."""
if not os.path.exists(file_dir): file_path = os.path.join(BASE_DIR, url.split("?")[0])
os.makedirs(file_dir) os.makedirs(os.path.dirname(file_path), exist_ok=True)
file_path = os.path.join(base_dir, url.split("?")[0]) subprocess.run(["curl", "-H", f"User-Agent: {USER_AGENT}", "-fsLo", file_path, url])
# 用 curl 模拟 apt 下载文件User-Agent 来自 Debian 12
subprocess.run(
[
"curl",
"-H",
"User-Agent: Debian APT-HTTP/1.3 (2.6.1)",
"-fsLo",
file_path,
url,
]
)
def check_download(name, version, url, arch): def check_download(name, version, url, arch="amd64"):
"""Check and handle package download/update."""
logging.info("%s:%s = %s", name, arch, version) logging.info("%s:%s = %s", name, arch, version)
# connect to db db_path = os.path.join("data", f"{BASE_DIR}.db")
with sqlite3.connect(os.path.join("data", f"{base_dir}.db")) as conn: # get local version
cur = conn.cursor() with version_lock, sqlite3.connect(db_path) as conn:
res = cur.execute( res = conn.execute(
f"SELECT version, url FROM {arch} WHERE name = ?", (name,) f"SELECT version, url FROM '{arch}' WHERE name = ?", (name,)
).fetchall() ).fetchone()
if len(res): if res:
local_version = res[0][0] local_version, local_url = res
local_url = res[0][1] if local_version != version:
if local_version != version: print(f"Update: {name}:{arch} ({local_version} -> {version})")
print(f"Update: {name}:{arch} ({local_version} -> {version})") download(url)
download(url) # update database
# wirte to db with version_lock, sqlite3.connect(db_path) as conn:
cur.execute( conn.execute(
f"UPDATE {arch} SET version = ?, url = ? WHERE name = ?", f"UPDATE '{arch}' SET version = ?, url = ? WHERE name = ?",
(version, url, name), (version, url, name),
) )
# remove old version conn.commit()
if local_url != url: # 针对固定下载链接 # remove old version
old_file_path = os.path.join(base_dir, local_url.split("?")[0]) if local_url != url: # 防止固定下载链接
if os.path.exists(old_file_path): old_file_path = os.path.join(BASE_DIR, local_url.split("?")[0])
os.remove(old_file_path) if os.path.exists(old_file_path):
else: os.remove(old_file_path)
print(f"AddNew: {name}:{arch} ({version})") else:
download(url) print(f"AddNew: {name}:{arch} ({version})")
# wirte to db download(url)
cur.execute( # update database
f"INSERT INTO {arch}(name, version, url) VALUES (?, ?, ?)", with version_lock, sqlite3.connect(db_path) as conn:
conn.execute(
f"INSERT INTO '{arch}'(name, version, url) VALUES (?, ?, ?)",
(name, version, url), (name, version, url),
) )
conn.commit() conn.commit()
if __name__ == "__main__": if __name__ == "__main__":
args = os.sys.argv args = sys.argv
if len(args) == 5: if len(args) in (4, 5):
check_download(args[1], args[2], args[3], args[4]) check_download(*args[1:])
elif len(args) == 4:
check_download(args[1], args[2], args[3], "x86_64")
elif len(args) > 1: elif len(args) > 1:
logging.error(f"Unknown Args: {args[1:]}") logging.error(f"Unknown Args: {args[1:]}")
else: else:
print(f"Usage: {args[0]} <package_name> <version> <url> [arch]") print(f"Usage: {args[0]} <package_name> <version> <url> [arch]")
print("options:") print("options:")
print(" arch: x86_64, arm64. default is x86_64") print(" arch: amd64, arm64, all. default is amd64")

View File

@ -1,108 +1,108 @@
{ {
"clash-verge": { "clash-verge": {
"repo": "clash-verge-rev/clash-verge-rev", "repo": "clash-verge-rev/clash-verge-rev",
"file_list": [ "file_list": {
"Clash.Verge_{stripped_version}_amd64.deb", "amd64": "Clash.Verge_{version}_amd64.deb",
"Clash.Verge_{stripped_version}_arm64.deb" "arm64": "Clash.Verge_{version}_arm64.deb"
] }
}, },
"mihomo": { "mihomo": {
"repo": "MetaCubeX/mihomo", "repo": "MetaCubeX/mihomo",
"file_list": [ "file_list": {
"mihomo-linux-amd64-compatible-{version_tag}.deb", "amd64": "mihomo-linux-amd64-compatible-{releases_tag}.deb",
"mihomo-linux-arm64-{version_tag}.deb" "arm64": "mihomo-linux-arm64-{releases_tag}.deb"
] }
}, },
"flclash": { "flclash": {
"repo": "chen08209/FlClash", "repo": "chen08209/FlClash",
"file_list": [ "file_list": {
"FlClash-{stripped_version}-linux-amd64.deb" "amd64": "FlClash-{version}-linux-amd64.deb"
] }
}, },
"hugo": { "hugo": {
"repo": "gohugoio/hugo", "repo": "gohugoio/hugo",
"file_list": [ "file_list": {
"hugo_extended_{stripped_version}_linux-amd64.deb", "amd64": "hugo_extended_{version}_linux-amd64.deb",
"hugo_extended_{stripped_version}_linux-arm64.deb" "arm64": "hugo_extended_{version}_linux-arm64.deb"
] }
}, },
"rustdesk": { "rustdesk": {
"repo": "rustdesk/rustdesk", "repo": "rustdesk/rustdesk",
"file_list": [ "file_list": {
"rustdesk-{version_tag}-x86_64.deb", "amd64": "rustdesk-{releases_tag}-x86_64.deb",
"rustdesk-{version_tag}-aarch64.deb" "arm64": "rustdesk-{releases_tag}-aarch64.deb"
] }
}, },
"obsidian": { "obsidian": {
"repo": "obsidianmd/obsidian-releases", "repo": "obsidianmd/obsidian-releases",
"file_list": [ "file_list": {
"obsidian_{stripped_version}_amd64.deb" "amd64": "obsidian_{version}_amd64.deb"
] }
}, },
"tabby": { "tabby": {
"repo": "Eugeny/tabby", "repo": "Eugeny/tabby",
"file_list": [ "file_list": {
"tabby-{stripped_version}-linux-x64.deb", "amd64": "tabby-{version}-linux-x64.deb",
"tabby-{stripped_version}-linux-arm64.deb" "arm64": "tabby-{version}-linux-arm64.deb"
] }
}, },
"pandoc": { "pandoc": {
"repo": "jgm/pandoc", "repo": "jgm/pandoc",
"file_list": [ "file_list": {
"pandoc-{version_tag}-1-amd64.deb", "amd64": "pandoc-{releases_tag}-1-amd64.deb",
"pandoc-{version_tag}-1-arm64.deb" "arm64": "pandoc-{releases_tag}-1-arm64.deb"
] }
}, },
"localsend": { "localsend": {
"repo": "localsend/localsend", "repo": "localsend/localsend",
"file_list": [ "file_list": {
"LocalSend-{stripped_version}-linux-x86-64.deb", "amd64": "LocalSend-{version}-linux-x86-64.deb",
"LocalSend-{stripped_version}-linux-arm-64.deb" "arm64": "LocalSend-{version}-linux-arm-64.deb"
] }
}, },
"motrix": { "motrix": {
"repo": "agalwood/Motrix", "repo": "agalwood/Motrix",
"file_list": [ "file_list": {
"Motrix_{stripped_version}_amd64.deb", "amd64": "Motrix_{version}_amd64.deb",
"Motrix_{stripped_version}_arm64.deb" "arm64": "Motrix_{version}_arm64.deb"
] }
}, },
"peazip": { "peazip": {
"repo": "peazip/PeaZip", "repo": "peazip/PeaZip",
"file_list": [ "file_list": {
"peazip_{version_tag}.LINUX.GTK2-1_amd64.deb" "amd64": "peazip_{releases_tag}.LINUX.GTK2-1_amd64.deb"
] }
}, },
"neovim": { "neovim": {
"repo": "neovim/neovim-releases", "repo": "neovim/neovim-releases",
"file_list": [ "file_list": {
"nvim-linux64.deb" "amd64": "nvim-linux64.deb"
] }
}, },
"hiddify": { "hiddify": {
"repo": "hiddify/hiddify-app", "repo": "hiddify/hiddify-app",
"file_list": [ "file_list": {
"Hiddify-Debian-x64.deb" "amd64": "Hiddify-Debian-x64.deb"
] }
}, },
"cloudflared": { "cloudflared": {
"repo": "cloudflare/cloudflared", "repo": "cloudflare/cloudflared",
"file_list": [ "file_list": {
"cloudflared-linux-amd64.deb", "amd64": "cloudflared-linux-amd64.deb",
"cloudflared-linux-arm64.deb" "arm64": "cloudflared-linux-arm64.deb"
] }
}, },
"caddy": { "caddy": {
"repo": "caddyserver/caddy", "repo": "caddyserver/caddy",
"file_list": [ "file_list": {
"caddy_{stripped_version}_linux_amd64.deb", "amd64": "caddy_{version}_linux_amd64.deb",
"caddy_{stripped_version}_linux_arm64.deb" "arm64": "caddy_{version}_linux_arm64.deb"
] }
}, },
"foliate": { "foliate": {
"repo": "johnfactotum/foliate", "repo": "johnfactotum/foliate",
"file_list": [ "file_list": {
"foliate_{version_tag}_all.deb" "all": "foliate_{releases_tag}_all.deb"
] }
} }
} }

View File

@ -1,106 +1,126 @@
[ {
{ "google-chrome": {
"name": "google-chrome",
"repo": "https://dl.google.com/linux/chrome/deb/", "repo": "https://dl.google.com/linux/chrome/deb/",
"amd64_path": "dists/stable/main/binary-amd64/Packages.gz" "path": {
"amd64": "dists/stable/main/binary-amd64/Packages.gz"
}
}, },
{ "google-earth": {
"name": "google-earth",
"repo": "https://dl.google.com/linux/earth/deb/", "repo": "https://dl.google.com/linux/earth/deb/",
"amd64_path": "dists/stable/main/binary-amd64/Packages.gz" "path": {
"amd64": "dists/stable/main/binary-amd64/Packages.gz"
}
}, },
{ "termius": {
"name": "termius",
"repo": "https://deb.termius.com/", "repo": "https://deb.termius.com/",
"amd64_path": "dists/squeeze/main/binary-amd64/Packages.gz" "path": {
"amd64": "dists/squeeze/main/binary-amd64/Packages.gz"
}
}, },
{ "steam": {
"name": "steam",
"repo": "https://repo.steampowered.com/steam/", "repo": "https://repo.steampowered.com/steam/",
"amd64_path": "dists/stable/steam/binary-amd64/Packages.gz" "path": {
"amd64": "dists/stable/steam/binary-amd64/Packages.gz"
}
}, },
{ "firefox": {
"name": "firefox",
"repo": "https://packages.mozilla.org/apt/", "repo": "https://packages.mozilla.org/apt/",
"amd64_path": "dists/mozilla/main/binary-amd64/Packages", "path": {
"arm64_path": "dists/mozilla/main/binary-arm64/Packages" "amd64": "dists/mozilla/main/binary-amd64/Packages",
"arm64": "dists/mozilla/main/binary-arm64/Packages"
}
}, },
{ "microsoft-edge": {
"name": "microsoft-edge",
"repo": "https://packages.microsoft.com/repos/edge/", "repo": "https://packages.microsoft.com/repos/edge/",
"amd64_path": "dists/stable/main/binary-amd64/Packages.gz" "path": {
"amd64": "dists/stable/main/binary-amd64/Packages.gz"
}
}, },
{ "opera-stable": {
"name": "opera-stable",
"repo": "https://deb.opera.com/opera-stable/", "repo": "https://deb.opera.com/opera-stable/",
"amd64_path": "dists/stable/non-free/binary-amd64/Packages.gz" "path": {
"amd64": "dists/stable/non-free/binary-amd64/Packages.gz"
}
}, },
{ "code": {
"name": "code",
"repo": "https://packages.microsoft.com/repos/code/", "repo": "https://packages.microsoft.com/repos/code/",
"amd64_path": "dists/stable/main/binary-amd64/Packages.gz", "path": {
"arm64_path": "dists/stable/main/binary-arm64/Packages.gz" "amd64": "dists/stable/main/binary-amd64/Packages.gz",
"arm64": "dists/stable/main/binary-arm64/Packages.gz"
}
}, },
{ "tailscale": {
"name": "tailscale",
"repo": "https://pkgs.tailscale.com/stable/debian/", "repo": "https://pkgs.tailscale.com/stable/debian/",
"amd64_path": "dists/sid/main/binary-amd64/Packages.gz", "path": {
"arm64_path": "dists/sid/main/binary-arm64/Packages.gz" "amd64": "dists/sid/main/binary-amd64/Packages.gz",
"arm64": "dists/sid/main/binary-arm64/Packages.gz"
}
}, },
{ "sublime": {
"name": "sublime",
"repo": "https://download.sublimetext.com/", "repo": "https://download.sublimetext.com/",
"mix_path": "apt/stable/Packages.gz" "path": {
"mix": "apt/stable/Packages.gz"
}
}, },
{ "black-desk": {
"name": "black-desk",
"repo": "https://github.com/black-desk/debs/releases/latest/download/", "repo": "https://github.com/black-desk/debs/releases/latest/download/",
"amd64_path": "Packages" "path": {
"amd64": "Packages"
}
}, },
{ "typora": {
"name": "typora",
"repo": "https://typoraio.cn/linux/", "repo": "https://typoraio.cn/linux/",
"mix_path": "Packages.gz" "path": {
"mix": "Packages.gz"
}
}, },
{ "zotero": {
"name": "zotero",
"repo": "https://zotero.retorque.re/file/apt-package-archive/", "repo": "https://zotero.retorque.re/file/apt-package-archive/",
"amd64_path": "Packages" "path": {
"amd64": "Packages"
}
}, },
{ "gh": {
"name": "gh",
"repo": "https://cli.github.com/packages/", "repo": "https://cli.github.com/packages/",
"amd64_path": "dists/stable/main/binary-amd64/Packages.gz", "path": {
"arm64_path": "dists/stable/main/binary-arm64/Packages.gz" "amd64": "dists/stable/main/binary-amd64/Packages.gz",
"arm64": "dists/stable/main/binary-arm64/Packages.gz"
}
}, },
{ "dufs": {
"name": "dufs",
"repo": "https://github.com/wcbing-build/dufs-debs/releases/latest/download/", "repo": "https://github.com/wcbing-build/dufs-debs/releases/latest/download/",
"mix_path": "Packages" "path": {
"mix": "Packages"
}
}, },
{ "frp": {
"name": "frp",
"repo": "https://github.com/wcbing-build/frp-debs/releases/latest/download/", "repo": "https://github.com/wcbing-build/frp-debs/releases/latest/download/",
"mix_path": "Packages" "path": {
"mix": "Packages"
}
}, },
{ "lazydocker": {
"name": "lazydocker",
"repo": "https://github.com/wcbing-build/lazydocker-debs/releases/latest/download/", "repo": "https://github.com/wcbing-build/lazydocker-debs/releases/latest/download/",
"mix_path": "Packages" "path": {
"mix": "Packages"
}
}, },
{ "lazygit": {
"name": "lazygit",
"repo": "https://github.com/wcbing-build/lazygit-debs/releases/latest/download/", "repo": "https://github.com/wcbing-build/lazygit-debs/releases/latest/download/",
"mix_path": "Packages" "path": {
"mix": "Packages"
}
}, },
{ "nexttrace": {
"name": "nexttrace",
"repo": "https://github.com/nxtrace/nexttrace-debs/releases/latest/download/", "repo": "https://github.com/nxtrace/nexttrace-debs/releases/latest/download/",
"mix_path": "Packages" "path": {
"mix": "Packages"
}
}, },
{ "debiancn": {
"name": "debiancn",
"repo": "https://mirrors.cernet.edu.cn/debiancn/", "repo": "https://mirrors.cernet.edu.cn/debiancn/",
"amd64_path": "dists/bookworm/main/binary-amd64/Packages.gz" "path": {
"amd64": "dists/bookworm/main/binary-amd64/Packages.gz"
}
} }
] }

61
get-github-releases.py Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python3
import argparse
import requests
import json
import os
import re
from concurrent.futures import ThreadPoolExecutor, wait
from check_downloader import check_download
github_info_list = {}
CONFIG = {"data_dir": "data", "proxy": "", "thread": 5}
# 读取命令行参数
def read_args():
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--data", default="data", help="从 <DATA> 读取仓库配置")
parser.add_argument(
"-p", "--proxy", default="", help="Github 代理,<PROXY> 必须以 / 结尾"
)
parser.add_argument(
"-t", "--thread", type=int, default=5, help="并发下载线程数量,默认为 5"
)
args = parser.parse_args()
CONFIG.update({"data_dir": args.data, "proxy": args.proxy, "thread": args.thread})
if __name__ == "__main__":
read_args()
# read all repo info 读取所有仓库配置
with open(os.path.join(CONFIG["data_dir"], "github.json"), "r") as f:
github_info_list = json.load(f)
tasks = []
with ThreadPoolExecutor(max_workers=CONFIG["thread"]) as executor:
for name, repo in github_info_list.items():
release_url = (
f'{CONFIG["proxy"]}https://github.com/{repo["repo"]}/releases'
)
# get latest releases tag 获取最新版本标签
location = requests.head(release_url + "/latest").headers.get("Location", "")
match = re.search(r".*releases/tag/([^/]+)", location)
if not match:
continue
releases_tag = match.group(1)
version = match.group() if (match := re.search("[0-9].*", releases_tag)) else ""
for arch, file_name in repo["file_list"].items():
release_file = file_name.format(
releases_tag=releases_tag, version=version
)
file_url = f"{release_url}/download/{releases_tag}/{release_file}"
# 提交任务到线程池
tasks.append(
executor.submit(check_download, name, version, file_url, arch)
)
# 等待所有任务完成
wait(tasks)

19
init-deb.py Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
import sqlite3
# create table
conn = sqlite3.connect("data/deb.db")
for arch in ["amd64", "arm64", "all"]:
conn.execute(
f"""
CREATE TABLE IF NOT EXISTS '{arch}' (
name TEXT UNIQUE,
version TEXT,
url TEXT
);
"""
)
conn.commit()
conn.close()

View File

@ -1,27 +0,0 @@
#!/usr/bin/env python3
import sqlite3
# create table
conn = sqlite3.connect("data/deb.db")
conn.execute(
"""
CREATE TABLE IF NOT EXISTS x86_64 (
name TEXT UNIQUE,
version TEXT,
url TEXT
);
"""
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS arm64 (
name TEXT UNIQUE,
version TEXT,
url TEXT
);
"""
)
conn.commit()
conn.close()

View File

@ -17,30 +17,37 @@ package_version = {arch: {} for arch in ["all", "amd64", "i386", "arm64"]}
package_info = {arch: {} for arch in ["all", "amd64", "i386", "arm64"]} package_info = {arch: {} for arch in ["all", "amd64", "i386", "arm64"]}
lock = {arch: Lock() for arch in ["all", "amd64", "i386", "arm64"]} lock = {arch: Lock() for arch in ["all", "amd64", "i386", "arm64"]}
USER_AGENT = "Debian APT-HTTP/1.3 (2.6.1)" # from Debian 12
""" """
repo info json format: repo info json format:
{ "repo_name": {
"name": repo name
"repo": repo url, end with "/" "repo": repo url, end with "/"
"xxx_path": repo xxx Packages file path, start with no "/" "xxx_path": {
"arch": repo Packages file path of "arch", start with no "/"
}
} }
""" """
def read_repo_list(repo_list_file): def read_repo_list(repo_list_file: str) -> dict:
try: try:
with open(repo_list_file, "r") as f: with open(repo_list_file, "r") as f:
return json.load(f) return json.load(f)
except Exception as e: except Exception as e:
logging.error(f"Error reading repo list: {e}") logging.error(f"Error reading repo list: {e}")
return [] return {}
# get the packages file content from remote repo def get_remote_packages(repo_url: str, file_path: str) -> bytes:
def get_remote_packages(repo_url, file_path): """
get the packages file content from remote repo
"""
file_url = repo_url + file_path file_url = repo_url + file_path
try: try:
response = requests.get(file_url, timeout=10) response = requests.get(
file_url, timeout=10, headers={"User-Agent": USER_AGENT}
)
if response.status_code != 200: if response.status_code != 200:
logging.error( logging.error(
f"GetError: {file_url} returned status {response.status_code}" f"GetError: {file_url} returned status {response.status_code}"
@ -67,9 +74,11 @@ def get_remote_packages(repo_url, file_path):
return b"" return b""
def get_latest(deb_packages): def get_latest(deb_packages: bytes):
# split the information of each packet, store it in infoList """
# 将每个包的信息分割开,存放到 infoList 中 split the information of each packet, deduplication and store the latest in infoList
将每个包的信息分割开去重并将最新的存放到 infoList
"""
deb_packages = re.sub(rb"^Package: ", b"{{start}}Package: ", deb_packages, flags=re.MULTILINE) deb_packages = re.sub(rb"^Package: ", b"{{start}}Package: ", deb_packages, flags=re.MULTILINE)
info_list = deb_packages.split(b"{{start}}")[1:] info_list = deb_packages.split(b"{{start}}")[1:]
@ -97,18 +106,14 @@ def get_latest(deb_packages):
return return
def process_repo(r): def process_repo(r: dict):
"""
获取仓库中不同架构子仓库的内容最后调用 get_latest 去重并保存
"""
try: try:
deb_packages = b"" deb_packages = b""
if r.get("mix_path"): # 获取扁平 Repo 中包信息 for arch, path in r["path"].items():
deb_packages += get_remote_packages(r["repo"], r["mix_path"]) deb_packages += get_remote_packages(r["repo"], path)
else:
if r.get("amd64_path"): # 获取 Repo 中 Amd64 包信息
deb_packages += get_remote_packages(r["repo"], r["amd64_path"])
if r.get("arm64_path"): # 获取 Repo 中 Arm64 包信息
deb_packages += get_remote_packages(r["repo"], r["arm64_path"])
if r.get("all_path"): # 获取 Repo 中 All 包信息
deb_packages += get_remote_packages(r["repo"], r["all_path"])
get_latest(deb_packages) get_latest(deb_packages)
except Exception as e: except Exception as e:
logging.error(f"Error processing repo {r.get('name', 'unknown')}: {e}") logging.error(f"Error processing repo {r.get('name', 'unknown')}: {e}")
@ -137,19 +142,19 @@ if __name__ == "__main__":
with open(args.local) as f: with open(args.local) as f:
get_latest(f.read().encode()) get_latest(f.read().encode())
repo_list_file = args.repo # 读取 repo_list 配置
repo_list = read_repo_list(repo_list_file) repo_list = read_repo_list(args.repo)
if not repo_list: if not repo_list:
sys.exit() sys.exit()
# 多线程,同时限制最大线程数 # 多线程,同时限制最大线程数
with ThreadPoolExecutor(max_workers=10) as executor: with ThreadPoolExecutor(max_workers=10) as executor:
executor.map(process_repo, repo_list) executor.map(process_repo, repo_list.values())
# 分别输出到不同文件
os.makedirs("deb/amd64/", exist_ok=True) os.makedirs("deb/amd64/", exist_ok=True)
os.makedirs("deb/arm64/", exist_ok=True) os.makedirs("deb/arm64/", exist_ok=True)
# 分别输出到不同文件
with open("deb/amd64/Packages", "+wb") as f: with open("deb/amd64/Packages", "+wb") as f:
for i in package_info["amd64"].values(): for i in package_info["amd64"].values():
f.write(i) f.write(i)

2
run.sh
View File

@ -7,7 +7,7 @@ gen_release() {
} }
# check for updates # check for updates
$HOME/go/bin/github-downloader -r -o deb ./get-github-releases.py
find get -type f -name "*.sh" -exec sh {} \; find get -type f -name "*.sh" -exec sh {} \;
cd deb cd deb