This is a fix, suggested by Lode Leroy, to not modify PATH in
"our" environment, because it's actually Explorer's environment.
See env_for_git().

Now, because our environment does not have git.exe or wish.exe in PATH,
it's harder to start wish.exe, so we start git.exe hidden. Given that we
will need other ways to start Git, a new module - exec.[ch] - is created.
---
This is a variation of the original patch after it has been reviewed
by Johannes Schindelin and has been given some additional testing. The
exec.[ch] module was inspired by the review of the next patch "Preview
implementation of "smart" context menu".

 Makefile |    5 ++-
 exec.c   |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 exec.h   |   11 +++++++++
 menu.c   |   46 ++-----------------------------------
 4 files changed, 93 insertions(+), 45 deletions(-)
 create mode 100644 exec.c
 create mode 100644 exec.h

diff --git a/Makefile b/Makefile
index dd6c1fe..bfc2bc6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-OBJECTS=ext.o debug.o dll.o factory.o menu.o systeminfo.o registry.o
+OBJECTS=ext.o debug.o dll.o factory.o menu.o systeminfo.o registry.o exec.o
 CFLAGS=-O -g

 TARGET=git_shell_ext.dll
@@ -20,9 +20,10 @@ $(TARGET): $(OBJECTS) git_shell_ext.def
 dll.o: dll.h ext.h factory.h systeminfo.h registry.h
 ext.o: ext.h debug.h
 factory.o: factory.h ext.h menu.h
-menu.o: menu.h ext.h debug.h systeminfo.h
+menu.o: menu.h ext.h debug.h systeminfo.h exec.h
 systeminfo.o: systeminfo.h
 registry.o: registry.h
+exec.o: debug.h systeminfo.h exec.h

 install: all
        regsvr32 -s -n -i:machine $(DLL_PATH)
diff --git a/exec.c b/exec.c
new file mode 100644
index 0000000..4d519cc
--- /dev/null
+++ b/exec.c
@@ -0,0 +1,76 @@
+#include <windows.h>
+#include <stdio.h>
+#include "debug.h"
+#include "systeminfo.h"
+#include "exec.h"
+
+char *env_for_git()
+{
+       static char *environment;
+
+       /*
+        * if we can't find path to msys in the registry, return NULL and
+        * the CreateProcess will copy the environment for us
+        */
+       if (!environment && msys_path()) {
+               char *old = GetEnvironmentStrings();
+               size_t space = 0, path_index = -1, name_len = 0, len2;
+
+               while (old[space]) {
+                       /* if it's PATH variable (could be Path= too!) */
+                       if (!strnicmp(old + space, "PATH=", 5)) {
+                               path_index = space;
+                               name_len = 5;
+                       }
+
+                       while (old[space])
+                               space++;
+                       space++; /* skip var-terminating NULL */
+               }
+
+               if (path_index == -1)
+                       path_index = space;
+
+               environment = (char *)malloc(space +
+                               2 * strlen(msys_path()) + 32);
+
+               /* copy the block up to the equal sign of PATH var */
+               memcpy(environment, old, path_index);
+               /* insert new segments of the PATH */
+               len2 = sprintf(environment + path_index,
+                       "PATH=%s\\bin;%s\\mingw\\bin%s",
+                       msys_path(), msys_path(), name_len ? ";" : "");
+               /* append original value of PATH and variables after it */
+               memcpy(environment + path_index + len2,
+                       old + path_index + name_len,
+                       space + 1 - path_index - name_len);
+
+               FreeEnvironmentStrings(old);
+       }
+
+       return environment;
+}
+
+void exec_gui(char *command, const char *wd)
+{
+       STARTUPINFO si = { sizeof(si) };
+       PROCESS_INFORMATION pi;
+
+       si.dwFlags = STARTF_USESHOWWINDOW;
+       si.wShowWindow = SW_HIDE;
+
+       debug_git("Trying to spawn '%s' in working directory '%s'\n",
+               command, wd);
+       if (CreateProcess(NULL, command, NULL, NULL, FALSE, 0,
+                       env_for_git(), wd, &si, &pi))
+       {
+               CloseHandle(pi.hProcess);
+               CloseHandle(pi.hThread);
+       }
+       else
+               debug_git("[ERROR] Could not create process (%d)"
+                       "wd: %s; cmd: %s",
+                       GetLastError(), wd, command);
+
+}
+
diff --git a/exec.h b/exec.h
new file mode 100644
index 0000000..cebb56b
--- /dev/null
+++ b/exec.h
@@ -0,0 +1,11 @@
+
+/*
+ * Modifies a copy of the environment to include Git in PATH
+ */
+char *env_for_git();
+
+/*
+ * Executes a console application hidden as in "git gui" to hide git
+ */
+void exec_gui(char *cmd, const char *wd);
+
diff --git a/menu.c b/menu.c
index c6a5a55..97811fa 100644
--- a/menu.c
+++ b/menu.c
@@ -6,6 +6,7 @@
 #include "ext.h"
 #include "debug.h"
 #include "systeminfo.h"
