summaryrefslogtreecommitdiffstats
path: root/build_tools/bin/check_repo
diff options
context:
space:
mode:
Diffstat (limited to 'build_tools/bin/check_repo')
-rw-r--r--build_tools/bin/check_repo/README8
-rw-r--r--build_tools/bin/check_repo/alpm.c40
-rwxr-xr-xbuild_tools/bin/check_repo/alpm.sobin0 -> 14742 bytes
-rwxr-xr-xbuild_tools/bin/check_repo/build/lib.linux-x86_64-2.6/alpm.sobin0 -> 14742 bytes
-rwxr-xr-xbuild_tools/bin/check_repo/check_packages.py506
-rwxr-xr-xbuild_tools/bin/check_repo/parse_pkgbuilds.sh149
-rw-r--r--build_tools/bin/check_repo/setup.py10
7 files changed, 713 insertions, 0 deletions
diff --git a/build_tools/bin/check_repo/README b/build_tools/bin/check_repo/README
new file mode 100644
index 0000000..f3a1b90
--- /dev/null
+++ b/build_tools/bin/check_repo/README
@@ -0,0 +1,8 @@
+1) Build the python module
+$ python setup.py build
+
+2) copy it back to the current working directory
+$ cp build/lib.*/alpm.* .
+
+3) run the script
+$ ./check_packages.py -h
diff --git a/build_tools/bin/check_repo/alpm.c b/build_tools/bin/check_repo/alpm.c
new file mode 100644
index 0000000..0b7cd2c
--- /dev/null
+++ b/build_tools/bin/check_repo/alpm.c
@@ -0,0 +1,40 @@
+#include <Python.h>
+#include <alpm.h>
+
+static PyObject *
+alpm_vercmp(PyObject *self, PyObject *args)
+{
+ const char *v1, *v2;
+ int ret;
+
+ if (!PyArg_ParseTuple(args, "ss", &v1, &v2))
+ return NULL;
+ ret = alpm_pkg_vercmp(v1, v2);
+ return Py_BuildValue("i", ret);
+}
+
+static PyMethodDef AlpmMethods[] = {
+ {"vercmp", alpm_vercmp, METH_VARARGS,
+ "Execute vercmp."},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+PyMODINIT_FUNC
+initalpm(void)
+{
+ (void) Py_InitModule("alpm", AlpmMethods);
+}
+
+int
+main(int argc, char *argv[])
+{
+ /* Pass argv[0] to the Python interpreter */
+ Py_SetProgramName(argv[0]);
+
+ /* Initialize the Python interpreter. Required. */
+ Py_Initialize();
+
+ /* Add a static module */
+ initalpm();
+ return 0;
+}
diff --git a/build_tools/bin/check_repo/alpm.so b/build_tools/bin/check_repo/alpm.so
new file mode 100755
index 0000000..f6c4b3d
--- /dev/null
+++ b/build_tools/bin/check_repo/alpm.so
Binary files differ
diff --git a/build_tools/bin/check_repo/build/lib.linux-x86_64-2.6/alpm.so b/build_tools/bin/check_repo/build/lib.linux-x86_64-2.6/alpm.so
new file mode 100755
index 0000000..f6c4b3d
--- /dev/null
+++ b/build_tools/bin/check_repo/build/lib.linux-x86_64-2.6/alpm.so
Binary files differ
diff --git a/build_tools/bin/check_repo/check_packages.py b/build_tools/bin/check_repo/check_packages.py
new file mode 100755
index 0000000..39ac4fb
--- /dev/null
+++ b/build_tools/bin/check_repo/check_packages.py
@@ -0,0 +1,506 @@
+#!/usr/bin/python
+#
+# check_archlinux.py
+#
+# Original script by Scott Horowitz <stonecrest@gmail.com>
+# Rewritten by Xavier Chantry <shiningxc@gmail.com>
+#
+# This script currently checks for a number of issues in your ABS tree:
+# 1. Directories with missing PKGBUILDS
+# 2. Invalid PKGBUILDs (bash syntax error for instance)
+# 3. PKGBUILD names that don't match their directory
+# 4. Duplicate PKGBUILDs
+# 5. Valid arch's in PKGBUILDS
+# 6. Missing (make-)dependencies
+# 7. Hierarchy of repos (e.g., that a core package doesn't depend on
+# a non-core package)
+# 8. Circular dependencies
+
+import os,re,commands,getopt,sys,tarfile,alpm
+import pdb
+
+DBEXT='.db.tar.gz'
+
+packages = {} # pkgname : PacmanPackage
+repopkgs = {} # pkgname : PacmanPackage
+provisions = {} # provision : PacmanPackage
+pkgdeps,makepkgdeps = {},{} # PacmanPackage : list of the PacmanPackage dependencies
+invalid_pkgbuilds = []
+missing_pkgbuilds = []
+dups = []
+
+dbonly = []
+absonly = []
+
+mismatches = []
+missing_deps = []
+missing_makedeps = []
+invalid_archs = []
+dep_hierarchy = []
+makedep_hierarchy = []
+circular_deps = [] # pkgname>dep1>dep2>...>pkgname
+checked_deps = []
+
+class PacmanPackage:
+ def __init__(self):
+ self.name,self.version = "",""
+ self.base = ""
+ self.path,self.repo = "",""
+ self.deps,self.makedeps = [],[]
+ self.provides,self.conflicts = [],[]
+ self.archs = []
+
+class Depend:
+ def __init__(self,name,version,mod):
+ self.name = name
+ self.version = version
+ self.mod = mod
+
+def parse_pkgbuilds(repos,arch):
+ for absroot in absroots:
+ for repo in repos:
+ cmd = os.path.dirname(os.path.realpath(sys.argv[0])) + '/parse_pkgbuilds.sh '
+ cmd += arch + ' ' + absroot + '/' + repo
+ print cmd
+ (status,output) = commands.getstatusoutput(cmd)
+ if status != 0:
+ print "Error : failed to run '%s'" % cmd
+ sys.exit()
+ parse_data(repo,output)
+
+def parse_data(repo,data):
+ attrname = None
+
+ for line in data.split('\n'):
+ if line.startswith('%'):
+ attrname = line.strip('%').lower()
+ elif line.strip() == '':
+ attrname = None
+ elif attrname == "invalid":
+ if repo in repos:
+ invalid_pkgbuilds.append(line)
+ elif attrname == "missing":
+ if repo in repos:
+ missing_pkgbuilds.append(line)
+ elif attrname == "name":
+ pkg = PacmanPackage()
+ pkg.name = line
+ pkg.repo = repo
+ dup = None
+ if packages.has_key(pkg.name):
+ dup = packages[pkg.name]
+ else:
+ packages[pkg.name] = pkg
+ elif attrname == "base":
+ pkg.base = line
+ elif attrname == "version":
+ pkg.version = line
+ elif attrname == "path":
+ pkg.path = line
+ if dup != None and (pkg.repo in repos or dup.repo in repos):
+ dups.append(pkg.path + " vs. " + dup.path)
+ elif attrname == "arch":
+ pkg.archs.append(line)
+ elif attrname == "depends":
+ pkg.deps.append(line)
+ elif attrname == "makedepends":
+ pkg.makedeps.append(line)
+ elif attrname == "conflicts":
+ pkg.conflicts.append(line)
+ elif attrname == "provides":
+ pkg.provides.append(line)
+
+def parse_dbs(repos,arch):
+ dbpkgs = {}
+ for repo in repos:
+ pkgs = set([])
+ db = tarfile.open(os.path.join(repodir,repo,repo + DBEXT))
+ for line in db.getnames():
+ if not '/' in line:
+ pkgs.add(line.rsplit('-',2)[0])
+ dbpkgs[repo] = pkgs
+ return(dbpkgs)
+
+def splitdep(dep):
+ name = dep
+ version = ""
+ mod = ""
+ for char in (">=", "<=", "=", ">", "<"):
+ pos = dep.find(char)
+ if pos > -1:
+ name = dep[:pos]
+ version = dep[pos:].replace(char, "")
+ mod = char
+ break
+ return Depend(name,version,mod)
+
+def splitprov(prov):
+ name = prov
+ version = ""
+ pos = prov.find("=")
+ if pos > -1:
+ name = prov[:pos]
+ version = prov[pos:].replace("=", "")
+ return (name,version)
+
+def vercmp(v1,mod,v2):
+ res = alpm.vercmp(v1,v2)
+ if res == 0:
+ return (mod.find("=") > -1)
+ elif res < 0:
+ return (mod.find("<") > -1)
+ elif res > 0:
+ return (mod.find(">") > -1)
+ return False
+
+
+def depcmp(name,version,dep):
+ if name != dep.name:
+ return False
+ if dep.version == "" or dep.mod == "":
+ return True
+ if version == "":
+ return False
+ return vercmp(version,dep.mod,dep.version)
+
+def provcmp(pkg,dep):
+ for prov in pkg.provides:
+ (provname,provver) = splitprov(prov)
+ if depcmp(provname,provver,dep):
+ return True
+ return False
+
+def verify_dep(dep):
+ dep = splitdep(dep)
+ if packages.has_key(dep.name):
+ pkg = packages[dep.name]
+ if depcmp(pkg.name,pkg.version,dep):
+ return [pkg]
+ if provisions.has_key(dep.name):
+ provlist = provisions[dep.name]
+ results = []
+ for prov in provlist:
+ if provcmp(prov,dep):
+ results.append(prov)
+ return results
+ return []
+
+def verify_deps(name,repo,deps):
+ pkg_deps = []
+ missdeps = []
+ hierarchy = []
+ for dep in deps:
+ pkglist = verify_dep(dep)
+ if pkglist == []:
+ missdeps.append(repo + "/" + name + " --> '" + dep + "'")
+ else:
+ valid_repos = get_repo_hierarchy(repo)
+ pkgdep = None
+ for pkg in pkglist:
+ if pkg.repo in valid_repos:
+ pkgdep = pkg
+ break
+ if not pkgdep:
+ pkgdep = pkglist[0]
+ hierarchy.append((repo,name,pkgdep))
+
+ pkg_deps.append(pkgdep)
+
+ return (pkg_deps,missdeps,hierarchy)
+
+def compute_deplist(pkg):
+ list = []
+ stack = [pkg]
+ while stack != []:
+ dep = stack.pop()
+ if pkgdeps.has_key(dep):
+ for dep2 in pkgdeps[dep]:
+ if dep2 not in list:
+ list.append(dep2)
+ stack.append(dep2)
+ if makepkgdeps.has_key(dep):
+ for dep2 in makepkgdeps[dep]:
+ if dep2 not in list:
+ list.append(dep2)
+ stack.append(dep2)
+ return list
+
+def check_hierarchy(deph):
+ hierarchy = []
+ for (repo,name,pkgdep) in deph:
+ deplist = compute_deplist(pkgdep)
+ valid_repos = get_repo_hierarchy(repo)
+ extdeps = []
+ for dep in deplist:
+ if dep.repo not in valid_repos:
+ extdeps.append(dep.name)
+ string = repo + "/" + name + " depends on " + pkgdep.repo + "/" + pkgdep.name + " ("
+ string += "%s extra (make)deps to pull" % len(extdeps)
+ if 0 < len(extdeps) < 10:
+ string += " : " + ' '.join(extdeps)
+ string += ")"
+ hierarchy.append(string)
+ return hierarchy
+
+def get_repo_hierarchy(repo):
+ repo_hierarchy = {'core': ['core'], \
+ 'extra': ['core', 'extra'], \
+ 'extra-testing': ['core-testing', 'extra-testing'], \
+ 'core-testing': ['core-testing'], \
+ 'mv-core': ['mv-core'], \
+ 'community': ['core', 'extra', 'community']}
+ if repo_hierarchy.has_key(repo):
+ return repo_hierarchy[repo]
+ else:
+ return ['core','extra']
+ #return ['core','extra','community']
+ #return ['core','extra','community']
+
+def verify_archs(name,repo,archs):
+ valid_archs = ['any', 'i686', 'x86_64']
+ invalid_archs = []
+ for arch in archs:
+ if arch not in valid_archs:
+ invalid_archs.append(repo + "/" + name + " --> " + arch)
+ return invalid_archs
+
+def find_scc(packages):
+ # reset all variables
+ global index,S,pkgindex,pkglowlink
+ index = 0
+ S = []
+ pkgindex = {}
+ pkglowlink = {}
+ cycles = []
+ for pkg in packages:
+ tarjan(pkg)
+
+def tarjan(pkg):
+ global index,S,pkgindex,pkglowlink,cycles
+ pkgindex[pkg] = index
+ pkglowlink[pkg] = index
+ index += 1
+ checked_deps.append(pkg)
+ S.append(pkg)
+ deps = []
+ if pkgdeps.has_key(pkg):
+ deps = pkgdeps[pkg]
+ for dep in deps:
+ if not pkgindex.has_key(dep):
+ tarjan(dep)
+ pkglowlink[pkg] = min(pkglowlink[pkg],pkglowlink[dep])
+ elif dep in S:
+ pkglowlink[pkg] = min(pkglowlink[pkg],pkgindex[dep])
+ if pkglowlink[pkg] == pkgindex[pkg]:
+ dep = S.pop()
+ if pkg == dep:
+ return
+ path = pkg.name
+ while pkg != dep:
+ path = dep.repo + "/" + dep.name + ">" + path
+ dep = S.pop()
+ path = dep.name + ">" + path
+ if pkg.repo in repos:
+ circular_deps.append(path)
+
+def print_heading(heading):
+ print ""
+ print "=" * (len(heading) + 4)
+ print "= " + heading + " ="
+ print "=" * (len(heading) + 4)
+
+def print_subheading(subheading):
+ print ""
+ print subheading
+ print "-" * (len(subheading) + 2)
+
+def print_missdeps(pkgname,missdeps) :
+ for d in missdeps:
+ print pkgname + " : " + d
+
+def print_result(list, subheading):
+ if len(list) > 0:
+ list.sort()
+ print_subheading(subheading)
+ for item in list:
+ print item
+
+def print_results():
+ print_result(missing_pkgbuilds, "Missing PKGBUILDs")
+ print_result(invalid_pkgbuilds, "Invalid PKGBUILDs")
+ print_result(mismatches, "Mismatched Pkgnames")
+ print_result(dups, "Duplicate PKGBUILDs")
+ print_result(invalid_archs, "Invalid Archs")
+ print_result(missing_deps, "Missing Dependencies")
+ print_result(missing_makedeps, "Missing Makedepends")
+ print_result(dep_hierarchy, "Repo Hierarchy for Dependencies")
+ print_result(makedep_hierarchy, "Repo Hierarchy for Makedepends")
+ print_result(circular_deps, "Circular Dependencies")
+ print_result(dbonly, "Packages found in db, but not in tree")
+ print_result(absonly,"Packages found in tree, but not in db")
+ print_subheading("Summary")
+ print "Missing PKGBUILDs: ", len(missing_pkgbuilds)
+ print "Invalid PKGBUILDs: ", len(invalid_pkgbuilds)
+ print "Mismatching PKGBUILD names: ", len(mismatches)
+ print "Duplicate PKGBUILDs: ", len(dups)
+ print "Invalid archs: ", len(invalid_archs)
+ print "Missing (make)dependencies: ", len(missing_deps)+len(missing_makedeps)
+ print "Repo hierarchy problems: ", len(dep_hierarchy)+len(makedep_hierarchy)
+ print "Circular dependencies: ", len(circular_deps)
+ print "In db, but not in tree: ", len(dbonly)
+ print "In tree, but not in db: ", len(absonly)
+ print ""
+
+def print_usage():
+ print ""
+ print "Usage: ./check_packages.py [OPTION]"
+ print ""
+ print "Options:"
+ print " --abs-tree=<path[,path]> Check the specified tree(s) (default : /var/abs)"
+ print " --repos=<r1,r2,...> Check the specified repos (default : core,extra)"
+ print " --arch=<i686|x86_64> Check the specified arch (default : i686)"
+ print " --repo-dir=<path> Check the dbs at the specified path (default : /srv/ftp)"
+ print " -h, --help Show this help and exit"
+ print ""
+ print "Examples:"
+ print "\n Check core and extra in existing abs tree:"
+ print " ./check_packages.py --abs-tree=/var/abs --repos=core,extra --arch=i686"
+ print "\n Check community:"
+ print " ./check_packages.py --abs-tree=/var/abs --repos=community --arch=i686"
+ print ""
+
+## Default path to the abs root directory
+absroots = ["/var/abs"]
+## Default list of repos to check
+repos = ['core', 'extra']
+## Default arch
+arch = "i686"
+## Default repodir
+repodir = "/srv/ftp"
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "", ["abs-tree=", "repos=",
+ "arch=", "repo-dir="])
+except getopt.GetoptError:
+ print_usage()
+ sys.exit()
+if opts != []:
+ for o, a in opts:
+ if o in ("--abs-tree"):
+ absroots = a.split(',')
+ elif o in ("--repos"):
+ repos = a.split(",")
+ elif o in ("--arch"):
+ arch = a
+ elif o in ("--repo-dir"):
+ repodir = a
+ else:
+ print_usage()
+ sys.exit()
+ if args != []:
+ print_usage()
+ sys.exit()
+
+for absroot in absroots:
+ if not os.path.isdir(absroot):
+ print "Error : the abs tree " + absroot + " does not exist"
+ sys.exit()
+ for repo in repos:
+ repopath = absroot + "/" + repo
+ if not os.path.isdir(repopath):
+ print "Error : the repository " + repo + " does not exist in " + absroot
+ sys.exit()
+if not os.path.isdir(repodir):
+ print "Error: the repository directory %s does not exist" % repodir
+ sys.exit()
+for repo in repos:
+ #path = os.path.join(repodir,repo,repo + DBEXT)
+ path = os.path.join(repodir,repo,repo + DBEXT)
+ if not os.path.isfile(path):
+ print "Error : repo DB %s : File not found" % path
+ sys.exit()
+ if not tarfile.is_tarfile(path):
+ print "Error : Cant open repo DB %s, not a valid tar file" % path
+ sys.exit()
+# repos which need to be loaded
+loadrepos = set([])
+for repo in repos:
+ loadrepos = loadrepos | set(get_repo_hierarchy(repo))
+
+print_heading("Integrity Check " + arch + " of " + ",".join(repos))
+print "\nPerforming integrity checks..."
+
+print "==> parsing pkgbuilds"
+parse_pkgbuilds(loadrepos,arch)
+
+# fill provisions
+for name,pkg in packages.iteritems():
+ for prov in pkg.provides:
+ provname=prov.split("=")[0]
+ if not provisions.has_key(provname):
+ provisions[provname] = []
+ provisions[provname].append(pkg)
+
+# fill repopkgs
+for name,pkg in packages.iteritems():
+ if pkg.repo in repos:
+ repopkgs[name] = pkg
+
+print "==> parsing db files"
+dbpkgs = parse_dbs(repos,arch)
+
+print "==> checking mismatches"
+for name,pkg in repopkgs.iteritems():
+ pkgdirname = pkg.path.split("/")[-1]
+ if name != pkgdirname and pkg.base != pkgdirname:
+ mismatches.append(name + " vs. " + pkg.path)
+
+print "==> checking archs"
+for name,pkg in repopkgs.iteritems():
+ archs = verify_archs(name,pkg.repo,pkg.archs)
+ invalid_archs.extend(archs)
+
+# ugly hack to strip the weird kblic- deps
+for name,pkg in packages.iteritems():
+ p = re.compile('klibc-[\w\-]{27}|klibc-\*')
+ pkg.deps = [dep for dep in pkg.deps if not p.match(dep)]
+ pkg.makedeps = [dep for dep in pkg.makedeps if not p.match(dep)]
+
+deph,makedeph = [],[]
+
+print "==> checking dependencies"
+for name,pkg in repopkgs.iteritems():
+ (deps,missdeps,hierarchy) = verify_deps(name,pkg.repo,pkg.deps)
+ pkgdeps[pkg] = deps
+ missing_deps.extend(missdeps)
+ deph.extend(hierarchy)
+
+print "==> checking makedepends"
+for name,pkg in repopkgs.iteritems():
+ (makedeps,missdeps,hierarchy) = verify_deps(name,pkg.repo,pkg.makedeps)
+ makepkgdeps[pkg] = makedeps
+ missing_makedeps.extend(missdeps)
+ makedeph.extend(hierarchy)
+
+print "==> checking hierarchy"
+dep_hierarchy = check_hierarchy(deph)
+makedep_hierarchy = check_hierarchy(makedeph)
+
+print "==> checking for circular dependencies"
+# make sure pkgdeps is filled for every package
+for name,pkg in packages.iteritems():
+ if not pkgdeps.has_key(pkg):
+ (deps,missdeps,_) = verify_deps(name,pkg.repo,pkg.deps)
+ pkgdeps[pkg] = deps
+find_scc(repopkgs.values())
+
+print "==> checking for differences between db files and pkgbuilds"
+for repo in repos:
+ for pkg in dbpkgs[repo]:
+ if not (pkg in repopkgs.keys() and repopkgs[pkg].repo == repo):
+ dbonly.append("%s/%s" % (repo,pkg))
+for name,pkg in repopkgs.iteritems():
+ if not name in dbpkgs[pkg.repo]:
+ absonly.append("%s/%s" % (pkg.repo,name))
+
+print_results()
diff --git a/build_tools/bin/check_repo/parse_pkgbuilds.sh b/build_tools/bin/check_repo/parse_pkgbuilds.sh
new file mode 100755
index 0000000..5cd17e4
--- /dev/null
+++ b/build_tools/bin/check_repo/parse_pkgbuilds.sh
@@ -0,0 +1,149 @@
+#!/bin/bash
+
+# Usage : parse_pkgbuilds.sh arch <pkgbuilds_dir1,dir2,...>
+# Example : parse_pkgbuilds.sh i686 /var/abs/core /var/abs/extra
+
+exit() { return; }
+
+splitpkg_overrides=('depends' 'optdepends' 'provides' 'conflicts')
+variables=('pkgname' 'pkgbase' 'pkgver' 'pkgrel' 'makedepends' 'arch' ${splitpkg_overrides[@]})
+readonly -a variables splitpkg_overrides
+
+backup_package_variables() {
+ for var in ${splitpkg_overrides[@]}; do
+ indirect="${var}_backup"
+ eval "${indirect}=(\${$var[@]})"
+ done
+}
+
+restore_package_variables() {
+ for var in ${splitpkg_overrides[@]}; do
+ indirect="${var}_backup"
+ if [ -n "${!indirect}" ]; then
+ eval "${var}=(\${$indirect[@]})"
+ else
+ unset ${var}
+ fi
+ done
+}
+
+print_info() {
+ echo -e "%NAME%\n$pkgname\n"
+ echo -e "%VERSION%\n$pkgver-$pkgrel\n"
+ echo -e "%PATH%\n$dir\n"
+
+ if [ -n "$pkgbase" ]; then
+ echo -e "%BASE%\n$pkgbase\n"
+ fi
+
+ if [ -n "$arch" ]; then
+ echo "%ARCH%"
+ for i in ${arch[@]}; do echo $i; done
+ echo ""
+ fi
+ if [ -n "$depends" ]; then
+ echo "%DEPENDS%"
+ for i in ${depends[@]}; do
+ echo $i
+ done
+ echo ""
+ fi
+ if [ -n "$makedepends" ]; then
+ echo "%MAKEDEPENDS%"
+ for i in ${makedepends[@]}; do
+ echo $i
+ done
+ echo ""
+ fi
+ if [ -n "$conflicts" ]; then
+ echo "%CONFLICTS%"
+ for i in ${conflicts[@]}; do echo $i; done
+ echo ""
+ fi
+ if [ -n "$provides" ]; then
+ echo "%PROVIDES%"
+ for i in ${provides[@]}; do echo $i; done
+ echo ""
+ fi
+}
+
+source_pkgbuild() {
+ ret=0
+ dir=$1
+ pkgbuild=$dir/PKGBUILD
+ for var in ${variables[@]}; do
+ unset ${var}
+ done
+ source $pkgbuild &>/dev/null || ret=$?
+
+ # ensure $pkgname and $pkgver variables were found
+ if [ $ret -ne 0 -o -z "$pkgname" -o -z "$pkgver" ]; then
+ echo -e "%INVALID%\n$pkgbuild\n"
+ return 1
+ fi
+
+ if [ "${#pkgname[@]}" -gt "1" ]; then
+ pkgbase=${pkgbase:-${pkgname[0]}}
+ for pkg in ${pkgname[@]}; do
+ if [ "$(type -t package_${pkg})" != "function" ]; then
+ echo -e "%INVALID%\n$pkgbuild\n"
+ return 1
+ else
+ backup_package_variables
+ pkgname=$pkg
+ while IFS= read -r line; do
+ var=${line%%=*}
+ var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
+ for realvar in ${variables[@]}; do
+ if [ "$var" == "$realvar" ]; then
+ eval $line
+ break
+ fi
+ done
+ done < <(type package_${pkg})
+ print_info
+ restore_package_variables
+ fi
+ done
+ else
+ echo
+ print_info
+ fi
+
+ return 0
+}
+
+find_pkgbuilds() {
+ #Skip over some dirs
+ local d="${1##*/}"
+ if [ "$d" = "CVS" -o "$d" = ".svn" ]; then
+ return
+ fi
+
+ if [ -f $1/PKGBUILD ]; then
+ source_pkgbuild $1
+ return
+ fi
+ empty=1
+ for dir in $1/*; do
+ if [ -d $dir ]; then
+ find_pkgbuilds $dir
+ unset empty
+ fi
+ done
+ if [ -n "$empty" ]; then
+ echo -e "%MISSING%\n$1\n"
+ fi
+}
+
+if [ -z "$1" -o -z "$2" ]; then
+ exit 1
+fi
+
+CARCH=$1
+shift
+for dir in "$@"; do
+ find_pkgbuilds $dir
+done
+
+exit 0
diff --git a/build_tools/bin/check_repo/setup.py b/build_tools/bin/check_repo/setup.py
new file mode 100644
index 0000000..b172752
--- /dev/null
+++ b/build_tools/bin/check_repo/setup.py
@@ -0,0 +1,10 @@
+from distutils.core import setup, Extension
+
+alpm = Extension('alpm',
+ libraries = ['alpm'],
+ sources = ['alpm.c'])
+
+setup (name = 'Alpm',
+ version = '1.0',
+ description = 'Alpm bindings',
+ ext_modules = [alpm])