Skip to content
This repository was archived by the owner on Aug 7, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/cmds/bundle_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,12 @@ static enum swupd_code show_included_bundles(char *bundle_name, int version)
goto out;
}

if (!mom_search_bundle(mom, bundle_name)) {
ret_code = SWUPD_INVALID_BUNDLE;
warn("Bundle \"%s\" is invalid, skipping it...\n", bundle_name);
goto out;
}

// add_subscriptions takes a list, so construct one with only bundle_name
bundles = list_prepend_data(bundles, bundle_name);
ret = add_subscriptions(bundles, &subs, mom, true, 0);
Expand Down Expand Up @@ -554,6 +560,7 @@ enum swupd_code bundle_list_main(int argc, char **argv)
ret = list_bundles();
if (ret == SWUPD_OK && cmdline_option_orphans) {
info("\nUse \"swupd bundle-add BUNDLE\" to no longer list BUNDLE and its dependencies as orphaned\n");
info("\nUse \"swupd bundle-remove --orphans\" to delete all orphaned bundles\n");
}

swupd_deinit();
Expand Down
56 changes: 40 additions & 16 deletions src/cmds/update.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ int add_included_manifests(struct manifest *mom, struct list **subs)
* hit the Manifest delta path. */
ret = add_subscriptions(subbed, subs, mom, true, 0);
list_free_list(subbed);
if (ret & (add_sub_ERR | add_sub_BADNAME)) {
if (ret & add_sub_ERR) {
return ret;
}

Expand Down Expand Up @@ -213,16 +213,17 @@ static bool is_installed_and_verified(struct file *file)
/* Find files which need updated based on differences in last_change.
Should let further do_not_update policy be handled in the caller, but for
now some hacky exclusions are done here. */
static struct list *create_update_list(struct manifest *server)
static struct list *create_update_list(struct manifest *current, struct manifest *server)
{
struct list *output = NULL;
struct list *list;
struct file *file1, *file2;
struct list *list1, *list2;

list = list_head(server->files);
while (list) {
list2 = list_head(server->files);
while (list2) {
struct file *file;
file = list->data;
list = list->next;
file = list2->data;
list2 = list2->next;

/* Look for potential short circuit, if something has the same
* flags and the same hash, then conclude they are the same. */
Expand Down Expand Up @@ -255,6 +256,35 @@ static struct list *create_update_list(struct manifest *server)
}
}

list1 = list_head(current->files);
list2 = list_head(server->files);

while (list1 && list2) { /* m1/file1 matches m2/file2 */
int ret;
file1 = list1->data;
file2 = list2->data;

ret = str_cmp(file1->filename, file2->filename);
if (ret == 0) {
list1 = list1->next;
list2 = list2->next;
} else if (ret < 0) { /* m1/file1 is before m2/file2 */
// modify the current manifest in place
file1->is_deleted = true;
output = list_prepend_data(output, file1);
list1 = list1->next;
} else { /* else ret > 0 m1/file1 is after m2/file2 */
list2 = list2->next;
}
}

while (list1) {
file1 = list1->data;
file1->is_deleted = true;
output = list_prepend_data(output, file1);
list1 = list1->next;
}

return output;
}

Expand Down Expand Up @@ -366,14 +396,8 @@ enum swupd_code execute_update_extra(extra_proc_fn_t post_update_fn, extra_proc_
timelist_timer_start(globals.global_times, "Add included bundle manifests");
ret = add_included_manifests(server_manifest, &latest_subs);
if (ret) {
if (ret & add_sub_BADNAME) {
/* this means a bundle(s) was removed in a future version */
warn("One or more installed bundles are no longer available at version %d\n",
server_version);
} else {
ret = SWUPD_RECURSE_MANIFEST;
goto clean_exit;
}
ret = SWUPD_RECURSE_MANIFEST;
goto clean_exit;
}
timelist_timer_stop(globals.global_times); // closing: Add included bundle manifests

Expand Down Expand Up @@ -415,7 +439,7 @@ enum swupd_code execute_update_extra(extra_proc_fn_t post_update_fn, extra_proc_
/* some more housekeeping */
/* TODO: consider trying to do less sorting of manifests */
timelist_timer_start(globals.global_times, "Create update list");
updates = create_update_list(server_manifest);
updates = create_update_list(current_manifest, server_manifest);

print_statistics(current_version, server_version);
timelist_timer_stop(globals.global_times); // closing: Create update list
Expand Down
23 changes: 11 additions & 12 deletions src/cmds/verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,16 @@ enum swupd_code execute_verify_extra(extra_proc_fn_t post_verify_fn)
/* get the list of subscribed (installed) bundles */
read_subscriptions(&all_subs);
selected_subs = all_subs;
if (!cmdline_option_force) {
char *bundle_name = NULL;
for (iter = list_head(all_subs); iter; iter = iter->next) {
bundle_name = ((struct sub *)(iter->data))->component;
if (!mom_search_bundle(official_manifest, bundle_name)) {
invalid_bundle = true;
warn("Bundle \"%s\" is invalid, skipping it...\n", bundle_name);
}
}
}
if (cmdline_option_bundles) {
info("\n");
for (iter = list_head(cmdline_option_bundles); iter; iter = iter->next) {
Expand Down Expand Up @@ -1084,18 +1094,7 @@ enum swupd_code execute_verify_extra(extra_proc_fn_t post_verify_fn)
* continue only if --force was used since the bundles could be removed */
if (ret || invalid_bundle) {
if ((ret & add_sub_BADNAME) || invalid_bundle) {
if (cmdline_option_force) {
if (cmdline_option_picky && cmdline_option_fix) {
warn("\nOne or more installed bundles that are not "
"available at version %d will be removed\n",
version);
} else if (cmdline_option_picky && !cmdline_option_fix) {
warn("\nOne or more installed bundles are not "
"available at version %d\n",
version);
}
ret = SWUPD_OK;
} else {
if (!cmdline_option_force) {
if (cmdline_option_install || cmdline_option_bundles) {
error("\nOne or more of the provided bundles are not available at version %d\n", version);
info("Please make sure the name of the provided bundles are correct, or use --force to override\n")
Expand Down
28 changes: 18 additions & 10 deletions src/swupd_lib/manifest.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,19 +469,20 @@ void link_manifests(struct manifest *m1, struct manifest *m2)
continue;
}
if (ret < 0) { /* m1/file1 is before m2/file2 */
/* File is absent in m2, indicating that a format bump
* happened, removing deleted file entries from the
* previous format(s). Do not account the deleted file
* in this case, since an update will not delete the
* file.
*/
account_deleted_file();
list1 = list1->next;
continue;
} /* else ret > 0 m1/file1 is after m2/file2 */
list2 = list2->next;
account_new_file();
}

// Capture deleted files if they are at the tail end of the file list
while (list1) {
list1 = list1->next;
account_deleted_file();
}

// Capture new files if they are at the tail end of the file list
while (list2) {
list2 = list2->next;
Expand Down Expand Up @@ -534,9 +535,10 @@ void link_submanifests(struct manifest *m1, struct manifest *m2, struct list *su
}
if (ret < 0) { /* m1/file1 is before m2/file2 */
/* A bundle manifest going missing from the MoM in the
* latest version is a breaking change, only possible
* during a format bump, so don't account for this
* possibility in the stats. */
* latest version is no longer a breaking change. */
if (!server && subbed1) {
account_deleted_bundle();
}
list1 = list1->next;
continue;
} /* else ret > 0 m1/file1 is after m2/file2 */
Expand All @@ -546,8 +548,14 @@ void link_submanifests(struct manifest *m1, struct manifest *m2, struct list *su
}
}

// Capture deleted bundles if they are at the tail end of the list
while (!server && list1) {
list1 = list1->next;
account_deleted_bundle();
}

// Capture new bundles if they are at the tail end of the list
while (list2) {
while (server && list2) {
file2 = list2->data;
list2 = list2->next;
bool subbed2 = component_subscribed(subs2, file2->filename);
Expand Down
3 changes: 1 addition & 2 deletions src/swupd_lib/subscriptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,7 @@ static int recurse_subscriptions(struct list *bundles, struct list **subs, struc

file = mom_search_bundle(mom, bundle);
if (!file) {
warn("Bundle \"%s\" is invalid, skipping it...\n", bundle);
ret |= add_sub_BADNAME; /* Use this to get non-zero exit code */
// No longer add_sub_BADNAME with bundle deletes allowed
continue;
}

Expand Down
52 changes: 52 additions & 0 deletions test/functional/bundlelist/list-orphans.bats
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ setup_file() {
create_bundle -L -n test-bundle6 -f /file6 "$TEST_NAME"
add_dependency_to_manifest "$WEB_DIR"/10/Manifest.test-bundle3 test-bundle4

create_version -r "$TEST_NAME" 20 10
remove_from_manifest "$WEB_DIR"/20/Manifest.MoM test-bundle3

}

teardown_file() {
Expand All @@ -38,6 +41,7 @@ teardown_file() {
- test-bundle6
Total: 2
Use "swupd bundle-add BUNDLE" to no longer list BUNDLE and its dependencies as orphaned
Use "swupd bundle-remove --orphans" to delete all orphaned bundles
EOM
)
assert_is_output "$expected_output"
Expand All @@ -58,6 +62,54 @@ teardown_file() {
- test-bundle6 (installed)
Total: 2
Use "swupd bundle-add BUNDLE" to no longer list BUNDLE and its dependencies as orphaned
Use "swupd bundle-remove --orphans" to delete all orphaned bundles
EOM
)
assert_is_output "$expected_output"

}

@test "LST030: Update deleting a bundle shows new orphans" {

run sudo sh -c "$SWUPD update $SWUPD_OPTS"
assert_status_is 0
expected_output=$(cat <<-EOM
Update started
Preparing to update from 10 to 20
Downloading packs for:
- os-core
Finishing packs extraction...
Statistics for going from version 10 to version 20:
changed bundles : 1
new bundles : 0
deleted bundles : 1
changed files : 0
new files : 7
deleted files : 2
Validate downloaded files
No extra files need to be downloaded
Installing files...
Update was applied
Calling post-update helper scripts
Update successful - System updated from version 10 to version 20
EOM
)
assert_is_output "$expected_output"
# bundle should not exist
assert_file_not_exists "$TARGET_DIR"/file_3
assert_file_not_exists "$TARGET_DIR"/usr/share/clear/bundles/test-bundle3

run sudo sh -c "$SWUPD bundle-list $SWUPD_OPTS --orphans"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Loading required manifests...
Orphan bundles:
- test-bundle4
- test-bundle5
- test-bundle6
Total: 3
Use "swupd bundle-add BUNDLE" to no longer list BUNDLE and its dependencies as orphaned
Use "swupd bundle-remove --orphans" to delete all orphaned bundles
EOM
)
assert_is_output "$expected_output"
Expand Down
52 changes: 52 additions & 0 deletions test/functional/bundleremove/remove-orphans.bats
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ test_setup() {
create_bundle -L -n test-bundle3 -f /file3 "$TEST_NAME"
create_bundle -L -n test-bundle4 -f /file4 "$TEST_NAME"
create_bundle -L -n test-bundle5 -f /file5 "$TEST_NAME"
sudo touch "$state_path"/bundles/os-core
add_dependency_to_manifest "$WEB_DIR"/10/Manifest.test-bundle1 test-bundle2
add_dependency_to_manifest "$WEB_DIR"/10/Manifest.test-bundle4 test-bundle5

create_version -r "$TEST_NAME" 20 10
remove_from_manifest "$WEB_DIR"/20/Manifest.MoM test-bundle1

}

@test "REM030: Remove orphan bundles" {
Expand Down Expand Up @@ -56,3 +60,51 @@ test_setup() {
assert_in_output "$expected_output"

}

@test "REM033: Update deleting bundle adds new orphans that are removed" {

run sudo sh -c "$SWUPD update $SWUPD_OPTS"
assert_status_is 0
expected_output=$(cat <<-EOM
Update started
Preparing to update from 10 to 20
Downloading packs for:
- os-core
Finishing packs extraction...
Statistics for going from version 10 to version 20:
changed bundles : 1
new bundles : 0
deleted bundles : 1
changed files : 0
new files : 7
deleted files : 2
Validate downloaded files
No extra files need to be downloaded
Installing files...
Update was applied
Calling post-update helper scripts
Update successful - System updated from version 10 to version 20
EOM
)
assert_is_output "$expected_output"
# bundle should not exist
assert_file_not_exists "$TARGET_DIR"/file_1
assert_file_not_exists "$TARGET_DIR"/usr/share/clear/bundles/test-bundle1

run sudo sh -c "$SWUPD bundle-remove $SWUPD_OPTS --orphans"

assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
The following bundles are being removed:
- test-bundle5
- test-bundle4
- test-bundle3
- test-bundle2
Deleting bundle files...
Total deleted files: 8
Successfully removed 4 bundles
EOM
)
assert_is_output "$expected_output"

}
2 changes: 0 additions & 2 deletions test/functional/diagnose/diagnose-picky-downgrade.bats
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ test_setup() {
expected_output=$(cat <<-EOM
Diagnosing version 10
Downloading missing manifests...
Warning: Bundle "test-bundle2" is invalid, skipping it...
Warning: One or more installed bundles are not available at version 10
Checking for missing files
Checking for corrupt files
-> Hash mismatch for file: $ABS_TARGET_DIR/usr/lib/os-release
Expand Down
6 changes: 1 addition & 5 deletions test/functional/repair/repair-picky-downgrade.bats
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ test_setup() {
expected_output=$(cat <<-EOM
Diagnosing version 10
Warning: The --picky option is specified; ignoring version mismatch for repair
Downloading missing manifests...
Warning: Bundle "test-bundle2" is invalid, skipping it...
Downloading missing manifests...
Error: Unable to verify. One or more currently installed bundles are not available at version 10. Use --force to override
Repair did not fully succeed
EOM
Expand All @@ -47,8 +47,6 @@ test_setup() {
Diagnosing version 10
Warning: The --force option is specified; ignoring version mismatch for repair
Downloading missing manifests...
Warning: Bundle "test-bundle2" is invalid, skipping it...
Warning: One or more installed bundles that are not available at version 10 will be removed
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Expand Down Expand Up @@ -93,8 +91,6 @@ test_setup() {
Diagnosing version 10
Warning: The --force option is specified; ignoring version mismatch for repair
Downloading missing manifests...
Warning: Bundle "test-bundle2" is invalid, skipping it...
Warning: One or more installed bundles that are not available at version 10 will be removed
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Expand Down
Loading