OSDN Git Service

added current branch info to context menu
authorMyagi <snowcoder@gmail.com>
Sun, 22 Feb 2009 02:42:07 +0000 (03:42 +0100)
committerFrank Li <lznuaa@gmail.com>
Sun, 22 Feb 2009 03:40:36 +0000 (11:40 +0800)
src/Git/Git.cpp
src/Git/Git.h
src/TortoiseShell/ContextMenu.cpp

index 024d6bd..bb32abf 100644 (file)
@@ -333,6 +333,52 @@ CString CGit::GetCurrentBranch(void)
        return CString("");\r
 }\r
 \r
+int CGit::GetCurrentBranchFromFile(const CString &sProjectRoot, CString &sBranchOut)\r
+{\r
+       // read current branch name like git-gui does, by parsing the .git/HEAD file directly\r
+\r
+       if ( sProjectRoot.IsEmpty() )\r
+               return -1;\r
+\r
+       CString sHeadFile = sProjectRoot + _T("\\") + g_GitAdminDir.GetAdminDirName() + _T("\\HEAD");\r
+\r
+       FILE *pFile;\r
+       _tfopen_s(&pFile, sHeadFile.GetString(), _T("r"));\r
+\r
+       if (!pFile)\r
+       {\r
+               return -1;\r
+       }\r
+\r
+       char s[256] = {0};\r
+    fgets(s, sizeof(s), pFile);\r
+\r
+       fclose(pFile);\r
+\r
+       const char *pfx = "ref: refs/heads/";\r
+       const int len = 16;//strlen(pfx)\r
+\r
+       if ( !strncmp(s, pfx, len) )\r
+       {\r
+               //# We're on a branch.  It might not exist.  But\r
+               //# HEAD looks good enough to be a branch.\r
+               sBranchOut = s + len;\r
+               sBranchOut.TrimRight(_T(" \r\n\t"));\r
+\r
+               if ( sBranchOut.IsEmpty() )\r
+                       return -1;\r
+       }\r
+       else\r
+       {\r
+               //# Assume this is a detached head.\r
+               sBranchOut = "HEAD";\r
+\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
 int CGit::BuildOutputFormat(CString &format,bool IsFull)\r
 {\r
        CString log;\r
index a65abc1..487c854 100644 (file)
@@ -47,6 +47,8 @@ public:
        CString GetUserName(void);\r
        CString GetUserEmail(void);\r
        CString GetCurrentBranch(void);\r
+       // read current branch name from HEAD file, returns 0 on success, -1 on failure, 1 detached (branch name "HEAD" returned)\r
+       int GetCurrentBranchFromFile(const CString &sProjectRoot, CString &sBranchOut);\r
        BOOL CheckCleanWorkTree();\r
        int Revert(CTGitPath &path,bool keep=true);\r
        int Revert(CTGitPathList &list,bool keep=true);\r
index fb7db36..d4d7386 100644 (file)
@@ -659,7 +659,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
 \r
 void CShellExt::InsertGitMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, GitCommands com, UINT uFlags)\r
 {\r
-       TCHAR menutextbuffer[255] = {0};\r
+       TCHAR menutextbuffer[512] = {0};\r
        TCHAR verbsbuffer[255] = {0};\r
        MAKESTRING(stringid);\r
 \r
@@ -670,6 +670,61 @@ void CShellExt::InsertGitMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UIN
                _tcscpy_s(menutextbuffer, 255, _T("Git "));\r
        }\r
        _tcscat_s(menutextbuffer, 255, stringtablebuffer);\r
+#if 1\r
+       // insert branch name into "Git Commit..." entry, so it looks like "Git Commit "master"..."\r
+       // so we have an easy and fast way to check the current branch\r
+       // (the other alternative is using a separate disabled menu entry, the code is already done but commented out)\r
+       if (com == ShellMenuCommit)\r
+       {\r
+               // get branch name\r
+               CTGitPath path(folder_.empty() ? files_.front().c_str() : folder_.c_str());\r
+               CString sProjectRoot;\r
+               CString sBranchName;\r
+\r
+               if (path.HasAdminDir(&sProjectRoot) && !g_Git.GetCurrentBranchFromFile(sProjectRoot, sBranchName))\r
+               {\r
+                       if (sBranchName.GetLength() == 40)\r
+                       {\r
+                               // if SHA1 only show 4 first bytes\r
+                               BOOL bIsSha1 = TRUE;\r
+                               for (int i=0; i<40; i++)\r
+                                       if ( !iswxdigit(sBranchName[i]) )\r
+                                       {\r
+                                               bIsSha1 = FALSE;\r
+                                               break;\r
+                                       }\r
+                               if (bIsSha1)\r
+                                       sBranchName = sBranchName.Left(8) + _T("....");\r
+                       }\r
+\r
+                       // sanity check\r
+                       if (sBranchName.GetLength() > 64)\r
+                               sBranchName = sBranchName.Left(64) + _T("...");\r
+\r
+                       // scan to before "..."\r
+                       LPTSTR s = menutextbuffer + _tcslen(menutextbuffer)-1;\r
+                       if (s > menutextbuffer)\r
+                       {\r
+                               while (s > menutextbuffer)\r
+                               {\r
+                                       if (*s != _T('.'))\r
+                                       {\r
+                                               s++;\r
+                                               break;\r
+                                       }\r
+                                       s--;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               s = menutextbuffer;\r
+                       }\r
+\r
+                       // append branch name and end with ...\r
+                       _tcscpy(s, _T(" -> \"") + sBranchName + _T("\"..."));\r
+               }\r
+       }\r
+#endif\r
        if ((fullver < 0x500)||(fullver == 0x500 && !(uFlags&~(CMF_RESERVED|CMF_EXPLORE))))\r
        {\r
                // on win2k, the context menu does not work properly if we use\r
@@ -1096,6 +1151,72 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,
        // ?? TSV disabled icons for win2k and earlier, but they work for win2k and should work for win95 and up\r
        /*if (fullver <= 0x500)\r
                bShowIcons = false;*/\r
+\r
+#if 0\r
+       if (itemStates & (ITEMIS_INSVN|ITEMIS_FOLDERINSVN))\r
+       {\r
+               // show current branch name (as a "read-only" menu entry)\r
+\r
+               CTGitPath path(folder_.empty() ? files_.front().c_str() : folder_.c_str());\r
+               CString sProjectRoot;\r
+               CString sBranchName;\r
+\r
+               if (path.HasAdminDir(&sProjectRoot) && !g_Git.GetCurrentBranchFromFile(sProjectRoot, sBranchName))\r
+               {\r
+                       if (sBranchName.GetLength() == 40)\r
+                       {\r
+                               // if SHA1 only show 4 first bytes\r
+                               BOOL bIsSha1 = TRUE;\r
+                               for (int i=0; i<40; i++)\r
+                                       if ( !iswxdigit(sBranchName[i]) )\r
+                                       {\r
+                                               bIsSha1 = FALSE;\r
+                                               break;\r
+                                       }\r
+                               if (bIsSha1)\r
+                                       sBranchName = sBranchName.Left(8) + _T("....");\r
+                       }\r
+\r
+                       sBranchName = _T('"') + sBranchName + _T('"');\r
+\r
+                       const int icon = IDI_COPY;\r
+                       const int pos = indexMenu++;\r
+                       const int id = idCmd++;\r
+\r
+                       if ((fullver < 0x500)||(fullver == 0x500 && !(uFlags&~(CMF_RESERVED|CMF_EXPLORE))))\r
+                       {\r
+                               InsertMenu(hMenu, pos, MF_DISABLED|MF_GRAYED|MF_BYPOSITION|MF_STRING, id, sBranchName);\r
+                               HBITMAP bmp = IconToBitmap(icon); \r
+                               SetMenuItemBitmaps(hMenu, pos, MF_BYPOSITION, bmp, bmp);\r
+                       }\r
+                       else\r
+                       {\r
+                               MENUITEMINFO menuiteminfo;\r
+                               SecureZeroMemory(&menuiteminfo, sizeof(menuiteminfo));\r
+                               menuiteminfo.cbSize = sizeof(menuiteminfo);\r
+                               menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_STATE;\r
+                               menuiteminfo.fState = MFS_DISABLED;\r
+                               menuiteminfo.fType = MFT_STRING;\r
+                               menuiteminfo.dwTypeData = (LPWSTR)sBranchName.GetString();\r
+                               if (icon)\r
+                               {\r
+                                       menuiteminfo.fMask |= MIIM_BITMAP;\r
+                                       menuiteminfo.hbmpItem = (fullver >= 0x600) ? IconToBitmapPARGB32(icon) : HBMMENU_CALLBACK;\r
+\r
+                                       if (menuiteminfo.hbmpItem == HBMMENU_CALLBACK)\r
+                                       {\r
+                                               // WM_DRAWITEM uses myIDMap to get icon, we use the same icon as create branch\r
+                                               myIDMap[id - idCmdFirst] = ShellMenuBranch;\r
+                                               myIDMap[id] = ShellMenuBranch;\r
+                                       }\r
+                               }\r
+                               menuiteminfo.wID = id;\r
+                               InsertMenuItem(hMenu, pos, TRUE, &menuiteminfo);\r
+                       }\r
+               }\r
+       }\r
+#endif\r
+\r
        while (menuInfo[menuIndex].command != ShellMenuLastEntry)\r
        {\r
                if (menuInfo[menuIndex].command == ShellSeparator)\r