From 3d9e60c7f3625fb6d081f4e58286d926b57579f9 Mon Sep 17 00:00:00 2001
From: David Bauer <mail@david-bauer.net>
Date: Sat, 9 Dec 2023 21:59:19 +0100
Subject: [PATCH] build: allow modification of device build-properties

Signed-off-by: David Bauer <mail@david-bauer.net>
---
 scripts/image_customization_lib.lua | 67 ++++++++++++++++++++++-----
 scripts/target_config_lib.lua       | 25 +++++------
 scripts/target_lib.lua              | 70 ++++++++++++++++++++++-------
 3 files changed, 120 insertions(+), 42 deletions(-)

diff --git a/scripts/image_customization_lib.lua b/scripts/image_customization_lib.lua
index 6808383d8..26d99db2c 100644
--- a/scripts/image_customization_lib.lua
+++ b/scripts/image_customization_lib.lua
@@ -8,10 +8,23 @@ local function collect_keys(t)
 	return ret
 end
 
-local function evaluate_device(files, env, dev)
+local function file_exists(file)
+	local f = io.open(file)
+	if not f then
+		return false
+	end
+	f:close()
+	return true
+end
+
+local function get_customization_file_name(env)
+	return env.GLUON_SITEDIR .. '/image-customization'
+end
+
+local function evaluate_device(env, dev)
 	local selections = {}
 	local funcs = {}
-	local device_disabled = false
+	local device_overrides = {}
 
 	local function add_elements(element_type, element_list)
 		for _, element in ipairs(element_list) do
@@ -23,6 +36,10 @@ local function evaluate_device(files, env, dev)
 		end
 	end
 
+	local function add_override(ovr_key, ovr_value)
+		device_overrides[ovr_key] = ovr_value
+	end
+
 	function funcs.features(features)
 		add_elements('feature', features)
 	end
@@ -31,6 +48,21 @@ local function evaluate_device(files, env, dev)
 		add_elements('package', packages)
 	end
 
