7 #define MAX_DIRBUFFER 1000
11 GetCurrentDirectory(MAX_DIRBUFFER
,m_CurrentDir
.GetBuffer(MAX_DIRBUFFER
));
18 static char g_Buffer
[4096];
20 int CGit::RunAsync(CString cmd
,PROCESS_INFORMATION
*piOut
,HANDLE
*hReadOut
,CString
*StdioFile
)
22 SECURITY_ATTRIBUTES sa
;
26 sa
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
27 sa
.lpSecurityDescriptor
=NULL
;
28 sa
.bInheritHandle
=TRUE
;
29 if(!CreatePipe(&hRead
,&hWrite
,&sa
,0))
31 return GIT_ERROR_OPEN_PIP
;
36 hStdioFile
=CreateFile(*StdioFile
,GENERIC_WRITE
,FILE_SHARE_READ
| FILE_SHARE_WRITE
,
37 &sa
,CREATE_ALWAYS
,FILE_ATTRIBUTE_NORMAL
,NULL
);
41 PROCESS_INFORMATION pi
;
42 si
.cb
=sizeof(STARTUPINFO
);
47 si
.hStdOutput
=hStdioFile
;
51 si
.wShowWindow
=SW_HIDE
;
52 si
.dwFlags
=STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
;
54 if(!CreateProcess(NULL
,(LPWSTR
)cmd
.GetString(), NULL
,NULL
,TRUE
,NULL
,NULL
,(LPWSTR
)m_CurrentDir
.GetString(),&si
,&pi
))
57 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
58 NULL
,GetLastError(),MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
61 return GIT_ERROR_CREATE_PROCESS
;
73 //Must use sperate function to convert ANSI str to union code string
74 //Becuase A2W use stack as internal convert buffer.
75 void CGit::StringAppend(CString
*str
,char *p
)
78 str
->Append(A2W_CP(p
,CP_UTF8
));
81 BOOL
CGit::IsInitRepos()
85 if(g_Git
.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout
))
87 // CMessageBox::Show(NULL,cmdout,_T("TortoiseGit"),MB_OK);
95 int CGit::Run(CString cmd
, CString
* output
)
97 PROCESS_INFORMATION pi
;
99 if(RunAsync(cmd
,&pi
,&hRead
))
100 return GIT_ERROR_CREATE_PROCESS
;
103 while(ReadFile(hRead
,g_Buffer
,1023,&readnumber
,NULL
))
105 g_Buffer
[readnumber
]=0;
106 StringAppend(output
,g_Buffer
);
110 CloseHandle(pi
.hThread
);
112 WaitForSingleObject(pi
.hProcess
, INFINITE
);
115 if(!GetExitCodeProcess(pi
.hProcess
,&exitcode
))
117 return GIT_ERROR_GET_EXIT_CODE
;
120 CloseHandle(pi
.hProcess
);
126 CString
CGit::GetUserName(void)
129 Run(_T("git.exe config user.name"),&UserName
);
132 CString
CGit::GetUserEmail(void)
135 Run(_T("git.exe config user.email"),&UserName
);
139 CString
CGit::GetCurrentBranch(void)
142 //Run(_T("git.exe branch"),&branch);
144 int ret
=g_Git
.Run(_T("git.exe branch"),&output
);
152 one
=output
.Tokenize(_T("\n"),pos
);
153 //list.push_back(one.Right(one.GetLength()-2));
154 if(one
[0] == _T('*'))
155 return one
.Right(one
.GetLength()-2);
161 int CGit::BuildOutputFormat(CString
&format
,bool IsFull
)
164 log
.Format(_T("#<%c>%%n"),LOG_REV_ITEM_BEGIN
);
168 log
.Format(_T("#<%c>%%an%%n"),LOG_REV_AUTHOR_NAME
);
170 log
.Format(_T("#<%c>%%ae%%n"),LOG_REV_AUTHOR_EMAIL
);
172 log
.Format(_T("#<%c>%%ai%%n"),LOG_REV_AUTHOR_DATE
);
174 log
.Format(_T("#<%c>%%cn%%n"),LOG_REV_COMMIT_NAME
);
176 log
.Format(_T("#<%c>%%ce%%n"),LOG_REV_COMMIT_EMAIL
);
178 log
.Format(_T("#<%c>%%ci%%n"),LOG_REV_COMMIT_DATE
);
180 log
.Format(_T("#<%c>%%s%%n"),LOG_REV_COMMIT_SUBJECT
);
182 log
.Format(_T("#<%c>%%b%%n"),LOG_REV_COMMIT_BODY
);
185 log
.Format(_T("#<%c>%%m%%H%%n"),LOG_REV_COMMIT_HASH
);
187 log
.Format(_T("#<%c>%%P%%n"),LOG_REV_COMMIT_PARENT
);
192 log
.Format(_T("#<%c>%%n"),LOG_REV_COMMIT_FILE
);
198 int CGit::GetLog(CString
& logOut
, CString
&hash
, CTGitPath
*path
,int count
,int mask
)
209 file
.Format(_T(" -- \"%s\""),path
->GetGitPathString());
212 num
.Format(_T("-n%d"),count
);
216 if(mask
& LOG_INFO_STAT
)
217 param
+= _T(" --numstat ");
218 if(mask
& LOG_INFO_FILESTATE
)
219 param
+= _T(" --raw ");
221 if(mask
& LOG_INFO_FULLHISTORY
)
222 param
+= _T(" --full-history ");
224 if(mask
& LOG_INFO_BOUNDARY
)
225 param
+= _T(" --left-right --boundary ");
227 if(mask
& CGit::LOG_INFO_ALL_BRANCH
)
228 param
+= _T(" --all ");
230 if(mask
& CGit::LOG_INFO_DETECT_COPYRENAME
)
233 if(mask
& CGit::LOG_INFO_DETECT_RENAME
)
238 cmd
.Format(_T("git.exe log %s --topo-order --parents %s --pretty=format:\""),
241 BuildOutputFormat(log
,!(mask
&CGit::LOG_INFO_ONLY_HASH
));
244 cmd
+= CString(_T("\" "))+hash
+file
;
246 return Run(cmd
,&logOut
);
250 int CGit::GetShortLog(CString
&logOut
,CTGitPath
* path
, int count
)
259 cmd
.Format(_T("git.exe log --left-right --boundary --topo-order -n%d --pretty=format:\""),n
);
260 BuildOutputFormat(log
,false);
263 cmd
+= _T(" -- \"")+path
->GetGitPathString()+_T("\"");
264 //cmd += CString(_T("\" HEAD~40..HEAD"));
265 return Run(cmd
,&logOut
);
270 void GetTempPath(CString
&path
)
272 TCHAR lpPathBuffer
[BUFSIZE
];
274 DWORD dwBufSize
=BUFSIZE
;
275 dwRetVal
= GetTempPath(dwBufSize
, // length of the buffer
276 lpPathBuffer
); // buffer for path
277 if (dwRetVal
> dwBufSize
|| (dwRetVal
== 0))
281 path
.Format(_T("%s"),lpPathBuffer
);
283 CString
GetTempFile()
285 TCHAR lpPathBuffer
[BUFSIZE
];
287 DWORD dwBufSize
=BUFSIZE
;
288 TCHAR szTempName
[BUFSIZE
];
291 dwRetVal
= GetTempPath(dwBufSize
, // length of the buffer
292 lpPathBuffer
); // buffer for path
293 if (dwRetVal
> dwBufSize
|| (dwRetVal
== 0))
297 // Create a temporary file.
298 uRetVal
= GetTempFileName(lpPathBuffer
, // directory for tmp files
299 TEXT("Patch"), // temp file name prefix
300 0, // create unique name
301 szTempName
); // buffer for name
309 return CString(szTempName
);
313 int CGit::RunLogFile(CString cmd
,CString
&filename
)
315 HANDLE hRead
, hWrite
;
318 PROCESS_INFORMATION pi
;
319 si
.cb
=sizeof(STARTUPINFO
);
322 SECURITY_ATTRIBUTES psa
={sizeof(psa
),NULL
,TRUE
};;
323 psa
.bInheritHandle
=TRUE
;
325 HANDLE houtfile
=CreateFile(filename
,GENERIC_WRITE
,FILE_SHARE_READ
| FILE_SHARE_WRITE
,
326 &psa
,CREATE_ALWAYS
,FILE_ATTRIBUTE_NORMAL
,NULL
);
329 si
.wShowWindow
=SW_HIDE
;
330 si
.dwFlags
=STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
;
331 si
.hStdOutput
= houtfile
;
333 if(!CreateProcess(NULL
,(LPWSTR
)cmd
.GetString(), NULL
,NULL
,TRUE
,NULL
,NULL
,(LPWSTR
)m_CurrentDir
.GetString(),&si
,&pi
))
336 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
337 NULL
,GetLastError(),MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
340 return GIT_ERROR_CREATE_PROCESS
;
343 WaitForSingleObject(pi
.hProcess
,INFINITE
);
345 CloseHandle(pi
.hThread
);
346 CloseHandle(pi
.hProcess
);
347 CloseHandle(houtfile
);
352 git_revnum_t
CGit::GetHash(CString
&friendname
)
356 cmd
.Format(_T("git.exe rev-parse %s" ),friendname
);
358 int pos
=out
.ReverseFind(_T('\n'));
360 return out
.Left(pos
);
364 int CGit::GetTagList(STRING_VECTOR
&list
)
368 cmd
=_T("git.exe tag -l");
370 ret
=g_Git
.Run(cmd
,&output
);
378 one
=output
.Tokenize(_T("\n"),pos
);
385 int CGit::GetBranchList(STRING_VECTOR
&list
,int *current
,BRANCH_TYPE type
)
389 cmd
=_T("git.exe branch");
391 if(type
==(BRANCH_LOCAL
|BRANCH_REMOTE
))
393 else if(type
==BRANCH_REMOTE
)
397 ret
=g_Git
.Run(cmd
,&output
);
405 one
=output
.Tokenize(_T("\n"),pos
);
406 list
.push_back(one
.Right(one
.GetLength()-2));
407 if(one
[0] == _T('*'))
415 int CGit::GetRemoteList(STRING_VECTOR
&list
)
419 cmd
=_T("git.exe config --get-regexp remote.*.url");
420 ret
=g_Git
.Run(cmd
,&output
);
427 one
=output
.Tokenize(_T("\n"),pos
);
428 int start
=one
.Find(_T("."),0);
432 url
=one
.Right(one
.GetLength()-start
-1);
434 one
=one
.Left(one
.Find(_T("."),0));
442 int CGit::GetMapHashToFriendName(MAP_HASH_NAME
&map
)
446 cmd
=_T("git show-ref -d");
447 ret
=g_Git
.Run(cmd
,&output
);
454 one
=output
.Tokenize(_T("\n"),pos
);
455 int start
=one
.Find(_T(" "),0);
459 name
=one
.Right(one
.GetLength()-start
-1);
462 hash
=one
.Left(start
);
464 map
[hash
].push_back(name
);
471 BOOL
CGit::CheckMsysGitDir()
473 CRegString msysdir
=CRegString(_T("Software\\TortoiseGit\\MSysGit"),_T(""),FALSE
,HKEY_LOCAL_MACHINE
);
477 CRegString msysinstalldir
=CRegString(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1\\InstallLocation"),_T(""),FALSE
,HKEY_LOCAL_MACHINE
);
484 //CGit::m_MsysGitPath=str;
486 TCHAR
*oldpath
,*home
;
489 _tdupenv_s(&home
,&size
,_T("HOME"));
493 _tdupenv_s(&home
,&size
,_T("USERPROFILE"));
494 _tputenv_s(_T("HOME"),home
);
498 _tdupenv_s(&oldpath
,&size
,_T("PATH"));
501 path
.Format(_T("%s;"),str
);
504 _tputenv_s(_T("PATH"),path
);
509 cmd
=_T("git.exe --version");
510 if(g_Git
.Run(cmd
,&out
))