From 10769cccbfe6b06d8f957377afaabeeacbc53891 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Tue, 31 Dec 2013 09:06:39 +0000 Subject: db: rename module to aports.db --- aports/db.lua | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 aports/db.lua (limited to 'aports') diff --git a/aports/db.lua b/aports/db.lua new file mode 100644 index 0000000..971af86 --- /dev/null +++ b/aports/db.lua @@ -0,0 +1,308 @@ + +abuild_conf_file = "/etc/abuild.conf" +abuild_functions = "/usr/share/abuild/functions.sh" + +local abuild_conf = {} +local M = {} + +function M.get_abuild_conf(var) + -- check cache + if abuild_conf[var] ~= nil then + return abuild_conf[var] + end + + -- use os env var + abuild_conf[var] = os.getenv(var) + if abuild_conf[var] ~= nil then + return abuild_conf[var] + end + + -- parse config file + local f = io.popen(" . "..abuild_conf_file..' ; echo -n "$'..var..'"') + abuild_conf[var] = f:read("*all") + f:close() + return abuild_conf[var] +end + +local function split_subpkgs(str) + local t = {} + local e + if (str == nil) then + return nil + end + for e in string.gmatch(str, "%S+") do + t[#t + 1] = string.gsub(e, ":.*", "") + end + return t +end + +local function split(str) + local t = {} + local e + if (str == nil) then + return nil + end + for e in string.gmatch(str, "%S+") do + t[#t + 1] = e + end + return t +end + +local function split_apkbuild(line) + local r = {} + local dir,pkgname, pkgver, pkgrel, arch, depends, makedepends, subpackages, source, url = string.match(line, "([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)") + r.dir = dir + r.pkgname = pkgname + r.pkgver = pkgver + r.pkgrel = pkgrel + r.depends = split(depends) + r.makedepends = split(makedepends) + r.subpackages = split_subpkgs(subpackages) + r.source = split(source) + r.url = url + return r +end + +-- parse the APKBUILDs and return an iterator +local function parse_apkbuilds(dirs) + local i,v, p + local str="" + if dirs == nil then + return nil + end + --expand repos + for i,v in ipairs(dirs) do + str = str..v.."/*/APKBUILD " + end + + local p = io.popen(". "..abuild_functions..";"..[[ + for i in ]]..str..[[; do + pkgname= + pkgver= + pkgrel= + arch= + depends= + makedepends= + subpackages= + source= + url= + dir="${i%/APKBUILD}"; + [ -n "$dir" ] || exit 1; + cd "$dir"; + . ./APKBUILD; + echo $dir\|$pkgname\|$pkgver\|$pkgrel\|$arch\|$depends\|$makedepends\|$subpackages\|$source\|$url ; + done; + ]]) + return function() + local line = p:read("*line") + if line == nil then + p:close() + return nil + end + return split_apkbuild(line) + end +end + + + +-- return a key list with makedepends and depends +function M.all_deps(p) + local m = {} + local k,v + if p == nil then + return m + end + if type(p.depends) == "table" then + for k,v in pairs(p.depends) do + m[v] = true + end + end + if type(p.makedepends) == "table" then + for k,v in pairs(p.makedepends) do + m[v] = true + end + end + return m +end + +function M.is_remote(url) + local _,pref + for _,pref in pairs{ "^http://", "^ftp://", "^https://", ".*::.*" } do + if string.match(url, pref) then + return true + end + end + return false +end + +-- iterator for all remote sources of given pkg/aport +function M.remote_sources(p) + if p == nil or type(p.source) ~= "table" then + return nil + end + return coroutine.wrap(function() + for _,url in pairs(p.source) do + if M.is_remote(url) then + coroutine.yield(url) + end + end + end) +end + +function M.get_maintainer(pkg) + if pkg == nil or pkg.dir == nil then + return nil + end + local f = io.open(pkg.dir.."/APKBUILD") + if f == nil then + return nil + end + local line + for line in f:lines() do + local maintainer = line:match("^%s*#%s*Maintainer:%s*(.*)") + if maintainer then + f:close() + return maintainer + end + end + f:close() + return nil +end + +function M.get_repo_name(pkg) + if pkg == nil or pkg.dir == nil then + return nil + end + return string.match(pkg.dir, ".*/(.*)/.*") +end + +function M.get_apk_filename(pkg) + return pkg.pkgname.."-"..pkg.pkgver.."-r"..pkg.pkgrel..".apk" +end + +function M.get_apk_file_path(pkg) + local pkgdest = get_abuild_conf("PKGDEST") + if pkgdest ~= nil and pkgdest ~= "" then + return pkgdest.."/"..M.get_apk_filename(pkg) + end + local repodest = M.get_abuild_conf("REPODEST") + if repodest ~= nil and repodest ~= "" then + local arch = M.get_abuild_conf("CARCH") + return repodest.."/"..M.get_repo_name(pkg).."/"..arch.."/"..M.get_apk_filename(pkg) + end + return pkg.dir.."/"..M.get_apk_filename(pkg) +end + + +local function init_apkdb(repodirs) + local pkgdb = {} + local revdeps = {} + local a + for a in parse_apkbuilds(repodirs) do + -- io.write(a.pkgname.." "..a.pkgver.."\t"..a.dir.."\n") + if pkgdb[a.pkgname] == nil then + pkgdb[a.pkgname] = {} + end + a.all_deps = M.all_deps + table.insert(pkgdb[a.pkgname], a) + -- add subpackages to package db + local k,v + for k,v in pairs(a.subpackages) do + if pkgdb[v] == nil then + pkgdb[v] = {} + end + table.insert(pkgdb[v], a) + end + -- add to reverse dependencies + for v in pairs(M.all_deps(a)) do + if revdeps[v] == nil then + revdeps[v] = {} + end + table.insert(revdeps[v], a) + end + end + return pkgdb, revdeps +end + +local Aports = {} +function Aports:recursive_dependencies(pn) + local visited={} + local apkdb = self.apks + + return coroutine.wrap(function() + function recurs(pn) + if pn == nil or visited[pn] or apkdb[pn] == nil then + return false + end + visited[pn] = true + local _, p + for _, p in pairs(apkdb[pn]) do + local d + for d in pairs(M.all_deps(p)) do + if recurs(d) then + return true + end + end + end + coroutine.yield(pn) + end + return recurs(pn) + end) +end + +function Aports:target_packages(pkgname) + return coroutine.wrap(function() + for k,v in pairs(self.apks[pkgname]) do + coroutine.yield(pkgname.."-"..v.pkgver.."-r"..v.pkgrel..".apk") + end + end) +end + +function Aports:each() + local apks = self.apks + return coroutine.wrap(function() + for k,v in pairs(self.apks) do + coroutine.yield(k,v) + end + end) +end + +function Aports:each_reverse_dependency(pkg) + return coroutine.wrap(function() + for k,v in pairs(self.revdeps[pkg] or {}) do + coroutine.yield(k,v) + end + end) +end + +function Aports:each_pkg(pkg, f) + if self.apks[pkg] == nil then + io.stderr:write("WARNING: "..pkg.." has no data\n") + end + return coroutine.wrap(function() + for k,v in pairs(self.apks[pkg]) do + coroutine.yield(k,v) + end + end) +end + +function Aports:each_aport() + return coroutine.wrap(function() + for pkgname,v in self:each() do + for _,pkg in self:each_pkg(pkgname) do + if pkgname == pkg.pkgname then + coroutine.yield(pkg) + end + end + end + end) +end + +function M.new(repodirs) + local h = Aports + h.repodirs = repodirs + h.apks, h.revdeps = init_apkdb(repodirs) + return h +end + +return M -- cgit v1.2.3