diff options
author | Jiachen Yang | 2015-08-10 19:10:12 +0900 |
---|---|---|
committer | Jiachen Yang | 2015-08-10 19:10:12 +0900 |
commit | 700e1bffd16b935a5db7c1ae973817f1bbb81d39 (patch) | |
tree | 0a19482d1129990b6ef8fa730cae176c4906de89 | |
download | aur-700e1bffd16b935a5db7c1ae973817f1bbb81d39.tar.gz |
takeover pkgtools
-rw-r--r-- | .SRCINFO | 31 | ||||
-rw-r--r-- | PKGBUILD | 45 | ||||
-rw-r--r-- | pip2arch.py | 255 | ||||
-rw-r--r-- | pkgtools.install | 42 | ||||
-rwxr-xr-x | whoneeds.bash | 4 |
5 files changed, 377 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..36e4db7f4374 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,31 @@ +pkgbase = pkgtools + pkgdesc = A collection of scripts for Arch Linux packages + pkgver = 25 + pkgrel = 5 + url = https://bbs.archlinux.org/viewtopic.php?pid=384196 + install = pkgtools.install + arch = any + license = GPL + depends = coreutils + depends = bash>=4 + depends = pcre + depends = libarchive + depends = python + optdepends = abs: Provides PKGBUILD prototypes for newpkg + optdepends = gem2arch: Create PKGBUILD from Ruby Gem Package + optdepends = pkgfile: Required to use pkgconflict + optdepends = namcap: Package analyzer + provides = newpkg + provides = pip2arch + backup = etc/pkgtools/newpkg.conf + backup = etc/pkgtools/pkgfile.conf + backup = etc/pkgtools/spec2arch.conf + source = pkgtools-v25.tar.gz::https://github.com/Daenyth/pkgtools/tarball/v25 + source = https://raw.githubusercontent.com/bluepeppers/pip2arch/master/pip2arch.py + source = whoneeds.bash + md5sums = 9e9d7aad5ba8ecee1b798c3ed4e0a0a7 + md5sums = 9267993a72489019ec1536c887304374 + md5sums = e0b7b1b320ead7a552be1b9eae29b494 + +pkgname = pkgtools + diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..ee1e334cfcf3 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,45 @@ +# Maintainer: farseerfc <farseerfc@archlinuxcn.org> +# Contributor: Nyarcel <nyarcel AT SPAMFREE gmail DOT com> +# Contributor: Lara Maia <lara@craft.net.br> +# Contributor: BlackICE <manfredi at gmail.com> +# Contributor: Daenyth <Daenyth+Arch AT gmail DOT com> + +pkgname=pkgtools +pkgver=25 +pkgrel=5 +pkgdesc="A collection of scripts for Arch Linux packages" +arch=('any') +url="https://bbs.archlinux.org/viewtopic.php?pid=384196" +license=('GPL') +depends=('coreutils' # for comm in whoneeds + 'bash>=4' + 'pcre' + 'libarchive' + 'python') +optdepends=('abs: Provides PKGBUILD prototypes for newpkg' + 'gem2arch: Create PKGBUILD from Ruby Gem Package' + 'pkgfile: Required to use pkgconflict' + 'namcap: Package analyzer') +provides=('newpkg' 'pip2arch') +backup=('etc/pkgtools/newpkg.conf' + 'etc/pkgtools/pkgfile.conf' + 'etc/pkgtools/spec2arch.conf') +install=pkgtools.install +source=("${pkgname}-v${pkgver}.tar.gz::https://github.com/Daenyth/pkgtools/tarball/v$pkgver" + "https://raw.githubusercontent.com/bluepeppers/pip2arch/master/pip2arch.py" # submodule issue + 'whoneeds.bash') +md5sums=('9e9d7aad5ba8ecee1b798c3ed4e0a0a7' + '9267993a72489019ec1536c887304374' + 'e0b7b1b320ead7a552be1b9eae29b494') + +prepare() { + cp -f pip2arch.py Daenyth-"$pkgname"-*/scripts/pip2arch/ +} + +package() { + cp whoneeds.bash "$srcdir"/Daenyth-"$pkgname"-*/scripts/ + + cd Daenyth-"$pkgname"-* + + make DESTDIR="$pkgdir" install +} diff --git a/pip2arch.py b/pip2arch.py new file mode 100644 index 000000000000..6b1d9692ad8d --- /dev/null +++ b/pip2arch.py @@ -0,0 +1,255 @@ +#!/usr/bin/python +from __future__ import unicode_literals +from __future__ import with_statement + +import sys +import datetime +import logging +import argparse +import re + +# make this script work for python2 and python3 +# the try will fail on python3 +try: + input = raw_input + from xmlrpclib import ServerProxy +except NameError: + from xmlrpc.client import ServerProxy + +BLANK_PKGBUILD = """\ +#Automatically generated by pip2arch on {date} + +pkgname={pkg.outname} +pkgver={pkg.version} +pkgrel=1 +pkgdesc="{pkg.description}" +url="{pkg.url}" +depends=('{pkg.pyversion}' {depends}) +makedepends=('{pkg.distributepackage}' {makedepends}) +license=('{pkg.license}') +arch=('any') +source=('{pkg.download_url}') +md5sums=('{pkg.md5}') + +build() {{ + cd $srcdir/{pkg.name}-{pkg.version} + {pkg.pyversion} setup.py build +}} + +package() {{ + cd $srcdir/{pkg.name}-{pkg.version} + {pkg.pyversion} setup.py install --root="$pkgdir" --optimize=1 {pkg.setup_args} +}} +""" + +SOURCEFILE_TYPE_RE = re.compile(".*\.(tar|zip|gz|z|bz2?|xz)", re.IGNORECASE) + +class pip2archException(Exception): pass +class VersionNotFound(pip2archException): pass +class LackOfInformation(pip2archException): pass + +class Package(object): + logging.info('Creating Server Proxy object') + client = ServerProxy('http://pypi.python.org/pypi') + depends = [] + makedepends = [] + data_received = False + setup_args = '' + + def get_package(self, name, outname, pyversion ,version=None): + if version is None: + versions = self.client.package_releases(name) + if len(versions) > 1: + version = self.choose_version(versions) + else: + logging.info('Using version %s' % versions[0]) + version = versions[0] + self.version = version + self.pyversion = pyversion + + data = self.client.release_data(name, version) + logging.info('Got release_data from PyPi') + + raw_urls = self.client.release_urls(name, version) + logging.info('Got release_urls from PyPi') + if not len(data): + raise VersionNotFound('PyPi did not return any information for version {0}'.format(self.version)) + elif not len(raw_urls): + if 'download_url' in data: + download_url = data['download_url'] + if SOURCEFILE_TYPE_RE.match(data['download_url']) is None: + raise LackOfInformation("Couldn't find any suitable source") + else: + urls = {'url': download_url} + logging.warning('Got download link but no md5, you may have to search it by youself or generate it') + else: + raise LackOfInformation('PyPi did not return the necessary information to create the PKGBUILD') + else: + urls = {} + for url in raw_urls: + if SOURCEFILE_TYPE_RE.match(url['filename']): + urls = url + if not urls: + raise pip2archException + ('Selected package version had no suitable sources') + logging.info('Parsed release_urls data') + + + self.distributepackage = 'python2-distribute' if\ + self.pyversion != 'python' else 'python3' + logging.info("Set distribute package as {0}".format(self.distributepackage)) + + if outname is not None: + self.outname = outname.lower() + elif any(re.search(r'Librar(ies|y)', item) for item in data['classifiers']): + #if this is a library + self.outname = '{pyversion}-{pkgname}'.format( + pyversion=self.pyversion, pkgname=name).lower() + logging.info('Automaticly added {0} to the front of the package'.format(self.pyversion)) + else: + self.outname = name.lower() + + #check for licenes texts + if len(data.get('license', '')) > 10: + self.license = 'CUSTOM' + else: + self.license = data.get('license', 'UNKNOWN') + + try: + self.name = data['name'] + self.description = data['summary'] + self.download_url = urls.get('url', '') + self.md5 = urls.get('md5_digest', '') + self.url = data.get('home_page', '') + self.depends = data.get('requires', []) + except KeyError: + raise pip2archException('PyPi did not return needed information') + logging.info('Parsed other data') + self.data_received = True + + def search(self, term, interactive=False): + results = self.client.search({'description': term[1:], + 'name': term[1:]}, + 'or') + logging.info('Got search results for term {term} from PyPi server'.format(term=term)) + + #If no results + if not results: + print ('No packages found') + return + for i, result in enumerate(results): + i += 1 + print ('{index}. {name} - {summary}'.format(index=i, name=result['name'], summary=result['summary'])) + + #If we don't want talking, exit here + if not interactive: + #self.data_received = False + return + + selection = raw_input('Enter the number of the PyPi package you would like to process\n') + + try: + selection = int(selection.strip()) + selection -= 1 + chosen = results[selection] + except (TypeError, IndexError): + print ('Not a valid selection. Must be integer in range 1 - {length}'.format(length=len(results))) + retry = raw_input('Retry? [Y/n]\n') + if retry.strip()[0].lower() != 'n': + #offer recurse on failure, maybe user will be smarter this time -.- + return self.search(term) + else: + return + + name = chosen['name'] + outname = chosen['name'] + + return self.get_package(name, outname) + + def choose_version(self, versions): + print ('Multiple versions found:') + print (', '.join(versions)) + ver = raw_input('Which version would you like to use? ') + if ver in versions: + return ver + else: + print ('That was NOT one of the choices...') + print ('Try again') + return self.choose_version(versions) + + def add_depends(self, depends): + self.depends += depends + + def add_makedepends(self, makedepends): + self.makedepends += makedepends + + def render(self): + depends = "'" + "' '".join(d for d in self.depends) + "'" if self.depends else '' + makedepends = "'" + "' '".join(d for d in self.makedepends) + "'" if self.makedepends else '' + return BLANK_PKGBUILD.format(pkg=self, + date=datetime.date.today(), + depends=depends, + makedepends=makedepends) + +def set_logging_level(level_str): + level = getattr(logging, level_str.upper()) + logging.root.setLevel(level) + +def main(): + parser = argparse.ArgumentParser(description='Convert a PyPi package into an Arch Linux PKGBUILD.') + parser.add_argument('pkgname', metavar='PKGNAME', action='store', + help='Name of PyPi package for pip2arch to process') + parser.add_argument('-v', '--version', dest='version', action='store', + help='The version of the speciied PyPi package to process') + parser.add_argument('-p', '--python-version', dest='pyversion', action='store', + default='python', choices=('python','python2'), + help='The python version to build and install the package with') + parser.add_argument('-o', '--output', dest='outfile', action='store', + default='PKGBUILD', + help='The file to output the generated PKGBUILD to') + parser.add_argument('-s', '--search', dest='search', action='store_true', + help="Search for given package name, instead of building PKGBUILD") + parser.add_argument('-i', '--interactive', dest='interactive', action='store_true', + help="Makes all commands interactive, prompting user for input.") + parser.add_argument('-d', '--dependencies', dest='depends', action='append', + help="The name of a package that should be added to the depends array") + parser.add_argument('-m', '--make-dependencies', dest='makedepends', action='append', + help="The name of a package that should be added to the makedepends array") + parser.add_argument('-n', '--output-package-name', dest='outname', action='store', default=None, + help='The name of the package that pip2arch will generate') + parser.add_argument('--logging-level', dest='logging_level', action='store', default='warning', choices=('warning', 'info', 'debug'), + help='The level of logging messages to show') + parser.add_argument('-b', '--build-args', dest='build_args', action='store', + help='Custom arguments for the python install setup.py file') + + args = parser.parse_args() + + set_logging_level(args.logging_level) + + p = Package() + + if args.search: + p.search(args.pkgname, interactive=args.interactive) + else: + p.get_package(name=args.pkgname, pyversion= args.pyversion, + version=args.version, outname=args.outname) + + if args.depends: + p.add_depends(args.depends) + if args.makedepends: + p.add_makedepends(args.makedepends) + if args.build_args: + p.setup_args = args.build_args + if p.data_received: + print ('Got package information') + with open(args.outfile, 'w') as f: + f.write(p.render()) + print ('PKGBUILD written') + +if __name__ == '__main__': + try: + main() + except pip2archException as e: + sys.exit('Pip2Arch error: {0}'.format(e)) + else: + sys.exit(0) diff --git a/pkgtools.install b/pkgtools.install new file mode 100644 index 000000000000..2395698bc9b4 --- /dev/null +++ b/pkgtools.install @@ -0,0 +1,42 @@ +is_update_from() { + res="`vercmp $1 $2`" + case $res in + '-1'|'0') return 0;; + '1') return 1;; + esac +} + +## arg 1: the new package version +## arg 2: the old package version +post_upgrade() { + if is_update_from $2 15-1; then + echo " - pkgtools now uses \$XDG_CONFIG_HOME for all user-specific configuration." + echo " run «mv ~/.pkgtools \"\$XDG_CONFIG_HOME/pkgtools\"»" + fi + if is_update_from $2 18-1; then + echo " - newpkg has been rewritten to be completely modular. See here for more info:" + echo " http://github.com/Daenyth/pkgtools/commit/2d37197" + fi + if is_update_from $2 22-1; then + echo " - This is the largest release in a long time. This updates all python scripts" + echo " to py3k." + echo " - This version of pkgtools includes a new tool called gem2arch, for automating" + echo " ruby gem packaging" + fi + if is_update_from $2 24-2; then + echo " - pkgtools no longer provides the pkgfile command. This is now provided by the" + echo " 'pkgfile' package." + echo " - you may want to clean /var/cache/pkgtools/lists" + fi + if is_update_from $2 25-4; then + echo " - As pactree can print reverse dependency tree since the release of pacman 3.4," + echo " whoneeds is just a small wrapper around pactree now." + fi +} + +## arg 1: the old package version +post_remove() { + cat << _EOM + - You may want to clean /var/cache/pkgtools/lists +_EOM +} diff --git a/whoneeds.bash b/whoneeds.bash new file mode 100755 index 000000000000..cf9371191ac3 --- /dev/null +++ b/whoneeds.bash @@ -0,0 +1,4 @@ +#! /bin/bash + +echo "Packages that depend on [$1]" +comm -12 <(pactree -ru $1|sort) <(pacman -Qqe) | grep -v ^$1$ | sed 's/^/ /' |