#!/usr/bin/env python from __future__ import absolute_import from __future__ import print_function import sys, os, posixpath import subprocess import opkg import getopt import re verbose = 0 def usage(): sys.stderr.write("%s [-h] [-s] [-m] [-l Packages.filelist] [-p Packages] [-r Packages.old] [-L localesdir] [-v] packagesdir\n" % (sys.argv[0],)) sys.exit(-1) def to_morgue(filename): morgue_dir = pkg_dir + "/morgue" if verbose: sys.stderr.write ("Moving " + filename + " to morgue\n") if not os.path.exists(morgue_dir): os.mkdir(morgue_dir) if os.path.exists(pkg_dir + "/" + filename): os.rename(pkg_dir + "/" + filename, morgue_dir + "/" + filename) if os.path.exists(pkg_dir + "/" + filename + ".asc"): os.rename(pkg_dir + "/" + filename + ".asc", morgue_dir + "/" + filename + ".asc") locales_dir = None def to_locale(filename, locale): locale_dir = pkg_dir + '/' + locales_dir + '/' + locale + "/" if verbose: sys.stderr.write ("Moving " + filename + " to " + locale_dir + "\n") if not os.path.exists(locale_dir): os.mkdir(locale_dir) os.rename(pkg_dir + "/" + filename, locale_dir + "/" + filename) if os.path.exists(pkg_dir + "/" + filename + ".asc"): os.rename(pkg_dir + "/" + filename + ".asc", locale_dir + "/" + filename + ".asc") old_filename = None packages_filename = None filelist_filename = None stamplist_filename = "Packages.stamps" opt_s = 0 opt_m = 0 (opts, remaining_args) = getopt.getopt(sys.argv[1:], "hl:p:vsmr:L:") for (optkey, optval) in opts: if optkey == '-h': usage() if optkey == '-s': opt_s = 1 if optkey == '-p': packages_filename = optval stamplist_filename = optval + ".stamps" if optkey == '-l': filelist_filename = optval if optkey == '-v': verbose = 1 if optkey == '-m': opt_m = 1 if optkey == '-r': old_filename = optval if optkey == '-L': locales_dir = optval if ( not remaining_args ): usage() pkg_dir=remaining_args[0] packages = opkg.Packages() old_pkg_hash = {} if packages_filename and not old_filename and os.path.exists(packages_filename): old_filename = packages_filename pkgsStamps = {} if old_filename: if (verbose): sys.stderr.write("Reading package list from " + old_filename + "\n") old_packages = opkg.Packages() old_packages.read_packages_file(old_filename) for k in list(old_packages.packages.keys()): p = old_packages.packages[k] old_pkg_hash[p.filename] = p try: f = open(stamplist_filename, "r") for l in f: l = l.strip() s, f = l.split(" ", 1) pkgsStamps[f] = int(s) except IOError: pass if (verbose): sys.stderr.write("Reading in all the package info from %s\n" % (pkg_dir, )) files=[] opkg_extensions=['.ipk','.opk','.deb'] for dirpath, dirnames, filenames in os.walk(pkg_dir): for f in filenames: ext = os.path.splitext(f)[1] if ext in opkg_extensions: files.append(os.path.join(dirpath, f)) files.sort() for abspath in files: try: filename = os.path.relpath(abspath, pkg_dir) pkg = None fnameStat = os.stat(abspath) if filename in old_pkg_hash: if filename in pkgsStamps and int(fnameStat.st_mtime) == pkgsStamps[filename]: if (verbose): sys.stderr.write("Found %s in Packages\n" % (filename,)) pkg = old_pkg_hash[filename] else: sys.stderr.write("Found %s in Packages, but mtime differs - re-reading\n" % (filename,)) if not pkg: if (verbose): sys.stderr.write("Reading info for package %s\n" % (filename,)) pkg = opkg.Package(abspath, relpath=pkg_dir) pkg_key = ("%s:%s" % (pkg.package, pkg.architecture)) if (pkg_key in packages.packages): old_filename = packages.packages[pkg_key].filename else: old_filename = "" s = packages.add_package(pkg) pkgsStamps[filename] = fnameStat.st_mtime if s == 0: if old_filename: # old package was displaced by newer if opt_m: to_morgue(old_filename) if opt_s: print(("%s/%s" % (pkg_dir, old_filename))) else: if opt_m: to_morgue(filename) if opt_s: print(filename) except OSError as e: sys.stderr.write("Package %s disappeared on us!\n(%s)\n" % (filename, e)) continue except IOError as e: sys.stderr.write("Package %s disappeared on us!\n(%s)\n" % (filename, e)) continue pkgsStampsFile = open(stamplist_filename, "w") for f in list(pkgsStamps.keys()): pkgsStampsFile.write("%d %s\n" % (pkgsStamps[f], f)) pkgsStampsFile.close() if opt_s: sys.exit(0) if verbose: sys.stderr.write("Generating Packages file\n") if packages_filename: tmp_packages_filename = ("%s.%d" % (packages_filename, os.getpid())) pkgsFile = open(tmp_packages_filename, "w") names = list(packages.packages.keys()) names.sort() for name in names: try: pkg = packages.packages[name] if locales_dir and pkg.depends: depends = pkg.depends.split(',') locale = None for d in depends: m = re.match('.*virtual-locale-([a-zA-Z]+).*', d) mp = re.match('locale-base-([a-zA-Z]+)([-+])?.*', pkg.package) if m: locale = m.group(1) if mp: locale = mp.group(1) if locale: to_locale(pkg.filename, locale) continue if (verbose): sys.stderr.write("Writing info for package %s\n" % (pkg.package,)) if packages_filename: pkgsFile.write(str(pkg)) else: print(pkg) except OSError as e: sys.stderr.write("Package %s disappeared on us!\n(%s)\n" % (name, e)) continue except IOError as e: sys.stderr.write("Package %s disappeared on us!\n(%s)\n" % (name, e)) continue if packages_filename: pkgsFile.close() gzip_filename = ("%s.gz" % packages_filename) tmp_gzip_filename = ("%s.%d" % (gzip_filename, os.getpid())) gzip_cmd = "gzip -9c < %s > %s" % (tmp_packages_filename, tmp_gzip_filename) subprocess.call(gzip_cmd, shell=True) os.rename(tmp_packages_filename, packages_filename) os.rename(tmp_gzip_filename, gzip_filename) if filelist_filename: if verbose: sys.stderr.write("Generate Packages.filelist file\n") files = {} names = list(packages.packages.keys()) names.sort() for name in names: try: if verbose: sys.stderr.write("Reading filelist for package '%s'\n" % name) # sys.stderr.write("Package for name '%s':\n'%s'\n" % (name, packages[name])) fnlist = packages[name].get_file_list_dir(pkg_dir) # sys.stderr.write("Filelist for package '%s': '%s'\n" % (name, fnlist)) except OSError as e: sys.stderr.write("Package %s disappeared on us!\n(%s)\n" % (name, e)) continue except IOError as e: sys.stderr.write("Package %s disappeared on us!\n(%s)\n" % (name, e)) continue for fn in fnlist: (h,t) = os.path.split(fn) if not t: continue if t not in files: files[t] = name+':'+fn else: files[t] = files[t] + ',' + name+':'+fn tmp_filelist_filename = ("%s.%d" % (filelist_filename, os.getpid())) f = open(tmp_filelist_filename, "w") names = list(files.keys()) names.sort() for name in names: f.write("%s %s\n" % (name, files[name])) f.close() if posixpath.exists(filelist_filename): os.unlink(filelist_filename) os.rename(tmp_filelist_filename, filelist_filename)