From: Felix Fietkau Date: Tue, 5 Feb 2008 00:23:55 +0000 (+0100) Subject: implement the uci changes command to display uncommitted changes X-Git-Url: http://git.openwrt.org/?p=project%2Fuci.git;a=commitdiff_plain;h=14654223268133b5e74ee1748cec2374664ac5bf implement the uci changes command to display uncommitted changes --- diff --git a/cli.c b/cli.c index e05f5d4..dadadaa 100644 --- a/cli.c +++ b/cli.c @@ -38,6 +38,7 @@ enum { CMD_REVERT, /* package cmds */ CMD_SHOW, + CMD_CHANGES, CMD_EXPORT, CMD_COMMIT, /* other cmds */ @@ -106,18 +107,45 @@ static void uci_show_package(struct uci_package *p) } } +static void uci_show_changes(struct uci_package *p) +{ + struct uci_element *e; + + uci_foreach_element(&p->saved_history, e) { + struct uci_history *h = uci_to_history(e); + + if (h->cmd == UCI_CMD_REMOVE) + printf("-"); + printf("%s.%s", p->e.name, h->section); + if (e->name) + printf(".%s", e->name); + if (h->cmd != UCI_CMD_REMOVE) + printf("=%s", h->value); + printf("\n"); + } +} static int package_cmd(int cmd, char *package) { struct uci_package *p = NULL; + int ret; - if (uci_load(ctx, package, &p) != UCI_OK) { + if (cmd == CMD_CHANGES) + ctx->flags |= UCI_FLAG_SAVED_HISTORY; + ret = uci_load(ctx, package, &p); + if (cmd == CMD_CHANGES) + ctx->flags &= ~UCI_FLAG_SAVED_HISTORY; + + if (ret != UCI_OK) { cli_perror(); return 1; } if (!p) return 0; switch(cmd) { + case CMD_CHANGES: + uci_show_changes(p); + break; case CMD_COMMIT: if (flags & CLI_FLAG_NOCOMMIT) return 0; @@ -355,6 +383,8 @@ static int uci_cmd(int argc, char **argv) return uci_batch(); else if (!strcasecmp(argv[0], "show")) cmd = CMD_SHOW; + else if (!strcasecmp(argv[0], "changes")) + cmd = CMD_CHANGES; else if (!strcasecmp(argv[0], "export")) cmd = CMD_EXPORT; else if (!strcasecmp(argv[0], "commit")) @@ -387,6 +417,7 @@ static int uci_cmd(int argc, char **argv) case CMD_SHOW: case CMD_EXPORT: case CMD_COMMIT: + case CMD_CHANGES: return uci_do_package_cmd(cmd, argc, argv); case CMD_IMPORT: return uci_do_import(argc, argv); diff --git a/history.c b/history.c index 3a8b73e..070930b 100644 --- a/history.c +++ b/history.c @@ -26,6 +26,42 @@ #include #include +/* record a change that was done to a package */ +static void +uci_add_history(struct uci_context *ctx, struct uci_list *list, int cmd, char *section, char *option, char *value) +{ + struct uci_history *h; + int size = strlen(section) + 1; + char *ptr; + + if (value) + size += strlen(value) + 1; + + h = uci_alloc_element(ctx, history, option, size); + ptr = uci_dataptr(h); + h->cmd = cmd; + h->section = strcpy(ptr, section); + if (value) { + ptr += strlen(ptr) + 1; + h->value = strcpy(ptr, value); + } + uci_list_add(list, &h->e.list); +} + +static void +uci_free_history(struct uci_history *h) +{ + if (!h) + return; + if ((h->section != NULL) && + (h->section != uci_dataptr(h))) { + free(h->section); + free(h->value); + } + uci_free_element(&h->e); +} + + int uci_set_savedir(struct uci_context *ctx, const char *dir) { char *sdir; @@ -85,6 +121,20 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * if (rename && !uci_validate_str(value, (option || delete))) goto error; + if (ctx->flags & UCI_FLAG_SAVED_HISTORY) { + int cmd; + + /* NB: no distinction between CMD_CHANGE and CMD_ADD possible at this point */ + if(delete) + cmd = UCI_CMD_REMOVE; + else if (rename) + cmd = UCI_CMD_RENAME; + else + cmd = UCI_CMD_CHANGE; + + uci_add_history(ctx, &p->saved_history, cmd, section, option, value); + } + if (rename) UCI_INTERNAL(uci_rename, ctx, p, section, option, value); else if (delete) diff --git a/libuci.c b/libuci.c index 66e6d23..7805d74 100644 --- a/libuci.c +++ b/libuci.c @@ -39,6 +39,7 @@ static const char *uci_errstr[] = { [UCI_ERR_UNKNOWN] = "Unknown error", }; +#include "uci_internal.h" #include "util.c" #include "list.c" #include "history.c" diff --git a/list.c b/list.c index 24382c8..e817118 100644 --- a/list.c +++ b/list.c @@ -151,44 +151,6 @@ uci_free_section(struct uci_section *s) uci_free_element(&s->e); } -/* record a change that was done to a package */ -static void -uci_add_history(struct uci_context *ctx, struct uci_package *p, int cmd, char *section, char *option, char *value) -{ - struct uci_history *h; - int size = strlen(section) + 1; - char *ptr; - - if (!p->confdir) - return; - - if (value) - size += strlen(value) + 1; - - h = uci_alloc_element(ctx, history, option, size); - ptr = uci_dataptr(h); - h->cmd = cmd; - h->section = strcpy(ptr, section); - if (value) { - ptr += strlen(ptr) + 1; - h->value = strcpy(ptr, value); - } - uci_list_add(&p->history, &h->e.list); -} - -static void -uci_free_history(struct uci_history *h) -{ - if (!h) - return; - if ((h->section != NULL) && - (h->section != uci_dataptr(h))) { - free(h->section); - free(h->value); - } - uci_free_element(&h->e); -} - static struct uci_package * uci_alloc_package(struct uci_context *ctx, const char *name) { @@ -198,6 +160,7 @@ uci_alloc_package(struct uci_context *ctx, const char *name) p->ctx = ctx; uci_list_init(&p->sections); uci_list_init(&p->history); + uci_list_init(&p->saved_history); return p; } @@ -218,6 +181,9 @@ uci_free_package(struct uci_package **package) uci_foreach_element_safe(&p->history, tmp, e) { uci_free_history(uci_to_history(e)); } + uci_foreach_element_safe(&p->saved_history, tmp, e) { + uci_free_history(uci_to_history(e)); + } uci_free_element(&p->e); *package = NULL; } @@ -294,8 +260,8 @@ int uci_del_element(struct uci_context *ctx, struct uci_element *e) } p = s->package; - if (!internal) - uci_add_history(ctx, p, UCI_CMD_REMOVE, s->e.name, option, NULL); + if (!internal && p->confdir) + uci_add_history(ctx, &p->history, UCI_CMD_REMOVE, s->e.name, option, NULL); switch(e->type) { case UCI_TYPE_SECTION: @@ -357,8 +323,8 @@ int uci_set_element_value(struct uci_context *ctx, struct uci_element **element, return 0; } p = s->package; - if (!internal) - uci_add_history(ctx, p, UCI_CMD_CHANGE, section, option, value); + if (!internal && p->confdir) + uci_add_history(ctx, &p->history, UCI_CMD_CHANGE, section, option, value); uci_list_del(&e->list); e = uci_realloc(ctx, e, size); @@ -391,8 +357,8 @@ int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, ch /* NB: p, section, option validated by uci_lookup */ UCI_INTERNAL(uci_lookup, ctx, &e, p, section, option); - if (!internal) - uci_add_history(ctx, p, UCI_CMD_RENAME, section, option, name); + if (!internal && p->confdir) + uci_add_history(ctx, &p->history, UCI_CMD_RENAME, section, option, name); name = uci_strdup(ctx, name); if (e->name) @@ -479,8 +445,8 @@ notfound: UCI_THROW(ctx, UCI_ERR_NOTFOUND); /* now add the missing entry */ - if (!internal) - uci_add_history(ctx, p, UCI_CMD_ADD, section, option, value); + if (!internal && p->confdir) + uci_add_history(ctx, &p->history, UCI_CMD_ADD, section, option, value); if (s) uci_alloc_option(s, option, value); else { diff --git a/uci.h b/uci.h index 9f03a6f..cfcdf3e 100644 --- a/uci.h +++ b/uci.h @@ -279,9 +279,10 @@ enum uci_type { }; enum uci_flags { - UCI_FLAG_STRICT = (1 << 0), /* strict mode for the parser */ - UCI_FLAG_PERROR = (1 << 1), /* print parser error messages */ - UCI_FLAG_EXPORT_NAME = (1 << 2), /* when exporting, name unnamed sections */ + UCI_FLAG_STRICT = (1 << 0), /* strict mode for the parser */ + UCI_FLAG_PERROR = (1 << 1), /* print parser error messages */ + UCI_FLAG_EXPORT_NAME = (1 << 2), /* when exporting, name unnamed sections */ + UCI_FLAG_SAVED_HISTORY = (1 << 3), /* store the saved history in memory as well */ }; struct uci_element @@ -317,23 +318,6 @@ struct uci_context int bufsz; }; -struct uci_parse_context -{ - /* error context */ - const char *reason; - int line; - int byte; - - /* private: */ - struct uci_package *package; - struct uci_section *section; - bool merge; - FILE *file; - const char *name; - char *buf; - int bufsz; -}; - struct uci_package { struct uci_element e; @@ -345,6 +329,7 @@ struct uci_package /* private: */ int n_section; struct uci_list history; + struct uci_list saved_history; }; struct uci_section diff --git a/uci_internal.h b/uci_internal.h new file mode 100644 index 0000000..5b496ea --- /dev/null +++ b/uci_internal.h @@ -0,0 +1,38 @@ +/* + * libuci - Library for the Unified Configuration Interface + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __UCI_INTERNAL_H +#define __UCI_INTERNAL_H + +struct uci_parse_context +{ + /* error context */ + const char *reason; + int line; + int byte; + + /* private: */ + struct uci_package *package; + struct uci_section *section; + bool merge; + FILE *file; + const char *name; + char *buf; + int bufsz; +}; + +static void uci_add_history(struct uci_context *ctx, struct uci_list *list, int cmd, char *section, char *option, char *value); +static void uci_free_history(struct uci_history *h); + +#endif