playground build-numbers cf
LOCALSHTOOLS =
LUA_LIBS = e2option.lua luafile.lua generic_git.lua err.lua
-LUA_LIBS += e2tool.lua
+LUA_LIBS += e2tool.lua scm.lua git.lua svn.lua cvs.lua files.lua
LOCALTOOLS = $(LOCALSHTOOLS) $(LOCALLUATOOLS)
SYMLINKS_2_1 = lookup-server use-source prepare-cargo sync-results cleanup \
url.lua \
collection.lua \
e2lib.lua \
- e2scm.lua git.lua svn.lua cvs.lua files.lua \
hash.lua \
lock.lua \
e2build.lua \
-- cvs.lua - CVS-specific SCM operations -*- Lua -*-
--
--- See e2scm.lua for more information about these operations.
---
--- A "cvs" source description file "src" has this content:
---
--- <server> <remote> <working> <branch> <tag>
---
--- Restrictions:
---
--- * the working copy directory must have the same basename as
--- the CVS module name
--- * branches are not supported, yet
---
--- This code has only been tested superficially.
-
-
-local cvs = {}
+module("cvs", package.seeall)
+require("scm")
--- validate source configuration, log errors to the debug log
-- @param info the info table
-- @param sourcename the source name
-- @return bool
function cvs.validate_source(info, sourcename)
- local rc, re = generic_validate_source(info, sourcename)
+ local rc, re = git.generic_validate_source(info, sourcename)
if not rc then
-- error in generic configuration. Don't try to go on.
return false, re
src.sourceid = {}
end
local e = new_error("in source %s:", sourcename)
- rc, re = source_apply_default_working(info, sourcename)
+ rc, re = git.source_apply_default_working(info, sourcename)
if not rc then
return false, e:cat(re)
end
src.sourceid[source_set] = "working-copy"
end
if src.sourceid[source_set] then
- return src.sourceid[source_set]
+ return true, nil, src.sourceid[source_set]
end
local e = new_error("calculating sourceid failed for source %s",
sourcename)
hash.hash_line(hc, l)
local licenceid, re = e2tool.licenceid(info, l)
if not licenceid then
- return nil, re
+ return false, re
end
hash.hash_line(hc, licenceid)
end
-- skip src.working
e2lib.logf(4, "hash data for source %s\n%s", src.name, hc.data)
src.sourceid[source_set] = hash.hash_finish(hc)
- return src.sourceid[source_set], nil
+ return true, nil, src.sourceid[source_set]
end
function cvs.toresult(info, sourcename, sourceset, directory)
-- <directory>/licences
local rc, re
local e = new_error("converting result")
- rc, re = check(info, sourcename, true)
+ rc, re = git.check(info, sourcename, true)
if not rc then
return false, e:cat(re)
end
return true, nil
end
-e2scm.register("cvs", cvs)
+scm.register("cvs", cvs)
+++ /dev/null
---[[
- 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
-
- For more information have a look at http://www.e2factory.org
-
- e2factory is a registered trademark by emlix GmbH.
-
- This file is part of e2factory, the emlix embedded build system.
-
- e2factory 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 3 of the License, or
- (at your option) any later version.
-
- This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
-]]
-
--- e2scm.lua - SCM-specific functionality -*- Lua -*-
-
-
-e2scm = e2lib.module("e2scm")
-
-
--- General SCM wrapping
---
--- SCM-specific functions are implemented as sub-tables of the "e2scm"
--- namespace and calls to "e2scm.<SCM>.<op>(...)" are simply passed
--- to the SCM specific entries (after checking whether such an operation
--- exists for the selected SCM).
---
--- e2scm.register(SCMNAME, [TABLE]) -> TABLE
---
--- Registers an SCM with the given name and creates the namespace and
--- returns it (to be filled with operations). If a table is given as
--- argument, then the argument table is used instead of creating a
--- fresh one.
---
--- e2scm.register_op(OPNAME, DOC)
---
--- Registers SCM operation with documentation string.
---
-
-local scms = {}
-local ops = {}
-local scmmt = {}
-
-function scmmt.__index(t, k)
- local doc = ops[ k ] or
- e2lib.bomb("invalid SCM operation `" .. k .. "'")
- local x = rawget(t, k)
- return x or e2lib.abort("`" .. t.name .. "' can not " .. ops[ k ])
-end
-
-function e2scm.register(scm, t)
- t = t or {}
- t.name = scm
- scms[ scm ] = t
- return t
-end
-
-function e2scm.register_op(op, doc)
- ops[ op ] = doc
-end
-
-function e2scm.registered(scm)
- return scms[ scm ]
-end
-
--- iterate over registrated scm, include "files" when all is true
-function e2scm.iteratescms(all)
- local k = nil
- local t = scms
- local function nextscm(t)
- k = next(t, k)
- if k == "files" and not all then k = next(t, k) end
- return k
- end
- return nextscm, t
-end
-
--- for all scms, add an options flag
-function e2scm.optionsaddflags(all, text)
- local t = text or "use"
- for scm in e2scm.iteratescms(all) do
- e2option.flag(scm, t .. " source of type '" .. scm .. "'")
- end
-end
-
--- with options parsed, see which flag has been given with the options
-function e2scm.optionswhichflag(options, default)
- local f = nil
- for scm in e2scm.iteratescms(true) do
- if options[scm] then
- f = f and e2lib.abort("scm type flags to be used exclusively") or scm
- end
- end
- return f or default or e2lib.abort("no scm type flag given")
-end
-
-local mt = {}
-
-function mt.__index(t, k)
- local scm = scms[ k ]
- return scm or e2lib.bomb("no SCM is registered under the name `" .. k .. "'")
-end
-
-setmetatable(e2scm, mt)
-
-scm = {}
-
-local function sourcebyname(info, sourcename)
- local s = info.sources[sourcename]
- if not s then
- return nil, new_error("no source by that name: %s", sourcename)
- end
- return s, nil
-end
-
---- calculate and return the sourceid
--- @param info
--- @param sourcename
--- @param sourceset string: source set
--- @return string: the sourceid, or nil
--- @return an error object on failure
-function scm.sourceid(info, sourcename, sourceset)
- local src = sourcebyname(info, sourcename)
- local rc, re, e
- e = new_error("getting sourceid failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].sourceid then
- e:append("sourceid not implemented for source type: %s",
- src.type)
- return false, e
- end
- local sourceid
- sourceid, re = e2scm[src.type].sourceid(info, sourcename, sourceset)
- if not sourceid then
- return nil, re
- end
- return sourceid, nil
-end
-
---- validate a source configuration
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.validate_source(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("validating source failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].validate_source then
- e:append("validate_source not implemented for source type: %s",
- src.type)
- return false, e
- end
- rc, re = e2scm[src.type].validate_source(info, sourcename)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- create a result from a source
--- @param info
--- @param sourcename
--- @param sourceset string: source set
--- @param directory string: destination path to create the result
--- @return bool
--- @return an error object on failure
-function scm.toresult(info, sourcename, sourceset, directory)
- -- create in directory the following structure:
- -- ./makefile
- -- ./source/<files>
- -- ./licences/<files>.licences -- a list of licences per file
- -- ...
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].toresult then
- e:append("toresult not implemented for source type: %s",
- src.type)
- return false, e
- end
- local rc, re = e2scm[src.type].toresult(info, sourcename,
- sourceset, directory)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- prepare a source for building
--- @param info
--- @param sourcename
--- @param sourceset string: source set
--- @param buildpath string: destination path
--- @return bool
--- @return an error object on failure
-function scm.prepare_source(info, sourcename, sourceset, buildpath)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].prepare_source then
- e:append("prepare_source not implemented for source type: %s",
- src.type)
- return false, e
- end
- rc, re = e2scm[src.type].prepare_source(info, sourcename, sourceset,
- buildpath)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- fetch a source
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.fetch_source(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].fetch_source then
- e:append("fetch_source not implemented for source type: %s",
- src.type)
- return false, e
- end
- rc, re = e2scm[src.type].fetch_source(info, sourcename)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- update a source
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.update(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].update then
- e:append("update not implemented for source type: %s",
- src.type)
- return false, e
- end
- rc, re = e2scm[src.type].update(info, sourcename)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- sanity check a working copy
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.check_workingcopy(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].check_workingcopy then
- e:append(
- "check_workingcopy not implemented for source type: %s",
- src.type)
- return false, e
- end
- rc, re = e2scm[src.type].check_workingcopy(info, sourcename)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- check if a working copy is available
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.working_copy_available(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].working_copy_available then
- e:append(
- "working_copy_available not implemented for source "..
- "type: %s", src.type)
- return false, e
- end
- rc, re = e2scm[src.type].working_copy_available(info, sourcename)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- create a table of lines for display
--- @param info
--- @param sourcename
--- @return a table
--- @return an error object on failure
-function scm.display(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].display then
- e:append(
- "display not implemented for source "..
- "type: %s", src.type)
- return false, e
- end
- rc, re = e2scm[src.type].display(info, sourcename)
- if not rc then
- return nil, re
- end
- return rc, nil
-end
-
---- check if this scm type supports a working copy
--- @param info
--- @param sourcename
--- @return a table
--- @return an error object on failure
-function scm.has_working_copy(info, sourcename)
- local src = info.sources[sourcename]
- local rc, re, e
- e = new_error("calling scm operation failed")
- if not e2scm[src.type] then
- return false, e:append("no such source type: %s", src.type)
- end
- if not e2scm[src.type].has_working_copy then
- e:append(
- "has_working_copy not implemented for source "..
- "type: %s", src.type)
- return false, e
- end
- rc, re = e2scm[src.type].has_working_copy(info, sourcename)
- if not rc then
- return false, re
- end
- return true, nil
-end
-
---- register a new scm interface
--- @param name string: interface name
--- @param func function: interface function
--- @return bool
--- @return an error object on failure
-function scm.register_interface(name, func)
- local e = new_error("registering scm interface failed")
- if scm[name] then
- return false, e:append(
- "interface with that name exists: %s", name)
- end
- scm[name] = func
- return true, nil
-end
-
---- register a new scm function (accessible through a scm interface)
--- @param type string: scm type
--- @param name string: interface name
--- @param func function: interface function
--- @return bool
--- @return an error object on failure
-function scm.register_function(type, name, func)
- local e = new_error("registering scm function failed")
- if not e2scm[type] then
- return false, e:append("no scm type by that name: %s", type)
- end
- if not scm[name] then
- return false, e:append("no scm interface by that name: %s", name)
- end
- if e2scm[type][name] then
- return false, e:append("scm function exists: %s.%s", type, name)
- end
- scms[type][name] = func
- return true, nil
-end
-- High-level tools used by the build process and basic build operations.
module("e2tool", package.seeall)
+require("scm")
+require("files")
+require("git")
+require("cvs")
+require("svn")
-- Information gathering and inquiry
--
for _,s in ipairs(r.sources) do
local src = info.sources[s]
local source_set = r.build_mode.source_set()
- local sourceid, re =
+ local rc, re, sourceid =
scm.sourceid(info, s, source_set)
- if not sourceid then
+ if not rc then
return nil, e:cat(re)
end
hash.hash_line(hc, s) -- source name
e2lib.warnf("WDEFAULT", " type attribute defaults to `files'")
src.type = "files"
end
- if not e2scm[src.type] then
- e:append("unknown scm type: %s", src.type)
- return false, e
- end
rc, re = scm.validate_source(info, sourcename)
if not rc then
return false, re
-- fetch
for _, s in pairs(info.sources) do
local has_wc = scm.has_working_copy(info, s.name)
- local wc_avail = e2scm[s.type].working_copy_available(info, s.name)
+ local wc_avail = scm.working_copy_available(info, s.name)
if opts.fetch and sel[s.name] then
if wc_avail then
e2lib.log(1, "working copy for " .. s.name .. " is already available")
-- update
for _, s in pairs(info.sources) do
local has_wc = scm.has_working_copy(info, s.name)
- local wc_avail = e2scm[s.type].working_copy_available(info, s.name)
+ local wc_avail = scm.working_copy_available(info, s.name)
if opts.update and has_wc and sel[s.name] then
if not wc_avail then
e2lib.log(1, string.format("working copy for %s is not available",
--
-- See e2scm.lua for more information about these operations.
-
-local files = {}
+module("files", package.seeall)
+require("scm")
--- validate source configuration, log errors to the debug log
-- @param info the info table
-- @return bool
function files.validate_source(info, sourcename)
local rc1 = true -- the return value
- local rc, e = generic_validate_source(info, sourcename)
+ local rc, e = git.generic_validate_source(info, sourcename)
if not rc then
return false, e
end
end
local src = info.sources[sourcename]
if src.sourceid then
- return src.sourceid
+ return true, nil, src.sourceid
end
-- sourceset is ignored for files sources
local hc = hash.hash_start()
hash.hash_line(hc, l)
local licenceid, re = e2tool.licenceid(info, l)
if not licenceid then
- return nil, re
+ return false, re
end
hash.hash_line(hc, licenceid)
end
e2lib.log(4, string.format("hash data for source %s\n%s", src.name,
hc.data))
src.sourceid = hash.hash_finish(hc)
- return src.sourceid
+ return true, nil, src.sourceid
end
-- export the source to a result structure
return true, nil
end
-e2scm.register("files", files)
+function files.update(info, sourcename)
+ return true, nil
+end
+
+scm.register("files", files)
--
-- See e2scm.lua for more information about these operations.
-local git = {}
+module("git", package.seeall)
+require("scm")
--- git branch wrapper
-- get the current branch
src.commitid = {}
end
if src.sourceid[sourceset] then
- return src.sourceid[sourceset]
+ return true, nil, src.sourceid[sourceset]
end
src.commitid[sourceset], e = git.get_revision_id(info, sourcename,
sourceset, e2option.opts["check-remote"])
if not src.commitid[sourceset] then
- return nil, e
+ return false, e
end
local hc = hash.hash_start()
hash.hash_line(hc, src.name)
hash.hash_line(hc, l)
local licenceid, re = e2tool.licenceid(info, l)
if not licenceid then
- return nil, re
+ return false, re
end
hash.hash_line(hc, licenceid)
end
e2lib.log(4, string.format("hash data for source %s\n%s", src.name,
hc.data))
src.sourceid[sourceset] = hash.hash_finish(hc)
- return src.sourceid[sourceset]
+ return true, nil, src.sourceid[sourceset]
end
function git.toresult(info, sourcename, sourceset, directory)
return true, nil
end
-e2scm.register("git", git)
+scm.register("git", git)
--- /dev/null
+--[[
+ 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
+
+ For more information have a look at http://www.e2factory.org
+
+ e2factory is a registered trademark by emlix GmbH.
+
+ This file is part of e2factory, the emlix embedded build system.
+
+ e2factory 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+]]
+
+scm = module("scm", package.seeall)
+
+-- scm modules
+local scms = {}
+
+-- scm interfaces
+local intf = {}
+
+--- register a scm module
+-- @param scmname string: scm name
+-- @param mod the module
+-- @return bool
+-- @return an error object on failure
+function register(scmname, mod)
+ local e = new_error("error registering scm")
+ if scms[scmname] then
+ return false, e:append("scm with that name exists")
+ end
+ scms[scmname] = {}
+ for name,func in pairs(intf) do
+ rc, re = register_function(scmname, name, mod[name])
+ if not rc then
+ return false, e:cat(re)
+ end
+ end
+ return true, nil
+end
+
+--- register a new scm interface
+-- @param name string: interface name
+-- @return bool
+-- @return an error object on failure
+function register_interface(name)
+ local e = new_error("registering scm interface failed")
+ if intf[name] then
+ return false, e:append(
+ "interface with that name exists: %s", name)
+ end
+
+ -- closure: name
+ local function func(info, sourcename, ...)
+ local src = info.sources[sourcename]
+ local rc, re, e
+ e = new_error("calling scm operation failed")
+ if not scms[src.type] then
+ return false, e:append("no such source type: %s", src.type)
+ end
+ local f = scms[src.type][name]
+ if not f then
+ e:append("%s is not implemented for source type: %s", src.type)
+ return false, e
+ end
+ return f(info, sourcename, ...)
+ end
+
+ intf[name] = func
+
+ -- we have lots of calls like scm.<function>(...). Register the interface
+ -- function in the scm module to support those calls.
+ scm[name] = func
+ return true, nil
+end
+
+--- register a new scm function (accessible through a scm interface)
+-- @param type string: scm type
+-- @param name string: interface name
+-- @param func function: interface function
+-- @return bool
+-- @return an error object on failure
+function register_function(type, name, func)
+ local e = new_error("registering scm function failed")
+ if not scms[type] then
+ return false, e:append("no scm type by that name: %s", type)
+ end
+ if not intf[name] then
+ return false, e:append("no scm interface by that name: %s", name)
+ end
+ if scms[type][name] then
+ return false, e:append("scm function exists: %s.%s", type, name)
+ end
+ scms[type][name] = func
+ return true, nil
+end
+
+register_interface("sourceid")
+register_interface("validate_source")
+register_interface("toresult")
+register_interface("prepare_source")
+register_interface("fetch_source")
+register_interface("update")
+register_interface("check_workingcopy")
+register_interface("working_copy_available")
+register_interface("display")
+register_interface("has_working_copy")
]]
-- svn.lua - Subversion-specific SCM operations -*- Lua -*-
---
--- See e2scm.lua for more information about these operations.
---
--- The code assumes the directory layout in a svn repository looks like this:
---
--- <source>/<branch>/<dir>
--- <source>/<tag>/<dir>
--- helper functions
+module("svn", package.seeall)
+require("scm")
--- translate url into subversion url
-- @param u table: url table
end
src.sourceid["working-copy"] = "working-copy"
if src.sourceid[source_set] then
- return src.sourceid[source_set]
+ return true, nil, src.sourceid[source_set]
end
local hc = hash.hash_start()
hash.hash_line(hc, src.name)
e2lib.log(4, string.format("hash data for source %s\n%s", src.name,
hc.data))
src.sourceid[source_set] = hash.hash_finish(hc)
- return src.sourceid[source_set]
+ return true, nil, src.sourceid[source_set]
end
function svn.toresult(info, sourcename, sourceset, directory) --OK
-- <directory>/licences
local rc, re
local e = new_error("converting result")
- rc, re = check(info, sourcename, true)
+ rc, re = git.check(info, sourcename, true)
if not rc then
return false, e:cat(re)
end
-- @param sourcename the source name
-- @return bool
function svn.validate_source(info, sourcename) --OK
- local rc, re = generic_validate_source(info, sourcename)
+ local rc, re = git.generic_validate_source(info, sourcename)
if not rc then
-- error in generic configuration. Don't try to go on.
return false, re
src.sourceid = {}
end
local e = new_error("in source %s:", sourcename)
- rc, re = source_apply_default_working(info, sourcename)
+ rc, re = git.source_apply_default_working(info, sourcename)
if not rc then
return false, e:cat(re)
end
return true, nil
end
-e2scm.register("svn", svn)
+scm.register("svn", svn)