+--- e2-build-numbers command.
+-- This command was removed in e2factory 2.3.13.
+-- @module local.e2-build-numbers
+
--[[
e2factory, the emlix embedded build system
- Copyright (C) 2007-2009 Gordon Hecker <gh@emlix.com>, emlix GmbH
- Copyright (C) 2007-2009 Oskar Schirmer <os@emlix.com>, emlix GmbH
- Copyright (C) 2007-2008 Felix Winkelmann, emlix GmbH
+ Copyright (C) Tobias Ulmer <tu@emlix.com>, emlix GmbH
For more information have a look at http://www.e2factory.org
local e2lib = require("e2lib")
local e2tool = require("e2tool")
-local e2option = require("e2option")
-local policy = require("policy")
+local err = require("err")
e2lib.init()
local info, re = e2tool.local_init(nil, "build-numbers")
e2lib.abort(re)
end
-e2option.documentation = [[
-usage:
-e2-buildnumbers [--no-sync]
-]]
-
-policy.register_commandline_options()
-e2option.flag("no-sync", "do not synchronize with the server")
-
-local opts = e2option.parse(arg)
--- get build mode from the command line
-local build_mode = policy.handle_commandline_options(opts, true)
-if not build_mode then
- e2lib.abort("no build mode given")
-end
-info, re = e2tool.collect_project_info(info)
-if not info then
- e2lib.abort(re)
-end
-local rc, re = e2tool.check_project_info(info)
-if not rc then
- e2lib.abort(re)
-end
-
--- apply the standard build mode to all results
-for _,res in pairs(info.results) do
- res.build_mode = build_mode
-end
-
--- read build numbers,
--- merge to results,
--- flush buildids,
--- calculate buildids,
--- merge back,
--- request new build numbers,
--- write new build numbers
-
-local rc, re
-rc, re = e2tool.buildnumber_read(info)
-if not rc then
- e2lib.abort(re)
-end
-rc, re = e2tool.buildnumber_mergetoresults(info)
-if not rc then
- e2lib.abort(re)
-end
--- recalculate build ids ids
-e2tool.flush_buildids(info)
-e2tool.calc_buildids(info)
-rc, re = e2tool.buildnumber_mergefromresults(info)
-if not rc then
- e2lib.abort(re)
-end
-if opts["no-sync"] then
- rc, re = e2tool.buildnumber_request_local(info)
-else
- rc, re = e2tool.buildnumber_request(info)
-end
-if not rc then
- e2lib.abort(re)
-end
-rc, re = e2tool.buildnumber_write(info)
-if not rc then
- e2lib.abort(re)
-end
-e2tool.buildnumber_display(info.build_numbers, 1)
-e2lib.finish()
+e2lib.abort(err.new("e2-build-numbers is deprecated and has been removed"))
-- vim:sw=4:sts=4:et:
-- @field chroot_groups_sorted table: sorted list of chroot groups
-- @field ghash table: temporary list keeps hashes for chroot groups
-- (generated by buildid_chrootgroup())
--- @field build_numbers table: build numbers keyed by result names
-- @field project_location string: project location relative to the servers
-- @field release_id string: release identifiert XXX where do we initialize it?
-- @field env table: env table
-- if x86_64 mode is requested.
info.chroot_call_prefix["x86_64"] = ""
- -- build number state file
- info.buildnumber_file = string.format("%s/.e2/build-numbers", info.root)
-
- -- build number table
- info.build_numbers = {}
-
info.hashcache_file = string.format("%s/.e2/hashcache", info.root)
rc, re = hashcache_setup(info)
if not rc then
return true, nil
end
---- parse build numbers from a string and store to the build number table
--- @param info the info table
--- @param s string: the string to parse
--- @param build_numbers table: build number table (optional)
--- @return bool
--- @return nil, an error object on error
-local function string2bn(info, s, build_numbers)
- e2lib.logf(4, "string2bn()")
- if not build_numbers then
- build_numbers = info.build_numbers
- end
- local rc
- local re = err.new("error parsing build numbers:")
- e2lib.log(3, "parsing build numbers")
- local line = 0
- for l in s:gmatch("[^\n]+") do
- line = line + 1
- local bn = {}
- local r
- r, bn.bid, bn.status, bn.num = l:match(
- ("([-%w_]+)%s+(%x+)%s+(%S+)%s+(%d+)"))
- if not r then
- re:append("parse error in line %d", line)
- return false, re
- end
- e2lib.logf(4, "%s %s %s %s", r, bn.bid, bn.status, bn.num)
- local oldbn = build_numbers[r]
- if oldbn and oldbn.num and oldbn.num ~= bn.num then
- bn.oldnum = oldbn.num
- end
- build_numbers[r] = bn
- end
- return true, nil
-end
-
---- serialize the build number table suitable for storage or network
--- transport
--- @param info info table
--- @param build_numbers table: build number table (optional)
--- @return s string: serialized build numbers, or nil
--- @return nil, an error object on error
-local function bn2string(info, build_numbers)
- e2lib.logf(4, "bn2string()")
- if not build_numbers then
- build_numbers = info.build_numbers
- end
- local s = ""
- for r,bn in pairs(build_numbers) do
- e2lib.logf(4, "%s %s %s %s", r, bn.bid, bn.status, bn.num)
- local s1 = string.format("%s %s %s %s\n",
- r, bn.bid, bn.status, bn.num)
- s = s .. s1
- end
- return s, nil
-end
-
---- write the build number file
--- @param info the info table
--- @param file string: the build number file (optional)
--- @param build_numbers table: build number table (optional)
--- @return bool
--- @return an error object on error
-local function buildnumber_write(info, file, build_numbers)
- e2lib.logf(4, "e2tool.buildnumber_write()")
- local rc, msg
- if not file then
- file = info.buildnumber_file
- end
- if not build_numbers then
- build_numbers = info.build_numbers
- end
- local e = err.new("error writing build number file:")
- e2lib.logf(3, "writing build numbers to %s", file)
- local s, re = bn2string(info)
- if not s then
- e:cat(re)
- return false, e
- end
- rc, re = e2lib.write_file(file, s)
- if not rc then
- e:cat(re)
- return false, e
- end
- return true, nil
-end
-
---- read the build number file into the buildnumber table
--- @param info the info table
--- @param file string: the build number file (optional)
--- @param build_numbers table: build number table (optional)
--- @return bool
--- @return an error object on error
-function e2tool.buildnumber_read(info, file, build_numbers)
- e2lib.logf(4, "e2tool.buildnumber_read()")
- local rc, re, msg
- if not file then
- file = info.buildnumber_file
- end
- if not build_numbers then
- build_numbers = info.build_numbers
- end
- local e = err.new("error reading build number file:")
- e2lib.logf(3, "reading build-numbers from %s", file)
- local s, re = e2lib.read_file(file)
- if not s and e2lib.isfile(file) then
- e:cat(re)
- return false, e
- elseif not s then
- e2lib.warnf("WOTHER", "build number file does not exist")
- s = ""
- end
- local rc, re = string2bn(info, s, build_numbers)
- if not rc then
- e:cat(re)
- return false, e
- end
- return true, nil
-end
-
---- merge build numbers from the build number table to the results
--- @param info table: the info table
--- @return bool
--- @return nil, an error object on failure
-function e2tool.buildnumber_mergetoresults(info)
- e2lib.log(3, string.format("merging build numbers to results"))
- local e = err.new("merging build numbers to results:")
- for r, res in pairs(info.results) do
- local bn = info.build_numbers[r]
- if not bn then
- e2lib.warnf("WOTHER",
- "no build number entry for result: %s", r)
- elseif res.pbuildid == bn.id then
- e2lib.log(3, string.format(
- "applying build number to result: %s [%s]",
- r, bn.num))
- res.buildno = bn.num
- else
- e:append("pseudo buildid mismatch in result %s", r)
- end
- end
- if e:getcount() > 1 then
- return false, e
- end
- return true, nil
-end
-
---- merge build numbers and pbid from the result to the build number table
--- @param info table: the info table
--- @return bool
--- @return nil, an error object on failure
-function e2tool.buildnumber_mergefromresults(info)
- e2lib.log(3, string.format("merging build numbers from results"))
- for r, res in pairs(info.results) do
- local bn = info.build_numbers[r]
- if not bn then
- e2lib.warnf("WOTHER",
- "creating new build number entry for result: %s", r)
- -- create a new entry
- bn = {}
- bn.status = "ok"
- bn.num = res.buildno
- info.build_numbers[r] = bn
- end
- bn.bid = pbuildid(info, r)
- e2lib.logf(4, "%s %s %s %s", r, tostring(bn.bid), bn.status, bn.num)
- end
- return true, nil
-end
-
---- display buildnumbers
--- @param build_numbers table: build number table
--- @param loglevel (optional, default 2)
--- @return nil
-local function buildnumber_display(build_numbers, loglevel)
- if not loglevel then
- loglevel = 2
- end
- e2lib.log(loglevel, "displaying build-number table:")
- e2lib.logf(loglevel, "%-20s %-40s %2s %5s %-7s",
- "result", "pbuildid", "st", "num", "old")
- for r,bn in pairs(build_numbers) do
- local changed = ""
- if bn.oldnum then
- changed = string.format("[%d]", bn.oldnum)
- end
- e2lib.logf(loglevel, "%-20s %40s %2s %5d %-7s",
- r, bn.bid, bn.status, bn.num, changed)
- end
-end
-
---- request new build numbers from the server
--- @param info
--- @return bool
--- @return an error object on failure
-function e2tool.buildnumber_request(info)
- e2lib.log(3, "requesting build numbers from server")
-
- if e2lib.globals.buildnumber_server_url == nil then
- return false, err.new("no build number server configured")
- end
-
- local rc, re
- local e = err.new("error requesting build numbers")
- local tmpdir = e2lib.mktempdir()
- local tmpreq = string.format("%s/build-number.req.tmp", tmpdir)
- local tmpres = string.format("%s/build-number.res.tmp", tmpdir)
- local curlflags = "--create-dirs --silent --show-error --fail"
- local url = string.format(
- "'%s?project=%s&user=%s&host=%s'",
- e2lib.globals.buildnumber_server_url, info.name,
- e2lib.globals.osenv["USER"], e2lib.globals.hostname)
- local args = string.format(
- "%s " ..
- "--header 'Content-type: text/plain' " ..
- "--data-binary '@%s' %s -o %s",
- curlflags,
- tmpreq, url, tmpres)
- rc, re = buildnumber_write(info, tmpreq)
- if not rc then
- e:append(re)
- return false, e
- end
- e2lib.log(3, "sending request")
- rc, re = e2lib.curl(args)
- if not rc then
- e:append(re)
- return false, e
- end
- rc, re = e2tool.buildnumber_read(info, tmpres)
- if not rc then
- e:append(re)
- return false, e
- end
- e2lib.rmtempdir(tmpdir)
- return true, nil
-end
-
---- perform the buildnumber update without synchronizing to the server
--- @param info
--- @return bool
--- @return an error object on failure
-local function buildnumber_request_local(info)
- e2lib.log(3, "requesting build numbers locally")
- local rc, re
- local req -- the request
- local sta -- the state
- local res -- the response
- local e = err.new("error in local buildnumber request")
- -- compose the request
- req = info.build_numbers
- -- compose the state
- sta = {}
- rc, re = e2tool.buildnumber_read(info, nil, sta)
- if not rc then
- return false, e:cat(re)
- end
- -- run the update function locally
- res = {}
- rc, re = buildnumber_update(sta, req, res)
- if not rc then
- return false, e:cat(re)
- end
- -- convert the result to a string
- local s
- s, re = bn2string(info, res)
- if not s then
- return false, e:cat(re)
- end
- -- convert the string back into the info structure
- rc, re = string2bn(info, s)
- if not rc then
- return false, e:cat(re)
- end
- return true
-end
-
---- update buildnumbers - usable on server side, or in --no-sync mode on the
--- client side
--- @param state table: build number table state
--- @param request table: build number table request
--- @param response table: build number table response
--- @return build number table
-local function buildnumber_update(state, request, response)
- e2lib.log(4, "buildnumber_update()")
- e2lib.log(4, "state:")
- buildnumber_display(state, 4)
- e2lib.log(4, "request")
- buildnumber_display(request, 4)
- for r,bn in pairs(request) do
- local req = bn
- local sta = state[r]
- e2lib.logf(4, "checking status for %s", r)
- if not sta then
- sta = {}
- sta.bid = req.bid
- sta.num = 1
- sta.status = "ok"
- state[r] = sta
- elseif sta.bid ~= req.bid or sta.num ~= req.num then
- e2lib.logf(4, "increasing buildnumber for %s", r)
- -- update status
- sta.num = math.max(sta.num, req.num) + 1
- sta.bid = req.bid
- sta.status = "ok"
- end
- -- create the response
- local res = {}
- res.bid = sta.bid
- res.num = sta.num
- res.status = sta.status
- response[r] = res
- end
- return true, nil
-end
-
--- select the result and apply build options
-- @param info
-- @param r string: the result name
+++ /dev/null
--- retrieve-build-numbers.lua - fetch current or new build-numbers -*- Lua -*-
---
--- method: POST
---
--- body: result-lines of the form "<resultname> <buildid*> <buildnumber>"
---
--- query string:
---
--- project=<projectname>
---
--- response: same format as request body, with updated or same contents
-
-
-local cl = os.getenv("CONTENT_LENGTH")
-
-local function fail(msg)
- print("Status: 500 Internal Server Error\n\n" .. msg)
- os.exit(1)
-end
-
-if not cl then fail("no content-length") end
-
-local function readbn(str)
- local t = {}
- for ln in string.gmatch(str, "[^\n]*\n") do
- if not string.match(ln, "^%s*$") then
- local res, bid, status, num =
- string.match(ln, "([-%w_]+)%s+(%x+)%s+(%S+)%s+(%d+)")
- if res then
- t[ res ] = { id = bid, num = num, status = status }
- else
- fail("invalid request line: " .. ln)
- end
- end
- end
- return t
-end
-
-local function writebn(f, t)
- for k, v in pairs(t) do
- f:write(k, " ", v.id, " ok ", v.num, "\n")
- end
-end
-
-local bytes = tonumber(cl)
-
-if bytes == 0 then
- fail("zero content-length")
-end
-
-local req = io.read(bytes) or fail("empty request")
-local usernums = readbn(req)
-local query = {}
-
-for k, v in string.gmatch(os.getenv("QUERY_STRING"), "(%w+)=([-%w_]+)") do
- query[ k ] = v
-end
-
-if not query.project then fail("no project given") end
-
-local logdir = "@LOGDIR@/" .. query.project
-local numfile = logdir .. "/build-numbers"
-
-os.execute("mkdir -p '" .. logdir .. "'")
-
-local currentnums
-local f, msg = io.open(numfile, "r")
-local changed = not f
-
-if not f then
- currentnums = usernums
-else
- local i = f:read("*a")
- if not i then
- fail("empty request")
- end
- f:close()
- currentnums = readbn(i)
-end
-
-for k, v in pairs(usernums) do
- local r = currentnums[ k ]
- if r then
- if r.id == v.id and v.status ~= "force" then
- v.num = r.num
- else
- r.num = r.num + 1
- r.id = v.id
- changed = true
- v.num = r.num
- end
- else
- currentnums[ k ] = v
- end
-end
-
-if changed then
- f, msg = io.open(numfile, "w")
- if not f then
- fail("can not write `" .. numfile .. "': " .. msg)
- end
- writebn(f, currentnums)
- f:close()
-end
-
-print("Content-type: text/plain\n")
-
-writebn(io.stdout, usernums)