mirror of
https://gitdl.cn/https://github.com/chakralinux/core.git
synced 2025-02-05 05:37:15 +08:00
207 lines
6.9 KiB
Python
Executable File
207 lines
6.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# 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
|
|
# along with larch; if not, write to the Free Software Foundation, Inc.,
|
|
# 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.
|
|
|
|
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.
|
|
|
|
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)
|