diff options
| author | 67au <[email protected]> | 2021-12-11 03:03:14 +0800 |
|---|---|---|
| committer | Kunoi Sayami <[email protected]> | 2021-12-11 18:42:40 +0800 |
| commit | dcbf7ce789edce4042c674ab71fa89a25141084b (patch) | |
| tree | 90e60440cd65b13d6ea46e32959b6d14e6b21724 /utils/aur/check-aur-update.py | |
| parent | 84a71e61c3a8674c9cee6f30240fb4d86cc1dc04 (diff) | |
feat(script): add new aur check
Signed-off-by: 67au <[email protected]>
Diffstat (limited to 'utils/aur/check-aur-update.py')
| -rw-r--r-- | utils/aur/check-aur-update.py | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/utils/aur/check-aur-update.py b/utils/aur/check-aur-update.py new file mode 100644 index 0000000..85f02c2 --- /dev/null +++ b/utils/aur/check-aur-update.py @@ -0,0 +1,110 @@ +import asyncio +import argparse +import logging +from collections.abc import Coroutine +from pathlib import Path +from typing import Optional + +import aiohttp +import aiofiles + +from AURUtils.srcinfo import SRCINFO +from AURUtils.version import vercmp + + +MAX_WORKERS = 16 + + +async def check_aur_update( + session: aiohttp.ClientSession, + item: Path, dry_run: bool, + parse_pkgbuild: Optional[Path] = None, +) -> None: + if item.name.startswith('.') or not item.is_dir(): + return + pkgbuild_file = item.joinpath('PKGBUILD') + if not pkgbuild_file.exists(): + logging.warning(f'PKGBUILD not in {str(item)}, SKIP!') + return + srcinfo_file = item.joinpath('.SRCINFO') + if not srcinfo_file.exists(): + if parse_pkgbuild.exists(): + logging.warning(f'.SRCINFO not in {str(item)}, try to parse') + proc = await asyncio.create_subprocess_exec( + f'{str(parse_pkgbuild.resolve())}', + f'{str(pkgbuild_file)}', + stdout=asyncio.subprocess.PIPE, + ) + async with aiofiles.open(srcinfo_file, 'w') as f: + await f.write((await proc.stdout.read()).decode()) + logging.info(f'extract .SRCINFO in {str(item)}') + else: + logging.warning(f'.SRCINFO not in {str(item)}, no tool to parse') + return + async with aiofiles.open(srcinfo_file, 'r') as f: + srcinfo = SRCINFO.parse(await f.read()) + version = srcinfo.get_version() + async with session.get(f'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h={srcinfo.pkgbase}') as resp: + if resp.status != 200: + logging.info(f'{item.name} not register in AUR') + return + new_version = SRCINFO.parse(await resp.text()).get_version() + result = vercmp(new_version, version) + if result == 0: + return + elif result < 0: + logging.warning(f'Warning: {version} is newer than AUR') + else: + if item.joinpath('.git').exists(): + if not dry_run: + await asyncio.create_subprocess_exec('git', '-C', f'{str(item)}', 'pull', 'origin', 'master') + logging.info(f'Upgrade {item.name} from {version} to {new_version}') + else: + logging.info(f'Found update {item.name}({new_version}) (local: {version})') + + +async def with_sem(sem: asyncio.Semaphore, coro: Coroutine): + async with sem: + return await coro + + +async def main() -> int: + parser = argparse.ArgumentParser(description='aur-check-update.py') + parser.add_argument('--dry', help='dry run', action='store_true') + parser.add_argument('--parse-pkgbuild', dest='script', metavar='SCRIPT', + help='a script to parse pkgbuild', + action='store') + parser.add_argument('--max-workers', dest='workers', metavar='MAX_WORKERS', + help=f'aur check max workers, default: {MAX_WORKERS}', + default=MAX_WORKERS, action='store', type=int) + parser.add_argument(dest='repo_dir', metavar='REPO_DIR', help='repository directory', nargs='?') + + args = parser.parse_args() + + dry_run = args.dry + sem = asyncio.Semaphore(args.workers) + + if args.repo_dir is None: + logging.error('repository directory not found') + return 1 + + script_file = Path(args.script) + if args.script is None or not (script_file.is_file() and script_file.exists()): + logging.info(f'Parse script {str(script_file)+" " if args.script is None else ""} not found') + script_file = None + + repo_dir = Path(args.repo_dir) + + async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(10)) as session: + tasks = [asyncio.create_task( + with_sem(sem, check_aur_update(session, item, dry_run, script_file)) + ) for item in repo_dir.iterdir()] + await asyncio.gather(*tasks) + + return 0 + + +if __name__ == '__main__': + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s - %(levelname)s - %(funcName)s - %(lineno)d - %(message)s') + asyncio.run(main())
\ No newline at end of file |
