@@ -462,8 +462,14 @@ def merge_overrides_into_sources(sources, overrides):
layers[k] = v
return layers
+def get_selected_sources(config):
+ source_choices = config["data"].get("source-choices")
+ if source_choices is not None:
+ return source_choices[config["selected-source-choice"]]["sources"]
+ return config["data"]["sources"]
+
def update_build(config, confdir, setupdir, layerdir, d, update_bb_conf="prompt", init_vscode=False, rebase_conflicts_strategy='abort'):
- layer_config = merge_overrides_into_sources(config["data"]["sources"], config["source-overrides"]["sources"])
+ layer_config = merge_overrides_into_sources(get_selected_sources(config), config["source-overrides"]["sources"])
sources_fixed_revisions = checkout_layers(layer_config, confdir, layerdir, d, rebase_conflicts_strategy=rebase_conflicts_strategy)
bitbake_config = config["bitbake-config"]
thisdir = os.path.dirname(config["path"]) if config["type"] == 'local' else None
@@ -594,6 +600,44 @@ def choose_fragments(possibilities, parameters, non_interactive, skip_selection)
choices[k] = options_enumerated[option_n][1]["name"]
return choices
+def choose_source_choice(source_choices, source_choice_arg, non_interactive):
+ if not source_choices:
+ raise Exception("Configuration template must define at least one source choice.")
+
+ source_choice_names = sorted(source_choices.keys())
+ not_expired_choices = [k for k in source_choice_names if not has_expired(source_choices[k].get("expires", None))]
+ if source_choice_arg is not None:
+ if source_choice_arg in source_choices:
+ return source_choice_arg
+ raise Exception("Source choice {} not found; replace with one of {}".format(source_choice_arg, source_choice_names))
+
+ if len(not_expired_choices) == 1:
+ only_choice = not_expired_choices[0]
+ logger.plain("\nSelecting the only available source choice {}".format(only_choice))
+ return only_choice
+
+ if not not_expired_choices:
+ raise Exception("No unexpired source choices available.")
+
+ if non_interactive:
+ raise Exception("Unable to choose from source choices in non-interactive mode: {}".format(not_expired_choices))
+
+ descs = []
+ for c in not_expired_choices:
+ d = source_choices[c]["description"]
+ expiry_date = source_choices[c].get("expires", None)
+ if expiry_date:
+ d += f" (supported until {expiry_date})"
+ descs.append(d)
+
+ logger.plain("")
+ print_configs("Available source choices",
+ not_expired_choices,
+ descs)
+ choice_n = int_input([i[0] for i in list(enumerate(not_expired_choices, 1))],
+ "\nPlease select one of the above source choices by its number: ") - 1
+ return not_expired_choices[choice_n]
+
def obtain_config(top_dir, registry, args, source_overrides, d):
if args.config:
config_id = args.config[0]
@@ -632,9 +676,30 @@ def obtain_config(top_dir, registry, args, source_overrides, d):
config_parameters = []
upstream_config = {'type':'registry','registry':registry,'name':config_id,'data':json.load(open(get_registry_config(registry_path,config_id)))}
+ selected_source_choice = None
+ has_sources = 'sources' in upstream_config['data']
+ has_source_choices = 'source-choices' in upstream_config['data']
+ if has_sources == has_source_choices:
+ raise Exception("Configuration template must define exactly one of 'sources' or 'source-choices'.")
+ if has_source_choices:
+ source_choices = upstream_config['data']['source-choices']
+ source_choice_arg = config_parameters[0] if config_parameters else None
+ selected_source_choice = choose_source_choice(source_choices, source_choice_arg, args.non_interactive)
+ if source_choice_arg is not None:
+ config_parameters = config_parameters[1:]
+ expiry_date = source_choices[selected_source_choice].get("expires", None)
+ if has_expired(expiry_date):
+ logger.warning("The selected source choice {} is no longer supported after {}. Please consider changing to a supported source choice.".format(selected_source_choice, expiry_date))
+ upstream_config['selected-source-choice'] = selected_source_choice
+
upstream_config['bitbake-config'] = choose_bitbake_config(upstream_config['data']['bitbake-setup']['configurations'], config_parameters, args.non_interactive)
upstream_config['bitbake-config']['oe-fragment-choices'] = choose_fragments(upstream_config['bitbake-config'].get('oe-fragments-one-of',{}), config_parameters[1:], args.non_interactive, args.skip_selection)
- upstream_config['non-interactive-cmdline-options'] = [config_id, upstream_config['bitbake-config']['name']] + sorted(upstream_config['bitbake-config']['oe-fragment-choices'].values())
+ upstream_config['non-interactive-cmdline-options'] = (
+ [config_id] +
+ ([selected_source_choice] if selected_source_choice is not None else []) +
+ [upstream_config['bitbake-config']['name']] +
+ sorted(upstream_config['bitbake-config']['oe-fragment-choices'].values())
+ )
upstream_config['source-overrides'] = source_overrides
upstream_config['skip-selection'] = args.skip_selection
return upstream_config
@@ -952,7 +1017,7 @@ def build_status(top_dir, settings, args, d, update=False):
bb.process.run(["git", "-C", confdir, "restore", "config-upstream.json"])
return
- layer_config = merge_overrides_into_sources(current_upstream_config["data"]["sources"], current_upstream_config["source-overrides"]["sources"])
+ layer_config = merge_overrides_into_sources(get_selected_sources(current_upstream_config), current_upstream_config["source-overrides"]["sources"])
if are_layers_changed(layer_config, layerdir, d):
if update:
update_build(current_upstream_config, confdir, setupdir, layerdir,
@@ -15,6 +15,35 @@
"sources": {
"$ref": "layers.schema.json#/properties/sources"
},
+ "source-choices": {
+ "type": "object",
+ "description": "Named choices of sources to select from",
+ "minProperties": 1,
+ "patternProperties": {
+ ".+": {
+ "type": "object",
+ "required": [
+ "description",
+ "sources"
+ ],
+ "properties": {
+ "description": {
+ "type": "string",
+ "description": "Human-readable description of the source choice"
+ },
+ "sources": {
+ "$ref": "layers.schema.json#/properties/sources"
+ },
+ "expires": {
+ "type": "string",
+ "description": "End of life date for this source choice, in ISO 8601 format (YYYY-MM-DD)"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
"expires": {
"type": "string",
"description": "End of life date for this configuration, in ISO 8601 format (YYYY-MM-DD)"
@@ -152,5 +181,17 @@
]
}
},
+ "oneOf": [
+ {
+ "required": [
+ "sources"
+ ]
+ },
+ {
+ "required": [
+ "source-choices"
+ ]
+ }
+ ],
"additionalProperties": false
}