From 9efe1776b65ca921fb4021df128ed5122f570524 Mon Sep 17 00:00:00 2001 From: Tobias Ulmer Date: Mon, 27 Feb 2017 20:59:36 +0100 Subject: [PATCH] licencesrc: add new source type providing licence info to build Signed-off-by: Tobias Ulmer --- Changelog | 1 + plugins/Makefile | 3 +- plugins/licencesrc.lua | 438 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 plugins/licencesrc.lua diff --git a/Changelog b/Changelog index 69a2570..600ca25 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,5 @@ NEXT: + * Add new source type "licence", providing licence info to build environment * Removed lazytag build mode, it was deprecated for a long time * Fix error in cvs source if cvsroot unset diff --git a/plugins/Makefile b/plugins/Makefile index b333248..1493351 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -21,7 +21,8 @@ include $(TOPLEVEL)/make.vars SUBDIRS = CLEAN_FILES = -LOCALPLUGINS = cvs.lua files.lua git.lua gitrepo.lua svn.lua collect_project.lua +LOCALPLUGINS = cvs.lua files.lua git.lua gitrepo.lua svn.lua \ + collect_project.lua licencesrc.lua .PHONY: all local install uninstall install install-local doc install-doc diff --git a/plugins/licencesrc.lua b/plugins/licencesrc.lua new file mode 100644 index 0000000..ec92606 --- /dev/null +++ b/plugins/licencesrc.lua @@ -0,0 +1,438 @@ +--- Licence provider plugin +-- @module plugins.licencesrc + +-- Copyright (C) 2017 emlix GmbH, see file AUTHORS +-- +-- This file is part of e2factory, the emlix embedded build system. +-- For more information see http://www.e2factory.org +-- +-- e2factory is a registered trademark of emlix GmbH. +-- +-- 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. + +local licencesrc = {} +local cache = require("cache") +local class = require("class") +local e2lib = require("e2lib") +local e2tool = require("e2tool") +local eio = require("eio") +local environment = require("environment") +local err = require("err") +local hash = require("hash") +local licence = require("licence") +local result = require("result") +local sl = require("sl") +local source = require("source") +local strict = require("strict") + +-------------------------------------------------------------------------------- + +local licence_source = class("licence_source", source.basic_source) + +function licence_source:initialize(rawsrc) + assert(type(rawsrc) == "table") + assert(type(rawsrc.name) == "string" and #rawsrc.name > 0) + assert(type(rawsrc.type) == "string" and rawsrc.type == "licence") + + local rc, re, e + + source.basic_source.initialize(self, rawsrc) + + self._results = {} + self._sources = {} + self._results_list = false + self._initialized = false + self._sourceid = false + + -- required but unused. + self:set_env(environment.new()) + self:set_licences(sl.sl:new()) + + rc, re = e2lib.vrfy_dict_exp_keys(rawsrc, "e2source config", { + "name", + "results", + "sources", + "type", + }) + if not rc then + error(re) + end + + if rawsrc.results == nil then + rawsrc.results = {} + end + + rc, re = e2lib.vrfy_listofstrings(rawsrc.results, "results", false, true) + if not rc then + error(re) + end + + for _,resultname in ipairs(rawsrc.results) do + table.insert(self._results, resultname) + end + + --- + + if rawsrc.sources == nil then + rawsrc.sources = {} + end + + rc, re = e2lib.vrfy_listofstrings(rawsrc.sources, "sources", false, true) + if not rc then + error(re) + end + + for _,sourcename in ipairs(rawsrc.sources) do + table.insert(self._sources, sourcename) + end +end + +function licence_source:_post_initialize() + if self._initialized then + return true + end + + local rc, re + + for _,resultname in ipairs(self._results) do + if not result.results[resultname] then + return false, err.new("result does not exist: %s", resultname) + end + end + + for _,sourcename in ipairs(self._sources) do + if not source.sources[sourcename] then + return false, err.new("source does not exist: %s", sourcename) + end + end + + self._results_list, re = e2tool.dlist_recursive(self._results) + if not self._results_list then + return false, re + end + + self._initialized = true + return true +end + +function licence_source:sourceid(sourceset) + assertIsStringN(sourceset) + + local rc, re, e + local hc, id + + e = err.new("calculating SourceID for %q failed", self._name) + + rc, re = self:_post_initialize() + if not rc then + return false, e:cat(re) + end + + if self._sourceid then + return self._sourceid + end + + hc = hash.hash_start() + hash.hash_append(hc, self._name) + hash.hash_append(hc, self._type) + + for _,resultname in ipairs(self._results_list) do + local res = result.results[resultname] + + hash.hash_append(hc, resultname) + + for sourcename in res:sources_list():iter() do + if sourcename ~= self._name then + local src = source.sources[sourcename] + + id, re = src:sourceid(sourceset) + if not id then + return false, e:cat(re) + end + + hash.hash_append(hc, id) + end + end + end + + for _,sourcename in ipairs(self._sources) do + if sourcename ~= self._name then + id, re = source.sources[sourcename]:sourceid(sourceset) + if not id then + return false, e:cat(re) + end + hash.hash_append(hc, id) + end + end + + self._sourceid = hash.hash_finish(hc) + + return self._sourceid +end + +function licence_source:prepare_source(sourceset, buildpath) + assertIsStringN(sourceset) + assertIsStringN(buildpath) + + local rc, re, e + local destdir, sdir, rdir, ldir, source_list, licence_list + + e = err.new("preparing source %q failed", self._name) + + rc, re = self:_post_initialize() + if not rc then + return false, e:cat(re) + end + + destdir = e2lib.join(buildpath, self._name) + + sdir = e2lib.join(destdir, "src") + rdir = e2lib.join(destdir, "res") + ldir = e2lib.join(destdir, "licences") + + rc, re = e2lib.mkdir_recursive(sdir) + if not rc then + return false, e:cat(re) + end + + rc, re = e2lib.mkdir_recursive(rdir) + if not rc then + return false, e:cat(re) + end + + rc, re = e2lib.mkdir_recursive(ldir) + if not rc then + return false, e:cat(re) + end + + source_list = sl.sl:new() + licence_list = sl.sl:new() + + for _,resultname in ipairs(self._results_list) do + local res = result.results[resultname] + local resdir = e2lib.join(rdir, res:get_name()) + local t = {} + + rc, re = e2lib.mkdir(resdir) + if not rc then + return false, e:cat(re) + end + + for sourcename in res:sources_list():iter() do + if sourcename ~= self._name then + table.insert(t, sourcename) + source_list:insert(sourcename) -- collect to process later + end + end + + t = table.concat(t, "\n").."\n" + + rc, re = eio.file_write(e2lib.join(resdir, "sources"), t) + if not rc then + return false, e:cat(re) + end + end + + for _,sourcename in ipairs(self._sources) do + if sourcename ~= self.name then + source_list:insert(sourcename) + end + end + + for sourcename in source_list:iter() do + local src = source.sources[sourcename] + local srcdir = e2lib.join(sdir, src:get_name()) + + rc, re = e2lib.mkdir(srcdir) + if not rc then + return false, e:cat(re) + end + + -- collect all licences for later processing + licence_list:insert_sl(src:get_licences()) + + -- write licences + local l = src:get_licences():concat("\n").."\n" + + rc, re = eio.file_write(e2lib.join(srcdir, "licences"), l) + if not rc then + return false, e:cat(re) + end + end + + for licencename in licence_list:iter() do + local lic = licence.licences[licencename] + + rc, re = e2lib.mkdir(e2lib.join(ldir, lic:get_name())) + if not rc then + return false, e:cat(re) + end + + for file in lic:file_iter() do + rc, re = file:checksum_verify() + if not rc then + return false, e:cat(re) + end + rc, re = cache.fetch_file(cache.cache(), file:server(), + file:location(), e2lib.join(ldir, lic:get_name())) + if not rc then + return false, e:cat(re) + end + end + end + + return true +end + +function licence_source:display(sourceset) + assertIsStringN(sourceset) + + local rc, re, e + local t = {} + + e = err.new("showing attributes of source %q failed", self._name) + + rc, re = self:_post_initialize() + if not rc then + return false, e:cat(re) + end + + + table.insert(t, string.format("%-10s = %s", "type", self:get_type())) + if #self._results > 0 then + table.insert(t, string.format("%-10s = %s", "results", + table.concat(self._results, " "))) + end + if #self._sources > 0 then + table.insert(t, string.format("%-10s = %s", "sources", + table.concat(self._sources, " "))) + end + + if self._sourceid then + table.insert(d, string.format("%-10s = %s", "sourceid", self._sourceid)) + end + + return t +end + +function licence_source:fetch_source() + local rc, re = self:_post_initialize() + if not rc then + return false, re + end + return true +end + +function licence_source:update_source() + local rc, re = self:_post_initialize() + if not rc then + return false, re + end + return true +end + +function licence_source:working_copy_available() + return false, err.new("source %q doesn't require a working copy", self._name) +end + +function licence_source:check_workingcopy() + local rc, re = self:_post_initialize() + if not rc then + return false, re + end + return true +end + +-------------------------------------------------------------------------------- + +local function licences_to_result(src, sourceset, directory) + assertIsTable(src) + assertIsStringN(sourceset) + assertIsStringN(directory) + + local rc, re, e + local out, tmpdir, adir, archive + + e = err.new("converting %q to result failed", src:get_name()) + + tmpdir, re = e2lib.mktempdir() + if not tmpdir then + return false, e:cat(re) + end + + rc, re = src:prepare_source(sourceset, tmpdir) + if not rc then + return false, e:cat(re) + end + + adir = e2lib.join(directory, "source") + rc, re = e2lib.mkdir_recursive(adir) + if not rc then + return false, e:cat(re) + end + + archive = string.format("%s.tar.gz", src:get_name()) + + rc, re = e2lib.tar({ "-C", tmpdir ,"-czf", + e2lib.join(adir, archive), src:get_name()}) + if not rc then + return false, e:cat(re) + end + + out = { + ".PHONY: place", + "", + "place:", + string.format("\ttar xzf \"source/%s\" -C \"$(BUILD)\"", archive), + } + + out = table.concat(out, "\n").."\n" + + rc, re = eio.file_write(e2lib.join(directory, "Makefile"), out) + if not rc then + return false, e:cat(re) + end + + e2lib.rmtempdir(tmpdir) + + return true +end + +-------------------------------------------------------------------------------- + +plugin_descriptor = { + description = "Licence Provider Plugin", + init = function (ctx) + local rc, re + + rc, re = source.register_source_class("licence", licence_source) + if not rc then + return false, re + end + + for typ, theclass in result.iterate_result_classes() do + if typ == "collect_project" then + theclass:add_source_to_result_fn("licence", licences_to_result) + break + end + end + + return true + end, + exit = function (ctx) return true end, + depends = { + "collect_project.lua" + } +} + +strict.lock(licencesrc) + +-- vim:sw=4:sts=4:et: -- 2.39.5