diff options
author | An-Cheng Huang <ancheng@vyatta.com> | 2011-01-18 13:35:50 -0800 |
---|---|---|
committer | An-Cheng Huang <ancheng@vyatta.com> | 2011-01-18 13:35:50 -0800 |
commit | dbe4a4ee85b2968ae63415bd12080abba3b9a8df (patch) | |
tree | 5cd0c572b3b9ca822fde828aebce1f5bfffd3265 | |
parent | 5ec1f60e4c641a9e135fb9818e9a7334aa3180f7 (diff) | |
download | vyatta-cfg-dbe4a4ee85b2968ae63415bd12080abba3b9a8df.tar.gz vyatta-cfg-dbe4a4ee85b2968ae63415bd12080abba3b9a8df.zip |
initial implementation of context diff
-rw-r--r-- | src/cli_shell_api.cpp | 4 | ||||
-rw-r--r-- | src/cnode/cnode-algorithm.cpp | 180 | ||||
-rw-r--r-- | src/cnode/cnode-algorithm.hpp | 8 |
3 files changed, 141 insertions, 51 deletions
diff --git a/src/cli_shell_api.cpp b/src/cli_shell_api.cpp index 047bd4a..c04cf16 100644 --- a/src/cli_shell_api.cpp +++ b/src/cli_shell_api.cpp @@ -56,6 +56,7 @@ int op_show_active_only = 0; int op_show_show_defaults = 0; int op_show_hide_secrets = 0; int op_show_working_only = 0; +int op_show_context_diff = 0; typedef void (*OpFuncT)(Cstore& cstore, const vector<string>& args); @@ -391,7 +392,7 @@ showCfg(Cstore& cstore, const vector<string>& args) cnode::show_cfg(wroot, op_show_show_defaults, op_show_hide_secrets); } else { cnode::show_cfg_diff(aroot, wroot, op_show_show_defaults, - op_show_hide_secrets); + op_show_hide_secrets, op_show_context_diff); } } } @@ -464,6 +465,7 @@ struct option options[] = { {"show-show-defaults", no_argument, &op_show_show_defaults, 1}, {"show-hide-secrets", no_argument, &op_show_hide_secrets, 1}, {"show-working-only", no_argument, &op_show_working_only, 1}, + {"show-context-diff", no_argument, &op_show_context_diff, 1}, {NULL, 0, NULL, 0} }; diff --git a/src/cnode/cnode-algorithm.cpp b/src/cnode/cnode-algorithm.cpp index a30b281..23b5b41 100644 --- a/src/cnode/cnode-algorithm.cpp +++ b/src/cnode/cnode-algorithm.cpp @@ -36,8 +36,9 @@ static const string PFX_DIFF_NULL = ""; ////// static (internal) functions static void -_show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level, bool show_def, - bool hide_secret); +_show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level, + vector<string>& cur_path, bool show_def, + bool hide_secret, bool context_diff); static void _get_cmds_diff(const CfgNode *cfg1, const CfgNode *cfg2, @@ -212,7 +213,18 @@ _diff_print_indent(const CfgNode *cfg1, const CfgNode *cfg2, int level, } static void -_diff_print_comment(const CfgNode *cfg1, const CfgNode *cfg2, int level) +_diff_print_context(vector<string>& cur_path) +{ + printf("[edit"); + for (size_t i = 0; i < cur_path.size(); i++) { + printf(" %s", cur_path[i].c_str()); + } + printf("]\n"); +} + +static bool +_diff_print_comment(const CfgNode *cfg1, const CfgNode *cfg2, int level, + vector<string>& cur_path, bool context_diff) { const char *pfx_diff = PFX_DIFF_NONE.c_str(); string comment = ""; @@ -246,15 +258,25 @@ _diff_print_comment(const CfgNode *cfg1, const CfgNode *cfg2, int level) } if (comment == "") { // no comment - return; + return false; + } + if (!context_diff || (pfx_diff != PFX_DIFF_NONE.c_str() + && pfx_diff != PFX_DIFF_NULL.c_str())) { + if (context_diff) { + _diff_print_context(cur_path); + } + _diff_print_indent(cfg1, cfg2, level, pfx_diff); + printf("/* %s */\n", comment.c_str()); + return true; + } else { + return false; } - _diff_print_indent(cfg1, cfg2, level, pfx_diff); - printf("/* %s */\n", comment.c_str()); } static bool _diff_check_and_show_leaf(const CfgNode *cfg1, const CfgNode *cfg2, int level, - bool show_def, bool hide_secret) + vector<string>& cur_path, bool show_def, + bool hide_secret, bool context_diff) { if ((cfg1 && !cfg1->isLeaf()) || (cfg2 && !cfg2->isLeaf())) { // not a leaf node @@ -275,28 +297,45 @@ _diff_check_and_show_leaf(const CfgNode *cfg1, const CfgNode *cfg2, int level, } } - _diff_print_comment(cfg1, cfg2, level); + bool cprint = _diff_print_comment(cfg1, cfg2, level, cur_path, context_diff); + if (cprint) { + context_diff = false; + } if (cfg->isMulti()) { // multi-value node if (force_pfx_diff) { // simple case: just use the same diff prefix for all values - const vector<string>& vvec = cfg->getValues(); - for (size_t i = 0; i < vvec.size(); i++) { - _diff_print_indent(cfg1, cfg2, level, force_pfx_diff); - printf("%s ", cfg->getName().c_str()); - _print_value_str(cfg->getName(), vvec[i].c_str(), hide_secret); - printf("\n"); + if (!cprint && context_diff) { + _diff_print_context(cur_path); + } + if (!context_diff || force_pfx_diff != PFX_DIFF_NULL.c_str()) { + const vector<string>& vvec = cfg->getValues(); + for (size_t i = 0; i < vvec.size(); i++) { + _diff_print_indent(cfg1, cfg2, level, force_pfx_diff); + printf("%s ", cfg->getName().c_str()); + _print_value_str(cfg->getName(), vvec[i].c_str(), hide_secret); + printf("\n"); + } } } else { // need to actually do a diff. vector<string> values; vector<const char *> pfxs; - _cmp_multi_values(cfg1, cfg2, values, pfxs); - for (size_t i = 0; i < values.size(); i++) { - _diff_print_indent(cfg1, cfg2, level, pfxs[i]); - printf("%s ", cfg->getName().c_str()); - _print_value_str(cfg->getName(), values[i].c_str(), hide_secret); - printf("\n"); + bool changed = _cmp_multi_values(cfg1, cfg2, values, pfxs); + if (!context_diff || changed) { + for (size_t i = 0; i < values.size(); i++) { + if (context_diff && pfxs[i] == PFX_DIFF_NONE.c_str()) { + continue; + } + if (!cprint && context_diff) { + _diff_print_context(cur_path); + cprint = true; + } + _diff_print_indent(cfg1, cfg2, level, pfxs[i]); + printf("%s ", cfg->getName().c_str()); + _print_value_str(cfg->getName(), values[i].c_str(), hide_secret); + printf("\n"); + } } } } else { @@ -312,10 +351,17 @@ _diff_check_and_show_leaf(const CfgNode *cfg1, const CfgNode *cfg2, int level, force_pfx_diff = PFX_DIFF_UPD.c_str(); } } - _diff_print_indent(cfg1, cfg2, level, force_pfx_diff); - printf("%s ", cfg->getName().c_str()); - _print_value_str(cfg->getName(), val.c_str(), hide_secret); - printf("\n"); + bool changed = (force_pfx_diff != PFX_DIFF_NONE.c_str() + && force_pfx_diff != PFX_DIFF_NULL.c_str()); + if (!context_diff || changed) { + if (!cprint && context_diff) { + _diff_print_context(cur_path); + } + _diff_print_indent(cfg1, cfg2, level, force_pfx_diff); + printf("%s ", cfg->getName().c_str()); + _print_value_str(cfg->getName(), val.c_str(), hide_secret); + printf("\n"); + } } } @@ -324,8 +370,10 @@ _diff_check_and_show_leaf(const CfgNode *cfg1, const CfgNode *cfg2, int level, static void _diff_show_other(const CfgNode *cfg1, const CfgNode *cfg2, int level, - bool show_def, bool hide_secret) + vector<string>& cur_path, bool show_def, + bool hide_secret, bool context_diff) { + bool orig_cdiff = context_diff; const char *pfx_diff = PFX_DIFF_NONE.c_str(); if (!cfg1) { pfx_diff = PFX_DIFF_ADD.c_str(); @@ -349,37 +397,64 @@ _diff_show_other(const CfgNode *cfg1, const CfgNode *cfg2, int level, * (3) has a "name". */ bool print_this = (not_tag_node && level >= 0 && name.size() > 0); + int next_level = level + 1; if (print_this) { - _diff_print_comment(cfg1, cfg2, level); - _diff_print_indent(cfg1, cfg2, level, pfx_diff); + bool cprint = _diff_print_comment(cfg1, cfg2, level, cur_path, orig_cdiff); + if (orig_cdiff && pfx_diff != PFX_DIFF_NONE.c_str()) { + context_diff = false; + } + if (cprint || !orig_cdiff || pfx_diff != PFX_DIFF_NONE.c_str()) { + if (!cprint && orig_cdiff) { + _diff_print_context(cur_path); + } + _diff_print_indent(cfg1, cfg2, level, pfx_diff); + if (is_value) { + // at tag value + printf("%s %s", name.c_str(), value.c_str()); + } else { + // at intermediate node + printf("%s", name.c_str()); + } + if (cprint && pfx_diff == PFX_DIFF_NONE.c_str()) { + printf(" { ... }\n"); + is_leaf_typeless = true; + } else { + printf("%s\n", (is_leaf_typeless ? "" : " {")); + } + } + + cur_path.push_back(name); if (is_value) { - // at tag value - printf("%s %s", name.c_str(), value.c_str()); - } else { - // at intermediate node - printf("%s", name.c_str()); + cur_path.push_back(value); } - printf("%s\n", (is_leaf_typeless ? "" : " {")); + } else { + next_level = (level >= 0 ? level : 0); } for (size_t i = 0; i < rcnodes1.size(); i++) { - int next_level = level + 1; - if (!print_this) { - next_level = (level >= 0 ? level : 0); - } - _show_diff(rcnodes1[i], rcnodes2[i], next_level, show_def, hide_secret); + _show_diff(rcnodes1[i], rcnodes2[i], next_level, cur_path, + show_def, hide_secret, context_diff); } // finish printing "this" node if necessary - if (print_this && !is_leaf_typeless) { - _diff_print_indent(cfg1, cfg2, level, pfx_diff); - printf("}\n"); + if (print_this) { + cur_path.pop_back(); + if (is_value) { + cur_path.pop_back(); + } + if (!orig_cdiff || pfx_diff != PFX_DIFF_NONE.c_str()) { + if (!is_leaf_typeless) { + _diff_print_indent(cfg1, cfg2, level, pfx_diff); + printf("}\n"); + } + } } } static void -_show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level, bool show_def, - bool hide_secret) +_show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level, + vector<string>& cur_path, bool show_def, + bool hide_secret, bool context_diff) { // if doesn't exist, treat as NULL if (cfg1 && !cfg1->exists()) { @@ -407,13 +482,23 @@ _show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level, bool show_def, exit(1); } + if (context_diff) { + if (cfg1 == cfg2) { + // nothing to do for context diff + return; + } + level = 0; + } + if (_diff_check_and_show_leaf(cfg1, cfg2, (level >= 0 ? level : 0), - show_def, hide_secret)) { + cur_path, show_def, hide_secret, + context_diff)) { // leaf node has been shown. done. return; } else { // intermediate node, tag node, or tag value - _diff_show_other(cfg1, cfg2, level, show_def, hide_secret); + _diff_show_other(cfg1, cfg2, level, cur_path, show_def, hide_secret, + context_diff); } } @@ -640,7 +725,7 @@ _print_cmds_list(const char *op, vector<vector<string> >& list) ////// algorithms void cnode::show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2, bool show_def, - bool hide_secret) + bool hide_secret, bool context_diff) { if (cfg1.isInvalid() || cfg2.isInvalid()) { printf("Specified configuration path is not valid\n"); @@ -651,7 +736,8 @@ cnode::show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2, bool show_def, printf("Configuration under specified path is empty\n"); return; } - _show_diff(&cfg1, &cfg2, -1, show_def, hide_secret); + vector<string> cur_path; + _show_diff(&cfg1, &cfg2, -1, cur_path, show_def, hide_secret, context_diff); } void diff --git a/src/cnode/cnode-algorithm.hpp b/src/cnode/cnode-algorithm.hpp index 07faf07..8837054 100644 --- a/src/cnode/cnode-algorithm.hpp +++ b/src/cnode/cnode-algorithm.hpp @@ -21,9 +21,11 @@ namespace cnode { -void show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2, bool show_def, - bool hide_secret); -void show_cfg(const CfgNode& cfg, bool show_def, bool hide_secret); +void show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2, + bool show_def = false, bool hide_secret = false, + bool context_diff = false); +void show_cfg(const CfgNode& cfg, bool show_def = false, + bool hide_secret = false); void show_cmds_diff(const CfgNode& cfg1, const CfgNode& cfg2); void show_cmds(const CfgNode& cfg); |