+	function funcs.broken(broken)
+		assert(
+			type(broken) == 'boolean',
+			'Incorrect use of broken(): has to be a boolean value')
+		add_override('broken', broken)
+	end
+
+	function funcs.disable()
+		add_override('disabled', true)
+	end
+
+	function funcs.disable_factory()
+		add_override('disable_factory', true)
+	end
+
 	function funcs.device(device_names)
 		assert(
 			type(device_names) == 'table',
@@ -66,24 +98,35 @@ local function evaluate_device(files, env, dev)
 	end
 
 	-- Evaluate the feature definition files
-	for _, file in ipairs(files) do
-		local f, err = loadfile(file)
-		if not f then
-			error('Failed to parse feature definition: ' .. err)
-		end
-		setfenv(f, funcs)
-		f()
+	local f, err = loadfile(get_customization_file_name(env))
+	if not f then
+		error('Failed to parse feature definition: ' .. err)
 	end
+	setfenv(f, funcs)
+	f()
 
 	return {
 		selections = selections,
-		device_disabled = device_disabled,
+		device_overrides = device_overrides,
 	}
 end
 
-function M.get_selection(selection_type, files, env, dev)
-	local eval_result = evaluate_device(files, env, dev)
+function M.get_selection(selection_type, env, dev)
+	if not file_exists(get_customization_file_name(env)) then
+		return {}
+	end
+
+	local eval_result = evaluate_device(env, dev)
 	return collect_keys(eval_result.selections[selection_type] or {})
 end
 
+function M.device_overrides(env, dev)
+	if not file_exists(get_customization_file_name(env)) then
+		return {}
+	end
+
+	local eval_result = evaluate_device(env, dev)
+	return eval_result.device_overrides
+end
+
 return M
diff --git a/scripts/target_config_lib.lua b/scripts/target_config_lib.lua
index 356c43731..becfd7a89 100644
--- a/scripts/target_config_lib.lua
+++ b/scripts/target_config_lib.lua
@@ -87,24 +87,19 @@ local function feature_packages(features)
 end
 
 local function site_specific_packages(dev_info)
-	local image_custoization = env.GLUON_SITEDIR .. '/image-customization'
+	local site_packages
+	local feature_inherited_pkgs
+	local site_features
 
-	local site_packages = {}
-	local feature_inherited_pkgs = {}
+	-- First read enabled features from site
+	site_features = image_customization_lib.get_selection('feature', env, dev_info)
+	site_features = compact_list(site_features, false)
 
-	if file_exists(image_custoization) then
-		local site_features
+	-- Create List from packages inherited from features
+	feature_inherited_pkgs = feature_packages(site_features)
 
-		-- First read enabled features from site
-		site_features = image_customization_lib.get_selection('feature', {image_custoization}, env, dev_info)
-		site_features = compact_list(site_features, false)
-
-		-- Create List from packages inherited from features
-		feature_inherited_pkgs = feature_packages(site_features)
-
-		-- Read list of packages from site
-		site_packages = image_customization_lib.get_selection('package', {image_custoization}, env, dev_info)
-	end
+	-- Read list of packages from site
+	site_packages = image_customization_lib.get_selection('package',  env, dev_info)
 
 	-- Concat feature-packages with site-packages
 	local pkgs = concat_list(feature_inherited_pkgs, site_packages)
diff --git a/scripts/target_lib.lua b/scripts/target_lib.lua
index b8dd933e4..0579d620d 100644
--- a/scripts/target_lib.lua
+++ b/scripts/target_lib.lua
@@ -1,3 +1,5 @@
+local image_customization_lib = dofile('scripts/image_customization_lib.lua')
+
 -- Functions for use in targets/*
 local F = {}
 
@@ -55,11 +57,37 @@ function F.istrue(v)
 	return (tonumber(v) or 0) > 0
 end
 
-local function want_device(dev, options)
-	if options.broken and not F.istrue(env.BROKEN) then
+local function get_device_overrides(device_info)
+	return image_customization_lib.device_overrides(env, device_info)
+end
+
+local function device_broken(device_info, overrides)
+	if F.istrue(env.BROKEN) then
 		return false
 	end
-	if options.deprecated and env.GLUON_DEPRECATED == '0' then
+
+	if overrides['broken'] ~= nil then
+		return overrides['broken'] == true
+	elseif device_info.options.broken then
+		return true
+	end
+
+	return false
+end
+
+local function want_device(device_info)
+	local overrides = get_device_overrides(device_info)
+
+	-- Check if device is disabled via image-customization in site
+	if overrides['disabled'] then
+		return false
+	end
+
+	if device_broken(device_info, overrides) then
+		return false
+	end
+
+	if device_info.options.deprecated and env.GLUON_DEPRECATED == '0' then
 		return false
 	end
 
@@ -67,13 +95,10 @@ local function want_device(dev, options)
 		return true
 	end
 
-	unknown_devices[dev] = nil
-	return gluon_devices[dev]
+	unknown_devices[device_info.image] = nil
+	return gluon_devices[device_info.image]
 end
 
-local full_deprecated = env.GLUON_DEPRECATED == 'full'
-
-
 local function merge(a, b)
 	local ret = {}
 	for k, v in pairs(a) do
@@ -210,18 +235,33 @@ local function as_table(v)
 	end
 end
 
-function F.device(image, name, options)
-	options = merge(default_options, options)
+local function disable_factory_image(device_info)
+	if device_info.options.deprecated and env.GLUON_DEPRECATED ~= 'full' then
+		return true
+	end
 
-	if not want_device(image, options) then
-		return
+	local overrides = get_device_overrides(device_info)
+	if overrides["disable_factory"] then
+		return true
 	end
 
-	table.insert(M.devices, {
+	return false
+end
+
+function F.device(image, name, options)
+	options = merge(default_options, options)
+
+	local device_info = {
 		image = image,
 		name = name,
 		options = options,
-	})
+	}
+
+	if not want_device(device_info) then
+		return
+	end
+
+	table.insert(M.devices, device_info)
 
 	if options.sysupgrade then
 		add_image {
@@ -236,7 +276,7 @@ function F.device(image, name, options)
 		}
 	end
 
-	if options.deprecated and not full_deprecated then
+	if disable_factory_image(device_info) then
 		return
 	end
 
-- 
GitLab