diff options
author | Jakub Jirutka <jakub@jirutka.cz> | 2017-07-25 21:44:50 +0200 |
---|---|---|
committer | Jakub Jirutka <jakub@jirutka.cz> | 2017-07-25 21:44:50 +0200 |
commit | a66abec72346d0bd50d0dad6c02c2fc8023e277a (patch) | |
tree | da36dddf35be68bbac04ce9a3b161a59e96b4aa4 /bin | |
parent | b8151f36204607d1697701ad6174af2073ffa77c (diff) | |
download | lua-aports-a66abec72346d0bd50d0dad6c02c2fc8023e277a.tar.bz2 lua-aports-a66abec72346d0bd50d0dad6c02c2fc8023e277a.tar.xz |
move binfiles to bin/ directory
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/ap.lua | 153 | ||||
-rwxr-xr-x | bin/buildrepo.lua | 259 |
2 files changed, 412 insertions, 0 deletions
diff --git a/bin/ap.lua b/bin/ap.lua new file mode 100755 index 0000000..1251064 --- /dev/null +++ b/bin/ap.lua @@ -0,0 +1,153 @@ +#!/usr/bin/lua5.2 + +local lfs = require('lfs') + + +-- subcommands ----------------------- +local subcmd = {} + +subcmd.revdep = { + desc = "Print reverse dependencies", + usage = "PKG...", + run = function(db, opts) + for i = 1, #opts do + for _, pkg in db:each_reverse_dependency(opts[i]) do + print(pkg.pkgname) + end + end + end +} + +subcmd.list = { + desc = "Print all packages built from aports tree", + usage = "", + run = function(db) + for _,pn in db:each() do + print(pn) + end + end +} + +subcmd.recursdeps = { + desc = "Recursively print all make dependencies for given packages", + usage = "PKG...", + run = function (db, opts) + for i = 1, #opts do + for dep in db:recursive_dependencies(opts[i]) do + print(dep) + end + end + end +} + +subcmd.builddirs = { + desc = "Print the build dirs for given packages in build order", + usage = "PKG...", + run = function(db, opts) + for pkg in db:each_in_build_order(opts) do + print(pkg.dir) + end + end +} + +subcmd.sources = { + desc = "List sources", + usage = "PKG...", + run = function(db, opts) + for i = 1, #opts do + for pkg in db:each_pkg_with_name(opts[i]) do + for url in pkg:remote_sources() do + print(pkg.pkgname, pkg.pkgver, string.gsub(url, pkg.pkgver, "$VERSION")) + end + end + end + end +} + +subcmd["build-list"] = { + desc = "List packages that can/should be rebuilt", + usage = "", + run = function(db) + local nlist = {} + for pkg in db:each_need_build() do + table.insert(nlist, pkg.pkgname) + end + for pkg in db:each_in_build_order(nlist) do + print(pkg.dir) + end + end +} + +subcmd["apk-list"] = { + desc = "List all apk files", + usage = "", + run = function(db) + for pkg in db:each() do + if pkg:relevant() then + print(pkg:get_apk_file_name()) + end + end + end +} + +subcmd["dump-json"] = { + desc = "Dump all abuilds from aports tree to JSON", + run = function(db) + local dump = require "aports.dump" + print(dump.pkgs_to_json(db:each_aport())) + end +} + +local function print_usage() + io.write("usage: ap -d <DIR> SUBCOMMAND [options]\n\nSubcommands are:\n") + for k in pairs(subcmd) do + print(" "..k) + end +end + +-- those should be read from some config file +local repodirs = {} + + +-- parse args +local opts = {} +local help = false +do + local i = 1 + while i <= #arg do + if arg[i] == "-d" then + i = i + 1 + repodirs[#repodirs + 1] = arg[i] + elseif arg[i] == "-h" then + help = true + else + opts[#opts + 1] = arg[i] + end + i = i + 1 + end +end + +local cmd = table.remove(opts, 1) + +if help or not cmd then + print_usage() + -- usage + return +end + +if #repodirs == 0 then + if lfs.attributes("APKBUILD") then + repodirs[1] = string.gsub(lfs.currentdir(), "(.*)/.*", "%1") + else + repodirs[1] = lfs.currentdir() + end +end + +if subcmd[cmd] and type(subcmd[cmd].run) == "function" then + for _, dir in pairs(repodirs) do + local db = require('aports.db').new(dir:match("(.*)/([^/]*)")) + subcmd[cmd].run(db, opts) + end +else + io.stderr:write(cmd..": invalid subcommand\n") +end diff --git a/bin/buildrepo.lua b/bin/buildrepo.lua new file mode 100755 index 0000000..7f6b886 --- /dev/null +++ b/bin/buildrepo.lua @@ -0,0 +1,259 @@ +#!/usr/bin/lua5.2 + +local abuild = require("aports.abuild") +local apkrepo = require("aports.apkrepo") +local lfs = require("lfs") +local optarg = require("optarg") + +local pluginsdir = "/etc/buildrepo/plugins.d" + +local function warn(formatstr, ...) + io.stderr:write(("WARNING: %s\n"):format(formatstr:format(...))) + io.stderr:flush() +end + +local function err(formatstr, ...) + io.stderr:write(("ERROR: %s\n"):format(formatstr:format(...))) + io.stderr:flush() +end + +local function info(formatstr, ...) + io.stdout:write(("%s\n"):format(formatstr:format(...))) + io.stdout:flush() +end + +local function skip_aport(aport) + local dirattr = lfs.attributes(aport.dir.."/src/") + local fileattr = lfs.attributes(aport.dir.."/APKBUILD") + if not dirattr or not fileattr then + return false + end + if os.difftime(fileattr.modification, dirattr.modification) > 0 then + return false + end + warn("%s: Skipped due to previous build failure", aport.pkgname) + return true +end + +local function run_plugins(dirpath, func, ...) + local a = lfs.attributes(dirpath) + if not a or a.mode ~= "directory" then + return + end + local flist = {} + for f in lfs.dir(dirpath) do + if string.match(f, ".lua$") then + table.insert(flist, f) + end + end + table.sort(flist) + for i = 1, #flist do + local m = dofile(dirpath.."/"..flist[i]) + if type(m[func]) == "function" then + m[func](...) + end + end +end + +local function plugins_prebuild(...) + return run_plugins(pluginsdir, "prebuild", ...) +end + +local function plugins_postbuild(...) + return run_plugins(pluginsdir, "postbuild", ...) +end + +local function plugins_prerepo(...) + return run_plugins(pluginsdir, "prerepo", ...) +end + +local function plugins_postrepo(...) + return run_plugins(pluginsdir, "postrepo", ...) +end + +local function logfile_path(logdirbase, repo, aport) + if not logdirbase then + return nil + end + local dir = ("%s/%s/%s"):format(logdirbase, repo, aport.pkgname) + if not lfs.attributes(dir) then + local path = "" + for n in string.gmatch(dir, "[^/]+") do + path = path.."/"..n + lfs.mkdir(path) + end + end + return ("%s/%s-%s-r%s.log"):format(dir, aport.pkgname, aport.pkgver, aport.pkgrel) +end + + +local function build_aport(aport, repodest, logfile) + local success, errmsg = lfs.chdir(aport.dir) + if not success then + err("%s", errmsg) + return nil + end + local logredirect = "" + if logfile ~= nil then + logredirect = ("> '%s' 2>&1"):format(logfile) + end + local cmd = ("REPODEST='%s' abuild -r -m %s"):format(repodest, logredirect) + success = os.execute(cmd) + if not success then + err("%s: Failed to build", aport.pkgname) + end + return success +end + +local function log_progress(progress, repo, aport) + info("%d/%d %d/%d %s/%s %s-r%s", + progress.tried, progress.total, + progress.repo_built, progress.repo_total, + repo, aport.pkgname, aport.pkgver, aport.pkgrel) +end +----------------------------------------------------------------- +local opthelp = [[ + -a, --aports=DIR Set the aports base dir to DIR instead of $HOME/aports + -d, --destdir=DIR Set destination repository base to DIR instead of + $HOME/packages + -h, --help Show this help and exit + -l, --logdir=DIR Create build logs in DIR/REPO/pkgname/ instead of stdout + -k, --keep-going Keep going, even if packages fails + -n, --dry-run Dry run. Don't acutally build or delete, just print + -p, --purge Purge obsolete packages from REPODIR after build + -r, --deps-repo=REPO Dependencies are found in REPO + -s, --skip-failed Skip those who previously failed (src dir exists) +]] + +local function usage(exitcode) + io.stdout:write(( + "Usage: %s [-hknps] [-a DIR] [-d DIR] [-l DIR] [-r REPO] REPO...\n".. + "Options:\n%s\n"):format(_G.arg[0], opthelp)) + os.exit(exitcode) +end + +local opts, args = optarg.from_opthelp(opthelp) +if not opts or #args == 0 then + usage(1) +end + +if opts.h then + usage(0) +end + +local homedir = os.getenv("HOME") +local aportsdir = opts.a or ("%s/aports"):format(homedir) +local repodest = opts.d or abuild.repodest or ("%s/packages"):format(homedir) +local logdirbase = opts.l + +if opts.n then + build_aport = function() return true end +end + +local stats = {} +for _, repo in pairs(args) do + local db = require('aports.db').new(aportsdir, repo, repodest) + local pkgs = {} + local unsorted = {} + stats[repo] = {} + local start_time = os.clock() + + if not db then + err("%s/%s: Failed to open apkbuilds", aportsdir, repo) + os.exit(1) + end + + -- count total aports + local relevant_aports = 0 + local total_aports = 0 + for aport in db:each_aport() do + total_aports = total_aports + 1 + if aport:relevant() then + relevant_aports = relevant_aports + 1 + end + end + stats[repo].relevant_aports = relevant_aports + stats[repo].total_aports = total_aports + + -- run prerepo hooks + plugins_prerepo(repo, aportsdir, repodest, abuild.arch, stats[repo]) + + -- find out what needs to be built + for aport in db:each_need_build() do + table.insert(pkgs, aport.pkgname) + if unsorted[aport.pkgname] then + warn("more than one aport provides %s", aport.pkgname) + end + unsorted[aport.pkgname] = true + end + + -- build packages + local built = 0 + local tried = 0 + for aport in db:each_in_build_order(pkgs) do + local logfile = logfile_path(logdirbase, repo, aport) + tried = tried + 1 + local progress = { + tried = tried, + total = #pkgs, + repo_built = stats[repo].relevant_aports - #pkgs + built, + repo_total = stats[repo].relevant_aports, + } + if not db:known_deps_exists(aport) then + warn("%s: Skipped due to missing dependencies", aport.pkgname) + elseif not (opts.s and skip_aport(aport)) then + log_progress(progress, repo, aport) + plugins_prebuild(aport, progress, repodest, abuild.arch, logfile) + local success = build_aport(aport, repodest, logfile) + plugins_postbuild(aport, success, repodest, abuild.arch, logfile) + if success then + built = built + 1 + end + if not success and not opts.k then + os.exit(1) + end + end + end + + -- purge old packages + local deleted = 0 + if opts.p then + local keep = {} + for aport, name in db:each() do + keep[aport:get_apk_file_name(name)] = true + end + local apkrepodir = ("%s/%s/%s"):format(repodest, repo, abuild.arch) + for file in lfs.dir(apkrepodir) do + if file:match("%.apk$") and not keep[file] then + info("Deleting %s", file) + if not opts.n then + os.remove(("%s/%s"):format(apkrepodir, file)) + deleted = deleted + 1 + end + end + end + end + + -- generate new apkindex + if not opts.n and (built > 0 or deleted > 0) then + info("Updating apk index") + apkrepo.update_index(("%s/%s"):format(repodest, repo), + abuild.arch, db:git_describe()) + end + stats[repo].built = built + stats[repo].tried = tried + stats[repo].deleted = deleted + stats[repo].time = os.clock() - start_time + + -- run portrepo hooks + plugins_postrepo(repo, aportsdir, repodest, abuild.arch, stats[repo]) +end + +for repo, stat in pairs(stats) do + info("%s built:\t%d", repo, stat.built) + info("%s tried:\t%d", repo, stat.tried) + info("%s deleted:\t%d", repo, stat.deleted) + info("%s total built:\t%d", repo, stat.relevant_aports - stat.tried + stat.built) + info("%s total relevant aports:\t%d", repo, stat.relevant_aports) + info("%s total aports:\t%d", repo, stat.total_aports) +end |