OSDN Git Service

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