OSDN Git Service

Compiler warnings removal Numerous tweaks to remove compiler warnings where solution...
[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 #define MAX_DIRBUFFER 1000\r
9 CGit g_Git;\r
10 CGit::CGit(void)\r
11 {\r
12         GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER));\r
13 }\r
14 \r
15 CGit::~CGit(void)\r
16 {\r
17 }\r
18 \r
19 static char g_Buffer[4096];\r
20 \r
21 int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut,CString *StdioFile)\r
22 {\r
23         SECURITY_ATTRIBUTES sa;\r
24         HANDLE hRead, hWrite;\r
25         HANDLE hStdioFile;\r
26 \r
27         sa.nLength = sizeof(SECURITY_ATTRIBUTES);\r
28         sa.lpSecurityDescriptor=NULL;\r
29         sa.bInheritHandle=TRUE;\r
30         if(!CreatePipe(&hRead,&hWrite,&sa,0))\r
31         {\r
32                 return GIT_ERROR_OPEN_PIP;\r
33         }\r
34         \r
35         if(StdioFile)\r
36         {\r
37                 hStdioFile=CreateFile(*StdioFile,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
38                         &sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);  \r
39         }\r
40 \r
41         STARTUPINFO si;\r
42         PROCESS_INFORMATION pi;\r
43         si.cb=sizeof(STARTUPINFO);\r
44         GetStartupInfo(&si);\r
45 \r
46         si.hStdError=hWrite;\r
47         if(StdioFile)\r
48                 si.hStdOutput=hStdioFile;\r
49         else\r
50                 si.hStdOutput=hWrite;\r
51 \r
52         si.wShowWindow=SW_HIDE;\r
53         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
54 \r
55         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
56         {\r
57                 LPVOID lpMsgBuf;\r
58                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
59                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
60                         (LPTSTR)&lpMsgBuf,\r
61                         0,NULL);\r
62                 return GIT_ERROR_CREATE_PROCESS;\r
63         }\r
64         \r
65         CloseHandle(hWrite);\r
66         if(piOut)\r
67                 *piOut=pi;\r
68         if(hReadOut)\r
69                 *hReadOut=hRead;\r
70         \r
71         return 0;\r
72 \r
73 }\r
74 //Must use sperate function to convert ANSI str to union code string\r
75 //Becuase A2W use stack as internal convert buffer. \r
76 void CGit::StringAppend(CString *str,BYTE *p,int code)\r
77 {\r
78        USES_CONVERSION;\r
79        str->Append(A2W_CP((LPCSTR)p,code));\r
80 \r
81 }       \r
82 BOOL CGit::IsInitRepos()\r
83 {\r
84         CString cmdout;\r
85         cmdout.Empty();\r
86         if(g_Git.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout,CP_UTF8))\r
87         {\r
88         //      CMessageBox::Show(NULL,cmdout,_T("TortoiseGit"),MB_OK);\r
89                 return TRUE;\r
90         }\r
91         if(cmdout.IsEmpty())\r
92                 return TRUE;\r
93 \r
94         return FALSE;\r
95 }\r
96 int CGit::Run(CString cmd,BYTE_VECTOR *vector)\r
97 {\r
98         PROCESS_INFORMATION pi;\r
99         HANDLE hRead;\r
100         if(RunAsync(cmd,&pi,&hRead))\r
101                 return GIT_ERROR_CREATE_PROCESS;\r
102 \r
103         DWORD readnumber;\r
104         BYTE data;\r
105         while(ReadFile(hRead,&data,1,&readnumber,NULL))\r
106         {\r
107                 //g_Buffer[readnumber]=0;\r
108                 vector->push_back(data);\r
109 //              StringAppend(output,g_Buffer,codes);\r
110         }\r
111 \r
112         \r
113         CloseHandle(pi.hThread);\r
114 \r
115         WaitForSingleObject(pi.hProcess, INFINITE);\r
116         DWORD exitcode =0;\r
117 \r
118         if(!GetExitCodeProcess(pi.hProcess,&exitcode))\r
119         {\r
120                 return GIT_ERROR_GET_EXIT_CODE;\r
121         }\r
122 \r
123         CloseHandle(pi.hProcess);\r
124 \r
125         CloseHandle(hRead);\r
126         return exitcode;\r
127 \r
128 }\r
129 int CGit::Run(CString cmd, CString* output,int code)\r
130 {\r
131         BYTE_VECTOR vector;\r
132         int ret;\r
133         ret=Run(cmd,&vector);\r
134 \r
135         if(ret)\r
136                 return ret;\r
137         \r
138         vector.push_back(0);\r
139         StringAppend(output,&(vector[0]),code);\r
140         return 0;\r
141 }\r
142 \r
143 CString CGit::GetUserName(void)\r
144 {\r
145         CString UserName;\r
146         Run(_T("git.exe config user.name"),&UserName,CP_UTF8);\r
147         return UserName;\r
148 }\r
149 CString CGit::GetUserEmail(void)\r
150 {\r
151         CString UserName;\r
152         Run(_T("git.exe config user.email"),&UserName,CP_UTF8);\r
153         return UserName;\r
154 }\r
155 \r
156 CString CGit::GetCurrentBranch(void)\r
157 {\r
158         CString output;\r
159         //Run(_T("git.exe branch"),&branch);\r
160 \r
161         int ret=g_Git.Run(_T("git.exe branch"),&output,CP_UTF8);\r
162         if(!ret)\r
163         {               \r
164                 int pos=0;\r
165                 CString one;\r
166                 while( pos>=0 )\r
167                 {\r
168                         //i++;\r
169                         one=output.Tokenize(_T("\n"),pos);\r
170                         //list.push_back(one.Right(one.GetLength()-2));\r
171                         if(one[0] == _T('*'))\r
172                                 return one.Right(one.GetLength()-2);\r
173                 }\r
174         }\r
175         return CString("");\r
176 }\r
177 \r
178 int CGit::BuildOutputFormat(CString &format,bool IsFull)\r
179 {\r
180         CString log;\r
181         log.Format(_T("#<%c>%%x00"),LOG_REV_ITEM_BEGIN);\r
182         format += log;\r
183         if(IsFull)\r
184         {\r
185                 log.Format(_T("#<%c>%%an%%x00"),LOG_REV_AUTHOR_NAME);\r
186                 format += log;\r
187                 log.Format(_T("#<%c>%%ae%%x00"),LOG_REV_AUTHOR_EMAIL);\r
188                 format += log;\r
189                 log.Format(_T("#<%c>%%ai%%x00"),LOG_REV_AUTHOR_DATE);\r
190                 format += log;\r
191                 log.Format(_T("#<%c>%%cn%%x00"),LOG_REV_COMMIT_NAME);\r
192                 format += log;\r
193                 log.Format(_T("#<%c>%%ce%%x00"),LOG_REV_COMMIT_EMAIL);\r
194                 format += log;\r
195                 log.Format(_T("#<%c>%%ci%%x00"),LOG_REV_COMMIT_DATE);\r
196                 format += log;\r
197                 log.Format(_T("#<%c>%%s%%x00"),LOG_REV_COMMIT_SUBJECT);\r
198                 format += log;\r
199                 log.Format(_T("#<%c>%%b%%x00"),LOG_REV_COMMIT_BODY);\r
200                 format += log;\r
201         }\r
202         log.Format(_T("#<%c>%%m%%H%%x00"),LOG_REV_COMMIT_HASH);\r
203         format += log;\r
204         log.Format(_T("#<%c>%%P%%x00"),LOG_REV_COMMIT_PARENT);\r
205         format += log;\r
206 \r
207         if(IsFull)\r
208         {\r
209                 log.Format(_T("#<%c>%%x00"),LOG_REV_COMMIT_FILE);\r
210                 format += log;\r
211         }\r
212         return 0;\r
213 }\r
214 \r
215 int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash,  CTGitPath *path ,int count,int mask)\r
216 {\r
217 \r
218         CString cmd;\r
219         CString log;\r
220         CString num;\r
221         CString since;\r
222 \r
223         CString file;\r
224 \r
225         if(path)\r
226                 file.Format(_T(" -- \"%s\""),path->GetGitPathString());\r
227         \r
228         if(count>0)\r
229                 num.Format(_T("-n%d"),count);\r
230 \r
231         CString param;\r
232 \r
233         if(mask& LOG_INFO_STAT )\r
234                 param += _T(" --numstat ");\r
235         if(mask& LOG_INFO_FILESTATE)\r
236                 param += _T(" --raw ");\r
237 \r
238         if(mask& LOG_INFO_FULLHISTORY)\r
239                 param += _T(" --full-history ");\r
240 \r
241         if(mask& LOG_INFO_BOUNDARY)\r
242                 param += _T(" --left-right --boundary ");\r
243 \r
244         if(mask& CGit::LOG_INFO_ALL_BRANCH)\r
245                 param += _T(" --all ");\r
246 \r
247         if(mask& CGit::LOG_INFO_DETECT_COPYRENAME)\r
248                 param += _T(" -C ");\r
249         \r
250         if(mask& CGit::LOG_INFO_DETECT_RENAME )\r
251                 param += _T(" -M ");\r
252 \r
253         param+=hash;\r
254 \r
255         cmd.Format(_T("git.exe log %s -z --topo-order --parents %s --pretty=format:\""),\r
256                                 num,param);\r
257 \r
258         BuildOutputFormat(log,!(mask&CGit::LOG_INFO_ONLY_HASH));\r
259 \r
260         cmd += log;\r
261         cmd += CString(_T("\"  "))+hash+file;\r
262 \r
263         return Run(cmd,&logOut);\r
264 }\r
265 \r
266 #if 0\r
267 int CGit::GetShortLog(CString &logOut,CTGitPath * path, int count)\r
268 {\r
269         CString cmd;\r
270         CString log;\r
271         int n;\r
272         if(count<0)\r
273                 n=100;\r
274         else\r
275                 n=count;\r
276         cmd.Format(_T("git.exe log --left-right --boundary --topo-order -n%d --pretty=format:\""),n);\r
277         BuildOutputFormat(log,false);\r
278         cmd += log+_T("\"");\r
279         if (path)\r
280                 cmd+= _T("  -- \"")+path->GetGitPathString()+_T("\"");\r
281         //cmd += CString(_T("\" HEAD~40..HEAD"));\r
282         return Run(cmd,&logOut);\r
283 }\r
284 #endif\r
285 \r
286 #define BUFSIZE 512\r
287 void GetTempPath(CString &path)\r
288 {\r
289         TCHAR lpPathBuffer[BUFSIZE];\r
290         DWORD dwRetVal;\r
291         DWORD dwBufSize=BUFSIZE;\r
292         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
293                            lpPathBuffer); // buffer for path \r
294     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
295     {\r
296         path=_T("");\r
297     }\r
298         path.Format(_T("%s"),lpPathBuffer);\r
299 }\r
300 CString GetTempFile()\r
301 {\r
302         TCHAR lpPathBuffer[BUFSIZE];\r
303         DWORD dwRetVal;\r
304     DWORD dwBufSize=BUFSIZE;\r
305         TCHAR szTempName[BUFSIZE];  \r
306         UINT uRetVal;\r
307 \r
308         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
309                            lpPathBuffer); // buffer for path \r
310     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
311     {\r
312         return _T("");\r
313     }\r
314          // Create a temporary file. \r
315     uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files\r
316                               TEXT("Patch"),  // temp file name prefix \r
317                               0,            // create unique name \r
318                               szTempName);  // buffer for name \r
319 \r
320 \r
321     if (uRetVal == 0)\r
322     {\r
323         return _T("");\r
324     }\r
325 \r
326         return CString(szTempName);\r
327 \r
328 }\r
329 \r
330 int CGit::RunLogFile(CString cmd,CString &filename)\r
331 {\r
332         STARTUPINFO si;\r
333         PROCESS_INFORMATION pi;\r
334         si.cb=sizeof(STARTUPINFO);\r
335         GetStartupInfo(&si);\r
336 \r
337         SECURITY_ATTRIBUTES   psa={sizeof(psa),NULL,TRUE};;   \r
338         psa.bInheritHandle=TRUE;   \r
339     \r
340         HANDLE   houtfile=CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
341                         &psa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);   \r
342 \r
343 \r
344         si.wShowWindow=SW_HIDE;\r
345         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
346         si.hStdOutput   =   houtfile; \r
347         \r
348         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
349         {\r
350                 LPVOID lpMsgBuf;\r
351                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
352                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
353                         (LPTSTR)&lpMsgBuf,\r
354                         0,NULL);\r
355                 return GIT_ERROR_CREATE_PROCESS;\r
356         }\r
357         \r
358         WaitForSingleObject(pi.hProcess,INFINITE);   \r
359         \r
360         CloseHandle(pi.hThread);\r
361         CloseHandle(pi.hProcess);\r
362         CloseHandle(houtfile);\r
363         return GIT_SUCCESS;\r
364         return 0;\r
365 }\r
366 \r
367 git_revnum_t CGit::GetHash(CString &friendname)\r
368 {\r
369         CString cmd;\r
370         CString out;\r
371         cmd.Format(_T("git.exe rev-parse %s" ),friendname);\r
372         Run(cmd,&out,CP_UTF8);\r
373         int pos=out.ReverseFind(_T('\n'));\r
374         if(pos>0)\r
375                 return out.Left(pos);\r
376         return out;\r
377 }\r
378 \r
379 int CGit::GetTagList(STRING_VECTOR &list)\r
380 {\r
381         int ret;\r
382         CString cmd,output;\r
383         cmd=_T("git.exe tag -l");\r
384         int i=0;\r
385         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
386         if(!ret)\r
387         {               \r
388                 int pos=0;\r
389                 CString one;\r
390                 while( pos>=0 )\r
391                 {\r
392                         i++;\r
393                         one=output.Tokenize(_T("\n"),pos);\r
394                         list.push_back(one);\r
395                 }\r
396         }\r
397         return ret;\r
398 }\r
399 \r
400 int CGit::GetBranchList(STRING_VECTOR &list,int *current,BRANCH_TYPE type)\r
401 {\r
402         int ret;\r
403         CString cmd,output;\r
404         cmd=_T("git.exe branch");\r
405 \r
406         if(type==(BRANCH_LOCAL|BRANCH_REMOTE))\r
407                 cmd+=_T(" -a");\r
408         else if(type==BRANCH_REMOTE)\r
409                 cmd+=_T(" -r");\r
410 \r
411         int i=0;\r
412         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
413         if(!ret)\r
414         {               \r
415                 int pos=0;\r
416                 CString one;\r
417                 while( pos>=0 )\r
418                 {\r
419                         i++;\r
420                         one=output.Tokenize(_T("\n"),pos);\r
421                         list.push_back(one.Right(one.GetLength()-2));\r
422                         if(one[0] == _T('*'))\r
423                                 if(current)\r
424                                         *current=i;\r
425                 }\r
426         }\r
427         return ret;\r
428 }\r
429 \r
430 int CGit::GetRemoteList(STRING_VECTOR &list)\r
431 {\r
432         int ret;\r
433         CString cmd,output;\r
434         cmd=_T("git.exe config  --get-regexp remote.*.url");\r
435         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
436         if(!ret)\r
437         {\r
438                 int pos=0;\r
439                 CString one;\r
440                 while( pos>=0 )\r
441                 {\r
442                         one=output.Tokenize(_T("\n"),pos);\r
443                         int start=one.Find(_T("."),0);\r
444                         if(start>0)\r
445                         {\r
446                                 CString url;\r
447                                 url=one.Right(one.GetLength()-start-1);\r
448                                 one=url;\r
449                                 one=one.Left(one.Find(_T("."),0));\r
450                                 list.push_back(one);\r
451                         }\r
452                 }\r
453         }\r
454         return ret;\r
455 }\r
456 \r
457 int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map)\r
458 {\r
459         int ret;\r
460         CString cmd,output;\r
461         cmd=_T("git show-ref -d");\r
462         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
463         if(!ret)\r
464         {\r
465                 int pos=0;\r
466                 CString one;\r
467                 while( pos>=0 )\r
468                 {\r
469                         one=output.Tokenize(_T("\n"),pos);\r
470                         int start=one.Find(_T(" "),0);\r
471                         if(start>0)\r
472                         {\r
473                                 CString name;\r
474                                 name=one.Right(one.GetLength()-start-1);\r
475 \r
476                                 CString hash;\r
477                                 hash=one.Left(start);\r
478 \r
479                                 map[hash].push_back(name);\r
480                         }\r
481                 }\r
482         }\r
483         return ret;\r
484 }\r
485 \r
486 BOOL CGit::CheckMsysGitDir()\r
487 {\r
488         CRegString msysdir=CRegString(REG_MSYSGIT_PATH,_T(""),FALSE,HKEY_LOCAL_MACHINE);\r
489         CString str=msysdir;\r
490         if(str.IsEmpty())\r
491         {\r
492                 CRegString msysinstalldir=CRegString(REG_MSYSGIT_INSTALL,_T(""),FALSE,HKEY_LOCAL_MACHINE);\r
493                 str=msysinstalldir;\r
494                 str+="\\bin";\r
495                 msysdir=str;\r
496                 msysdir.write();\r
497 \r
498         }\r
499         //CGit::m_MsysGitPath=str;\r
500 \r
501         TCHAR *oldpath,*home;\r
502         size_t size;\r
503 \r
504         _tdupenv_s(&home,&size,_T("HOME")); \r
505         \r
506         if(home == NULL)\r
507         {               \r
508                 _tdupenv_s(&home,&size,_T("USERPROFILE")); \r
509                 _tputenv_s(_T("HOME"),home);\r
510                 free(home);\r
511         }\r
512         //set path\r
513         _tdupenv_s(&oldpath,&size,_T("PATH")); \r
514 \r
515         CString path;\r
516         path.Format(_T("%s;"),str);\r
517         path+=oldpath;\r
518 \r
519         _tputenv_s(_T("PATH"),path);\r
520 \r
521         free(oldpath);\r
522 \r
523         CString cmd,out;\r
524         cmd=_T("git.exe --version");\r
525         if(g_Git.Run(cmd,&out,CP_UTF8))\r
526         {\r
527                 return false;\r
528         }\r
529         else\r
530                 return true;\r
531 \r
532 }