summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiachen Yang2015-08-10 19:10:12 +0900
committerJiachen Yang2015-08-10 19:10:12 +0900
commit700e1bffd16b935a5db7c1ae973817f1bbb81d39 (patch)
tree0a19482d1129990b6ef8fa730cae176c4906de89
downloadaur-700e1bffd16b935a5db7c1ae973817f1bbb81d39.tar.gz
takeover pkgtools
-rw-r--r--.SRCINFO31
-rw-r--r--PKGBUILD45
-rw-r--r--pip2arch.py255
-rw-r--r--pkgtools.install42
-rwxr-xr-xwhoneeds.bash4
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/^/ /'