#!/usr/bin/python # -*- coding: utf-8 -*- # Maintain ebuilds for app-xemacs packages from the # package-index.LATEST.gpg file. # Copyright (C) 2017 Mats Lidell # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Usage: pebuild package-index.LATEST.gpg import os import sys import re from optparse import OptionParser # Package mappings packageMappings = { 'eterm':'xemacs-eterm', 'hm--html-menus':'hm-html-menus', 'ispell':'xemacs-ispell', 'Sun':'sun' } def mappedName(name): if name in packageMappings: return packageMappings[name] return name class pkg(object): def __init__(self, name, version, category): self.name = name self.deps = [] self.version = version self.category = category def setDeps(self, deps): self.deps = deps def getDeps(self): res = [] for d in self.deps: if d != self.name: res.append(d) return res def getVersion(self): return self.version def getName(self): return self.name def getCategory(self): return self.category def listpackages(path): return [os.path.join(path, p) for p in os.listdir(path)] def infopackage(path): # print 'debug: ', path files = os.listdir(path) package = os.path.basename(path) cpat = re.compile(package + '-((\d+\.\d+)(|-r\d+))\.ebuild') versions = [] for v in files: m = cpat.match(v) if m: versions += [m.group(1)] if len(versions) == 0: return versions.sort() versions.reverse() result = [package, versions, versions[0]] return result # Simplified parse. Filename identifies both package and # version. Requires section that follows is assumed to belong to the # package. ... and category comes before. def parsepkglist(pkglist): ctgpat = re.compile(' category "(.*)"') fnpat = re.compile(' filename "(.*)-(\d+\.\d+)-pkg\.tar\.gz"') dpnpat = re.compile(' requires \((.*)\)') result = {} category = '' f = open(pkglist, 'r') for l in f.readlines()[:-1]: m = ctgpat.match(l) if m: category = m.group(1) continue m = fnpat.match(l) if m: # print 'Match:', m p = pkg(mappedName(m.group(1)), m.group(2), category) result[p.getName()] = p continue m = dpnpat.match(l) if m: p.setDeps([mappedName(n) for n in m.group(1).split()]) p = None f.close() return result dependField = 'RDEPEND="' oldDependField = 'DEPEND="' def updateEbuild(path, po, p): pack = p.getName() oldv = po.getVersion() newv = p.getVersion() deps = p.getDeps() # Create new ebuild file f = open(os.path.join(os.path.join(path, pack), pack + '-' + oldv + '.ebuild')) newEbuild = os.path.join(os.path.join(path, pack), pack + '-' + newv + '.ebuild') fn = open(newEbuild, 'w') # Copy lines but alter RDEPEND. Move from DEPEND to RDEPEND if # there is a DEPEND line. independ = False for l in f.readlines(): if not independ: if l.startswith(dependField) or l.startswith(oldDependField): fn.write(dependField) for d in deps: fn.write('app-xemacs/' + d + '\n') fn.write('"\n') if not l.startswith(dependField + '"') and not l.startswith(oldDependField + '"'): independ = True continue fn.write(l) elif l == '"\n': independ = False fn.close() f.close() # Execute command for creating the ebuild os.system('ekeyword ~all ' + newEbuild) if not noEbuild: os.system('ebuild ' + newEbuild + ' digest') def createNewEbuild(np): print(' '*3, np.getName().ljust(20), 'Version:', np.getVersion()) def removeEbuild(np): print(' '*3, np.getName().ljust(20), 'Version:', np.getVersion()) def comparepackages(path, old, new, single): if not pretend: print('\n=== UPDATE EBUILDS ===') for k in list(new.keys()): if single and k != single: continue if k in old: if new[k].getVersion() > old[k].getVersion(): if not pretend: print(' '*3, k.ljust(20), 'Old:', old[k].getVersion(), 'New:', new[k].getVersion()) updateEbuild(path, old[k], new[k]) print('\n=== SUMMARY ===') print('\n*** Unmodified packages') for k in list(new.keys()): if single and k != single: continue if k in old: if new[k].getVersion() == old[k].getVersion(): print(' '*3, k.ljust(20), 'Version:', new[k].getVersion()) print('\n*** Updated packages') for k in list(new.keys()): if single and k != single: continue if k in old: if new[k].getVersion() > old[k].getVersion(): print(' '*3, k.ljust(20), 'Old:', old[k].getVersion().ljust(10), 'New:', new[k].getVersion()) # if not pretend: updateEbuild(path, old[k], new[k]) print('\n*** New packages') for k in list(new.keys()): if single and k != single: continue if k not in old: createNewEbuild(new[k]) print('\n*** Obsolete or Gentoo packages') for k in list(old.keys()): if single and k != single: continue if k not in new: removeEbuild(old[k]) def pp_print(p): if verbose: print('\t>=app-xemacs/' + (p.getName() + '-' + p.getVersion()).ljust(25) + " ".join(p.getDeps())) else: print('\t>=app-xemacs/' + p.getName() + '-' + p.getVersion()) def pp_packages(packages): mule = Set() print('*** Standard packages') keys = list(packages.keys()) keys.sort() for p in keys: if packages[p].getCategory() == 'mule': mule.add(packages[p]) else: pp_print(packages[p]) print('\n*** Mule packages') for p in mule: pp_print(p) def main(): global pretend global noEbuild global verbose root = os.getcwd() usage = "usage: %prog [options] package-list [single-package]" parser = OptionParser(usage) parser.add_option('-p', '--pretend', action='store_true', dest='pretend', help='don\'t actually do anything. Just report ...') parser.add_option('-n', '--noebuild', action='store_true', dest='noEbuild', help='don\'t execute the ebuild command but do the rest.') parser.add_option('-s', '--show', action='store_true', dest='show', help='just show info about the packages and the dependencies.') parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='say more.') (options, args) = parser.parse_args() if len(args) < 1 or 2 < len(args): parser.error("Wrong number of arguments") pkglist = args[0] single = args[1] if len(args) == 2 else None pretend = options.pretend noEbuild = options.noEbuild verbose = options.verbose newpackages = parsepkglist(pkglist) if options.show: pp_packages(newpackages) else: oldpackages = {} for p in listpackages(root): if os.path.isdir(p): i = infopackage(p) if i: p = pkg(i[0], i[2], None) oldpackages[p.getName()] = p comparepackages(root, oldpackages, newpackages, single) main()