aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-08-13 14:10:48 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-08-13 16:52:22 +0300
commit5f571ad3cc75d35a8259ca6a3d5d78b6ee62d137 (patch)
treedc5e2bf437766d8d7042252486d23678bdae07f7
parentedab35e216bc3839915129e54f98160428634283 (diff)
Add --pre-hook option to bdep-new
-rw-r--r--bdep/new.cxx175
-rw-r--r--tests/new.testscript62
2 files changed, 155 insertions, 82 deletions
diff --git a/bdep/new.cxx b/bdep/new.cxx
index 507ee3d..359d45f 100644
--- a/bdep/new.cxx
+++ b/bdep/new.cxx
@@ -599,9 +599,86 @@ namespace bdep
// for details.
//
if (!exists (out))
- mk_p (out);
+ mk_p (out);
}
+ // Run pre/post hooks.
+ //
+ auto run_hooks = [&prj, &sub, &pkg, &n, &b, &s, &t, &l, &vc, &out]
+ (const strings& hooks, const char* what)
+ {
+ command_substitution_map subs;
+ strings vars;
+
+ auto add_var = [&subs, &vars] (string name, string value)
+ {
+ vars.push_back ("BDEP_NEW_" +
+ ucase (const_cast<const string&> (name)) +
+ '=' +
+ value);
+
+ subs[move (name)] = move (value);
+ };
+
+ add_var ("mode", sub ? "subdirectory" : pkg ? "package" : "project");
+ add_var ("name", n);
+ add_var ("base", b);
+ add_var ("stem", s);
+ add_var ("type", t.string ());
+ add_var ("lang", l.string (true /* lower */));
+ add_var ("vcs", vc.string ());
+ add_var ("root", prj.string ());
+
+ // Note: out directory path is absolute and normalized.
+ //
+ optional<process_env> env (process_env (process_path (), out, vars));
+
+ for (const string& cmd: hooks)
+ {
+ try
+ {
+ process_exit e (command_run (cmd,
+ env,
+ subs,
+ '@',
+ [] (const char* const args[], size_t n)
+ {
+ if (verb >= 2)
+ {
+ print_process (args, n);
+ }
+ }));
+
+ if (!e)
+ {
+ if (e.normal ())
+ throw failed (); // Assume the command issued diagnostics.
+
+ fail << what << " hook '" << cmd << "' " << e;
+ }
+ }
+ catch (const invalid_argument& e)
+ {
+ fail << "invalid " << what << " hook '" << cmd << "': " << e;
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to execute " << what << " hook '" << cmd << "': "
+ << e;
+ }
+ catch (const process_error& e)
+ {
+ fail << "unable to execute " << what << " hook '" << cmd << "': "
+ << e;
+ }
+ }
+ };
+
+ // Run pre hooks.
+ //
+ if (o.pre_hook_specified ())
+ run_hooks (o.pre_hook (), "pre");
+
// Source directory relative to package root.
//
const dir_path& d (sub ? *sub : dir_path (b));
@@ -706,7 +783,7 @@ namespace bdep
// we have already created.
//
vector<auto_rmfile> rms;
- for (path cf;;) // Breakout look with the current file being written.
+ for (path cf;;) // Breakout loop with the current file being written.
try
{
ofdstream os;
@@ -1995,78 +2072,10 @@ namespace bdep
}
}
-
- // Run post-hooks.
+ // Run post hooks.
//
- optional<process_env> env;
- optional<command_substitution_map> subs;
- strings vars;
-
if (o.post_hook_specified ())
- {
- subs = command_substitution_map ();
-
- auto add_var = [&subs, &vars] (string name, string value)
- {
- vars.push_back ("BDEP_NEW_" +
- ucase (const_cast<const string&> (name)) +
- '=' +
- value);
-
- (*subs)[move (name)] = move (value);
- };
-
- add_var ("mode", sub ? "subdirectory" : pkg ? "package" : "project");
- add_var ("name", n);
- add_var ("base", move (b));
- add_var ("stem", move (s));
- add_var ("type", t.string ());
- add_var ("lang", l.string (true /* lower */));
- add_var ("vcs", vc.string ());
- add_var ("root", prj.string ());
-
- env = process_env (process_path (), out, vars);
- }
-
- for (const string& cmd: o.post_hook ())
- {
- try
- {
- // Note: out directory path is absolute and normalized.
- //
- process_exit e (command_run (cmd,
- env,
- subs,
- '@',
- [] (const char* const args[], size_t n)
- {
- if (verb >= 2)
- {
- print_process (args, n);
- }
- }));
-
- if (!e)
- {
- if (e.normal ())
- throw failed (); // Assume the command issued diagnostics.
-
- fail << "post hook '" << cmd << "' " << e;
- }
- }
- catch (const invalid_argument& e)
- {
- fail << "invalid post hook '" << cmd << "': " << e;
- }
- catch (const io_error& e)
- {
- fail << "unable to execute post hook '" << cmd << "': " << e;
- }
- catch (const process_error& e)
- {
- fail << "unable to execute post hook '" << cmd << "': " << e;
- }
- }
+ run_hooks (o.post_hook (), "post");
if (verb)
text << "created new " << t << ' ' << (sub ? "source subdirectory" :
@@ -2226,16 +2235,26 @@ namespace bdep
forbid ("--config-create|-C", o.config_create_specified ());
forbid ("--wipe", o.wipe ()); // Dangerous.
- if (e.remote && o.post_hook_specified ())
+ if (e.remote && (o.pre_hook_specified () || o.post_hook_specified ()))
{
if (dr.empty ())
- dr << text << "remote post-creation hooks:";
+ dr << text;
+ else
+ dr << '\n';
+
+ dr << "remote hook commands in " << e.file << ':';
+
+ auto add = [&dr] (const strings& hs, const char* what)
+ {
+ for (const string& cmd: hs)
+ dr << "\n " << what << ' ' << cmd;
+ };
- dr << "\n " << e.file << ':';
+ if (o.pre_hook_specified ())
+ add (o.pre_hook (), "pre: ");
- const strings& hs (o.post_hook ());
- for (const string& h: hs)
- dr << (hs.size () == 1 ? " " : "\n ") << h;
+ if (o.post_hook_specified ())
+ add (o.post_hook (), "post:");
}
};
diff --git a/tests/new.testscript b/tests/new.testscript
index 9ac0b9f..3c39b47 100644
--- a/tests/new.testscript
+++ b/tests/new.testscript
@@ -704,7 +704,7 @@ status += -d prj
: default-options-files
:
{
- : remote-post-hook
+ : remote-hooks
:
if $posix
{
@@ -713,15 +713,32 @@ status += -d prj
mkdir prj/.build2;
cat <<EOI >=prj/.build2/bdep-new-package.options;
- --post-hook "echo .idea/ >>.gitignore"
+ --pre-hook "mv .gitignore .gitignore.bak"
+ --post-hook "cat .gitignore.bak >>.gitignore"
+ --post-hook "rm .gitignore.bak"
+ EOI
+
+ mkdir --no-cleanup prj/libprj;
+
+ cat <<EOI >=prj/libprj/.gitignore;
+ CMakeCache.txt
EOI
$* --package -t lib -d prj libprj <'y' 2>>~%EOE%;
- remote post-creation hooks:
- % .+/.build2/bdep-new-package.options: echo .idea/ >>.gitignore%
+ %remote hook commands in .+/.build2/bdep-new-package.options:%
+ pre: mv .gitignore .gitignore.bak
+ post: cat .gitignore.bak >>.gitignore
+ post: rm .gitignore.bak
%execute\? \[y/n\] created new library package libprj in .+/prj/libprj/%
EOE
+ cat prj/libprj/.gitignore >>~%EOO%;
+ # Compiler/linker output.
+ #
+ %.+
+ CMakeCache.txt
+ EOO
+
$build prj/libprj/ $cxx 2>>~%EOE%
%(version\.in|c\+\+|ar|ld) .+%{7}
EOE
@@ -826,6 +843,43 @@ status += -d prj
EOE
}
}
+
+ : pre-hook
+ :
+ if $posix
+ {
+ : success
+ :
+ {
+ mkdir --no-cleanup prj &prj/***;
+
+ cat <<EOI >=prj/.gitignore;
+ CMakeCache.txt
+ EOI
+
+ $* prj --pre-hook "mv .gitignore .gitignore.bak" \
+ --post-hook "cat .gitignore.bak >>.gitignore" \
+ --post-hook "rm .gitignore.bak" 2>>/"EOE";
+ created new executable project prj in $~/prj/
+ EOE
+
+ cat prj/.gitignore >>~%EOO%
+ .bdep/
+ %.+
+ CMakeCache.txt
+ EOO
+ }
+
+ : failure
+ :
+ {
+ : substitution
+ :
+ $* prj --pre-hook 'echo foo >>@bar@' 2>>EOE &prj/*** != 0
+ error: invalid pre hook 'echo foo >>@bar@': unknown variable 'bar'
+ EOE
+ }
+ }
}
: cfg