As Johannes Schindelin suggested, it verifies that the selected item is
a valid Git repository and adds different menu items accordingly.
This version is for preview purposes only. It implements the suggestion
in a way that the text of the item is context-sensitive, but the action
is always the same.

TODO: think about moving env_for_git() and exec_with_status() to
systeminfo. It does not really belong there, but even less so to menu.
TODO: decide on a structure and actions of added menu items.
---
 ext.c  |    4 +++
 menu.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 89 insertions(+), 10 deletions(-)

diff --git a/ext.c b/ext.c
index 593d4e4..8579386 100644
--- a/ext.c
+++ b/ext.c
@@ -57,6 +57,10 @@ inline STDMETHODIMP initialize_git_data(struct
git_data *this_,
        UINT count;
        HRESULT result = S_OK;

+       // store the folder, if provided
+       if (folder)
+               SHGetPathFromIDList(folder, this_->name);
+
        if (!data)
                return S_OK;

diff --git a/menu.c b/menu.c
index f3e876c..7f034db 100644
--- a/menu.c
+++ b/menu.c
@@ -1,12 +1,13 @@
 #include <shlobj.h>
-#include <stdarg.h>
-#include <tchar.h>
 #include <stdio.h>
 #include "menu.h"
 #include "ext.h"
 #include "debug.h"
 #include "systeminfo.h"

+#define LONGEST_MENU_ITEM 40
+#define MAX_PROCESSING_TIME (60 * 1000)
+
 /*
  * Modifies a copy of the environment, to include Git in PATH
  */
@@ -58,6 +59,46 @@ static void *env_for_git()
        return environment;
 }

+static int exec_with_status(char *cmd, const char *wd)
+{
+       STARTUPINFO si = { sizeof(si) };
+       PROCESS_INFORMATION pi;
+       DWORD status = -1;
+
+       si.dwFlags = STARTF_USESHOWWINDOW;
+       si.wShowWindow = SW_HIDE;
+
+       if (CreateProcess(NULL, cmd,
+               NULL, NULL, FALSE, 0,
+               env_for_git(), wd, &si, &pi)) {
+
+               if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess,
+                       MAX_PROCESSING_TIME)) {
+
+                       if (! GetExitCodeProcess(pi.hProcess, &status)) {
+                               debug_git("[ERROR] GetExitCode failed (%d); "
+                                       "wd: %s; cmd: %s",
+                                       GetLastError(), wd, cmd);
+                       }
+
+               } else {
+                       debug_git("[ERROR] process timed out; "
+                               "wd: %s; cmd: %s",
+                               wd, cmd);
+               }
+
+               CloseHandle(pi.hProcess);
+               CloseHandle(pi.hThread);
+
+       } else {
+               debug_git("[ERROR] Could not create git process (%d); "
+                       "wd: %s; cmd: %s",
+                       GetLastError(), wd, cmd);
+       }
+
+       return status;
+}
+
 /*
  * These are the functions for handling the context menu.
  */
@@ -67,16 +108,52 @@ static STDMETHODIMP query_context_menu(void *p, HMENU menu,
 {
        struct git_menu *this_menu = p;
        struct git_data *this_ = this_menu->git_data;
+       char *wd;
+       BOOL bDirSelected = TRUE;
+
+       UINT original_first = first_command;
+       char menu_item[LONGEST_MENU_ITEM];
+
+       int status;

        if (flags & CMF_DEFAULTONLY)
                return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);

+       // figure out the directory
+       wd = strdup(this_->name);
+       if (! (FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(wd))) {
+               char *c = strrchr(wd, '\\');
+               *c = 0;
+               bDirSelected = FALSE;
+       }
+
+       status = exec_with_status ("git.exe rev-parse --show-cdup", wd);
+       free (wd);
+
+       if (-1 == status)
+               return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
+
+       /* TODO: the following big, ugly code needs to be something like
+                build_menu_items()
+                It's left as is to signify the preview nature of the patch
+       */
+       if (0 != status) { // this is not a repository
+               if (bDirSelected)
+                       strcpy(menu_item, "&Git Clone Here");
+               else
+                       strcpy(menu_item, "&Git Init Here");
+       } else
+               strcpy(menu_item, "&Git");
+
        InsertMenu(menu, index, MF_SEPARATOR | MF_BYPOSITION,
-                       first_command, "");
+                       first_command++, "");
        InsertMenu(menu, index+1, MF_STRING | MF_BYPOSITION,
-                  first_command+1, _T("&Git Gui"));
+                  first_command++, menu_item);
        
-       return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 2);
+       /* TODO: when the above block is fixed, we'll just have
+                return MAKE_RESULT(..., build_menu_items()); */
+       return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL,
+               first_command - original_first);
 }

 /*
@@ -147,13 +224,11 @@ static STDMETHODIMP invoke_command(void *p,
                STARTUPINFO si = { sizeof(si) };
                PROCESS_INFORMATION pi;
                
-               TCHAR command[1024];
+               char command[1024];
                const char *wd;
                DWORD dwAttr, fa;

-               wsprintf(command, TEXT("wish.exe \"%s/bin/git-gui\""),
-                        msys_path());
-               
+               sprintf(command, "wish.exe \"%s/bin/git-gui\"", msys_path());   
        
                
                wd = this_->name;
                if (wd == NULL || strlen(wd) == 0)
@@ -202,7 +277,7 @@ static STDMETHODIMP get_command_string(void *p, UINT id,


        if (flags & GCS_HELPTEXT) {
-               LPCTSTR text = _T("Launch the GIT Gui in the local or chosen 
directory.");
+               char *text = "Launch the GIT Gui in the local or chosen 
directory.";
                size_t len = strlen(text) + 1;
                LPWSTR tw = malloc(len*sizeof(wchar_t));
                // need to convert terminating NULL as well
-- 
1.5.4.rc0.929.g50e2

Reply via email to