Function to perform actions on 3rd-party bundles

This commit provides a function to perform general actions on every
3rd-party bundle on a list. If a repo is not specified, the bundles are
looked for in every existing repo. This function will be useful to reuse
code when adding other 3rd-party commands like bundle-remove or
bundle-info.
This commit is contained in:
Castulo Martinez
2019-12-11 16:11:35 -08:00
committed by Castulo J. Martinez
parent 2a2018744e
commit bb43d47fd4
3 changed files with 192 additions and 114 deletions
+20 -114
View File
@@ -93,16 +93,27 @@ static bool parse_options(int argc, char **argv)
return true;
}
static enum swupd_code add_bundle(char *bundle)
{
struct list *bundle_to_install = NULL;
enum swupd_code ret = SWUPD_OK;
/* execute_bundle_add expects a list */
bundle_to_install = list_append_data(bundle_to_install, bundle);
info("\nBundles added from a 3rd-party repository are forced to run with the --no-scripts flag for security reasons\n\n");
globals.no_scripts = true;
ret = execute_bundle_add(bundle_to_install);
list_free_list(bundle_to_install);
return ret;
}
enum swupd_code third_party_bundle_add_main(int argc, char **argv)
{
struct list *bundles = NULL;
struct list *iter1 = NULL;
struct list *iter2 = NULL;
struct list *repos = NULL;
char *state_dir;
char *path_prefix;
int repo_version;
int ret;
enum swupd_code ret_code = SWUPD_OK;
/*
@@ -132,9 +143,6 @@ enum swupd_code third_party_bundle_add_main(int argc, char **argv)
return ret_code;
}
/* load the existing 3rd-party repos from the repo.ini config file */
repos = third_party_get_repos();
/* move the bundles provided in the command line into a
* list so it is easier to handle them */
for (; *cmdline_bundles; ++cmdline_bundles) {
@@ -143,115 +151,13 @@ enum swupd_code third_party_bundle_add_main(int argc, char **argv)
}
bundles = list_head(bundles);
/* backup the original state_dir and path_prefix values */
state_dir = strdup_or_die(globals.state_dir);
path_prefix = strdup_or_die(globals.path_prefix);
/* try installing bundles one by one */
for (iter1 = bundles; iter1; iter1 = iter1->next) {
char *bundle = iter1->data;
struct repo *selected_repo = NULL;
int count = 0;
ret_code = third_party_run_operation(bundles, cmdline_repo, add_bundle);
/* if the repo to be used was specified, use it, otherwise
* search for the bundle in all the 3rd-party repos */
if (cmdline_repo) {
selected_repo = list_search(repos, cmdline_repo, repo_name_cmp);
} else {
info("Searching for bundle %s in the 3rd-party repositories...\n", bundle);
for (iter2 = repos; iter2; iter2 = iter2->next) {
struct repo *repo = iter2->data;
struct manifest *mom = NULL;
struct file *file = NULL;
/* set the appropriate content_dir and state_dir for the selected 3rd-party repo */
ret = third_party_set_repo(state_dir, path_prefix, repo);
if (ret) {
ret_code = ret;
goto clean_and_exit;
}
/* get repo's version */
repo_version = get_current_version(globals.path_prefix);
if (repo_version < 0) {
error("Unable to determine current version for repository %s\n\n", repo->name);
ret_code = SWUPD_CURRENT_VERSION_UNKNOWN;
goto clean_and_exit;
}
/* load the repo's MoM*/
mom = load_mom(repo_version, false, NULL);
if (!mom) {
error("Cannot load manifest MoM for 3rd-party repository %s version %i\n", repo->name, repo_version);
ret_code = SWUPD_COULDNT_LOAD_MOM;
goto clean_and_exit;
}
/* search for the bundle in the MoM */
file = mom_search_bundle(mom, bundle);
if (file) {
/* the bundle was found in this repo, keep a pointer to the repo */
info("Bundle %s found in 3rd-party repository %s\n", bundle, repo->name);
count++;
selected_repo = repo;
}
manifest_free(mom);
}
/* if the bundle exists in only one repo, we can continue */
if (count == 0) {
error("bundle %s was not found in any 3rd-party repository\n\n", bundle);
ret_code = SWUPD_INVALID_BUNDLE;
continue;
} else if (count > 1) {
error("bundle %s was found in more than one 3rd-party repository\n", bundle);
info("Please specify a repository using the --repo flag\n\n");
ret_code = SWUPD_INVALID_OPTION;
continue;
}
}
if (!selected_repo) {
error("3rd-party repository %s was not found\n\n", cmdline_repo);
ret_code = SWUPD_INVALID_REPOSITORY;
goto clean_and_exit;
}
/* set the appropriate content_dir and state_dir for the selected 3rd-party repo */
ret = third_party_set_repo(state_dir, path_prefix, selected_repo);
if (ret) {
ret_code = ret;
goto clean_and_exit;
}
/* execute_bundle_add expects a list so we can send a new list with only
* the one bundle we want to install in this iteration */
struct list *bundle_to_install = NULL;
bundle_to_install = list_append_data(bundle_to_install, bundle);
info("\nBundles added from a 3rd-party repository are forced to run with the --no-scripts flag for security reasons\n\n");
globals.no_scripts = true;
ret = execute_bundle_add(bundle_to_install);
if (ret != SWUPD_OK) {
ret_code = ret;
}
list_free_list(bundle_to_install);
info("\n");
}
clean_and_exit:
free_string(&state_dir);
free_string(&path_prefix);
list_free_list(bundles);
list_free_list_and_data(repos, repo_free_data);
swupd_deinit();
progress_finish_steps(ret_code);
return ret_code;
}
+157
View File
@@ -244,4 +244,161 @@ enum swupd_code third_party_set_repo(const char *state_dir, const char *path_pre
return SWUPD_OK;
}
static enum swupd_code third_party_find_bundle(const char *bundle, struct list *repos, struct repo **found_repo)
{
struct list *iter = NULL;
char *state_dir;
char *path_prefix;
char *content_url;
int count = 0;
int version;
enum swupd_code ret_code = SWUPD_OK;
/* backup the original state_dir and path_prefix values */
state_dir = strdup_or_die(globals.state_dir);
path_prefix = strdup_or_die(globals.path_prefix);
content_url = strdup_or_die(globals.content_url);
info("Searching for bundle %s in the 3rd-party repositories...\n", bundle);
for (iter = repos; iter; iter = iter->next) {
struct repo *repo = iter->data;
struct manifest *mom = NULL;
struct file *file = NULL;
/* set the appropriate content_dir and state_dir for the selected 3rd-party repo */
ret_code = third_party_set_repo(state_dir, path_prefix, repo);
if (ret_code != SWUPD_OK) {
return ret_code;
}
/* get repo's version */
version = get_current_version(globals.path_prefix);
if (version < 0) {
error("Unable to determine current version for repository %s\n\n", repo->name);
ret_code = SWUPD_CURRENT_VERSION_UNKNOWN;
goto clean_and_exit;
}
/* load the repo's MoM*/
mom = load_mom(version, false, NULL);
if (!mom) {
error("Cannot load manifest MoM for 3rd-party repository %s version %i\n", repo->name, version);
ret_code = SWUPD_COULDNT_LOAD_MOM;
goto clean_and_exit;
}
/* search for the bundle in the MoM */
file = mom_search_bundle(mom, bundle);
if (file) {
/* the bundle was found in this repo, keep a pointer to the repo */
info("Bundle %s found in 3rd-party repository %s\n", bundle, repo->name);
count++;
*found_repo = repo;
}
manifest_free(mom);
}
/* if the bundle was not found or exists in more than one repo,
* return NULL */
if (count == 0) {
error("bundle %s was not found in any 3rd-party repository\n\n", bundle);
ret_code = SWUPD_INVALID_BUNDLE;
} else if (count > 1) {
error("bundle %s was found in more than one 3rd-party repository\n", bundle);
info("Please specify a repository using the --repo flag\n\n");
ret_code = SWUPD_INVALID_OPTION;
}
clean_and_exit:
set_path_prefix(path_prefix);
set_state_dir(state_dir);
set_content_url(content_url);
free_string(&path_prefix);
free_string(&state_dir);
free_string(&content_url);
return ret_code;
}
enum swupd_code third_party_run_operation(struct list *bundles, const char *repo, run_operation_fn_t run_operation_fn)
{
struct list *repos = NULL;
struct list *iter = NULL;
struct repo *selected_repo = NULL;
char *state_dir;
char *path_prefix;
char *content_url;
int ret;
enum swupd_code ret_code = SWUPD_OK;
/* load the existing 3rd-party repos from the repo.ini config file */
repos = third_party_get_repos();
/* backup the original global values */
state_dir = strdup_or_die(globals.state_dir);
path_prefix = strdup_or_die(globals.path_prefix);
content_url = strdup_or_die(globals.content_url);
/* try action on the bundles one by one */
for (iter = bundles; iter; iter = iter->next) {
char *bundle = iter->data;
/* if the repo to be used was specified, use it, otherwise
* search for the bundle in all the 3rd-party repos */
if (repo) {
selected_repo = list_search(repos, repo, repo_name_cmp);
if (!selected_repo) {
error("3rd-party repository %s was not found\n\n", repo);
ret_code = SWUPD_INVALID_REPOSITORY;
goto clean_and_exit;
}
} else {
/* search for the bundle in all repos */
ret = third_party_find_bundle(bundle, repos, &selected_repo);
if (ret) {
ret_code = ret;
/* something went wrong or wasn't found,
* go to the next bundle */
continue;
}
}
if (selected_repo) {
/* set the appropriate content_dir and state_dir for the selected 3rd-party repo */
ret = third_party_set_repo(state_dir, path_prefix, selected_repo);
if (ret) {
ret_code = ret;
goto next;
}
/* perform appropriate action on the bundle */
ret = run_operation_fn(bundle);
if (ret) {
/* if we have an error here it is ok to overwrite any previous error */
ret_code = ret;
}
info("\n");
/* return the global variables to the original values */
next:
set_path_prefix(path_prefix);
set_state_dir(state_dir);
set_content_url(content_url);
}
}
/* free data */
clean_and_exit:
list_free_list_and_data(repos, repo_free_data);
free_string(&path_prefix);
free_string(&state_dir);
free_string(&content_url);
return ret_code;
}
#endif
+15
View File
@@ -20,6 +20,9 @@ struct repo {
char *url;
};
/* @brief Definition of a function that performs an action on a given bundle */
typedef enum swupd_code (*run_operation_fn_t)(char *bundle);
/**
* @brief Free repo pointed by @c repo.
*/
@@ -77,6 +80,18 @@ enum swupd_code third_party_set_repo(const char *state_dir, const char *path_pre
*/
int repo_name_cmp(const void *repo, const void *name);
/**
* @brief Performs an operation on every bundle from the list.
*
* @param repo the name of the 3rd-party repository where the bundles
* should be looked for. If no repo is specified the bundles are searched for
* in all existing repos.
* @param run_operation_fn the function to be performed on the bundles
*
* @returns a swupd_code
*/
enum swupd_code third_party_run_operation(struct list *bundles, const char *repo, run_operation_fn_t run_operation_fn);
#endif
#ifdef __cplusplus