summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2011-01-18 13:35:50 -0800
committerAn-Cheng Huang <ancheng@vyatta.com>2011-01-18 13:35:50 -0800
commitdbe4a4ee85b2968ae63415bd12080abba3b9a8df (patch)
tree5cd0c572b3b9ca822fde828aebce1f5bfffd3265
parent5ec1f60e4c641a9e135fb9818e9a7334aa3180f7 (diff)
downloadvyatta-cfg-dbe4a4ee85b2968ae63415bd12080abba3b9a8df.tar.gz
vyatta-cfg-dbe4a4ee85b2968ae63415bd12080abba3b9a8df.zip
initial implementation of context diff
-rw-r--r--src/cli_shell_api.cpp4
-rw-r--r--src/cnode/cnode-algorithm.cpp180
-rw-r--r--src/cnode/cnode-algorithm.hpp8
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);