pkgcrap/pkgcrap/outdated_check.py

112 lines
3.5 KiB
Python

#!/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)