Skip to content

Commit

Permalink
Revamped dependency detection. Fixed flake8 woes.
Browse files Browse the repository at this point in the history
Today’s commits are brought to you by python-pyside.

Signed-off-by: Chris “Kwpolska” Warrick <[email protected]>
  • Loading branch information
Kwpolska committed Sep 6, 2013
1 parent fcec867 commit bd372fe
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 69 deletions.
3 changes: 2 additions & 1 deletion pkgbuilder/aur.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ def jsonmultiinfo(self, args):
return '{"type": "info", "resultcount": 0, "results": []}'

try:
req = requests.get(self.rpc, params={'type': 'multiinfo', 'arg[]': args})
req = requests.get(self.rpc, params={'type': 'multiinfo', 'arg[]':
args})
req.raise_for_status()
except requests.exceptions.ConnectionError as e:
raise ConnectionError(e.args[0].reason, e)
Expand Down
61 changes: 45 additions & 16 deletions pkgbuilder/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import subprocess
import functools
import glob
import datetime

__all__ = ['validate', 'install', 'safeupgrade', 'auto_build', 'download',
'rsync', 'extract', 'prepare_deps', 'depcheck', 'fetch_runner',
Expand Down Expand Up @@ -81,7 +80,8 @@ def install(pkgpaths, sigpaths, asdeps, uopt=''):
DS.fancy_msg(_('Installing built packages...'))

DS.log.info('pkgs={0}; sigs={1}'.format(pkgpaths, sigpaths))
DS.log.debug('cp {0} {1} /var/cache/pacman/pkg/'.format(pkgpaths, sigpaths))
DS.log.debug('cp {0} {1} /var/cache/pacman/pkg/'.format(pkgpaths,
sigpaths))
DS.sudo(['cp'] + pkgpaths + sigpaths + ['/var/cache/pacman/pkg/'])

if asdeps:
Expand Down Expand Up @@ -151,7 +151,8 @@ def auto_build(pkgname, performdepcheck=True,
for pkgname2 in build_result[1]:
toinstall = []
if pkgname2 in completelist:
if completelist.index(pkgname2) < completelist.index(pkgname):
if (completelist.index(pkgname2) <
completelist.index(pkgname)):
# Already built the package.
toinstall, sigs = find_packagefile(
os.path.join(os.getcwd(), pkgname2))
Expand Down Expand Up @@ -251,16 +252,41 @@ def extract(filename):

def prepare_deps(pkgbuild_path):
"""Gets (make)depends from a PKGBUILD and returns them."""
# I decided to use a subprocess instead of pyparsing magic. Less
# dependencies for us and no fuckups EVER. And if the PKGBUILD is
# malicious, we speed up the destroying of the user system by about 10
# seconds, so it makes no sense not to do this. And it takes only 7 lines
# instead of about 40 in the pyparsing implementation.

deps = subprocess.check_output('source ' + pkgbuild_path + '; for i in '
'${depends[*]}; do echo $i; done; for '
'i in ${makedepends[*]}; do echo $i; '
'done', shell=True)
# Back in the day, there was a comment praising replacing pyparsing
# with shell magic. It claimed that we will have no fuckups ever.
# OF COURSE WE DID. SPLIT PACKAGES. PKGBUILDer crashed when it
# encountered one. Here comes the output from sh:
#
# PKGBUILD: line XX: `package_package-name': not a valid identifier
#
# shell=True with subprocess.check_output() uses /bin/sh, which is more
# strict than /bin/bash used by makepkg.
#
# So, I replaced it by a call to /usr/bin/bash (which is equivalent
# to /bin/bash on Arch Linux).
#
# And if the PKGBUILD is malicious, we speed up the destroying of the user
# system by about 10 seconds, so it makes no sense not to do this.
# Moreover, it takes only 7 lines instead of about 40 in the pyparsing
# implementation.
#
# PS. I am amazed that `bash -c` ignores !events. That saved me one
# replace. I am also amazed that it ignored \a and \n.
#
# FULL DISCLOSURE: the following path was used to test the current
# implementation. I may have not noticed
# something else that is not accounted for by
# this very path, so if you know that some
# breakage occurs, tell me.
#
# I am an "idiot"/no, 'really'/exclamation!mark, seriously/backsl\ash/a\n

ppath = pkgbuild_path.replace('"', r'\"').join(('"', '"'))

deps = subprocess.check_output(('/usr/bin/bash', '-c', 'source ' +
ppath + ';for i in ${depends[*]};'
'do echo $i;done;for i in '
'${makedepends[*]};do echo $i; done'))
deps = deps.decode('utf-8')
deps = deps.split('\n')

Expand Down Expand Up @@ -320,13 +346,15 @@ def depcheck(depends, pkgobj=None):
if not depmatch:
ssat = pyalpm.find_satisfier(syncpkgs, dep)
if ssat:
depmatch = _test_dependency(ssat.version, diff, ver)
depmatch = _test_dependency(ssat.version, diff,
ver)
parseddeps[dep] = 1

if not depmatch:
asat = pkgbuilder.utils.info([dep])
if asat:
depmatch = _test_dependency(asat[0].version, diff, ver)
depmatch = _test_dependency(asat[0].version,
diff, ver)
parseddeps[dep] = 2

if not depmatch:
Expand Down Expand Up @@ -402,7 +430,8 @@ def fetch_runner(pkgnames, preprocessed=False):
syncpkgs = []
for j in [i.pkgcache for i in DS.pyc.get_syncdbs()]:
syncpkgs.append(j)
syncpkgs = functools.reduce(lambda x, y: x + y, syncpkgs)
syncpkgs = functools.reduce(lambda x, y: x + y,
syncpkgs)
abspkg = pyalpm.find_satisfier(syncpkgs, pkgname)
pkg = pkgbuilder.package.ABSPackage.from_pyalpm(abspkg)

Expand Down
9 changes: 9 additions & 0 deletions pkgbuilder/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
class PBException(Exception):
"""Base exception for PKGBUILDer."""
qualname = 'PBException'

def __init__(self, msg, source, *args, **kwargs):
"""Throw an error to the log and take the arguments."""
DS.log.error('({0:<20}) {1}'.format(self.qualname, msg))
Expand All @@ -40,6 +41,7 @@ def __str__(self):
class AURError(PBException):
"""AUR-related errors."""
qualname = 'AURError'

def __init__(self, msg, *args, **kwargs):
"""Throw an error to the log and take the arguments."""
DS.log.error('({0:<20}) {1}'.format(self.qualname, msg))
Expand All @@ -56,6 +58,7 @@ def __str__(self):
class MakepkgError(PBException):
"""makepkg errors (return codes)"""
qualname = 'MakepkgError'

def __init__(self, retcode, *args, **kwargs):
"""Throw an error to the log and take the arguments."""
DS.log.error('({0:<20}) {1}'.format(self.qualname, retcode))
Expand All @@ -72,6 +75,7 @@ def __str__(self):
class NetworkError(PBException):
"""Network-related errors."""
qualname = 'NetworkError'

def __init__(self, msg, source, *args, **kwargs):
"""Throw an error to the log and take the arguments."""
DS.log.error('({0:<20}) {1} (via {2})'.format(self.qualname, msg,
Expand All @@ -96,6 +100,7 @@ def __str__(self):
class ConnectionError(NetworkError):
"""A connection error."""
qualname = 'ConnectionError'

def __str__(self):
return _('Connection error: {0} (via {1})').format(self.msg,
self.source)
Expand All @@ -104,6 +109,7 @@ def __str__(self):
class HTTPError(NetworkError):
"""An HTTP error."""
qualname = 'HTTPError'

def __init__(self, source, origin, *args, **kwargs):
DS.log.error('({0:<20}) {1} (via {2})'.format(self.qualname,
source.status_code,
Expand Down Expand Up @@ -131,6 +137,7 @@ def __str__(self):
class PackageError(PBException):
"""Package-related errors."""
qualname = 'PackageError'

def __init__(self, msg, source, *args, **kwargs):
"""Throw an error to the log and take the arguments."""
DS.log.error('({0:<20}) {1} (from {2})'.format(self.qualname, msg,
Expand All @@ -147,6 +154,7 @@ def __str__(self):

class PackageNotFoundError(PackageError):
qualname = 'PackageNotFoundError'

def __init__(self, name, source, *args, **kwargs):
"""Throw an error to the log and take the arguments."""
DS.log.error('({0:<20}) {1} (via {2})'.format(self.qualname, name,
Expand All @@ -165,6 +173,7 @@ def __str__(self):
class SanityError(PBException):
"""Sometimes PKGBUILDer or one of its friends can go insane."""
qualname = 'SanityError'

def __init__(self, msg, source, *args, **kwargs):
DS.log.error('({0:<20}) {1} (via {2})'.format(self.qualname, msg,
source))
Expand Down
106 changes: 58 additions & 48 deletions pkgbuilder/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,60 +38,70 @@ def main(source='AUTO', quit=True):
if locale != 'LANG locale by AUTHOR <[email protected]>':
verstring = ' — '.join([verstring, locale])
DS.log.info('Initialized, parsing arguments.')
parser = argparse.ArgumentParser(description=_('An AUR helper'
' (and library) in Python 3.'),
epilog=_('Also accepting ABS '
'packages.'))
parser.add_argument('-V', '--version', action='version',
version=verstring,
help=_('show version number and quit'))
parser.add_argument('pkgnames', metavar=_('PACKAGE'), action='store',
nargs='*', help=_('AUR/ABS packages to build'))
parser = argparse.ArgumentParser(
description=_('An AUR helper (and library) in Python 3.'),
epilog=_('Also accepting ABS packages.'))
parser.add_argument(
'-V', '--version', action='version', version=verstring,
help=_('show version number and quit'))
parser.add_argument(
'pkgnames', metavar=_('PACKAGE'), action='store', nargs='*',
help=_('AUR/ABS packages to build'))

argopr = parser.add_argument_group(_('operations'))
argopr.add_argument('-F', '--fetch', action='store_true',
default=False, dest='fetch',
help=_('fetch package files'))
argopr.add_argument('--userfetch', action='append',
dest='userfetch', metavar=_('USER'),
help=_('fetch all package files of an user'))
argopr.add_argument(
'-F', '--fetch', action='store_true', default=False, dest='fetch',
help=_('fetch package files'))
argopr.add_argument(
'--userfetch', action='append', dest='userfetch',
metavar=_('USER'), help=_('fetch all package files of an user'))
argopr.add_argument('-i', '--info', action='store_true', default=False,
dest='info', help=_('view package information'))
argopr.add_argument('-s', '--search', action='store_true',
default=False, dest='search', help=_('search the '
'AUR for matching strings'))
argopr.add_argument('-u', '--sysupgrade', action='count',
default=False, dest='upgrade',
help=_('upgrade installed AUR packages'))
argopr.add_argument(
'-s', '--search', action='store_true',
default=False, dest='search', help=_('search the AUR for '
'matching strings'))
argopr.add_argument(
'-u', '--sysupgrade', action='count', default=False,
dest='upgrade', help=_('upgrade installed AUR packages'))

argopt = parser.add_argument_group(_('options'))
argopt.add_argument('-c', '--clean', action='store_true',
default=False, dest='cleanup', help=_('clean up '
'work files after build'))
argopt.add_argument('-C', '--nocolors', action='store_false',
default=True, dest='color', help=_('don\'t use '
'colors in output'))
argopt.add_argument('--debug', action='store_true', default=False,
dest='debug', help=_('display debug messages'))
argopt.add_argument('-d', '--nodepcheck', action='store_false',
default=True, dest='depcheck', help=_('don\'t '
'check dependencies (may break makepkg)'))
argopt.add_argument('-D', '--vcsupgrade', action='store_true',
default=False, dest='vcsup', help=_('upgrade '
'all the VCS/date-versioned packages'))
argopt.add_argument('-v', '--novalidation', action='store_false',
default=True, dest='validate', help=_('don\'t '
'check if packages were installed after build'))
argopt.add_argument('-w', '--buildonly', action='store_false',
default=True, dest='pkginst', help=_('don\'t '
'install packages after building'))
argopt.add_argument('-S', '--sync', action='store_true', default=False,
dest='pac', help=_('pacman-like mode'))
argopt.add_argument('--safeupgrade', action='store_true',
default=False, dest='safeupgrade', help=_(
'perform a failsafe upgrade of PKGBUILDer'))
argopt.add_argument('-y', '--refresh', action='store_true',
default=False, dest='pacupd', help=_('(dummy)'))
argopt.add_argument(
'-c', '--clean', action='store_true',
default=False, dest='cleanup', help=_('clean up work files after '
'build'))
argopt.add_argument(
'-C', '--nocolors', action='store_false',
default=True, dest='color', help=_('don\'t use colors in output'))
argopt.add_argument(
'--debug', action='store_true', default=False,
dest='debug', help=_('display debug messages'))
argopt.add_argument(
'-d', '--nodepcheck', action='store_false',
default=True, dest='depcheck', help=_('don\'t check dependencies '
'(may break makepkg)'))
argopt.add_argument(
'-D', '--vcsupgrade', action='store_true',
default=False, dest='vcsup', help=_('upgrade all the VCS/'
'date-versioned packages'))
argopt.add_argument(
'-v', '--novalidation', action='store_false',
default=True, dest='validate',
help=_('don\'t check if packages were installed after build'))
argopt.add_argument(
'-w', '--buildonly', action='store_false',
default=True, dest='pkginst', help=_('don\'t install packages '
'after building'))
argopt.add_argument(
'-S', '--sync', action='store_true', default=False, dest='pac',
help=_('pacman-like mode'))
argopt.add_argument(
'--safeupgrade', action='store_true', default=False,
dest='safeupgrade', help=_('perform a failsafe upgrade of '
'PKGBUILDer'))
argopt.add_argument(
'-y', '--refresh', action='store_true', default=False,
dest='pacupd', help=_('(dummy)'))

if source != 'AUTO':
args = parser.parse_args(source)
Expand Down
4 changes: 2 additions & 2 deletions pkgbuilder/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def auto_upgrade(downgrade=False, vcsup=False):

if DS.pacman:
print(':: ' + _('The following packages should be upgraded '
'first:'))
'first:'))
print(' {0}'.format(pkgbname))
print(':: ' + _('Do you want to cancel the current operation'))
query = ':: ' + _('and upgrade these packages now? [Y/n] ')
Expand Down Expand Up @@ -279,4 +279,4 @@ def auto_upgrade(downgrade=False, vcsup=False):
if yesno.lower().strip().startswith('y') or yesno.strip() == '':
return upgnames
else:
return []
return []
4 changes: 2 additions & 2 deletions pkgbuilder/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ def wrapper(source='AUTO'):
'root']

pbshort = ['D', 'C', 'F']
pblong = ['fetch', 'userfetch', 'vcsupgrade', 'nocolors', 'nodepcheck', 'novalidation',
'buildonly']
pblong = ['fetch', 'userfetch', 'vcsupgrade', 'nocolors', 'nodepcheck',
'novalidation', 'buildonly']

commonshort = ['S', 'd', 'i', 's', 'v', 'w']
commonlong = ['debug', 'info', 'search', 'sync']
Expand Down

0 comments on commit bd372fe

Please sign in to comment.