diff --git a/pkgbuilder/aur.py b/pkgbuilder/aur.py index f6a5be8..f6d48d7 100644 --- a/pkgbuilder/aur.py +++ b/pkgbuilder/aur.py @@ -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) diff --git a/pkgbuilder/build.py b/pkgbuilder/build.py index 3727636..4b0e209 100644 --- a/pkgbuilder/build.py +++ b/pkgbuilder/build.py @@ -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', @@ -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: @@ -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)) @@ -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') @@ -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: @@ -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) diff --git a/pkgbuilder/exceptions.py b/pkgbuilder/exceptions.py index 8fa9755..5436b36 100644 --- a/pkgbuilder/exceptions.py +++ b/pkgbuilder/exceptions.py @@ -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)) @@ -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)) @@ -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)) @@ -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, @@ -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) @@ -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, @@ -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, @@ -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, @@ -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)) diff --git a/pkgbuilder/main.py b/pkgbuilder/main.py index 5f10a32..97472ba 100644 --- a/pkgbuilder/main.py +++ b/pkgbuilder/main.py @@ -38,60 +38,70 @@ def main(source='AUTO', quit=True): if locale != 'LANG locale by AUTHOR ': 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) diff --git a/pkgbuilder/upgrade.py b/pkgbuilder/upgrade.py index 09553da..9d1e130 100644 --- a/pkgbuilder/upgrade.py +++ b/pkgbuilder/upgrade.py @@ -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] ') @@ -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 [] diff --git a/pkgbuilder/wrapper.py b/pkgbuilder/wrapper.py index 2fcf9b6..23ecf09 100644 --- a/pkgbuilder/wrapper.py +++ b/pkgbuilder/wrapper.py @@ -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']