Loading aurbot 0 → 100755 +242 −0 Original line number Diff line number Diff line #!/usr/bin/env python # Copyright Sébastien Luttringer <seblu@seblu.net> # Started 30/10/2011 import os import time import json import glob import shutil import argparse import tempfile import tarfile import urllib.request import configparser import subprocess import AUR class Repositories(dict): ''' Repository class abstract all stuff around repositories ''' def init(self, repo): ''' Init a repository ''' print('Initialize %s' % repo) # create repository path if self[repo]['path'] is not None: os.makedirs(self[repo]['path'], exist_ok=True) # create chroot if self[repo]['chroot'] is not None: root = os.path.join(self[repo]['chroot'], 'root') if not os.path.exists(root): os.makedirs(self[repo]['chroot'], exist_ok=True) cmds = ['mkarchroot', '-n', root, 'base', 'base-devel', 'sudo'] if self[repo]['arch'] == 'i686': cmds.insert(0, 'linux32') elif self[repo]['arch'] == 'x86_64': cmds.insert(0, 'linux64') if os.geteuid() != 0: cmds.insert(0, 'sudo') subprocess.check_call(cmds, close_fds=True) def load(self, conf_path, db_path): ''' Load repositories configuration ''' try: # read config cp = configparser.RawConfigParser() cp.read(conf_path) for sec in cp.sections(): self[sec] = { 'dbname': '%s.db.tar.gz' % sec, 'arch': None, 'path': None, 'chroot': None, 'build_command': None} self[sec].update(cp.items(sec)) self[sec]['packages'] = cp.get(sec, 'packages', fallback='').split() # checks if self[sec]['arch'] not in ('x86_64', 'i686'): raise Exception('Invalid arch') if self[sec]['path'] is None: raise Exception('Invalid repository path') except Exception as e: print('Unable to load package database: %s' % e) def tobuild(self): ''' of packages to build ''' for repo in self: for pkg in self[repo]['packages']: yield (repo, pkg) def add(self, repo, files=[]): ''' Add pkg to repo ''' dbpath = os.path.join(self[repo]['path'], self[repo]['dbname']) for f in files: dstpath = os.path.join(self[repo]['path'], os.path.basename(f)) shutil.copy(f, dstpath) subprocess.check_call(['repo-add', dbpath, dstpath], close_fds=True) class AURPackages(dict): ''' Packages class handle package informations ''' aur_url = 'https://aur.archlinux.org' aur_min_update_interval = 60 def load(self, path): ''' Load packages informations from a file ''' if not os.path.exists(path): return try: self.update(json.load(open(path, "r"))) except Exception as e: print('Unable to load package database: %s' % e) def save(self, path): ''' Save packages informations to a file ''' json.dump(self, open(path, 'w')) def register(self, pkg, update=False): if pkg not in self or update: self.aur_update(pkg) def aur_update(self, pkg): ''' update information about a package ''' if (pkg in self and 'aurbuilder_update' in self[pkg] and self[pkg]['aurbuilder_update'] + self.aur_min_update_interval > time.time()): return info = AUR.aur_query('info', pkg) if info is not None: self[pkg] = info self[pkg]['aurbuilder_update'] = time.time() else: print('No package %s' % pkg) def extract(self, pkg, path): ''' Extract aur source tarball inside a directory path ''' # feed package db self.register(pkg, update=args.update) # get tarball fo = urllib.request.urlopen('%s/%s' % (self.aur_url, self[pkg]['URLPath'])) # extract tarball tarball = tarfile.open(mode='r|*', fileobj=fo) tarball.extractall(path) ################ #Parser commands ################ def c_init(args): ''' Init command ''' for repo in args.repos: args.repos.init(repo) def c_update(args): ''' Update command ''' args.aurpkg.update() def c_build(args): ''' Build command ''' # /dev/null fd devnull = open('/dev/null', 'w') # start building for repo, pkg in repositories.tobuild(): print('Building %s in %s' % (repo, pkg)) # creating temp directory to extract tarball tempd = tempfile.TemporaryDirectory() # extract package inside tempdir aurpkg.extract(pkg, tempd.name) # compile try: builddir = os.path.join(tempd.name, pkg) os.chdir(builddir) # subprocess.check_call(['makechrootpkg', # '-c', '-r', repositories[reponame]['chroot']]) subprocess.check_call(['makepkg','-c'], close_fds=True, stdout=devnull, stderr=devnull) files = glob.glob(os.path.join(builddir, '*.pkg.tar.xz')) if len(files) == 0: raise Exception('Unable to find binary packages') except Exception as e: # FIXME: mark package as invalid to build print('build failure: %s' % e) finally: os.chdir(cwd) # add to repository try: repositories.add(repo, files) except Exception as e: print('repository modification failure: %s' % e) pass # we start here parser = argparse.ArgumentParser() parser.add_argument('-r', '--repo-conf', default='repositories.conf', help='repository definitions') parser.add_argument('-R', '--repo-db', default='repositories.json', help='repositories databases') parser.add_argument('-p', '--aurpkg-db', default='packages.json', help='AUR packages database') parser.add_argument('-q', '--quiet', action='store_true', default=False, help='Quiet mode') sp = parser.add_subparsers() p_init = sp.add_parser('init') p_init.set_defaults(func=c_init) p_update = sp.add_parser('update') p_update.set_defaults(func=c_update) p_build = sp.add_parser('build') p_build.set_defaults(func=c_build) #p_update.add_argument('-u', '--update', action='store_true', default=False, # help='Connect AUR to update packages db') # parse args args = parser.parse_args() # path must be absolute! args.repo_conf = os.path.abspath(args.repo_conf) args.repo_db = os.path.abspath(args.repo_db) args.aurpkg_db = os.path.abspath(args.aurpkg_db) # store current directory cwd = os.getcwd() # load repo mananger repos = Repositories() repos.load(args.repo_conf, args.repo_db) # load package manager aurpkg = AURPackages() aurpkg.load(args.aurpkg_db) # add aurpkg and repos to args args.aurpkg = aurpkg args.repos = repos # run command function args.func(args) # save aur packages db aurpkg.save(args.aurpkg_db) repositories.conf 0 → 100644 +20 −0 Original line number Diff line number Diff line [seblu-aur-i686] arch = i686 path=repo/i686 chroot=chroots/i686 packages = atftp lantencytop rar rootcheck [seblu-aur-x86_64] dbname = seblu-aur.db.tar.gz arch = x86_64 path=repo/amd64 chroot=chroots/amd64 build_command = makepkg -c packages = atftp latencytop rar rootcheck Loading
aurbot 0 → 100755 +242 −0 Original line number Diff line number Diff line #!/usr/bin/env python # Copyright Sébastien Luttringer <seblu@seblu.net> # Started 30/10/2011 import os import time import json import glob import shutil import argparse import tempfile import tarfile import urllib.request import configparser import subprocess import AUR class Repositories(dict): ''' Repository class abstract all stuff around repositories ''' def init(self, repo): ''' Init a repository ''' print('Initialize %s' % repo) # create repository path if self[repo]['path'] is not None: os.makedirs(self[repo]['path'], exist_ok=True) # create chroot if self[repo]['chroot'] is not None: root = os.path.join(self[repo]['chroot'], 'root') if not os.path.exists(root): os.makedirs(self[repo]['chroot'], exist_ok=True) cmds = ['mkarchroot', '-n', root, 'base', 'base-devel', 'sudo'] if self[repo]['arch'] == 'i686': cmds.insert(0, 'linux32') elif self[repo]['arch'] == 'x86_64': cmds.insert(0, 'linux64') if os.geteuid() != 0: cmds.insert(0, 'sudo') subprocess.check_call(cmds, close_fds=True) def load(self, conf_path, db_path): ''' Load repositories configuration ''' try: # read config cp = configparser.RawConfigParser() cp.read(conf_path) for sec in cp.sections(): self[sec] = { 'dbname': '%s.db.tar.gz' % sec, 'arch': None, 'path': None, 'chroot': None, 'build_command': None} self[sec].update(cp.items(sec)) self[sec]['packages'] = cp.get(sec, 'packages', fallback='').split() # checks if self[sec]['arch'] not in ('x86_64', 'i686'): raise Exception('Invalid arch') if self[sec]['path'] is None: raise Exception('Invalid repository path') except Exception as e: print('Unable to load package database: %s' % e) def tobuild(self): ''' of packages to build ''' for repo in self: for pkg in self[repo]['packages']: yield (repo, pkg) def add(self, repo, files=[]): ''' Add pkg to repo ''' dbpath = os.path.join(self[repo]['path'], self[repo]['dbname']) for f in files: dstpath = os.path.join(self[repo]['path'], os.path.basename(f)) shutil.copy(f, dstpath) subprocess.check_call(['repo-add', dbpath, dstpath], close_fds=True) class AURPackages(dict): ''' Packages class handle package informations ''' aur_url = 'https://aur.archlinux.org' aur_min_update_interval = 60 def load(self, path): ''' Load packages informations from a file ''' if not os.path.exists(path): return try: self.update(json.load(open(path, "r"))) except Exception as e: print('Unable to load package database: %s' % e) def save(self, path): ''' Save packages informations to a file ''' json.dump(self, open(path, 'w')) def register(self, pkg, update=False): if pkg not in self or update: self.aur_update(pkg) def aur_update(self, pkg): ''' update information about a package ''' if (pkg in self and 'aurbuilder_update' in self[pkg] and self[pkg]['aurbuilder_update'] + self.aur_min_update_interval > time.time()): return info = AUR.aur_query('info', pkg) if info is not None: self[pkg] = info self[pkg]['aurbuilder_update'] = time.time() else: print('No package %s' % pkg) def extract(self, pkg, path): ''' Extract aur source tarball inside a directory path ''' # feed package db self.register(pkg, update=args.update) # get tarball fo = urllib.request.urlopen('%s/%s' % (self.aur_url, self[pkg]['URLPath'])) # extract tarball tarball = tarfile.open(mode='r|*', fileobj=fo) tarball.extractall(path) ################ #Parser commands ################ def c_init(args): ''' Init command ''' for repo in args.repos: args.repos.init(repo) def c_update(args): ''' Update command ''' args.aurpkg.update() def c_build(args): ''' Build command ''' # /dev/null fd devnull = open('/dev/null', 'w') # start building for repo, pkg in repositories.tobuild(): print('Building %s in %s' % (repo, pkg)) # creating temp directory to extract tarball tempd = tempfile.TemporaryDirectory() # extract package inside tempdir aurpkg.extract(pkg, tempd.name) # compile try: builddir = os.path.join(tempd.name, pkg) os.chdir(builddir) # subprocess.check_call(['makechrootpkg', # '-c', '-r', repositories[reponame]['chroot']]) subprocess.check_call(['makepkg','-c'], close_fds=True, stdout=devnull, stderr=devnull) files = glob.glob(os.path.join(builddir, '*.pkg.tar.xz')) if len(files) == 0: raise Exception('Unable to find binary packages') except Exception as e: # FIXME: mark package as invalid to build print('build failure: %s' % e) finally: os.chdir(cwd) # add to repository try: repositories.add(repo, files) except Exception as e: print('repository modification failure: %s' % e) pass # we start here parser = argparse.ArgumentParser() parser.add_argument('-r', '--repo-conf', default='repositories.conf', help='repository definitions') parser.add_argument('-R', '--repo-db', default='repositories.json', help='repositories databases') parser.add_argument('-p', '--aurpkg-db', default='packages.json', help='AUR packages database') parser.add_argument('-q', '--quiet', action='store_true', default=False, help='Quiet mode') sp = parser.add_subparsers() p_init = sp.add_parser('init') p_init.set_defaults(func=c_init) p_update = sp.add_parser('update') p_update.set_defaults(func=c_update) p_build = sp.add_parser('build') p_build.set_defaults(func=c_build) #p_update.add_argument('-u', '--update', action='store_true', default=False, # help='Connect AUR to update packages db') # parse args args = parser.parse_args() # path must be absolute! args.repo_conf = os.path.abspath(args.repo_conf) args.repo_db = os.path.abspath(args.repo_db) args.aurpkg_db = os.path.abspath(args.aurpkg_db) # store current directory cwd = os.getcwd() # load repo mananger repos = Repositories() repos.load(args.repo_conf, args.repo_db) # load package manager aurpkg = AURPackages() aurpkg.load(args.aurpkg_db) # add aurpkg and repos to args args.aurpkg = aurpkg args.repos = repos # run command function args.func(args) # save aur packages db aurpkg.save(args.aurpkg_db)
repositories.conf 0 → 100644 +20 −0 Original line number Diff line number Diff line [seblu-aur-i686] arch = i686 path=repo/i686 chroot=chroots/i686 packages = atftp lantencytop rar rootcheck [seblu-aur-x86_64] dbname = seblu-aur.db.tar.gz arch = x86_64 path=repo/amd64 chroot=chroots/amd64 build_command = makepkg -c packages = atftp latencytop rar rootcheck