#!/usr/bin/env python3 # -*- coding: utf-8 -*- import urllib.request import pkgcrap.parse as parse from pkgcrap.util import maintained_packages_get from functools import cmp_to_key from libversion import version_compare def guess_repo(uri): forges = [ ('git', 'https://github.com', True), ('https://gitlab.com', True), ('https://git.sr.ht', False), ] for forge in forges: if uri.startswith(forge[0]): suffix = '.git' if forge[1] == True else '' return '/'.join(uri.split('/')[:5])+suffix return None def repo_from_metadata(pkg): if len(pkg.metadata.remotes) == 0: return None remote = pkg.metadata.remotes[0] if remote[0] == 'github': return "https://github.com/"+remote[1]+".git" if remote[0] == 'gitlab': return "https://gitlab.com/"+remote[1]+".git" return None def repo_from_egit_uri(pkg): if 'EGIT_REPO_URI' in pkg.ebuilds[0].vars: return pkg.ebuilds[0].vars['EGIT_REPO_URI'].replace('${PN}', pkg.name) def repo_from_src_uri(pkg): for eb in pkg.ebuilds: if 'SRC_URI' in eb.vars: return guess_repo(eb.vars['SRC_URI'].split(' ')[0].replace('${PN}', pkg.name)) def repo_from_homepage(pkg): for eb in pkg.ebuilds: if 'HOMEPAGE' in eb.vars: return guess_repo(eb.vars['HOMEPAGE']) def repo_from_pkg(pkg): repo = repo_from_metadata(pkg) if repo is None: repo = repo_from_egit_uri(pkg) if repo is None: repo = repo_from_src_uri(pkg) if repo is None: repo = repo_from_homepage(pkg) return repo def repo_get_latest(repo, pkg): try: r = urllib.request.urlopen(repo+'/info/refs?service=git-upload-pack') except urllib.error.HTTPError: print(pkg.full_name+':', 'Invalid repo!', repo) return None tags = [] for line in reversed(r.read().decode('utf-8').split("\n")): line = line.split(' ')[-1].split("\t")[-1] if line[:10] == 'refs/tags/' and line[-3:] != '^{}': tag = line[10:] if tag.startswith(pkg.name): tag = tag[len(pkg.name):] if tag.startswith('version'): tag = tag[7:] if not tag[0].isdigit() and tag[1].isdigit(): tag = tag[1:] tags.append(tag) if len(tags) < 1: return None latest = sorted(tags, key=cmp_to_key(version_compare))[-1] if not latest[0].isdigit(): return None return latest def outdated_check(pkg, verbose=False): if len(pkg.ebuilds) == 1 and pkg.ebuilds[0].live: if verbose: print(pkg.full_name+':', 'Only has live ebuild') return repo = repo_from_pkg(pkg) if repo == None: if verbose: print(pkg.full_name+':', 'Repo not found') return current = pkg.version_latest() latest = repo_get_latest(repo, pkg) if latest == None: if verbose: print(pkg.full_name+':', 'Unable to find latest version!') return if version_compare(current, latest) == -1: print(pkg.full_name+':', 'Outdated package!', current, '->', latest) elif verbose: print(pkg.full_name+':', 'Up to date!', current, '->', latest) def main(args): if 'all' in args: packages = maintained_packages_get() verbose = 'verbose' in args else: packages = [parse.package.from_path('.')] verbose = True for pkg in packages: pkg.load() outdated_check(pkg, verbose=verbose)