OSDN Git Service

6b880c19c65bc6453fe9738fbbd700638a8b8750
[tortoisegit/TortoiseGitJp.git] / src / Git / Git.cpp
1 #include "StdAfx.h"\r
2 #include "Git.h"\r
3 #include "atlconv.h"\r
4 #include "GitRev.h"\r
5 #include "registry.h"\r
6 #include "GitConfig.h"\r
7 \r
8 \r
9 static LPTSTR nextpath(LPCTSTR src, LPTSTR dst, UINT maxlen)\r
10 {\r
11         LPCTSTR orgsrc;\r
12 \r
13         while (*src == _T(';'))\r
14                 src++;\r
15 \r
16         orgsrc = src;\r
17 \r
18         if (!--maxlen)\r
19                 goto nullterm;\r
20 \r
21         while (*src && *src != _T(';'))\r
22         {\r
23                 if (*src != _T('"'))\r
24                 {\r
25                         *dst++ = *src++;\r
26                         if (!--maxlen)\r
27                         {\r
28                                 orgsrc = src;\r
29                                 goto nullterm;\r
30                         }\r
31                 }\r
32                 else\r
33                 {\r
34                         src++;\r
35                         while (*src && *src != _T('"'))\r
36                         {\r
37                                 *dst++ = *src++;\r
38                                 if (!--maxlen)\r
39                                 {\r
40                                         orgsrc = src;\r
41                                         goto nullterm;\r
42                                 }\r
43                         }\r
44 \r
45                         if (*src)\r
46                                 src++;\r
47                 }\r
48         }\r
49 \r
50         while (*src == _T(';'))\r
51                 src++;\r
52 \r
53 nullterm:\r
54 \r
55         *dst = 0;\r
56 \r
57         return (orgsrc != src) ? (LPTSTR)src : NULL;\r
58 }\r
59 \r
60 static inline BOOL FileExists(LPCTSTR lpszFileName)\r
61 {\r
62         struct _stat st;\r
63         return _tstat(lpszFileName, &st) == 0;\r
64 }\r
65 \r
66 static BOOL FindGitPath()\r
67 {\r
68         size_t size;\r
69         _tgetenv_s(&size, NULL, 0, _T("PATH"));\r
70 \r
71         if (!size)\r
72         {\r
73                 return FALSE;\r
74         }\r
75 \r
76         TCHAR *env = (TCHAR*)alloca(size * sizeof(TCHAR));\r
77         _tgetenv_s(&size, env, size, _T("PATH"));\r
78 \r
79         TCHAR buf[_MAX_PATH];\r
80 \r
81         // search in all paths defined in PATH\r
82         while ((env = nextpath(env, buf, _MAX_PATH-1)) && *buf)\r
83         {\r
84                 TCHAR *pfin = buf + _tcslen(buf)-1;\r
85 \r
86                 // ensure trailing slash\r
87                 if (*pfin != _T('/') && *pfin != _T('\\'))\r
88                         _tcscpy(++pfin, _T("\\"));\r
89 \r
90                 const int len = _tcslen(buf);\r
91 \r
92                 if ((len + 7) < _MAX_PATH)\r
93                         _tcscpy(pfin+1, _T("git.exe"));\r
94                 else\r
95                         break;\r
96 \r
97                 if ( FileExists(buf) )\r
98                 {\r
99                         // dir found\r
100                         return TRUE;\r
101                 }\r
102         }\r
103 \r
104         return FALSE;\r
105 }\r
106 \r
107 \r
108 #define MAX_DIRBUFFER 1000\r
109 CString CGit::ms_LastMsysGitDir;\r
110 CGit g_Git;\r
111 BOOL g_IsWingitDllload = TRUE;\r
112 \r
113 LPBYTE wgGetRevisionID_safe(const char *pszProjectPath, const char *pszName)\r
114 {\r
115         if(g_IsWingitDllload)\r
116                 return wgGetRevisionID(pszProjectPath,pszName);\r
117         else\r
118                 return NULL;\r
119 }\r
120 \r
121 BOOL wgEnumFiles_safe(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
122 {\r
123         if(g_IsWingitDllload)\r
124                 return wgEnumFiles(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);\r
125         else\r
126                 return FALSE;\r
127 }\r
128 \r
129 BOOL CGit::IsVista()\r
130 {\r
131 \r
132         if( CRegStdWORD(_T("Software\\TortoiseGit\\CacheType") ) == 0)\r
133         {\r
134                 g_IsWingitDllload=FALSE;\r
135                 return TRUE;\r
136         }\r
137 \r
138         OSVERSIONINFO osvi;\r
139     BOOL bIsWindowsXPorLater;\r
140 \r
141     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));\r
142     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
143 \r
144     GetVersionEx(&osvi);\r
145         \r
146         if(osvi.dwMajorVersion >= 6)\r
147                 return TRUE;\r
148         else\r
149                 return FALSE;\r
150 }\r
151 \r
152 static void InitWinGitDll()\r
153 {\r
154         __try\r
155         {\r
156 \r
157                 if( CGit::IsVista () )\r
158                 {\r
159                         g_IsWingitDllload=FALSE;\r
160                         return;\r
161                 }\r
162                 if ( !wgInit() )\r
163                 {\r
164                                 // TODO\r
165                 }\r
166         }\r
167         __except(1)\r
168         {\r
169                 g_IsWingitDllload=FALSE;\r
170                 return;\r
171         }\r
172 \r
173 }\r
174 CGit::CGit(void)\r
175 {\r
176         GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER));\r
177         m_CurrentDir.ReleaseBuffer();\r
178         // make sure git/bin is in PATH before wingit.dll gets (delay) loaded by wgInit()\r
179         if ( !CheckMsysGitDir() )\r
180         {\r
181                 // TODO\r
182         }\r
183         InitWinGitDll();\r
184 }\r
185 \r
186 CGit::~CGit(void)\r
187 {\r
188 }\r
189 \r
190 static char g_Buffer[4096];\r
191 \r
192 int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut,CString *StdioFile)\r
193 {\r
194         SECURITY_ATTRIBUTES sa;\r
195         HANDLE hRead, hWrite;\r
196         HANDLE hStdioFile = NULL;\r
197 \r
198         sa.nLength = sizeof(SECURITY_ATTRIBUTES);\r
199         sa.lpSecurityDescriptor=NULL;\r
200         sa.bInheritHandle=TRUE;\r
201         if(!CreatePipe(&hRead,&hWrite,&sa,0))\r
202         {\r
203                 return GIT_ERROR_OPEN_PIP;\r
204         }\r
205         \r
206         if(StdioFile)\r
207         {\r
208                 hStdioFile=CreateFile(*StdioFile,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
209                         &sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);  \r
210         }\r
211 \r
212         STARTUPINFO si;\r
213         PROCESS_INFORMATION pi;\r
214         si.cb=sizeof(STARTUPINFO);\r
215         GetStartupInfo(&si);\r
216 \r
217         si.hStdError=hWrite;\r
218         if(StdioFile)\r
219                 si.hStdOutput=hStdioFile;\r
220         else\r
221                 si.hStdOutput=hWrite;\r
222 \r
223         si.wShowWindow=SW_HIDE;\r
224         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
225 \r
226         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
227         {\r
228                 LPVOID lpMsgBuf;\r
229                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
230                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
231                         (LPTSTR)&lpMsgBuf,\r
232                         0,NULL);\r
233                 return GIT_ERROR_CREATE_PROCESS;\r
234         }\r
235         \r
236         CloseHandle(hWrite);\r
237         if(piOut)\r
238                 *piOut=pi;\r
239         if(hReadOut)\r
240                 *hReadOut=hRead;\r
241         \r
242         return 0;\r
243 \r
244 }\r
245 //Must use sperate function to convert ANSI str to union code string\r
246 //Becuase A2W use stack as internal convert buffer. \r
247 void CGit::StringAppend(CString *str,BYTE *p,int code,int length)\r
248 {\r
249      //USES_CONVERSION;\r
250          //str->Append(A2W_CP((LPCSTR)p,code));\r
251         WCHAR * buf;\r
252 \r
253         int len ;\r
254         if(length<0)\r
255                 len= strlen((const char*)p);\r
256         else\r
257                 len=length;\r
258         //if (len==0)\r
259         //      return ;\r
260         //buf = new WCHAR[len*4 + 1];\r
261         buf = str->GetBuffer(len*4+1+str->GetLength())+str->GetLength();\r
262         SecureZeroMemory(buf, (len*4 + 1)*sizeof(WCHAR));\r
263         MultiByteToWideChar(code, 0, (LPCSTR)p, len, buf, len*4);\r
264         str->ReleaseBuffer();\r
265         //str->Append(buf);\r
266         //delete buf;\r
267 }       \r
268 BOOL CGit::IsInitRepos()\r
269 {\r
270         CString cmdout;\r
271         cmdout.Empty();\r
272         if(g_Git.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout,CP_UTF8))\r
273         {\r
274         //      CMessageBox::Show(NULL,cmdout,_T("TortoiseGit"),MB_OK);\r
275                 return TRUE;\r
276         }\r
277         if(cmdout.IsEmpty())\r
278                 return TRUE;\r
279 \r
280         return FALSE;\r
281 }\r
282 int CGit::Run(CString cmd,BYTE_VECTOR *vector)\r
283 {\r
284         PROCESS_INFORMATION pi;\r
285         HANDLE hRead;\r
286         if(RunAsync(cmd,&pi,&hRead))\r
287                 return GIT_ERROR_CREATE_PROCESS;\r
288 \r
289         DWORD readnumber;\r
290         BYTE data;\r
291         while(ReadFile(hRead,&data,1,&readnumber,NULL))\r
292         {\r
293                 //g_Buffer[readnumber]=0;\r
294                 vector->push_back(data);\r
295 //              StringAppend(output,g_Buffer,codes);\r
296         }\r
297 \r
298         \r
299         CloseHandle(pi.hThread);\r
300 \r
301         WaitForSingleObject(pi.hProcess, INFINITE);\r
302         DWORD exitcode =0;\r
303 \r
304         if(!GetExitCodeProcess(pi.hProcess,&exitcode))\r
305         {\r
306                 return GIT_ERROR_GET_EXIT_CODE;\r
307         }\r
308 \r
309         CloseHandle(pi.hProcess);\r
310 \r
311         CloseHandle(hRead);\r
312         return exitcode;\r
313 \r
314 }\r
315 int CGit::Run(CString cmd, CString* output,int code)\r
316 {\r
317         BYTE_VECTOR vector;\r
318         int ret;\r
319         ret=Run(cmd,&vector);\r
320 \r
321         vector.push_back(0);\r
322         \r
323         StringAppend(output,&(vector[0]),code);\r
324         return ret;\r
325 }\r
326 \r
327 CString CGit::GetUserName(void)\r
328 {\r
329         CString UserName;\r
330         Run(_T("git.exe config user.name"),&UserName,CP_UTF8);\r
331         return UserName;\r
332 }\r
333 CString CGit::GetUserEmail(void)\r
334 {\r
335         CString UserName;\r
336         Run(_T("git.exe config user.email"),&UserName,CP_UTF8);\r
337         return UserName;\r
338 }\r
339 \r
340 CString CGit::GetCurrentBranch(void)\r
341 {\r
342         CString output;\r
343         //Run(_T("git.exe branch"),&branch);\r
344 \r
345         int ret=g_Git.Run(_T("git.exe branch"),&output,CP_UTF8);\r
346         if(!ret)\r
347         {               \r
348                 int pos=0;\r
349                 CString one;\r
350                 while( pos>=0 )\r
351                 {\r
352                         //i++;\r
353                         one=output.Tokenize(_T("\n"),pos);\r
354                         //list.push_back(one.Right(one.GetLength()-2));\r
355                         if(one[0] == _T('*'))\r
356                                 return one.Right(one.GetLength()-2);\r
357                 }\r
358         }\r
359         return CString("");\r
360 }\r
361 \r
362 int CGit::BuildOutputFormat(CString &format,bool IsFull)\r
363 {\r
364         CString log;\r
365         log.Format(_T("#<%c>%%x00"),LOG_REV_ITEM_BEGIN);\r
366         format += log;\r
367         if(IsFull)\r
368         {\r
369                 log.Format(_T("#<%c>%%an%%x00"),LOG_REV_AUTHOR_NAME);\r
370                 format += log;\r
371                 log.Format(_T("#<%c>%%ae%%x00"),LOG_REV_AUTHOR_EMAIL);\r
372                 format += log;\r
373                 log.Format(_T("#<%c>%%ai%%x00"),LOG_REV_AUTHOR_DATE);\r
374                 format += log;\r
375                 log.Format(_T("#<%c>%%cn%%x00"),LOG_REV_COMMIT_NAME);\r
376                 format += log;\r
377                 log.Format(_T("#<%c>%%ce%%x00"),LOG_REV_COMMIT_EMAIL);\r
378                 format += log;\r
379                 log.Format(_T("#<%c>%%ci%%x00"),LOG_REV_COMMIT_DATE);\r
380                 format += log;\r
381                 log.Format(_T("#<%c>%%s%%x00"),LOG_REV_COMMIT_SUBJECT);\r
382                 format += log;\r
383                 log.Format(_T("#<%c>%%b%%x00"),LOG_REV_COMMIT_BODY);\r
384                 format += log;\r
385         }\r
386         log.Format(_T("#<%c>%%m%%H%%x00"),LOG_REV_COMMIT_HASH);\r
387         format += log;\r
388         log.Format(_T("#<%c>%%P%%x00"),LOG_REV_COMMIT_PARENT);\r
389         format += log;\r
390 \r
391         if(IsFull)\r
392         {\r
393                 log.Format(_T("#<%c>%%x00"),LOG_REV_COMMIT_FILE);\r
394                 format += log;\r
395         }\r
396         return 0;\r
397 }\r
398 \r
399 int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash,  CTGitPath *path ,int count,int mask)\r
400 {\r
401 \r
402         CString cmd;\r
403         CString log;\r
404         CString num;\r
405         CString since;\r
406 \r
407         CString file;\r
408 \r
409         if(path)\r
410                 file.Format(_T(" -- \"%s\""),path->GetGitPathString());\r
411         \r
412         if(count>0)\r
413                 num.Format(_T("-n%d"),count);\r
414 \r
415         CString param;\r
416 \r
417         if(mask& LOG_INFO_STAT )\r
418                 param += _T(" --numstat ");\r
419         if(mask& LOG_INFO_FILESTATE)\r
420                 param += _T(" --raw ");\r
421 \r
422         if(mask& LOG_INFO_FULLHISTORY)\r
423                 param += _T(" --full-history ");\r
424 \r
425         if(mask& LOG_INFO_BOUNDARY)\r
426                 param += _T(" --left-right --boundary ");\r
427 \r
428         if(mask& CGit::LOG_INFO_ALL_BRANCH)\r
429                 param += _T(" --all ");\r
430 \r
431         if(mask& CGit::LOG_INFO_DETECT_COPYRENAME)\r
432                 param += _T(" -C ");\r
433         \r
434         if(mask& CGit::LOG_INFO_DETECT_RENAME )\r
435                 param += _T(" -M ");\r
436 \r
437         if(mask& CGit::LOG_INFO_FIRST_PARENT )\r
438                 param += _T(" --first-parent ");\r
439         \r
440         if(mask& CGit::LOG_INFO_NO_MERGE )\r
441                 param += _T(" --no-merges ");\r
442 \r
443         if(mask& CGit::LOG_INFO_FOLLOW)\r
444                 param += _T(" --follow ");\r
445 \r
446         param+=hash;\r
447 \r
448         cmd.Format(_T("git.exe log %s -z --topo-order %s --parents --pretty=format:\""),\r
449                                 num,param);\r
450 \r
451         BuildOutputFormat(log,!(mask&CGit::LOG_INFO_ONLY_HASH));\r
452 \r
453         cmd += log;\r
454         cmd += CString(_T("\"  "))+hash+file;\r
455 \r
456         return Run(cmd,&logOut);\r
457 }\r
458 \r
459 #if 0\r
460 int CGit::GetShortLog(CString &logOut,CTGitPath * path, int count)\r
461 {\r
462         CString cmd;\r
463         CString log;\r
464         int n;\r
465         if(count<0)\r
466                 n=100;\r
467         else\r
468                 n=count;\r
469         cmd.Format(_T("git.exe log --left-right --boundary --topo-order -n%d --pretty=format:\""),n);\r
470         BuildOutputFormat(log,false);\r
471         cmd += log+_T("\"");\r
472         if (path)\r
473                 cmd+= _T("  -- \"")+path->GetGitPathString()+_T("\"");\r
474         //cmd += CString(_T("\" HEAD~40..HEAD"));\r
475         return Run(cmd,&logOut);\r
476 }\r
477 #endif\r
478 \r
479 #define BUFSIZE 512\r
480 void GetTempPath(CString &path)\r
481 {\r
482         TCHAR lpPathBuffer[BUFSIZE];\r
483         DWORD dwRetVal;\r
484         DWORD dwBufSize=BUFSIZE;\r
485         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
486                            lpPathBuffer); // buffer for path \r
487     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
488     {\r
489         path=_T("");\r
490     }\r
491         path.Format(_T("%s"),lpPathBuffer);\r
492 }\r
493 CString GetTempFile()\r
494 {\r
495         TCHAR lpPathBuffer[BUFSIZE];\r
496         DWORD dwRetVal;\r
497     DWORD dwBufSize=BUFSIZE;\r
498         TCHAR szTempName[BUFSIZE];  \r
499         UINT uRetVal;\r
500 \r
501         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
502                            lpPathBuffer); // buffer for path \r
503     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
504     {\r
505         return _T("");\r
506     }\r
507          // Create a temporary file. \r
508     uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files\r
509                               TEXT("Patch"),  // temp file name prefix \r
510                               0,            // create unique name \r
511                               szTempName);  // buffer for name \r
512 \r
513 \r
514     if (uRetVal == 0)\r
515     {\r
516         return _T("");\r
517     }\r
518 \r
519         return CString(szTempName);\r
520 \r
521 }\r
522 \r
523 int CGit::RunLogFile(CString cmd,CString &filename)\r
524 {\r
525         STARTUPINFO si;\r
526         PROCESS_INFORMATION pi;\r
527         si.cb=sizeof(STARTUPINFO);\r
528         GetStartupInfo(&si);\r
529 \r
530         SECURITY_ATTRIBUTES   psa={sizeof(psa),NULL,TRUE};;   \r
531         psa.bInheritHandle=TRUE;   \r
532     \r
533         HANDLE   houtfile=CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
534                         &psa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);   \r
535 \r
536 \r
537         si.wShowWindow=SW_HIDE;\r
538         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
539         si.hStdOutput   =   houtfile; \r
540         \r
541         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
542         {\r
543                 LPVOID lpMsgBuf;\r
544                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
545                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
546                         (LPTSTR)&lpMsgBuf,\r
547                         0,NULL);\r
548                 return GIT_ERROR_CREATE_PROCESS;\r
549         }\r
550         \r
551         WaitForSingleObject(pi.hProcess,INFINITE);   \r
552         \r
553         CloseHandle(pi.hThread);\r
554         CloseHandle(pi.hProcess);\r
555         CloseHandle(houtfile);\r
556         return GIT_SUCCESS;\r
557 //      return 0;\r
558 }\r
559 \r
560 git_revnum_t CGit::GetHash(CString &friendname)\r
561 {\r
562         // NOTE: could replace this with wgGetRevisionID call\r
563 \r
564         CString cmd;\r
565         CString out;\r
566         cmd.Format(_T("git.exe rev-parse %s" ),friendname);\r
567         Run(cmd,&out,CP_UTF8);\r
568         int pos=out.ReverseFind(_T('\n'));\r
569         if(pos>0)\r
570                 return out.Left(pos);\r
571         return out;\r
572 }\r
573 \r
574 int CGit::GetTagList(STRING_VECTOR &list)\r
575 {\r
576         int ret;\r
577         CString cmd,output;\r
578         cmd=_T("git.exe tag -l");\r
579         int i=0;\r
580         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
581         if(!ret)\r
582         {               \r
583                 int pos=0;\r
584                 CString one;\r
585                 while( pos>=0 )\r
586                 {\r
587                         i++;\r
588                         one=output.Tokenize(_T("\n"),pos);\r
589                         list.push_back(one);\r
590                 }\r
591         }\r
592         return ret;\r
593 }\r
594 \r
595 int CGit::GetBranchList(STRING_VECTOR &list,int *current,BRANCH_TYPE type)\r
596 {\r
597         int ret;\r
598         CString cmd,output;\r
599         cmd=_T("git.exe branch");\r
600 \r
601         if(type==(BRANCH_LOCAL|BRANCH_REMOTE))\r
602                 cmd+=_T(" -a");\r
603         else if(type==BRANCH_REMOTE)\r
604                 cmd+=_T(" -r");\r
605 \r
606         int i=0;\r
607         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
608         if(!ret)\r
609         {               \r
610                 int pos=0;\r
611                 CString one;\r
612                 while( pos>=0 )\r
613                 {\r
614                         one=output.Tokenize(_T("\n"),pos);\r
615                         list.push_back(one.Right(one.GetLength()-2));\r
616                         if(one[0] == _T('*'))\r
617                                 if(current)\r
618                                         *current=i;\r
619                         i++;\r
620                 }\r
621         }\r
622         return ret;\r
623 }\r
624 \r
625 int CGit::GetRemoteList(STRING_VECTOR &list)\r
626 {\r
627         int ret;\r
628         CString cmd,output;\r
629         cmd=_T("git.exe config  --get-regexp remote.*.url");\r
630         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
631         if(!ret)\r
632         {\r
633                 int pos=0;\r
634                 CString one;\r
635                 while( pos>=0 )\r
636                 {\r
637                         one=output.Tokenize(_T("\n"),pos);\r
638                         int start=one.Find(_T("."),0);\r
639                         if(start>0)\r
640                         {\r
641                                 CString url;\r
642                                 url=one.Right(one.GetLength()-start-1);\r
643                                 one=url;\r
644                                 one=one.Left(one.Find(_T("."),0));\r
645                                 list.push_back(one);\r
646                         }\r
647                 }\r
648         }\r
649         return ret;\r
650 }\r
651 \r
652 int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map)\r
653 {\r
654         int ret;\r
655         CString cmd,output;\r
656         cmd=_T("git show-ref -d");\r
657         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
658         if(!ret)\r
659         {\r
660                 int pos=0;\r
661                 CString one;\r
662                 while( pos>=0 )\r
663                 {\r
664                         one=output.Tokenize(_T("\n"),pos);\r
665                         int start=one.Find(_T(" "),0);\r
666                         if(start>0)\r
667                         {\r
668                                 CString name;\r
669                                 name=one.Right(one.GetLength()-start-1);\r
670 \r
671                                 CString hash;\r
672                                 hash=one.Left(start);\r
673 \r
674                                 map[hash].push_back(name);\r
675                         }\r
676                 }\r
677         }\r
678         return ret;\r
679 }\r
680 \r
681 BOOL CGit::CheckMsysGitDir()\r
682 {\r
683         static BOOL bInitialized = FALSE;\r
684 \r
685         if (bInitialized)\r
686         {\r
687                 return TRUE;\r
688         }\r
689 \r
690         TCHAR *oldpath,*home;\r
691         size_t size;\r
692 \r
693         // set HOME if not set already\r
694         _tgetenv_s(&size, NULL, 0, _T("HOME"));\r
695         if (!size)\r
696         {\r
697                 _tdupenv_s(&home,&size,_T("USERPROFILE")); \r
698                 _tputenv_s(_T("HOME"),home);\r
699                 free(home);\r
700         }\r
701 \r
702         //setup ssh client\r
703         CRegString sshclient=CRegString(_T("Software\\TortoiseGit\\SSH"));\r
704         CString ssh=sshclient;\r
705 \r
706         if(!ssh.IsEmpty())\r
707         {\r
708                 _tputenv_s(_T("GIT_SSH"),ssh);\r
709         }else\r
710         {\r
711                 _tputenv_s(_T("GIT_SSH"),_T(""));\r
712         }\r
713 \r
714         // search PATH if git/bin directory is alredy present\r
715         if ( FindGitPath() )\r
716         {\r
717                 bInitialized = TRUE;\r
718                 return TRUE;\r
719         }\r
720 \r
721         // add git/bin path to PATH\r
722 \r
723         CRegString msysdir=CRegString(REG_MSYSGIT_PATH,_T(""),FALSE,HKEY_LOCAL_MACHINE);\r
724         CString str=msysdir;\r
725         if(str.IsEmpty())\r
726         {\r
727                 CRegString msysinstalldir=CRegString(REG_MSYSGIT_INSTALL,_T(""),FALSE,HKEY_LOCAL_MACHINE);\r
728                 str=msysinstalldir;\r
729                 if ( !str.IsEmpty() )\r
730                 {\r
731                         str += (str[str.GetLength()-1] != '\\') ? "\\bin" : "bin";\r
732                         msysdir=str;\r
733                         msysdir.write();\r
734                 }\r
735                 else\r
736                 {\r
737                         return false;\r
738                 }\r
739         }\r
740         //CGit::m_MsysGitPath=str;\r
741 \r
742         //set path\r
743 \r
744         _tdupenv_s(&oldpath,&size,_T("PATH")); \r
745 \r
746         CString path;\r
747         path.Format(_T("%s;%s"),oldpath,str);\r
748 \r
749         _tputenv_s(_T("PATH"),path);\r
750 \r
751         free(oldpath);\r
752 \r
753 \r
754     if( !FindGitPath() )\r
755         {\r
756                 return false;\r
757         }\r
758         else\r
759         {\r
760                 bInitialized = TRUE;\r
761                 return true;\r
762         }\r
763 }\r