+#include "exec.h"

 /*
  * These are the functions for handling the context menu.
@@ -82,24 +83,6 @@ static char *convert_directory_format(const char *path)
        return converted;
 }

-static void adjust_path_for_git(const char *msys_path)
-{
-       static int initialized = 0;
-
-       if (!initialized) {
-               const char *old_path = getenv("PATH");
-               size_t old_len = strlen(old_path);
-               size_t msys_path_len = strlen(msys_path);
-               char *new_path = malloc(old_len + 2 * msys_path_len + 23);
-               if (!new_path)
-                       return;
-               sprintf(new_path, "PATH=%s\\bin;%s\\mingw\\bin;%s",
-                       old_path, msys_path, msys_path);
-               putenv(new_path);
-               initialized = 1;
-       }
-}
-
 static STDMETHODIMP invoke_command(void *p,
                                   LPCMINVOKECOMMANDINFO info)
 {
@@ -112,9 +95,6 @@ static STDMETHODIMP invoke_command(void *p,

        if (command == 1)
        {
-               STARTUPINFO si = { sizeof(si) };
-               PROCESS_INFORMATION pi;
-               
                TCHAR * msysPath = msys_path();

                if (msysPath)
@@ -123,8 +103,7 @@ static STDMETHODIMP invoke_command(void *p,
                        const char *wd;
                        DWORD dwAttr, fa;

-                       adjust_path_for_git(msysPath);
-                       wsprintf(command, TEXT("wish.exe \"%s/bin/git-gui\""),
+                       wsprintf(command, TEXT("\"%s\\bin\\git.exe\" gui"),
                                 msysPath);
                        
                        
@@ -137,30 +116,11 @@ static STDMETHODIMP invoke_command(void *p,
                        if (! (fa & dwAttr))
                                wd = info->lpDirectory;

-                       debug_git("Trying to spawn '%s' in working directory 
'%s'\n", command, wd);
-                       if (CreateProcess(
-                                   NULL,
-                                   command,
-                                   NULL,
-                                   NULL,
-                                   FALSE,
-                                   0, NULL, wd, &si, &pi))
-                       {
-                               CloseHandle(pi.hProcess);
-                               CloseHandle(pi.hThread);
-                       }
-                       else
-                       {
-                               debug_git("[ERROR] %s/%s:%d Could not create 
git gui process (%d)
Command: %s",
-                                         __FILE__, __FUNCTION__, __LINE__,
-                                         GetLastError(), command);
-                       }
+                       exec_gui(command, wd);
                }
                else
-               {
                        debug_git("[ERROR] %s/%s:%d Could not find msysPath",
                                  __FILE__, __FUNCTION__, __LINE__);
-               }
                
                return S_OK;
        }
-- 
1.5.4.rc0.929.g50e2

Reply via email to