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 ");
229 cmd
.Format(_T("git.exe log %s -C --topo-order --parents %s --pretty=format:\""),
232 BuildOutputFormat(log
);
234 cmd
+= CString(_T("\" "))+hash
+file
;
236 return Run(cmd
,&logOut
);
240 int CGit::GetShortLog(CString
&logOut
,CTGitPath
* path
, int count
)
249 cmd
.Format(_T("git.exe log --left-right --boundary --topo-order -n%d --pretty=format:\""),n
);
250 BuildOutputFormat(log
,false);
253 cmd
+= _T(" -- \"")+path
->GetGitPathString()+_T("\"");
254 //cmd += CString(_T("\" HEAD~40..HEAD"));
255 return Run(cmd
,&logOut
);
259 void GetTempPath(CString
&path
)
261 TCHAR lpPathBuffer
[BUFSIZE
];
263 DWORD dwBufSize
=BUFSIZE
;
264 dwRetVal
= GetTempPath(dwBufSize
, // length of the buffer
265 lpPathBuffer
); // buffer for path
266 if (dwRetVal
> dwBufSize
|| (dwRetVal
== 0))
270 path
.Format(_T("%s"),lpPathBuffer
);
272 CString
GetTempFile()
274 TCHAR lpPathBuffer
[BUFSIZE
];
276 DWORD dwBufSize
=BUFSIZE
;
277 TCHAR szTempName
[BUFSIZE
];
280 dwRetVal
= GetTempPath(dwBufSize
, // length of the buffer
281 lpPathBuffer
); // buffer for path
282 if (dwRetVal
> dwBufSize
|| (dwRetVal
== 0))
286 // Create a temporary file.
287 uRetVal
= GetTempFileName(lpPathBuffer
, // directory for tmp files
288 TEXT("Patch"), // temp file name prefix
289 0, // create unique name
290 szTempName
); // buffer for name
298 return CString(szTempName
);
302 int CGit::RunLogFile(CString cmd
,CString
&filename
)
304 HANDLE hRead
, hWrite
;
307 PROCESS_INFORMATION pi
;
308 si
.cb
=sizeof(STARTUPINFO
);
311 SECURITY_ATTRIBUTES psa
={sizeof(psa
),NULL
,TRUE
};;
312 psa
.bInheritHandle
=TRUE
;
314 HANDLE houtfile
=CreateFile(filename
,GENERIC_WRITE
,FILE_SHARE_READ
| FILE_SHARE_WRITE
,
315 &psa
,CREATE_ALWAYS
,FILE_ATTRIBUTE_NORMAL
,NULL
);
318 si
.wShowWindow
=SW_HIDE
;
319 si
.dwFlags
=STARTF_USESTDHANDLES
|STARTF_USESHOWWINDOW
;
320 si
.hStdOutput
= houtfile
;
322 if(!CreateProcess(NULL
,(LPWSTR
)cmd
.GetString(), NULL
,NULL
,TRUE
,NULL
,NULL
,(LPWSTR
)m_CurrentDir
.GetString(),&si
,&pi
))
325 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
326 NULL
,GetLastError(),MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
329 return GIT_ERROR_CREATE_PROCESS
;
332 WaitForSingleObject(pi
.hProcess
,INFINITE
);
334 CloseHandle(pi
.hThread
);
335 CloseHandle(pi
.hProcess
);
336 CloseHandle(houtfile
);
341 git_revnum_t
CGit::GetHash(CString
&friendname
)
345 cmd
.Format(_T("git.exe rev-parse %s" ),friendname
);
347 int pos
=out
.ReverseFind(_T('\n'));
349 return out
.Left(pos
);
353 int CGit::GetTagList(STRING_VECTOR
&list
)
357 cmd
=_T("git.exe tag -l");
359 ret
=g_Git
.Run(cmd
,&output
);
367 one
=output
.Tokenize(_T("\n"),pos
);
374 int CGit::GetBranchList(STRING_VECTOR
&list
,int *current
,BRANCH_TYPE type
)
378 cmd
=_T("git.exe branch");
380 if(type
==(BRANCH_LOCAL
|BRANCH_REMOTE
))
382 else if(type
==BRANCH_REMOTE
)
386 ret
=g_Git
.Run(cmd
,&output
);
394 one
=output
.Tokenize(_T("\n"),pos
);
395 list
.push_back(one
.Right(one
.GetLength()-2));
396 if(one
[0] == _T('*'))
404 int CGit::GetRemoteList(STRING_VECTOR
&list
)
408 cmd
=_T("git.exe config --get-regexp remote.*.url");
409 ret
=g_Git
.Run(cmd
,&output
);
416 one
=output
.Tokenize(_T("\n"),pos
);
417 int start
=one
.Find(_T("."),0);
421 url
=one
.Right(one
.GetLength()-start
-1);
423 one
=one
.Left(one
.Find(_T("."),0));
431 int CGit::GetMapHashToFriendName(MAP_HASH_NAME
&map
)
435 cmd
=_T("git show-ref -d");
436 ret
=g_Git
.Run(cmd
,&output
);
443 one
=output
.Tokenize(_T("\n"),pos
);
444 int start
=one
.Find(_T(" "),0);
448 name
=one
.Right(one
.GetLength()-start
-1);
451 hash
=one
.Left(start
);
453 map
[hash
].push_back(name
);
460 BOOL
CGit::CheckMsysGitDir()
462 CRegString msysdir
=CRegString(_T("Software\\TortoiseGit\\MSysGit"),_T(""),FALSE
,HKEY_LOCAL_MACHINE
);
466 CRegString msysinstalldir
=CRegString(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1\\InstallLocation"),_T(""),FALSE
,HKEY_LOCAL_MACHINE
);
473 //CGit::m_MsysGitPath=str;
475 TCHAR
*oldpath
,*home
;
478 _tdupenv_s(&home
,&size
,_T("HOME"));
482 _tdupenv_s(&home
,&size
,_T("USERPROFILE"));
483 _tputenv_s(_T("HOME"),home
);
487 _tdupenv_s(&oldpath
,&size
,_T("PATH"));
490 path
.Format(_T("%s;"),str
);
493 _tputenv_s(_T("PATH"),path
);
498 cmd
=_T("git.exe --version");
499 if(g_Git
.Run(cmd
,&out
))