OSDN Git Service

Add external diff merge and udiff Setting at setting Page
[tortoisegit/TortoiseGitJp.git] / src / Git / Git.cpp
index 8b58778..2733a88 100644 (file)
@@ -120,27 +120,6 @@ CGit g_Git;
 static LPTSTR l_processEnv = NULL;\r
 \r
 \r
-BOOL CGit::IsVista()\r
-{\r
-\r
-       if( CRegStdWORD(_T("Software\\TortoiseGit\\CacheType") ) == 0)\r
-       {\r
-               return TRUE;\r
-       }\r
-\r
-       OSVERSIONINFO osvi;\r
-    BOOL bIsWindowsXPorLater;\r
-\r
-    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));\r
-    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
-\r
-    GetVersionEx(&osvi);\r
-       \r
-       if(osvi.dwMajorVersion >= 6)\r
-               return TRUE;\r
-       else\r
-               return FALSE;\r
-}\r
 \r
 CGit::CGit(void)\r
 {\r
@@ -354,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
@@ -574,7 +599,8 @@ git_revnum_t CGit::GetHash(CString &friendname)
        CString out;\r
        cmd.Format(_T("git.exe rev-parse %s" ),friendname);\r
        Run(cmd,&out,CP_UTF8);\r
-       int pos=out.ReverseFind(_T('\n'));\r
+//     int pos=out.ReverseFind(_T('\n'));\r
+       int pos=out.FindOneOf(_T("\r\n"));\r
        if(pos>0)\r
                return out.Left(pos);\r
        return out;\r
@@ -782,7 +808,7 @@ BOOL CGit::CheckMsysGitDir()
 class CGitCall_EnumFiles : public CGitCall\r
 {\r
 public:\r
-       CGitCall_EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
+       CGitCall_EnumFiles(const TCHAR *pszProjectPath, const TCHAR *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
        :       m_pszProjectPath(pszProjectPath),\r
                m_pszSubPath(pszSubPath),\r
                m_nFlags(nFlags),\r
@@ -793,8 +819,8 @@ public:
 \r
        typedef std::map<CStringA,char> TStrCharMap;\r
 \r
-       const char *    m_pszProjectPath;\r
-       const char *    m_pszSubPath;\r
+       const TCHAR *   m_pszProjectPath;\r
+       const TCHAR *   m_pszSubPath;\r
        unsigned int    m_nFlags;\r
        WGENUMFILECB *  m_pEnumCb;\r
        void *                  m_pUserData;\r
@@ -842,6 +868,9 @@ public:
                fileStatus.nFlags = 0;\r
                if (*line == 'D')\r
                        fileStatus.nFlags |= WGFF_Directory;\r
+               else if (*line != 'F')\r
+                       // parse error\r
+                       return false;\r
                line += 2;\r
 \r
                // status\r
@@ -858,6 +887,10 @@ public:
                case 'I': fileStatus.nStatus = WGFS_Ignored; break;\r
                case 'U': fileStatus.nStatus = WGFS_Unversioned; break;\r
                case 'E': fileStatus.nStatus = WGFS_Empty; break;\r
+               case '?': fileStatus.nStatus = WGFS_Unknown; break;\r
+               default:\r
+                       // parse error\r
+                       return false;\r
                }\r
                line += 2;\r
 \r
@@ -869,7 +902,7 @@ public:
                {\r
                        for (int i=0; i<20; i++)\r
                        {\r
-                               sha1[i] = (HexChar(line[0]) << 8) | HexChar(line[1]);\r
+                               sha1[i] = (BYTE)((HexChar(line[0]) << 8) | HexChar(line[1]));\r
                                line += 2;\r
                        }\r
 \r
@@ -877,16 +910,23 @@ public:
                }\r
 \r
                // filename\r
-               fileStatus.sFileName = line;\r
+               int len = strlen(line);\r
+               if (len && len < 2048)\r
+               {\r
+                       WCHAR *buf = (WCHAR*)alloca((len*4+2)*sizeof(WCHAR));\r
+                       *buf = 0;\r
+                       MultiByteToWideChar(CP_ACP, 0, line, len+1, buf, len*4+1);\r
+                       fileStatus.sFileName = buf;\r
 \r
-               if ( (*m_pEnumCb)(&fileStatus,m_pUserData) )\r
-                       return false;\r
+                       if (*buf && (*m_pEnumCb)(&fileStatus,m_pUserData))\r
+                               return false;\r
+               }\r
 \r
                return true;\r
        }\r
 };\r
 \r
