mirror of
https://github.com/systemd/systemd.git
synced 2025-01-03 05:18:09 +03:00
sysupdate: Add verb to inspect features
This commit is contained in:
parent
2ffc8b23f0
commit
0cd1a58921
@ -106,6 +106,16 @@
|
||||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>features</option> <optional><replaceable>FEATURE</replaceable></optional></term>
|
||||
|
||||
<listitem><para>If invoked without an argument, enumerates optional features and shows a summarizing
|
||||
table, including which features are enabled or disabled. If a feature argument is specified, shows
|
||||
details about the specific feature, including the transfers that are controlled by the feature.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>check-new</option></term>
|
||||
|
||||
|
@ -45,11 +45,16 @@ Transfer* transfer_free(Transfer *t) {
|
||||
|
||||
t->temporary_path = rm_rf_subvolume_and_free(t->temporary_path);
|
||||
|
||||
free(t->id);
|
||||
|
||||
free(t->min_version);
|
||||
strv_free(t->protected_versions);
|
||||
free(t->current_symlink);
|
||||
free(t->final_path);
|
||||
|
||||
strv_free(t->features);
|
||||
strv_free(t->requisite_features);
|
||||
|
||||
strv_free(t->changelog);
|
||||
strv_free(t->appstream);
|
||||
|
||||
@ -520,6 +525,7 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H
|
||||
};
|
||||
|
||||
_cleanup_free_ char *filename = NULL;
|
||||
char *e;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
@ -545,6 +551,10 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
e = ASSERT_PTR(endswith(filename, ".transfer") ?: endswith(filename, ".conf"));
|
||||
*e = 0; /* Remove the file extension */
|
||||
t->id = TAKE_PTR(filename);
|
||||
|
||||
t->enabled = transfer_decide_if_enabled(t, known_features);
|
||||
|
||||
if (!RESOURCE_IS_SOURCE(t->source.type))
|
||||
|
@ -15,11 +15,15 @@ typedef struct Transfer Transfer;
|
||||
#include "sysupdate.h"
|
||||
|
||||
struct Transfer {
|
||||
char *id;
|
||||
|
||||
char *min_version;
|
||||
char **protected_versions;
|
||||
char *current_symlink;
|
||||
bool verify;
|
||||
|
||||
char **features;
|
||||
char **requisite_features;
|
||||
bool enabled;
|
||||
|
||||
Resource source, target;
|
||||
|
@ -1201,6 +1201,140 @@ static int verb_list(int argc, char **argv, void *userdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static int verb_features(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
|
||||
_cleanup_(context_freep) Context* context = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
const char *feature_id;
|
||||
Feature *f;
|
||||
int r;
|
||||
|
||||
assert(argc <= 2);
|
||||
feature_id = argc >= 2 ? argv[1] : NULL;
|
||||
|
||||
r = process_image(/* ro= */ true, &mounted_dir, &loop_device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_make_offline(&context, loop_device ? loop_device->node : NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (feature_id) {
|
||||
_cleanup_strv_free_ char **transfers = NULL;
|
||||
|
||||
f = hashmap_get(context->features, feature_id);
|
||||
if (!f)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
|
||||
"Optional feature not found: %s",
|
||||
feature_id);
|
||||
|
||||
table = table_new_vertical();
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
FOREACH_ARRAY(tr, context->transfers, context->n_transfers) {
|
||||
Transfer *t = *tr;
|
||||
|
||||
if (!strv_contains(t->features, f->id) && !strv_contains(t->requisite_features, f->id))
|
||||
continue;
|
||||
|
||||
r = strv_extend(&transfers, t->id);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
FOREACH_ARRAY(tr, context->disabled_transfers, context->n_disabled_transfers) {
|
||||
Transfer *t = *tr;
|
||||
|
||||
if (!strv_contains(t->features, f->id) && !strv_contains(t->requisite_features, f->id))
|
||||
continue;
|
||||
|
||||
r = strv_extend(&transfers, t->id);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "Name",
|
||||
TABLE_STRING, f->id,
|
||||
TABLE_FIELD, "Enabled",
|
||||
TABLE_BOOLEAN, f->enabled);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (f->description) {
|
||||
r = table_add_many(table, TABLE_FIELD, "Description", TABLE_STRING, f->description);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
if (f->documentation) {
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "Documentation",
|
||||
TABLE_STRING, f->documentation,
|
||||
TABLE_SET_URL, f->documentation);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
if (f->appstream) {
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "AppStream",
|
||||
TABLE_STRING, f->appstream,
|
||||
TABLE_SET_URL, f->appstream);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
if (!strv_isempty(transfers)) {
|
||||
r = table_add_many(table, TABLE_FIELD, "Transfers", TABLE_STRV_WRAPPED, transfers);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
} else if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
|
||||
table = table_new("", "feature", "description", "documentation");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
HASHMAP_FOREACH(f, context->features) {
|
||||
r = table_add_many(table,
|
||||
TABLE_BOOLEAN_CHECKMARK, f->enabled,
|
||||
TABLE_SET_COLOR, ansi_highlight_green_red(f->enabled),
|
||||
TABLE_STRING, f->id,
|
||||
TABLE_STRING, f->description,
|
||||
TABLE_STRING, f->documentation,
|
||||
TABLE_SET_URL, f->documentation);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
} else {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
|
||||
_cleanup_strv_free_ char **features = NULL;
|
||||
|
||||
HASHMAP_FOREACH(f, context->features) {
|
||||
r = strv_extend(&features, f->id);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = sd_json_buildo(&json, SD_JSON_BUILD_PAIR_STRV("features", features));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create JSON: %m");
|
||||
|
||||
r = sd_json_variant_dump(json, arg_json_format_flags, stdout, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to print JSON: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_check_new(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
|
||||
@ -1517,6 +1651,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
||||
"\n%5$sUpdate OS images.%6$s\n"
|
||||
"\n%3$sCommands:%4$s\n"
|
||||
" list [VERSION] Show installed and available versions\n"
|
||||
" features [FEATURE] Show optional features\n"
|
||||
" check-new Check if there's a new version available\n"
|
||||
" update [VERSION] Install new version now\n"
|
||||
" vacuum Make room, by deleting old versions\n"
|
||||
@ -1729,8 +1864,9 @@ static int sysupdate_main(int argc, char *argv[]) {
|
||||
static const Verb verbs[] = {
|
||||
{ "list", VERB_ANY, 2, VERB_DEFAULT, verb_list },
|
||||
{ "components", VERB_ANY, 1, 0, verb_components },
|
||||
{ "features", VERB_ANY, 2, 0, verb_features },
|
||||
{ "check-new", VERB_ANY, 1, 0, verb_check_new },
|
||||
{ "update", VERB_ANY, 2, 0, verb_update },
|
||||
{ "update", VERB_ANY, 2, 0, verb_update },
|
||||
{ "vacuum", VERB_ANY, 1, 0, verb_vacuum },
|
||||
{ "reboot", 1, 1, 0, verb_pending_or_reboot },
|
||||
{ "pending", 1, 1, 0, verb_pending_or_reboot },
|
||||
|
@ -303,6 +303,8 @@ EOF
|
||||
verify_version_current "$blockdev" "$sector_size" v5 2
|
||||
|
||||
# Now let's try enabling an optional feature
|
||||
"$SYSUPDATE" features | grep "optional"
|
||||
"$SYSUPDATE" features optional | grep "99-optional"
|
||||
test ! -f "$WORKDIR/xbootldr/EFI/Linux/uki_v5.efi.extra.d/optional.efi"
|
||||
mkdir "$CONFIGDIR/optional.feature.d"
|
||||
echo -e "[Feature]\nEnabled=true" > "$CONFIGDIR/optional.feature.d/enable.conf"
|
||||
|
Loading…
Reference in New Issue
Block a user