Add multipatch capability to osmo-config-merge

That's pretty straightforward and convenient extention: handle all
extra positional arguments as patch file names. This makes it similar to
'cp' and other coreutils basic tools. For example:
osmo-config-merge base.cfg patch1.cfg patch2.cfg patch3.cfg
will apply 3 patches to the base config file.

Change-Id: I212cbdc3bf6f251c1a3175737ac74242fb004c6d
This commit is contained in:
Max 2019-02-13 18:00:06 +01:00 committed by Harald Welte
parent 52a8375025
commit 2e717c968d
1 changed files with 45 additions and 21 deletions

View File

@ -49,6 +49,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/msgfile.h>
struct node {
struct node *parent; /* back-pointer */
@ -57,6 +58,11 @@ struct node {
char *line;
};
struct osmo_patch_entry {
struct llist_head list;
struct node *tree;
};
/* allocate a new node */
static struct node *node_alloc(void *ctx)
{
@ -225,49 +231,67 @@ static void dump_node(struct node *root, FILE *out, bool print_node_depth)
static void exit_usage(int rc)
{
fprintf(stderr, "Usage: osmo-config-merge <config-file> <config-patch> [--debug]\n");
fprintf(stderr, "Usage: osmo-config-merge <config-file> <config-patch>...<config-patch> [--debug]\n");
exit(rc);
}
int main(int argc, char **argv)
{
const char *base_fname, *patch_fname;
struct node *base_tree, *patch_tree;
struct node *base_tree;
struct osmo_config_list *trees;
struct osmo_patch_entry *entry;
bool debug_enabled = false;
unsigned i;
void *ctx;
if (argc < 3)
exit_usage(1);
base_fname = argv[1];
patch_fname = argv[2];
if (argc > 3) {
if (!strcmp(argv[3], "--debug"))
debug_enabled = true;
else
exit_usage(1);
}
ctx = talloc_named_const(NULL, 0, "root");
base_tree = file_read(ctx, base_fname);
patch_tree = file_read(ctx, patch_fname);
if (!base_tree || ! patch_tree) {
base_tree = file_read(ctx, argv[1]);
trees = talloc_zero(ctx, struct osmo_config_list);
if (!base_tree || !trees) {
talloc_free(ctx);
return 2;
}
INIT_LLIST_HEAD(&trees->entry);
for (i = 2; i < argc; i++) {
if (!strcmp(argv[i], "--debug"))
debug_enabled = true;
else {
entry = talloc_zero(trees, struct osmo_patch_entry);
if (!entry) {
talloc_free(ctx);
return 3;
}
entry->tree = file_read(ctx, argv[i]);
if (!entry->tree) {
talloc_free(ctx);
return 4;
}
llist_add_tail(&entry->list, &trees->entry);
}
}
if (llist_empty(&trees->entry))
exit_usage(1);
if (debug_enabled) {
fprintf(stderr, "====== dumping tree (base)\n");
dump_node(base_tree, stderr, true);
fprintf(stderr, "====== dumping tree (patch)\n");
dump_node(patch_tree, stderr, true);
}
append_patch(base_tree, patch_tree);
llist_for_each_entry(entry, &trees->entry, list) {
append_patch(base_tree, entry->tree);
if (debug_enabled) {
fprintf(stderr, "====== dumping tree (patch)\n");
dump_node(entry->tree, stderr, true);
}
}
if (debug_enabled)
fprintf(stderr, "====== dumping tree (patched)\n");
@ -275,7 +299,7 @@ int main(int argc, char **argv)
fflush(stdout);
/* make AddressSanitizer / LeakSanitizer happy by recursively freeing the trees */
talloc_free(patch_tree);
talloc_free(trees);
talloc_free(base_tree);
talloc_free(ctx);