-BOOL CGit::EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
+BOOL CGit::EnumFiles(const TCHAR *pszProjectPath, const TCHAR *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
 {\r
        if(!pszProjectPath || *pszProjectPath=='\0')\r
                return FALSE;\r
@@ -902,7 +942,7 @@ BOOL CGit::EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigne
        SetCurrentDirectoryA(W_szToDir);\r
        GetCurrentDirectoryA(sizeof(W_szToDir)-1,W_szToDir);\r
 */\r
-       SetCurrentDir(CUnicodeUtils::GetUnicode(pszProjectPath));\r
+       SetCurrentDir(pszProjectPath);\r
 \r
        CString sMode;\r
        if (nFlags)\r
@@ -920,9 +960,9 @@ BOOL CGit::EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigne
        }\r
 \r
        if (pszSubPath)\r
-               cmd.Format(_T("igit.exe \"%s\" status %s \"%s\""), CUnicodeUtils::GetUnicode(pszProjectPath), sMode, CUnicodeUtils::GetUnicode(pszSubPath));\r
+               cmd.Format(_T("igit.exe \"%s\" status %s \"%s\""), pszProjectPath, sMode, pszSubPath);\r
        else\r
-               cmd.Format(_T("igit.exe \"%s\" status %s"), CUnicodeUtils::GetUnicode(pszProjectPath), sMode);\r
+               cmd.Format(_T("igit.exe \"%s\" status %s"), pszProjectPath, sMode);\r
 \r
        W_GitCall.SetCmd(cmd);\r
        // NOTE: should igit get added as a part of msysgit then use below line instead of the above one\r
@@ -956,4 +996,62 @@ BOOL CGit::CheckCleanWorkTree()
                return FALSE;\r
 \r
        return TRUE;\r
+}\r
+int CGit::Revert(CTGitPathList &list,bool keep)\r
+{\r
+       int ret;\r
+       for(int i=0;i<list.GetCount();i++)\r
+       {       \r
+               ret = Revert((CTGitPath&)list[i],keep);\r
+               if(ret)\r
+                       return ret;\r
+       }\r
+       return 0;\r
+}\r
+int CGit::Revert(CTGitPath &path,bool keep)\r
+{\r
+       CString cmd, out;\r
+       if(path.m_Action & CTGitPath::LOGACTIONS_ADDED)\r
+       {       //To init git repository, there are not HEAD, so we can use git reset command\r
+               cmd.Format(_T("git.exe rm --cache -- \"%s\""),path.GetGitPathString());\r
+               if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+                       return -1;\r
+       }\r
+       else if(path.m_Action & CTGitPath::LOGACTIONS_REPLACED )\r
+       {\r
+               cmd.Format(_T("git.exe mv \"%s\" \"%s\""),path.GetGitPathString(),path.GetGitOldPathString());\r
+               if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+                       return -1;\r
+               \r
+               cmd.Format(_T("git.exe checkout HEAD -f -- \"%s\""),path.GetGitOldPathString());\r
+               if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+                       return -1;\r
+       }\r
+       else\r
+       {\r
+               cmd.Format(_T("git.exe checkout HEAD -f -- \"%s\""),path.GetGitPathString());\r
+               if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+                       return -1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+int CGit::ListConflictFile(CTGitPathList &list,CTGitPath *path)\r
+{\r
+       BYTE_VECTOR vector;\r
+\r
+       CString cmd;\r
+       if(path)\r
+               cmd.Format(_T("git.exe ls-files -u -t -z -- \"%s\""),path->GetGitPathString());\r
+       else\r
+               cmd=_T("git.exe ls-files -u -t -z");\r
+\r
+       if(g_Git.Run(cmd,&vector))\r
+       {\r
+               return -1;\r
+       }\r
+\r
+       list.ParserFromLsFile(vector);\r
+\r
+       return 0;\r
 }
\ No newline at end of file