core/larch/scripts/gen_repo

207 lines
6.9 KiB
Plaintext
Raw Normal View History

2010-11-15 09:45:06 +08:00
#!/usr/bin/env python2
2010-05-22 06:16:47 +08:00
# gen_repo - build a repository db file from a set of packages
#
# Author: Michael Towers (gradgrind) <mt.42@web.de>
#
# This file is part of the larch project.
#
# larch 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 2 of the License, or
# (at your option) any later version.
#
# larch 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
2010-11-15 09:45:06 +08:00
# along with larch; if not, write to the Free Software Foundation, Inc.,
2010-05-22 06:16:47 +08:00
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#----------------------------------------------------------------------------
#
# Version 1.5 // 7th July 2007
import os
import os.path
import sys
import tarfile
from types import *
import re
from subprocess import check_call
# to add a package:
#check_call(["repo-add", dbfile, pkg, pkg, pkg, ...])
# Regex to remove version comparison from package dependency
onlyname = re.compile("([^=><]+).*")
def create_db(dbname, packagesdir, dep_ignore_list):
os.chdir(packagesdir)
dbfile = dbname + ".db.tar.gz"
if os.path.exists(dbfile):
os.remove(dbfile)
# Get a list of packages
packages = filter(lambda s: s.endswith(".pkg.tar.gz"), os.listdir("."))
packages.sort()
# Use 'repo-add' to build the repo
check_call(["repo-add", dbfile] + packages)
# Make a dict for keeping track of dependencies
dep_dict = {}
for p in packages:
pkg_dict = get_pkg_info(p)
pkg_name = pkg_dict["pkgname"]
pkg_dbname = pkg_name + "-" + pkg_dict["pkgver"]
# Add dependency info to dependency dict
for d in pkg_dict["depend"]:
# But also need to cater for versioning!!!
# I will just ignore it here ...
dm = onlyname.match(d)
if not dm:
if d:
print "DEBUG: package %s, dependency = '%s'" % (pkg_name, d)
continue
d = dm.group(1)
if not dep_dict.has_key(d):
dep_dict[d] = [False]
dep_dict[d].append(pkg_name)
# Mark packages provided by this one
for p in (pkg_dict["provides"] + [pkg_name]):
if dep_dict.has_key(p):
dep_dict[p][0] = True
else:
dep_dict[p] = [True]
# Mark packages in ignore list
for p in dep_ignore_list:
if dep_dict.has_key(p):
dep_dict[p][0] = True
# Now display unsatisfied dependencies
# Should add the possibility of declaring a list of packages
# available (e.g. the base set, or all those on the live CD ..."
print "-------------\nUnsatisfied dependencies:"
for d, r in dep_dict.items():
if not r[0]:
print " ", d, "- needed by: ",
for p in r[1:]:
print p, " ",
print ""
def get_pkg_info(pkg):
tf = tarfile.open(pkg, "r:gz")
pkginfo = tf.extractfile(".PKGINFO")
pkg_dict = {# the first ones go to 'desc'
"pkgname" : None,
"pkgver" : None,
# from here they are optional, and can occur more than once
"depend" : [],
"provides" : [],
}
while True:
l = pkginfo.readline().strip()
if not l: break
if l[0] == "#": continue
split3 = l.split(None, 2)
while len(split3) < 3: split3.append("")
key, eq, value = split3
if not pkg_dict.has_key(key): continue
val = pkg_dict[key]
if val == None:
pkg_dict[key] = value
continue
if not isinstance(val, ListType):
print "Unexpected situation ...\n key [oldvalue] <- newvalue"
print key, "[%s]" % val, "<-", value
sys.exit(1)
pkg_dict[key].append(value)
pkginfo.close()
return pkg_dict
def cat(path):
"""Python version of 'cat'"""
fp = open(path, "r")
op = ""
for l in fp:
op += l
fp.close()
return op
def usage():
print """
gen_repo package-dir [repo-name] [-- ignore-list]
Generate a pacman db file for the packages in package-dir.
2010-11-15 09:45:06 +08:00
2010-05-22 06:16:47 +08:00
If repo-name is given, this will be used as the name for the repository,
otherwise the name of the directory containing the packages will be used.
2010-11-15 09:45:06 +08:00
2010-05-22 06:16:47 +08:00
All dependencies of the packages in the repository will be listed to
standard output, but a list of packages not to be included in this list
can be specified:
ignore-list should be either a file containing the names of packages
not to be listed as dependencies (separated by space or newline), or a
directory containing 'package directories', like /var/abs/base or
/var/lib/pacman/local
"""
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) < 2:
usage()
if os.getuid() != 0:
print "Must be root to run this"
sys.exit(1)
pkgdir = sys.argv[1]
if (len(sys.argv) == 2) or (sys.argv[2] == "--"):
dbname = os.path.basename(os.path.abspath(pkgdir))
i = 2
else:
dbname = sys.argv[2]
i = 3
if len(sys.argv) == i:
ignore_list = []
elif (len(sys.argv) == i+2) and (sys.argv[i] == "--"):
ignore_list = sys.argv[i+1]
else:
usage()
if not os.path.isdir(pkgdir):
print "\n1st argument must be a directory"
sys.exit(1)
print "\nCreating pacman database (%s.db.tar.gz) file in %s" % (dbname, pkgdir)
if ignore_list:
# Get list of packages to be ignored in dependency list
if os.path.isfile(ignore_list):
# A simple file containing the names of packages to ignore
# separated by space or newline.
ignore_list = cat(ignore_list).split()
elif os.path.isdir(ignore_list):
# A directory containing packages or package-directories (like in abs)
l = os.listdir(ignore_list)
# See if there are packages in this directory
lp = filter(lambda s: s.endswith(".pkg.tar.gz"), l)
if lp:
l = map(lambda s: s.replace(".pkg.tar.gz", ""), lp)
re1 = re.compile("(.+)-[^-]+?-[0-9]+")
ignore_list = []
for f in l:
m = re1.match(f)
if m:
ignore_list.append(m.group(1))
else:
# the directory contains just the package names (like abs)
ignore_list.append(m)
else:
print "!!! Invalid ignore-list"
usage()
create_db(dbname, pkgdir, ignore_list)