diff options
| author | An-Cheng Huang <ancheng@vyatta.com> | 2011-05-16 19:57:39 -0700 | 
|---|---|---|
| committer | An-Cheng Huang <ancheng@vyatta.com> | 2011-05-16 19:57:39 -0700 | 
| commit | 76ff750a6b057dacba1361726f15cd5bd4bfe14b (patch) | |
| tree | 8eea69cfa6ba3377883d2caa4aeca874c100b2a3 /src | |
| parent | 7ea935bc47f37111b95ed8a4f989a2ae3f578e5a (diff) | |
| download | vyatta-cfg-76ff750a6b057dacba1361726f15cd5bd4bfe14b.tar.gz vyatta-cfg-76ff750a6b057dacba1361726f15cd5bd4bfe14b.zip | |
reimplement commit hooks mechanism
* do NOT reinvent the wheel (directory traversal, sorting, script execution, etc.) when the functionality is already provided by the system.
* eliminate hard-coded hook directory in various feastures. everyone should obtain the directory path from the config backend.
Diffstat (limited to 'src')
| -rw-r--r-- | src/cli_shell_api.cpp | 23 | ||||
| -rw-r--r-- | src/commit/commit-algorithm.cpp | 35 | ||||
| -rw-r--r-- | src/commit/commit-algorithm.hpp | 36 | 
3 files changed, 64 insertions, 30 deletions
| diff --git a/src/cli_shell_api.cpp b/src/cli_shell_api.cpp index 6e8f384..0caccb9 100644 --- a/src/cli_shell_api.cpp +++ b/src/cli_shell_api.cpp @@ -486,6 +486,26 @@ _cf_process_args(Cstore& cstore, const Cpath& args, Cpath& path)    return root;  } +// output the "pre-commit hook dir" +static void +getPreCommitHookDir(Cstore& cstore, const Cpath& args) +{ +  const char *d = commit::getCommitHookDir(commit::PRE_COMMIT); +  if (d) { +    printf("%s", d); +  } +} + +// output the "post-commit hook dir" +static void +getPostCommitHookDir(Cstore& cstore, const Cpath& args) +{ +  const char *d = commit::getCommitHookDir(commit::POST_COMMIT); +  if (d) { +    printf("%s", d); +  } +} +  /* the following "cf" functions form the "config file" shell API, which   * allows shell scripts to "query" the "config" represented by a config   * file in a way similar to how they query the active/working config. @@ -574,6 +594,9 @@ static OpT ops[] = {    OP(showConfig, -1, NULL, -1, NULL, true),    OP(loadFile, 1, "Must specify config file", -1, NULL, false), +  OP(getPreCommitHookDir, 0, "No argument expected", -1, NULL, false), +  OP(getPostCommitHookDir, 0, "No argument expected", -1, NULL, false), +    OP(cfExists, -1, NULL, 2, "Must specify config file and path", false),    OP(cfReturnValue, -1, NULL, 2, "Must specify config file and path", false),    OP(cfReturnValues, -1, NULL, 2, "Must specify config file and path", false), diff --git a/src/commit/commit-algorithm.cpp b/src/commit/commit-algorithm.cpp index ad775df..80567f0 100644 --- a/src/commit/commit-algorithm.cpp +++ b/src/commit/commit-algorithm.cpp @@ -26,7 +26,13 @@ using namespace commit;  using namespace std; -////// static functions +////// static +static const char *commit_hook_dirs[3] = { +  "/etc/commit/pre-hooks.d", +  "/etc/commit/post-hooks.d", +  NULL +}; +  static void  _set_node_commit_state(CfgNode& node, CommitState s, bool recursive)  { @@ -742,6 +748,16 @@ _get_commit_other_node(CfgNode *cfg1, CfgNode *cfg2, const Cpath& cur_path)    return cn;  } +static void +_execute_hooks(CommitHook hook) +{ +  string cmd = "/bin/run-parts --regex='^[a-zA-Z0-9._-]+$' -- '"; +  cmd += getCommitHookDir(hook); +  cmd += "'"; +  // not checking return status +  system(cmd.c_str()); +} +  ////// class CommitData  CommitData::CommitData() @@ -1043,6 +1059,15 @@ PrioNode::setSubtreeSuccess()  ////// exported functions +const char * +commit::getCommitHookDir(CommitHook hook) +{ +  if (hook > LAST) { +    return NULL; +  } +  return commit_hook_dirs[hook]; +} +  CfgNode *  commit::getCommitTree(CfgNode *cfg1, CfgNode *cfg2, const Cpath& cur_path)  { @@ -1154,6 +1179,7 @@ commit::doCommit(Cstore& cs, CfgNode& cfg1, CfgNode& cfg2)      return true;    } +  _execute_hooks(PRE_COMMIT);    set_in_commit(true);    PrioNode proot(root); // proot corresponds to root @@ -1186,9 +1212,11 @@ commit::doCommit(Cstore& cs, CfgNode& cfg1, CfgNode& cfg2)      pq.pop();    }    bool ret = true; +  const char *cst = "SUCCESS";    if (f > 0) {      OUTPUT_USER("Commit failed\n");      ret = false; +    cst = ((s > 0) ? "PARTIAL" : "FAILURE");    }    if (!cs.commitConfig(proot)) { @@ -1204,6 +1232,11 @@ commit::doCommit(Cstore& cs, CfgNode& cfg1, CfgNode& cfg2)    if (ret) {      ret = cs.markSessionUnsaved();    } + +  setenv("COMMIT_STATUS", cst, 1); +  _execute_hooks(POST_COMMIT); +  unsetenv("COMMIT_STATUS"); +    return ret;  } diff --git a/src/commit/commit-algorithm.hpp b/src/commit/commit-algorithm.hpp index 3bc89a7..fca04cb 100644 --- a/src/commit/commit-algorithm.hpp +++ b/src/commit/commit-algorithm.hpp @@ -50,6 +50,12 @@ enum CommitTreeTraversalOrder {    POST_ORDER  }; +enum CommitHook { +  PRE_COMMIT, +  POST_COMMIT, +  LAST +}; +  class CommitData {  public:    CommitData(); @@ -120,35 +126,6 @@ public:    void setSubtreeFailure();    void setSubtreeSuccess(); -#if 0 -  // XXX testing -  void print(size_t lvl) { -#define INDENT for(size_t xyz = 0; xyz < lvl; xyz++) { printf("  "); }; -    INDENT; -    if (_node) { -      printf("[%s]\n", _node->getCommitPath().to_string().c_str()); -    } else { -      printf("[---]\n"); -    } -    INDENT; printf("|cp[%s]\n", -                   (_cfg_parent -                    ? _cfg_parent->getCommitPath().to_string().c_str() -                      : NULL)); -    if (_node) { -      INDENT; printf("======\n"); -      _node->rprint(lvl); -      INDENT; printf("======\n"); -    } -#undef INDENT -  } -  void rprint(size_t lvl) { -    print(lvl); -    for (size_t i = 0; i < numChildNodes(); i++) { -      childAt(i)->rprint(lvl + 1); -    } -  } -#endif -  private:    CfgNode *_node;    CfgNode *_cfg_parent; @@ -184,6 +161,7 @@ typedef std::pair<CommitState, std::tr1::shared_ptr<Cpath> >  typedef std::vector<CommittedPathT> CommittedPathListT;  // exported functions +const char *getCommitHookDir(CommitHook hook);  CfgNode *getCommitTree(CfgNode *cfg1, CfgNode *cfg2, const Cpath& cur_path);  bool isCommitPathEffective(Cstore& cs, const Cpath& pcomps,                             std::tr1::shared_ptr<Ctemplate> def, | 
