aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-11-28 17:45:41 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-11-28 17:45:41 +0300
commitf93e1e81eac9bcce3d11379e4cdefed5cf6093fd (patch)
tree39c4c0f1a0d8ee9c3d2813412429be603a5485bf
parent69f26f60cceae86bbd6d8b0b3013ef5153c6f666 (diff)
Fix bundled git running other git as a child on Windows
-rw-r--r--bdep/git.txx46
1 files changed, 43 insertions, 3 deletions
diff --git a/bdep/git.txx b/bdep/git.txx
index f3bedf0..c5aca72 100644
--- a/bdep/git.txx
+++ b/bdep/git.txx
@@ -82,9 +82,49 @@ namespace bdep
{
git_check_version (min_ver);
- return start (forward<I> (in), forward<O> (out), forward<E> (err),
- "git",
- forward<A> (args)...);
+ try
+ {
+ using namespace butl;
+
+ // On startup git prepends the PATH environment variable value with the
+ // computed directory path where its sub-programs are supposedly located
+ // (--exec-path option, GIT_EXEC_PATH environment variable, etc; see
+ // cmd_main() in git's git.c for details).
+ //
+ // Then, when git needs to run itself or one of its components as a
+ // child process, it resolves the full executable path searching in
+ // directories listed in PATH (see locate_in_PATH() in git's
+ // run-command.c for details).
+ //
+ // On Windows we install git and its components into a place where it is
+ // not expected to be, which results in the wrong path in PATH as set by
+ // git (for example, c:/build2/libexec/git-core) which in turn may lead
+ // to running some other git that appear in the PATH variable. To
+ // prevent this we pass the git's exec directory via the --exec-path
+ // option explicitly.
+ //
+ string ep;
+ process_path pp (process::path_search ("git", true /* init */));
+
+#ifdef _WIN32
+ ep = "--exec-path=" + pp.effect.directory ().string ();
+#endif
+
+ return process_start_callback (
+ [] (const char* const args[], size_t n)
+ {
+ if (verb >= 2)
+ print_process (args, n);
+ },
+ forward<I> (in), forward<O> (out), forward<E> (err),
+ pp,
+ !ep.empty () ? ep.c_str () : nullptr,
+ forward<A> (args)...);
+ }
+ catch (const process_error& e)
+ {
+ fail << "unable to execute git: " << e << endf;
+ }
}
template <typename... A>